Implement TreeProcessor to solve some issues with running the suite

- execute beforeAll/afterAll once per suite instead of once per child
  when running focused specs/suites Fixes #773
- refuse to execute an order if it would cause a suite with a beforeAll
  or afterAll to be re-entered after leaving once
- report children of an xdescribe similarly to how they would be
  reported if they were themselves x'd out Fixes #774
- only process the tree once instead of figuring it out again at each
  level

[finishes #87545620]
Fixes #776
This commit is contained in:
slackersoft
2015-02-27 11:16:53 -08:00
committed by Chris Amavisca and Gregg Van Hove
parent 0c68cc4afc
commit 715de7aa38
11 changed files with 1289 additions and 503 deletions

View File

@@ -100,27 +100,21 @@ getJasmineRequireObj().Env = function(j$) {
delete runnableResources[id];
};
var beforeAndAfterFns = function(suite, runnablesExplictlySet) {
var beforeAndAfterFns = function(suite) {
return function() {
var befores = [],
afters = [],
beforeAlls = [],
afterAlls = [];
afters = [];
while(suite) {
befores = befores.concat(suite.beforeFns);
afters = afters.concat(suite.afterFns);
if (runnablesExplictlySet()) {
beforeAlls = beforeAlls.concat(suite.beforeAllFns);
afterAlls = afterAlls.concat(suite.afterAllFns);
}
suite = suite.parentSuite;
}
return {
befores: beforeAlls.reverse().concat(befores.reverse()),
afters: afters.concat(afterAlls)
befores: befores.reverse(),
afters: afters
};
};
};
@@ -190,26 +184,40 @@ getJasmineRequireObj().Env = function(j$) {
};
this.execute = function(runnablesToRun) {
if(runnablesToRun) {
runnablesExplictlySet = true;
} else if (focusedRunnables.length) {
runnablesExplictlySet = true;
runnablesToRun = focusedRunnables;
} else {
runnablesToRun = [topSuite.id];
if(!runnablesToRun) {
if (focusedRunnables.length) {
runnablesToRun = focusedRunnables;
} else {
runnablesToRun = [topSuite.id];
}
}
var processor = new j$.TreeProcessor({
tree: topSuite,
runnableIds: runnablesToRun,
queueRunnerFactory: queueRunnerFactory,
nodeStart: function(suite) {
currentlyExecutingSuites.push(suite);
defaultResourcesForRunnable(suite.id, suite.parentSuite.id);
reporter.suiteStarted(suite.result);
},
nodeComplete: function(suite, result) {
if (!suite.disabled) {
clearResourcesForRunnable(suite.id);
}
currentlyExecutingSuites.pop();
reporter.suiteDone(result);
}
});
var allFns = [];
for(var i = 0; i < runnablesToRun.length; i++) {
var runnable = runnableLookupTable[runnablesToRun[i]];
allFns.push((function(runnable) { return { fn: function(done) { runnable.execute(done); } }; })(runnable));
if(!processor.processTree().valid) {
throw new Error('Invalid order: would cause a beforeAll or afterAll to be run multiple times');
}
reporter.jasmineStarted({
totalSpecsDefined: totalSpecsDefined
});
queueRunnerFactory({queueableFns: allFns, onComplete: reporter.jasmineDone});
processor.execute(reporter.jasmineDone);
};
this.addReporter = function(reporterToAdd) {
@@ -233,28 +241,12 @@ getJasmineRequireObj().Env = function(j$) {
id: getNextSuiteId(),
description: description,
parentSuite: currentDeclarationSuite,
queueRunner: queueRunnerFactory,
onStart: suiteStarted,
expectationFactory: expectationFactory,
expectationResultFactory: expectationResultFactory,
runnablesExplictlySetGetter: runnablesExplictlySetGetter,
resultCallback: function(attrs) {
if (!suite.disabled) {
clearResourcesForRunnable(suite.id);
}
currentlyExecutingSuites.pop();
reporter.suiteDone(attrs);
}
expectationResultFactory: expectationResultFactory
});
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) {
@@ -326,17 +318,11 @@ getJasmineRequireObj().Env = function(j$) {
}
}
var runnablesExplictlySet = false;
var runnablesExplictlySetGetter = function(){
return runnablesExplictlySet;
};
var specFactory = function(description, fn, suite, timeout) {
totalSpecsDefined++;
var spec = new j$.Spec({
id: getNextSpecId(),
beforeAndAfterFns: beforeAndAfterFns(suite, runnablesExplictlySetGetter),
beforeAndAfterFns: beforeAndAfterFns(suite),
expectationFactory: expectationFactory,
resultCallback: specResultCallback,
getSpecName: function(spec) {