Merge branch 'beforeAll' into master

Conflicts:
	lib/jasmine-core/boot.js
	lib/jasmine-core/boot/boot.js
	lib/jasmine-core/jasmine.css
	lib/jasmine-core/jasmine.js
	spec/core/SpecSpec.js
	spec/core/SuiteSpec.js
	spec/core/integration/EnvSpec.js
	spec/node_suite.js
	src/core/Env.js
	src/core/requireCore.js
	src/core/util.js
This commit is contained in:
slackersoft
2014-09-24 20:19:47 -07:00
29 changed files with 2512 additions and 655 deletions

View File

@@ -19,7 +19,8 @@ getJasmineRequireObj().ConsoleReporter = function() {
red: '\x1B[31m',
yellow: '\x1B[33m',
none: '\x1B[0m'
};
},
failedSuites = [];
this.jasmineStarted = function() {
specCount = 0;
@@ -54,9 +55,12 @@ getJasmineRequireObj().ConsoleReporter = function() {
printNewline();
var seconds = timer.elapsed() / 1000;
print('Finished in ' + seconds + ' ' + plural('second', seconds));
printNewline();
for(i = 0; i < failedSuites.length; i++) {
suiteFailureDetails(failedSuites[i]);
}
onComplete(failureCount === 0);
};
@@ -81,6 +85,13 @@ getJasmineRequireObj().ConsoleReporter = function() {
}
};
this.suiteDone = function(result) {
if (result.failedExpectations && result.failedExpectations.length > 0) {
failureCount++;
failedSuites.push(result);
}
};
return this;
function printNewline() {
@@ -125,6 +136,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

@@ -14,11 +14,19 @@ getJasmineRequireObj().Env = function(j$) {
this.clock = new j$.Clock(global, new j$.DelayedFunctionScheduler(), new j$.MockDate(global));
var runnableLookupTable = {};
var spies = [];
var runnableResources = {};
var currentSpec = null;
var currentSuite = null;
var currentlyExecutingSuites = [];
var currentDeclarationSuite = null;
var currentSuite = function() {
return currentlyExecutingSuites[currentlyExecutingSuites.length - 1];
};
var currentRunnable = function() {
return currentSpec || currentSuite();
};
var reporter = new j$.ReportDispatcher([
'jasmineStarted',
@@ -33,11 +41,21 @@ getJasmineRequireObj().Env = function(j$) {
return true;
};
var equalityTesters = [];
var customEqualityTesters = [];
this.addCustomEqualityTester = function(tester) {
customEqualityTesters.push(tester);
if(!currentRunnable()) {
throw new Error('Custom Equalities must be added in a before function or a spec');
}
runnableResources[currentRunnable().id].customEqualityTesters.push(tester);
};
this.addMatchers = function(matchersToAdd) {
if(!currentRunnable()) {
throw new Error('Matchers must be added in a before function or a spec');
}
var customMatchers = runnableResources[currentRunnable().id].customMatchers;
for (var matcherName in matchersToAdd) {
customMatchers[matcherName] = matchersToAdd[matcherName];
}
};
j$.Expectation.addCoreMatchers(j$.matchers);
@@ -55,7 +73,8 @@ getJasmineRequireObj().Env = function(j$) {
var expectationFactory = function(actual, spec) {
return j$.Expectation.Factory({
util: j$.matchersUtil,
customEqualityTesters: customEqualityTesters,
customEqualityTesters: runnableResources[spec.id].customEqualityTesters,
customMatchers: runnableResources[spec.id].customMatchers,
actual: actual,
addExpectationResult: addExpectationResult
});
@@ -65,30 +84,44 @@ getJasmineRequireObj().Env = function(j$) {
}
};
var specStarted = function(spec) {
currentSpec = spec;
reporter.specStarted(spec.result);
var defaultResourcesForRunnable = function(id, parentRunnableId) {
var resources = {spies: [], customEqualityTesters: [], customMatchers: {}};
if(runnableResources[parentRunnableId]){
resources.customEqualityTesters = j$.util.clone(runnableResources[parentRunnableId].customEqualityTesters);
resources.customMatchers = j$.util.clone(runnableResources[parentRunnableId].customMatchers);
}
runnableResources[id] = resources;
};
var beforeFns = function(suite) {
var clearResourcesForRunnable = function(id) {
spyRegistry.clearSpies();
delete runnableResources[id];
};
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)
};
};
};
@@ -146,65 +179,54 @@ 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;
currentSuite = topSuite;
defaultResourcesForRunnable(topSuite.id);
currentDeclarationSuite = topSuite;
this.topSuite = function() {
return topSuite;
};
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++) {
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) {
reporter.addReporter(reporterToAdd);
};
this.addMatchers = function(matchersToAdd) {
j$.Expectation.addMatchers(matchersToAdd);
};
this.spyOn = function(obj, methodName) {
if (j$.util.isUndefined(obj)) {
throw new Error('spyOn could not find an object to spy upon for ' + methodName + '()');
var spyRegistry = new j$.SpyRegistry({currentSpies: function() {
if(!currentRunnable()) {
throw new Error('Spies must be created in a before function or a spec');
}
return runnableResources[currentRunnable().id].spies;
}});
if (j$.util.isUndefined(obj[methodName])) {
throw new Error(methodName + '() method does not exist');
}
if (obj[methodName] && j$.isSpy(obj[methodName])) {
//TODO?: should this return the current spy? Downside: may cause user confusion about spy state
throw new Error(methodName + ' has already been spied upon');
}
var spy = j$.createSpy(methodName, obj[methodName]);
spies.push({
spy: spy,
baseObj: obj,
methodName: methodName,
originalValue: obj[methodName]
});
obj[methodName] = spy;
return spy;
this.spyOn = function() {
return spyRegistry.spyOn.apply(spyRegistry, arguments);
};
var suiteFactory = function(description) {
@@ -212,40 +234,33 @@ getJasmineRequireObj().Env = function(j$) {
env: self,
id: getNextSuiteId(),
description: description,
parentSuite: currentSuite,
parentSuite: currentDeclarationSuite,
queueRunner: queueRunnerFactory,
onStart: suiteStarted,
expectationFactory: expectationFactory,
expectationResultFactory: expectationResultFactory,
resultCallback: function(attrs) {
if (!suite.disabled) {
clearResourcesForRunnable(suite.id);
currentlyExecutingSuites.pop();
}
reporter.suiteDone(attrs);
}
});
runnableLookupTable[suite.id] = suite;
return suite;
function suiteStarted(suite) {
currentlyExecutingSuites.push(suite);
defaultResourcesForRunnable(suite.id, suite.parentSuite.id);
reporter.suiteStarted(suite.result);
}
};
this.describe = function(description, specDefinitions) {
var suite = suiteFactory(description);
var parentSuite = currentSuite;
parentSuite.addChild(suite);
currentSuite = suite;
var declarationError = null;
try {
specDefinitions.call(suite);
} catch (e) {
declarationError = e;
}
if (declarationError) {
this.it('encountered a declaration exception', function() {
throw declarationError;
});
}
currentSuite = parentSuite;
addSpecsToSuite(suite, specDefinitions);
return suite;
};
@@ -255,15 +270,75 @@ getJasmineRequireObj().Env = function(j$) {
return suite;
};
var focusedRunnables = [];
this.fdescribe = function(description, specDefinitions) {
var suite = suiteFactory(description);
suite.isFocused = true;
focusedRunnables.push(suite.id);
unfocusAncestor();
addSpecsToSuite(suite, specDefinitions);
return suite;
};
function addSpecsToSuite(suite, specDefinitions) {
var parentSuite = currentDeclarationSuite;
parentSuite.addChild(suite);
currentDeclarationSuite = suite;
var declarationError = null;
try {
specDefinitions.call(suite);
} catch (e) {
declarationError = e;
}
if (declarationError) {
self.it('encountered a declaration exception', function() {
throw declarationError;
});
}
currentDeclarationSuite = parentSuite;
}
function findFocusedAncestor(suite) {
while (suite) {
if (suite.isFocused) {
return suite.id;
}
suite = suite.parentSuite;
}
return null;
}
function unfocusAncestor() {
var focusedAncestor = findFocusedAncestor(currentDeclarationSuite);
if (focusedAncestor) {
for (var i = 0; i < focusedRunnables.length; i++) {
if (focusedRunnables[i] === focusedAncestor) {
focusedRunnables.splice(i, 1);
break;
}
}
}
}
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);
@@ -272,7 +347,8 @@ getJasmineRequireObj().Env = function(j$) {
description: description,
expectationResultFactory: expectationResultFactory,
queueRunnerFactory: queueRunnerFactory,
fn: fn
userContext: function() { return suite.clonedSharedUserContext(); },
queueableFn: { fn: fn, type: 'it', timeout: function() { return j$.DEFAULT_TIMEOUT_INTERVAL; } }
});
runnableLookupTable[spec.id] = spec;
@@ -283,30 +359,22 @@ getJasmineRequireObj().Env = function(j$) {
return spec;
function removeAllSpies() {
for (var i = 0; i < spies.length; i++) {
var spyEntry = spies[i];
spyEntry.baseObj[spyEntry.methodName] = spyEntry.originalValue;
}
spies = [];
}
function specResultCallback(result) {
removeAllSpies();
j$.Expectation.resetMatchers();
customEqualityTesters = [];
clearResourcesForRunnable(spec.id);
currentSpec = null;
reporter.specDone(result);
}
};
var suiteStarted = function(suite) {
reporter.suiteStarted(suite.result);
function specStarted(spec) {
currentSpec = spec;
defaultResourcesForRunnable(spec.id, suite.id);
reporter.specStarted(spec.result);
}
};
this.it = function(description, fn) {
var spec = specFactory(description, fn, currentSuite);
currentSuite.addChild(spec);
var spec = specFactory(description, fn, currentDeclarationSuite);
currentDeclarationSuite.addChild(spec);
return spec;
};
@@ -316,20 +384,36 @@ getJasmineRequireObj().Env = function(j$) {
return spec;
};
this.fit = function(description, fn ){
var spec = this.it(description, fn);
focusedRunnables.push(spec.id);
unfocusAncestor();
return spec;
};
this.expect = function(actual) {
if (!currentSpec) {
if (!currentRunnable()) {
throw new Error('\'expect\' was used when there was no current spec, this could be because an asynchronous test timed out');
}
return currentSpec.expect(actual);
return currentRunnable().expect(actual);
};
this.beforeEach = function(beforeEachFunction) {
currentSuite.beforeEach(beforeEachFunction);
currentDeclarationSuite.beforeEach({ fn: beforeEachFunction, type: 'beforeEach', timeout: function() { return j$.DEFAULT_TIMEOUT_INTERVAL; } });
};
this.beforeAll = function(beforeAllFunction) {
currentDeclarationSuite.beforeAll({ fn: beforeAllFunction, type: 'beforeAll', timeout: function() { return j$.DEFAULT_TIMEOUT_INTERVAL; } });
};
this.afterEach = function(afterEachFunction) {
currentSuite.afterEach(afterEachFunction);
currentDeclarationSuite.afterEach({ fn: afterEachFunction, type: 'afterEach', timeout: function() { return j$.DEFAULT_TIMEOUT_INTERVAL; } });
};
this.afterAll = function(afterAllFunction) {
currentDeclarationSuite.afterAll({ fn: afterAllFunction, type: 'afterAll', timeout: function() { return j$.DEFAULT_TIMEOUT_INTERVAL; } });
};
this.pending = function() {
@@ -343,7 +427,7 @@ getJasmineRequireObj().Env = function(j$) {
message += error.message || error;
}
currentSpec.addExpectationResult(false, {
currentRunnable().addExpectationResult(false, {
matcherName: '',
passed: false,
expected: '',

View File

@@ -1,7 +1,5 @@
getJasmineRequireObj().Expectation = function() {
var matchers = {};
function Expectation(options) {
this.util = options.util || { buildFailureMessage: function() {} };
this.customEqualityTesters = options.customEqualityTesters || [];
@@ -9,8 +7,9 @@ getJasmineRequireObj().Expectation = function() {
this.addExpectationResult = options.addExpectationResult || function(){};
this.isNot = options.isNot;
for (var matcherName in matchers) {
this[matcherName] = matchers[matcherName];
var customMatchers = options.customMatchers || {};
for (var matcherName in customMatchers) {
this[matcherName] = Expectation.prototype.wrapCompare(matcherName, customMatchers[matcherName]);
}
}
@@ -77,19 +76,6 @@ getJasmineRequireObj().Expectation = function() {
}
};
Expectation.addMatchers = function(matchersToAdd) {
for (var name in matchersToAdd) {
var matcher = matchersToAdd[name];
matchers[name] = Expectation.prototype.wrapCompare(name, matcher);
}
};
Expectation.resetMatchers = function() {
for (var name in matchers) {
delete matchers[name];
}
};
Expectation.Factory = function(options) {
options = options || {};

View File

@@ -11,31 +11,31 @@ 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 = {};
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,
self = this,
iterativeIndex;
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,41 +45,46 @@ 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);
handleException(e, queueableFn);
}
}
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.'));
var error = new Error('Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.');
onException(error, queueableFn);
next();
}, j$.DEFAULT_TIMEOUT_INTERVAL]]);
}, queueableFn.timeout()]]);
}
try {
fn.call(self.userContext, next);
queueableFn.fn.call(self.userContext, next);
} catch (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..

View File

@@ -4,17 +4,16 @@ getJasmineRequireObj().Spec = function(j$) {
this.resultCallback = attrs.resultCallback || function() {};
this.id = attrs.id;
this.description = attrs.description || '';
this.fn = attrs.fn;
this.beforeFns = attrs.beforeFns || function() { return []; };
this.afterFns = attrs.afterFns || function() { return []; };
this.queueableFn = attrs.queueableFn;
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() {};
this.catchingExceptions = attrs.catchingExceptions || function() { return true; };
if (!this.fn) {
if (!this.queueableFn.fn) {
this.pend();
}
@@ -50,30 +49,16 @@ getJasmineRequireObj().Spec = function(j$) {
return;
}
var allFns = this.beforeFns().concat(this.fn).concat(this.afterFns());
var fns = this.beforeAndAfterFns();
var allFns = fns.befores.concat(this.queueableFn).concat(fns.afters);
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);
@@ -84,6 +69,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;
};
@@ -108,6 +108,10 @@ getJasmineRequireObj().Spec = function(j$) {
}
};
Spec.prototype.isExecutable = function() {
return !this.disabled && !this.markedPending;
};
Spec.prototype.getFullName = function() {
return this.getSpecName(this);
};

