Added ConductorAxisController tests

This commit is contained in:
Henry
2016-10-26 18:07:50 -07:00
parent c3322e3847
commit dfed0a0783
3 changed files with 94 additions and 63 deletions

View File

@ -62,7 +62,7 @@ define([
it("Returns appropriate time units for a given time span", function () { it("Returns appropriate time units for a given time span", function () {
var ONE_DAY = 1000 * 60 * 60 * 24; var ONE_DAY = 1000 * 60 * 60 * 24;
var FIVE_DAYS = 5 * ONE_DAY; var FIVE_DAYS = 5 * ONE_DAY;
var TWO_MONTHS = 60 * ONE_DAY; var FIVE_MONTHS = 60 * ONE_DAY;
var ONE_YEAR = 365 * ONE_DAY; var ONE_YEAR = 365 * ONE_DAY;
var SEVEN_YEARS = 7 * ONE_YEAR; var SEVEN_YEARS = 7 * ONE_YEAR;
@ -72,7 +72,7 @@ define([
expect(format.timeUnits(ONE_DAY)).toEqual("Hours"); expect(format.timeUnits(ONE_DAY)).toEqual("Hours");
//Multiple days should display "Days" //Multiple days should display "Days"
expect(format.timeUnits(FIVE_DAYS)).toEqual("Days"); expect(format.timeUnits(FIVE_DAYS)).toEqual("Days");
expect(format.timeUnits(TWO_MONTHS)).toEqual("Months"); expect(format.timeUnits(FIVE_MONTHS)).toEqual("Days");
//A span of one year should show a zoom level of "Months". //A span of one year should show a zoom level of "Months".
// Multiple years will show "Years" // Multiple years will show "Years"
expect(format.timeUnits(ONE_YEAR)).toEqual("Months"); expect(format.timeUnits(ONE_YEAR)).toEqual("Months");

View File

@ -34,7 +34,6 @@ define(
*/ */
function ConductorAxisController(openmct, formatService, conductorViewService, scope, element) { function ConductorAxisController(openmct, formatService, conductorViewService, scope, element) {
// Dependencies // Dependencies
this.d3 = d3;
this.formatService = formatService; this.formatService = formatService;
this.conductor = openmct.conductor; this.conductor = openmct.conductor;
this.conductorViewService = conductorViewService; this.conductorViewService = conductorViewService;
@ -70,19 +69,17 @@ define(
ConductorAxisController.prototype.initialize = function (element) { ConductorAxisController.prototype.initialize = function (element) {
this.target = element[0].firstChild; this.target = element[0].firstChild;
var height = this.target.offsetHeight; var height = this.target.offsetHeight;
var vis = this.d3.select(this.target) var vis = d3.select(this.target)
.append("svg:svg") .append("svg:svg")
.attr("width", "100%") .attr("width", "100%")
.attr("height", height); .attr("height", height);
this.xAxis = this.d3.axisTop(); this.xAxis = d3.axisTop();
// draw x axis with labels and move to the bottom of the chart area // draw x axis with labels and move to the bottom of the chart area
this.axisElement = vis.append("g") this.axisElement = vis.append("g")
.attr("transform", "translate(0," + (height - PADDING) + ")"); .attr("transform", "translate(0," + (height - PADDING) + ")");
this.initialized = true;
if (this.timeSystem !== undefined) { if (this.timeSystem !== undefined) {
this.changeTimeSystem(this.timeSystem); this.changeTimeSystem(this.timeSystem);
this.setScale(); this.setScale();
@ -100,7 +97,7 @@ define(
ConductorAxisController.prototype.changeBounds = function (bounds) { ConductorAxisController.prototype.changeBounds = function (bounds) {
this.bounds = bounds; this.bounds = bounds;
if (this.initialized && !this.zooming) { if (!this.zooming) {
this.setScale(); this.setScale();
} }
}; };
@ -114,13 +111,15 @@ define(
var bounds = this.bounds; var bounds = this.bounds;
if (timeSystem.isUTCBased()) { if (timeSystem.isUTCBased()) {
this.xScale = this.xScale || this.d3.scaleUtc(); this.xScale = this.xScale || d3.scaleUtc();
this.xScale.domain([new Date(bounds.start), new Date(bounds.end)]); this.xScale.domain([new Date(bounds.start), new Date(bounds.end)]);
} else { } else {
this.xScale = this.xScale || this.d3.scaleLinear(); this.xScale = this.xScale || d3.scaleLinear();
this.xScale.domain([bounds.start, bounds.end]); this.xScale.domain([bounds.start, bounds.end]);
} }
this.xAxis.scale(this.xScale);
this.xScale.range([PADDING, width - PADDING * 2]); this.xScale.range([PADDING, width - PADDING * 2]);
this.axisElement.call(this.xAxis); this.axisElement.call(this.xAxis);
@ -136,16 +135,16 @@ define(
this.timeSystem = timeSystem; this.timeSystem = timeSystem;
var key = timeSystem.formats()[0]; var key = timeSystem.formats()[0];
if (this.initialized && key !== undefined) { if (key !== undefined) {
var format = this.formatService.getFormat(key); var format = this.formatService.getFormat(key);
var bounds = this.conductor.bounds(); var bounds = this.conductor.bounds();
//The D3 scale used depends on the type of time system as d3 //The D3 scale used depends on the type of time system as d3
// supports UTC out of the box. // supports UTC out of the box.
if (timeSystem.isUTCBased()) { if (timeSystem.isUTCBased()) {
this.xScale = this.d3.scaleUtc(); this.xScale = d3.scaleUtc();
} else { } else {
this.xScale = this.d3.scaleLinear(); this.xScale = d3.scaleLinear();
} }
this.xAxis.scale(this.xScale); this.xAxis.scale(this.xScale);
@ -204,9 +203,7 @@ define(
}; };
ConductorAxisController.prototype.resize = function () { ConductorAxisController.prototype.resize = function () {
if (this.initialized) {
this.setScale(); this.setScale();
}
}; };
return ConductorAxisController; return ConductorAxisController;

View File

@ -20,16 +20,33 @@
* at runtime from the About dialog for additional information. * at runtime from the About dialog for additional information.
*****************************************************************************/ *****************************************************************************/
define(['./MctConductorAxis'], function (MctConductorAxis) { define([
describe("The MctConductorAxis directive", function () { './ConductorAxisController',
'zepto',
'd3'
], function (
ConductorAxisController,
$,
d3
) {
ddescribe("The ConductorAxisController", function () {
var directive, var directive,
mockConductor, mockConductor,
mockConductorViewService,
mockFormatService, mockFormatService,
mockScope, mockScope,
mockElement, mockElement,
mockTarget, mockTarget,
mockBounds, mockBounds,
d3; element,
mockTimeSystem,
mockFormat;
function getCallback(target, name) {
return target.calls.filter(function (call){
return call.args[0] === name;
})[0].args[1];
}
beforeEach(function () { beforeEach(function () {
mockScope = jasmine.createSpyObj("scope", [ mockScope = jasmine.createSpyObj("scope", [
@ -52,7 +69,8 @@ define(['./MctConductorAxis'], function (MctConductorAxis) {
"timeSystem", "timeSystem",
"bounds", "bounds",
"on", "on",
"off" "off",
"follow"
]); ]);
mockConductor.bounds.andReturn(mockBounds); mockConductor.bounds.andReturn(mockBounds);
@ -60,46 +78,19 @@ define(['./MctConductorAxis'], function (MctConductorAxis) {
"getFormat" "getFormat"
]); ]);
var d3Functions = [ mockConductorViewService = jasmine.createSpyObj("conductorViewService", [
"scale", "on",
"scaleUtc", "off",
"scaleLinear", "emit"
"select", ]);
"append",
"attr",
"axisTop",
"call",
"tickFormat",
"domain",
"range"
];
d3 = jasmine.createSpyObj("d3", d3Functions);
d3Functions.forEach(function (func) {
d3[func].andReturn(d3);
});
directive = new MctConductorAxis(mockConductor, mockFormatService); spyOn(d3, 'scaleUtc').andCallThrough();
directive.d3 = d3; spyOn(d3, 'scaleLinear').andCallThrough();
directive.link(mockScope, [mockElement]);
});
it("listens for changes to time system and bounds", function () { element = $('<div style="width: 100px;"><div style="width: 100%;"></div></div>');
expect(mockConductor.on).toHaveBeenCalledWith("timeSystem", directive.changeTimeSystem); $(document).find('body').append(element);
expect(mockConductor.on).toHaveBeenCalledWith("bounds", directive.setScale); directive = new ConductorAxisController({conductor: mockConductor}, mockFormatService, mockConductorViewService, mockScope, element);
});
it("on scope destruction, deregisters listeners", function () {
expect(mockScope.$on).toHaveBeenCalledWith("$destroy", directive.destroy);
directive.destroy();
expect(mockConductor.off).toHaveBeenCalledWith("timeSystem", directive.changeTimeSystem);
expect(mockConductor.off).toHaveBeenCalledWith("bounds", directive.setScale);
});
describe("when the time system changes", function () {
var mockTimeSystem;
var mockFormat;
beforeEach(function () {
mockTimeSystem = jasmine.createSpyObj("timeSystem", [ mockTimeSystem = jasmine.createSpyObj("timeSystem", [
"formats", "formats",
"isUTCBased" "isUTCBased"
@ -110,11 +101,27 @@ define(['./MctConductorAxis'], function (MctConductorAxis) {
mockTimeSystem.formats.andReturn(["mockFormat"]); mockTimeSystem.formats.andReturn(["mockFormat"]);
mockFormatService.getFormat.andReturn(mockFormat); mockFormatService.getFormat.andReturn(mockFormat);
mockConductor.timeSystem.andReturn(mockTimeSystem);
mockTimeSystem.isUTCBased.andReturn(false);
}); });
it("listens for changes to time system and bounds", function () {
expect(mockConductor.on).toHaveBeenCalledWith("timeSystem", directive.changeTimeSystem);
expect(mockConductor.on).toHaveBeenCalledWith("bounds", directive.changeBounds);
});
it("on scope destruction, deregisters listeners", function () {
expect(mockScope.$on).toHaveBeenCalledWith("$destroy", directive.destroy);
directive.destroy();
expect(mockConductor.off).toHaveBeenCalledWith("timeSystem", directive.changeTimeSystem);
expect(mockConductor.off).toHaveBeenCalledWith("bounds", directive.changeBounds);
});
describe("when the time system changes", function () {
it("uses a UTC scale for UTC time systems", function () { it("uses a UTC scale for UTC time systems", function () {
mockTimeSystem.isUTCBased.andReturn(true); mockTimeSystem.isUTCBased.andReturn(true);
directive.changeTimeSystem(mockTimeSystem); directive.changeTimeSystem(mockTimeSystem);
expect(d3.scaleUtc).toHaveBeenCalled(); expect(d3.scaleUtc).toHaveBeenCalled();
expect(d3.scaleLinear).not.toHaveBeenCalled(); expect(d3.scaleLinear).not.toHaveBeenCalled();
}); });
@ -128,19 +135,46 @@ define(['./MctConductorAxis'], function (MctConductorAxis) {
it("sets axis domain to time conductor bounds", function () { it("sets axis domain to time conductor bounds", function () {
mockTimeSystem.isUTCBased.andReturn(false); mockTimeSystem.isUTCBased.andReturn(false);
mockConductor.timeSystem.andReturn(mockTimeSystem);
directive.setScale(); directive.setScale();
expect(d3.domain).toHaveBeenCalledWith([mockBounds.start, mockBounds.end]); expect(directive.xScale.domain()).toEqual([mockBounds.start, mockBounds.end]);
}); });
it("uses the format specified by the time system to format tick" + it("uses the format specified by the time system to format tick" +
" labels", function () { " labels", function () {
directive.changeTimeSystem(mockTimeSystem); directive.changeTimeSystem(mockTimeSystem);
expect(d3.tickFormat).toHaveBeenCalled();
d3.tickFormat.mostRecentCall.args[0]();
expect(mockFormat.format).toHaveBeenCalled(); expect(mockFormat.format).toHaveBeenCalled();
});
});
it('responds to zoom events', function () {
expect(mockConductorViewService.on).toHaveBeenCalledWith("zoom", directive.onZoom);
var cb = getCallback(mockConductorViewService.on, "zoom");
spyOn(directive, 'setScale').andCallThrough();
cb({bounds: {start: 0, end: 100}});
expect(directive.setScale).toHaveBeenCalled();
});
it('adjusts scale on pan', function () {
spyOn(directive, 'setScale').andCallThrough();
directive.pan(100);
expect(directive.setScale).toHaveBeenCalled();
});
it('emits event on pan', function () {
spyOn(directive,'setScale').andCallThrough();
directive.pan(100);
expect(mockConductorViewService.emit).toHaveBeenCalledWith("pan", jasmine.any(Object));
});
it('cleans up listeners on destruction', function () {
directive.destroy();
expect(mockConductor.off).toHaveBeenCalledWith("bounds", directive.changeBounds);
expect(mockConductor.off).toHaveBeenCalledWith("timeSystem", directive.changeTimeSystem);
expect(mockConductorViewService.off).toHaveBeenCalledWith("zoom", directive.onZoom);
});
}); });
}); });
}); });