mirror of
https://github.com/nasa/openmct.git
synced 2024-12-23 06:52:24 +00:00
5274923c49
...to sources for Clocks/Timers and Timelines, as noted in review nasa/openmctweb#207
250 lines
10 KiB
JavaScript
250 lines
10 KiB
JavaScript
/*****************************************************************************
|
|
* Open MCT Web, Copyright (c) 2009-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,describe,it,expect,beforeEach,waitsFor,jasmine,window,afterEach*/
|
|
|
|
define(
|
|
['../../src/controllers/TimelineController'],
|
|
function (TimelineController) {
|
|
'use strict';
|
|
|
|
var DOMAIN_OBJECT_METHODS = [
|
|
'getModel',
|
|
'getId',
|
|
'useCapability',
|
|
'hasCapability',
|
|
'getCapability'
|
|
];
|
|
|
|
describe("The timeline controller", function () {
|
|
var mockScope,
|
|
mockQ,
|
|
mockLoader,
|
|
mockDomainObject,
|
|
mockSpan,
|
|
testModels,
|
|
testConfiguration,
|
|
controller;
|
|
|
|
function asPromise(v) {
|
|
return (v || {}).then ? v : {
|
|
then: function (callback) {
|
|
return asPromise(callback(v));
|
|
},
|
|
testValue: v
|
|
};
|
|
}
|
|
|
|
function allPromises(promises) {
|
|
return asPromise(promises.map(function (p) {
|
|
return (p || {}).then ? p.testValue : p;
|
|
}));
|
|
}
|
|
|
|
function subgraph(domainObject, objects) {
|
|
function lookupSubgraph(id) {
|
|
return subgraph(objects[id], objects);
|
|
}
|
|
return {
|
|
domainObject: domainObject,
|
|
composition: (domainObject.getModel().composition || [])
|
|
.map(lookupSubgraph)
|
|
};
|
|
}
|
|
|
|
|
|
beforeEach(function () {
|
|
var mockA, mockB, mockUtilization, mockPromise, mockGraph, testCapabilities;
|
|
|
|
function getCapability(c) {
|
|
return testCapabilities[c];
|
|
}
|
|
|
|
function useCapability(c) {
|
|
return c === 'timespan' ? asPromise(mockSpan) :
|
|
c === 'graph' ? asPromise({ abc: mockGraph, xyz: mockGraph }) :
|
|
undefined;
|
|
}
|
|
|
|
testModels = {
|
|
a: { modified: 40, composition: ['b'] },
|
|
b: { modified: 2 }
|
|
};
|
|
|
|
testConfiguration = {};
|
|
|
|
mockQ = jasmine.createSpyObj('$q', ['when', 'all']);
|
|
mockA = jasmine.createSpyObj('a', DOMAIN_OBJECT_METHODS);
|
|
mockB = jasmine.createSpyObj('b', DOMAIN_OBJECT_METHODS);
|
|
mockSpan = jasmine.createSpyObj('span', ['getStart', 'getEnd']);
|
|
mockUtilization = jasmine.createSpyObj('utilization', ['resources', 'utilization']);
|
|
mockGraph = jasmine.createSpyObj('graph', ['getPointCount']);
|
|
mockPromise = jasmine.createSpyObj('promise', ['then']);
|
|
|
|
mockScope = jasmine.createSpyObj(
|
|
"$scope",
|
|
[ '$watch', '$on' ]
|
|
);
|
|
mockLoader = jasmine.createSpyObj('objectLoader', ['load']);
|
|
mockDomainObject = mockA;
|
|
|
|
mockScope.domainObject = mockDomainObject;
|
|
mockScope.configuration = testConfiguration;
|
|
mockQ.when.andCallFake(asPromise);
|
|
mockQ.all.andCallFake(allPromises);
|
|
mockA.getId.andReturn('a');
|
|
mockA.getModel.andReturn(testModels.a);
|
|
mockB.getId.andReturn('b');
|
|
mockB.getModel.andReturn(testModels.b);
|
|
mockA.useCapability.andCallFake(useCapability);
|
|
mockB.useCapability.andCallFake(useCapability);
|
|
mockA.hasCapability.andReturn(true);
|
|
mockB.hasCapability.andReturn(true);
|
|
mockA.getCapability.andCallFake(getCapability);
|
|
mockB.getCapability.andCallFake(getCapability);
|
|
mockSpan.getStart.andReturn(42);
|
|
mockSpan.getEnd.andReturn(12321);
|
|
mockUtilization.resources.andReturn(['abc', 'xyz']);
|
|
mockUtilization.utilization.andReturn(mockPromise);
|
|
mockLoader.load.andCallFake(function () {
|
|
return asPromise(subgraph(mockA, {
|
|
a: mockA,
|
|
b: mockB
|
|
}));
|
|
});
|
|
|
|
testCapabilities = {
|
|
"utilization": mockUtilization
|
|
};
|
|
|
|
controller = new TimelineController(mockScope, mockQ, mockLoader, 0);
|
|
});
|
|
|
|
it("exposes scroll state tracker in scope", function () {
|
|
expect(mockScope.scroll.x).toEqual(0);
|
|
expect(mockScope.scroll.y).toEqual(0);
|
|
});
|
|
|
|
it("repopulates when modifications are made", function () {
|
|
var fnWatchCall,
|
|
strWatchCall;
|
|
|
|
// Find the $watch that was given a function
|
|
mockScope.$watch.calls.forEach(function (call) {
|
|
if (typeof call.args[0] === 'function') {
|
|
// white-box: we know the first call is
|
|
// the one we're looking for
|
|
fnWatchCall = fnWatchCall || call;
|
|
} else if (typeof call.args[0] === 'string') {
|
|
strWatchCall = strWatchCall || call;
|
|
}
|
|
});
|
|
|
|
// Make sure string watch was for domainObject
|
|
expect(strWatchCall.args[0]).toEqual('domainObject');
|
|
// Initially populate
|
|
strWatchCall.args[1](mockDomainObject);
|
|
|
|
// There should be to swimlanes
|
|
expect(controller.swimlanes().length).toEqual(2);
|
|
|
|
// Watch should be for sum of modified flags...
|
|
expect(fnWatchCall.args[0]()).toEqual(42);
|
|
|
|
// Remove the child, then fire the watch
|
|
testModels.a.composition = [];
|
|
fnWatchCall.args[1]();
|
|
|
|
// Swimlanes should have updated
|
|
expect(controller.swimlanes().length).toEqual(1);
|
|
});
|
|
|
|
it("repopulates graphs when graph choices change", function () {
|
|
var tmp;
|
|
|
|
// Note that this test is brittle; it relies upon the
|
|
// order of $watch calls in TimelineController.
|
|
|
|
// Initially populate
|
|
mockScope.$watch.calls[0].args[1](mockDomainObject);
|
|
|
|
// Verify precondition - no graphs
|
|
expect(controller.graphs().length).toEqual(0);
|
|
|
|
// Execute the watch function for graph state
|
|
tmp = mockScope.$watch.calls[2].args[0]();
|
|
|
|
// Change graph state
|
|
testConfiguration.graph = { a: true, b: true };
|
|
|
|
// Verify that this would have triggered a watch
|
|
expect(mockScope.$watch.calls[2].args[0]())
|
|
.not.toEqual(tmp);
|
|
|
|
// Run the function the watch would have triggered
|
|
mockScope.$watch.calls[2].args[1]();
|
|
|
|
// Should have some graphs now
|
|
expect(controller.graphs().length).toEqual(2);
|
|
|
|
});
|
|
|
|
it("reports full scrollable width using zoom controller", function () {
|
|
var mockZoom = jasmine.createSpyObj('zoom', ['toPixels', 'duration']);
|
|
mockZoom.toPixels.andReturn(54321);
|
|
mockZoom.duration.andReturn(12345);
|
|
|
|
// Initially populate
|
|
mockScope.$watch.calls[0].args[1](mockDomainObject);
|
|
|
|
expect(controller.width(mockZoom)).toEqual(54321);
|
|
// Verify interactions; we took zoom's duration for our start/end,
|
|
// and converted it to pixels.
|
|
// First, check that we used the start/end (from above)
|
|
expect(mockZoom.duration).toHaveBeenCalledWith(12321 - 42);
|
|
// Next, verify that the result was passed to toPixels
|
|
expect(mockZoom.toPixels).toHaveBeenCalledWith(12345);
|
|
});
|
|
|
|
it("provides drag handles", function () {
|
|
// TimelineDragPopulator et al are tested for these,
|
|
// so just verify that handles are indeed exposed.
|
|
expect(controller.handles()).toEqual(jasmine.any(Array));
|
|
});
|
|
|
|
it("refreshes graphs on request", function () {
|
|
var mockGraph = jasmine.createSpyObj('graph', ['refresh']);
|
|
|
|
// Sneak a mock graph into the graph populator...
|
|
// This is whiteboxy and will have to change if
|
|
// GraphPopulator changes
|
|
controller.graphs().push(mockGraph);
|
|
|
|
// Refresh
|
|
controller.refresh();
|
|
|
|
// Should have refreshed the graph
|
|
expect(mockGraph.refresh).toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
}
|
|
); |