From 244583b2f790f21519745452fe7d87147c2d84f1 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Thu, 15 Jan 2015 13:36:21 -0800 Subject: [PATCH] [Forms] Separate out FormController Separate out the controller for mct-form from its directive definition, to allow reuse by the mct-toolbar directive, WTD-684. --- platform/forms/src/MCTForm.js | 51 ++------------ .../forms/src/controllers/FormController.js | 57 +++++++++++++++ .../test/controllers/FormControllerSpec.js | 69 +++++++++++++++++++ platform/forms/test/suite.json | 3 +- 4 files changed, 132 insertions(+), 48 deletions(-) create mode 100644 platform/forms/src/controllers/FormController.js create mode 100644 platform/forms/test/controllers/FormControllerSpec.js diff --git a/platform/forms/src/MCTForm.js b/platform/forms/src/MCTForm.js index 8414938171..0de41797f7 100644 --- a/platform/forms/src/MCTForm.js +++ b/platform/forms/src/MCTForm.js @@ -4,13 +4,10 @@ * Module defining MCTForm. Created by vwoeltje on 11/10/14. */ define( - [], - function () { + ["./controllers/FormController"], + function (FormController) { "use strict"; - // Default ng-pattern; any non whitespace - var NON_WHITESPACE = /\S/; - /** * The mct-form directive allows generation of displayable * forms based on a declarative description of the form's @@ -37,45 +34,6 @@ define( "templates/form.html" ].join("/"); - function controller($scope) { - var regexps = []; - - // ng-pattern seems to want a RegExp, and not a - // string (despite what documentation says) but - // we want form structure to be JSON-expressible, - // so we make RegExp's from strings as-needed - function getRegExp(pattern) { - // If undefined, don't apply a pattern - if (!pattern) { - return NON_WHITESPACE; - } - - // Just echo if it's already a regexp - if (pattern instanceof RegExp) { - return pattern; - } - - // Otherwise, assume a string - // Cache for easy lookup later (so we don't - // creat a new RegExp every digest cycle) - if (!regexps[pattern]) { - regexps[pattern] = new RegExp(pattern); - } - - return regexps[pattern]; - } - - // Publish the form state under the requested - // name in the parent scope - $scope.$watch("mctForm", function (mctForm) { - if ($scope.name) { - $scope.$parent[$scope.name] = mctForm; - } - }); - - $scope.getRegExp = getRegExp; - } - return { // Only show at the element level restrict: "E", @@ -83,9 +41,8 @@ define( // Load the forms template templateUrl: templatePath, - // Use the controller defined above to - // populate/respond to changes in scope - controller: controller, + // Use FormController to populate/respond to changes in scope + controller: FormController, // Initial an isolate scope scope: { diff --git a/platform/forms/src/controllers/FormController.js b/platform/forms/src/controllers/FormController.js new file mode 100644 index 0000000000..ff7a1b0769 --- /dev/null +++ b/platform/forms/src/controllers/FormController.js @@ -0,0 +1,57 @@ +/*global define*/ + +define( + [], + function () { + "use strict"; + + // Default ng-pattern; any non whitespace + var NON_WHITESPACE = /\S/; + + /** + * Controller for mct-form and mct-toolbar directives. + * @constructor + */ + function FormController($scope) { + var regexps = []; + + // ng-pattern seems to want a RegExp, and not a + // string (despite what documentation says) but + // we want form structure to be JSON-expressible, + // so we make RegExp's from strings as-needed + function getRegExp(pattern) { + // If undefined, don't apply a pattern + if (!pattern) { + return NON_WHITESPACE; + } + + // Just echo if it's already a regexp + if (pattern instanceof RegExp) { + return pattern; + } + + // Otherwise, assume a string + // Cache for easy lookup later (so we don't + // creat a new RegExp every digest cycle) + if (!regexps[pattern]) { + regexps[pattern] = new RegExp(pattern); + } + + return regexps[pattern]; + } + + // Publish the form state under the requested + // name in the parent scope + $scope.$watch("mctForm", function (mctForm) { + if ($scope.name) { + $scope.$parent[$scope.name] = mctForm; + } + }); + + // Expose the regexp lookup + $scope.getRegExp = getRegExp; + } + + return FormController; + } +); \ No newline at end of file diff --git a/platform/forms/test/controllers/FormControllerSpec.js b/platform/forms/test/controllers/FormControllerSpec.js new file mode 100644 index 0000000000..538e4e5156 --- /dev/null +++ b/platform/forms/test/controllers/FormControllerSpec.js @@ -0,0 +1,69 @@ +/*global define,describe,it,expect,beforeEach,waitsFor,jasmine*/ + +define( + ["../../src/controllers/FormController"], + function (FormController) { + "use strict"; + + describe("The form controller", function () { + var mockScope, + controller; + + beforeEach(function () { + mockScope = jasmine.createSpyObj("$scope", [ "$watch" ]); + mockScope.$parent = {}; + controller = new FormController(mockScope); + }); + + it("watches for changes in form by name", function () { + expect(mockScope.$watch).toHaveBeenCalledWith( + "mctForm", + jasmine.any(Function) + ); + }); + + it("conveys form status to parent scope", function () { + var someState = { someKey: "some value" }; + mockScope.name = "someName"; + mockScope.$watch.mostRecentCall.args[1](someState); + expect(mockScope.$parent.someName).toBe(someState); + }); + + it("allows strings to be converted to RegExps", function () { + // Should have added getRegExp to the scope, + // to convert strings to regular expressions + expect(mockScope.getRegExp("^\\d+$")).toEqual(/^\d+$/); + }); + + it("returns the same regexp instance for the same string", function () { + // Don't want new instances each digest cycle, for performance + var strRegExp = "^[a-z]\\d+$", + regExp; + + // Add getRegExp to scope + regExp = mockScope.getRegExp(strRegExp); + + // Same object instance each time... + expect(mockScope.getRegExp(strRegExp)).toBe(regExp); + expect(mockScope.getRegExp(strRegExp)).toBe(regExp); + }); + + it("passes RegExp objects through untouched", function () { + // Permit using forms to simply provide their own RegExp object + var regExp = /^\d+[a-d]$/; + + // Should have added getRegExp to the scope, + // to convert strings to regular expressions + expect(mockScope.getRegExp(regExp)).toBe(regExp); + }); + + it("passes a non-whitespace regexp when no pattern is defined", function () { + // If no pattern is supplied, ng-pattern should match anything + expect(mockScope.getRegExp()).toEqual(/\S/); + expect(mockScope.getRegExp(undefined)).toEqual(/\S/); + }); + + + }); + } +); \ No newline at end of file diff --git a/platform/forms/test/suite.json b/platform/forms/test/suite.json index f69c3a325e..61eff300e6 100644 --- a/platform/forms/test/suite.json +++ b/platform/forms/test/suite.json @@ -2,5 +2,6 @@ "MCTControl", "MCTForm", "controllers/CompositeController", - "controllers/DateTimeController" + "controllers/DateTimeController", + "controllers/FormController" ] \ No newline at end of file