[Plugins] Bring over timeline, clock plugins
WTD-1239
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
/*global define,describe,it,expect,beforeEach,waitsFor,jasmine,window,afterEach*/
|
||||
|
||||
define(
|
||||
["../../src/actions/AbstractStartTimerAction"],
|
||||
function (AbstractStartTimerAction) {
|
||||
"use strict";
|
||||
|
||||
describe("A timer's start/restart action", function () {
|
||||
var mockNow,
|
||||
mockDomainObject,
|
||||
mockPersistence,
|
||||
testModel,
|
||||
action;
|
||||
|
||||
function asPromise(value) {
|
||||
return (value || {}).then ? value : {
|
||||
then: function (callback) {
|
||||
return asPromise(callback(value));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
mockNow = jasmine.createSpy('now');
|
||||
mockDomainObject = jasmine.createSpyObj(
|
||||
'domainObject',
|
||||
[ 'getCapability', 'useCapability' ]
|
||||
);
|
||||
mockPersistence = jasmine.createSpyObj(
|
||||
'persistence',
|
||||
['persist']
|
||||
);
|
||||
|
||||
mockDomainObject.getCapability.andCallFake(function (c) {
|
||||
return (c === 'persistence') && mockPersistence;
|
||||
});
|
||||
mockDomainObject.useCapability.andCallFake(function (c, v) {
|
||||
if (c === 'mutation') {
|
||||
testModel = v(testModel) || testModel;
|
||||
return asPromise(true);
|
||||
}
|
||||
});
|
||||
|
||||
testModel = {};
|
||||
|
||||
action = new AbstractStartTimerAction(mockNow, {
|
||||
domainObject: mockDomainObject
|
||||
});
|
||||
});
|
||||
|
||||
it("updates the model with a timestamp and persists", function () {
|
||||
mockNow.andReturn(12000);
|
||||
action.perform();
|
||||
expect(testModel.timestamp).toEqual(12000);
|
||||
expect(mockPersistence.persist).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("does not truncate milliseconds", function () {
|
||||
mockNow.andReturn(42321);
|
||||
action.perform();
|
||||
expect(testModel.timestamp).toEqual(42321);
|
||||
expect(mockPersistence.persist).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
@@ -0,0 +1,76 @@
|
||||
/*global define,describe,it,expect,beforeEach,waitsFor,jasmine,window,afterEach*/
|
||||
|
||||
define(
|
||||
["../../src/actions/RestartTimerAction"],
|
||||
function (RestartTimerAction) {
|
||||
"use strict";
|
||||
|
||||
describe("A timer's restart action", function () {
|
||||
var mockNow,
|
||||
mockDomainObject,
|
||||
mockPersistence,
|
||||
testModel,
|
||||
testContext,
|
||||
action;
|
||||
|
||||
function asPromise(value) {
|
||||
return (value || {}).then ? value : {
|
||||
then: function (callback) {
|
||||
return asPromise(callback(value));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
mockNow = jasmine.createSpy('now');
|
||||
mockDomainObject = jasmine.createSpyObj(
|
||||
'domainObject',
|
||||
[ 'getCapability', 'useCapability', 'getModel' ]
|
||||
);
|
||||
mockPersistence = jasmine.createSpyObj(
|
||||
'persistence',
|
||||
['persist']
|
||||
);
|
||||
|
||||
mockDomainObject.getCapability.andCallFake(function (c) {
|
||||
return (c === 'persistence') && mockPersistence;
|
||||
});
|
||||
mockDomainObject.useCapability.andCallFake(function (c, v) {
|
||||
if (c === 'mutation') {
|
||||
testModel = v(testModel) || testModel;
|
||||
return asPromise(true);
|
||||
}
|
||||
});
|
||||
mockDomainObject.getModel.andCallFake(function () {
|
||||
return testModel;
|
||||
});
|
||||
|
||||
testModel = {};
|
||||
testContext = { domainObject: mockDomainObject };
|
||||
|
||||
action = new RestartTimerAction(mockNow, testContext);
|
||||
});
|
||||
|
||||
it("updates the model with a timestamp and persists", function () {
|
||||
mockNow.andReturn(12000);
|
||||
action.perform();
|
||||
expect(testModel.timestamp).toEqual(12000);
|
||||
expect(mockPersistence.persist).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("applies only to timers with a target time", function () {
|
||||
testModel.type = 'warp.timer';
|
||||
testModel.timestamp = 12000;
|
||||
expect(RestartTimerAction.appliesTo(testContext)).toBeTruthy();
|
||||
|
||||
testModel.type = 'warp.timer';
|
||||
testModel.timestamp = undefined;
|
||||
expect(RestartTimerAction.appliesTo(testContext)).toBeFalsy();
|
||||
|
||||
testModel.type = 'warp.clock';
|
||||
testModel.timestamp = 12000;
|
||||
expect(RestartTimerAction.appliesTo(testContext)).toBeFalsy();
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
76
platform/features/clock/test/actions/StartTimerActionSpec.js
Normal file
76
platform/features/clock/test/actions/StartTimerActionSpec.js
Normal file
@@ -0,0 +1,76 @@
|
||||
/*global define,describe,it,expect,beforeEach,waitsFor,jasmine,window,afterEach*/
|
||||
|
||||
define(
|
||||
["../../src/actions/StartTimerAction"],
|
||||
function (StartTimerAction) {
|
||||
"use strict";
|
||||
|
||||
describe("A timer's start action", function () {
|
||||
var mockNow,
|
||||
mockDomainObject,
|
||||
mockPersistence,
|
||||
testModel,
|
||||
testContext,
|
||||
action;
|
||||
|
||||
function asPromise(value) {
|
||||
return (value || {}).then ? value : {
|
||||
then: function (callback) {
|
||||
return asPromise(callback(value));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
mockNow = jasmine.createSpy('now');
|
||||
mockDomainObject = jasmine.createSpyObj(
|
||||
'domainObject',
|
||||
[ 'getCapability', 'useCapability', 'getModel' ]
|
||||
);
|
||||
mockPersistence = jasmine.createSpyObj(
|
||||
'persistence',
|
||||
['persist']
|
||||
);
|
||||
|
||||
mockDomainObject.getCapability.andCallFake(function (c) {
|
||||
return (c === 'persistence') && mockPersistence;
|
||||
});
|
||||
mockDomainObject.useCapability.andCallFake(function (c, v) {
|
||||
if (c === 'mutation') {
|
||||
testModel = v(testModel) || testModel;
|
||||
return asPromise(true);
|
||||
}
|
||||
});
|
||||
mockDomainObject.getModel.andCallFake(function () {
|
||||
return testModel;
|
||||
});
|
||||
|
||||
testModel = {};
|
||||
testContext = { domainObject: mockDomainObject };
|
||||
|
||||
action = new StartTimerAction(mockNow, testContext);
|
||||
});
|
||||
|
||||
it("updates the model with a timestamp and persists", function () {
|
||||
mockNow.andReturn(12000);
|
||||
action.perform();
|
||||
expect(testModel.timestamp).toEqual(12000);
|
||||
expect(mockPersistence.persist).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("applies only to timers without a target time", function () {
|
||||
testModel.type = 'warp.timer';
|
||||
testModel.timestamp = 12000;
|
||||
expect(StartTimerAction.appliesTo(testContext)).toBeFalsy();
|
||||
|
||||
testModel.type = 'warp.timer';
|
||||
testModel.timestamp = undefined;
|
||||
expect(StartTimerAction.appliesTo(testContext)).toBeTruthy();
|
||||
|
||||
testModel.type = 'warp.clock';
|
||||
testModel.timestamp = 12000;
|
||||
expect(StartTimerAction.appliesTo(testContext)).toBeFalsy();
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
@@ -0,0 +1,83 @@
|
||||
/*global define,describe,it,expect,beforeEach,waitsFor,jasmine,window,afterEach*/
|
||||
|
||||
define(
|
||||
["../../src/controllers/ClockController"],
|
||||
function (ClockController) {
|
||||
"use strict";
|
||||
|
||||
// Wed, 03 Jun 2015 17:56:14 GMT
|
||||
var TEST_TIMESTAMP = 1433354174000;
|
||||
|
||||
describe("A clock view's controller", function () {
|
||||
var mockScope,
|
||||
mockTicker,
|
||||
mockUnticker,
|
||||
mockDomainObject,
|
||||
controller;
|
||||
|
||||
beforeEach(function () {
|
||||
mockScope = jasmine.createSpyObj('$scope', ['$watch', '$on']);
|
||||
mockTicker = jasmine.createSpyObj('ticker', ['listen']);
|
||||
mockUnticker = jasmine.createSpy('unticker');
|
||||
|
||||
mockTicker.listen.andReturn(mockUnticker);
|
||||
|
||||
controller = new ClockController(mockScope, mockTicker);
|
||||
});
|
||||
|
||||
it("watches for clock format from the domain object model", function () {
|
||||
expect(mockScope.$watch).toHaveBeenCalledWith(
|
||||
"model.clockFormat",
|
||||
jasmine.any(Function)
|
||||
);
|
||||
});
|
||||
|
||||
it("subscribes to clock ticks", function () {
|
||||
expect(mockTicker.listen)
|
||||
.toHaveBeenCalledWith(jasmine.any(Function));
|
||||
});
|
||||
|
||||
it("unsubscribes to ticks when destroyed", function () {
|
||||
// Make sure $destroy is being listened for...
|
||||
expect(mockScope.$on.mostRecentCall.args[0]).toEqual('$destroy');
|
||||
expect(mockUnticker).not.toHaveBeenCalled();
|
||||
|
||||
// ...and makes sure that its listener unsubscribes from ticker
|
||||
mockScope.$on.mostRecentCall.args[1]();
|
||||
expect(mockUnticker).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("formats using the format string from the model", function () {
|
||||
mockTicker.listen.mostRecentCall.args[0](TEST_TIMESTAMP);
|
||||
mockScope.$watch.mostRecentCall.args[1]([
|
||||
"YYYY-DDD hh:mm:ss",
|
||||
"clock24"
|
||||
]);
|
||||
|
||||
expect(controller.zone()).toEqual("UTC");
|
||||
expect(controller.text()).toEqual("2015-154 17:56:14");
|
||||
expect(controller.ampm()).toEqual("");
|
||||
});
|
||||
|
||||
it("formats 12-hour time", function () {
|
||||
mockTicker.listen.mostRecentCall.args[0](TEST_TIMESTAMP);
|
||||
mockScope.$watch.mostRecentCall.args[1]([
|
||||
"YYYY-DDD hh:mm:ss",
|
||||
"clock12"
|
||||
]);
|
||||
|
||||
expect(controller.zone()).toEqual("UTC");
|
||||
expect(controller.text()).toEqual("2015-154 05:56:14");
|
||||
expect(controller.ampm()).toEqual("PM");
|
||||
});
|
||||
|
||||
it("does not throw exceptions when clockFormat is undefined", function () {
|
||||
mockTicker.listen.mostRecentCall.args[0](TEST_TIMESTAMP);
|
||||
expect(function () {
|
||||
mockScope.$watch.mostRecentCall.args[1](undefined);
|
||||
}).not.toThrow();
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
);
|
||||
@@ -0,0 +1,63 @@
|
||||
/*global define,describe,it,expect,beforeEach,waitsFor,jasmine,window,afterEach*/
|
||||
|
||||
define(
|
||||
["../../src/controllers/RefreshingController"],
|
||||
function (RefreshingController) {
|
||||
"use strict";
|
||||
|
||||
|
||||
|
||||
describe("The refreshing controller", function () {
|
||||
var mockScope,
|
||||
mockTicker,
|
||||
mockUnticker,
|
||||
controller;
|
||||
|
||||
beforeEach(function () {
|
||||
mockScope = jasmine.createSpyObj('$scope', ['$on']);
|
||||
mockTicker = jasmine.createSpyObj('ticker', ['listen']);
|
||||
mockUnticker = jasmine.createSpy('unticker');
|
||||
|
||||
mockTicker.listen.andReturn(mockUnticker);
|
||||
|
||||
controller = new RefreshingController(mockScope, mockTicker);
|
||||
});
|
||||
|
||||
it("refreshes the represented object on every tick", function () {
|
||||
var mockDomainObject = jasmine.createSpyObj(
|
||||
'domainObject',
|
||||
[ 'getCapability' ]
|
||||
),
|
||||
mockPersistence = jasmine.createSpyObj(
|
||||
'persistence',
|
||||
[ 'persist', 'refresh' ]
|
||||
);
|
||||
|
||||
mockDomainObject.getCapability.andCallFake(function (c) {
|
||||
return (c === 'persistence') && mockPersistence;
|
||||
});
|
||||
|
||||
mockScope.domainObject = mockDomainObject;
|
||||
|
||||
mockTicker.listen.mostRecentCall.args[0](12321);
|
||||
expect(mockPersistence.refresh).toHaveBeenCalled();
|
||||
expect(mockPersistence.persist).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("subscribes to clock ticks", function () {
|
||||
expect(mockTicker.listen)
|
||||
.toHaveBeenCalledWith(jasmine.any(Function));
|
||||
});
|
||||
|
||||
it("unsubscribes to ticks when destroyed", function () {
|
||||
// Make sure $destroy is being listened for...
|
||||
expect(mockScope.$on.mostRecentCall.args[0]).toEqual('$destroy');
|
||||
expect(mockUnticker).not.toHaveBeenCalled();
|
||||
|
||||
// ...and makes sure that its listener unsubscribes from ticker
|
||||
mockScope.$on.mostRecentCall.args[1]();
|
||||
expect(mockUnticker).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
178
platform/features/clock/test/controllers/TimerControllerSpec.js
Normal file
178
platform/features/clock/test/controllers/TimerControllerSpec.js
Normal file
@@ -0,0 +1,178 @@
|
||||
/*global define,describe,it,expect,beforeEach,waitsFor,jasmine,window,afterEach*/
|
||||
|
||||
define(
|
||||
["../../src/controllers/TimerController"],
|
||||
function (TimerController) {
|
||||
"use strict";
|
||||
|
||||
// Wed, 03 Jun 2015 17:56:14 GMT
|
||||
var TEST_TIMESTAMP = 1433354174000;
|
||||
|
||||
describe("A timer view's controller", function () {
|
||||
var mockScope,
|
||||
mockWindow,
|
||||
mockNow,
|
||||
mockDomainObject,
|
||||
mockActionCapability,
|
||||
mockStart,
|
||||
mockRestart,
|
||||
testModel,
|
||||
controller;
|
||||
|
||||
function invokeWatch(expr, value) {
|
||||
mockScope.$watch.calls.forEach(function (call) {
|
||||
if (call.args[0] === expr) {
|
||||
call.args[1](value);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
mockScope = jasmine.createSpyObj(
|
||||
'$scope',
|
||||
['$watch', '$on', '$apply']
|
||||
);
|
||||
mockWindow = jasmine.createSpyObj(
|
||||
'$window',
|
||||
['requestAnimationFrame']
|
||||
);
|
||||
mockDomainObject = jasmine.createSpyObj(
|
||||
'domainObject',
|
||||
[ 'getCapability', 'useCapability', 'getModel' ]
|
||||
);
|
||||
mockActionCapability = jasmine.createSpyObj(
|
||||
'action',
|
||||
['getActions']
|
||||
);
|
||||
mockStart = jasmine.createSpyObj(
|
||||
'start',
|
||||
['getMetadata', 'perform']
|
||||
);
|
||||
mockRestart = jasmine.createSpyObj(
|
||||
'restart',
|
||||
['getMetadata', 'perform']
|
||||
);
|
||||
mockNow = jasmine.createSpy('now');
|
||||
|
||||
mockDomainObject.getCapability.andCallFake(function (c) {
|
||||
return (c === 'action') && mockActionCapability;
|
||||
});
|
||||
mockDomainObject.getModel.andCallFake(function () {
|
||||
return testModel;
|
||||
});
|
||||
mockActionCapability.getActions.andCallFake(function (k) {
|
||||
return [{
|
||||
'warp.timer.start': mockStart,
|
||||
'warp.timer.restart': mockRestart
|
||||
}[k]];
|
||||
});
|
||||
mockStart.getMetadata.andReturn({ glyph: "S", name: "Start" });
|
||||
mockRestart.getMetadata.andReturn({ glyph: "R", name: "Restart" });
|
||||
mockScope.domainObject = mockDomainObject;
|
||||
|
||||
testModel = {};
|
||||
|
||||
controller = new TimerController(mockScope, mockWindow, mockNow);
|
||||
});
|
||||
|
||||
it("watches for the domain object in view", function () {
|
||||
expect(mockScope.$watch).toHaveBeenCalledWith(
|
||||
"domainObject",
|
||||
jasmine.any(Function)
|
||||
);
|
||||
});
|
||||
|
||||
it("watches for domain object modifications", function () {
|
||||
expect(mockScope.$watch).toHaveBeenCalledWith(
|
||||
"model.modified",
|
||||
jasmine.any(Function)
|
||||
);
|
||||
});
|
||||
|
||||
it("updates on a timer", function () {
|
||||
expect(mockWindow.requestAnimationFrame)
|
||||
.toHaveBeenCalledWith(jasmine.any(Function));
|
||||
});
|
||||
|
||||
it("displays nothing when there is no target", function () {
|
||||
// Notify that domain object is available via scope
|
||||
invokeWatch('domainObject', mockDomainObject);
|
||||
mockNow.andReturn(TEST_TIMESTAMP);
|
||||
mockWindow.requestAnimationFrame.mostRecentCall.args[0]();
|
||||
expect(controller.sign()).toEqual("");
|
||||
expect(controller.text()).toEqual("");
|
||||
});
|
||||
|
||||
it("formats time to display relative to target", function () {
|
||||
testModel.timestamp = TEST_TIMESTAMP;
|
||||
testModel.timerFormat = 'long';
|
||||
// Notify that domain object is available via scope
|
||||
invokeWatch('domainObject', mockDomainObject);
|
||||
|
||||
mockNow.andReturn(TEST_TIMESTAMP + 121000);
|
||||
mockWindow.requestAnimationFrame.mostRecentCall.args[0]();
|
||||
expect(controller.sign()).toEqual("+");
|
||||
expect(controller.text()).toEqual("0D 00:02:01");
|
||||
|
||||
mockNow.andReturn(TEST_TIMESTAMP - 121000);
|
||||
mockWindow.requestAnimationFrame.mostRecentCall.args[0]();
|
||||
expect(controller.sign()).toEqual("-");
|
||||
expect(controller.text()).toEqual("0D 00:02:01");
|
||||
|
||||
mockNow.andReturn(TEST_TIMESTAMP);
|
||||
mockWindow.requestAnimationFrame.mostRecentCall.args[0]();
|
||||
expect(controller.sign()).toEqual("");
|
||||
expect(controller.text()).toEqual("0D 00:00:00");
|
||||
});
|
||||
|
||||
it("shows glyph & name for the applicable start/restart action", function () {
|
||||
invokeWatch('domainObject', mockDomainObject);
|
||||
expect(controller.buttonGlyph()).toEqual("S");
|
||||
expect(controller.buttonText()).toEqual("Start");
|
||||
|
||||
testModel.timestamp = 12321;
|
||||
invokeWatch('model.modified', 1);
|
||||
expect(controller.buttonGlyph()).toEqual("R");
|
||||
expect(controller.buttonText()).toEqual("Restart");
|
||||
});
|
||||
|
||||
it("performs correct start/restart action on click", function () {
|
||||
invokeWatch('domainObject', mockDomainObject);
|
||||
expect(mockStart.perform).not.toHaveBeenCalled();
|
||||
controller.clickButton();
|
||||
expect(mockStart.perform).toHaveBeenCalled();
|
||||
|
||||
testModel.timestamp = 12321;
|
||||
invokeWatch('model.modified', 1);
|
||||
expect(mockRestart.perform).not.toHaveBeenCalled();
|
||||
controller.clickButton();
|
||||
expect(mockRestart.perform).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("stops requesting animation frames when destroyed", function () {
|
||||
var initialCount = mockWindow.requestAnimationFrame.calls.length;
|
||||
|
||||
// First, check that normally new frames keep getting requested
|
||||
mockWindow.requestAnimationFrame.mostRecentCall.args[0]();
|
||||
expect(mockWindow.requestAnimationFrame.calls.length)
|
||||
.toEqual(initialCount + 1);
|
||||
mockWindow.requestAnimationFrame.mostRecentCall.args[0]();
|
||||
expect(mockWindow.requestAnimationFrame.calls.length)
|
||||
.toEqual(initialCount + 2);
|
||||
|
||||
// Now, verify that it stops after $destroy
|
||||
expect(mockScope.$on.mostRecentCall.args[0])
|
||||
.toEqual('$destroy');
|
||||
mockScope.$on.mostRecentCall.args[1]();
|
||||
|
||||
// Frames should no longer get requested
|
||||
mockWindow.requestAnimationFrame.mostRecentCall.args[0]();
|
||||
expect(mockWindow.requestAnimationFrame.calls.length)
|
||||
.toEqual(initialCount + 2);
|
||||
mockWindow.requestAnimationFrame.mostRecentCall.args[0]();
|
||||
expect(mockWindow.requestAnimationFrame.calls.length)
|
||||
.toEqual(initialCount + 2);
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
@@ -0,0 +1,96 @@
|
||||
/*global define,describe,it,expect,beforeEach,waitsFor,jasmine,window,afterEach*/
|
||||
|
||||
define(
|
||||
["../../src/controllers/TimerFormatter"],
|
||||
function (TimerFormatter) {
|
||||
"use strict";
|
||||
|
||||
var MS_IN_SEC = 1000,
|
||||
MS_IN_MIN = MS_IN_SEC * 60,
|
||||
MS_IN_HR = MS_IN_MIN * 60,
|
||||
MS_IN_DAY = MS_IN_HR * 24;
|
||||
|
||||
describe("The timer value formatter", function () {
|
||||
var formatter = new TimerFormatter();
|
||||
|
||||
function sum(a, b) {
|
||||
return a + b;
|
||||
}
|
||||
|
||||
function toDuration(days, hours, mins, secs) {
|
||||
return [
|
||||
days * MS_IN_DAY,
|
||||
hours * MS_IN_HR,
|
||||
mins * MS_IN_MIN,
|
||||
secs * MS_IN_SEC
|
||||
].reduce(sum, 0);
|
||||
}
|
||||
|
||||
function twoDigits(n) {
|
||||
return n < 10 ? ('0' + n) : n;
|
||||
}
|
||||
|
||||
it("formats short-form values (no days)", function () {
|
||||
expect(formatter.short(toDuration(0, 123, 2, 3) + 123))
|
||||
.toEqual("123:02:03");
|
||||
});
|
||||
|
||||
it("formats negative short-form values (no days)", function () {
|
||||
expect(formatter.short(-toDuration(0, 123, 2, 3) + 123))
|
||||
.toEqual("123:02:03");
|
||||
});
|
||||
|
||||
it("formats long-form values (with days)", function () {
|
||||
expect(formatter.long(toDuration(0, 123, 2, 3) + 123))
|
||||
.toEqual("5D 03:02:03");
|
||||
});
|
||||
|
||||
it("formats negative long-form values (no days)", function () {
|
||||
expect(formatter.long(-toDuration(0, 123, 2, 3) + 123))
|
||||
.toEqual("5D 03:02:03");
|
||||
});
|
||||
|
||||
it("rounds seconds down for positive durations", function () {
|
||||
expect(formatter.short(MS_IN_SEC + 600))
|
||||
.toEqual("00:00:01");
|
||||
});
|
||||
|
||||
it("rounds seconds up for negative durations", function () {
|
||||
expect(formatter.short(-MS_IN_SEC - 600))
|
||||
.toEqual("00:00:02");
|
||||
});
|
||||
|
||||
it("short-formats correctly around negative time borders", function () {
|
||||
expect(formatter.short(-1)).toEqual("00:00:01");
|
||||
expect(formatter.short(-1000)).toEqual("00:00:01");
|
||||
expect(formatter.short(-1001)).toEqual("00:00:02");
|
||||
expect(formatter.short(-2000)).toEqual("00:00:02");
|
||||
expect(formatter.short(-59001)).toEqual("00:01:00");
|
||||
expect(formatter.short(-60000)).toEqual("00:01:00");
|
||||
|
||||
expect(formatter.short(-MS_IN_HR + 999)).toEqual("01:00:00");
|
||||
expect(formatter.short(-MS_IN_HR)).toEqual("01:00:00");
|
||||
});
|
||||
|
||||
it("differentiates between values around zero", function () {
|
||||
// These are more than 1000 ms apart so should not appear
|
||||
// as the same second
|
||||
expect(formatter.short(-999))
|
||||
.not.toEqual(formatter.short(999));
|
||||
});
|
||||
|
||||
it("handles negative days", function () {
|
||||
expect(formatter.long(-10 * MS_IN_DAY))
|
||||
.toEqual("10D 00:00:00");
|
||||
expect(formatter.long(-10 * MS_IN_DAY + 100))
|
||||
.toEqual("10D 00:00:00");
|
||||
expect(formatter.long(-10 * MS_IN_DAY + 999))
|
||||
.toEqual("10D 00:00:00");
|
||||
|
||||
expect(formatter.short(-10 * MS_IN_DAY + 100))
|
||||
.toEqual("240:00:00");
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
);
|
||||
@@ -0,0 +1,40 @@
|
||||
/*global define,describe,it,expect,beforeEach,waitsFor,jasmine,window,afterEach*/
|
||||
|
||||
define(
|
||||
["../../src/indicators/ClockIndicator"],
|
||||
function (ClockIndicator) {
|
||||
"use strict";
|
||||
|
||||
// Wed, 03 Jun 2015 17:56:14 GMT
|
||||
var TEST_TIMESTAMP = 1433354174000,
|
||||
TEST_FORMAT = "YYYY-DDD HH:mm:ss";
|
||||
|
||||
describe("The clock indicator", function () {
|
||||
var mockTicker,
|
||||
mockUnticker,
|
||||
indicator;
|
||||
|
||||
beforeEach(function () {
|
||||
mockTicker = jasmine.createSpyObj('ticker', ['listen']);
|
||||
mockUnticker = jasmine.createSpy('unticker');
|
||||
|
||||
mockTicker.listen.andReturn(mockUnticker);
|
||||
|
||||
indicator = new ClockIndicator(mockTicker, TEST_FORMAT);
|
||||
});
|
||||
|
||||
it("displays the current time", function () {
|
||||
mockTicker.listen.mostRecentCall.args[0](TEST_TIMESTAMP);
|
||||
expect(indicator.getText()).toEqual("2015-154 17:56:14 UTC");
|
||||
});
|
||||
|
||||
it("implements the Indicator interface", function () {
|
||||
expect(indicator.getGlyph()).toEqual(jasmine.any(String));
|
||||
expect(indicator.getGlyphClass()).toEqual(jasmine.any(String));
|
||||
expect(indicator.getText()).toEqual(jasmine.any(String));
|
||||
expect(indicator.getDescription()).toEqual(jasmine.any(String));
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
);
|
||||
43
platform/features/clock/test/services/TickerServiceSpec.js
Normal file
43
platform/features/clock/test/services/TickerServiceSpec.js
Normal file
@@ -0,0 +1,43 @@
|
||||
/*global define,describe,it,expect,beforeEach,waitsFor,jasmine,window,afterEach*/
|
||||
|
||||
define(
|
||||
["../../src/services/TickerService"],
|
||||
function (TickerService) {
|
||||
"use strict";
|
||||
|
||||
var TEST_TIMESTAMP = 1433354174000;
|
||||
|
||||
describe("The ticker service", function () {
|
||||
var mockTimeout,
|
||||
mockNow,
|
||||
mockCallback,
|
||||
tickerService;
|
||||
|
||||
beforeEach(function () {
|
||||
mockTimeout = jasmine.createSpy('$timeout');
|
||||
mockNow = jasmine.createSpy('now');
|
||||
mockCallback = jasmine.createSpy('callback');
|
||||
|
||||
mockNow.andReturn(TEST_TIMESTAMP);
|
||||
|
||||
tickerService = new TickerService(mockTimeout, mockNow);
|
||||
});
|
||||
|
||||
it("notifies listeners of clock ticks", function () {
|
||||
tickerService.listen(mockCallback);
|
||||
mockNow.andReturn(TEST_TIMESTAMP + 12321);
|
||||
mockTimeout.mostRecentCall.args[0]();
|
||||
expect(mockCallback)
|
||||
.toHaveBeenCalledWith(TEST_TIMESTAMP + 12321);
|
||||
});
|
||||
|
||||
it("allows listeners to unregister", function () {
|
||||
tickerService.listen(mockCallback)(); // Unregister immediately
|
||||
mockNow.andReturn(TEST_TIMESTAMP + 12321);
|
||||
mockTimeout.mostRecentCall.args[0]();
|
||||
expect(mockCallback).not
|
||||
.toHaveBeenCalledWith(TEST_TIMESTAMP + 12321);
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
11
platform/features/clock/test/suite.json
Normal file
11
platform/features/clock/test/suite.json
Normal file
@@ -0,0 +1,11 @@
|
||||
[
|
||||
"actions/AbstractStartTimerAction",
|
||||
"actions/RestartTimerAction",
|
||||
"actions/StartTimerAction",
|
||||
"controllers/ClockController",
|
||||
"controllers/RefreshingController",
|
||||
"controllers/TimerController",
|
||||
"controllers/TimerFormatter",
|
||||
"indicators/ClockIndicator",
|
||||
"services/TickerService"
|
||||
]
|
||||
Reference in New Issue
Block a user