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
+63 -61
View File
@@ -2,15 +2,15 @@ describe("QueueRunner", function() {
it("runs all the functions it's passed", function() {
var calls = [],
fn1 = jasmine.createSpy('fn1'),
fn2 = jasmine.createSpy('fn2'),
queueableFn1 = { fn: jasmine.createSpy('fn1') },
queueableFn2 = { fn: jasmine.createSpy('fn2') },
queueRunner = new j$.QueueRunner({
fns: [fn1, fn2]
queueableFns: [queueableFn1, queueableFn2]
});
fn1.and.callFake(function() {
queueableFn1.fn.and.callFake(function() {
calls.push('fn1');
});
fn2.and.callFake(function() {
queueableFn2.fn.and.callFake(function() {
calls.push('fn2');
});
@@ -20,19 +20,19 @@ describe("QueueRunner", function() {
});
it("calls each function with a consistent 'this'-- an empty object", function() {
var fn1 = jasmine.createSpy('fn1'),
fn2 = jasmine.createSpy('fn2'),
fn3 = function(done) { asyncContext = this; done(); },
var queueableFn1 = { fn: jasmine.createSpy('fn1') },
queueableFn2 = { fn: jasmine.createSpy('fn2') },
queueableFn3 = { fn: function(done) { asyncContext = this; done(); } },
queueRunner = new j$.QueueRunner({
fns: [fn1, fn2, fn3]
queueableFns: [queueableFn1, queueableFn2, queueableFn3]
}),
asyncContext;
queueRunner.execute();
var context = fn1.calls.first().object;
var context = queueableFn1.fn.calls.first().object;
expect(context).toEqual({});
expect(fn2.calls.first().object).toBe(context);
expect(queueableFn2.fn.calls.first().object).toBe(context);
expect(asyncContext).toBe(context);
});
@@ -53,20 +53,20 @@ describe("QueueRunner", function() {
beforeCallback = jasmine.createSpy('beforeCallback'),
fnCallback = jasmine.createSpy('fnCallback'),
afterCallback = jasmine.createSpy('afterCallback'),
fn1 = function(done) {
queueableFn1 = { fn: function(done) {
beforeCallback();
setTimeout(done, 100);
},
fn2 = function(done) {
} },
queueableFn2 = { fn: function(done) {
fnCallback();
setTimeout(done, 100);
},
fn3 = function(done) {
} },
queueableFn3 = { fn: function(done) {
afterCallback();
setTimeout(done, 100);
},
} },
queueRunner = new j$.QueueRunner({
fns: [fn1, fn2, fn3],
queueableFns: [queueableFn1, queueableFn2, queueableFn3],
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() {
var beforeFn = function(done) { },
fn = jasmine.createSpy('fn'),
var timeout = 3,
beforeFn = { fn: function(done) { }, timeout: function() { return timeout; } },
queueableFn = { fn: jasmine.createSpy('fn') },
onComplete = jasmine.createSpy('onComplete'),
onException = jasmine.createSpy('onException'),
queueRunner = new j$.QueueRunner({
fns: [beforeFn, fn],
queueableFns: [beforeFn, queueableFn],
onComplete: onComplete,
onException: onException,
enforceTimeout: function() { return true; }
onException: onException
});
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(fn).toHaveBeenCalled();
expect(queueableFn.fn).toHaveBeenCalled();
expect(onComplete).toHaveBeenCalled();
});
it("by default does not set a timeout for asynchronous functions", function() {
var beforeFn = function(done) { },
fn = jasmine.createSpy('fn'),
var beforeFn = { fn: function(done) { } },
queueableFn = { fn: jasmine.createSpy('fn') },
onComplete = jasmine.createSpy('onComplete'),
onException = jasmine.createSpy('onException'),
queueRunner = new j$.QueueRunner({
fns: [beforeFn, fn],
queueableFns: [beforeFn, queueableFn],
onComplete: onComplete,
onException: onException,
});
queueRunner.execute();
expect(fn).not.toHaveBeenCalled();
expect(queueableFn.fn).not.toHaveBeenCalled();
jasmine.clock().tick(j$.DEFAULT_TIMEOUT_INTERVAL);
expect(onException).not.toHaveBeenCalled();
expect(fn).not.toHaveBeenCalled();
expect(queueableFn.fn).not.toHaveBeenCalled();
expect(onComplete).not.toHaveBeenCalled();
});
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'),
onException = jasmine.createSpy('onException'),
queueRunner = new j$.QueueRunner({
fns: [fn],
queueableFns: [queueableFn],
onComplete: onComplete,
onException: onException
});
@@ -156,11 +156,11 @@ describe("QueueRunner", 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'),
onException = jasmine.createSpy('onException'),
queueRunner = new j$.QueueRunner({
fns: [fn],
queueableFns: [queueableFn],
onComplete: onComplete,
onException: onException
});
@@ -174,39 +174,39 @@ describe("QueueRunner", function() {
});
it("only moves to the next spec the first time you call done", function() {
var fn = function(done) {done(); done();},
nextFn = jasmine.createSpy('nextFn');
var queueableFn = { fn: function(done) {done(); done();} },
nextQueueableFn = { fn: jasmine.createSpy('nextFn') };
queueRunner = new j$.QueueRunner({
fns: [fn, nextFn]
queueableFns: [queueableFn, nextQueueableFn]
});
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() {
var fn = function(done) {
var queueableFn = { fn: function(done) {
setTimeout(done, 1);
throw new Error('error!');
},
nextFn = jasmine.createSpy('nextFn');
} },
nextQueueableFn = { fn: jasmine.createSpy('nextFn') };
queueRunner = new j$.QueueRunner({
fns: [fn, nextFn]
queueableFns: [queueableFn, nextQueueableFn]
});
queueRunner.execute();
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() {
var fn = function() {
var queueableFn = { fn: function() {
throw new Error('fake error');
},
} },
exceptionCallback = jasmine.createSpy('exception callback'),
queueRunner = new j$.QueueRunner({
fns: [fn],
queueableFns: [queueableFn],
onException: exceptionCallback
});
@@ -216,33 +216,35 @@ describe("QueueRunner", function() {
});
it("rethrows an exception if told to", function() {
var fn = function() {
var queueableFn = { fn: function() {
throw new Error('fake error');
},
} },
queueRunner = new j$.QueueRunner({
fns: [fn],
queueableFns: [queueableFn],
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() {
var fn = function(done) { throw new Error("error"); },
nextFn = jasmine.createSpy("nextFunction"),
var queueableFn = { fn: function(done) { throw new Error("error"); } },
nextQueueableFn = { fn: jasmine.createSpy("nextFunction") },
queueRunner = new j$.QueueRunner({
fns: [fn, nextFn]
queueableFns: [queueableFn, nextQueueableFn]
});
queueRunner.execute();
expect(nextFn).toHaveBeenCalled();
expect(nextQueueableFn.fn).toHaveBeenCalled();
});
it("calls a provided complete callback when done", function() {
var fn = jasmine.createSpy('fn'),
var queueableFn = { fn: jasmine.createSpy('fn') },
completeCallback = jasmine.createSpy('completeCallback'),
queueRunner = new j$.QueueRunner({
fns: [fn],
queueableFns: [queueableFn],
onComplete: completeCallback
});
@@ -252,12 +254,12 @@ describe("QueueRunner", function() {
});
it("calls a provided stack clearing function when done", function() {
var asyncFn = function(done) { done() },
afterFn = jasmine.createSpy('afterFn'),
var asyncFn = { fn: function(done) { done() } },
afterFn = { fn: jasmine.createSpy('afterFn') },
completeCallback = jasmine.createSpy('completeCallback'),
clearStack = jasmine.createSpy('clearStack'),
queueRunner = new j$.QueueRunner({
fns: [asyncFn, afterFn],
queueableFns: [asyncFn, afterFn],
clearStack: clearStack,
onComplete: completeCallback
});
@@ -265,7 +267,7 @@ describe("QueueRunner", function() {
clearStack.and.callFake(function(fn) { fn(); });
queueRunner.execute();
expect(afterFn).toHaveBeenCalled();
expect(afterFn.fn).toHaveBeenCalled();
expect(clearStack).toHaveBeenCalledWith(completeCallback);
});
});
+19 -17
View File
@@ -29,7 +29,7 @@ describe("Spec", function() {
spec = new j$.Spec({
description: 'my test',
id: 'some-id',
fn: function() {},
queueableFn: { fn: function() {} },
queueRunnerFactory: fakeQueueRunner
});
@@ -44,7 +44,7 @@ describe("Spec", function() {
spec = new j$.Spec({
id: 123,
description: 'foo bar',
fn: function() {},
queueableFn: { fn: function() {} },
onStart: startCallback,
queueRunnerFactory: fakeQueueRunner
});
@@ -66,7 +66,7 @@ describe("Spec", function() {
expect(beforesWereCalled).toBe(false);
}),
spec = new j$.Spec({
fn: function() {},
queueableFn: { fn: function() {} },
beforeFns: function() {
return [function() {
beforesWereCalled = true
@@ -85,12 +85,12 @@ describe("Spec", function() {
var fakeQueueRunner = jasmine.createSpy('fakeQueueRunner'),
before = jasmine.createSpy('before'),
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(after).not.toHaveBeenCalled();
}),
}) },
spec = new j$.Spec({
fn: fn,
queueableFn: queueableFn,
beforeFns: function() {
return [before]
},
@@ -102,8 +102,8 @@ describe("Spec", function() {
spec.execute();
var allSpecFns = fakeQueueRunner.calls.mostRecent().args[0].fns;
expect(allSpecFns).toEqual([before, fn, after]);
var allSpecFns = fakeQueueRunner.calls.mostRecent().args[0].queueableFns;
expect(allSpecFns).toEqual([before, queueableFn, after]);
});
it("is marked pending if created without a function body", function() {
@@ -113,7 +113,7 @@ describe("Spec", function() {
resultCallback = jasmine.createSpy('resultCallback'),
spec = new j$.Spec({
onStart: startCallback,
fn: null,
queueableFn: { fn: null },
resultCallback: resultCallback,
queueRunnerFactory: fakeQueueRunner
});
@@ -129,7 +129,7 @@ describe("Spec", function() {
resultCallback = jasmine.createSpy('resultCallback'),
spec = new j$.Spec({
onStart:startCallback,
fn: specBody,
queueableFn: { fn: specBody },
resultCallback: resultCallback,
queueRunnerFactory: fakeQueueRunner
});
@@ -158,7 +158,8 @@ describe("Spec", function() {
getSpecName: function() {
return "a suite with a spec"
},
queueRunnerFactory: fakeQueueRunner
queueRunnerFactory: fakeQueueRunner,
queueableFn: { fn: null }
});
spec.pend();
@@ -182,7 +183,7 @@ describe("Spec", function() {
it("should call the done callback on execution complete", function() {
var done = jasmine.createSpy('done callback'),
spec = new j$.Spec({
fn: function() {},
queueableFn: { fn: function() {} },
catchExceptions: function() { return false; },
resultCallback: function() {},
queueRunnerFactory: function(attrs) { attrs.onComplete(); }
@@ -194,18 +195,18 @@ describe("Spec", 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');
});
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);
expect(spec.status()).toBe('passed');
});
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(false);
expect(spec.status()).toBe('failed');
@@ -215,7 +216,8 @@ describe("Spec", function() {
var specNameSpy = jasmine.createSpy('specNameSpy').and.returnValue('expected val');
var spec = new j$.Spec({
getSpecName: specNameSpy
getSpecName: specNameSpy,
queueableFn: { fn: null }
});
expect(spec.getFullName()).toBe('expected val');
@@ -230,7 +232,7 @@ describe("Spec", function() {
spec = new j$.Spec({
description: 'my test',
id: 'some-id',
fn: function() { },
queueableFn: { fn: function() { } },
queueRunnerFactory: fakeQueueRunner
});
+14 -14
View File
@@ -69,7 +69,7 @@ describe("Suite", function() {
suite.addChild(fakeIt);
suite.execute();
var suiteFns = fakeQueueRunner.calls.mostRecent().args[0].fns;
var suiteFns = fakeQueueRunner.calls.mostRecent().args[0].queueableFns;
suiteFns[0]();
expect(firstBefore).toHaveBeenCalled();
@@ -109,7 +109,7 @@ describe("Suite", function() {
suite.addChild(fakeIt);
suite.execute();
var suiteFns = fakeQueueRunner.calls.mostRecent().args[0].fns;
var suiteFns = fakeQueueRunner.calls.mostRecent().args[0].queueableFns;
suiteFns[1]();
expect(firstAfter).toHaveBeenCalled();
@@ -154,8 +154,8 @@ describe("Suite", function() {
execute: jasmine.createSpy('fakeSpec1'),
isExecutable: function() { return true; }
},
beforeAllFn = jasmine.createSpy('beforeAll'),
afterAllFn = jasmine.createSpy('afterAll');
beforeAllFn = { fn: jasmine.createSpy('beforeAll') },
afterAllFn = { fn: jasmine.createSpy('afterAll') };
spyOn(suite, "execute");
@@ -166,16 +166,16 @@ describe("Suite", function() {
parentSuite.execute(parentSuiteDone);
var parentSuiteFns = fakeQueueRunnerForParent.calls.mostRecent().args[0].fns;
var parentSuiteFns = fakeQueueRunnerForParent.calls.mostRecent().args[0].queueableFns;
parentSuiteFns[0]();
expect(beforeAllFn).toHaveBeenCalled();
parentSuiteFns[1]();
parentSuiteFns[0].fn();
expect(beforeAllFn.fn).toHaveBeenCalled();
parentSuiteFns[1].fn();
expect(fakeSpec1.execute).toHaveBeenCalled();
parentSuiteFns[2]();
parentSuiteFns[2].fn();
expect(suite.execute).toHaveBeenCalled();
parentSuiteFns[3]();
expect(afterAllFn).toHaveBeenCalled();
parentSuiteFns[3].fn();
expect(afterAllFn.fn).toHaveBeenCalled();
});
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,
parentSuite: parentSuite
}),
spec1 = new j$.Spec({expectationFactory: function() {}}),
spec2 = new j$.Spec({expectationFactory: function() {}}),
spec1 = new j$.Spec({expectationFactory: function() {}, queueableFn: {}}),
spec2 = new j$.Spec({expectationFactory: function() {}, queueableFn: {}}),
beforeAllFn = jasmine.createSpy('beforeAll'),
afterAllFn = jasmine.createSpy('afterAll');
@@ -203,7 +203,7 @@ describe("Suite", function() {
childSuite.addChild(spec1);
parentSuite.execute();
expect(fakeQueueRunnerForParent).toHaveBeenCalledWith(jasmine.objectContaining({fns: []}));
expect(fakeQueueRunnerForParent).toHaveBeenCalledWith(jasmine.objectContaining({queueableFns: []}));
});
it("calls a provided onStart callback when starting", function() {
+32 -3
View File
@@ -414,11 +414,11 @@ describe("Env integration", function() {
beforeEach(function() {
originalTimeout = j$.DEFAULT_TIMEOUT_INTERVAL;
jasmine.getEnv().clock.install();
jasmine.clock().install();
});
afterEach(function() {
jasmine.getEnv().clock.uninstall();
jasmine.clock().uninstall();
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.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();