diff --git a/spec/core/ClockSpec.js b/spec/core/ClockSpec.js index 0595ab05..e7f92811 100644 --- a/spec/core/ClockSpec.js +++ b/spec/core/ClockSpec.js @@ -5,7 +5,8 @@ describe("Clock", function() { fakeGlobal = { setTimeout: fakeSetTimeout }, delayedFunctionScheduler = jasmine.createSpyObj("delayedFunctionScheduler", ["scheduleFunction"]), delayedFn = jasmine.createSpy("delayedFn"), - clock = new j$.Clock(fakeGlobal, delayedFunctionScheduler); + mockDate = { install: function() {}, tick: function() {}, uninstall: function() {} }, + clock = new j$.Clock(fakeGlobal, delayedFunctionScheduler, mockDate); fakeGlobal.setTimeout(delayedFn, 0); @@ -26,7 +27,8 @@ describe("Clock", function() { fakeGlobal = { clearTimeout: fakeClearTimeout }, delayedFunctionScheduler = jasmine.createSpyObj("delayedFunctionScheduler", ["removeFunctionWithId"]), delayedFn = jasmine.createSpy("delayedFn"), - clock = new j$.Clock(fakeGlobal, delayedFunctionScheduler); + mockDate = { install: function() {}, tick: function() {}, uninstall: function() {} }, + clock = new j$.Clock(fakeGlobal, delayedFunctionScheduler, mockDate); fakeGlobal.clearTimeout("foo"); @@ -47,7 +49,8 @@ describe("Clock", function() { fakeGlobal = { setInterval: fakeSetInterval }, delayedFunctionScheduler = jasmine.createSpyObj("delayedFunctionScheduler", ["scheduleFunction"]), delayedFn = jasmine.createSpy("delayedFn"), - clock = new j$.Clock(fakeGlobal, delayedFunctionScheduler); + mockDate = { install: function() {}, tick: function() {}, uninstall: function() {} }, + clock = new j$.Clock(fakeGlobal, delayedFunctionScheduler, mockDate); fakeGlobal.setInterval(delayedFn, 0); @@ -68,7 +71,8 @@ describe("Clock", function() { fakeGlobal = { clearInterval: fakeClearInterval }, delayedFunctionScheduler = jasmine.createSpyObj("delayedFunctionScheduler", ["removeFunctionWithId"]), delayedFn = jasmine.createSpy("delayedFn"), - clock = new j$.Clock(fakeGlobal, delayedFunctionScheduler); + mockDate = { install: function() {}, tick: function() {}, uninstall: function() {} }, + clock = new j$.Clock(fakeGlobal, delayedFunctionScheduler, mockDate); fakeGlobal.clearInterval("foo"); @@ -97,7 +101,8 @@ describe("Clock", function() { }, delayedFunctionScheduler = jasmine.createSpyObj("delayedFunctionScheduler", ["scheduleFunction", "reset"]), delayedFn = jasmine.createSpy("delayedFn"), - clock = new j$.Clock(fakeGlobal, delayedFunctionScheduler); + mockDate = { install: function() {}, tick: function() {}, uninstall: function() {} }, + clock = new j$.Clock(fakeGlobal, delayedFunctionScheduler, mockDate); clock.install(); clock.uninstall(); @@ -119,7 +124,8 @@ describe("Clock", function() { delayedFunctionScheduler = { scheduleFunction: scheduleFunction }, fakeGlobal = { setTimeout: fakeSetTimeout }, delayedFn = jasmine.createSpy('delayedFn'), - clock = new j$.Clock(fakeGlobal, delayedFunctionScheduler); + mockDate = { install: function() {}, tick: function() {}, uninstall: function() {} }, + clock = new j$.Clock(fakeGlobal, delayedFunctionScheduler, mockDate); clock.install(); clock.setTimeout(delayedFn, 0, 'a', 'b'); @@ -135,7 +141,8 @@ describe("Clock", function() { delayedFunctionScheduler = {scheduleFunction: scheduleFunction}, fakeGlobal = { setTimeout: fakeSetTimeout }, delayedFn = jasmine.createSpy('delayedFn'), - clock = new j$.Clock(fakeGlobal, delayedFunctionScheduler), + mockDate = { install: function() {}, tick: function() {}, uninstall: function() {} }, + clock = new j$.Clock(fakeGlobal, delayedFunctionScheduler, mockDate), timeoutId; clock.install(); @@ -149,7 +156,8 @@ describe("Clock", function() { delayedFunctionScheduler = jasmine.createSpyObj('delayedFunctionScheduler', ['removeFunctionWithId']), fakeGlobal = { setTimeout: fakeClearTimeout }, delayedFn = jasmine.createSpy('delayedFn'), - clock = new j$.Clock(fakeGlobal, delayedFunctionScheduler); + mockDate = { install: function() {}, tick: function() {}, uninstall: function() {} }, + clock = new j$.Clock(fakeGlobal, delayedFunctionScheduler, mockDate); clock.install(); clock.clearTimeout(123); @@ -164,7 +172,8 @@ describe("Clock", function() { delayedFunctionScheduler = {scheduleFunction: scheduleFunction}, fakeGlobal = { setInterval: fakeSetInterval }, delayedFn = jasmine.createSpy('delayedFn'), - clock = new j$.Clock(fakeGlobal, delayedFunctionScheduler); + mockDate = { install: function() {}, tick: function() {}, uninstall: function() {} }, + clock = new j$.Clock(fakeGlobal, delayedFunctionScheduler, mockDate); clock.install(); clock.setInterval(delayedFn, 0, 'a', 'b'); @@ -180,7 +189,8 @@ describe("Clock", function() { delayedFunctionScheduler = {scheduleFunction: scheduleFunction}, fakeGlobal = { setInterval: fakeSetInterval }, delayedFn = jasmine.createSpy('delayedFn'), - clock = new j$.Clock(fakeGlobal, delayedFunctionScheduler), + mockDate = { install: function() {}, tick: function() {}, uninstall: function() {} }, + clock = new j$.Clock(fakeGlobal, delayedFunctionScheduler, mockDate), intervalId; clock.install(); @@ -194,7 +204,8 @@ describe("Clock", function() { delayedFunctionScheduler = jasmine.createSpyObj('delayedFunctionScheduler', ['removeFunctionWithId']), fakeGlobal = { setInterval: clearInterval }, delayedFn = jasmine.createSpy('delayedFn'), - clock = new j$.Clock(fakeGlobal, delayedFunctionScheduler); + mockDate = { install: function() {}, tick: function() {}, uninstall: function() {} }, + clock = new j$.Clock(fakeGlobal, delayedFunctionScheduler, mockDate); clock.install(); clock.clearInterval(123); @@ -220,7 +231,8 @@ describe("Clock", function() { setTimeout: fakeSetTimeout, setInterval: fakeSetInterval }, - clock = new j$.Clock(fakeGlobal, delayedFunctionScheduler); + mockDate = { install: function() {}, tick: function() {}, uninstall: function() {} }, + clock = new j$.Clock(fakeGlobal, delayedFunctionScheduler, mockDate); fakeSetTimeout.apply = null; fakeSetInterval.apply = null; @@ -249,7 +261,8 @@ describe("Clock (acceptance)", function() { delayedFn3 = jasmine.createSpy('delayedFn3'), recurring1 = jasmine.createSpy('recurring1'), delayedFunctionScheduler = new j$.DelayedFunctionScheduler(), - clock = new j$.Clock({setTimeout: setTimeout}, delayedFunctionScheduler); + mockDate = { install: function() {}, tick: function() {}, uninstall: function() {} }, + clock = new j$.Clock({setTimeout: setTimeout}, delayedFunctionScheduler, mockDate); clock.install(); @@ -295,7 +308,8 @@ describe("Clock (acceptance)", function() { it("can clear a previously set timeout", function() { var clearedFn = jasmine.createSpy('clearedFn'), delayedFunctionScheduler = new j$.DelayedFunctionScheduler(), - clock = new j$.Clock({setTimeout: function() {}}, delayedFunctionScheduler), + mockDate = { install: function() {}, tick: function() {}, uninstall: function() {} }, + clock = new j$.Clock({setTimeout: function() {}}, delayedFunctionScheduler, mockDate), timeoutId; clock.install(); @@ -312,7 +326,8 @@ describe("Clock (acceptance)", function() { it("correctly schedules functions after the Clock has advanced", function() { var delayedFn1 = jasmine.createSpy('delayedFn1'), delayedFunctionScheduler = new j$.DelayedFunctionScheduler(), - clock = new j$.Clock({setTimeout: function() {}}, delayedFunctionScheduler); + mockDate = { install: function() {}, tick: function() {}, uninstall: function() {} }, + clock = new j$.Clock({setTimeout: function() {}}, delayedFunctionScheduler, mockDate); clock.install(); @@ -328,7 +343,8 @@ describe("Clock (acceptance)", function() { var delayedFn1 = jasmine.createSpy('delayedFn1'), delayedFn2 = jasmine.createSpy('delayedFn2'), delayedFunctionScheduler = new j$.DelayedFunctionScheduler(), - clock = new j$.Clock({setTimeout: function() {}}, delayedFunctionScheduler); + mockDate = { install: function() {}, tick: function() {}, uninstall: function() {} }, + clock = new j$.Clock({setTimeout: function() {}}, delayedFunctionScheduler, mockDate); delayedFn1.and.callFake(function() { clock.setTimeout(delayedFn2, 0); }); clock.install(); @@ -346,7 +362,8 @@ describe("Clock (acceptance)", function() { var delayedFn1 = jasmine.createSpy('delayedFn1'), delayedFn2 = jasmine.createSpy('delayedFn2'), delayedFunctionScheduler = new j$.DelayedFunctionScheduler(), - clock = new j$.Clock({setTimeout: function() {}}, delayedFunctionScheduler); + mockDate = { install: function() {}, tick: function() {}, uninstall: function() {} }, + clock = new j$.Clock({setTimeout: function() {}}, delayedFunctionScheduler, mockDate); delayedFn1.and.callFake(function() { clock.setTimeout(delayedFn2, 1); }); clock.install(); @@ -357,7 +374,7 @@ describe("Clock (acceptance)", function() { expect(delayedFn2).toHaveBeenCalled(); }); - it("does not mock the Date object when installing without parameters", function() { + it("does not mock the Date object by default", function() { var delayedFunctionScheduler = new j$.DelayedFunctionScheduler(), global = {Date: Date}, mockDate = new j$.MockDate(global), @@ -367,30 +384,30 @@ describe("Clock (acceptance)", function() { expect(global.Date).toEqual(Date); - var now = global.Date.now(); + var now = new global.Date().getTime(); clock.tick(50); - expect(global.Date.now() - now).not.toEqual(50); + expect(new global.Date().getTime() - now).not.toEqual(50); }); - it("mocks the Date object and sets it to current time when installing with true parameter", function() { + it("mocks the Date object and sets it to current time", function() { var delayedFunctionScheduler = new j$.DelayedFunctionScheduler(), global = {Date: Date}, mockDate = new j$.MockDate(global), clock = new j$.Clock({setTimeout: setTimeout}, delayedFunctionScheduler, mockDate); - clock.install(true); + clock.install().mockDate(); - var now = global.Date.now(); + var now = new global.Date().getTime(); clock.tick(50); - expect(global.Date.now() - now).toEqual(50); + expect(new global.Date().getTime() - now).toEqual(50); var timeoutDate = 0; clock.setTimeout(function() { - timeoutDate = global.Date.now(); + timeoutDate = new global.Date().getTime(); }, 100); clock.tick(100); @@ -398,7 +415,7 @@ describe("Clock (acceptance)", function() { expect(timeoutDate - now).toEqual(150); }); - it("mocks the Date object and sets it to a given time when installing with a Date parameter", function() { + it("mocks the Date object and sets it to a given time", function() { var delayedFunctionScheduler = new j$.DelayedFunctionScheduler(), global = {Date: Date}, mockDate = new j$.MockDate(global), @@ -406,19 +423,19 @@ describe("Clock (acceptance)", function() { baseTime = new Date(2013, 9, 23); - clock.install(baseTime); + clock.install().mockDate(baseTime); - var now = global.Date.now(); + var now = new global.Date().getTime(); expect(now).toEqual(baseTime.getTime()); clock.tick(50); - expect(global.Date.now()).toEqual(baseTime.getTime() + 50); + expect(new global.Date().getTime()).toEqual(baseTime.getTime() + 50); var timeoutDate = 0; clock.setTimeout(function() { - timeoutDate = global.Date.now(); + timeoutDate = new global.Date().getTime(); }, 100); clock.tick(100); diff --git a/spec/core/MockDateSpec.js b/spec/core/MockDateSpec.js index 05bf86f9..72aa357b 100644 --- a/spec/core/MockDateSpec.js +++ b/spec/core/MockDateSpec.js @@ -3,84 +3,126 @@ describe("FakeDate", function() { var fakeGlobal = {}, mockDate = new j$.MockDate(fakeGlobal); - mockDate.install(); - - fakeGlobal.Date = jasmine.createSpy("Date"); - - mockDate.tick(0); - - expect(fakeGlobal.Date).not.toHaveBeenCalled(); + expect(function() { + mockDate.install(); + mockDate.tick(0); + mockDate.uninstall(); + }).not.toThrow(); }); - it("does not replace global Date if it is not installed", function() { - var fakeDate = jasmine.createSpy("global Date"), - fakeGlobal = { Date: fakeDate }, + it("replaces the global Date when it is installed", function() { + var globalDate = jasmine.createSpy("global Date").and.callFake(function() { + return { + getTime: function() {} + } + }), + fakeGlobal = { Date: globalDate }, mockDate = new j$.MockDate(fakeGlobal); - fakeDate.now = function(){}; - - expect(fakeDate).toEqual(fakeGlobal.Date); + expect(fakeGlobal.Date).toEqual(globalDate); mockDate.install(); - expect(fakeDate).not.toEqual(fakeGlobal.Date); + expect(fakeGlobal.Date).not.toEqual(globalDate); }); it("replaces the global Date on uninstall", function() { - var fakeDate = jasmine.createSpy("global Date"), - fakeGlobal = { Date: fakeDate }, + var globalDate = jasmine.createSpy("global Date").and.callFake(function() { + return { + getTime: function() {} + } + }), + fakeGlobal = { Date: globalDate }, mockDate = new j$.MockDate(fakeGlobal); - fakeDate.now = function(){}; - mockDate.install(); mockDate.uninstall(); - expect(fakeDate).toEqual(fakeGlobal.Date); - + expect(fakeGlobal.Date).toEqual(globalDate); }); it("takes the current time as the base when installing without parameters", function() { - var fakeDate = jasmine.createSpy("global Date"), - fakeGlobal = { Date: fakeDate }, + var globalDate = jasmine.createSpy("global Date").and.callFake(function() { + return { + getTime: function() { + return 1000; + } + } + }), + fakeGlobal = { Date: globalDate }, mockDate = new j$.MockDate(fakeGlobal); - fakeGlobal.Date.prototype.getTime = function() { - return 1000; - }; - fakeDate.now = function(){ return 1000; }; - mockDate.install(); - expect(new fakeGlobal.Date().getTime()).toEqual(1000); + globalDate.calls.reset(); + new fakeGlobal.Date(); + expect(globalDate).toHaveBeenCalledWith(1000); }); it("can accept a date as time base when installing", function() { var fakeGlobal = { Date: Date }, mockDate = new j$.MockDate(fakeGlobal), - baseDate = new Date(2013, 9, 23); + baseDate = new Date(); + spyOn(baseDate, 'getTime').and.returnValue(123); mockDate.install(baseDate); - expect(new fakeGlobal.Date().getTime()).toEqual(baseDate.getTime()); + expect(new fakeGlobal.Date().getTime()).toEqual(123); }); + it("makes real dates", function() { + var fakeGlobal = { Date: Date }, + mockDate = new j$.MockDate(fakeGlobal); + + mockDate.install(); + expect(new fakeGlobal.Date()).toEqual(jasmine.any(Date)); + }); it("fakes current time when using Date.now()", function() { - var fakeGlobal = { Date: Date }, - mockDate = new j$.MockDate(fakeGlobal), - baseDate = new Date(2013, 9, 23); + var globalDate = jasmine.createSpy("global Date").and.callFake(function() { + return { + getTime: function() { + return 1000; + } + } + }), + fakeGlobal = { Date: globalDate }; - mockDate.install(baseDate); + globalDate.now = function() {}; + var mockDate = new j$.MockDate(fakeGlobal); - expect(fakeGlobal.Date.now()).toEqual(baseDate.getTime()); + mockDate.install(); + + expect(fakeGlobal.Date.now()).toEqual(1000); + }); + + it("does not stub Date.now() if it doesn't already exist", function() { + var globalDate = jasmine.createSpy("global Date").and.callFake(function() { + return { + getTime: function() { + return 1000; + } + } + }), + fakeGlobal = { Date: globalDate }, + mockDate = new j$.MockDate(fakeGlobal); + + mockDate.install(); + + expect(fakeGlobal.Date.now).toThrowError("Browser does not support Date.now()"); }); it("makes time passes using tick", function() { - var fakeDate = jasmine.createSpy("global Date"), - fakeGlobal = { Date: fakeDate }, - mockDate = new j$.MockDate(fakeGlobal); + var globalDate = jasmine.createSpy("global Date").and.callFake(function() { + return { + getTime: function() { + return 1000; + } + } + }), + fakeGlobal = { Date: globalDate }; - fakeDate.now = function(){ return 1000; }; + globalDate.now = function() {}; + var mockDate = new j$.MockDate(fakeGlobal); mockDate.install(); @@ -94,11 +136,17 @@ describe("FakeDate", function() { }); it("allows to increase 0 milliseconds using tick", function() { - var fakeDate = jasmine.createSpy("global Date"), - fakeGlobal = { Date: fakeDate }, - mockDate = new j$.MockDate(fakeGlobal); + var globalDate = jasmine.createSpy("global Date").and.callFake(function() { + return { + getTime: function() { + return 1000; + } + } + }), + fakeGlobal = { Date: globalDate }; - fakeDate.now = function(){ return 1000; }; + globalDate.now = function() {}; + var mockDate = new j$.MockDate(fakeGlobal); mockDate.install(); @@ -109,7 +157,7 @@ describe("FakeDate", function() { expect(fakeGlobal.Date.now()).toEqual(1000); }); - it("allows to create a Date in a different time than now", function() { + it("allows to create a Date in a different time than the mocked time", function() { var fakeGlobal = { Date: Date }, mockDate = new j$.MockDate(fakeGlobal), baseDate = new Date(2013, 9, 23, 0, 0, 0, 0); @@ -117,22 +165,14 @@ describe("FakeDate", function() { mockDate.install(baseDate); var otherDate = new fakeGlobal.Date(2013, 9, 23, 0, 0, 1, 0); - - mockDate.tick(1000); - - expect(fakeGlobal.Date.now()).toEqual(otherDate.getTime()); + expect(otherDate.getTime()).not.toEqual(baseDate.getTime()); }); it("copies all Date properties to the mocked date", function() { var fakeGlobal = { Date: Date }, - mockDate = new j$.MockDate(fakeGlobal), - baseDate = new Date(2013, 9, 23, 0, 0, 0, 0); + mockDate = new j$.MockDate(fakeGlobal); - mockDate.install(baseDate); - - var otherDate = new fakeGlobal.Date(); - - expect(otherDate).toEqual(jasmine.any(Date)); + mockDate.install(); expect(fakeGlobal.Date.UTC(2013, 9, 23)).toEqual(Date.UTC(2013, 9, 23)); }); diff --git a/src/core/Clock.js b/src/core/Clock.js index c05f2a97..1ca84708 100644 --- a/src/core/Clock.js +++ b/src/core/Clock.js @@ -1,5 +1,5 @@ getJasmineRequireObj().Clock = function() { - function Clock(global, delayedFunctionScheduler, date) { + function Clock(global, delayedFunctionScheduler, mockDate) { var self = this, realTimingFunctions = { setTimeout: global.setTimeout, @@ -17,27 +17,27 @@ getJasmineRequireObj().Clock = function() { timer; - self.install = function(mockDate) { + self.install = function() { replace(global, fakeTimingFunctions); timer = fakeTimingFunctions; installed = true; - if (date && mockDate) { - date.install(mockDate); - } + return self; }; self.uninstall = function() { delayedFunctionScheduler.reset(); - if (date) { - date.uninstall(); - } + mockDate.uninstall(); replace(global, realTimingFunctions); timer = realTimingFunctions; installed = false; }; + self.mockDate = function(initialDate) { + mockDate.install(initialDate); + }; + self.setTimeout = function(fn, delay, params) { if (legacyIE()) { if (arguments.length > 2) { @@ -68,9 +68,7 @@ getJasmineRequireObj().Clock = function() { self.tick = function(millis) { if (installed) { - if (date) { - date.tick(millis); - } + mockDate.tick(millis); delayedFunctionScheduler.tick(millis); } else { throw new Error('Mock clock is not installed, use jasmine.clock().install()'); diff --git a/src/core/MockDate.js b/src/core/MockDate.js index 294579bb..bab3b751 100644 --- a/src/core/MockDate.js +++ b/src/core/MockDate.js @@ -13,10 +13,10 @@ getJasmineRequireObj().MockDate = function() { var GlobalDate = global.Date; self.install = function(mockDate) { - if (mockDate instanceof Date) { + if (mockDate instanceof GlobalDate) { currentTime = mockDate.getTime(); } else { - currentTime = GlobalDate.now(); + currentTime = new GlobalDate().getTime(); } global.Date = FakeDate; @@ -48,7 +48,11 @@ getJasmineRequireObj().MockDate = function() { function createDateProperties() { FakeDate.now = function() { - return currentTime; + if (GlobalDate.now) { + return currentTime; + } else { + throw new Error("Browser does not support Date.now()"); + } }; FakeDate.toSource = GlobalDate.toSource;