Slight refactoring of clearing timeouts when an exception is thrown
This commit is contained in:
@@ -266,7 +266,8 @@ getJasmineRequireObj().Spec = function(j$) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Spec.prototype.execute = function(onComplete) {
|
Spec.prototype.execute = function(onComplete) {
|
||||||
var self = this;
|
var self = this,
|
||||||
|
timeout;
|
||||||
|
|
||||||
this.onStart(this);
|
this.onStart(this);
|
||||||
|
|
||||||
@@ -277,26 +278,25 @@ getJasmineRequireObj().Spec = function(j$) {
|
|||||||
|
|
||||||
function timeoutable(fn) {
|
function timeoutable(fn) {
|
||||||
return function(done) {
|
return function(done) {
|
||||||
var timeout = Function.prototype.apply.apply(self.timer.setTimeout, [j$.getGlobal(), [function() {
|
timeout = Function.prototype.apply.apply(self.timer.setTimeout, [j$.getGlobal(), [function() {
|
||||||
onException(new Error('Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.'));
|
onException(new Error('Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.'));
|
||||||
done();
|
done();
|
||||||
}, j$.DEFAULT_TIMEOUT_INTERVAL]]);
|
}, j$.DEFAULT_TIMEOUT_INTERVAL]]);
|
||||||
|
|
||||||
var callDone = function() {
|
var callDone = function() {
|
||||||
Function.prototype.apply.apply(self.timer.clearTimeout, [j$.getGlobal(), [timeout]]);
|
clearTimeoutable();
|
||||||
done();
|
done();
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
fn.call(this, callDone); //TODO: do we care about more than 1 arg?
|
||||||
fn.call(this, callDone); //TODO: do we care about more than 1 arg?
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
onException(e);
|
|
||||||
callDone();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function clearTimeoutable() {
|
||||||
|
Function.prototype.apply.apply(self.timer.clearTimeout, [j$.getGlobal(), [timeout]]);
|
||||||
|
timeout = void 0;
|
||||||
|
}
|
||||||
|
|
||||||
var befores = this.beforeFns() || [],
|
var befores = this.beforeFns() || [],
|
||||||
afters = this.afterFns() || [],
|
afters = this.afterFns() || [],
|
||||||
thisOne = (this.fn.length) ? timeoutable(this.fn) : this.fn;
|
thisOne = (this.fn.length) ? timeoutable(this.fn) : this.fn;
|
||||||
@@ -309,6 +309,7 @@ getJasmineRequireObj().Spec = function(j$) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
function onException(e) {
|
function onException(e) {
|
||||||
|
clearTimeoutable();
|
||||||
if (Spec.isPendingSpecException(e)) {
|
if (Spec.isPendingSpecException(e)) {
|
||||||
self.pend();
|
self.pend();
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -218,42 +218,24 @@ describe("Spec", function() {
|
|||||||
expect(specNameSpy.calls.mostRecent().args[0].id).toEqual(spec.id);
|
expect(specNameSpy.calls.mostRecent().args[0].id).toEqual(spec.id);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("resets the timeout timer when an async spec throws an exception", function(done) {
|
it("resets the timeout timer when an async spec throws an exception", function() {
|
||||||
var handleException = jasmine.createSpy('exception handler'),
|
var queueRunnerSpy = jasmine.createSpy('queueRunner'),
|
||||||
|
clearTimeoutSpy = jasmine.createSpy('clear timeout'),
|
||||||
spec = new j$.Spec({
|
spec = new j$.Spec({
|
||||||
fn: function(done) { throw new Error('test'); },
|
fn: function(done) { },
|
||||||
catchExceptions: function() { return true; },
|
catchExceptions: function() { return true; },
|
||||||
expectationResultFactory: handleException,
|
|
||||||
timer: {
|
timer: {
|
||||||
// Force timeout to 0 to postpone execution to next tick
|
setTimeout: function () { return 920; },
|
||||||
// without using the default 5s interval
|
clearTimeout: clearTimeoutSpy
|
||||||
setTimeout: function (fn) { return setTimeout(fn, 0); },
|
|
||||||
clearTimeout: clearTimeout
|
|
||||||
},
|
},
|
||||||
queueRunnerFactory: function (attrs) {
|
queueRunnerFactory: queueRunnerSpy
|
||||||
// Fake the "run" method of a regular queue runner
|
|
||||||
// for an async spec.
|
|
||||||
try {
|
|
||||||
attrs.fns[0].call({}, function () {});
|
|
||||||
} catch (e) {
|
|
||||||
handleException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Spec execution will create the timeout timer that would report
|
|
||||||
// a failure on next tick unless it gets properly cleared before
|
|
||||||
// the end of this tick.
|
|
||||||
spec.execute();
|
spec.execute();
|
||||||
|
queueRunnerSpy.calls.mostRecent().args[0].fns[0]();
|
||||||
|
queueRunnerSpy.calls.mostRecent().args[0].onException(new Error());
|
||||||
|
|
||||||
// Run the expect clause on next tick to detect the case when the
|
expect(clearTimeoutSpy).toHaveBeenCalledWith(920);
|
||||||
// timeout timer was not properly reset. The exception handler is
|
|
||||||
// called once when the error is thrown. It is called twice when
|
|
||||||
// the timeout timer is not properly reset.
|
|
||||||
setTimeout(function () {
|
|
||||||
expect(handleException.calls.count()).toEqual(1);
|
|
||||||
done();
|
|
||||||
}, 0);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("when a spec is marked pending during execution", function() {
|
describe("when a spec is marked pending during execution", function() {
|
||||||
|
|||||||
@@ -41,7 +41,8 @@ getJasmineRequireObj().Spec = function(j$) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Spec.prototype.execute = function(onComplete) {
|
Spec.prototype.execute = function(onComplete) {
|
||||||
var self = this;
|
var self = this,
|
||||||
|
timeout;
|
||||||
|
|
||||||
this.onStart(this);
|
this.onStart(this);
|
||||||
|
|
||||||
@@ -52,26 +53,25 @@ getJasmineRequireObj().Spec = function(j$) {
|
|||||||
|
|
||||||
function timeoutable(fn) {
|
function timeoutable(fn) {
|
||||||
return function(done) {
|
return function(done) {
|
||||||
var timeout = Function.prototype.apply.apply(self.timer.setTimeout, [j$.getGlobal(), [function() {
|
timeout = Function.prototype.apply.apply(self.timer.setTimeout, [j$.getGlobal(), [function() {
|
||||||
onException(new Error('Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.'));
|
onException(new Error('Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.'));
|
||||||
done();
|
done();
|
||||||
}, j$.DEFAULT_TIMEOUT_INTERVAL]]);
|
}, j$.DEFAULT_TIMEOUT_INTERVAL]]);
|
||||||
|
|
||||||
var callDone = function() {
|
var callDone = function() {
|
||||||
Function.prototype.apply.apply(self.timer.clearTimeout, [j$.getGlobal(), [timeout]]);
|
clearTimeoutable();
|
||||||
done();
|
done();
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
fn.call(this, callDone); //TODO: do we care about more than 1 arg?
|
||||||
fn.call(this, callDone); //TODO: do we care about more than 1 arg?
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
onException(e);
|
|
||||||
callDone();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function clearTimeoutable() {
|
||||||
|
Function.prototype.apply.apply(self.timer.clearTimeout, [j$.getGlobal(), [timeout]]);
|
||||||
|
timeout = void 0;
|
||||||
|
}
|
||||||
|
|
||||||
var befores = this.beforeFns() || [],
|
var befores = this.beforeFns() || [],
|
||||||
afters = this.afterFns() || [],
|
afters = this.afterFns() || [],
|
||||||
thisOne = (this.fn.length) ? timeoutable(this.fn) : this.fn;
|
thisOne = (this.fn.length) ? timeoutable(this.fn) : this.fn;
|
||||||
@@ -84,6 +84,7 @@ getJasmineRequireObj().Spec = function(j$) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
function onException(e) {
|
function onException(e) {
|
||||||
|
clearTimeoutable();
|
||||||
if (Spec.isPendingSpecException(e)) {
|
if (Spec.isPendingSpecException(e)) {
|
||||||
self.pend();
|
self.pend();
|
||||||
return;
|
return;
|
||||||
|
|||||||
Reference in New Issue
Block a user