From 5b9e43f8ff354af232870228d794e5b3fafa2087 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Thu, 19 Nov 2015 14:22:44 -0800 Subject: [PATCH] [Status] Test platform/status --- platform/status/src/StatusConstants.js | 26 ++++++ platform/status/src/StatusRepresenter.js | 6 +- platform/status/src/StatusService.js | 6 +- platform/status/test/StatusCapabilitySpec.js | 52 +++++++++++ platform/status/test/StatusRepresenterSpec.js | 90 ++++++++++++++++++- platform/status/test/StatusServiceSpec.js | 62 +++++++++++++ 6 files changed, 234 insertions(+), 8 deletions(-) create mode 100644 platform/status/src/StatusConstants.js diff --git a/platform/status/src/StatusConstants.js b/platform/status/src/StatusConstants.js new file mode 100644 index 0000000000..75b1bca2e1 --- /dev/null +++ b/platform/status/src/StatusConstants.js @@ -0,0 +1,26 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2015, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT Web is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT Web includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ +/*global define*/ +define({ + CSS_CLASS_PREFIX: 's-status-', + TOPIC_PREFIX: 'status:' +}); diff --git a/platform/status/src/StatusRepresenter.js b/platform/status/src/StatusRepresenter.js index 0bab5fd571..0808688c02 100644 --- a/platform/status/src/StatusRepresenter.js +++ b/platform/status/src/StatusRepresenter.js @@ -22,11 +22,11 @@ /*global define*/ define( - [], - function () { + ['./StatusConstants'], + function (StatusConstants) { 'use strict'; - var STATUS_CLASS_PREFIX = "s-status-"; + var STATUS_CLASS_PREFIX = StatusConstants.CSS_CLASS_PREFIX; /** * Adds/removes CSS classes to `mct-representation`s to reflect the diff --git a/platform/status/src/StatusService.js b/platform/status/src/StatusService.js index b19cf7ca1d..6fff6f49d8 100644 --- a/platform/status/src/StatusService.js +++ b/platform/status/src/StatusService.js @@ -22,11 +22,11 @@ /*global define*/ define( - [], - function () { + ['./StatusConstants'], + function (StatusConstants) { 'use strict'; - var STATUS_PREFIX = "status:"; + var STATUS_PREFIX = StatusConstants.TOPIC_PREFIX; /** * The `statusService` maintains information about the current diff --git a/platform/status/test/StatusCapabilitySpec.js b/platform/status/test/StatusCapabilitySpec.js index f016ebfa89..481abf6a53 100644 --- a/platform/status/test/StatusCapabilitySpec.js +++ b/platform/status/test/StatusCapabilitySpec.js @@ -27,6 +27,58 @@ define( "use strict"; describe("The status capability", function () { + var mockStatusService, + mockDomainObject, + mockUnlisten, + testId, + testStatusFlags, + capability; + + beforeEach(function () { + testId = "some-id"; + testStatusFlags = [ 'a', 'b', 'c' ]; + + mockStatusService = jasmine.createSpyObj( + 'statusService', + [ 'listen', 'setStatus', 'getStatus' ] + ); + mockDomainObject = jasmine.createSpyObj( + 'domainObject', + [ 'getId', 'getCapability', 'getModel' ] + ); + mockUnlisten = jasmine.createSpy('unlisten'); + + mockStatusService.listen.andReturn(mockUnlisten); + mockStatusService.getStatus.andReturn(testStatusFlags); + mockDomainObject.getId.andReturn(testId); + + capability = new StatusCapability( + mockStatusService, + mockDomainObject + ); + }); + + it("sets status with the statusService", function () { + var testStatus = "some-test-status"; + capability.set(testStatus, true); + expect(mockStatusService.setStatus) + .toHaveBeenCalledWith(testId, testStatus, true); + capability.set(testStatus, false); + expect(mockStatusService.setStatus) + .toHaveBeenCalledWith(testId, testStatus, false); + }); + + it("gets status from the statusService", function () { + expect(capability.get()).toBe(testStatusFlags); + }); + + it("listens to changes from the statusService", function () { + var mockCallback = jasmine.createSpy(); + expect(capability.listen(mockCallback)) + .toBe(mockUnlisten); + expect(mockStatusService.listen) + .toHaveBeenCalledWith(testId, mockCallback); + }); }); } ); diff --git a/platform/status/test/StatusRepresenterSpec.js b/platform/status/test/StatusRepresenterSpec.js index cd058401c1..e9191587a7 100644 --- a/platform/status/test/StatusRepresenterSpec.js +++ b/platform/status/test/StatusRepresenterSpec.js @@ -22,11 +22,97 @@ /*global define,Promise,describe,it,expect,beforeEach,waitsFor,jasmine*/ define( - ["../src/StatusRepresenter"], - function (StatusRepresenter) { + ["../src/StatusRepresenter", "../src/StatusConstants"], + function (StatusRepresenter, StatusConstants) { "use strict"; describe("The status representer", function () { + var mockScope, + mockElement, + testRepresentation, + mockDomainObject, + mockStatusCapability, + mockUnlisten, + elementClasses, + testStatusFlags, + representer; + + function verifyClasses() { + expect(Object.keys(elementClasses).sort()) + .toEqual(testStatusFlags.map(function (s) { + return StatusConstants.CSS_CLASS_PREFIX + s; + }).sort()); + } + + function updateStatus(newFlags) { + testStatusFlags = newFlags; + mockStatusCapability.get.andReturn(newFlags); + mockStatusCapability.listen.mostRecentCall + .args[0](newFlags); + } + + beforeEach(function () { + testStatusFlags = [ 'x', 'y', 'z' ]; + + mockScope = {}; + mockElement = jasmine.createSpyObj('element', [ + 'addClass', + 'removeClass' + ]); + testRepresentation = { key: "someKey" }; + mockDomainObject = jasmine.createSpyObj( + 'domainObject', + [ 'getModel', 'getId', 'getCapability' ] + ); + mockStatusCapability = jasmine.createSpyObj( + 'status', + [ 'get', 'set', 'listen' ] + ); + mockUnlisten = jasmine.createSpy(); + + elementClasses = {}; + + mockElement.addClass.andCallFake(function (c) { + elementClasses[c] = true; + }); + mockElement.removeClass.andCallFake(function (c) { + delete elementClasses[c]; + }); + + mockStatusCapability.get.andReturn(testStatusFlags); + mockStatusCapability.listen.andReturn(mockUnlisten); + + mockDomainObject.getCapability.andCallFake(function (c) { + return c === 'status' && mockStatusCapability; + }); + + representer = new StatusRepresenter(mockScope, mockElement); + representer.represent(testRepresentation, mockDomainObject); + }); + + it("listens for status changes", function () { + expect(mockStatusCapability.listen) + .toHaveBeenCalledWith(jasmine.any(Function)); + }); + + it("initially sets classes to reflect status", verifyClasses); + + it("changes classes on status change callbacks", function () { + updateStatus(['a', 'x', '123']); + verifyClasses(); + }); + + it("stops listening when destroyed", function () { + expect(mockUnlisten).not.toHaveBeenCalled(); + representer.destroy(); + expect(mockUnlisten).toHaveBeenCalled(); + }); + + it("removes status classes when destroyed", function () { + expect(elementClasses).not.toEqual({}); + representer.destroy(); + expect(elementClasses).toEqual({}); + }); }); } ); diff --git a/platform/status/test/StatusServiceSpec.js b/platform/status/test/StatusServiceSpec.js index f800002551..1f85cd70a1 100644 --- a/platform/status/test/StatusServiceSpec.js +++ b/platform/status/test/StatusServiceSpec.js @@ -27,6 +27,68 @@ define( "use strict"; describe("The status service", function () { + var mockTopic, + mockTopicInstance, + mockUnlisten, + mockCallback, + testId, + testStatus, + statusService; + + beforeEach(function () { + testId = "some-domain-object-identifier"; + testStatus = "test-status"; + + mockTopic = jasmine.createSpy('topic'); + mockTopicInstance = jasmine.createSpyObj( + 'topicInstance', + [ 'notify', 'listen' ] + ); + mockUnlisten = jasmine.createSpy('unlisten'); + mockCallback = jasmine.createSpy('callback'); + + mockTopic.andReturn(mockTopicInstance); + mockTopicInstance.listen.andReturn(mockUnlisten); + + statusService = new StatusService(mockTopic); + }); + + it("initially contains no flags for an object", function () { + expect(statusService.getStatus(testId)).toEqual([]); + }); + + it("stores and clears status flags", function () { + statusService.setStatus(testId, testStatus, true); + expect(statusService.getStatus(testId)).toEqual([testStatus]); + statusService.setStatus(testId, testStatus, false); + expect(statusService.getStatus(testId)).toEqual([]); + }); + + it("uses topic to listen for changes", function () { + expect(statusService.listen(testId, mockCallback)) + .toEqual(mockUnlisten); + expect(mockTopic) + .toHaveBeenCalledWith(jasmine.any(String)); + // Just care that the topic was somehow unique to the object + expect(mockTopic.mostRecentCall.args[0].indexOf(testId)) + .not.toEqual(-1); + }); + + it("notifies listeners of changes", function () { + statusService.setStatus(testId, testStatus, true); + expect(mockTopicInstance.notify) + .toHaveBeenCalledWith([ testStatus ]); + statusService.setStatus(testId, testStatus, false); + expect(mockTopicInstance.notify) + .toHaveBeenCalledWith([ ]); + + expect(mockTopic) + .toHaveBeenCalledWith(jasmine.any(String)); + // Just care that the topic was somehow unique to the object + expect(mockTopic.mostRecentCall.args[0].indexOf(testId)) + .not.toEqual(-1); + }); + }); } );