From ba14aeabc661d969bf4bf26f497d42ff135ed59a Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Wed, 3 Dec 2014 17:59:37 -0800 Subject: [PATCH] [Forms] Complete specs Fill in new specs and amend existing specs to ensure full coverage after integration of forms component, and associated changes. WTD-593. --- .../browse/test/creation/CreateWizardSpec.js | 20 ++++++- .../test/creation/LocatorControllerSpec.js | 58 +++++++++++++++++++ .../edit/test/actions/PropertiesActionSpec.js | 44 +++++++++----- .../general/test/TreeNodeControllerSpec.js | 31 +++++----- platform/core/test/types/TypePropertySpec.js | 26 +++++++++ 5 files changed, 150 insertions(+), 29 deletions(-) diff --git a/platform/commonUI/browse/test/creation/CreateWizardSpec.js b/platform/commonUI/browse/test/creation/CreateWizardSpec.js index 8bef902e90..fc46f2904b 100644 --- a/platform/commonUI/browse/test/creation/CreateWizardSpec.js +++ b/platform/commonUI/browse/test/creation/CreateWizardSpec.js @@ -12,6 +12,7 @@ define( var mockType, mockParent, mockProperties, + testModel, wizard; function createMockProperty(name) { @@ -20,6 +21,7 @@ define( [ "getDefinition", "getValue", "setValue" ] ); mockProperty.getDefinition.andReturn({}); + mockProperty.getValue.andReturn(name); return mockProperty; } @@ -45,11 +47,13 @@ define( ); mockProperties = [ "A", "B", "C" ].map(createMockProperty); + testModel = { someKey: "some value" }; + mockType.getKey.andReturn("test"); mockType.getGlyph.andReturn("T"); mockType.getDescription.andReturn("a test type"); mockType.getName.andReturn("Test"); - mockType.getInitialModel.andReturn({}); + mockType.getInitialModel.andReturn(testModel); mockType.getProperties.andReturn(mockProperties); wizard = new CreateWizard( @@ -80,12 +84,24 @@ define( // Should have gotten a setValue call mockProperties.forEach(function (mockProperty, i) { expect(mockProperty.setValue).toHaveBeenCalledWith( - { type: 'test' }, + { someKey: "some value", type: 'test' }, "field " + i ); }); + }); + it("looks up initial values from properties", function () { + var initialValue = wizard.getInitialFormValue(); + expect(initialValue[0]).toEqual("A"); + expect(initialValue[1]).toEqual("B"); + expect(initialValue[2]).toEqual("C"); + + // Verify that expected argument was passed + mockProperties.forEach(function (mockProperty) { + expect(mockProperty.getValue) + .toHaveBeenCalledWith(testModel); + }); }); diff --git a/platform/commonUI/browse/test/creation/LocatorControllerSpec.js b/platform/commonUI/browse/test/creation/LocatorControllerSpec.js index a81ae49359..605e98f1dc 100644 --- a/platform/commonUI/browse/test/creation/LocatorControllerSpec.js +++ b/platform/commonUI/browse/test/creation/LocatorControllerSpec.js @@ -9,6 +9,64 @@ define( "use strict"; describe("The locator controller", function () { + var mockScope, + mockDomainObject, + mockRootObject, + mockContext, + controller; + + beforeEach(function () { + mockScope = jasmine.createSpyObj( + "$scope", + [ "$watch" ] + ); + mockDomainObject = jasmine.createSpyObj( + "domainObject", + [ "getCapability" ] + ); + mockRootObject = jasmine.createSpyObj( + "rootObject", + [ "getCapability" ] + ); + mockContext = jasmine.createSpyObj( + "context", + [ "getRoot" ] + ); + + mockDomainObject.getCapability.andReturn(mockContext); + mockContext.getRoot.andReturn(mockRootObject); + + mockScope.ngModel = {}; + mockScope.field = "someField"; + + controller = new LocatorController(mockScope); + }); + + it("adds a treeModel to scope", function () { + expect(mockScope.treeModel).toBeDefined(); + }); + + it("watches for changes to treeModel", function () { + // This is what the embedded tree representation + // will be modifying. + expect(mockScope.$watch).toHaveBeenCalledWith( + "treeModel.selectedObject", + jasmine.any(Function) + ); + }); + + it("changes its own model on embedded model updates", function () { + // Need to pass on selection changes as updates to + // the control's value + mockScope.$watch.mostRecentCall.args[1](mockDomainObject); + expect(mockScope.ngModel.someField).toEqual(mockDomainObject); + expect(mockScope.rootObject).toEqual(mockRootObject); + + // Verify that the capability we expect to have been used + // was used. + expect(mockDomainObject.getCapability) + .toHaveBeenCalledWith("context"); + }); }); } diff --git a/platform/commonUI/edit/test/actions/PropertiesActionSpec.js b/platform/commonUI/edit/test/actions/PropertiesActionSpec.js index 957c9279ec..ad0f6ad895 100644 --- a/platform/commonUI/edit/test/actions/PropertiesActionSpec.js +++ b/platform/commonUI/edit/test/actions/PropertiesActionSpec.js @@ -1,4 +1,4 @@ -/*global define,describe,it,xit,expect,beforeEach*/ +/*global define,describe,it,xit,expect,beforeEach,jasmine*/ define( ['../../src/actions/PropertiesAction'], @@ -6,9 +6,7 @@ define( "use strict"; describe("Properties action", function () { - var captured, model, object, context, input, dialogService, action; - - function capture(k) { return function (v) { captured[k] = v; }; } + var capabilities, model, object, context, input, dialogService, action; function mockPromise(value) { return { @@ -19,17 +17,19 @@ define( } beforeEach(function () { - var capabilities = { + capabilities = { type: { getProperties: function () { return []; } }, - persistence: {}, - mutation: {} + persistence: jasmine.createSpyObj("persistence", ["persist"]), + mutation: jasmine.createSpy("mutation") }; model = {}; input = {}; object = { getId: function () { return 'test-id'; }, getCapability: function (k) { return capabilities[k]; }, - getModel: function () { return model; } + getModel: function () { return model; }, + useCapability: function (k, v) { return capabilities[k](v); }, + hasCapability: function () { return true; } }; context = { someKey: "some value", domainObject: object }; dialogService = { @@ -37,18 +37,34 @@ define( return mockPromise(input); } }; - captured = {}; - action = new PropertiesAction(object, context, dialogService); + + capabilities.mutation.andReturn(true); + + action = new PropertiesAction(dialogService, context); }); it("persists when an action is performed", function () { - + action.perform(); + expect(capabilities.persistence.persist) + .toHaveBeenCalled(); }); it("does not persist any changes upon cancel", function () { -// input = undefined; -// action.perform(); -// expect(captured.persisted).toBeFalsy(); + input = undefined; + action.perform(); + expect(capabilities.persistence.persist) + .not.toHaveBeenCalled(); + }); + + it("mutates an object when performed", function () { + action.perform(); + expect(capabilities.mutation).toHaveBeenCalled(); + capabilities.mutation.mostRecentCall.args[0]({}); + }); + + it("is only applicable when a domain object is in context", function () { + expect(PropertiesAction.appliesTo(context)).toBeTruthy(); + expect(PropertiesAction.appliesTo({})).toBeFalsy(); }); }); } diff --git a/platform/commonUI/general/test/TreeNodeControllerSpec.js b/platform/commonUI/general/test/TreeNodeControllerSpec.js index a128d3067f..655368a35f 100644 --- a/platform/commonUI/general/test/TreeNodeControllerSpec.js +++ b/platform/commonUI/general/test/TreeNodeControllerSpec.js @@ -52,11 +52,13 @@ define( // Verify precondition expect(controller.isSelected()).toBeFalsy(); -// mockNavigationService.getNavigation.andReturn(obj); -// mockScope.domainObject = obj; -// mockNavigationService.addListener.mostRecentCall.args[0](obj); + // Change the represented domain object + mockScope.domainObject = obj; - //expect(controller.isSelected()).toBeTruthy(); + // Invoke the watch with the new selection + mockScope.$watch.calls[0].args[1](obj); + + expect(controller.isSelected()).toBeTruthy(); }); it("expands a node if it is on the navigation path", function () { @@ -80,9 +82,12 @@ define( mockScope.domainObject = parent; mockScope.toggle = jasmine.createSpyObj("toggle", ["setState"]); -// expect(mockScope.toggle.setState).toHaveBeenCalledWith(true); -// expect(controller.hasBeenExpanded()).toBeTruthy(); -// expect(controller.isSelected()).toBeFalsy(); + // Invoke the watch with the new selection + mockScope.$watch.calls[0].args[1](child); + + expect(mockScope.toggle.setState).toHaveBeenCalledWith(true); + expect(controller.hasBeenExpanded()).toBeTruthy(); + expect(controller.isSelected()).toBeFalsy(); }); @@ -107,12 +112,12 @@ define( mockScope.domainObject = parent; mockScope.toggle = jasmine.createSpyObj("toggle", ["setState"]); - // Trigger update -// mockNavigationService.addListener.mostRecentCall.args[0](child); -// -// expect(mockScope.toggle.setState).not.toHaveBeenCalled(); -// expect(controller.hasBeenExpanded()).toBeFalsy(); -// expect(controller.isNavigated()).toBeFalsy(); + // Invoke the watch with the new selection + mockScope.$watch.calls[0].args[1](child); + + expect(mockScope.toggle.setState).not.toHaveBeenCalled(); + expect(controller.hasBeenExpanded()).toBeFalsy(); + expect(controller.isSelected()).toBeFalsy(); }); }); diff --git a/platform/core/test/types/TypePropertySpec.js b/platform/core/test/types/TypePropertySpec.js index 09a55e35a0..778bea4500 100644 --- a/platform/core/test/types/TypePropertySpec.js +++ b/platform/core/test/types/TypePropertySpec.js @@ -75,6 +75,32 @@ define( expect(property.getValue(model)).toBeUndefined(); }); + it("provides empty arrays for values that are array-like", function () { + var definition = { + property: "someProperty", + items: [ {}, {}, {} ] + }, + model = {}, + property = new TypeProperty(definition); + expect(property.getValue(model)) + .toEqual([undefined, undefined, undefined]); + }); + + it("detects and ignores empty arrays on setValue", function () { + var definition = { + property: "someProperty", + items: [ {}, {}, {} ] + }, + model = {}, + property = new TypeProperty(definition); + + property.setValue(model, [undefined, undefined, undefined]); + expect(model.someProperty).toBeUndefined(); + + // Verify that this only happens when all are undefined + property.setValue(model, [undefined, "x", 42]); + expect(model.someProperty).toEqual([undefined, "x", 42]); + }); }); }