45
src/core/SpyRegistry.js Normal file
View File

@@ -0,0 +1,45 @@
getJasmineRequireObj().SpyRegistry = function(j$) {
function SpyRegistry(options) {
options = options || {};
var currentSpies = options.currentSpies || function() { return []; };
this.spyOn = function(obj, methodName) {
if (j$.util.isUndefined(obj)) {
throw new Error('spyOn could not find an object to spy upon for ' + methodName + '()');
}
if (j$.util.isUndefined(obj[methodName])) {
throw new Error(methodName + '() method does not exist');
}
if (obj[methodName] && j$.isSpy(obj[methodName])) {
//TODO?: should this return the current spy? Downside: may cause user confusion about spy state
throw new Error(methodName + ' has already been spied upon');
}
var spy = j$.createSpy(methodName, obj[methodName]);
currentSpies().push({
spy: spy,
baseObj: obj,
methodName: methodName,
originalValue: obj[methodName]
});
obj[methodName] = spy;
return spy;
};
this.clearSpies = function() {
var spies = currentSpies();
for (var i = 0; i < spies.length; i++) {
var spyEntry = spies[i];
spyEntry.baseObj[spyEntry.methodName] = spyEntry.originalValue;
}
};
}
return SpyRegistry;
};

View File

@@ -7,9 +7,13 @@ getJasmineRequireObj().Suite = function() {
this.onStart = attrs.onStart || 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 = [];
this.beforeAllFns = [];
this.afterAllFns = [];
this.queueRunner = attrs.queueRunner || function() {};
this.disabled = false;
@@ -17,12 +21,16 @@ getJasmineRequireObj().Suite = function() {
this.result = {
id: this.id,
status: this.disabled ? 'disabled' : '',
description: this.description,
fullName: this.getFullName()
fullName: this.getFullName(),
failedExpectations: []
};
}
Suite.prototype.expect = function(actual) {
return this.expectationFactory(actual, this);
};
Suite.prototype.getFullName = function() {
var fullName = this.description;
for (var parentSuite = this.parentSuite; parentSuite; parentSuite = parentSuite.parentSuite) {
@@ -42,10 +50,18 @@ getJasmineRequireObj().Suite = function() {
this.beforeFns.unshift(fn);
};
Suite.prototype.beforeAll = function(fn) {
this.beforeAllFns.push(fn);
};
Suite.prototype.afterEach = function(fn) {
this.afterFns.unshift(fn);
};
Suite.prototype.afterAll = function(fn) {
this.afterAllFns.push(fn);
};
Suite.prototype.addChild = function(child) {
this.children.push(child);
};
@@ -62,16 +78,25 @@ getJasmineRequireObj().Suite = function() {
var allFns = [];
for (var i = 0; i < this.children.length; i++) {
allFns.push(wrapChildAsAsync(this.children[i]));
if (this.isExecutable()) {
allFns = allFns.concat(this.beforeAllFns);
for (var i = 0; i < this.children.length; i++) {
allFns.push(wrapChildAsAsync(this.children[i]));
}
allFns = allFns.concat(this.afterAllFns);
}
this.queueRunner({
fns: allFns,
onComplete: complete
queueableFns: allFns,
onComplete: complete,
userContext: this.sharedUserContext(),
onException: function() { self.onException.apply(self, arguments); }
});
function complete() {
self.result.status = self.disabled ? 'disabled' : 'finished';
self.resultCallback(self.result);
if (onComplete) {
@@ -80,10 +105,82 @@ getJasmineRequireObj().Suite = function() {
}
function wrapChildAsAsync(child) {
return function(done) { child.execute(done); };
return { fn: function(done) { child.execute(done); } };
}
};
Suite.prototype.isExecutable = function() {
var foundActive = false;
for(var i = 0; i < this.children.length; i++) {
if(this.children[i].isExecutable()) {
foundActive = true;
break;
}
}
return foundActive;
};
Suite.prototype.sharedUserContext = function() {
if (!this.sharedContext) {
this.sharedContext = this.parentSuite ? clone(this.parentSuite.sharedUserContext()) : {};
}
return this.sharedContext;
};
Suite.prototype.clonedSharedUserContext = function() {
return clone(this.sharedUserContext());
};
Suite.prototype.onException = function() {
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)){
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) {
if (obj.hasOwnProperty(prop)) {
clonedObj[prop] = obj[prop];
}
}
return clonedObj;
}
return Suite;
};

View File

@@ -33,6 +33,7 @@ getJasmineRequireObj = (function (jasmineGlobal) {
j$.QueueRunner = jRequire.QueueRunner(j$);
j$.ReportDispatcher = jRequire.ReportDispatcher();
j$.Spec = jRequire.Spec(j$);
j$.SpyRegistry = jRequire.SpyRegistry(j$);
j$.SpyStrategy = jRequire.SpyStrategy();
j$.Suite = jRequire.Suite();
j$.Timer = jRequire.Timer();

View File

@@ -24,6 +24,14 @@ getJasmineRequireObj().interface = function(jasmine, env) {
return env.afterEach(afterEachFunction);
},
beforeAll: function(beforeAllFunction) {
return env.beforeAll(beforeAllFunction);
},
afterAll: function(afterAllFunction) {
return env.afterAll(afterAllFunction);
},
expect: function(actual) {
return env.expect(actual);
},

View File

@@ -40,5 +40,20 @@ getJasmineRequireObj().util = function() {
return false;
};
util.clone = function(obj) {
if (Object.prototype.toString.apply(obj) === '[object Array]') {
return obj.slice();
}
var cloned = {};
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
cloned[prop] = obj[prop];
}
}
return cloned;
};
return util;
};

View File

@@ -17,7 +17,8 @@ jasmineRequire.HtmlReporter = function(j$) {
failureCount = 0,
pendingSpecCount = 0,
htmlReporterMain,
symbols;
symbols,
failedSuites = [];
this.initialize = function() {
clearPrior();
@@ -54,6 +55,10 @@ jasmineRequire.HtmlReporter = function(j$) {
};
this.suiteDone = function(result) {
if (result.failedExpectations && result.failedExpectations.length > 0) {
failedSuites.push(result);
}
if (currentParent == topResults) {
return;
}
@@ -149,6 +154,15 @@ jasmineRequire.HtmlReporter = function(j$) {
alert.appendChild(createDom('span', {className: statusBarClassName}, statusBarMessage));
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');
results.appendChild(summary);

View File

@@ -194,6 +194,10 @@ body {
background-color: $neutral-color;
}
&.errored {
background-color: $failing-color;
}
&.menu {
background-color: #fff;
color: $faint-text-color;