diff --git a/platform/commonUI/edit/src/EditController.js b/platform/commonUI/edit/src/EditController.js index 073f321120..758988330b 100644 --- a/platform/commonUI/edit/src/EditController.js +++ b/platform/commonUI/edit/src/EditController.js @@ -20,6 +20,9 @@ define( setNavigation(navigationService.getNavigation()); navigationService.addListener(setNavigation); + $scope.$on("$destroy", function () { + navigationService.removeListener(setNavigation); + }); } return EditController; diff --git a/platform/commonUI/edit/test/EditActionControllerSpec.js b/platform/commonUI/edit/test/EditActionControllerSpec.js index 7b8fc1741c..e0e23cada8 100644 --- a/platform/commonUI/edit/test/EditActionControllerSpec.js +++ b/platform/commonUI/edit/test/EditActionControllerSpec.js @@ -6,7 +6,35 @@ define( "use strict"; describe("The Edit Action controller", function () { + var mockScope, + mockActions, + controller; + beforeEach(function () { + mockActions = jasmine.createSpyObj("action", ["getActions"]); + mockScope = jasmine.createSpyObj("$scope", ["$watch"]); + controller = new EditActionController(mockScope); + }); + + it("watches scope that may change applicable actions", function () { + // The action capability + expect(mockScope.$watch).toHaveBeenCalledWith( + "action", + jasmine.any(Function) + ); + }); + + it("populates the scope with grouped and ungrouped actions", function () { + mockScope.action = mockActions; + + mockActions.getActions.andReturn(["a", "b", "c"]); + + // Call the watch + mockScope.$watch.mostRecentCall.args[1](); + + // Should have grouped and ungrouped actions in scope now + expect(mockScope.editActions.length).toEqual(3); + }); }); } ); \ No newline at end of file diff --git a/platform/commonUI/edit/test/EditControllerSpec.js b/platform/commonUI/edit/test/EditControllerSpec.js index 572eae4110..3dff5f7ed8 100644 --- a/platform/commonUI/edit/test/EditControllerSpec.js +++ b/platform/commonUI/edit/test/EditControllerSpec.js @@ -6,6 +6,75 @@ define( "use strict"; describe("The Edit mode controller", function () { + var mockScope, + mockNavigationService, + mockObject, + mockCapability, + controller; + + beforeEach(function () { + mockScope = jasmine.createSpyObj( + "$scope", + [ "$on" ] + ); + mockNavigationService = jasmine.createSpyObj( + "navigationService", + [ "getNavigation", "addListener", "removeListener" ] + ); + mockObject = jasmine.createSpyObj( + "domainObject", + [ "getId", "getModel", "getCapability" ] + ); + mockCapability = jasmine.createSpyObj( + "capability", + [ "invoke" ] + ); + + mockNavigationService.getNavigation.andReturn(mockObject); + mockObject.getId.andReturn("test"); + mockObject.getModel.andReturn({ name: "Test object" }); + mockObject.getCapability.andReturn(mockCapability); + + controller = new EditController( + mockScope, + mockNavigationService + ); + }); + + it("places the currently-navigated object in scope", function () { + expect(mockScope.navigatedObject).toBeDefined(); + expect(mockScope.navigatedObject.getId()).toEqual("test"); + }); + + it("adds an editor capability to the navigated object", function () { + // Should provide an editor capability... + expect(mockScope.navigatedObject.getCapability("editor")) + .toBeDefined(); + // Shouldn't have been the mock capability we provided + expect(mockScope.navigatedObject.getCapability("editor")) + .not.toEqual(mockCapability); + }); + + it("detaches its navigation listener when destroyed", function () { + var navCallback = mockNavigationService + .addListener.mostRecentCall.args[0]; + + expect(mockScope.$on).toHaveBeenCalledWith( + "$destroy", + jasmine.any(Function) + ); + + // Verify precondition + expect(mockNavigationService.removeListener) + .not.toHaveBeenCalled(); + + // Trigger destroy + mockScope.$on.mostRecentCall.args[1](); + + // Listener should have been removed + expect(mockNavigationService.removeListener) + .toHaveBeenCalledWith(navCallback); + }); }); }