Re-add Mock Clock behavior as global 'clock'
- Use clock.install, clock.tick... - Add unit coverage. - Fixes old bug in function scheduler
This commit is contained in:
@@ -38,6 +38,9 @@
|
|||||||
return env.spyOn(obj, methodName);
|
return env.spyOn(obj, methodName);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
clock: function() {
|
||||||
|
return env.clock;
|
||||||
|
},
|
||||||
|
|
||||||
jsApiReporter: new jasmine.JsApiReporter(jasmine)
|
jsApiReporter: new jasmine.JsApiReporter(jasmine)
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -108,8 +108,8 @@ jasmine.MessageResult.prototype.toString = function() {
|
|||||||
/**
|
/**
|
||||||
* Getter for the Jasmine environment. Ensures one gets created
|
* Getter for the Jasmine environment. Ensures one gets created
|
||||||
*/
|
*/
|
||||||
jasmine.getEnv = function() {
|
jasmine.getEnv = function(options) {
|
||||||
var env = jasmine.currentEnv_ = jasmine.currentEnv_ || new jasmine.Env();
|
var env = jasmine.currentEnv_ = jasmine.currentEnv_ || new jasmine.Env(options);
|
||||||
//jasmine. singletons in here (setTimeout blah blah).
|
//jasmine. singletons in here (setTimeout blah blah).
|
||||||
return env;
|
return env;
|
||||||
};
|
};
|
||||||
@@ -519,12 +519,17 @@ jasmine.buildExpectationResult = function(params) {
|
|||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
(function() {
|
(function() {
|
||||||
jasmine.Env = function() {
|
jasmine.Env = function(options) {
|
||||||
|
options = options || {};
|
||||||
var self = this;
|
var self = this;
|
||||||
|
var global = options.global || jasmine.getGlobal();
|
||||||
|
|
||||||
|
this.clock = new jasmine.Clock(global, new jasmine.DelayedFunctionScheduler());
|
||||||
|
|
||||||
var suiteConstructor = jasmine.Suite;
|
var suiteConstructor = jasmine.Suite;
|
||||||
var isSuite = function(thing) {
|
var isSuite = function(thing) {
|
||||||
return thing instanceof suiteConstructor;
|
return thing instanceof suiteConstructor;
|
||||||
}
|
};
|
||||||
this.jasmine = jasmine;
|
this.jasmine = jasmine;
|
||||||
this.currentRunner_ = new jasmine.Runner(this, isSuite);
|
this.currentRunner_ = new jasmine.Runner(this, isSuite);
|
||||||
this.spies_ = [];
|
this.spies_ = [];
|
||||||
@@ -610,8 +615,7 @@ jasmine.buildExpectationResult = function(params) {
|
|||||||
afterFns: afterFns(suite),
|
afterFns: afterFns(suite),
|
||||||
expectationFactory: expectationFactory,
|
expectationFactory: expectationFactory,
|
||||||
exceptionFormatter: exceptionFormatter,
|
exceptionFormatter: exceptionFormatter,
|
||||||
//TODO: move spec creation to more appropriate level and remove this shim
|
resultCallback: specResultCallback,
|
||||||
resultCallback: function(result) { self.currentSpec = null; suite.specComplete(result); },
|
|
||||||
fullNameFactory: function(spec) { return fullNameFactory(spec, suite) },
|
fullNameFactory: function(spec) { return fullNameFactory(spec, suite) },
|
||||||
startCallback: startCallback,
|
startCallback: startCallback,
|
||||||
description: description,
|
description: description,
|
||||||
@@ -625,8 +629,13 @@ jasmine.buildExpectationResult = function(params) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return spec;
|
return spec;
|
||||||
};
|
|
||||||
|
|
||||||
|
function specResultCallback(result) {
|
||||||
|
self.clock.uninstall();
|
||||||
|
self.currentSpec = null;
|
||||||
|
suite.specComplete(result);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
var queueConstructor = jasmine.Queue;
|
var queueConstructor = jasmine.Queue;
|
||||||
var queueFactory = function() {
|
var queueFactory = function() {
|
||||||
@@ -638,12 +647,6 @@ jasmine.buildExpectationResult = function(params) {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
jasmine.Env.prototype.setTimeout = jasmine.setTimeout;
|
|
||||||
jasmine.Env.prototype.clearTimeout = jasmine.clearTimeout;
|
|
||||||
jasmine.Env.prototype.setInterval = jasmine.setInterval;
|
|
||||||
jasmine.Env.prototype.clearInterval = jasmine.clearInterval;
|
|
||||||
|
|
||||||
//TODO: shim Spec addMatchers behavior into Env. Should be rewritten to remove globals, etc.
|
//TODO: shim Spec addMatchers behavior into Env. Should be rewritten to remove globals, etc.
|
||||||
jasmine.Env.prototype.addMatchers = function(matchersPrototype) {
|
jasmine.Env.prototype.addMatchers = function(matchersPrototype) {
|
||||||
var parent = this.matchersClass;
|
var parent = this.matchersClass;
|
||||||
@@ -1480,190 +1483,6 @@ jasmine.Matchers.ObjectContaining.prototype.jasmineMatches = function(other, mis
|
|||||||
jasmine.Matchers.ObjectContaining.prototype.jasmineToString = function () {
|
jasmine.Matchers.ObjectContaining.prototype.jasmineToString = function () {
|
||||||
return "<jasmine.objectContaining(" + jasmine.pp(this.sample) + ")>";
|
return "<jasmine.objectContaining(" + jasmine.pp(this.sample) + ")>";
|
||||||
};
|
};
|
||||||
// Mock setTimeout, clearTimeout
|
|
||||||
// Contributed by Pivotal Computer Systems, www.pivotalsf.com
|
|
||||||
|
|
||||||
jasmine.FakeTimer = function() {
|
|
||||||
this.reset();
|
|
||||||
|
|
||||||
var self = this;
|
|
||||||
self.setTimeout = function(funcToCall, millis) {
|
|
||||||
self.timeoutsMade++;
|
|
||||||
self.scheduleFunction(self.timeoutsMade, funcToCall, millis, false);
|
|
||||||
return self.timeoutsMade;
|
|
||||||
};
|
|
||||||
|
|
||||||
self.setInterval = function(funcToCall, millis) {
|
|
||||||
self.timeoutsMade++;
|
|
||||||
self.scheduleFunction(self.timeoutsMade, funcToCall, millis, true);
|
|
||||||
return self.timeoutsMade;
|
|
||||||
};
|
|
||||||
|
|
||||||
self.clearTimeout = function(timeoutKey) {
|
|
||||||
self.scheduledFunctions[timeoutKey] = jasmine.undefined;
|
|
||||||
};
|
|
||||||
|
|
||||||
self.clearInterval = function(timeoutKey) {
|
|
||||||
self.scheduledFunctions[timeoutKey] = jasmine.undefined;
|
|
||||||
};
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.FakeTimer.prototype.reset = function() {
|
|
||||||
this.timeoutsMade = 0;
|
|
||||||
this.scheduledFunctions = {};
|
|
||||||
this.nowMillis = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.FakeTimer.prototype.tick = function(millis) {
|
|
||||||
var oldMillis = this.nowMillis;
|
|
||||||
var newMillis = oldMillis + millis;
|
|
||||||
this.runFunctionsWithinRange(oldMillis, newMillis);
|
|
||||||
this.nowMillis = newMillis;
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.FakeTimer.prototype.runFunctionsWithinRange = function(oldMillis, nowMillis) {
|
|
||||||
var scheduledFunc;
|
|
||||||
var funcsToRun = [];
|
|
||||||
for (var timeoutKey in this.scheduledFunctions) {
|
|
||||||
scheduledFunc = this.scheduledFunctions[timeoutKey];
|
|
||||||
if (scheduledFunc != jasmine.undefined &&
|
|
||||||
scheduledFunc.runAtMillis >= oldMillis &&
|
|
||||||
scheduledFunc.runAtMillis <= nowMillis) {
|
|
||||||
funcsToRun.push(scheduledFunc);
|
|
||||||
this.scheduledFunctions[timeoutKey] = jasmine.undefined;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (funcsToRun.length > 0) {
|
|
||||||
funcsToRun.sort(function(a, b) {
|
|
||||||
return a.runAtMillis - b.runAtMillis;
|
|
||||||
});
|
|
||||||
for (var i = 0; i < funcsToRun.length; ++i) {
|
|
||||||
try {
|
|
||||||
var funcToRun = funcsToRun[i];
|
|
||||||
this.nowMillis = funcToRun.runAtMillis;
|
|
||||||
funcToRun.funcToCall();
|
|
||||||
if (funcToRun.recurring) {
|
|
||||||
this.scheduleFunction(funcToRun.timeoutKey,
|
|
||||||
funcToRun.funcToCall,
|
|
||||||
funcToRun.millis,
|
|
||||||
true);
|
|
||||||
}
|
|
||||||
} catch(e) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.runFunctionsWithinRange(oldMillis, nowMillis);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.FakeTimer.prototype.scheduleFunction = function(timeoutKey, funcToCall, millis, recurring) {
|
|
||||||
this.scheduledFunctions[timeoutKey] = {
|
|
||||||
runAtMillis: this.nowMillis + millis,
|
|
||||||
funcToCall: funcToCall,
|
|
||||||
recurring: recurring,
|
|
||||||
timeoutKey: timeoutKey,
|
|
||||||
millis: millis
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @namespace
|
|
||||||
*/
|
|
||||||
jasmine.Clock = {
|
|
||||||
defaultFakeTimer: new jasmine.FakeTimer(),
|
|
||||||
|
|
||||||
reset: function() {
|
|
||||||
jasmine.Clock.assertInstalled();
|
|
||||||
jasmine.Clock.defaultFakeTimer.reset();
|
|
||||||
},
|
|
||||||
|
|
||||||
tick: function(millis) {
|
|
||||||
jasmine.Clock.assertInstalled();
|
|
||||||
jasmine.Clock.defaultFakeTimer.tick(millis);
|
|
||||||
},
|
|
||||||
|
|
||||||
runFunctionsWithinRange: function(oldMillis, nowMillis) {
|
|
||||||
jasmine.Clock.defaultFakeTimer.runFunctionsWithinRange(oldMillis, nowMillis);
|
|
||||||
},
|
|
||||||
|
|
||||||
scheduleFunction: function(timeoutKey, funcToCall, millis, recurring) {
|
|
||||||
jasmine.Clock.defaultFakeTimer.scheduleFunction(timeoutKey, funcToCall, millis, recurring);
|
|
||||||
},
|
|
||||||
|
|
||||||
useMock: function() {
|
|
||||||
if (!jasmine.Clock.isInstalled()) {
|
|
||||||
//TODO: this is using an interface that doesn't exist.
|
|
||||||
var spec = jasmine.getEnv().currentSpec;
|
|
||||||
spec.after(jasmine.Clock.uninstallMock);
|
|
||||||
|
|
||||||
jasmine.Clock.installMock();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
installMock: function() {
|
|
||||||
jasmine.Clock.installed = jasmine.Clock.defaultFakeTimer;
|
|
||||||
},
|
|
||||||
|
|
||||||
uninstallMock: function() {
|
|
||||||
jasmine.Clock.assertInstalled();
|
|
||||||
jasmine.Clock.installed = jasmine.Clock.real;
|
|
||||||
},
|
|
||||||
|
|
||||||
real: {
|
|
||||||
setTimeout: jasmine.getGlobal().setTimeout,
|
|
||||||
clearTimeout: jasmine.getGlobal().clearTimeout,
|
|
||||||
setInterval: jasmine.getGlobal().setInterval,
|
|
||||||
clearInterval: jasmine.getGlobal().clearInterval
|
|
||||||
},
|
|
||||||
|
|
||||||
assertInstalled: function() {
|
|
||||||
if (!jasmine.Clock.isInstalled()) {
|
|
||||||
throw new Error("Mock clock is not installed, use jasmine.Clock.useMock()");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
isInstalled: function() {
|
|
||||||
return jasmine.Clock.installed == jasmine.Clock.defaultFakeTimer;
|
|
||||||
},
|
|
||||||
|
|
||||||
installed: null
|
|
||||||
};
|
|
||||||
jasmine.Clock.installed = jasmine.Clock.real;
|
|
||||||
|
|
||||||
//else for IE support
|
|
||||||
jasmine.getGlobal().setTimeout = function(funcToCall, millis) {
|
|
||||||
if (jasmine.Clock.installed.setTimeout.apply) {
|
|
||||||
return jasmine.Clock.installed.setTimeout.apply(this, arguments);
|
|
||||||
} else {
|
|
||||||
return jasmine.Clock.installed.setTimeout(funcToCall, millis);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.getGlobal().setInterval = function(funcToCall, millis) {
|
|
||||||
if (jasmine.Clock.installed.setInterval.apply) {
|
|
||||||
return jasmine.Clock.installed.setInterval.apply(this, arguments);
|
|
||||||
} else {
|
|
||||||
return jasmine.Clock.installed.setInterval(funcToCall, millis);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.getGlobal().clearTimeout = function(timeoutKey) {
|
|
||||||
if (jasmine.Clock.installed.clearTimeout.apply) {
|
|
||||||
return jasmine.Clock.installed.clearTimeout.apply(this, arguments);
|
|
||||||
} else {
|
|
||||||
return jasmine.Clock.installed.clearTimeout(timeoutKey);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.getGlobal().clearInterval = function(timeoutKey) {
|
|
||||||
if (jasmine.Clock.installed.clearTimeout.apply) {
|
|
||||||
return jasmine.Clock.installed.clearInterval.apply(this, arguments);
|
|
||||||
} else {
|
|
||||||
return jasmine.Clock.installed.clearInterval(timeoutKey);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
@@ -2288,6 +2107,201 @@ jasmine.Suite.prototype.execute = function(onComplete) {
|
|||||||
self.finish(onComplete);
|
self.finish(onComplete);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
jasmine.Clock = function(global, delayedFunctionScheduler) {
|
||||||
|
var self = this,
|
||||||
|
realTimingFunctions = {
|
||||||
|
setTimeout: global.setTimeout,
|
||||||
|
clearTimeout: global.clearTimeout,
|
||||||
|
setInterval: global.setInterval,
|
||||||
|
clearInterval: global.clearInterval
|
||||||
|
},
|
||||||
|
fakeTimingFunctions = {
|
||||||
|
setTimeout: setTimeout,
|
||||||
|
clearTimeout: clearTimeout,
|
||||||
|
setInterval: setInterval,
|
||||||
|
clearInterval: clearInterval
|
||||||
|
},
|
||||||
|
timer = realTimingFunctions,
|
||||||
|
installed = false;
|
||||||
|
|
||||||
|
self.install = function() {
|
||||||
|
installed = true;
|
||||||
|
timer = fakeTimingFunctions;
|
||||||
|
};
|
||||||
|
|
||||||
|
self.uninstall = function() {
|
||||||
|
delayedFunctionScheduler.reset();
|
||||||
|
installed = false;
|
||||||
|
timer = realTimingFunctions;
|
||||||
|
};
|
||||||
|
|
||||||
|
self.setTimeout = function(fn, delay, params) {
|
||||||
|
if (legacyIE()) {
|
||||||
|
if (arguments.length > 2) {
|
||||||
|
throw new Error("IE < 9 cannot support extra params to setTimeout without a polyfill");
|
||||||
|
}
|
||||||
|
return timer.setTimeout(fn, delay);
|
||||||
|
}
|
||||||
|
return timer.setTimeout.apply(null, arguments);
|
||||||
|
};
|
||||||
|
|
||||||
|
self.setInterval = function(fn, delay, params) {
|
||||||
|
if (legacyIE()) {
|
||||||
|
if (arguments.length > 2) {
|
||||||
|
throw new Error("IE < 9 cannot support extra params to setInterval without a polyfill");
|
||||||
|
}
|
||||||
|
return timer.setInterval(fn, delay);
|
||||||
|
}
|
||||||
|
return timer.setInterval.apply(null, arguments);
|
||||||
|
};
|
||||||
|
|
||||||
|
self.clearTimeout = function(id) {
|
||||||
|
return timer.clearTimeout(id);
|
||||||
|
};
|
||||||
|
|
||||||
|
self.clearInterval = function(id) {
|
||||||
|
return timer.clearInterval(id);
|
||||||
|
};
|
||||||
|
|
||||||
|
self.tick = function(millis) {
|
||||||
|
if (installed) {
|
||||||
|
delayedFunctionScheduler.tick(millis)
|
||||||
|
} else {
|
||||||
|
throw new Error("Mock clock is not installed, use jasmine.Clock.useMock()");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return self;
|
||||||
|
|
||||||
|
function legacyIE() {
|
||||||
|
//if these methods are polyfilled, apply will be present
|
||||||
|
//TODO: it may be difficult to load the polyfill before jasmine loads
|
||||||
|
//(env should be new-ed inside of onload)
|
||||||
|
return !(global.setTimeout || global.setInterval).apply;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setTimeout(fn, delay) {
|
||||||
|
return delayedFunctionScheduler.scheduleFunction(fn, delay, argSlice(arguments,2));
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearTimeout(id) {
|
||||||
|
return delayedFunctionScheduler.removeFunctionWithId(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setInterval(fn, interval) {
|
||||||
|
return delayedFunctionScheduler.scheduleFunction(fn, interval, argSlice(arguments, 2), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearInterval(id) {
|
||||||
|
return delayedFunctionScheduler.removeFunctionWithId(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
function argSlice(argsObj, n) {
|
||||||
|
return Array.prototype.slice.call(argsObj, 2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
jasmine.DelayedFunctionScheduler = function() {
|
||||||
|
var self = this;
|
||||||
|
var scheduledFunctions = {};
|
||||||
|
var currentTime = 0;
|
||||||
|
var delayedFnCount = 0;
|
||||||
|
|
||||||
|
self.tick = function(millis) {
|
||||||
|
runFunctionsWithinRange(currentTime, currentTime + millis);
|
||||||
|
currentTime = currentTime + millis;
|
||||||
|
};
|
||||||
|
|
||||||
|
self.scheduleFunction = function(funcToCall, millis, params, recurring, timeoutKey, runAtMillis) {
|
||||||
|
timeoutKey = timeoutKey || ++delayedFnCount;
|
||||||
|
runAtMillis = runAtMillis || (currentTime + millis);
|
||||||
|
scheduledFunctions[timeoutKey] = {
|
||||||
|
runAtMillis: runAtMillis,
|
||||||
|
funcToCall: funcToCall,
|
||||||
|
recurring: recurring,
|
||||||
|
params: params,
|
||||||
|
timeoutKey: timeoutKey,
|
||||||
|
millis: millis
|
||||||
|
};
|
||||||
|
return timeoutKey;
|
||||||
|
};
|
||||||
|
|
||||||
|
self.removeFunctionWithId = function(timeoutKey) {
|
||||||
|
delete scheduledFunctions[timeoutKey];
|
||||||
|
};
|
||||||
|
|
||||||
|
self.reset = function() {
|
||||||
|
currentTime = 0;
|
||||||
|
scheduledFunctions = {};
|
||||||
|
delayedFnCount = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
return self;
|
||||||
|
|
||||||
|
|
||||||
|
//finds/dupes functions within range and removes them.
|
||||||
|
function functionsWithinRange(startMillis, endMillis) {
|
||||||
|
var fnsToRun = [];
|
||||||
|
for (var timeoutKey in scheduledFunctions) {
|
||||||
|
var scheduledFunc = scheduledFunctions[timeoutKey];
|
||||||
|
if (scheduledFunc &&
|
||||||
|
scheduledFunc.runAtMillis >= startMillis &&
|
||||||
|
scheduledFunc.runAtMillis <= endMillis) {
|
||||||
|
//remove fn -- we'll reschedule later if it is recurring.
|
||||||
|
self.removeFunctionWithId(timeoutKey);
|
||||||
|
if (!scheduledFunc.recurring) {
|
||||||
|
fnsToRun.push(scheduledFunc); // schedules each function only once
|
||||||
|
} else {
|
||||||
|
fnsToRun.push(buildNthInstanceOf(scheduledFunc, 0));
|
||||||
|
var additionalTimesFnRunsInRange =
|
||||||
|
Math.floor((endMillis - scheduledFunc.runAtMillis) / scheduledFunc.millis);
|
||||||
|
for (var i = 0; i < additionalTimesFnRunsInRange; i++) {
|
||||||
|
fnsToRun.push(buildNthInstanceOf(scheduledFunc, i + 1));
|
||||||
|
}
|
||||||
|
reschedule(buildNthInstanceOf(scheduledFunc, additionalTimesFnRunsInRange));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fnsToRun;
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildNthInstanceOf(scheduledFunc, n) {
|
||||||
|
return {
|
||||||
|
runAtMillis: scheduledFunc.runAtMillis + (scheduledFunc.millis * n),
|
||||||
|
funcToCall: scheduledFunc.funcToCall,
|
||||||
|
params: scheduledFunc.params,
|
||||||
|
millis: scheduledFunc.millis,
|
||||||
|
recurring: scheduledFunc.recurring,
|
||||||
|
timeoutKey: scheduledFunc.timeoutKey
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function reschedule(scheduledFn) {
|
||||||
|
self.scheduleFunction(scheduledFn.funcToCall,
|
||||||
|
scheduledFn.millis,
|
||||||
|
scheduledFn.params,
|
||||||
|
true,
|
||||||
|
scheduledFn.timeoutKey,
|
||||||
|
scheduledFn.runAtMillis + scheduledFn.millis);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function runFunctionsWithinRange(startMillis, endMillis) {
|
||||||
|
var funcsToRun = functionsWithinRange(startMillis, endMillis);
|
||||||
|
if (funcsToRun.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
funcsToRun.sort(function(a, b) {
|
||||||
|
return a.runAtMillis - b.runAtMillis;
|
||||||
|
});
|
||||||
|
|
||||||
|
for (var i = 0; i < funcsToRun.length; ++i) {
|
||||||
|
var funcToRun = funcsToRun[i];
|
||||||
|
funcToRun.funcToCall.apply(null, funcToRun.params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
jasmine.version_= {
|
jasmine.version_= {
|
||||||
"major": 1,
|
"major": 1,
|
||||||
|
|||||||
296
spec/core/ClockSpec.js
Normal file
296
spec/core/ClockSpec.js
Normal file
@@ -0,0 +1,296 @@
|
|||||||
|
describe("Clock", function() {
|
||||||
|
|
||||||
|
// TODO: fullName/SpecFilter is broken, so don't nest describes you want to filter
|
||||||
|
|
||||||
|
it("calls the global setTimeout directly if Clock is not installed", function() {
|
||||||
|
var setTimeout = jasmine.createSpy('setTimeout'),
|
||||||
|
delayedFunctionScheduler = jasmine.createSpyObj('delayedFunctionScheduler', ['scheduleFunction']),
|
||||||
|
global = { setTimeout: setTimeout },
|
||||||
|
delayedFn = jasmine.createSpy('delayedFn'),
|
||||||
|
clock = new jasmine.Clock(global, delayedFunctionScheduler);
|
||||||
|
|
||||||
|
clock.setTimeout(delayedFn, 0);
|
||||||
|
|
||||||
|
expect(delayedFunctionScheduler.scheduleFunction).not.toHaveBeenCalled();
|
||||||
|
expect(setTimeout).toHaveBeenCalledWith(delayedFn, 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("schedules the delayed function with the fake timer", function() {
|
||||||
|
var setTimeout = jasmine.createSpy('setTimeout'),
|
||||||
|
scheduleFunction = jasmine.createSpy('scheduleFunction'),
|
||||||
|
delayedFunctionScheduler = {scheduleFunction: scheduleFunction},
|
||||||
|
global = { setTimeout: setTimeout },
|
||||||
|
delayedFn = jasmine.createSpy('delayedFn'),
|
||||||
|
clock = new jasmine.Clock(global, delayedFunctionScheduler);
|
||||||
|
|
||||||
|
clock.install();
|
||||||
|
clock.setTimeout(delayedFn, 0, 'a', 'b');
|
||||||
|
|
||||||
|
expect(setTimeout).not.toHaveBeenCalled();
|
||||||
|
expect(delayedFunctionScheduler.scheduleFunction).toHaveBeenCalledWith(delayedFn, 0, ['a', 'b']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns an id for the delayed function", function() {
|
||||||
|
var setTimeout = jasmine.createSpy('setTimeout'),
|
||||||
|
scheduleId = 123,
|
||||||
|
scheduleFunction = jasmine.createSpy('scheduleFunction').andReturn(scheduleId),
|
||||||
|
delayedFunctionScheduler = {scheduleFunction: scheduleFunction},
|
||||||
|
global = { setTimeout: setTimeout },
|
||||||
|
delayedFn = jasmine.createSpy('delayedFn'),
|
||||||
|
clock = new jasmine.Clock(global, delayedFunctionScheduler),
|
||||||
|
timeoutId;
|
||||||
|
|
||||||
|
clock.install();
|
||||||
|
timeoutId = clock.setTimeout(delayedFn, 0);
|
||||||
|
|
||||||
|
expect(timeoutId).toEqual(123);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("calls the global clearTimeout directly if Clock is not installed", function() {
|
||||||
|
var clearTimeout = jasmine.createSpy('clearTimeout'),
|
||||||
|
delayedFunctionScheduler = jasmine.createSpyObj('delayedFunctionScheduler', ['clearTimeout']),
|
||||||
|
global = { clearTimeout: clearTimeout },
|
||||||
|
clock = new jasmine.Clock(global, delayedFunctionScheduler);
|
||||||
|
|
||||||
|
clock.clearTimeout(123);
|
||||||
|
|
||||||
|
expect(clearTimeout).toHaveBeenCalledWith(123);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("clears the scheduled function with the scheduler", function() {
|
||||||
|
var clearTimeout = jasmine.createSpy('clearTimeout'),
|
||||||
|
delayedFunctionScheduler = jasmine.createSpyObj('delayedFunctionScheduler', ['removeFunctionWithId']),
|
||||||
|
global = { setTimeout: clearTimeout },
|
||||||
|
delayedFn = jasmine.createSpy('delayedFn'),
|
||||||
|
clock = new jasmine.Clock(global, delayedFunctionScheduler);
|
||||||
|
|
||||||
|
clock.install();
|
||||||
|
clock.clearTimeout(123);
|
||||||
|
|
||||||
|
expect(clearTimeout).not.toHaveBeenCalled();
|
||||||
|
expect(delayedFunctionScheduler.removeFunctionWithId).toHaveBeenCalledWith(123);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("calls the global setInterval directly if Clock is not installed", function() {
|
||||||
|
var setInterval = jasmine.createSpy('setInterval'),
|
||||||
|
delayedFunctionScheduler = jasmine.createSpyObj('delayedFunctionScheduler', ['scheduleFunction']),
|
||||||
|
global = { setInterval: setInterval },
|
||||||
|
delayedFn = jasmine.createSpy('delayedFn'),
|
||||||
|
clock = new jasmine.Clock(global, delayedFunctionScheduler);
|
||||||
|
|
||||||
|
clock.setInterval(delayedFn, 0);
|
||||||
|
|
||||||
|
expect(delayedFunctionScheduler.scheduleFunction).not.toHaveBeenCalled();
|
||||||
|
expect(setInterval).toHaveBeenCalledWith(delayedFn, 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("schedules the delayed function with the fake timer", function() {
|
||||||
|
var setInterval = jasmine.createSpy('setInterval'),
|
||||||
|
scheduleFunction = jasmine.createSpy('scheduleFunction'),
|
||||||
|
delayedFunctionScheduler = {scheduleFunction: scheduleFunction},
|
||||||
|
global = { setInterval: setInterval },
|
||||||
|
delayedFn = jasmine.createSpy('delayedFn'),
|
||||||
|
clock = new jasmine.Clock(global, delayedFunctionScheduler);
|
||||||
|
|
||||||
|
clock.install();
|
||||||
|
clock.setInterval(delayedFn, 0, 'a', 'b');
|
||||||
|
|
||||||
|
expect(setInterval).not.toHaveBeenCalled();
|
||||||
|
expect(delayedFunctionScheduler.scheduleFunction).toHaveBeenCalledWith(delayedFn, 0, ['a', 'b'], true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns an id for the delayed function", function() {
|
||||||
|
var setInterval = jasmine.createSpy('setInterval'),
|
||||||
|
scheduleId = 123,
|
||||||
|
scheduleFunction = jasmine.createSpy('scheduleFunction').andReturn(scheduleId),
|
||||||
|
delayedFunctionScheduler = {scheduleFunction: scheduleFunction},
|
||||||
|
global = { setInterval: setInterval },
|
||||||
|
delayedFn = jasmine.createSpy('delayedFn'),
|
||||||
|
clock = new jasmine.Clock(global, delayedFunctionScheduler),
|
||||||
|
intervalId;
|
||||||
|
|
||||||
|
clock.install();
|
||||||
|
intervalId = clock.setInterval(delayedFn, 0);
|
||||||
|
|
||||||
|
expect(intervalId).toEqual(123);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("calls the global clearInterval directly if Clock is not installed", function() {
|
||||||
|
var clearInterval = jasmine.createSpy('clearInterval'),
|
||||||
|
delayedFunctionScheduler = jasmine.createSpyObj('delayedFunctionScheduler', ['clearInterval']),
|
||||||
|
global = { clearInterval: clearInterval },
|
||||||
|
clock = new jasmine.Clock(global, delayedFunctionScheduler);
|
||||||
|
|
||||||
|
clock.clearInterval(123);
|
||||||
|
|
||||||
|
expect(clearInterval).toHaveBeenCalledWith(123);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("clears the scheduled function with the scheduler", function() {
|
||||||
|
var clearInterval = jasmine.createSpy('clearInterval'),
|
||||||
|
delayedFunctionScheduler = jasmine.createSpyObj('delayedFunctionScheduler', ['removeFunctionWithId']),
|
||||||
|
global = { setInterval: clearInterval },
|
||||||
|
delayedFn = jasmine.createSpy('delayedFn'),
|
||||||
|
clock = new jasmine.Clock(global, delayedFunctionScheduler);
|
||||||
|
|
||||||
|
clock.install();
|
||||||
|
clock.clearInterval(123);
|
||||||
|
|
||||||
|
expect(clearInterval).not.toHaveBeenCalled();
|
||||||
|
expect(delayedFunctionScheduler.removeFunctionWithId).toHaveBeenCalledWith(123);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("gives you a friendly reminder if the Clock is not installed and you tick", function() {
|
||||||
|
var clock = new jasmine.Clock({}, jasmine.createSpyObj('delayedFunctionScheduler', ['tick']));
|
||||||
|
expect(function() {
|
||||||
|
clock.tick(50);
|
||||||
|
}).toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("can be uninstalled", function() {
|
||||||
|
var setTimeout = jasmine.createSpy('setTimeout'),
|
||||||
|
setInterval = jasmine.createSpy('setInterval'),
|
||||||
|
delayedFunctionScheduler = jasmine.createSpyObj('delayedFunctionScheduler', ['scheduleFunction', 'tick', 'reset']),
|
||||||
|
global = { setTimeout: setTimeout, setInterval: setInterval },
|
||||||
|
delayedFn = jasmine.createSpy('delayedFn'),
|
||||||
|
clock = new jasmine.Clock(global, delayedFunctionScheduler);
|
||||||
|
|
||||||
|
clock.install();
|
||||||
|
clock.setTimeout(delayedFn, 0);
|
||||||
|
expect(setTimeout).not.toHaveBeenCalled();
|
||||||
|
|
||||||
|
clock.setInterval(delayedFn, 0);
|
||||||
|
expect(setInterval).not.toHaveBeenCalled();
|
||||||
|
|
||||||
|
expect(function() {
|
||||||
|
clock.tick(0);
|
||||||
|
}).not.toThrow();
|
||||||
|
|
||||||
|
clock.uninstall();
|
||||||
|
|
||||||
|
expect(delayedFunctionScheduler.reset).toHaveBeenCalled();
|
||||||
|
|
||||||
|
clock.setTimeout(delayedFn, 0);
|
||||||
|
|
||||||
|
expect(setTimeout).toHaveBeenCalled();
|
||||||
|
|
||||||
|
clock.setInterval(delayedFn, 0);
|
||||||
|
expect(setInterval).toHaveBeenCalled();
|
||||||
|
|
||||||
|
expect(function() {
|
||||||
|
clock.tick(0);
|
||||||
|
}).toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it("on IE < 9, fails if extra args are passed to fake clock", function() {
|
||||||
|
//fail, because this would break in IE9.
|
||||||
|
var setTimeout = jasmine.createSpy('setTimeout'),
|
||||||
|
setInterval = jasmine.createSpy('setInterval'),
|
||||||
|
delayedFunctionScheduler = jasmine.createSpyObj('delayedFunctionScheduler', ['scheduleFunction']),
|
||||||
|
fn = jasmine.createSpy('fn'),
|
||||||
|
global = { setTimeout: setTimeout, setInterval: setInterval },
|
||||||
|
clock = new jasmine.Clock(global, delayedFunctionScheduler);
|
||||||
|
|
||||||
|
setTimeout.apply = null;
|
||||||
|
setInterval.apply = null;
|
||||||
|
|
||||||
|
clock.install();
|
||||||
|
|
||||||
|
clock.setTimeout(fn, 0);
|
||||||
|
expect(delayedFunctionScheduler.scheduleFunction).toHaveBeenCalledWith(fn, 0, []);
|
||||||
|
expect(function() {
|
||||||
|
clock.setTimeout(fn, 0, 'extra');
|
||||||
|
}).toThrow();
|
||||||
|
|
||||||
|
clock.setInterval(fn, 0);
|
||||||
|
expect(delayedFunctionScheduler.scheduleFunction).toHaveBeenCalledWith(fn, 0, [], true);
|
||||||
|
expect(function() {
|
||||||
|
clock.setInterval(fn, 0, 'extra');
|
||||||
|
}).toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Clock (acceptance)", function() {
|
||||||
|
it("can run setTimeouts/setIntervals synchronously", function() {
|
||||||
|
var delayedFn1 = jasmine.createSpy('delayedFn1'),
|
||||||
|
delayedFn2 = jasmine.createSpy('delayedFn2'),
|
||||||
|
delayedFn3 = jasmine.createSpy('delayedFn3'),
|
||||||
|
recurring1 = jasmine.createSpy('recurring1'),
|
||||||
|
delayedFunctionScheduler = new jasmine.DelayedFunctionScheduler(),
|
||||||
|
clock = new jasmine.Clock({setTimeout: setTimeout}, delayedFunctionScheduler);
|
||||||
|
|
||||||
|
clock.install();
|
||||||
|
|
||||||
|
clock.setTimeout(delayedFn1, 0, 'some', 'arg');
|
||||||
|
var intervalId = clock.setInterval(recurring1, 50, 'some', 'other', 'args');
|
||||||
|
clock.setTimeout(delayedFn2, 100);
|
||||||
|
clock.setTimeout(delayedFn3, 200);
|
||||||
|
|
||||||
|
expect(delayedFn1).not.toHaveBeenCalled();
|
||||||
|
expect(delayedFn2).not.toHaveBeenCalled();
|
||||||
|
expect(delayedFn3).not.toHaveBeenCalled();
|
||||||
|
|
||||||
|
clock.tick(0);
|
||||||
|
|
||||||
|
expect(delayedFn1).toHaveBeenCalledWith('some', 'arg');
|
||||||
|
expect(delayedFn2).not.toHaveBeenCalled();
|
||||||
|
expect(delayedFn3).not.toHaveBeenCalled();
|
||||||
|
|
||||||
|
clock.tick(50);
|
||||||
|
|
||||||
|
expect(recurring1).toHaveBeenCalledWith('some', 'other', 'args');
|
||||||
|
expect(recurring1.callCount).toBe(1);
|
||||||
|
expect(delayedFn2).not.toHaveBeenCalled();
|
||||||
|
expect(delayedFn3).not.toHaveBeenCalled();
|
||||||
|
|
||||||
|
clock.tick(50);
|
||||||
|
|
||||||
|
expect(recurring1.callCount).toBe(2);
|
||||||
|
expect(delayedFn2).toHaveBeenCalled();
|
||||||
|
expect(delayedFn3).not.toHaveBeenCalled();
|
||||||
|
|
||||||
|
clock.tick(100);
|
||||||
|
|
||||||
|
expect(recurring1.callCount).toBe(4);
|
||||||
|
expect(delayedFn3).toHaveBeenCalled();
|
||||||
|
|
||||||
|
clock.clearInterval(intervalId);
|
||||||
|
clock.tick(50);
|
||||||
|
|
||||||
|
expect(recurring1.callCount).toBe(4);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("can clear a previously set timeout", function() {
|
||||||
|
var clearedFn = jasmine.createSpy('clearedFn'),
|
||||||
|
delayedFunctionScheduler = new jasmine.DelayedFunctionScheduler(),
|
||||||
|
clock = new jasmine.Clock({setTimeout: function() {}}, delayedFunctionScheduler),
|
||||||
|
timeoutId;
|
||||||
|
|
||||||
|
clock.install();
|
||||||
|
|
||||||
|
timeoutId = clock.setTimeout(clearedFn, 100);
|
||||||
|
expect(clearedFn).not.toHaveBeenCalled();
|
||||||
|
|
||||||
|
clock.clearTimeout(timeoutId);
|
||||||
|
clock.tick(100);
|
||||||
|
|
||||||
|
expect(clearedFn).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("correctly schedules functions after the Clock has advanced", function() {
|
||||||
|
var delayedFn1 = jasmine.createSpy('delayedFn1'),
|
||||||
|
delayedFunctionScheduler = new jasmine.DelayedFunctionScheduler(),
|
||||||
|
clock = new jasmine.Clock({setTimeout: function(){}}, delayedFunctionScheduler);
|
||||||
|
|
||||||
|
clock.install();
|
||||||
|
|
||||||
|
clock.tick(100);
|
||||||
|
clock.setTimeout(delayedFn1, 10, ['some', 'arg']);
|
||||||
|
clock.tick(5);
|
||||||
|
expect(delayedFn1).not.toHaveBeenCalled();
|
||||||
|
clock.tick(5);
|
||||||
|
expect(delayedFn1).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
142
spec/core/DelayedFunctionSchedulerSpec.js
Normal file
142
spec/core/DelayedFunctionSchedulerSpec.js
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
describe("DelayedFunctionScheduler", function() {
|
||||||
|
it("schedules a function for later execution", function() {
|
||||||
|
var scheduler = new jasmine.DelayedFunctionScheduler(),
|
||||||
|
fn = jasmine.createSpy('fn');
|
||||||
|
|
||||||
|
scheduler.scheduleFunction(fn, 0);
|
||||||
|
|
||||||
|
expect(fn).not.toHaveBeenCalled();
|
||||||
|
|
||||||
|
scheduler.tick(0);
|
||||||
|
|
||||||
|
expect(fn).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("optionally passes params to scheduled functions", function() {
|
||||||
|
var scheduler = new jasmine.DelayedFunctionScheduler(),
|
||||||
|
fn = jasmine.createSpy('fn');
|
||||||
|
|
||||||
|
scheduler.scheduleFunction(fn, 0, ['foo', 'bar']);
|
||||||
|
|
||||||
|
expect(fn).not.toHaveBeenCalled();
|
||||||
|
|
||||||
|
scheduler.tick(0);
|
||||||
|
|
||||||
|
expect(fn).toHaveBeenCalledWith('foo', 'bar');
|
||||||
|
});
|
||||||
|
|
||||||
|
it("scheduled fns can optionally reoccur", function() {
|
||||||
|
var scheduler = new jasmine.DelayedFunctionScheduler(),
|
||||||
|
fn = jasmine.createSpy('fn');
|
||||||
|
|
||||||
|
scheduler.scheduleFunction(fn, 20, [], true);
|
||||||
|
|
||||||
|
expect(fn).not.toHaveBeenCalled();
|
||||||
|
|
||||||
|
scheduler.tick(20);
|
||||||
|
|
||||||
|
expect(fn.callCount).toBe(1);
|
||||||
|
|
||||||
|
scheduler.tick(40);
|
||||||
|
|
||||||
|
expect(fn.callCount).toBe(3);
|
||||||
|
|
||||||
|
scheduler.tick(21);
|
||||||
|
|
||||||
|
expect(fn.callCount).toBe(4);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it("increments scheduled fns ids unless one is passed", function() {
|
||||||
|
var scheduler = new jasmine.DelayedFunctionScheduler();
|
||||||
|
|
||||||
|
expect(scheduler.scheduleFunction(function() {
|
||||||
|
}, 0)).toBe(1);
|
||||||
|
expect(scheduler.scheduleFunction(function() {
|
||||||
|
}, 0)).toBe(2);
|
||||||
|
expect(scheduler.scheduleFunction(function() {
|
||||||
|
}, 0, [], false, 123)).toBe(123);
|
||||||
|
expect(scheduler.scheduleFunction(function() {
|
||||||
|
}, 0)).toBe(3);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("#removeFunctionWithId removes a previously scheduled function with a given id", function() {
|
||||||
|
var scheduler = new jasmine.DelayedFunctionScheduler(),
|
||||||
|
fn = jasmine.createSpy('fn'),
|
||||||
|
timeoutKey;
|
||||||
|
|
||||||
|
timeoutKey = scheduler.scheduleFunction(fn, 0);
|
||||||
|
|
||||||
|
expect(fn).not.toHaveBeenCalled();
|
||||||
|
|
||||||
|
scheduler.removeFunctionWithId(timeoutKey);
|
||||||
|
|
||||||
|
scheduler.tick(0);
|
||||||
|
|
||||||
|
expect(fn).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("reset removes scheduled functions", function() {
|
||||||
|
var scheduler = new jasmine.DelayedFunctionScheduler(),
|
||||||
|
fn = jasmine.createSpy('fn');
|
||||||
|
|
||||||
|
scheduler.scheduleFunction(fn, 0);
|
||||||
|
|
||||||
|
expect(fn).not.toHaveBeenCalled();
|
||||||
|
|
||||||
|
scheduler.reset();
|
||||||
|
|
||||||
|
scheduler.tick(0);
|
||||||
|
|
||||||
|
expect(fn).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("reset resets the returned ids", function() {
|
||||||
|
var scheduler = new jasmine.DelayedFunctionScheduler();
|
||||||
|
expect(scheduler.scheduleFunction(function() { }, 0)).toBe(1);
|
||||||
|
expect(scheduler.scheduleFunction(function() { }, 0, [], false, 123)).toBe(123);
|
||||||
|
|
||||||
|
scheduler.reset();
|
||||||
|
expect(scheduler.scheduleFunction(function() { }, 0)).toBe(1);
|
||||||
|
expect(scheduler.scheduleFunction(function() { }, 0, [], false, 123)).toBe(123);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("reset resets the current tick time", function() {
|
||||||
|
var scheduler = new jasmine.DelayedFunctionScheduler(),
|
||||||
|
fn = jasmine.createSpy('fn');
|
||||||
|
|
||||||
|
expect(fn).not.toHaveBeenCalled();
|
||||||
|
|
||||||
|
scheduler.tick(15);
|
||||||
|
scheduler.reset();
|
||||||
|
|
||||||
|
scheduler.scheduleFunction(fn, 20, [], false, 1, 20);
|
||||||
|
|
||||||
|
scheduler.tick(5);
|
||||||
|
|
||||||
|
expect(fn).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("executes recurring functions interleaved with regular functions in the correct order", function() {
|
||||||
|
var scheduler = new jasmine.DelayedFunctionScheduler(),
|
||||||
|
fn = jasmine.createSpy('fn'),
|
||||||
|
recurringCallCount = 0,
|
||||||
|
recurring = jasmine.createSpy('recurring').andCallFake(function() {
|
||||||
|
recurringCallCount++;
|
||||||
|
if (recurringCallCount < 5) {
|
||||||
|
expect(fn).not.toHaveBeenCalled();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
scheduler.scheduleFunction(recurring, 10, [], true);
|
||||||
|
scheduler.scheduleFunction(fn, 50);
|
||||||
|
|
||||||
|
scheduler.tick(60);
|
||||||
|
|
||||||
|
expect(recurring).toHaveBeenCalled();
|
||||||
|
expect(recurring.callCount).toBe(6);
|
||||||
|
expect(fn).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
@@ -157,3 +157,33 @@ describe("jasmine.Env", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("jasmine Env", function() {
|
||||||
|
|
||||||
|
it("Mock clock can be installed and used in tests", function() {
|
||||||
|
var setTimeout = jasmine.createSpy('setTimeout'),
|
||||||
|
globalTimeoutFn = jasmine.createSpy('globalTimeoutFn'),
|
||||||
|
fakeTimeoutFn = jasmine.createSpy('fakeTimeoutFn'),
|
||||||
|
env = new jasmine.Env({global: { setTimeout: setTimeout }});
|
||||||
|
|
||||||
|
env.describe("tests", function() {
|
||||||
|
env.it("test with mock clock", function() {
|
||||||
|
env.clock.install();
|
||||||
|
env.clock.setTimeout(fakeTimeoutFn, 100);
|
||||||
|
env.clock.tick(100);
|
||||||
|
});
|
||||||
|
env.it("test without mock clock", function() {
|
||||||
|
env.clock.setTimeout(globalTimeoutFn, 100);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(setTimeout).not.toHaveBeenCalled();
|
||||||
|
expect(fakeTimeoutFn).not.toHaveBeenCalled();
|
||||||
|
|
||||||
|
env.execute();
|
||||||
|
|
||||||
|
expect(fakeTimeoutFn).toHaveBeenCalled();
|
||||||
|
expect(setTimeout).toHaveBeenCalledWith(globalTimeoutFn, 100);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|||||||
@@ -1,40 +0,0 @@
|
|||||||
//// TODO: Disabling b/c this spec isn't testing what it thinks it is.
|
|
||||||
//// Make a proper unit and intergration tests for this object
|
|
||||||
//describe("MockClock", function () {
|
|
||||||
//
|
|
||||||
// beforeEach(function() {
|
|
||||||
// jasmine.Clock.useMock();
|
|
||||||
// });
|
|
||||||
//
|
|
||||||
// describe("setTimeout", function () {
|
|
||||||
// it("should mock the clock when useMock is in a beforeEach", function() {
|
|
||||||
// var expected = false;
|
|
||||||
// setTimeout(function() {
|
|
||||||
// expected = true;
|
|
||||||
// }, 30000);
|
|
||||||
// expect(expected).toBe(false);
|
|
||||||
// jasmine.Clock.tick(30001);
|
|
||||||
// expect(expected).toBe(true);
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
//
|
|
||||||
// describe("setInterval", function () {
|
|
||||||
// it("should mock the clock when useMock is in a beforeEach", function() {
|
|
||||||
// var interval = 0;
|
|
||||||
// setInterval(function() {
|
|
||||||
// interval++;
|
|
||||||
// }, 30000);
|
|
||||||
// expect(interval).toEqual(0);
|
|
||||||
// jasmine.Clock.tick(30001);
|
|
||||||
// expect(interval).toEqual(1);
|
|
||||||
// jasmine.Clock.tick(30001);
|
|
||||||
// expect(interval).toEqual(2);
|
|
||||||
// jasmine.Clock.tick(1);
|
|
||||||
// expect(interval).toEqual(2);
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
//
|
|
||||||
// it("shouldn't complain if you call jasmine.Clock.useMock() more than once", function() {
|
|
||||||
// jasmine.Clock.useMock();
|
|
||||||
// });
|
|
||||||
//});
|
|
||||||
@@ -5,12 +5,6 @@ describe('RunnerTest', function() {
|
|||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
env = new jasmine.Env();
|
env = new jasmine.Env();
|
||||||
env.updateInterval = 0;
|
env.updateInterval = 0;
|
||||||
|
|
||||||
fakeTimer = new jasmine.FakeTimer();
|
|
||||||
env.setTimeout = fakeTimer.setTimeout;
|
|
||||||
env.clearTimeout = fakeTimer.clearTimeout;
|
|
||||||
env.setInterval = fakeTimer.setInterval;
|
|
||||||
env.clearInterval = fakeTimer.clearInterval;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('beforeEach', function() {
|
describe('beforeEach', function() {
|
||||||
|
|||||||
@@ -5,12 +5,6 @@ describe("jasmine spec running", function () {
|
|||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
env = new jasmine.Env();
|
env = new jasmine.Env();
|
||||||
env.updateInterval = 0;
|
env.updateInterval = 0;
|
||||||
|
|
||||||
fakeTimer = new originalJasmine.FakeTimer();
|
|
||||||
env.setTimeout = fakeTimer.setTimeout;
|
|
||||||
env.clearTimeout = fakeTimer.clearTimeout;
|
|
||||||
env.setInterval = fakeTimer.setInterval;
|
|
||||||
env.clearInterval = fakeTimer.clearInterval;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should assign spec ids sequentially', function() {
|
it('should assign spec ids sequentially', function() {
|
||||||
|
|||||||
@@ -1,16 +1,9 @@
|
|||||||
describe('Suite', function() {
|
describe('Suite', function() {
|
||||||
var fakeTimer;
|
|
||||||
var env;
|
var env;
|
||||||
|
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
env = new jasmine.Env();
|
env = new jasmine.Env();
|
||||||
env.updateInterval = 0;
|
env.updateInterval = 0;
|
||||||
|
|
||||||
fakeTimer = new originalJasmine.FakeTimer();
|
|
||||||
env.setTimeout = fakeTimer.setTimeout;
|
|
||||||
env.clearTimeout = fakeTimer.clearTimeout;
|
|
||||||
env.setInterval = fakeTimer.setInterval;
|
|
||||||
env.clearInterval = fakeTimer.clearInterval;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Specs', function () {
|
describe('Specs', function () {
|
||||||
|
|||||||
@@ -71,12 +71,6 @@ describe("HtmlReporter", function() {
|
|||||||
|
|
||||||
var runner, spec, fakeTimer;
|
var runner, spec, fakeTimer;
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
fakeTimer = new jasmine.FakeTimer();
|
|
||||||
env.setTimeout = fakeTimer.setTimeout;
|
|
||||||
env.clearTimeout = fakeTimer.clearTimeout;
|
|
||||||
env.setInterval = fakeTimer.setInterval;
|
|
||||||
env.clearInterval = fakeTimer.clearInterval;
|
|
||||||
fakeDocument.location.search = "?";
|
|
||||||
env.addReporter(htmlReporter);
|
env.addReporter(htmlReporter);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -89,7 +83,6 @@ describe("HtmlReporter", function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
env.execute();
|
env.execute();
|
||||||
fakeTimer.tick(0);
|
|
||||||
|
|
||||||
var resultEl = getResultMessageDiv(body);
|
var resultEl = getResultMessageDiv(body);
|
||||||
expect(resultEl.innerHTML).toMatch(/foo/);
|
expect(resultEl.innerHTML).toMatch(/foo/);
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ src_files:
|
|||||||
- 'core/Env.js'
|
- 'core/Env.js'
|
||||||
- 'core/JsApiReporter.js'
|
- 'core/JsApiReporter.js'
|
||||||
- 'core/Matchers.js'
|
- 'core/Matchers.js'
|
||||||
- 'core/mock-timeout.js'
|
|
||||||
- 'core/MultiReporter.js'
|
- 'core/MultiReporter.js'
|
||||||
- 'core/NestedResults.js'
|
- 'core/NestedResults.js'
|
||||||
- 'core/PrettyPrinter.js'
|
- 'core/PrettyPrinter.js'
|
||||||
|
|||||||
176
spec/node_performance_suite.js
Normal file
176
spec/node_performance_suite.js
Normal file
@@ -0,0 +1,176 @@
|
|||||||
|
var fs = require('fs');
|
||||||
|
var util = require('util');
|
||||||
|
var path = require('path');
|
||||||
|
|
||||||
|
// yes, really keep this here to keep us honest, but only for jasmine's own runner! [xw]
|
||||||
|
// undefined = "diz be undefined yo";
|
||||||
|
|
||||||
|
|
||||||
|
var jasmineGlobals = require('../lib/jasmine-core/jasmine.js');
|
||||||
|
for (var k in jasmineGlobals) {
|
||||||
|
global[k] = jasmineGlobals[k];
|
||||||
|
}
|
||||||
|
var env = jasmine.getEnv();
|
||||||
|
|
||||||
|
var jasmineInterface = {
|
||||||
|
describe: function(description, specDefinitions) {
|
||||||
|
return env.describe(description, specDefinitions);
|
||||||
|
},
|
||||||
|
|
||||||
|
xdescribe: function(description, specDefinitions) {
|
||||||
|
return env.xdescribe(description, specDefinitions);
|
||||||
|
},
|
||||||
|
|
||||||
|
it: function(desc, func) {
|
||||||
|
return env.it(desc, func);
|
||||||
|
},
|
||||||
|
|
||||||
|
xit: function(desc, func) {
|
||||||
|
return env.xit(desc, func);
|
||||||
|
},
|
||||||
|
|
||||||
|
beforeEach: function(beforeEachFunction) {
|
||||||
|
return env.beforeEach(beforeEachFunction);
|
||||||
|
},
|
||||||
|
|
||||||
|
afterEach: function(afterEachFunction) {
|
||||||
|
return env.afterEach(afterEachFunction);
|
||||||
|
},
|
||||||
|
|
||||||
|
expect: function(actual) {
|
||||||
|
return env.expect(actual);
|
||||||
|
},
|
||||||
|
|
||||||
|
addMatchers: function(matchers) {
|
||||||
|
return env.addMatchers(matchers);
|
||||||
|
},
|
||||||
|
|
||||||
|
spyOn: function(obj, methodName) {
|
||||||
|
return env.spyOn(obj, methodName);
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
jsApiReporter: new jasmine.JsApiReporter(jasmine)
|
||||||
|
};
|
||||||
|
|
||||||
|
for (var k in jasmineInterface) {
|
||||||
|
global[k] = jasmineInterface[k];
|
||||||
|
}
|
||||||
|
|
||||||
|
require('../src/console/ConsoleReporter.js');
|
||||||
|
|
||||||
|
/*
|
||||||
|
Pulling in code from jasmine-node.
|
||||||
|
|
||||||
|
We can't just depend on jasmine-node because it has its own jasmine that it uses.
|
||||||
|
*/
|
||||||
|
|
||||||
|
global.window = {
|
||||||
|
setTimeout: setTimeout,
|
||||||
|
clearTimeout: clearTimeout,
|
||||||
|
setInterval: setInterval,
|
||||||
|
clearInterval: clearInterval
|
||||||
|
};
|
||||||
|
|
||||||
|
delete global.window;
|
||||||
|
|
||||||
|
function noop() {
|
||||||
|
}
|
||||||
|
|
||||||
|
jasmine.executeSpecs = function(specs, done, isVerbose, showColors) {
|
||||||
|
global.originalJasmine = jasmine;
|
||||||
|
|
||||||
|
for (var i = 0, len = specs.length; i < len; ++i) {
|
||||||
|
var filename = specs[i];
|
||||||
|
require(filename.replace(/\.\w+$/, ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
var jasmineEnv = jasmine.getEnv();
|
||||||
|
var consoleReporter = new jasmine.ConsoleReporter(util.print, done, showColors);
|
||||||
|
|
||||||
|
jasmineEnv.addReporter(consoleReporter);
|
||||||
|
jasmineEnv.execute();
|
||||||
|
};
|
||||||
|
|
||||||
|
jasmine.getAllSpecFiles = function(dir, matcher) {
|
||||||
|
var specs = [];
|
||||||
|
|
||||||
|
if (fs.statSync(dir).isFile() && dir.match(matcher)) {
|
||||||
|
specs.push(dir);
|
||||||
|
} else {
|
||||||
|
var files = fs.readdirSync(dir);
|
||||||
|
for (var i = 0, len = files.length; i < len; ++i) {
|
||||||
|
var filename = dir + '/' + files[i];
|
||||||
|
if (fs.statSync(filename).isFile() && filename.match(matcher)) {
|
||||||
|
specs.push(filename);
|
||||||
|
} else if (fs.statSync(filename).isDirectory()) {
|
||||||
|
var subfiles = this.getAllSpecFiles(filename, matcher);
|
||||||
|
subfiles.forEach(function(result) {
|
||||||
|
specs.push(result);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return specs;
|
||||||
|
};
|
||||||
|
|
||||||
|
function now() {
|
||||||
|
return new Date().getTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
jasmine.asyncSpecWait = function() {
|
||||||
|
var wait = jasmine.asyncSpecWait;
|
||||||
|
wait.start = now();
|
||||||
|
wait.done = false;
|
||||||
|
(function innerWait() {
|
||||||
|
waits(10);
|
||||||
|
runs(function() {
|
||||||
|
if (wait.start + wait.timeout < now()) {
|
||||||
|
expect('timeout waiting for spec').toBeNull();
|
||||||
|
} else if (wait.done) {
|
||||||
|
wait.done = false;
|
||||||
|
} else {
|
||||||
|
innerWait();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
};
|
||||||
|
jasmine.asyncSpecWait.timeout = 4 * 1000;
|
||||||
|
jasmine.asyncSpecDone = function() {
|
||||||
|
jasmine.asyncSpecWait.done = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
for (var key in jasmine) {
|
||||||
|
exports[key] = jasmine[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
End jasmine-node runner
|
||||||
|
*/
|
||||||
|
|
||||||
|
var isVerbose = false;
|
||||||
|
var showColors = true;
|
||||||
|
process.argv.forEach(function(arg) {
|
||||||
|
switch (arg) {
|
||||||
|
case '--color': showColors = true; break;
|
||||||
|
case '--noColor': showColors = false; break;
|
||||||
|
case '--verbose': isVerbose = true; break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var specs = jasmine.getAllSpecFiles(__dirname + '/smoke/', new RegExp("test.js$"));
|
||||||
|
var domIndependentSpecs = [];
|
||||||
|
for (var i = 0; i < specs.length; i++) {
|
||||||
|
if (fs.readFileSync(specs[i], "utf8").indexOf("document.createElement") < 0) {
|
||||||
|
domIndependentSpecs.push(specs[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
jasmine.executeSpecs(domIndependentSpecs, function(passed) {
|
||||||
|
if (passed) {
|
||||||
|
process.exit(0);
|
||||||
|
} else {
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}, isVerbose, showColors);
|
||||||
@@ -34,7 +34,8 @@
|
|||||||
<script type="text/javascript" src=".././spec/core/ExpectationResultSpec.js"></script>
|
<script type="text/javascript" src=".././spec/core/ExpectationResultSpec.js"></script>
|
||||||
<script type="text/javascript" src=".././spec/core/JsApiReporterSpec.js"></script>
|
<script type="text/javascript" src=".././spec/core/JsApiReporterSpec.js"></script>
|
||||||
<script type="text/javascript" src=".././spec/core/MatchersSpec.js"></script>
|
<script type="text/javascript" src=".././spec/core/MatchersSpec.js"></script>
|
||||||
<script type="text/javascript" src=".././spec/core/MockClockSpec.js"></script>
|
<script type="text/javascript" src=".././spec/core/ClockSpec.js"></script>
|
||||||
|
<script type="text/javascript" src=".././spec/core/DelayedFunctionSchedulerSpec.js"></script>
|
||||||
<script type="text/javascript" src=".././spec/core/MultiReporterSpec.js"></script>
|
<script type="text/javascript" src=".././spec/core/MultiReporterSpec.js"></script>
|
||||||
<script type="text/javascript" src=".././spec/core/NestedResultsSpec.js"></script>
|
<script type="text/javascript" src=".././spec/core/NestedResultsSpec.js"></script>
|
||||||
<script type="text/javascript" src=".././spec/core/PrettyPrintSpec.js"></script>
|
<script type="text/javascript" src=".././spec/core/PrettyPrintSpec.js"></script>
|
||||||
|
|||||||
93
src/core/Clock.js
Normal file
93
src/core/Clock.js
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
jasmine.Clock = function(global, delayedFunctionScheduler) {
|
||||||
|
var self = this,
|
||||||
|
realTimingFunctions = {
|
||||||
|
setTimeout: global.setTimeout,
|
||||||
|
clearTimeout: global.clearTimeout,
|
||||||
|
setInterval: global.setInterval,
|
||||||
|
clearInterval: global.clearInterval
|
||||||
|
},
|
||||||
|
fakeTimingFunctions = {
|
||||||
|
setTimeout: setTimeout,
|
||||||
|
clearTimeout: clearTimeout,
|
||||||
|
setInterval: setInterval,
|
||||||
|
clearInterval: clearInterval
|
||||||
|
},
|
||||||
|
timer = realTimingFunctions,
|
||||||
|
installed = false;
|
||||||
|
|
||||||
|
self.install = function() {
|
||||||
|
installed = true;
|
||||||
|
timer = fakeTimingFunctions;
|
||||||
|
};
|
||||||
|
|
||||||
|
self.uninstall = function() {
|
||||||
|
delayedFunctionScheduler.reset();
|
||||||
|
installed = false;
|
||||||
|
timer = realTimingFunctions;
|
||||||
|
};
|
||||||
|
|
||||||
|
self.setTimeout = function(fn, delay, params) {
|
||||||
|
if (legacyIE()) {
|
||||||
|
if (arguments.length > 2) {
|
||||||
|
throw new Error("IE < 9 cannot support extra params to setTimeout without a polyfill");
|
||||||
|
}
|
||||||
|
return timer.setTimeout(fn, delay);
|
||||||
|
}
|
||||||
|
return timer.setTimeout.apply(null, arguments);
|
||||||
|
};
|
||||||
|
|
||||||
|
self.setInterval = function(fn, delay, params) {
|
||||||
|
if (legacyIE()) {
|
||||||
|
if (arguments.length > 2) {
|
||||||
|
throw new Error("IE < 9 cannot support extra params to setInterval without a polyfill");
|
||||||
|
}
|
||||||
|
return timer.setInterval(fn, delay);
|
||||||
|
}
|
||||||
|
return timer.setInterval.apply(null, arguments);
|
||||||
|
};
|
||||||
|
|
||||||
|
self.clearTimeout = function(id) {
|
||||||
|
return timer.clearTimeout(id);
|
||||||
|
};
|
||||||
|
|
||||||
|
self.clearInterval = function(id) {
|
||||||
|
return timer.clearInterval(id);
|
||||||
|
};
|
||||||
|
|
||||||
|
self.tick = function(millis) {
|
||||||
|
if (installed) {
|
||||||
|
delayedFunctionScheduler.tick(millis)
|
||||||
|
} else {
|
||||||
|
throw new Error("Mock clock is not installed, use jasmine.Clock.useMock()");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return self;
|
||||||
|
|
||||||
|
function legacyIE() {
|
||||||
|
//if these methods are polyfilled, apply will be present
|
||||||
|
//TODO: it may be difficult to load the polyfill before jasmine loads
|
||||||
|
//(env should be new-ed inside of onload)
|
||||||
|
return !(global.setTimeout || global.setInterval).apply;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setTimeout(fn, delay) {
|
||||||
|
return delayedFunctionScheduler.scheduleFunction(fn, delay, argSlice(arguments,2));
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearTimeout(id) {
|
||||||
|
return delayedFunctionScheduler.removeFunctionWithId(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setInterval(fn, interval) {
|
||||||
|
return delayedFunctionScheduler.scheduleFunction(fn, interval, argSlice(arguments, 2), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearInterval(id) {
|
||||||
|
return delayedFunctionScheduler.removeFunctionWithId(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
function argSlice(argsObj, n) {
|
||||||
|
return Array.prototype.slice.call(argsObj, 2);
|
||||||
|
}
|
||||||
|
};
|
||||||
102
src/core/DelayedFunctionScheduler.js
Normal file
102
src/core/DelayedFunctionScheduler.js
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
jasmine.DelayedFunctionScheduler = function() {
|
||||||
|
var self = this;
|
||||||
|
var scheduledFunctions = {};
|
||||||
|
var currentTime = 0;
|
||||||
|
var delayedFnCount = 0;
|
||||||
|
|
||||||
|
self.tick = function(millis) {
|
||||||
|
runFunctionsWithinRange(currentTime, currentTime + millis);
|
||||||
|
currentTime = currentTime + millis;
|
||||||
|
};
|
||||||
|
|
||||||
|
self.scheduleFunction = function(funcToCall, millis, params, recurring, timeoutKey, runAtMillis) {
|
||||||
|
timeoutKey = timeoutKey || ++delayedFnCount;
|
||||||
|
runAtMillis = runAtMillis || (currentTime + millis);
|
||||||
|
scheduledFunctions[timeoutKey] = {
|
||||||
|
runAtMillis: runAtMillis,
|
||||||
|
funcToCall: funcToCall,
|
||||||
|
recurring: recurring,
|
||||||
|
params: params,
|
||||||
|
timeoutKey: timeoutKey,
|
||||||
|
millis: millis
|
||||||
|
};
|
||||||
|
return timeoutKey;
|
||||||
|
};
|
||||||
|
|
||||||
|
self.removeFunctionWithId = function(timeoutKey) {
|
||||||
|
delete scheduledFunctions[timeoutKey];
|
||||||
|
};
|
||||||
|
|
||||||
|
self.reset = function() {
|
||||||
|
currentTime = 0;
|
||||||
|
scheduledFunctions = {};
|
||||||
|
delayedFnCount = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
return self;
|
||||||
|
|
||||||
|
|
||||||
|
//finds/dupes functions within range and removes them.
|
||||||
|
function functionsWithinRange(startMillis, endMillis) {
|
||||||
|
var fnsToRun = [];
|
||||||
|
for (var timeoutKey in scheduledFunctions) {
|
||||||
|
var scheduledFunc = scheduledFunctions[timeoutKey];
|
||||||
|
if (scheduledFunc &&
|
||||||
|
scheduledFunc.runAtMillis >= startMillis &&
|
||||||
|
scheduledFunc.runAtMillis <= endMillis) {
|
||||||
|
//remove fn -- we'll reschedule later if it is recurring.
|
||||||
|
self.removeFunctionWithId(timeoutKey);
|
||||||
|
if (!scheduledFunc.recurring) {
|
||||||
|
fnsToRun.push(scheduledFunc); // schedules each function only once
|
||||||
|
} else {
|
||||||
|
fnsToRun.push(buildNthInstanceOf(scheduledFunc, 0));
|
||||||
|
var additionalTimesFnRunsInRange =
|
||||||
|
Math.floor((endMillis - scheduledFunc.runAtMillis) / scheduledFunc.millis);
|
||||||
|
for (var i = 0; i < additionalTimesFnRunsInRange; i++) {
|
||||||
|
fnsToRun.push(buildNthInstanceOf(scheduledFunc, i + 1));
|
||||||
|
}
|
||||||
|
reschedule(buildNthInstanceOf(scheduledFunc, additionalTimesFnRunsInRange));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fnsToRun;
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildNthInstanceOf(scheduledFunc, n) {
|
||||||
|
return {
|
||||||
|
runAtMillis: scheduledFunc.runAtMillis + (scheduledFunc.millis * n),
|
||||||
|
funcToCall: scheduledFunc.funcToCall,
|
||||||
|
params: scheduledFunc.params,
|
||||||
|
millis: scheduledFunc.millis,
|
||||||
|
recurring: scheduledFunc.recurring,
|
||||||
|
timeoutKey: scheduledFunc.timeoutKey
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function reschedule(scheduledFn) {
|
||||||
|
self.scheduleFunction(scheduledFn.funcToCall,
|
||||||
|
scheduledFn.millis,
|
||||||
|
scheduledFn.params,
|
||||||
|
true,
|
||||||
|
scheduledFn.timeoutKey,
|
||||||
|
scheduledFn.runAtMillis + scheduledFn.millis);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function runFunctionsWithinRange(startMillis, endMillis) {
|
||||||
|
var funcsToRun = functionsWithinRange(startMillis, endMillis);
|
||||||
|
if (funcsToRun.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
funcsToRun.sort(function(a, b) {
|
||||||
|
return a.runAtMillis - b.runAtMillis;
|
||||||
|
});
|
||||||
|
|
||||||
|
for (var i = 0; i < funcsToRun.length; ++i) {
|
||||||
|
var funcToRun = funcsToRun[i];
|
||||||
|
funcToRun.funcToCall.apply(null, funcToRun.params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -4,12 +4,17 @@
|
|||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
(function() {
|
(function() {
|
||||||
jasmine.Env = function() {
|
jasmine.Env = function(options) {
|
||||||
|
options = options || {};
|
||||||
var self = this;
|
var self = this;
|
||||||
|
var global = options.global || jasmine.getGlobal();
|
||||||
|
|
||||||
|
this.clock = new jasmine.Clock(global, new jasmine.DelayedFunctionScheduler());
|
||||||
|
|
||||||
var suiteConstructor = jasmine.Suite;
|
var suiteConstructor = jasmine.Suite;
|
||||||
var isSuite = function(thing) {
|
var isSuite = function(thing) {
|
||||||
return thing instanceof suiteConstructor;
|
return thing instanceof suiteConstructor;
|
||||||
}
|
};
|
||||||
this.jasmine = jasmine;
|
this.jasmine = jasmine;
|
||||||
this.currentRunner_ = new jasmine.Runner(this, isSuite);
|
this.currentRunner_ = new jasmine.Runner(this, isSuite);
|
||||||
this.spies_ = [];
|
this.spies_ = [];
|
||||||
@@ -95,8 +100,7 @@
|
|||||||
afterFns: afterFns(suite),
|
afterFns: afterFns(suite),
|
||||||
expectationFactory: expectationFactory,
|
expectationFactory: expectationFactory,
|
||||||
exceptionFormatter: exceptionFormatter,
|
exceptionFormatter: exceptionFormatter,
|
||||||
//TODO: move spec creation to more appropriate level and remove this shim
|
resultCallback: specResultCallback,
|
||||||
resultCallback: function(result) { self.currentSpec = null; suite.specComplete(result); },
|
|
||||||
fullNameFactory: function(spec) { return fullNameFactory(spec, suite) },
|
fullNameFactory: function(spec) { return fullNameFactory(spec, suite) },
|
||||||
startCallback: startCallback,
|
startCallback: startCallback,
|
||||||
description: description,
|
description: description,
|
||||||
@@ -110,8 +114,13 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
return spec;
|
return spec;
|
||||||
};
|
|
||||||
|
|
||||||
|
function specResultCallback(result) {
|
||||||
|
self.clock.uninstall();
|
||||||
|
self.currentSpec = null;
|
||||||
|
suite.specComplete(result);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
var queueConstructor = jasmine.Queue;
|
var queueConstructor = jasmine.Queue;
|
||||||
var queueFactory = function() {
|
var queueFactory = function() {
|
||||||
@@ -123,12 +132,6 @@
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
jasmine.Env.prototype.setTimeout = jasmine.setTimeout;
|
|
||||||
jasmine.Env.prototype.clearTimeout = jasmine.clearTimeout;
|
|
||||||
jasmine.Env.prototype.setInterval = jasmine.setInterval;
|
|
||||||
jasmine.Env.prototype.clearInterval = jasmine.clearInterval;
|
|
||||||
|
|
||||||
//TODO: shim Spec addMatchers behavior into Env. Should be rewritten to remove globals, etc.
|
//TODO: shim Spec addMatchers behavior into Env. Should be rewritten to remove globals, etc.
|
||||||
jasmine.Env.prototype.addMatchers = function(matchersPrototype) {
|
jasmine.Env.prototype.addMatchers = function(matchersPrototype) {
|
||||||
var parent = this.matchersClass;
|
var parent = this.matchersClass;
|
||||||
|
|||||||
@@ -108,8 +108,8 @@ jasmine.MessageResult.prototype.toString = function() {
|
|||||||
/**
|
/**
|
||||||
* Getter for the Jasmine environment. Ensures one gets created
|
* Getter for the Jasmine environment. Ensures one gets created
|
||||||
*/
|
*/
|
||||||
jasmine.getEnv = function() {
|
jasmine.getEnv = function(options) {
|
||||||
var env = jasmine.currentEnv_ = jasmine.currentEnv_ || new jasmine.Env();
|
var env = jasmine.currentEnv_ = jasmine.currentEnv_ || new jasmine.Env(options);
|
||||||
//jasmine. singletons in here (setTimeout blah blah).
|
//jasmine. singletons in here (setTimeout blah blah).
|
||||||
return env;
|
return env;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,184 +0,0 @@
|
|||||||
// Mock setTimeout, clearTimeout
|
|
||||||
// Contributed by Pivotal Computer Systems, www.pivotalsf.com
|
|
||||||
|
|
||||||
jasmine.FakeTimer = function() {
|
|
||||||
this.reset();
|
|
||||||
|
|
||||||
var self = this;
|
|
||||||
self.setTimeout = function(funcToCall, millis) {
|
|
||||||
self.timeoutsMade++;
|
|
||||||
self.scheduleFunction(self.timeoutsMade, funcToCall, millis, false);
|
|
||||||
return self.timeoutsMade;
|
|
||||||
};
|
|
||||||
|
|
||||||
self.setInterval = function(funcToCall, millis) {
|
|
||||||
self.timeoutsMade++;
|
|
||||||
self.scheduleFunction(self.timeoutsMade, funcToCall, millis, true);
|
|
||||||
return self.timeoutsMade;
|
|
||||||
};
|
|
||||||
|
|
||||||
self.clearTimeout = function(timeoutKey) {
|
|
||||||
self.scheduledFunctions[timeoutKey] = jasmine.undefined;
|
|
||||||
};
|
|
||||||
|
|
||||||
self.clearInterval = function(timeoutKey) {
|
|
||||||
self.scheduledFunctions[timeoutKey] = jasmine.undefined;
|
|
||||||
};
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.FakeTimer.prototype.reset = function() {
|
|
||||||
this.timeoutsMade = 0;
|
|
||||||
this.scheduledFunctions = {};
|
|
||||||
this.nowMillis = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.FakeTimer.prototype.tick = function(millis) {
|
|
||||||
var oldMillis = this.nowMillis;
|
|
||||||
var newMillis = oldMillis + millis;
|
|
||||||
this.runFunctionsWithinRange(oldMillis, newMillis);
|
|
||||||
this.nowMillis = newMillis;
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.FakeTimer.prototype.runFunctionsWithinRange = function(oldMillis, nowMillis) {
|
|
||||||
var scheduledFunc;
|
|
||||||
var funcsToRun = [];
|
|
||||||
for (var timeoutKey in this.scheduledFunctions) {
|
|
||||||
scheduledFunc = this.scheduledFunctions[timeoutKey];
|
|
||||||
if (scheduledFunc != jasmine.undefined &&
|
|
||||||
scheduledFunc.runAtMillis >= oldMillis &&
|
|
||||||
scheduledFunc.runAtMillis <= nowMillis) {
|
|
||||||
funcsToRun.push(scheduledFunc);
|
|
||||||
this.scheduledFunctions[timeoutKey] = jasmine.undefined;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (funcsToRun.length > 0) {
|
|
||||||
funcsToRun.sort(function(a, b) {
|
|
||||||
return a.runAtMillis - b.runAtMillis;
|
|
||||||
});
|
|
||||||
for (var i = 0; i < funcsToRun.length; ++i) {
|
|
||||||
try {
|
|
||||||
var funcToRun = funcsToRun[i];
|
|
||||||
this.nowMillis = funcToRun.runAtMillis;
|
|
||||||
funcToRun.funcToCall();
|
|
||||||
if (funcToRun.recurring) {
|
|
||||||
this.scheduleFunction(funcToRun.timeoutKey,
|
|
||||||
funcToRun.funcToCall,
|
|
||||||
funcToRun.millis,
|
|
||||||
true);
|
|
||||||
}
|
|
||||||
} catch(e) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.runFunctionsWithinRange(oldMillis, nowMillis);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.FakeTimer.prototype.scheduleFunction = function(timeoutKey, funcToCall, millis, recurring) {
|
|
||||||
this.scheduledFunctions[timeoutKey] = {
|
|
||||||
runAtMillis: this.nowMillis + millis,
|
|
||||||
funcToCall: funcToCall,
|
|
||||||
recurring: recurring,
|
|
||||||
timeoutKey: timeoutKey,
|
|
||||||
millis: millis
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @namespace
|
|
||||||
*/
|
|
||||||
jasmine.Clock = {
|
|
||||||
defaultFakeTimer: new jasmine.FakeTimer(),
|
|
||||||
|
|
||||||
reset: function() {
|
|
||||||
jasmine.Clock.assertInstalled();
|
|
||||||
jasmine.Clock.defaultFakeTimer.reset();
|
|
||||||
},
|
|
||||||
|
|
||||||
tick: function(millis) {
|
|
||||||
jasmine.Clock.assertInstalled();
|
|
||||||
jasmine.Clock.defaultFakeTimer.tick(millis);
|
|
||||||
},
|
|
||||||
|
|
||||||
runFunctionsWithinRange: function(oldMillis, nowMillis) {
|
|
||||||
jasmine.Clock.defaultFakeTimer.runFunctionsWithinRange(oldMillis, nowMillis);
|
|
||||||
},
|
|
||||||
|
|
||||||
scheduleFunction: function(timeoutKey, funcToCall, millis, recurring) {
|
|
||||||
jasmine.Clock.defaultFakeTimer.scheduleFunction(timeoutKey, funcToCall, millis, recurring);
|
|
||||||
},
|
|
||||||
|
|
||||||
useMock: function() {
|
|
||||||
if (!jasmine.Clock.isInstalled()) {
|
|
||||||
//TODO: this is using an interface that doesn't exist.
|
|
||||||
var spec = jasmine.getEnv().currentSpec;
|
|
||||||
spec.after(jasmine.Clock.uninstallMock);
|
|
||||||
|
|
||||||
jasmine.Clock.installMock();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
installMock: function() {
|
|
||||||
jasmine.Clock.installed = jasmine.Clock.defaultFakeTimer;
|
|
||||||
},
|
|
||||||
|
|
||||||
uninstallMock: function() {
|
|
||||||
jasmine.Clock.assertInstalled();
|
|
||||||
jasmine.Clock.installed = jasmine.Clock.real;
|
|
||||||
},
|
|
||||||
|
|
||||||
real: {
|
|
||||||
setTimeout: jasmine.getGlobal().setTimeout,
|
|
||||||
clearTimeout: jasmine.getGlobal().clearTimeout,
|
|
||||||
setInterval: jasmine.getGlobal().setInterval,
|
|
||||||
clearInterval: jasmine.getGlobal().clearInterval
|
|
||||||
},
|
|
||||||
|
|
||||||
assertInstalled: function() {
|
|
||||||
if (!jasmine.Clock.isInstalled()) {
|
|
||||||
throw new Error("Mock clock is not installed, use jasmine.Clock.useMock()");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
isInstalled: function() {
|
|
||||||
return jasmine.Clock.installed == jasmine.Clock.defaultFakeTimer;
|
|
||||||
},
|
|
||||||
|
|
||||||
installed: null
|
|
||||||
};
|
|
||||||
jasmine.Clock.installed = jasmine.Clock.real;
|
|
||||||
|
|
||||||
//else for IE support
|
|
||||||
jasmine.getGlobal().setTimeout = function(funcToCall, millis) {
|
|
||||||
if (jasmine.Clock.installed.setTimeout.apply) {
|
|
||||||
return jasmine.Clock.installed.setTimeout.apply(this, arguments);
|
|
||||||
} else {
|
|
||||||
return jasmine.Clock.installed.setTimeout(funcToCall, millis);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.getGlobal().setInterval = function(funcToCall, millis) {
|
|
||||||
if (jasmine.Clock.installed.setInterval.apply) {
|
|
||||||
return jasmine.Clock.installed.setInterval.apply(this, arguments);
|
|
||||||
} else {
|
|
||||||
return jasmine.Clock.installed.setInterval(funcToCall, millis);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.getGlobal().clearTimeout = function(timeoutKey) {
|
|
||||||
if (jasmine.Clock.installed.clearTimeout.apply) {
|
|
||||||
return jasmine.Clock.installed.clearTimeout.apply(this, arguments);
|
|
||||||
} else {
|
|
||||||
return jasmine.Clock.installed.clearTimeout(timeoutKey);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.getGlobal().clearInterval = function(timeoutKey) {
|
|
||||||
if (jasmine.Clock.installed.clearTimeout.apply) {
|
|
||||||
return jasmine.Clock.installed.clearInterval.apply(this, arguments);
|
|
||||||
} else {
|
|
||||||
return jasmine.Clock.installed.clearInterval(timeoutKey);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
@@ -8,7 +8,6 @@ class JasmineDev < Thor
|
|||||||
"Reporter.js",
|
"Reporter.js",
|
||||||
"JsApiReporter.js",
|
"JsApiReporter.js",
|
||||||
"Matchers.js",
|
"Matchers.js",
|
||||||
"mock-timeout.js",
|
|
||||||
"MultiReporter.js",
|
"MultiReporter.js",
|
||||||
"NestedResults.js",
|
"NestedResults.js",
|
||||||
"PrettyPrinter.js",
|
"PrettyPrinter.js",
|
||||||
@@ -16,6 +15,8 @@ class JasmineDev < Thor
|
|||||||
"Runner.js",
|
"Runner.js",
|
||||||
"Spec.js",
|
"Spec.js",
|
||||||
"Suite.js",
|
"Suite.js",
|
||||||
|
"Clock.js",
|
||||||
|
"DelayedFunctionScheduler.js"
|
||||||
],
|
],
|
||||||
|
|
||||||
:html => [
|
:html => [
|
||||||
|
|||||||
Reference in New Issue
Block a user