Slight refactoring of clearing timeouts when an exception is thrown

This commit is contained in:
Sheel Choksi
2013-11-14 20:48:28 -08:00
parent 72e9851217
commit c888b0c1b8
3 changed files with 32 additions and 48 deletions

View File

@@ -266,7 +266,8 @@ getJasmineRequireObj().Spec = function(j$) {
};
Spec.prototype.execute = function(onComplete) {
var self = this;
var self = this,
timeout;
this.onStart(this);
@@ -277,26 +278,25 @@ getJasmineRequireObj().Spec = function(j$) {
function timeoutable(fn) {
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.'));
done();
}, j$.DEFAULT_TIMEOUT_INTERVAL]]);
var callDone = function() {
Function.prototype.apply.apply(self.timer.clearTimeout, [j$.getGlobal(), [timeout]]);
clearTimeoutable();
done();
};
try {
fn.call(this, callDone); //TODO: do we care about more than 1 arg?
}
catch (e) {
onException(e);
callDone();
}
fn.call(this, callDone); //TODO: do we care about more than 1 arg?
};
}
function clearTimeoutable() {
Function.prototype.apply.apply(self.timer.clearTimeout, [j$.getGlobal(), [timeout]]);
timeout = void 0;
}
var befores = this.beforeFns() || [],
afters = this.afterFns() || [],
thisOne = (this.fn.length) ? timeoutable(this.fn) : this.fn;
@@ -309,6 +309,7 @@ getJasmineRequireObj().Spec = function(j$) {
});
function onException(e) {
clearTimeoutable();
if (Spec.isPendingSpecException(e)) {
self.pend();
return;

View File

@@ -218,42 +218,24 @@ describe("Spec", function() {
expect(specNameSpy.calls.mostRecent().args[0].id).toEqual(spec.id);
});
it("resets the timeout timer when an async spec throws an exception", function(done) {
var handleException = jasmine.createSpy('exception handler'),
it("resets the timeout timer when an async spec throws an exception", function() {
var queueRunnerSpy = jasmine.createSpy('queueRunner'),
clearTimeoutSpy = jasmine.createSpy('clear timeout'),
spec = new j$.Spec({
fn: function(done) { throw new Error('test'); },
fn: function(done) { },
catchExceptions: function() { return true; },
expectationResultFactory: handleException,
timer: {
// Force timeout to 0 to postpone execution to next tick
// without using the default 5s interval
setTimeout: function (fn) { return setTimeout(fn, 0); },
clearTimeout: clearTimeout
setTimeout: function () { return 920; },
clearTimeout: clearTimeoutSpy
},
queueRunnerFactory: function (attrs) {
// Fake the "run" method of a regular queue runner
// for an async spec.
try {
attrs.fns[0].call({}, function () {});
} catch (e) {
handleException(e);
}
}
queueRunnerFactory: queueRunnerSpy
});
// 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();
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
// 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);
expect(clearTimeoutSpy).toHaveBeenCalledWith(920);
});
describe("when a spec is marked pending during execution", function() {

View File

@@ -41,7 +41,8 @@ getJasmineRequireObj().Spec = function(j$) {
};
Spec.prototype.execute = function(onComplete) {
var self = this;
var self = this,
timeout;
this.onStart(this);
@@ -52,26 +53,25 @@ getJasmineRequireObj().Spec = function(j$) {
function timeoutable(fn) {
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.'));
done();
}, j$.DEFAULT_TIMEOUT_INTERVAL]]);
var callDone = function() {
Function.prototype.apply.apply(self.timer.clearTimeout, [j$.getGlobal(), [timeout]]);
clearTimeoutable();
done();
};
try {
fn.call(this, callDone); //TODO: do we care about more than 1 arg?
}
catch (e) {
onException(e);
callDone();
}
fn.call(this, callDone); //TODO: do we care about more than 1 arg?
};
}
function clearTimeoutable() {
Function.prototype.apply.apply(self.timer.clearTimeout, [j$.getGlobal(), [timeout]]);
timeout = void 0;
}
var befores = this.beforeFns() || [],
afters = this.afterFns() || [],
thisOne = (this.fn.length) ? timeoutable(this.fn) : this.fn;
@@ -84,6 +84,7 @@ getJasmineRequireObj().Spec = function(j$) {
});
function onException(e) {
clearTimeoutable();
if (Spec.isPendingSpecException(e)) {
self.pend();
return;