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

@@ -2,15 +2,15 @@ describe("QueueRunner", function() {
it("runs all the functions it's passed", function() { it("runs all the functions it's passed", function() {
var calls = [], var calls = [],
fn1 = jasmine.createSpy('fn1'), queueableFn1 = { fn: jasmine.createSpy('fn1') },
fn2 = jasmine.createSpy('fn2'), queueableFn2 = { fn: jasmine.createSpy('fn2') },
queueRunner = new j$.QueueRunner({ queueRunner = new j$.QueueRunner({
fns: [fn1, fn2] queueableFns: [queueableFn1, queueableFn2]
}); });
fn1.and.callFake(function() { queueableFn1.fn.and.callFake(function() {
calls.push('fn1'); calls.push('fn1');
}); });
fn2.and.callFake(function() { queueableFn2.fn.and.callFake(function() {
calls.push('fn2'); calls.push('fn2');
}); });
@@ -20,19 +20,19 @@ describe("QueueRunner", function() {
}); });
it("calls each function with a consistent 'this'-- an empty object", function() { it("calls each function with a consistent 'this'-- an empty object", function() {
var fn1 = jasmine.createSpy('fn1'), var queueableFn1 = { fn: jasmine.createSpy('fn1') },
fn2 = jasmine.createSpy('fn2'), queueableFn2 = { fn: jasmine.createSpy('fn2') },
fn3 = function(done) { asyncContext = this; done(); }, queueableFn3 = { fn: function(done) { asyncContext = this; done(); } },
queueRunner = new j$.QueueRunner({ queueRunner = new j$.QueueRunner({
fns: [fn1, fn2, fn3] queueableFns: [queueableFn1, queueableFn2, queueableFn3]
}), }),
asyncContext; asyncContext;
queueRunner.execute(); queueRunner.execute();
var context = fn1.calls.first().object; var context = queueableFn1.fn.calls.first().object;
expect(context).toEqual({}); expect(context).toEqual({});
expect(fn2.calls.first().object).toBe(context); expect(queueableFn2.fn.calls.first().object).toBe(context);
expect(asyncContext).toBe(context); expect(asyncContext).toBe(context);
}); });
@@ -53,20 +53,20 @@ describe("QueueRunner", function() {
beforeCallback = jasmine.createSpy('beforeCallback'), beforeCallback = jasmine.createSpy('beforeCallback'),
fnCallback = jasmine.createSpy('fnCallback'), fnCallback = jasmine.createSpy('fnCallback'),
afterCallback = jasmine.createSpy('afterCallback'), afterCallback = jasmine.createSpy('afterCallback'),
fn1 = function(done) { queueableFn1 = { fn: function(done) {
beforeCallback(); beforeCallback();
setTimeout(done, 100); setTimeout(done, 100);
}, } },
fn2 = function(done) { queueableFn2 = { fn: function(done) {
fnCallback(); fnCallback();
setTimeout(done, 100); setTimeout(done, 100);
}, } },
fn3 = function(done) { queueableFn3 = { fn: function(done) {
afterCallback(); afterCallback();
setTimeout(done, 100); setTimeout(done, 100);
}, } },
queueRunner = new j$.QueueRunner({ queueRunner = new j$.QueueRunner({
fns: [fn1, fn2, fn3], queueableFns: [queueableFn1, queueableFn2, queueableFn3],
onComplete: onComplete onComplete: onComplete
}); });
@@ -94,54 +94,54 @@ describe("QueueRunner", function() {
}); });
it("sets a timeout if requested for asynchronous functions so they don't go on forever", function() { it("sets a timeout if requested for asynchronous functions so they don't go on forever", function() {
var beforeFn = function(done) { }, var timeout = 3,
fn = jasmine.createSpy('fn'), beforeFn = { fn: function(done) { }, timeout: function() { return timeout; } },
queueableFn = { fn: jasmine.createSpy('fn') },
onComplete = jasmine.createSpy('onComplete'), onComplete = jasmine.createSpy('onComplete'),
onException = jasmine.createSpy('onException'), onException = jasmine.createSpy('onException'),
queueRunner = new j$.QueueRunner({ queueRunner = new j$.QueueRunner({
fns: [beforeFn, fn], queueableFns: [beforeFn, queueableFn],
onComplete: onComplete, onComplete: onComplete,
onException: onException, onException: onException
enforceTimeout: function() { return true; }
}); });
queueRunner.execute(); queueRunner.execute();
expect(fn).not.toHaveBeenCalled(); expect(queueableFn.fn).not.toHaveBeenCalled();
jasmine.clock().tick(j$.DEFAULT_TIMEOUT_INTERVAL); jasmine.clock().tick(timeout);
expect(onException).toHaveBeenCalledWith(jasmine.any(Error)); expect(onException).toHaveBeenCalledWith(jasmine.any(Error));
expect(fn).toHaveBeenCalled(); expect(queueableFn.fn).toHaveBeenCalled();
expect(onComplete).toHaveBeenCalled(); expect(onComplete).toHaveBeenCalled();
}); });
it("by default does not set a timeout for asynchronous functions", function() { it("by default does not set a timeout for asynchronous functions", function() {
var beforeFn = function(done) { }, var beforeFn = { fn: function(done) { } },
fn = jasmine.createSpy('fn'), queueableFn = { fn: jasmine.createSpy('fn') },
onComplete = jasmine.createSpy('onComplete'), onComplete = jasmine.createSpy('onComplete'),
onException = jasmine.createSpy('onException'), onException = jasmine.createSpy('onException'),
queueRunner = new j$.QueueRunner({ queueRunner = new j$.QueueRunner({
fns: [beforeFn, fn], queueableFns: [beforeFn, queueableFn],
onComplete: onComplete, onComplete: onComplete,
onException: onException, onException: onException,
}); });
queueRunner.execute(); queueRunner.execute();
expect(fn).not.toHaveBeenCalled(); expect(queueableFn.fn).not.toHaveBeenCalled();
jasmine.clock().tick(j$.DEFAULT_TIMEOUT_INTERVAL); jasmine.clock().tick(j$.DEFAULT_TIMEOUT_INTERVAL);
expect(onException).not.toHaveBeenCalled(); expect(onException).not.toHaveBeenCalled();
expect(fn).not.toHaveBeenCalled(); expect(queueableFn.fn).not.toHaveBeenCalled();
expect(onComplete).not.toHaveBeenCalled(); expect(onComplete).not.toHaveBeenCalled();
}); });
it("clears the timeout when an async function throws an exception, to prevent additional onException calls", function() { it("clears the timeout when an async function throws an exception, to prevent additional onException calls", function() {
var fn = function(done) { throw new Error("error!"); }, var queueableFn = { fn: function(done) { throw new Error("error!"); } },
onComplete = jasmine.createSpy('onComplete'), onComplete = jasmine.createSpy('onComplete'),
onException = jasmine.createSpy('onException'), onException = jasmine.createSpy('onException'),
queueRunner = new j$.QueueRunner({ queueRunner = new j$.QueueRunner({
fns: [fn], queueableFns: [queueableFn],
onComplete: onComplete, onComplete: onComplete,
onException: onException onException: onException
}); });
@@ -156,11 +156,11 @@ describe("QueueRunner", function() {
}); });
it("clears the timeout when the done callback is called", function() { it("clears the timeout when the done callback is called", function() {
var fn = function(done) { done(); }, var queueableFn = { fn: function(done) { done(); } },
onComplete = jasmine.createSpy('onComplete'), onComplete = jasmine.createSpy('onComplete'),
onException = jasmine.createSpy('onException'), onException = jasmine.createSpy('onException'),
queueRunner = new j$.QueueRunner({ queueRunner = new j$.QueueRunner({
fns: [fn], queueableFns: [queueableFn],
onComplete: onComplete, onComplete: onComplete,
onException: onException onException: onException
}); });
@@ -174,39 +174,39 @@ describe("QueueRunner", function() {
}); });
it("only moves to the next spec the first time you call done", function() { it("only moves to the next spec the first time you call done", function() {
var fn = function(done) {done(); done();}, var queueableFn = { fn: function(done) {done(); done();} },
nextFn = jasmine.createSpy('nextFn'); nextQueueableFn = { fn: jasmine.createSpy('nextFn') };
queueRunner = new j$.QueueRunner({ queueRunner = new j$.QueueRunner({
fns: [fn, nextFn] queueableFns: [queueableFn, nextQueueableFn]
}); });
queueRunner.execute(); queueRunner.execute();
expect(nextFn.calls.count()).toEqual(1); expect(nextQueueableFn.fn.calls.count()).toEqual(1);
}); });
it("does not move to the next spec if done is called after an exception has ended the spec", function() { it("does not move to the next spec if done is called after an exception has ended the spec", function() {
var fn = function(done) { var queueableFn = { fn: function(done) {
setTimeout(done, 1); setTimeout(done, 1);
throw new Error('error!'); throw new Error('error!');
}, } },
nextFn = jasmine.createSpy('nextFn'); nextQueueableFn = { fn: jasmine.createSpy('nextFn') };
queueRunner = new j$.QueueRunner({ queueRunner = new j$.QueueRunner({
fns: [fn, nextFn] queueableFns: [queueableFn, nextQueueableFn]
}); });
queueRunner.execute(); queueRunner.execute();
jasmine.clock().tick(1); jasmine.clock().tick(1);
expect(nextFn.calls.count()).toEqual(1); expect(nextQueueableFn.fn.calls.count()).toEqual(1);
}); });
}); });
it("calls an exception handler when an exception is thrown in a fn", function() { it("calls an exception handler when an exception is thrown in a fn", function() {
var fn = function() { var queueableFn = { fn: function() {
throw new Error('fake error'); throw new Error('fake error');
}, } },
exceptionCallback = jasmine.createSpy('exception callback'), exceptionCallback = jasmine.createSpy('exception callback'),
queueRunner = new j$.QueueRunner({ queueRunner = new j$.QueueRunner({
fns: [fn], queueableFns: [queueableFn],
onException: exceptionCallback onException: exceptionCallback
}); });
@@ -216,33 +216,35 @@ describe("QueueRunner", function() {
}); });
it("rethrows an exception if told to", function() { it("rethrows an exception if told to", function() {
var fn = function() { var queueableFn = { fn: function() {
throw new Error('fake error'); throw new Error('fake error');
}, } },
queueRunner = new j$.QueueRunner({ queueRunner = new j$.QueueRunner({
fns: [fn], queueableFns: [queueableFn],
catchException: function(e) { return false; } catchException: function(e) { return false; }
}); });
expect(queueRunner.execute).toThrow(); expect(function() {
queueRunner.execute();
}).toThrowError('fake error');
}); });
it("continues running the functions even after an exception is thrown in an async spec", function() { it("continues running the functions even after an exception is thrown in an async spec", function() {
var fn = function(done) { throw new Error("error"); }, var queueableFn = { fn: function(done) { throw new Error("error"); } },
nextFn = jasmine.createSpy("nextFunction"), nextQueueableFn = { fn: jasmine.createSpy("nextFunction") },
queueRunner = new j$.QueueRunner({ queueRunner = new j$.QueueRunner({
fns: [fn, nextFn] queueableFns: [queueableFn, nextQueueableFn]
}); });
queueRunner.execute(); queueRunner.execute();
expect(nextFn).toHaveBeenCalled(); expect(nextQueueableFn.fn).toHaveBeenCalled();
}); });
it("calls a provided complete callback when done", function() { it("calls a provided complete callback when done", function() {
var fn = jasmine.createSpy('fn'), var queueableFn = { fn: jasmine.createSpy('fn') },
completeCallback = jasmine.createSpy('completeCallback'), completeCallback = jasmine.createSpy('completeCallback'),
queueRunner = new j$.QueueRunner({ queueRunner = new j$.QueueRunner({
fns: [fn], queueableFns: [queueableFn],
onComplete: completeCallback onComplete: completeCallback
}); });
@@ -252,12 +254,12 @@ describe("QueueRunner", function() {
}); });
it("calls a provided stack clearing function when done", function() { it("calls a provided stack clearing function when done", function() {
var asyncFn = function(done) { done() }, var asyncFn = { fn: function(done) { done() } },
afterFn = jasmine.createSpy('afterFn'), afterFn = { fn: jasmine.createSpy('afterFn') },
completeCallback = jasmine.createSpy('completeCallback'), completeCallback = jasmine.createSpy('completeCallback'),
clearStack = jasmine.createSpy('clearStack'), clearStack = jasmine.createSpy('clearStack'),
queueRunner = new j$.QueueRunner({ queueRunner = new j$.QueueRunner({
fns: [asyncFn, afterFn], queueableFns: [asyncFn, afterFn],
clearStack: clearStack, clearStack: clearStack,
onComplete: completeCallback onComplete: completeCallback
}); });
@@ -265,7 +267,7 @@ describe("QueueRunner", function() {
clearStack.and.callFake(function(fn) { fn(); }); clearStack.and.callFake(function(fn) { fn(); });
queueRunner.execute(); queueRunner.execute();
expect(afterFn).toHaveBeenCalled(); expect(afterFn.fn).toHaveBeenCalled();
expect(clearStack).toHaveBeenCalledWith(completeCallback); expect(clearStack).toHaveBeenCalledWith(completeCallback);
}); });
}); });

View File

@@ -29,7 +29,7 @@ describe("Spec", function() {
spec = new j$.Spec({ spec = new j$.Spec({
description: 'my test', description: 'my test',
id: 'some-id', id: 'some-id',
fn: function() {}, queueableFn: { fn: function() {} },
queueRunnerFactory: fakeQueueRunner queueRunnerFactory: fakeQueueRunner
}); });
@@ -44,7 +44,7 @@ describe("Spec", function() {
spec = new j$.Spec({ spec = new j$.Spec({
id: 123, id: 123,
description: 'foo bar', description: 'foo bar',
fn: function() {}, queueableFn: { fn: function() {} },
onStart: startCallback, onStart: startCallback,
queueRunnerFactory: fakeQueueRunner queueRunnerFactory: fakeQueueRunner
}); });
@@ -66,7 +66,7 @@ describe("Spec", function() {
expect(beforesWereCalled).toBe(false); expect(beforesWereCalled).toBe(false);
}), }),
spec = new j$.Spec({ spec = new j$.Spec({
fn: function() {}, queueableFn: { fn: function() {} },
beforeFns: function() { beforeFns: function() {
return [function() { return [function() {
beforesWereCalled = true beforesWereCalled = true
@@ -85,12 +85,12 @@ describe("Spec", function() {
var fakeQueueRunner = jasmine.createSpy('fakeQueueRunner'), var fakeQueueRunner = jasmine.createSpy('fakeQueueRunner'),
before = jasmine.createSpy('before'), before = jasmine.createSpy('before'),
after = jasmine.createSpy('after'), after = jasmine.createSpy('after'),
fn = jasmine.createSpy('test body').and.callFake(function() { queueableFn = { fn: jasmine.createSpy('test body').and.callFake(function() {
expect(before).toHaveBeenCalled(); expect(before).toHaveBeenCalled();
expect(after).not.toHaveBeenCalled(); expect(after).not.toHaveBeenCalled();
}), }) },
spec = new j$.Spec({ spec = new j$.Spec({
fn: fn, queueableFn: queueableFn,
beforeFns: function() { beforeFns: function() {
return [before] return [before]
}, },
@@ -102,8 +102,8 @@ describe("Spec", function() {
spec.execute(); spec.execute();
var allSpecFns = fakeQueueRunner.calls.mostRecent().args[0].fns; var allSpecFns = fakeQueueRunner.calls.mostRecent().args[0].queueableFns;
expect(allSpecFns).toEqual([before, fn, after]); expect(allSpecFns).toEqual([before, queueableFn, after]);
}); });
it("is marked pending if created without a function body", function() { it("is marked pending if created without a function body", function() {
@@ -113,7 +113,7 @@ describe("Spec", function() {
resultCallback = jasmine.createSpy('resultCallback'), resultCallback = jasmine.createSpy('resultCallback'),
spec = new j$.Spec({ spec = new j$.Spec({
onStart: startCallback, onStart: startCallback,
fn: null, queueableFn: { fn: null },
resultCallback: resultCallback, resultCallback: resultCallback,
queueRunnerFactory: fakeQueueRunner queueRunnerFactory: fakeQueueRunner
}); });
@@ -129,7 +129,7 @@ describe("Spec", function() {
resultCallback = jasmine.createSpy('resultCallback'), resultCallback = jasmine.createSpy('resultCallback'),
spec = new j$.Spec({ spec = new j$.Spec({
onStart:startCallback, onStart:startCallback,
fn: specBody, queueableFn: { fn: specBody },
resultCallback: resultCallback, resultCallback: resultCallback,
queueRunnerFactory: fakeQueueRunner queueRunnerFactory: fakeQueueRunner
}); });
@@ -158,7 +158,8 @@ describe("Spec", function() {
getSpecName: function() { getSpecName: function() {
return "a suite with a spec" return "a suite with a spec"
}, },
queueRunnerFactory: fakeQueueRunner queueRunnerFactory: fakeQueueRunner,
queueableFn: { fn: null }
}); });
spec.pend(); spec.pend();
@@ -182,7 +183,7 @@ describe("Spec", function() {
it("should call the done callback on execution complete", function() { it("should call the done callback on execution complete", function() {
var done = jasmine.createSpy('done callback'), var done = jasmine.createSpy('done callback'),
spec = new j$.Spec({ spec = new j$.Spec({
fn: function() {}, queueableFn: { fn: function() {} },
catchExceptions: function() { return false; }, catchExceptions: function() { return false; },
resultCallback: function() {}, resultCallback: function() {},
queueRunnerFactory: function(attrs) { attrs.onComplete(); } queueRunnerFactory: function(attrs) { attrs.onComplete(); }
@@ -194,18 +195,18 @@ describe("Spec", function() {
}); });
it("#status returns passing by default", function() { it("#status returns passing by default", function() {
var spec = new j$.Spec({fn: jasmine.createSpy("spec body")}); var spec = new j$.Spec({queueableFn: { fn: jasmine.createSpy("spec body")} });
expect(spec.status()).toEqual('passed'); expect(spec.status()).toEqual('passed');
}); });
it("#status returns passed if all expectations in the spec have passed", function() { it("#status returns passed if all expectations in the spec have passed", function() {
var spec = new j$.Spec({fn: jasmine.createSpy("spec body")}); var spec = new j$.Spec({queueableFn: { fn: jasmine.createSpy("spec body")} });
spec.addExpectationResult(true); spec.addExpectationResult(true);
expect(spec.status()).toBe('passed'); expect(spec.status()).toBe('passed');
}); });
it("#status returns failed if any expectations in the spec have failed", function() { it("#status returns failed if any expectations in the spec have failed", function() {
var spec = new j$.Spec({ fn: jasmine.createSpy("spec body") }); var spec = new j$.Spec({queueableFn: { fn: jasmine.createSpy("spec body") } });
spec.addExpectationResult(true); spec.addExpectationResult(true);
spec.addExpectationResult(false); spec.addExpectationResult(false);
expect(spec.status()).toBe('failed'); expect(spec.status()).toBe('failed');
@@ -215,7 +216,8 @@ describe("Spec", function() {
var specNameSpy = jasmine.createSpy('specNameSpy').and.returnValue('expected val'); var specNameSpy = jasmine.createSpy('specNameSpy').and.returnValue('expected val');
var spec = new j$.Spec({ var spec = new j$.Spec({
getSpecName: specNameSpy getSpecName: specNameSpy,
queueableFn: { fn: null }
}); });
expect(spec.getFullName()).toBe('expected val'); expect(spec.getFullName()).toBe('expected val');
@@ -230,7 +232,7 @@ describe("Spec", function() {
spec = new j$.Spec({ spec = new j$.Spec({
description: 'my test', description: 'my test',
id: 'some-id', id: 'some-id',
fn: function() { }, queueableFn: { fn: function() { } },
queueRunnerFactory: fakeQueueRunner queueRunnerFactory: fakeQueueRunner
}); });

View File

@@ -69,7 +69,7 @@ describe("Suite", function() {
suite.addChild(fakeIt); suite.addChild(fakeIt);
suite.execute(); suite.execute();
var suiteFns = fakeQueueRunner.calls.mostRecent().args[0].fns; var suiteFns = fakeQueueRunner.calls.mostRecent().args[0].queueableFns;
suiteFns[0](); suiteFns[0]();
expect(firstBefore).toHaveBeenCalled(); expect(firstBefore).toHaveBeenCalled();
@@ -109,7 +109,7 @@ describe("Suite", function() {
suite.addChild(fakeIt); suite.addChild(fakeIt);
suite.execute(); suite.execute();
var suiteFns = fakeQueueRunner.calls.mostRecent().args[0].fns; var suiteFns = fakeQueueRunner.calls.mostRecent().args[0].queueableFns;
suiteFns[1](); suiteFns[1]();
expect(firstAfter).toHaveBeenCalled(); expect(firstAfter).toHaveBeenCalled();
@@ -154,8 +154,8 @@ describe("Suite", function() {
execute: jasmine.createSpy('fakeSpec1'), execute: jasmine.createSpy('fakeSpec1'),
isExecutable: function() { return true; } isExecutable: function() { return true; }
}, },
beforeAllFn = jasmine.createSpy('beforeAll'), beforeAllFn = { fn: jasmine.createSpy('beforeAll') },
afterAllFn = jasmine.createSpy('afterAll'); afterAllFn = { fn: jasmine.createSpy('afterAll') };
spyOn(suite, "execute"); spyOn(suite, "execute");
@@ -166,16 +166,16 @@ describe("Suite", function() {
parentSuite.execute(parentSuiteDone); parentSuite.execute(parentSuiteDone);
var parentSuiteFns = fakeQueueRunnerForParent.calls.mostRecent().args[0].fns; var parentSuiteFns = fakeQueueRunnerForParent.calls.mostRecent().args[0].queueableFns;
parentSuiteFns[0](); parentSuiteFns[0].fn();
expect(beforeAllFn).toHaveBeenCalled(); expect(beforeAllFn.fn).toHaveBeenCalled();
parentSuiteFns[1](); parentSuiteFns[1].fn();
expect(fakeSpec1.execute).toHaveBeenCalled(); expect(fakeSpec1.execute).toHaveBeenCalled();
parentSuiteFns[2](); parentSuiteFns[2].fn();
expect(suite.execute).toHaveBeenCalled(); expect(suite.execute).toHaveBeenCalled();
parentSuiteFns[3](); parentSuiteFns[3].fn();
expect(afterAllFn).toHaveBeenCalled(); expect(afterAllFn.fn).toHaveBeenCalled();
}); });
it("does not run beforeAll or afterAll if there are no child specs to run", function() { it("does not run beforeAll or afterAll if there are no child specs to run", function() {
@@ -193,8 +193,8 @@ describe("Suite", function() {
queueRunner: fakeQueueRunnerForChild, queueRunner: fakeQueueRunnerForChild,
parentSuite: parentSuite parentSuite: parentSuite
}), }),
spec1 = new j$.Spec({expectationFactory: function() {}}), spec1 = new j$.Spec({expectationFactory: function() {}, queueableFn: {}}),
spec2 = new j$.Spec({expectationFactory: function() {}}), spec2 = new j$.Spec({expectationFactory: function() {}, queueableFn: {}}),
beforeAllFn = jasmine.createSpy('beforeAll'), beforeAllFn = jasmine.createSpy('beforeAll'),
afterAllFn = jasmine.createSpy('afterAll'); afterAllFn = jasmine.createSpy('afterAll');
@@ -203,7 +203,7 @@ describe("Suite", function() {
childSuite.addChild(spec1); childSuite.addChild(spec1);
parentSuite.execute(); parentSuite.execute();
expect(fakeQueueRunnerForParent).toHaveBeenCalledWith(jasmine.objectContaining({fns: []})); expect(fakeQueueRunnerForParent).toHaveBeenCalledWith(jasmine.objectContaining({queueableFns: []}));
}); });
it("calls a provided onStart callback when starting", function() { it("calls a provided onStart callback when starting", function() {

View File

@@ -414,11 +414,11 @@ describe("Env integration", function() {
beforeEach(function() { beforeEach(function() {
originalTimeout = j$.DEFAULT_TIMEOUT_INTERVAL; originalTimeout = j$.DEFAULT_TIMEOUT_INTERVAL;
jasmine.getEnv().clock.install(); jasmine.clock().install();
}); });
afterEach(function() { afterEach(function() {
jasmine.getEnv().clock.uninstall(); jasmine.clock().uninstall();
j$.DEFAULT_TIMEOUT_INTERVAL = originalTimeout; j$.DEFAULT_TIMEOUT_INTERVAL = originalTimeout;
}); });
@@ -440,7 +440,36 @@ describe("Env integration", function() {
env.it("async spec that doesn't call done", function(underTestCallback) { env.it("async spec that doesn't call done", function(underTestCallback) {
env.expect(true).toBeTruthy(); env.expect(true).toBeTruthy();
jasmine.getEnv().clock.tick(8416); jasmine.clock().tick(8416);
});
env.execute();
});
it("should wait a specified interval before failing beforeAll's and their associated specs that haven't called done", function(done) {
var env = new j$.Env(),
reporter = jasmine.createSpyObj('fakeReporter', [ "specDone", "jasmineDone" ]);
reporter.jasmineDone.and.callFake(function() {
expect(reporter.specDone.calls.count()).toEqual(2);
expect(reporter.specDone.calls.argsFor(0)[0]).toEqual(jasmine.objectContaining({status: 'failed'}));
expect(reporter.specDone.calls.argsFor(1)[0]).toEqual(jasmine.objectContaining({status: 'failed'}));
done();
});
env.addReporter(reporter);
j$.DEFAULT_TIMEOUT_INTERVAL = 1290;
env.beforeAll(function(done) {
jasmine.clock().tick(1290);
});
env.it("spec that will be failed", function() {
});
env.describe("nesting", function() {
env.it("another spec to fail", function() {
});
}); });
env.execute(); env.execute();

View File

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

View File

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

View File

@@ -4,7 +4,7 @@ getJasmineRequireObj().Spec = function(j$) {
this.resultCallback = attrs.resultCallback || function() {}; this.resultCallback = attrs.resultCallback || function() {};
this.id = attrs.id; this.id = attrs.id;
this.description = attrs.description || ''; this.description = attrs.description || '';
this.fn = attrs.fn; this.queueableFn = attrs.queueableFn;
this.beforeFns = attrs.beforeFns || function() { return []; }; this.beforeFns = attrs.beforeFns || function() { return []; };
this.afterFns = attrs.afterFns || function() { return []; }; this.afterFns = attrs.afterFns || function() { return []; };
this.userContext = attrs.userContext || function() { return {}; }; this.userContext = attrs.userContext || function() { return {}; };
@@ -15,7 +15,7 @@ getJasmineRequireObj().Spec = function(j$) {
this.queueRunnerFactory = attrs.queueRunnerFactory || function() {}; this.queueRunnerFactory = attrs.queueRunnerFactory || function() {};
this.catchingExceptions = attrs.catchingExceptions || function() { return true; }; this.catchingExceptions = attrs.catchingExceptions || function() { return true; };
if (!this.fn) { if (!this.queueableFn.fn) {
this.pend(); this.pend();
} }
@@ -48,31 +48,15 @@ getJasmineRequireObj().Spec = function(j$) {
return; return;
} }
var allFns = this.beforeFns().concat(this.fn).concat(this.afterFns()); var allFns = this.beforeFns().concat(this.queueableFn).concat(this.afterFns());
this.queueRunnerFactory({ this.queueRunnerFactory({
fns: allFns, queueableFns: allFns,
onException: onException, onException: function() { self.onException.apply(self, arguments); },
onComplete: complete, onComplete: complete,
enforceTimeout: function() { return true; },
userContext: this.userContext() 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() { function complete() {
self.result.status = self.status(); self.result.status = self.status();
self.resultCallback(self.result); 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() { Spec.prototype.disable = function() {
this.disabled = true; this.disabled = true;
}; };

View File

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