[Plugins] Bring over timeline, clock plugins

WTD-1239
This commit is contained in:
Victor Woeltjen
2015-09-14 16:45:38 -07:00
parent 8c1b70f085
commit c932e953bc
119 changed files with 10485 additions and 0 deletions

View File

@@ -0,0 +1,132 @@
/*global define,describe,it,expect,beforeEach,waitsFor,jasmine,window,afterEach*/
define(
['../../../src/controllers/graph/TimelineGraphPopulator'],
function (TimelineGraphPopulator) {
'use strict';
describe("A Timeline's resource graph populator", function () {
var mockSwimlanes,
mockQ,
testResources,
populator;
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;
}));
}
beforeEach(function () {
testResources = {
a: [ 'xyz', 'abc' ],
b: [ 'xyz' ],
c: [ 'xyz', 'abc', 'def', 'ghi' ]
};
mockQ = jasmine.createSpyObj('$q', ['when', 'all']);
mockSwimlanes = ['a', 'b', 'c'].map(function (k) {
var mockSwimlane = jasmine.createSpyObj(
'swimlane-' + k,
[ 'graph', 'color' ]
),
mockGraph = jasmine.createSpyObj(
'graph-' + k,
[ 'getPointCount', 'getDomainValue', 'getRangeValue' ]
);
mockSwimlane.graph.andReturn(true);
mockSwimlane.domainObject = jasmine.createSpyObj(
'domainObject-' + k,
[ 'getCapability', 'hasCapability', 'useCapability', 'getId' ]
);
mockSwimlane.color.andReturn('#' + k);
// Provide just enough information about graphs to support
// determination of which graphs to show
mockSwimlane.domainObject.useCapability.andCallFake(function () {
var obj = {};
testResources[k].forEach(function (r) {
obj[r] = mockGraph;
});
return asPromise(obj);
});
mockSwimlane.domainObject.hasCapability
.andReturn(true);
mockSwimlane.domainObject.getId
.andReturn(k);
mockGraph.getPointCount.andReturn(0);
return mockSwimlane;
});
mockQ.when.andCallFake(asPromise);
mockQ.all.andCallFake(allPromises);
populator = new TimelineGraphPopulator(mockQ);
});
it("provides no graphs by default", function () {
expect(populator.get()).toEqual([]);
});
it("provides one graph per resource type", function () {
populator.populate(mockSwimlanes);
// There are 4 unique resource types shared here...
expect(populator.get().length).toEqual(4);
});
it("does not include graphs based on swimlane configuration", function () {
mockSwimlanes[2].graph.andReturn(false);
populator.populate(mockSwimlanes);
// Only two unique swimlanes in the other two
expect(populator.get().length).toEqual(2);
// Verify interactions as well
expect(mockSwimlanes[0].domainObject.useCapability)
.toHaveBeenCalledWith('graph');
expect(mockSwimlanes[1].domainObject.useCapability)
.toHaveBeenCalledWith('graph');
expect(mockSwimlanes[2].domainObject.useCapability)
.not.toHaveBeenCalled();
});
it("does not recreate graphs when swimlanes don't change", function () {
var initialValue;
// Get an initial set of graphs
populator.populate(mockSwimlanes);
initialValue = populator.get();
// Repopulate with same data; should get same graphs
populator.populate(mockSwimlanes);
expect(populator.get()).toBe(initialValue);
// Something changed...
mockSwimlanes.pop();
populator.populate(mockSwimlanes);
// Now we should get different graphs
expect(populator.get()).not.toBe(initialValue);
});
// Regression test for WTD-1155
it("does recreate graphs when inclusions change", function () {
var initialValue;
// Get an initial set of graphs
populator.populate(mockSwimlanes);
initialValue = populator.get();
// Change resource graph inclusion...
mockSwimlanes[1].graph.andReturn(false);
populator.populate(mockSwimlanes);
// Now we should get different graphs
expect(populator.get()).not.toBe(initialValue);
});
});
}
);

View File

