[Finishes #45476285] Add timeout support to async tests
This commit is contained in:
@@ -291,6 +291,55 @@ describe("Env integration", function() {
|
|||||||
|
|
||||||
env.execute();
|
env.execute();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("with a mock clock", function() {
|
||||||
|
beforeEach(function() {
|
||||||
|
jasmine.getEnv().clock.install();
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function() {
|
||||||
|
jasmine.getEnv().clock.uninstall();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should not hang on async specs that forget to call done()", function(done) {
|
||||||
|
var env = new j$.Env(),
|
||||||
|
reporter = jasmine.createSpyObj('fakeReporter', [
|
||||||
|
"jasmineStarted",
|
||||||
|
"jasmineDone",
|
||||||
|
"suiteStarted",
|
||||||
|
"suiteDone",
|
||||||
|
"specStarted",
|
||||||
|
"specDone"
|
||||||
|
]);
|
||||||
|
|
||||||
|
env.addReporter(reporter);
|
||||||
|
|
||||||
|
env.describe("tests", function() {
|
||||||
|
env.it("async spec that will hang", function(underTestCallback) {
|
||||||
|
env.expect(true).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
env.it("after async spec", function() {
|
||||||
|
env.expect(true).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
env.execute();
|
||||||
|
|
||||||
|
reporter.jasmineDone.and.callFake(function() {
|
||||||
|
expect(reporter.jasmineStarted).toHaveBeenCalledWith({
|
||||||
|
totalSpecsDefined: 2
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(reporter.specDone).toHaveBeenCalledWith(jasmine.objectContaining({status: 'passed'}));
|
||||||
|
expect(reporter.specDone).toHaveBeenCalledWith(jasmine.objectContaining({status: 'failed'}));
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
jasmine.getEnv().clock.tick(60001);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
// TODO: something is wrong with this spec
|
// TODO: something is wrong with this spec
|
||||||
it("should report as expected", function(done) {
|
it("should report as expected", function(done) {
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ describe('Spies', function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("warns the user that we indend to overwrite an existing property", function() {
|
it("warns the user that we indend to overwrite an existing property", function() {
|
||||||
|
TestClass.prototype.someFunction.and = "existing";
|
||||||
|
|
||||||
expect(function() {
|
expect(function() {
|
||||||
j$.createSpy(TestClass.prototype, TestClass.prototype.someFunction);
|
j$.createSpy(TestClass.prototype, TestClass.prototype.someFunction);
|
||||||
}).toThrowError("Jasmine spies would overwrite the 'and' and 'calls' properties on the object being spied upon");
|
}).toThrowError("Jasmine spies would overwrite the 'and' and 'calls' properties on the object being spied upon");
|
||||||
@@ -23,8 +25,8 @@ describe('Spies', function () {
|
|||||||
it("adds a spyStrategy and callTracker to the spy", function() {
|
it("adds a spyStrategy and callTracker to the spy", function() {
|
||||||
var spy = j$.createSpy(TestClass.prototype, TestClass.prototype.someFunction);
|
var spy = j$.createSpy(TestClass.prototype, TestClass.prototype.someFunction);
|
||||||
|
|
||||||
expect(spy.and).toEqual(jasmine.any(j$.SpyStrategy);
|
expect(spy.and).toEqual(jasmine.any(j$.SpyStrategy));
|
||||||
expect(spy.calls).toEqual(jasmine.any(j$.CallTracker);
|
expect(spy.calls).toEqual(jasmine.any(j$.CallTracker));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,9 @@
|
|||||||
|
|
||||||
var env = jasmine.getEnv();
|
var env = jasmine.getEnv();
|
||||||
|
|
||||||
|
SUPER_TIMEOUT = setTimeout;
|
||||||
|
SUPER_CLEAR_TIMEOUT = clearTimeout;
|
||||||
|
|
||||||
var jasmineInterface = {
|
var jasmineInterface = {
|
||||||
describe: function(description, specDefinitions) {
|
describe: function(description, specDefinitions) {
|
||||||
return env.describe(description, specDefinitions);
|
return env.describe(description, specDefinitions);
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
getJasmineRequireObj().Env = function(j$) {
|
getJasmineRequireObj().Env = function(j$) {
|
||||||
function Env(options) {
|
function Env(options) {
|
||||||
options = options || {};
|
options = options || {};
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
var global = options.global || j$.getGlobal();
|
var global = options.global || j$.getGlobal();
|
||||||
|
|
||||||
var catchExceptions = true;
|
var catchExceptions = true;
|
||||||
|
|
||||||
var realSetTimeout = j$.getGlobal().setTimeout;
|
var realSetTimeout = j$.getGlobal().setTimeout;
|
||||||
|
var realClearTimeout = j$.getGlobal().clearTimeout;
|
||||||
this.clock = new j$.Clock(global, new j$.DelayedFunctionScheduler());
|
this.clock = new j$.Clock(global, new j$.DelayedFunctionScheduler());
|
||||||
|
|
||||||
var spies = [];
|
var spies = [];
|
||||||
@@ -120,9 +121,13 @@ getJasmineRequireObj().Env = function(j$) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var asyncSpecTimeout = 60000;
|
||||||
|
|
||||||
var queueRunnerFactory = function(options) {
|
var queueRunnerFactory = function(options) {
|
||||||
options.catchException = self.catchException;
|
options.catchException = self.catchException;
|
||||||
options.clearStack = options.clearStack || clearStack;
|
options.clearStack = options.clearStack || clearStack;
|
||||||
|
options.realTimer = { setTimeout: realSetTimeout, clearTimeout: realClearTimeout };
|
||||||
|
options.asyncSpecTimeout = asyncSpecTimeout;
|
||||||
|
|
||||||
new j$.QueueRunner(options).run(options.fns, 0);
|
new j$.QueueRunner(options).run(options.fns, 0);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -6,6 +6,11 @@ getJasmineRequireObj().QueueRunner = function() {
|
|||||||
this.clearStack = attrs.clearStack || function(fn) {fn();};
|
this.clearStack = attrs.clearStack || function(fn) {fn();};
|
||||||
this.onException = attrs.onException || function() {};
|
this.onException = attrs.onException || function() {};
|
||||||
this.catchException = attrs.catchException || function() { return true; };
|
this.catchException = attrs.catchException || function() { return true; };
|
||||||
|
|
||||||
|
this.timer = attrs.realTimer;
|
||||||
|
this.asyncSpecTimeout = attrs.asyncSpecTimeout || 60000;
|
||||||
|
|
||||||
|
this.leaf = attrs.leaf || false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QueueRunner.prototype.execute = function() {
|
QueueRunner.prototype.execute = function() {
|
||||||
@@ -16,16 +21,23 @@ getJasmineRequireObj().QueueRunner = function() {
|
|||||||
var length = fns.length,
|
var length = fns.length,
|
||||||
self = this,
|
self = this,
|
||||||
iterativeIndex;
|
iterativeIndex;
|
||||||
|
|
||||||
|
var nextIteration = function(currentIteration) {
|
||||||
|
return function() {
|
||||||
|
self.run(fns, currentIteration + 1);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
for(iterativeIndex = recursiveIndex; iterativeIndex < length; iterativeIndex++) {
|
for(iterativeIndex = recursiveIndex; iterativeIndex < length; iterativeIndex++) {
|
||||||
var fn = fns[iterativeIndex];
|
var fn = fns[iterativeIndex];
|
||||||
|
|
||||||
if (fn.length > 0) {
|
if (fn.length > 0) {
|
||||||
var attemptSuccessful = attempt(function() {
|
var attemptSuccessful = attempt(fn, nextIteration(iterativeIndex));
|
||||||
fn.call(self, function() { self.run(fns, iterativeIndex + 1); });
|
|
||||||
});
|
|
||||||
|
|
||||||
if(attemptSuccessful) {
|
if(attemptSuccessful) {
|
||||||
return;
|
return;
|
||||||
|
} else {
|
||||||
|
// TODO cleanup the timeout ?
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
attempt(function() { fn.call(self); });
|
attempt(function() { fn.call(self); });
|
||||||
@@ -38,9 +50,24 @@ getJasmineRequireObj().QueueRunner = function() {
|
|||||||
this.clearStack(this.onComplete);
|
this.clearStack(this.onComplete);
|
||||||
}
|
}
|
||||||
|
|
||||||
function attempt(fn) {
|
function attempt(fn, done) {
|
||||||
|
var timeout;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
fn();
|
if (self.leaf) {
|
||||||
|
timeout = self.timer.setTimeout(function() {
|
||||||
|
self.onException(new Error("timeout"));
|
||||||
|
done();
|
||||||
|
}, self.asyncSpecTimeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
var next = function() {
|
||||||
|
if (self.leaf) { self.timer.clearTimeout(timeout); }
|
||||||
|
done();
|
||||||
|
};
|
||||||
|
|
||||||
|
fn.call(self, next);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
self.onException(e);
|
self.onException(e);
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ getJasmineRequireObj().Spec = function() {
|
|||||||
|
|
||||||
this.queueRunner({
|
this.queueRunner({
|
||||||
fns: allFns,
|
fns: allFns,
|
||||||
|
leaf: true,
|
||||||
onException: function(e) {
|
onException: function(e) {
|
||||||
if (Spec.isPendingSpecException(e)) {
|
if (Spec.isPendingSpecException(e)) {
|
||||||
self.pend();
|
self.pend();
|
||||||
|
|||||||
Reference in New Issue
Block a user