Suites report errors in afterAlls in the suiteDone event

- remove `afterAllEvent` from reporters
This commit is contained in:
slackersoft
2014-09-03 18:52:13 -07:00
parent 6b857d11ce
commit 9402d59859
14 changed files with 306 additions and 203 deletions

View File

@@ -55,7 +55,7 @@ getJasmineRequireObj().ConsoleReporter = function() {
yellow: '\x1B[33m',
none: '\x1B[0m'
},
exceptionList = [];
failedSuites = [];
this.jasmineStarted = function() {
specCount = 0;
@@ -87,12 +87,8 @@ getJasmineRequireObj().ConsoleReporter = function() {
print('Finished in ' + seconds + ' ' + plural('second', seconds));
printNewline();
for(i = 0; i < exceptionList.length; i++) {
printNewline();
print(colored('red', 'An error was thrown in an afterAll'));
printNewline();
print(colored('red', (exceptionList[i].message || exceptionList[i].description)));
printNewline();
for(i = 0; i < failedSuites.length; i++) {
suiteFailureDetails(failedSuites[i]);
}
onComplete(failureCount === 0);
@@ -119,8 +115,11 @@ getJasmineRequireObj().ConsoleReporter = function() {
}
};
this.afterAllError = function(error) {
exceptionList.push(error);
this.suiteDone = function(result) {
if (result.failedExpectations && result.failedExpectations.length > 0) {
failureCount++;
failedSuites.push(result);
}
};
return this;
@@ -166,6 +165,17 @@ getJasmineRequireObj().ConsoleReporter = function() {
printNewline();
}
function suiteFailureDetails(result) {
for (var i = 0; i < result.failedExpectations.length; i++) {
printNewline();
print(colored('red', 'An error was thrown in an afterAll'));
printNewline();
print(colored('red', 'AfterAll ' + result.failedExpectations[i].message));
}
printNewline();
}
}
return ConsoleReporter;

View File

@@ -47,7 +47,7 @@ jasmineRequire.HtmlReporter = function(j$) {
pendingSpecCount = 0,
htmlReporterMain,
symbols,
exceptionList = [];
failedSuites = [];
this.initialize = function() {
htmlReporterMain = createDom('div', {className: 'html-reporter'},
@@ -83,6 +83,10 @@ jasmineRequire.HtmlReporter = function(j$) {
};
this.suiteDone = function(result) {
if (result.failedExpectations && result.failedExpectations.length > 0) {
failedSuites.push(result);
}
if (currentParent == topResults) {
return;
}
@@ -94,10 +98,6 @@ jasmineRequire.HtmlReporter = function(j$) {
currentParent.addChild(result, 'spec');
};
this.afterAllException = function(error) {
exceptionList.push(error);
};
var failures = [];
this.specDone = function(result) {
if (result.status != 'disabled') {
@@ -170,10 +170,13 @@ jasmineRequire.HtmlReporter = function(j$) {
var statusBarClassName = 'bar ' + ((failureCount > 0) ? 'failed' : 'passed');
alert.appendChild(createDom('span', {className: statusBarClassName}, statusBarMessage));
for(i = 0; i < exceptionList.length; i++) {
var errorBarMessage = 'An error was thrown in an afterAll: ' + (exceptionList[i].message || exceptionList[i].description);
var errorBarClassName = 'bar errored';
alert.appendChild(createDom('span', {className: errorBarClassName}, errorBarMessage));
for(i = 0; i < failedSuites.length; i++) {
var failedSuite = failedSuites[i];
for(var j = 0; j < failedSuite.failedExpectations.length; j++) {
var errorBarMessage = 'AfterAll ' + failedSuite.failedExpectations[j].message;
var errorBarClassName = 'bar errored';
alert.appendChild(createDom('span', {className: errorBarClassName}, errorBarMessage));
}
}
var results = find('.results');

View File

@@ -250,11 +250,9 @@ getJasmineRequireObj().Spec = function(j$) {
this.id = attrs.id;
this.description = attrs.description || '';
this.queueableFn = attrs.queueableFn;
this.beforeFns = attrs.beforeFns || function() { return []; };
this.afterFns = attrs.afterFns || function() { return []; };
this.beforeAndAfterFns = attrs.beforeAndAfterFns || function() { return {befores: [], afters: []}; };
this.userContext = attrs.userContext || function() { return {}; };
this.onStart = attrs.onStart || function() {};
this.exceptionFormatter = attrs.exceptionFormatter || function() {};
this.getSpecName = attrs.getSpecName || function() { return ''; };
this.expectationResultFactory = attrs.expectationResultFactory || function() { };
this.queueRunnerFactory = attrs.queueRunnerFactory || function() {};
@@ -293,7 +291,8 @@ getJasmineRequireObj().Spec = function(j$) {
return;
}
var allFns = this.beforeFns().concat(this.queueableFn).concat(this.afterFns());
var fns = this.beforeAndAfterFns();
var allFns = fns.befores.concat(this.queueableFn).concat(fns.afters);
this.queueRunnerFactory({
queueableFns: allFns,
@@ -408,8 +407,7 @@ getJasmineRequireObj().Env = function(j$) {
'suiteStarted',
'suiteDone',
'specStarted',
'specDone',
'afterAllException'
'specDone'
]);
this.specFilter = function() {
@@ -475,25 +473,28 @@ getJasmineRequireObj().Env = function(j$) {
delete runnableResources[id];
};
var beforeFns = function(suite) {
var beforeAndAfterFns = function(suite, runnablesExplictlySet) {
return function() {
var befores = [];
var befores = [],
afters = [],
beforeAlls = [],
afterAlls = [];
while(suite) {
befores = befores.concat(suite.beforeFns);
suite = suite.parentSuite;
}
return befores.reverse();
};
};
var afterFns = function(suite) {
return function() {
var afters = [];
while(suite) {
afters = afters.concat(suite.afterFns);
if (runnablesExplictlySet()) {
beforeAlls = beforeAlls.concat(suite.beforeAllFns);
afterAlls = afterAlls.concat(suite.afterAllFns);
}
suite = suite.parentSuite;
}
return afters;
return {
befores: beforeAlls.reverse().concat(befores.reverse()),
afters: afters.concat(afterAlls)
};
};
};
@@ -540,7 +541,6 @@ getJasmineRequireObj().Env = function(j$) {
var queueRunnerFactory = function(options) {
options.catchException = catchException;
options.reporter = reporter;
options.clearStack = options.clearStack || clearStack;
options.timer = {setTimeout: realSetTimeout, clearTimeout: realClearTimeout};
@@ -552,7 +552,9 @@ getJasmineRequireObj().Env = function(j$) {
id: getNextSuiteId(),
description: 'Jasmine__TopLevel__Suite',
queueRunner: queueRunnerFactory,
resultCallback: function() {} // TODO - hook this up
resultCallback: function(attrs) {
reporter.suiteDone(attrs);
}
});
runnableLookupTable[topSuite.id] = topSuite;
defaultResourcesForRunnable(topSuite.id);
@@ -563,7 +565,14 @@ getJasmineRequireObj().Env = function(j$) {
};
this.execute = function(runnablesToRun) {
runnablesToRun = runnablesToRun || [topSuite.id];
if(runnablesToRun) {
runnablesExplictlySet = true;
} else if (focusedRunnables.length) {
runnablesExplictlySet = true;
runnablesToRun = focusedRunnables;
} else {
runnablesToRun = [topSuite.id];
}
var allFns = [];
for(var i = 0; i < runnablesToRun.length; i++) {
@@ -602,6 +611,7 @@ getJasmineRequireObj().Env = function(j$) {
queueRunner: queueRunnerFactory,
onStart: suiteStarted,
expectationFactory: expectationFactory,
expectationResultFactory: expectationResultFactory,
resultCallback: function(attrs) {
if (!suite.disabled) {
clearResourcesForRunnable(suite.id);
@@ -623,7 +633,28 @@ getJasmineRequireObj().Env = function(j$) {
this.describe = function(description, specDefinitions) {
var suite = suiteFactory(description);
addSpecsToSuite(suite, specDefinitions);
return suite;
};
this.xdescribe = function(description, specDefinitions) {
var suite = this.describe(description, specDefinitions);
suite.disable();
return suite;
};
this.fdescribe = function(description, specDefinitions) {
var suite = suiteFactory(description);
suite.isFocused = true;
addSpecsToSuite(suite, specDefinitions);
if (!hasFocusedAncestor(suite.parentSuite)) {
focusedRunnables.push(suite.id);
}
return suite;
};
function addSpecsToSuite(suite, specDefinitions) {
var parentSuite = currentDeclarationSuite;
parentSuite.addChild(suite);
currentDeclarationSuite = suite;
@@ -636,31 +667,37 @@ getJasmineRequireObj().Env = function(j$) {
}
if (declarationError) {
this.it('encountered a declaration exception', function() {
self.it('encountered a declaration exception', function() {
throw declarationError;
});
}
currentDeclarationSuite = parentSuite;
}
return suite;
};
function hasFocusedAncestor(suite) {
while (suite) {
if (suite.isFocused) {
return true;
}
suite = suite.parentSuite;
}
this.xdescribe = function(description, specDefinitions) {
var suite = this.describe(description, specDefinitions);
suite.disable();
return suite;
return false;
}
var runnablesExplictlySet = false;
var runnablesExplictlySetGetter = function(){
return runnablesExplictlySet;
};
var specFactory = function(description, fn, suite) {
totalSpecsDefined++;
var spec = new j$.Spec({
id: getNextSpecId(),
beforeFns: beforeFns(suite),
afterFns: afterFns(suite),
beforeAndAfterFns: beforeAndAfterFns(suite, runnablesExplictlySetGetter),
expectationFactory: expectationFactory,
exceptionFormatter: exceptionFormatter,
resultCallback: specResultCallback,
getSpecName: function(spec) {
return getSpecName(spec, suite);
@@ -670,7 +707,7 @@ getJasmineRequireObj().Env = function(j$) {
expectationResultFactory: expectationResultFactory,
queueRunnerFactory: queueRunnerFactory,
userContext: function() { return suite.clonedSharedUserContext(); },
queueableFn: { fn: fn, timeout: function() { return j$.DEFAULT_TIMEOUT_INTERVAL; } }
queueableFn: { fn: fn, type: 'it', timeout: function() { return j$.DEFAULT_TIMEOUT_INTERVAL; } }
});
runnableLookupTable[spec.id] = spec;
@@ -706,24 +743,35 @@ getJasmineRequireObj().Env = function(j$) {
return spec;
};
var focusedRunnables = [];
this.fit = function(description, fn ){
var spec = this.it(description, fn);
if (!hasFocusedAncestor(currentDeclarationSuite)) {
focusedRunnables.push(spec.id);
}
return spec;
};
this.expect = function(actual) {
return currentRunnable().expect(actual);
};
this.beforeEach = function(beforeEachFunction) {
currentDeclarationSuite.beforeEach({ fn: beforeEachFunction, timeout: function() { return j$.DEFAULT_TIMEOUT_INTERVAL; } });
currentDeclarationSuite.beforeEach({ fn: beforeEachFunction, type: 'beforeEach', timeout: function() { return j$.DEFAULT_TIMEOUT_INTERVAL; } });
};
this.beforeAll = function(beforeAllFunction) {
currentDeclarationSuite.beforeAll({ fn: beforeAllFunction, timeout: function() { return j$.DEFAULT_TIMEOUT_INTERVAL; } });
currentDeclarationSuite.beforeAll({ fn: beforeAllFunction, type: 'beforeAll', timeout: function() { return j$.DEFAULT_TIMEOUT_INTERVAL; } });
};
this.afterEach = function(afterEachFunction) {
currentDeclarationSuite.afterEach({ fn: afterEachFunction, timeout: function() { return j$.DEFAULT_TIMEOUT_INTERVAL; } });
currentDeclarationSuite.afterEach({ fn: afterEachFunction, type: 'afterEach', timeout: function() { return j$.DEFAULT_TIMEOUT_INTERVAL; } });
};
this.afterAll = function(afterAllFunction) {
currentDeclarationSuite.afterAll({ fn: afterAllFunction, isAfterAll: true, timeout: function() { return j$.DEFAULT_TIMEOUT_INTERVAL; } });
currentDeclarationSuite.afterAll({ fn: afterAllFunction, type: 'afterAll', timeout: function() { return j$.DEFAULT_TIMEOUT_INTERVAL; } });
};
this.pending = function() {
@@ -1583,7 +1631,6 @@ getJasmineRequireObj().QueueRunner = function(j$) {
this.catchException = attrs.catchException || function() { return true; };
this.userContext = attrs.userContext || {};
this.timer = attrs.timeout || {setTimeout: setTimeout, clearTimeout: clearTimeout};
this.reporter = attrs.reporter;
}
QueueRunner.prototype.execute = function() {
@@ -1591,10 +1638,10 @@ getJasmineRequireObj().QueueRunner = function(j$) {
};
QueueRunner.prototype.run = function(queueableFns, recursiveIndex) {
var runner = this,
length = queueableFns.length,
self = this,
iterativeIndex;
var length = queueableFns.length,
self = this,
iterativeIndex;
for(iterativeIndex = recursiveIndex; iterativeIndex < length; iterativeIndex++) {
var queueableFn = queueableFns[iterativeIndex];
@@ -1615,10 +1662,7 @@ getJasmineRequireObj().QueueRunner = function(j$) {
try {
queueableFn.fn.call(self.userContext);
} catch (e) {
if(queueableFn.isAfterAll){
runner.reporter.afterAllException(e);
}
handleException(e);
handleException(e, queueableFn);
}
}
@@ -1634,7 +1678,8 @@ getJasmineRequireObj().QueueRunner = function(j$) {
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.'));
var error = new Error('Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.');
onException(error, queueableFn);
next();
}, queueableFn.timeout()]]);
}
@@ -1642,16 +1687,17 @@ getJasmineRequireObj().QueueRunner = function(j$) {
try {
queueableFn.fn.call(self.userContext, next);
} catch (e) {
if(queueableFn.isAfterAll) {
runner.reporter.afterAllException(e);
}
handleException(e);
handleException(e, queueableFn);
next();
}
}
function handleException(e) {
function onException(e, queueableFn) {
self.onException(e);
}
function handleException(e, queueableFn) {
onException(e, queueableFn);
if (!self.catchException(e)) {
//TODO: set a var when we catch an exception and
//use a finally block to close the loop in a nice way..
@@ -1807,6 +1853,7 @@ getJasmineRequireObj().Suite = function() {
this.resultCallback = attrs.resultCallback || function() {};
this.clearStack = attrs.clearStack || function(fn) {fn();};
this.expectationFactory = attrs.expectationFactory;
this.expectationResultFactory = attrs.expectationResultFactory;
this.beforeFns = [];
this.afterFns = [];
@@ -1821,7 +1868,8 @@ getJasmineRequireObj().Suite = function() {
id: this.id,
status: this.disabled ? 'disabled' : '',
description: this.description,
fullName: this.getFullName()
fullName: this.getFullName(),
failedExpectations: []
};
}
@@ -1873,7 +1921,7 @@ getJasmineRequireObj().Suite = function() {
var allFns = [];
if (this.isExecutable()) {
allFns = this.beforeAllFns;
allFns = allFns.concat(this.beforeAllFns);
for (var i = 0; i < this.children.length; i++) {
allFns.push(wrapChildAsAsync(this.children[i]));
@@ -1928,19 +1976,43 @@ getJasmineRequireObj().Suite = function() {
};
Suite.prototype.onException = function() {
for (var i = 0; i < this.children.length; i++) {
var child = this.children[i];
child.onException.apply(child, arguments);
if(isAfterAll(this.children)) {
var data = {
matcherName: '',
passed: false,
expected: '',
actual: '',
error: arguments[0]
};
this.result.failedExpectations.push(this.expectationResultFactory(data));
} else {
for (var i = 0; i < this.children.length; i++) {
var child = this.children[i];
child.onException.apply(child, arguments);
}
}
};
Suite.prototype.addExpectationResult = function () {
for (var i = 0; i < this.children.length; i++) {
var child = this.children[i];
child.addExpectationResult.apply(child, arguments);
if(isAfterAll(this.children) && isFailure(arguments)){
var data = arguments[1];
this.result.failedExpectations.push(this.expectationResultFactory(data));
} else {
for (var i = 0; i < this.children.length; i++) {
var child = this.children[i];
child.addExpectationResult.apply(child, arguments);
}
}
};
function isAfterAll(children) {
return children && children[0].result.status;
}
function isFailure(args) {
return !args[0];
}
function clone(obj) {
var clonedObj = {};
for (var prop in obj) {

View File

@@ -187,9 +187,9 @@ describe("ConsoleReporter", function() {
expect(onComplete).toHaveBeenCalledWith(false);
});
it('calls it with false if there are afterAll events', function() {
reporter.afterAllEvent("bananas");
it('calls it with false if there are suite failures', function() {
reporter.specDone({status: "passed"});
reporter.suiteDone({failedExpectations: [{ message: 'bananas' }] });
reporter.jasmineDone();
expect(onComplete).toHaveBeenCalledWith(false);
});
@@ -244,12 +244,10 @@ describe("ConsoleReporter", function() {
var reporter = new j$.ConsoleReporter({
print: out.print,
showColors: true
}),
error = new Error('After All Exception'),
anotherError = new Error('Some Other Exception');
});
reporter.afterAllEvent(error);
reporter.afterAllEvent(anotherError);
reporter.suiteDone({ failedExpectations: [{ message: 'After All Exception' }] });
reporter.suiteDone({ failedExpectations: [{ message: 'Some Other Exception' }] });
reporter.jasmineDone();
expect(out.getOutput()).toMatch(/After All Exception/);

View File

@@ -98,12 +98,10 @@ describe("QueueRunner", function() {
beforeFn = { fn: function(done) { }, type: 'before', timeout: function() { return timeout; } },
queueableFn = { fn: jasmine.createSpy('fn'), type: 'queueable' },
onComplete = jasmine.createSpy('onComplete'),
reportException = jasmine.createSpy('reportException'),
onException = jasmine.createSpy('onException'),
queueRunner = new j$.QueueRunner({
queueableFns: [beforeFn, queueableFn],
onComplete: onComplete,
reportException: reportException,
onException: onException
});
@@ -112,7 +110,6 @@ describe("QueueRunner", function() {
jasmine.clock().tick(timeout);
expect(reportException).toHaveBeenCalledWith(jasmine.any(Error), 'before');
expect(onException).toHaveBeenCalledWith(jasmine.any(Error));
expect(queueableFn.fn).toHaveBeenCalled();
expect(onComplete).toHaveBeenCalled();
@@ -122,12 +119,10 @@ describe("QueueRunner", function() {
var beforeFn = { fn: function(done) { } },
queueableFn = { fn: jasmine.createSpy('fn') },
onComplete = jasmine.createSpy('onComplete'),
reportException = jasmine.createSpy('reportException'),
onException = jasmine.createSpy('onException'),
queueRunner = new j$.QueueRunner({
queueableFns: [beforeFn, queueableFn],
onComplete: onComplete,
reportException: reportException,
onException: onException,
});
@@ -136,7 +131,6 @@ describe("QueueRunner", function() {
jasmine.clock().tick(j$.DEFAULT_TIMEOUT_INTERVAL);
expect(reportException).not.toHaveBeenCalled();
expect(onException).not.toHaveBeenCalled();
expect(queueableFn.fn).not.toHaveBeenCalled();
expect(onComplete).not.toHaveBeenCalled();
@@ -145,35 +139,29 @@ describe("QueueRunner", function() {
it("clears the timeout when an async function throws an exception, to prevent additional exception reporting", function() {
var queueableFn = { fn: function(done) { throw new Error("error!"); } },
onComplete = jasmine.createSpy('onComplete'),
reportException = jasmine.createSpy('reportException'),
onException = jasmine.createSpy('onException'),
queueRunner = new j$.QueueRunner({
queueableFns: [queueableFn],
onComplete: onComplete,
reportException: reportException,
onException: onException
});
queueRunner.execute();
expect(onComplete).toHaveBeenCalled();
expect(reportException).toHaveBeenCalled();
expect(onException).toHaveBeenCalled();
jasmine.clock().tick(j$.DEFAULT_TIMEOUT_INTERVAL);
expect(reportException.calls.count()).toEqual(1);
expect(onException.calls.count()).toEqual(1);
});
it("clears the timeout when the done callback is called", function() {
var queueableFn = { fn: function(done) { done(); } },
onComplete = jasmine.createSpy('onComplete'),
reportException = jasmine.createSpy('reportException'),
onException = jasmine.createSpy('onException'),
queueRunner = new j$.QueueRunner({
queueableFns: [queueableFn],
onComplete: onComplete,
reportException: reportException,
onException: onException
});
@@ -182,7 +170,6 @@ describe("QueueRunner", function() {
expect(onComplete).toHaveBeenCalled();
jasmine.clock().tick(j$.DEFAULT_TIMEOUT_INTERVAL);
expect(reportException).not.toHaveBeenCalled();
expect(onException).not.toHaveBeenCalled();
});
@@ -218,17 +205,14 @@ describe("QueueRunner", function() {
fn: function() {
throw new Error('fake error');
} },
exceptionCallback = jasmine.createSpy('exception callback'),
onExceptionCallback = jasmine.createSpy('on exception callback'),
queueRunner = new j$.QueueRunner({
queueableFns: [queueableFn],
reportException: exceptionCallback,
onException: onExceptionCallback
});
queueRunner.execute();
expect(exceptionCallback).toHaveBeenCalledWith(jasmine.any(Error), 'queueable');
expect(onExceptionCallback).toHaveBeenCalledWith(jasmine.any(Error));
});

View File

@@ -262,7 +262,8 @@ describe("Suite", function() {
id: suite.id,
status: '',
description: "with a child suite",
fullName: "with a child suite"
fullName: "with a child suite",
failedExpectations: []
});
});
});

View File

@@ -330,11 +330,29 @@ describe("Env integration", function() {
it("reports when an afterAll fails an expectation", function(done) {
var env = new j$.Env(),
reporter = jasmine.createSpyObj('fakeReport', ['jasmineDone','afterAllEvent']);
reporter = jasmine.createSpyObj('fakeReport', ['jasmineDone','suiteDone']);
reporter.jasmineDone.and.callFake(function() {
expect(reporter.afterAllEvent).toHaveBeenCalledWith('Expectation failed: Expected 1 to equal 2.');
expect(reporter.afterAllEvent).toHaveBeenCalledWith('Expectation failed: Expected 2 to equal 3.');
expect(reporter.suiteDone).toHaveBeenCalledWith(jasmine.objectContaining({
failedExpectations: [
{
matcherName : 'toEqual',
expected : 2,
actual : 1,
message : 'Expected 1 to equal 2.',
stack: jasmine.any(String),
passed: false
},
{
matcherName : 'toEqual',
expected : 3,
actual : 2,
message : 'Expected 2 to equal 3.',
stack: jasmine.any(String),
passed: false
}
]
}));
done();
});
@@ -353,46 +371,23 @@ describe("Env integration", function() {
env.execute();
});
it("only reports afterAll expectation failures once, regardless of suite children", function(done) {
var env = new j$.Env(),
reporter = jasmine.createSpyObj('fakeReport', ['jasmineDone','afterAllEvent']);
reporter.jasmineDone.and.callFake(function() {
expect(reporter.afterAllEvent.calls.count()).toEqual(1);
expect(reporter.afterAllEvent).toHaveBeenCalledWith('Expectation failed: Expected 1 to equal 2.');
done();
});
env.addReporter(reporter);
env.describe('my suite', function() {
env.it('my spec', function() {
});
env.it('my spec2', function() {
});
env.describe('nested suite', function(){
env.it('my spec3', function() {
});
});
env.afterAll(function() {
env.expect(1).toEqual(2);
});
});
env.execute();
});
it("reports when afterAll throws an exception", function(done) {
var env = new j$.Env(),
error = new Error('After All Exception'),
reporter = jasmine.createSpyObj('fakeReport', ['jasmineDone','afterAllEvent']);
reporter = jasmine.createSpyObj('fakeReport', ['jasmineDone','suiteDone']);
reporter.jasmineDone.and.callFake(function() {
expect(reporter.afterAllEvent.calls.count()).toEqual(1);
expect(reporter.afterAllEvent).toHaveBeenCalledWith('Error thrown: After All Exception');
expect(reporter.suiteDone).toHaveBeenCalledWith(jasmine.objectContaining({
description: 'my suite',
failedExpectations: [{
matcherName : '',
expected : '',
actual : '',
message : 'Error: After All Exception',
stack : jasmine.any(String),
passed: false
}]
}));
done();
});
@@ -412,10 +407,19 @@ describe("Env integration", function() {
it("reports when an async afterAll fails an expectation", function(done) {
var env = new j$.Env(),
reporter = jasmine.createSpyObj('fakeReport', ['jasmineDone','afterAllEvent']);
reporter = jasmine.createSpyObj('fakeReport', ['jasmineDone','suiteDone']);
reporter.jasmineDone.and.callFake(function() {
expect(reporter.afterAllEvent).toHaveBeenCalledWith('Expectation failed: Expected 1 to equal 2.');
expect(reporter.suiteDone).toHaveBeenCalledWith(jasmine.objectContaining({
failedExpectations: [{
matcherName : 'toEqual',
expected : 2,
actual : 1,
message : 'Expected 1 to equal 2.',
stack: jasmine.any(String),
passed: false
}]
}));
done();
});
@@ -437,11 +441,21 @@ describe("Env integration", function() {
it("reports when an async afterAll throws an exception", function(done) {
var env = new j$.Env(),
error = new Error('After All Exception'),
reporter = jasmine.createSpyObj('fakeReport', ['jasmineDone','afterAllEvent']);
reporter = jasmine.createSpyObj('fakeReport', ['jasmineDone','suiteDone']);
reporter.jasmineDone.and.callFake(function() {
expect(reporter.afterAllEvent).toHaveBeenCalled();
expect(reporter.suiteDone).toHaveBeenCalledWith(jasmine.objectContaining({
description: 'my suite',
failedExpectations: [{
matcherName : '',
expected : '',
actual : '',
message : 'Error: After All Exception',
stack : jasmine.any(String),
passed: false
}]
}));
done();
});
@@ -747,10 +761,19 @@ describe("Env integration", function() {
it("should wait the specified interval before reporting an afterAll that fails to call done", function(done) {
var env = new j$.Env(),
reporter = jasmine.createSpyObj('fakeReport', ['jasmineDone','afterAllEvent']);
reporter = jasmine.createSpyObj('fakeReport', ['jasmineDone','suiteDone']);
reporter.jasmineDone.and.callFake(function() {
expect(reporter.afterAllEvent).toHaveBeenCalledWith(jasmine.any(String));
expect(reporter.suiteDone).toHaveBeenCalledWith(jasmine.objectContaining({
failedExpectations: [{
matcherName : '',
expected : '',
actual : '',
message : 'Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.',
stack : jasmine.any(String),
passed: false
}]
}));
done();
});

View File

@@ -130,7 +130,7 @@ describe("New HtmlReporter", function() {
});
});
describe("when there are afterAllEvents", function () {
describe("when there are suite failures", function () {
it("displays the exceptions in their own alert bars", function(){
var env = new j$.Env(),
container = document.createElement("div"),
@@ -140,15 +140,13 @@ describe("New HtmlReporter", function() {
getContainer: getContainer,
createElement: function() { return document.createElement.apply(document, arguments); },
createTextNode: function() { return document.createTextNode.apply(document, arguments); }
}),
error = new Error('My After All Exception'),
otherError = new Error('My Other Exception');
});
reporter.initialize();
reporter.jasmineStarted({});
reporter.afterAllEvent(error);
reporter.afterAllEvent(otherError);
reporter.suiteDone({ failedExpectations: [{ message: 'My After All Exception' }] });
reporter.suiteDone({ failedExpectations: [{ message: 'My Other Exception' }] });
reporter.jasmineDone({});
var alertBars = container.querySelectorAll(".alert .bar");

View File

@@ -20,7 +20,7 @@ getJasmineRequireObj().ConsoleReporter = function() {
yellow: '\x1B[33m',
none: '\x1B[0m'
},
exceptionList = [];
failedSuites = [];
this.jasmineStarted = function() {
specCount = 0;
@@ -52,10 +52,8 @@ getJasmineRequireObj().ConsoleReporter = function() {
print('Finished in ' + seconds + ' ' + plural('second', seconds));
printNewline();
for(i = 0; i < exceptionList.length; i++) {
printNewline();
print(colored('red', 'AfterAll ' + exceptionList[i]));
printNewline();
for(i = 0; i < failedSuites.length; i++) {
suiteFailureDetails(failedSuites[i]);
}
onComplete(failureCount === 0);
@@ -82,9 +80,11 @@ getJasmineRequireObj().ConsoleReporter = function() {
}
};
this.afterAllEvent = function(error) {
failureCount++;
exceptionList.push(error);
this.suiteDone = function(result) {
if (result.failedExpectations && result.failedExpectations.length > 0) {
failureCount++;
failedSuites.push(result);
}
};
return this;
@@ -130,6 +130,17 @@ getJasmineRequireObj().ConsoleReporter = function() {
printNewline();
}
function suiteFailureDetails(result) {
for (var i = 0; i < result.failedExpectations.length; i++) {
printNewline();
print(colored('red', 'An error was thrown in an afterAll'));
printNewline();
print(colored('red', 'AfterAll ' + result.failedExpectations[i].message));
}
printNewline();
}
}
return ConsoleReporter;

View File

@@ -34,8 +34,7 @@ getJasmineRequireObj().Env = function(j$) {
'suiteStarted',
'suiteDone',
'specStarted',
'specDone',
'afterAllEvent'
'specDone'
]);
this.specFilter = function() {
@@ -171,11 +170,6 @@ getJasmineRequireObj().Env = function(j$) {
options.catchException = catchException;
options.clearStack = options.clearStack || clearStack;
options.timer = {setTimeout: realSetTimeout, clearTimeout: realClearTimeout};
options.reportException = function(e, type) {
if (type === 'afterAll') {
reporter.afterAllEvent('Error thrown: '+ (e.message || e.description));
}
};
new j$.QueueRunner(options).execute();
};
@@ -185,8 +179,9 @@ getJasmineRequireObj().Env = function(j$) {
id: getNextSuiteId(),
description: 'Jasmine__TopLevel__Suite',
queueRunner: queueRunnerFactory,
resultCallback: function() {}, // TODO - hook this up
reportExpectationFailure: reportExpectationFailure
resultCallback: function(attrs) {
reporter.suiteDone(attrs);
}
});
runnableLookupTable[topSuite.id] = topSuite;
defaultResourcesForRunnable(topSuite.id);
@@ -243,14 +238,14 @@ getJasmineRequireObj().Env = function(j$) {
queueRunner: queueRunnerFactory,
onStart: suiteStarted,
expectationFactory: expectationFactory,
expectationResultFactory: expectationResultFactory,
resultCallback: function(attrs) {
if (!suite.disabled) {
clearResourcesForRunnable(suite.id);
currentlyExecutingSuites.pop();
}
reporter.suiteDone(attrs);
},
reportExpectationFailure: reportExpectationFailure
}
});
runnableLookupTable[suite.id] = suite;
@@ -330,7 +325,6 @@ getJasmineRequireObj().Env = function(j$) {
id: getNextSpecId(),
beforeAndAfterFns: beforeAndAfterFns(suite, runnablesExplictlySetGetter),
expectationFactory: expectationFactory,
exceptionFormatter: exceptionFormatter,
resultCallback: specResultCallback,
getSpecName: function(spec) {
return getSpecName(spec, suite);
@@ -410,10 +404,6 @@ getJasmineRequireObj().Env = function(j$) {
this.pending = function() {
throw j$.Spec.pendingSpecExceptionMessage;
};
function reportExpectationFailure(message) {
reporter.afterAllEvent('Expectation failed: '+ message);
}
}
return Env;

View File

@@ -18,7 +18,6 @@ getJasmineRequireObj().QueueRunner = function(j$) {
this.catchException = attrs.catchException || function() { return true; };
this.userContext = attrs.userContext || {};
this.timer = attrs.timeout || {setTimeout: setTimeout, clearTimeout: clearTimeout};
this.reportException = attrs.reportException || function() {};
}
QueueRunner.prototype.execute = function() {
@@ -81,7 +80,6 @@ getJasmineRequireObj().QueueRunner = function(j$) {
}
function onException(e, queueableFn) {
self.reportException(e, queueableFn.type);
self.onException(e);
}

View File

@@ -8,7 +8,6 @@ getJasmineRequireObj().Spec = function(j$) {
this.beforeAndAfterFns = attrs.beforeAndAfterFns || function() { return {befores: [], afters: []}; };
this.userContext = attrs.userContext || function() { return {}; };
this.onStart = attrs.onStart || function() {};
this.exceptionFormatter = attrs.exceptionFormatter || function() {};
this.getSpecName = attrs.getSpecName || function() { return ''; };
this.expectationResultFactory = attrs.expectationResultFactory || function() { };
this.queueRunnerFactory = attrs.queueRunnerFactory || function() {};

View File

@@ -8,7 +8,7 @@ getJasmineRequireObj().Suite = function() {
this.resultCallback = attrs.resultCallback || function() {};
this.clearStack = attrs.clearStack || function(fn) {fn();};
this.expectationFactory = attrs.expectationFactory;
this.reportExpectationFailure = attrs.reportExpectationFailure || function() {};
this.expectationResultFactory = attrs.expectationResultFactory;
this.beforeFns = [];
this.afterFns = [];
@@ -23,7 +23,8 @@ getJasmineRequireObj().Suite = function() {
id: this.id,
status: this.disabled ? 'disabled' : '',
description: this.description,
fullName: this.getFullName()
fullName: this.getFullName(),
failedExpectations: []
};
}
@@ -130,31 +131,43 @@ getJasmineRequireObj().Suite = function() {
};
Suite.prototype.onException = function() {
for (var i = 0; i < this.children.length; i++) {
var child = this.children[i];
child.onException.apply(child, arguments);
if(isAfterAll(this.children)) {
var data = {
matcherName: '',
passed: false,
expected: '',
actual: '',
error: arguments[0]
};
this.result.failedExpectations.push(this.expectationResultFactory(data));
} else {
for (var i = 0; i < this.children.length; i++) {
var child = this.children[i];
child.onException.apply(child, arguments);
}
}
};
Suite.prototype.addExpectationResult = function () {
if(isAfterAll(this.children) && isFailure(arguments)){
this.reportExpectationFailure(arguments[1].message);
var data = arguments[1];
this.result.failedExpectations.push(this.expectationResultFactory(data));
} else {
for (var i = 0; i < this.children.length; i++) {
var child = this.children[i];
child.addExpectationResult.apply(child, arguments);
}
}
function isAfterAll(children) {
return children && children[0].result.status;
}
function isFailure(args) {
return !args[0];
}
};
function isAfterAll(children) {
return children && children[0].result.status;
}
function isFailure(args) {
return !args[0];
}
function clone(obj) {
var clonedObj = {};
for (var prop in obj) {

View File

@@ -18,7 +18,7 @@ jasmineRequire.HtmlReporter = function(j$) {
pendingSpecCount = 0,
htmlReporterMain,
symbols,
exceptionList = [];
failedSuites = [];
this.initialize = function() {
htmlReporterMain = createDom('div', {className: 'html-reporter'},
@@ -54,6 +54,10 @@ jasmineRequire.HtmlReporter = function(j$) {
};
this.suiteDone = function(result) {
if (result.failedExpectations && result.failedExpectations.length > 0) {
failedSuites.push(result);
}
if (currentParent == topResults) {
return;
}
@@ -65,10 +69,6 @@ jasmineRequire.HtmlReporter = function(j$) {
currentParent.addChild(result, 'spec');
};
this.afterAllEvent = function(error) {
exceptionList.push(error);
};
var failures = [];
this.specDone = function(result) {
if (result.status != 'disabled') {
@@ -141,10 +141,13 @@ jasmineRequire.HtmlReporter = function(j$) {
var statusBarClassName = 'bar ' + ((failureCount > 0) ? 'failed' : 'passed');
alert.appendChild(createDom('span', {className: statusBarClassName}, statusBarMessage));
for(i = 0; i < exceptionList.length; i++) {
var errorBarMessage = 'AfterAll ' + (exceptionList[i]);
var errorBarClassName = 'bar errored';
alert.appendChild(createDom('span', {className: errorBarClassName}, errorBarMessage));
for(i = 0; i < failedSuites.length; i++) {
var failedSuite = failedSuites[i];
for(var j = 0; j < failedSuite.failedExpectations.length; j++) {
var errorBarMessage = 'AfterAll ' + failedSuite.failedExpectations[j].message;
var errorBarClassName = 'bar errored';
alert.appendChild(createDom('span', {className: errorBarClassName}, errorBarMessage));
}
}
var results = find('.results');