diff --git a/lib/jasmine-core/jasmine.js b/lib/jasmine-core/jasmine.js index f0a41428..6e6d4d59 100644 --- a/lib/jasmine-core/jasmine.js +++ b/lib/jasmine-core/jasmine.js @@ -1056,6 +1056,9 @@ getJasmineRequireObj().Clock = function() { self.install = function() { + if(!originalTimingFunctionsIntact()) { + throw new Error('Jasmine Clock was unable to install over custom global timer functions. Is the clock already installed?'); + } replace(global, fakeTimingFunctions); timer = fakeTimingFunctions; delayedFunctionScheduler = delayedFunctionSchedulerFactory(); @@ -1125,6 +1128,13 @@ getJasmineRequireObj().Clock = function() { return self; + function originalTimingFunctionsIntact() { + return global.setTimeout === realTimingFunctions.setTimeout && + global.clearTimeout === realTimingFunctions.clearTimeout && + global.setInterval === realTimingFunctions.setInterval && + global.clearInterval === realTimingFunctions.clearInterval; + } + function legacyIE() { //if these methods are polyfilled, apply will be present return !(realTimingFunctions.setTimeout || realTimingFunctions.setInterval).apply; diff --git a/spec/core/ClockSpec.js b/spec/core/ClockSpec.js index cda0d448..7ed8264a 100644 --- a/spec/core/ClockSpec.js +++ b/spec/core/ClockSpec.js @@ -88,6 +88,78 @@ describe("Clock", function() { expect(fakeClearInterval).not.toHaveBeenCalled(); }); + it("does not install if the current setTimeout is not the original function on the global", function() { + var originalFakeSetTimeout = function() {}, + replacedSetTimeout = function() {}, + fakeGlobal = { setTimeout: originalFakeSetTimeout }, + delayedFunctionSchedulerFactory = jasmine.createSpy('delayedFunctionSchedulerFactory'), + mockDate = {}, + clock = new j$.Clock(fakeGlobal, delayedFunctionSchedulerFactory, mockDate); + + fakeGlobal.setTimeout = replacedSetTimeout; + + expect(function() { + clock.install(); + }).toThrowError(/unable to install/); + + expect(delayedFunctionSchedulerFactory).not.toHaveBeenCalled(); + expect(fakeGlobal.setTimeout).toBe(replacedSetTimeout); + }); + + it("does not install if the current clearTimeout is not the original function on the global", function() { + var originalFakeClearTimeout = function() {}, + replacedClearTimeout = function() {}, + fakeGlobal = { clearTimeout: originalFakeClearTimeout }, + delayedFunctionSchedulerFactory = jasmine.createSpy('delayedFunctionSchedulerFactory'), + mockDate = {}, + clock = new j$.Clock(fakeGlobal, delayedFunctionSchedulerFactory, mockDate); + + fakeGlobal.clearTimeout = replacedClearTimeout; + + expect(function() { + clock.install(); + }).toThrowError(/unable to install/); + + expect(delayedFunctionSchedulerFactory).not.toHaveBeenCalled(); + expect(fakeGlobal.clearTimeout).toBe(replacedClearTimeout); + }); + + it("does not install if the current setInterval is not the original function on the global", function() { + var originalFakeSetInterval = function() {}, + replacedSetInterval = function() {}, + fakeGlobal = { setInterval: originalFakeSetInterval }, + delayedFunctionSchedulerFactory = jasmine.createSpy('delayedFunctionSchedulerFactory'), + mockDate = {}, + clock = new j$.Clock(fakeGlobal, delayedFunctionSchedulerFactory, mockDate); + + fakeGlobal.setInterval = replacedSetInterval; + + expect(function() { + clock.install(); + }).toThrowError(/unable to install/); + + expect(delayedFunctionSchedulerFactory).not.toHaveBeenCalled(); + expect(fakeGlobal.setInterval).toBe(replacedSetInterval); + }); + + it("does not install if the current clearInterval is not the original function on the global", function() { + var originalFakeClearInterval = function() {}, + replacedClearInterval = function() {}, + fakeGlobal = { clearInterval: originalFakeClearInterval }, + delayedFunctionSchedulerFactory = jasmine.createSpy('delayedFunctionSchedulerFactory'), + mockDate = {}, + clock = new j$.Clock(fakeGlobal, delayedFunctionSchedulerFactory, mockDate); + + fakeGlobal.clearInterval = replacedClearInterval; + + expect(function() { + clock.install(); + }).toThrowError(/unable to install/); + + expect(delayedFunctionSchedulerFactory).not.toHaveBeenCalled(); + expect(fakeGlobal.clearInterval).toBe(replacedClearInterval); + }); + it("replaces the global timer functions on uninstall", function() { var fakeSetTimeout = jasmine.createSpy("global setTimeout"), fakeClearTimeout = jasmine.createSpy("global clearTimeout"), diff --git a/src/core/Clock.js b/src/core/Clock.js index e07e9217..474a4fb7 100644 --- a/src/core/Clock.js +++ b/src/core/Clock.js @@ -19,6 +19,9 @@ getJasmineRequireObj().Clock = function() { self.install = function() { + if(!originalTimingFunctionsIntact()) { + throw new Error('Jasmine Clock was unable to install over custom global timer functions. Is the clock already installed?'); + } replace(global, fakeTimingFunctions); timer = fakeTimingFunctions; delayedFunctionScheduler = delayedFunctionSchedulerFactory(); @@ -88,6 +91,13 @@ getJasmineRequireObj().Clock = function() { return self; + function originalTimingFunctionsIntact() { + return global.setTimeout === realTimingFunctions.setTimeout && + global.clearTimeout === realTimingFunctions.clearTimeout && + global.setInterval === realTimingFunctions.setInterval && + global.clearInterval === realTimingFunctions.clearInterval; + } + function legacyIE() { //if these methods are polyfilled, apply will be present return !(realTimingFunctions.setTimeout || realTimingFunctions.setInterval).apply;