2015-09-04 16:44:08 +00:00
|
|
|
/*****************************************************************************
|
2016-07-12 23:21:58 +00:00
|
|
|
* Open MCT, Copyright (c) 2014-2016, United States Government
|
2015-09-04 16:44:08 +00:00
|
|
|
* as represented by the Administrator of the National Aeronautics and Space
|
|
|
|
* Administration. All rights reserved.
|
|
|
|
*
|
2016-07-12 23:21:58 +00:00
|
|
|
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
2015-09-04 16:44:08 +00:00
|
|
|
* "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.
|
|
|
|
*
|
2016-07-12 23:21:58 +00:00
|
|
|
* Open MCT includes source code licensed under additional open source
|
2015-09-04 16:44:08 +00:00
|
|
|
* 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.
|
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
define(
|
2015-09-25 17:40:19 +00:00
|
|
|
["../src/ConductorRepresenter", "./TestTimeConductor"],
|
|
|
|
function (ConductorRepresenter, TestTimeConductor) {
|
2015-09-04 16:44:08 +00:00
|
|
|
|
2015-09-04 19:12:21 +00:00
|
|
|
var SCOPE_METHODS = [
|
|
|
|
'$on',
|
|
|
|
'$watch',
|
|
|
|
'$broadcast',
|
|
|
|
'$emit',
|
|
|
|
'$new',
|
|
|
|
'$destroy'
|
|
|
|
],
|
|
|
|
ELEMENT_METHODS = [
|
|
|
|
'hasClass',
|
|
|
|
'addClass',
|
2015-09-04 19:44:49 +00:00
|
|
|
'removeClass',
|
|
|
|
'css',
|
|
|
|
'after',
|
2016-01-15 03:57:06 +00:00
|
|
|
'remove',
|
|
|
|
'parent'
|
2015-09-04 19:12:21 +00:00
|
|
|
];
|
|
|
|
|
2016-05-26 18:35:56 +00:00
|
|
|
describe("ConductorRepresenter", function () {
|
2015-10-02 23:38:32 +00:00
|
|
|
var mockThrottle,
|
|
|
|
mockConductorService,
|
2015-09-04 19:12:21 +00:00
|
|
|
mockCompile,
|
|
|
|
testViews,
|
|
|
|
mockScope,
|
|
|
|
mockElement,
|
|
|
|
mockConductor,
|
|
|
|
mockCompiledTemplate,
|
|
|
|
mockNewScope,
|
|
|
|
mockNewElement,
|
|
|
|
representer;
|
|
|
|
|
2015-09-04 19:44:49 +00:00
|
|
|
function fireWatch(scope, watch, value) {
|
|
|
|
scope.$watch.calls.forEach(function (call) {
|
|
|
|
if (call.args[0] === watch) {
|
|
|
|
call.args[1](value);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2015-09-04 19:12:21 +00:00
|
|
|
beforeEach(function () {
|
2015-10-02 23:38:32 +00:00
|
|
|
mockThrottle = jasmine.createSpy('throttle');
|
2015-09-04 19:12:21 +00:00
|
|
|
mockConductorService = jasmine.createSpyObj(
|
|
|
|
'conductorService',
|
|
|
|
['getConductor']
|
|
|
|
);
|
|
|
|
mockCompile = jasmine.createSpy('$compile');
|
2016-05-19 18:29:13 +00:00
|
|
|
testViews = [{ someKey: "some value" }];
|
2015-09-04 19:12:21 +00:00
|
|
|
mockScope = jasmine.createSpyObj('scope', SCOPE_METHODS);
|
|
|
|
mockElement = jasmine.createSpyObj('element', ELEMENT_METHODS);
|
2016-01-15 03:57:06 +00:00
|
|
|
mockElement.parent.andReturn(mockElement);
|
2015-09-25 17:40:19 +00:00
|
|
|
mockConductor = new TestTimeConductor();
|
2015-09-04 19:12:21 +00:00
|
|
|
mockCompiledTemplate = jasmine.createSpy('template');
|
|
|
|
mockNewScope = jasmine.createSpyObj('newScope', SCOPE_METHODS);
|
2015-09-04 19:44:49 +00:00
|
|
|
mockNewElement = jasmine.createSpyObj('newElement', ELEMENT_METHODS);
|
|
|
|
mockNewElement[0] = mockNewElement;
|
|
|
|
|
|
|
|
mockConductorService.getConductor.andReturn(mockConductor);
|
|
|
|
mockCompile.andReturn(mockCompiledTemplate);
|
|
|
|
mockCompiledTemplate.andReturn(mockNewElement);
|
|
|
|
mockScope.$new.andReturn(mockNewScope);
|
2015-10-02 23:38:32 +00:00
|
|
|
mockThrottle.andCallFake(function (fn) {
|
|
|
|
return fn;
|
|
|
|
});
|
2015-09-04 19:44:49 +00:00
|
|
|
|
|
|
|
representer = new ConductorRepresenter(
|
2015-10-02 23:38:32 +00:00
|
|
|
mockThrottle,
|
2015-09-04 19:44:49 +00:00
|
|
|
mockConductorService,
|
|
|
|
mockCompile,
|
|
|
|
testViews,
|
|
|
|
mockScope,
|
|
|
|
mockElement
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
|
|
|
afterEach(function () {
|
|
|
|
representer.destroy();
|
|
|
|
});
|
|
|
|
|
|
|
|
it("adds a conductor to views", function () {
|
|
|
|
representer.represent(testViews[0], {});
|
|
|
|
expect(mockElement.after).toHaveBeenCalledWith(mockNewElement);
|
|
|
|
});
|
|
|
|
|
|
|
|
it("adds nothing to non-view representations", function () {
|
|
|
|
representer.represent({ someKey: "something else" }, {});
|
|
|
|
expect(mockElement.after).not.toHaveBeenCalled();
|
|
|
|
});
|
|
|
|
|
|
|
|
it("removes the conductor when destroyed", function () {
|
|
|
|
representer.represent(testViews[0], {});
|
|
|
|
expect(mockNewElement.remove).not.toHaveBeenCalled();
|
|
|
|
representer.destroy();
|
|
|
|
expect(mockNewElement.remove).toHaveBeenCalled();
|
|
|
|
});
|
|
|
|
|
|
|
|
it("destroys any new scope created", function () {
|
|
|
|
representer.represent(testViews[0], {});
|
|
|
|
representer.destroy();
|
|
|
|
expect(mockNewScope.$destroy.calls.length)
|
|
|
|
.toEqual(mockScope.$new.calls.length);
|
|
|
|
});
|
|
|
|
|
|
|
|
it("exposes conductor state in scope", function () {
|
|
|
|
mockConductor.displayStart.andReturn(1977);
|
|
|
|
mockConductor.displayEnd.andReturn(1984);
|
2015-10-27 22:43:31 +00:00
|
|
|
mockConductor.domain.andReturn({ key: 'd' });
|
2015-09-04 19:44:49 +00:00
|
|
|
representer.represent(testViews[0], {});
|
|
|
|
|
2015-09-25 17:40:19 +00:00
|
|
|
expect(mockNewScope.ngModel.conductor).toEqual({
|
2015-10-09 18:17:57 +00:00
|
|
|
inner: { start: 1977, end: 1984, domain: 'd' },
|
|
|
|
outer: { start: 1977, end: 1984, domain: 'd' }
|
2015-09-04 19:44:49 +00:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it("updates conductor state from scope", function () {
|
|
|
|
var testState = {
|
2015-09-10 18:31:40 +00:00
|
|
|
inner: { start: 42, end: 1984 },
|
|
|
|
outer: { start: -1977, end: 12321 }
|
2015-09-04 19:44:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
representer.represent(testViews[0], {});
|
|
|
|
|
2015-09-25 17:40:19 +00:00
|
|
|
mockNewScope.ngModel.conductor = testState;
|
2015-09-04 19:44:49 +00:00
|
|
|
|
2015-09-25 17:40:19 +00:00
|
|
|
fireWatch(
|
|
|
|
mockNewScope,
|
|
|
|
'ngModel.conductor.inner.start',
|
|
|
|
testState.inner.start
|
|
|
|
);
|
2015-09-04 19:44:49 +00:00
|
|
|
expect(mockConductor.displayStart).toHaveBeenCalledWith(42);
|
|
|
|
|
2015-09-25 17:40:19 +00:00
|
|
|
fireWatch(
|
|
|
|
mockNewScope,
|
|
|
|
'ngModel.conductor.inner.end',
|
|
|
|
testState.inner.end
|
|
|
|
);
|
2015-09-04 19:44:49 +00:00
|
|
|
expect(mockConductor.displayEnd).toHaveBeenCalledWith(1984);
|
2015-09-04 19:12:21 +00:00
|
|
|
});
|
2015-09-04 19:44:49 +00:00
|
|
|
|
2015-10-02 23:38:32 +00:00
|
|
|
describe("when bounds are changing", function () {
|
2015-10-09 18:17:57 +00:00
|
|
|
var startWatch = "ngModel.conductor.inner.start",
|
|
|
|
endWatch = "ngModel.conductor.inner.end",
|
|
|
|
mockThrottledFn = jasmine.createSpy('throttledFn'),
|
2015-10-02 23:38:32 +00:00
|
|
|
testBounds;
|
|
|
|
|
|
|
|
function fireThrottledFn() {
|
|
|
|
mockThrottle.mostRecentCall.args[0]();
|
|
|
|
}
|
|
|
|
|
|
|
|
beforeEach(function () {
|
|
|
|
mockThrottle.andReturn(mockThrottledFn);
|
|
|
|
representer.represent(testViews[0], {});
|
|
|
|
testBounds = { start: 0, end: 1000 };
|
2015-10-09 18:17:57 +00:00
|
|
|
mockNewScope.ngModel.conductor.inner = testBounds;
|
2015-10-02 23:38:32 +00:00
|
|
|
mockConductor.displayStart.andCallFake(function () {
|
|
|
|
return testBounds.start;
|
|
|
|
});
|
|
|
|
mockConductor.displayEnd.andCallFake(function () {
|
|
|
|
return testBounds.end;
|
|
|
|
});
|
|
|
|
});
|
2015-09-04 19:44:49 +00:00
|
|
|
|
2015-10-02 23:38:32 +00:00
|
|
|
it("does not broadcast while bounds are changing", function () {
|
|
|
|
expect(mockScope.$broadcast).not.toHaveBeenCalled();
|
|
|
|
testBounds.start = 100;
|
2015-10-09 18:17:57 +00:00
|
|
|
fireWatch(mockNewScope, startWatch, testBounds.start);
|
2015-10-02 23:38:32 +00:00
|
|
|
testBounds.end = 500;
|
2015-10-09 18:17:57 +00:00
|
|
|
fireWatch(mockNewScope, endWatch, testBounds.end);
|
2015-10-02 23:38:32 +00:00
|
|
|
fireThrottledFn();
|
|
|
|
testBounds.start = 200;
|
2015-10-09 18:17:57 +00:00
|
|
|
fireWatch(mockNewScope, startWatch, testBounds.start);
|
2015-10-02 23:38:32 +00:00
|
|
|
testBounds.end = 400;
|
2015-10-09 18:17:57 +00:00
|
|
|
fireWatch(mockNewScope, endWatch, testBounds.end);
|
2015-10-02 23:38:32 +00:00
|
|
|
fireThrottledFn();
|
|
|
|
expect(mockScope.$broadcast).not.toHaveBeenCalled();
|
|
|
|
});
|
|
|
|
|
|
|
|
it("does broadcast when bounds have stabilized", function () {
|
|
|
|
expect(mockScope.$broadcast).not.toHaveBeenCalled();
|
|
|
|
testBounds.start = 100;
|
2015-10-09 18:17:57 +00:00
|
|
|
fireWatch(mockNewScope, startWatch, testBounds.start);
|
2015-10-02 23:38:32 +00:00
|
|
|
testBounds.end = 500;
|
2015-10-09 18:17:57 +00:00
|
|
|
fireWatch(mockNewScope, endWatch, testBounds.end);
|
2015-10-02 23:38:32 +00:00
|
|
|
fireThrottledFn();
|
2015-10-09 18:17:57 +00:00
|
|
|
fireWatch(mockNewScope, startWatch, testBounds.start);
|
|
|
|
fireWatch(mockNewScope, endWatch, testBounds.end);
|
2015-10-02 23:38:32 +00:00
|
|
|
fireThrottledFn();
|
|
|
|
expect(mockScope.$broadcast).toHaveBeenCalled();
|
|
|
|
});
|
2015-09-04 19:12:21 +00:00
|
|
|
});
|
2015-09-04 16:44:08 +00:00
|
|
|
|
2015-09-25 17:40:19 +00:00
|
|
|
it("exposes domain selection in scope", function () {
|
|
|
|
representer.represent(testViews[0], null);
|
|
|
|
|
|
|
|
expect(mockNewScope.ngModel.domain)
|
2015-10-27 22:43:31 +00:00
|
|
|
.toEqual(mockConductor.domain().key);
|
2015-09-25 17:40:19 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
it("exposes domain options in scope", function () {
|
|
|
|
representer.represent(testViews[0], null);
|
|
|
|
|
|
|
|
mockConductor.domainOptions().forEach(function (option, i) {
|
|
|
|
expect(mockNewScope.ngModel.options[i].value)
|
|
|
|
.toEqual(option.key);
|
|
|
|
expect(mockNewScope.ngModel.options[i].name)
|
|
|
|
.toEqual(option.name);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it("updates domain selection from scope", function () {
|
|
|
|
var choice;
|
|
|
|
representer.represent(testViews[0], null);
|
|
|
|
|
|
|
|
// Choose a domain that isn't currently selected
|
|
|
|
mockNewScope.ngModel.options.forEach(function (option) {
|
|
|
|
if (option.value !== mockNewScope.ngModel.domain) {
|
|
|
|
choice = option.value;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
expect(mockConductor.domain)
|
|
|
|
.not.toHaveBeenCalledWith(choice);
|
|
|
|
|
|
|
|
mockNewScope.ngModel.domain = choice;
|
|
|
|
fireWatch(mockNewScope, "ngModel.domain", choice);
|
|
|
|
|
|
|
|
expect(mockConductor.domain)
|
|
|
|
.toHaveBeenCalledWith(choice);
|
|
|
|
});
|
|
|
|
|
2015-09-04 16:44:08 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
);
|