beforeAll/afterAll can be timed out and errors are applied to all children specs

This commit is contained in:
Gregg Van Hove and Sheel Choksi
2014-03-03 16:13:59 -08:00
parent e17a2cb1e0
commit 52026fb0f7
8 changed files with 183 additions and 148 deletions

View File

@@ -161,14 +161,14 @@ getJasmineRequireObj().Env = function(j$) {
var allFns = [];
for(var i = 0; i < runnablesToRun.length; i++) {
var runnable = runnableLookupTable[runnablesToRun[i]];
allFns.push((function(runnable) { return function(done) { runnable.execute(done); }; })(runnable));
allFns.push((function(runnable) { return { fn: function(done) { runnable.execute(done); } }; })(runnable));
}
reporter.jasmineStarted({
totalSpecsDefined: totalSpecsDefined
});
queueRunnerFactory({fns: allFns, onComplete: reporter.jasmineDone});
queueRunnerFactory({queueableFns: allFns, onComplete: reporter.jasmineDone});
};
this.addReporter = function(reporterToAdd) {
@@ -273,7 +273,7 @@ getJasmineRequireObj().Env = function(j$) {
expectationResultFactory: expectationResultFactory,
queueRunnerFactory: queueRunnerFactory,
userContext: function() { return suite.clonedSharedUserContext(); },
fn: fn
queueableFn: { fn: fn, timeout: function() { return j$.DEFAULT_TIMEOUT_INTERVAL; } }
});
runnableLookupTable[spec.id] = spec;
@@ -322,19 +322,19 @@ getJasmineRequireObj().Env = function(j$) {
};
this.beforeEach = function(beforeEachFunction) {
currentSuite.beforeEach(beforeEachFunction);
currentSuite.beforeEach({ fn: beforeEachFunction, timeout: function() { return j$.DEFAULT_TIMEOUT_INTERVAL; } });
};
this.beforeAll = function(beforeAllFunction) {
currentSuite.beforeAll(beforeAllFunction);
currentSuite.beforeAll({ fn: beforeAllFunction, timeout: function() { return j$.DEFAULT_TIMEOUT_INTERVAL; } });
};
this.afterEach = function(afterEachFunction) {
currentSuite.afterEach(afterEachFunction);
currentSuite.afterEach({ fn: afterEachFunction, timeout: function() { return j$.DEFAULT_TIMEOUT_INTERVAL; } });
};
this.afterAll = function(afterAllFunction) {
currentSuite.afterAll(afterAllFunction);
currentSuite.afterAll({ fn: afterAllFunction, timeout: function() { return j$.DEFAULT_TIMEOUT_INTERVAL; } });
};
this.pending = function() {

View File

@@ -11,31 +11,30 @@ getJasmineRequireObj().QueueRunner = function(j$) {
}
function QueueRunner(attrs) {
this.fns = attrs.fns || [];
this.queueableFns = attrs.queueableFns || [];
this.onComplete = attrs.onComplete || function() {};
this.clearStack = attrs.clearStack || function(fn) {fn();};
this.onException = attrs.onException || function() {};
this.catchException = attrs.catchException || function() { return true; };
this.enforceTimeout = attrs.enforceTimeout || function() { return false; };
this.userContext = attrs.userContext || {};
this.timer = attrs.timeout || {setTimeout: setTimeout, clearTimeout: clearTimeout};
}
QueueRunner.prototype.execute = function() {
this.run(this.fns, 0);
this.run(this.queueableFns, 0);
};
QueueRunner.prototype.run = function(fns, recursiveIndex) {
var length = fns.length,
QueueRunner.prototype.run = function(queueableFns, recursiveIndex) {
var length = queueableFns.length,
self = this,
iterativeIndex;
for(iterativeIndex = recursiveIndex; iterativeIndex < length; iterativeIndex++) {
var fn = fns[iterativeIndex];
if (fn.length > 0) {
return attemptAsync(fn);
var queueableFn = queueableFns[iterativeIndex];
if (queueableFn.fn.length > 0) {
return attemptAsync(queueableFn);
} else {
attemptSync(fn);
attemptSync(queueableFn);
}
}
@@ -45,33 +44,33 @@ getJasmineRequireObj().QueueRunner = function(j$) {
this.clearStack(this.onComplete);
}
function attemptSync(fn) {
function attemptSync(queueableFn) {
try {
fn.call(self.userContext);
queueableFn.fn.call(self.userContext);
} catch (e) {
handleException(e);
}
}
function attemptAsync(fn) {
function attemptAsync(queueableFn) {
var clearTimeout = function () {
Function.prototype.apply.apply(self.timer.clearTimeout, [j$.getGlobal(), [timeoutId]]);
},
next = once(function () {
clearTimeout(timeoutId);
self.run(fns, iterativeIndex + 1);
self.run(queueableFns, iterativeIndex + 1);
}),
timeoutId;
if (self.enforceTimeout()) {
if (queueableFn.timeout) {
timeoutId = Function.prototype.apply.apply(self.timer.setTimeout, [j$.getGlobal(), [function() {
self.onException(new Error('Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.'));
next();
}, j$.DEFAULT_TIMEOUT_INTERVAL]]);
}, queueableFn.timeout()]]);
}
try {
fn.call(self.userContext, next);
queueableFn.fn.call(self.userContext, next);
} catch (e) {
handleException(e);
next();

View File

@@ -4,7 +4,7 @@ getJasmineRequireObj().Spec = function(j$) {
this.resultCallback = attrs.resultCallback || function() {};
this.id = attrs.id;
this.description = attrs.description || '';
this.fn = attrs.fn;
this.queueableFn = attrs.queueableFn;
this.beforeFns = attrs.beforeFns || function() { return []; };
this.afterFns = attrs.afterFns || function() { return []; };
this.userContext = attrs.userContext || function() { return {}; };
@@ -15,7 +15,7 @@ getJasmineRequireObj().Spec = function(j$) {
this.queueRunnerFactory = attrs.queueRunnerFactory || function() {};
this.catchingExceptions = attrs.catchingExceptions || function() { return true; };
if (!this.fn) {
if (!this.queueableFn.fn) {
this.pend();
}
@@ -48,31 +48,15 @@ getJasmineRequireObj().Spec = function(j$) {
return;
}
var allFns = this.beforeFns().concat(this.fn).concat(this.afterFns());
var allFns = this.beforeFns().concat(this.queueableFn).concat(this.afterFns());
this.queueRunnerFactory({
fns: allFns,
onException: onException,
queueableFns: allFns,
onException: function() { self.onException.apply(self, arguments); },
onComplete: complete,
enforceTimeout: function() { return true; },
userContext: this.userContext()
});
function onException(e) {
if (Spec.isPendingSpecException(e)) {
self.pend();
return;
}
self.addExpectationResult(false, {
matcherName: '',
passed: false,
expected: '',
actual: '',
error: e
});
}
function complete() {
self.result.status = self.status();
self.resultCallback(self.result);
@@ -83,6 +67,21 @@ getJasmineRequireObj().Spec = function(j$) {
}
};
Spec.prototype.onException = function onException(e) {
if (Spec.isPendingSpecException(e)) {
this.pend();
return;
}
this.addExpectationResult(false, {
matcherName: '',
passed: false,
expected: '',
actual: '',
error: e
});
};
Spec.prototype.disable = function() {
this.disabled = true;
};

View File

@@ -69,25 +69,22 @@ getJasmineRequireObj().Suite = function() {
var allFns = [];
if (this.isExecutable()) {
for (var b = 0; b < this.beforeAllFns.length; b++) {
allFns.push(this.beforeAllFns[b]);
}
allFns = this.beforeAllFns;
for (var i = 0; i < this.children.length; i++) {
allFns.push(wrapChildAsAsync(this.children[i]));
}
for (var a = 0; a < this.afterAllFns.length; a++) {
allFns.push(this.afterAllFns[a]);
}
allFns = allFns.concat(this.afterAllFns);
}
this.onStart(this);
this.queueRunner({
fns: allFns,
queueableFns: allFns,
onComplete: complete,
userContext: this.sharedUserContext()
userContext: this.sharedUserContext(),
onException: function() { self.onException.apply(self, arguments); }
});
function complete() {
@@ -99,7 +96,7 @@ getJasmineRequireObj().Suite = function() {
}
function wrapChildAsAsync(child) {
return function(done) { child.execute(done); };
return { fn: function(done) { child.execute(done); } };
}
};
@@ -126,6 +123,13 @@ getJasmineRequireObj().Suite = function() {
return clone(this.sharedUserContext());
};
Suite.prototype.onException = function() {
for (var i = 0; i < this.children.length; i++) {
var child = this.children[i];
child.onException.apply(child, arguments);
}
};
function clone(obj) {
var clonedObj = {};
for (var prop in obj) {