@@ -0,0 +1,56 @@
/*global define,describe,it,expect,beforeEach,waitsFor,jasmine,window,afterEach*/
define(
['../../../src/controllers/graph/TimelineGraphRenderer'],
function (TimelineGraphRenderer) {
'use strict';
describe("A Timeline's graph renderer", function () {
var renderer;
beforeEach(function () {
renderer = new TimelineGraphRenderer();
});
it("converts utilizations to buffers", function () {
var utilization = {
getPointCount: function () {
return 10;
},
getDomainValue: function (i) {
return i * 10;
},
getRangeValue: function (i) {
return Math.sin(i);
}
},
buffer = renderer.render(utilization),
i;
// Should be flat list of alternating x/y,
// so 20 elements
expect(buffer.length).toEqual(20);
// Verify contents
for (i = 0; i < 10; i += 1) {
// Check for 6 decimal digits of precision, roughly
// what we expect after conversion to 32-bit float
expect(buffer[i * 2]).toBeCloseTo(i * 10, 6);
expect(buffer[i * 2 + 1]).toBeCloseTo(Math.sin(i), 6);
}
});
it("decodes color strings", function () {
// Note that decoded color should have alpha channel as well
expect(renderer.decode('#FFFFFF'))
.toEqual([1, 1, 1, 1]);
expect(renderer.decode('#000000'))
.toEqual([0, 0, 0, 1]);
expect(renderer.decode('#FF8000'))
.toEqual([1, 0.5019607843137255, 0, 1]);
});
});
}
);

View File

@@ -0,0 +1,151 @@
/*global define,describe,it,expect,beforeEach,waitsFor,jasmine,window,afterEach*/
define(
['../../../src/controllers/graph/TimelineGraph'],
function (TimelineGraph) {
'use strict';
describe("A Timeline's resource graph", function () {
var mockDomainObjects,
mockRenderer,
testColors,
mockGraphs,
graph;
function asPromise(v) {
return (v || {}).then ? v : {
then: function (callback) {
return asPromise(callback(v));
}
};
}
beforeEach(function () {
testColors = {
a: [ 0, 1, 0 ],
b: [ 1, 0, 1 ],
c: [ 1, 0, 0 ]
};
mockGraphs = [];
mockDomainObjects = {};
['a', 'b', 'c'].forEach(function (k, i) {
var mockGraph = jasmine.createSpyObj(
'utilization-' + k,
[ 'getPointCount', 'getDomainValue', 'getRangeValue' ]
);
mockDomainObjects[k] = jasmine.createSpyObj(
'domainObject-' + k,
[ 'getCapability', 'useCapability' ]
);
mockDomainObjects[k].useCapability.andReturn(asPromise({
testResource: mockGraph
}));
mockGraph.getPointCount.andReturn(i + 2);
mockGraph.testField = k;
mockGraph.testIndex = i;
// Store to allow changes later
mockGraphs.push(mockGraph);
});
mockRenderer = jasmine.createSpyObj(
'renderer',
[ 'render', 'decode' ]
);
mockRenderer.render.andCallFake(function (utilization) {
var result = [];
while (result.length < (utilization.testIndex + 2) * 2) {
result.push(Math.floor(result.length / 2));
// Alternate +/- to give something to test to
result.push(
((result.length % 4 > 1) ? -1 : 1) *
(10 * utilization.testIndex)
);
}
return result;
});
mockRenderer.decode.andCallFake(function (color) {
return testColors[color];
});
graph = new TimelineGraph(
'testResource',
mockDomainObjects,
mockRenderer
);
});
it("exposes minimum/maximum", function () {
expect(graph.minimum()).toEqual(-20);
expect(graph.maximum()).toEqual(20);
});
it("exposes resource key", function () {
expect(graph.key).toEqual('testResource');
});
it("exposes a rendered drawing object", function () {
// Much of the work here is done by the renderer,
// so just check that it got used and assigned
expect(graph.drawingObject.lines).toEqual([
{
color: testColors.a,
buffer: [0, 0, 1, 0],
points: 2
},
{
color: testColors.b,
buffer: [0, 10, 1, -10, 2, 10],
points: 3
},
{
color: testColors.c,
buffer: [0, 20, 1, -20, 2, 20, 3, -20],
points: 4
}
]);
});
it("allows its bounds to be specified", function () {
graph.setBounds(42, 12321);
expect(graph.drawingObject.origin[0]).toEqual(42);
expect(graph.drawingObject.dimensions[0]).toEqual(12321);
});
it("provides a minimum/maximum even with no data", function () {
mockGraphs.forEach(function (mockGraph) {
mockGraph.getPointCount.andReturn(0);
});
// Create a graph of these utilizations
graph = new TimelineGraph(
'testResource',
mockDomainObjects,
mockRenderer
);
// Verify that we get some usable defaults
expect(graph.minimum()).toEqual(jasmine.any(Number));
expect(graph.maximum()).toEqual(jasmine.any(Number));
expect(graph.maximum() > graph.minimum()).toBeTruthy();
});
it("refreshes lines upon request", function () {
// Mock renderer looks at testIndex, so change it here...
mockGraphs[0].testIndex = 3;
// Should trigger a new render
graph.refresh();
// Values correspond to the new index now
expect(graph.drawingObject.lines[0].buffer).toEqual(
[0, 30, 1, -30, 2, 30, 3, -30, 4, 30]
);
});
});
}
);