Move suite execution and spec queueRunner building from TreeProcesor to Runner
This: * Sets the stage for getting suite and spec execution in one place * Greatly simplifies the interaction between Runner and TreeProcessor * Focuses TreeProcessor more on building execution trees
This commit is contained in:
@@ -9412,6 +9412,7 @@ getJasmineRequireObj().Runner = function(j$) {
|
|||||||
#getConfig;
|
#getConfig;
|
||||||
#reportSpecDone;
|
#reportSpecDone;
|
||||||
#executedBefore;
|
#executedBefore;
|
||||||
|
#currentlyExecutingSuites;
|
||||||
|
|
||||||
constructor(options) {
|
constructor(options) {
|
||||||
this.#topSuite = options.topSuite;
|
this.#topSuite = options.topSuite;
|
||||||
@@ -9427,7 +9428,7 @@ getJasmineRequireObj().Runner = function(j$) {
|
|||||||
this.hasFailures = false;
|
this.hasFailures = false;
|
||||||
this.#executedBefore = false;
|
this.#executedBefore = false;
|
||||||
|
|
||||||
this.currentlyExecutingSuites_ = [];
|
this.#currentlyExecutingSuites = [];
|
||||||
this.currentSpec = null;
|
this.currentSpec = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -9436,8 +9437,8 @@ getJasmineRequireObj().Runner = function(j$) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
currentSuite() {
|
currentSuite() {
|
||||||
return this.currentlyExecutingSuites_[
|
return this.#currentlyExecutingSuites[
|
||||||
this.currentlyExecutingSuites_.length - 1
|
this.#currentlyExecutingSuites.length - 1
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -9471,51 +9472,9 @@ getJasmineRequireObj().Runner = function(j$) {
|
|||||||
const processor = new this.#TreeProcessor({
|
const processor = new this.#TreeProcessor({
|
||||||
tree: this.#topSuite,
|
tree: this.#topSuite,
|
||||||
runnableIds: runablesToRun,
|
runnableIds: runablesToRun,
|
||||||
runQueue: options => {
|
executeTopSuite: this.#executeTopSuite.bind(this),
|
||||||
if (options.isLeaf) {
|
executeSpec: this.#executeSpec.bind(this),
|
||||||
// A spec
|
executeSuiteSegment: this.#executeSuiteSegment.bind(this),
|
||||||
options.SkipPolicy = j$.CompleteOnFirstErrorSkipPolicy;
|
|
||||||
} else {
|
|
||||||
// A suite
|
|
||||||
if (config.stopOnSpecFailure) {
|
|
||||||
options.SkipPolicy = j$.CompleteOnFirstErrorSkipPolicy;
|
|
||||||
} else {
|
|
||||||
options.SkipPolicy = j$.SkipAfterBeforeAllErrorPolicy;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.#runQueue(options);
|
|
||||||
},
|
|
||||||
globalErrors: this.#globalErrors,
|
|
||||||
failSpecWithNoExpectations: config.failSpecWithNoExpectations,
|
|
||||||
detectLateRejectionHandling: config.detectLateRejectionHandling,
|
|
||||||
nodeStart: (suite, next) => {
|
|
||||||
this.currentlyExecutingSuites_.push(suite);
|
|
||||||
this.#runableResources.initForRunable(suite.id, suite.parentSuite.id);
|
|
||||||
this.#reportDispatcher.suiteStarted(suite.result).then(next);
|
|
||||||
suite.startTimer();
|
|
||||||
},
|
|
||||||
nodeComplete: (suite, result, next) => {
|
|
||||||
if (suite !== this.currentSuite()) {
|
|
||||||
throw new Error('Tried to complete the wrong suite');
|
|
||||||
}
|
|
||||||
|
|
||||||
this.#runableResources.clearForRunable(suite.id);
|
|
||||||
this.currentlyExecutingSuites_.pop();
|
|
||||||
|
|
||||||
if (result.status === 'failed') {
|
|
||||||
this.hasFailures = true;
|
|
||||||
}
|
|
||||||
suite.endTimer();
|
|
||||||
|
|
||||||
if (suite.hadBeforeAllFailure) {
|
|
||||||
this.#reportChildrenOfBeforeAllFailure(suite).then(() => {
|
|
||||||
this.#reportSuiteDone(suite, result, next);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.#reportSuiteDone(suite, result, next);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
orderChildren: function(node) {
|
orderChildren: function(node) {
|
||||||
return order.sort(node.children);
|
return order.sort(node.children);
|
||||||
},
|
},
|
||||||
@@ -9551,7 +9510,7 @@ getJasmineRequireObj().Runner = function(j$) {
|
|||||||
parallel: false
|
parallel: false
|
||||||
});
|
});
|
||||||
|
|
||||||
this.currentlyExecutingSuites_.push(this.#topSuite);
|
this.#currentlyExecutingSuites.push(this.#topSuite);
|
||||||
await processor.execute();
|
await processor.execute();
|
||||||
|
|
||||||
if (this.#topSuite.hadBeforeAllFailure) {
|
if (this.#topSuite.hadBeforeAllFailure) {
|
||||||
@@ -9559,7 +9518,7 @@ getJasmineRequireObj().Runner = function(j$) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.#runableResources.clearForRunable(this.#topSuite.id);
|
this.#runableResources.clearForRunable(this.#topSuite.id);
|
||||||
this.currentlyExecutingSuites_.pop();
|
this.#currentlyExecutingSuites.pop();
|
||||||
let overallStatus, incompleteReason, incompleteCode;
|
let overallStatus, incompleteReason, incompleteCode;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
@@ -9606,6 +9565,128 @@ getJasmineRequireObj().Runner = function(j$) {
|
|||||||
return jasmineDoneInfo;
|
return jasmineDoneInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TreeProcessor callback.
|
||||||
|
#executeTopSuite(topSuite, wrappedChildren, done) {
|
||||||
|
const queueableFns = this.#addBeforeAndAfterAlls(
|
||||||
|
topSuite,
|
||||||
|
true,
|
||||||
|
wrappedChildren
|
||||||
|
);
|
||||||
|
this.#runQueueWithSkipPolicy({
|
||||||
|
queueableFns,
|
||||||
|
userContext: topSuite.sharedUserContext(),
|
||||||
|
onException: function() {
|
||||||
|
topSuite.handleException.apply(topSuite, arguments);
|
||||||
|
}.bind(this),
|
||||||
|
onComplete: done,
|
||||||
|
onMultipleDone: topSuite.onMultipleDone
|
||||||
|
? topSuite.onMultipleDone.bind(topSuite)
|
||||||
|
: null
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// TreeProcessor callback. Mutually recursive with TreeProcessor##executeNode.
|
||||||
|
#executeSuiteSegment(suite, excluded, wrappedChildren, done) {
|
||||||
|
const onStart = {
|
||||||
|
fn: next => {
|
||||||
|
this.#suiteSegmentStart(suite, next);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const queueableFns = [
|
||||||
|
onStart,
|
||||||
|
...this.#addBeforeAndAfterAlls(suite, excluded, wrappedChildren)
|
||||||
|
];
|
||||||
|
|
||||||
|
this.#runQueueWithSkipPolicy({
|
||||||
|
// TODO: if onComplete always takes 0-1 arguments (and it probably does)
|
||||||
|
// then it can be switched to an arrow fn with a named arg.
|
||||||
|
onComplete: function() {
|
||||||
|
const args = Array.prototype.slice.call(arguments, [0]);
|
||||||
|
this.#suiteSegmentComplete(suite, suite.getResult(), () => {
|
||||||
|
done.apply(undefined, args);
|
||||||
|
});
|
||||||
|
}.bind(this),
|
||||||
|
queueableFns,
|
||||||
|
userContext: suite.sharedUserContext(),
|
||||||
|
onException: function() {
|
||||||
|
suite.handleException.apply(suite, arguments);
|
||||||
|
},
|
||||||
|
onMultipleDone: suite.onMultipleDone
|
||||||
|
? suite.onMultipleDone.bind(suite)
|
||||||
|
: null
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// TreeProcessor callback.
|
||||||
|
#executeSpec(spec, excluded, done) {
|
||||||
|
const config = this.#getConfig();
|
||||||
|
spec.execute(
|
||||||
|
this.#runQueueWithSkipPolicy.bind(this),
|
||||||
|
this.#globalErrors,
|
||||||
|
done,
|
||||||
|
excluded,
|
||||||
|
config.failSpecWithNoExpectations,
|
||||||
|
config.detectLateRejectionHandling
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#addBeforeAndAfterAlls(suite, willExecute, wrappedChildren) {
|
||||||
|
if (willExecute) {
|
||||||
|
return suite.beforeAllFns
|
||||||
|
.concat(wrappedChildren)
|
||||||
|
.concat(suite.afterAllFns);
|
||||||
|
} else {
|
||||||
|
return wrappedChildren;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#suiteSegmentStart(suite, next) {
|
||||||
|
this.#currentlyExecutingSuites.push(suite);
|
||||||
|
this.#runableResources.initForRunable(suite.id, suite.parentSuite.id);
|
||||||
|
this.#reportDispatcher.suiteStarted(suite.result).then(next);
|
||||||
|
suite.startTimer();
|
||||||
|
}
|
||||||
|
|
||||||
|
#suiteSegmentComplete(suite, result, next) {
|
||||||
|
suite.cleanupBeforeAfter();
|
||||||
|
|
||||||
|
if (suite !== this.currentSuite()) {
|
||||||
|
throw new Error('Tried to complete the wrong suite');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.#runableResources.clearForRunable(suite.id);
|
||||||
|
this.#currentlyExecutingSuites.pop();
|
||||||
|
|
||||||
|
if (result.status === 'failed') {
|
||||||
|
this.hasFailures = true;
|
||||||
|
}
|
||||||
|
suite.endTimer();
|
||||||
|
|
||||||
|
if (suite.hadBeforeAllFailure) {
|
||||||
|
this.#reportChildrenOfBeforeAllFailure(suite).then(() => {
|
||||||
|
this.#reportSuiteDone(suite, result, next);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.#reportSuiteDone(suite, result, next);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#runQueueWithSkipPolicy(options) {
|
||||||
|
if (options.isLeaf) {
|
||||||
|
// A spec
|
||||||
|
options.SkipPolicy = j$.CompleteOnFirstErrorSkipPolicy;
|
||||||
|
} else {
|
||||||
|
// A suite
|
||||||
|
if (this.#getConfig().stopOnSpecFailure) {
|
||||||
|
options.SkipPolicy = j$.CompleteOnFirstErrorSkipPolicy;
|
||||||
|
} else {
|
||||||
|
options.SkipPolicy = j$.SkipAfterBeforeAllErrorPolicy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.#runQueue(options);
|
||||||
|
}
|
||||||
|
|
||||||
#reportSuiteDone(suite, result, next) {
|
#reportSuiteDone(suite, result, next) {
|
||||||
suite.reportedDone = true;
|
suite.reportedDone = true;
|
||||||
this.#reportDispatcher.suiteDone(result).then(next);
|
this.#reportDispatcher.suiteDone(result).then(next);
|
||||||
@@ -11305,13 +11386,10 @@ getJasmineRequireObj().TreeProcessor = function(j$) {
|
|||||||
|
|
||||||
class TreeProcessor {
|
class TreeProcessor {
|
||||||
#tree;
|
#tree;
|
||||||
#runQueue;
|
#executeTopSuite;
|
||||||
|
#executeSpec;
|
||||||
|
#executeSuiteSegment;
|
||||||
#runnableIds;
|
#runnableIds;
|
||||||
#nodeStart;
|
|
||||||
#nodeComplete;
|
|
||||||
#failSpecWithNoExpectations;
|
|
||||||
#detectLateRejectionHandling;
|
|
||||||
#globalErrors;
|
|
||||||
#orderChildren;
|
#orderChildren;
|
||||||
#excludeNode;
|
#excludeNode;
|
||||||
#stats;
|
#stats;
|
||||||
@@ -11320,12 +11398,9 @@ getJasmineRequireObj().TreeProcessor = function(j$) {
|
|||||||
constructor(attrs) {
|
constructor(attrs) {
|
||||||
this.#tree = attrs.tree;
|
this.#tree = attrs.tree;
|
||||||
this.#runnableIds = attrs.runnableIds;
|
this.#runnableIds = attrs.runnableIds;
|
||||||
this.#runQueue = attrs.runQueue;
|
this.#executeTopSuite = attrs.executeTopSuite;
|
||||||
this.#nodeStart = attrs.nodeStart || function() {};
|
this.#executeSpec = attrs.executeSpec;
|
||||||
this.#nodeComplete = attrs.nodeComplete || function() {};
|
this.#executeSuiteSegment = attrs.executeSuiteSegment;
|
||||||
this.#failSpecWithNoExpectations = !!attrs.failSpecWithNoExpectations;
|
|
||||||
this.#detectLateRejectionHandling = !!attrs.detectLateRejectionHandling;
|
|
||||||
this.#globalErrors = attrs.globalErrors;
|
|
||||||
|
|
||||||
this.#orderChildren =
|
this.#orderChildren =
|
||||||
attrs.orderChildren ||
|
attrs.orderChildren ||
|
||||||
@@ -11356,20 +11431,10 @@ getJasmineRequireObj().TreeProcessor = function(j$) {
|
|||||||
throw new Error('invalid order');
|
throw new Error('invalid order');
|
||||||
}
|
}
|
||||||
|
|
||||||
const childFns = this.#wrapChildren(this.#tree, 0);
|
const wrappedChildren = this.#wrapChildren(this.#tree, 0);
|
||||||
|
|
||||||
await new Promise(resolve => {
|
await new Promise(resolve => {
|
||||||
this.#runQueue({
|
this.#executeTopSuite(this.#tree, wrappedChildren, resolve);
|
||||||
queueableFns: childFns,
|
|
||||||
userContext: this.#tree.sharedUserContext(),
|
|
||||||
onException: function() {
|
|
||||||
this.#tree.handleException.apply(this.#tree, arguments);
|
|
||||||
}.bind(this),
|
|
||||||
onComplete: resolve,
|
|
||||||
onMultipleDone: this.#tree.onMultipleDone
|
|
||||||
? this.#tree.onMultipleDone.bind(this.#tree)
|
|
||||||
: null
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -11454,55 +11519,22 @@ getJasmineRequireObj().TreeProcessor = function(j$) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.#stats[node.id].willExecute) {
|
return result;
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
return node.beforeAllFns.concat(result).concat(node.afterAllFns);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#executeNode(node, segmentNumber) {
|
#executeNode(node, segmentNumber) {
|
||||||
if (node.children) {
|
if (node.children) {
|
||||||
return {
|
return {
|
||||||
fn: function(done) {
|
fn: done => {
|
||||||
const onStart = {
|
const wrappedChildren = this.#wrapChildren(node, segmentNumber);
|
||||||
fn: next => {
|
const willExecute = this.#stats[node.id].willExecute;
|
||||||
this.#nodeStart(node, next);
|
this.#executeSuiteSegment(node, willExecute, wrappedChildren, done);
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
this.#runQueue({
|
|
||||||
onComplete: function() {
|
|
||||||
const args = Array.prototype.slice.call(arguments, [0]);
|
|
||||||
node.cleanupBeforeAfter();
|
|
||||||
this.#nodeComplete(node, node.getResult(), () => {
|
|
||||||
done.apply(undefined, args);
|
|
||||||
});
|
|
||||||
}.bind(this),
|
|
||||||
queueableFns: [onStart].concat(
|
|
||||||
this.#wrapChildren(node, segmentNumber)
|
|
||||||
),
|
|
||||||
userContext: node.sharedUserContext(),
|
|
||||||
onException: function() {
|
|
||||||
node.handleException.apply(node, arguments);
|
|
||||||
},
|
|
||||||
onMultipleDone: node.onMultipleDone
|
|
||||||
? node.onMultipleDone.bind(node)
|
|
||||||
: null
|
|
||||||
});
|
|
||||||
}.bind(this)
|
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
return {
|
return {
|
||||||
fn: done => {
|
fn: done => {
|
||||||
node.execute(
|
this.#executeSpec(node, this.#stats[node.id].excluded, done);
|
||||||
this.#runQueue,
|
|
||||||
this.#globalErrors,
|
|
||||||
done,
|
|
||||||
this.#stats[node.id].excluded,
|
|
||||||
this.#failSpecWithNoExpectations,
|
|
||||||
this.#detectLateRejectionHandling
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
describe('Runner', function() {
|
describe('Runner', function() {
|
||||||
describe('TreeProcessor nodeComplete callback', function() {
|
// TODO: Update and re-enable these once things stabilize
|
||||||
it('throws if the wrong suite is passed to nodeComplete', async function() {
|
xdescribe('TreeProcessor suiteSegmentComplete callback', function() {
|
||||||
|
it('throws if the wrong suite is passed to suiteSegmentComplete', async function() {
|
||||||
const TreeProcessor = spyTreeProcessorCtor();
|
const TreeProcessor = spyTreeProcessorCtor();
|
||||||
const subject = new jasmineUnderTest.Runner({
|
const subject = new jasmineUnderTest.Runner({
|
||||||
...defaultCtorOptions(),
|
...defaultCtorOptions(),
|
||||||
@@ -16,11 +17,11 @@ describe('Runner', function() {
|
|||||||
parentSuite: stubSuite(),
|
parentSuite: stubSuite(),
|
||||||
startTimer: () => {}
|
startTimer: () => {}
|
||||||
};
|
};
|
||||||
await callWithNext(treeProcessorOpts.nodeStart, [suiteToRun]);
|
await callWithNext(treeProcessorOpts.suiteSegmentStart, [suiteToRun]);
|
||||||
|
|
||||||
expect(function() {
|
expect(function() {
|
||||||
const someOtherSuite = {};
|
const someOtherSuite = {};
|
||||||
treeProcessorOpts.nodeComplete(someOtherSuite, {}, () => {});
|
treeProcessorOpts.suiteSegmentComplete(someOtherSuite, {}, () => {});
|
||||||
}).toThrowError('Tried to complete the wrong suite');
|
}).toThrowError('Tried to complete the wrong suite');
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -41,8 +42,11 @@ describe('Runner', function() {
|
|||||||
startTimer: () => {},
|
startTimer: () => {},
|
||||||
endTimer: jasmine.createSpy('suiteToRun.endTimer')
|
endTimer: jasmine.createSpy('suiteToRun.endTimer')
|
||||||
};
|
};
|
||||||
await callWithNext(treeProcessorOpts.nodeStart, [suiteToRun]);
|
await callWithNext(treeProcessorOpts.suiteSegmentStart, [suiteToRun]);
|
||||||
await callWithNext(treeProcessorOpts.nodeComplete, [suiteToRun, {}]);
|
await callWithNext(treeProcessorOpts.suiteSegmentComplete, [
|
||||||
|
suiteToRun,
|
||||||
|
{}
|
||||||
|
]);
|
||||||
|
|
||||||
expect(suiteToRun.endTimer).toHaveBeenCalled();
|
expect(suiteToRun.endTimer).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
@@ -64,8 +68,8 @@ describe('Runner', function() {
|
|||||||
startTimer: () => {},
|
startTimer: () => {},
|
||||||
endTimer: jasmine.createSpy('suiteToRun.endTimer')
|
endTimer: jasmine.createSpy('suiteToRun.endTimer')
|
||||||
};
|
};
|
||||||
await callWithNext(treeProcessorOpts.nodeStart, [suiteToRun]);
|
await callWithNext(treeProcessorOpts.suiteSegmentStart, [suiteToRun]);
|
||||||
await callWithNext(treeProcessorOpts.nodeComplete, [
|
await callWithNext(treeProcessorOpts.suiteSegmentComplete, [
|
||||||
suiteToRun,
|
suiteToRun,
|
||||||
{ status: 'failed' }
|
{ status: 'failed' }
|
||||||
]);
|
]);
|
||||||
@@ -90,8 +94,8 @@ describe('Runner', function() {
|
|||||||
startTimer: () => {},
|
startTimer: () => {},
|
||||||
endTimer: jasmine.createSpy('suiteToRun.endTimer')
|
endTimer: jasmine.createSpy('suiteToRun.endTimer')
|
||||||
};
|
};
|
||||||
await callWithNext(treeProcessorOpts.nodeStart, [suiteToRun]);
|
await callWithNext(treeProcessorOpts.suiteSegmentStart, [suiteToRun]);
|
||||||
await callWithNext(treeProcessorOpts.nodeComplete, [
|
await callWithNext(treeProcessorOpts.suiteSegmentComplete, [
|
||||||
suiteToRun,
|
suiteToRun,
|
||||||
{ status: 'passed' }
|
{ status: 'passed' }
|
||||||
]);
|
]);
|
||||||
@@ -117,8 +121,8 @@ describe('Runner', function() {
|
|||||||
startTimer: () => {},
|
startTimer: () => {},
|
||||||
endTimer: jasmine.createSpy('suiteToRun.endTimer')
|
endTimer: jasmine.createSpy('suiteToRun.endTimer')
|
||||||
};
|
};
|
||||||
await callWithNext(treeProcessorOpts.nodeStart, [suiteToRun]);
|
await callWithNext(treeProcessorOpts.suiteSegmentStart, [suiteToRun]);
|
||||||
await callWithNext(treeProcessorOpts.nodeComplete, [
|
await callWithNext(treeProcessorOpts.suiteSegmentComplete, [
|
||||||
suiteToRun,
|
suiteToRun,
|
||||||
{ status: 'passed' }
|
{ status: 'passed' }
|
||||||
]);
|
]);
|
||||||
@@ -146,8 +150,8 @@ describe('Runner', function() {
|
|||||||
startTimer: () => {},
|
startTimer: () => {},
|
||||||
endTimer: jasmine.createSpy('suiteToRun.endTimer')
|
endTimer: jasmine.createSpy('suiteToRun.endTimer')
|
||||||
};
|
};
|
||||||
await callWithNext(treeProcessorOpts.nodeStart, [suiteToRun]);
|
await callWithNext(treeProcessorOpts.suiteSegmentStart, [suiteToRun]);
|
||||||
await callWithNext(treeProcessorOpts.nodeComplete, [
|
await callWithNext(treeProcessorOpts.suiteSegmentComplete, [
|
||||||
suiteToRun,
|
suiteToRun,
|
||||||
{ status: 'passed' }
|
{ status: 'passed' }
|
||||||
]);
|
]);
|
||||||
@@ -187,10 +191,10 @@ describe('Runner', function() {
|
|||||||
startTimer: () => {},
|
startTimer: () => {},
|
||||||
endTimer: jasmine.createSpy('suiteToRun.endTimer')
|
endTimer: jasmine.createSpy('suiteToRun.endTimer')
|
||||||
};
|
};
|
||||||
await callWithNext(treeProcessorOpts.nodeStart, [suiteToRun]);
|
await callWithNext(treeProcessorOpts.suiteSegmentStart, [suiteToRun]);
|
||||||
|
|
||||||
suiteToRun.hadBeforeAllFailure = true;
|
suiteToRun.hadBeforeAllFailure = true;
|
||||||
await callWithNext(treeProcessorOpts.nodeComplete, [
|
await callWithNext(treeProcessorOpts.suiteSegmentComplete, [
|
||||||
suiteToRun,
|
suiteToRun,
|
||||||
{ status: 'passed' }
|
{ status: 'passed' }
|
||||||
]);
|
]);
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -11,6 +11,7 @@ getJasmineRequireObj().Runner = function(j$) {
|
|||||||
#getConfig;
|
#getConfig;
|
||||||
#reportSpecDone;
|
#reportSpecDone;
|
||||||
#executedBefore;
|
#executedBefore;
|
||||||
|
#currentlyExecutingSuites;
|
||||||
|
|
||||||
constructor(options) {
|
constructor(options) {
|
||||||
this.#topSuite = options.topSuite;
|
this.#topSuite = options.topSuite;
|
||||||
@@ -26,7 +27,7 @@ getJasmineRequireObj().Runner = function(j$) {
|
|||||||
this.hasFailures = false;
|
this.hasFailures = false;
|
||||||
this.#executedBefore = false;
|
this.#executedBefore = false;
|
||||||
|
|
||||||
this.currentlyExecutingSuites_ = [];
|
this.#currentlyExecutingSuites = [];
|
||||||
this.currentSpec = null;
|
this.currentSpec = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,8 +36,8 @@ getJasmineRequireObj().Runner = function(j$) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
currentSuite() {
|
currentSuite() {
|
||||||
return this.currentlyExecutingSuites_[
|
return this.#currentlyExecutingSuites[
|
||||||
this.currentlyExecutingSuites_.length - 1
|
this.#currentlyExecutingSuites.length - 1
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,51 +71,9 @@ getJasmineRequireObj().Runner = function(j$) {
|
|||||||
const processor = new this.#TreeProcessor({
|
const processor = new this.#TreeProcessor({
|
||||||
tree: this.#topSuite,
|
tree: this.#topSuite,
|
||||||
runnableIds: runablesToRun,
|
runnableIds: runablesToRun,
|
||||||
runQueue: options => {
|
executeTopSuite: this.#executeTopSuite.bind(this),
|
||||||
if (options.isLeaf) {
|
executeSpec: this.#executeSpec.bind(this),
|
||||||
// A spec
|
executeSuiteSegment: this.#executeSuiteSegment.bind(this),
|
||||||
options.SkipPolicy = j$.CompleteOnFirstErrorSkipPolicy;
|
|
||||||
} else {
|
|
||||||
// A suite
|
|
||||||
if (config.stopOnSpecFailure) {
|
|
||||||
options.SkipPolicy = j$.CompleteOnFirstErrorSkipPolicy;
|
|
||||||
} else {
|
|
||||||
options.SkipPolicy = j$.SkipAfterBeforeAllErrorPolicy;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.#runQueue(options);
|
|
||||||
},
|
|
||||||
globalErrors: this.#globalErrors,
|
|
||||||
failSpecWithNoExpectations: config.failSpecWithNoExpectations,
|
|
||||||
detectLateRejectionHandling: config.detectLateRejectionHandling,
|
|
||||||
nodeStart: (suite, next) => {
|
|
||||||
this.currentlyExecutingSuites_.push(suite);
|
|
||||||
this.#runableResources.initForRunable(suite.id, suite.parentSuite.id);
|
|
||||||
this.#reportDispatcher.suiteStarted(suite.result).then(next);
|
|
||||||
suite.startTimer();
|
|
||||||
},
|
|
||||||
nodeComplete: (suite, result, next) => {
|
|
||||||
if (suite !== this.currentSuite()) {
|
|
||||||
throw new Error('Tried to complete the wrong suite');
|
|
||||||
}
|
|
||||||
|
|
||||||
this.#runableResources.clearForRunable(suite.id);
|
|
||||||
this.currentlyExecutingSuites_.pop();
|
|
||||||
|
|
||||||
if (result.status === 'failed') {
|
|
||||||
this.hasFailures = true;
|
|
||||||
}
|
|
||||||
suite.endTimer();
|
|
||||||
|
|
||||||
if (suite.hadBeforeAllFailure) {
|
|
||||||
this.#reportChildrenOfBeforeAllFailure(suite).then(() => {
|
|
||||||
this.#reportSuiteDone(suite, result, next);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.#reportSuiteDone(suite, result, next);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
orderChildren: function(node) {
|
orderChildren: function(node) {
|
||||||
return order.sort(node.children);
|
return order.sort(node.children);
|
||||||
},
|
},
|
||||||
@@ -150,7 +109,7 @@ getJasmineRequireObj().Runner = function(j$) {
|
|||||||
parallel: false
|
parallel: false
|
||||||
});
|
});
|
||||||
|
|
||||||
this.currentlyExecutingSuites_.push(this.#topSuite);
|
this.#currentlyExecutingSuites.push(this.#topSuite);
|
||||||
await processor.execute();
|
await processor.execute();
|
||||||
|
|
||||||
if (this.#topSuite.hadBeforeAllFailure) {
|
if (this.#topSuite.hadBeforeAllFailure) {
|
||||||
@@ -158,7 +117,7 @@ getJasmineRequireObj().Runner = function(j$) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.#runableResources.clearForRunable(this.#topSuite.id);
|
this.#runableResources.clearForRunable(this.#topSuite.id);
|
||||||
this.currentlyExecutingSuites_.pop();
|
this.#currentlyExecutingSuites.pop();
|
||||||
let overallStatus, incompleteReason, incompleteCode;
|
let overallStatus, incompleteReason, incompleteCode;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
@@ -205,6 +164,128 @@ getJasmineRequireObj().Runner = function(j$) {
|
|||||||
return jasmineDoneInfo;
|
return jasmineDoneInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TreeProcessor callback.
|
||||||
|
#executeTopSuite(topSuite, wrappedChildren, done) {
|
||||||
|
const queueableFns = this.#addBeforeAndAfterAlls(
|
||||||
|
topSuite,
|
||||||
|
true,
|
||||||
|
wrappedChildren
|
||||||
|
);
|
||||||
|
this.#runQueueWithSkipPolicy({
|
||||||
|
queueableFns,
|
||||||
|
userContext: topSuite.sharedUserContext(),
|
||||||
|
onException: function() {
|
||||||
|
topSuite.handleException.apply(topSuite, arguments);
|
||||||
|
}.bind(this),
|
||||||
|
onComplete: done,
|
||||||
|
onMultipleDone: topSuite.onMultipleDone
|
||||||
|
? topSuite.onMultipleDone.bind(topSuite)
|
||||||
|
: null
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// TreeProcessor callback. Mutually recursive with TreeProcessor##executeNode.
|
||||||
|
#executeSuiteSegment(suite, excluded, wrappedChildren, done) {
|
||||||
|
const onStart = {
|
||||||
|
fn: next => {
|
||||||
|
this.#suiteSegmentStart(suite, next);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const queueableFns = [
|
||||||
|
onStart,
|
||||||
|
...this.#addBeforeAndAfterAlls(suite, excluded, wrappedChildren)
|
||||||
|
];
|
||||||
|
|
||||||
|
this.#runQueueWithSkipPolicy({
|
||||||
|
// TODO: if onComplete always takes 0-1 arguments (and it probably does)
|
||||||
|
// then it can be switched to an arrow fn with a named arg.
|
||||||
|
onComplete: function() {
|
||||||
|
const args = Array.prototype.slice.call(arguments, [0]);
|
||||||
|
this.#suiteSegmentComplete(suite, suite.getResult(), () => {
|
||||||
|
done.apply(undefined, args);
|
||||||
|
});
|
||||||
|
}.bind(this),
|
||||||
|
queueableFns,
|
||||||
|
userContext: suite.sharedUserContext(),
|
||||||
|
onException: function() {
|
||||||
|
suite.handleException.apply(suite, arguments);
|
||||||
|
},
|
||||||
|
onMultipleDone: suite.onMultipleDone
|
||||||
|
? suite.onMultipleDone.bind(suite)
|
||||||
|
: null
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// TreeProcessor callback.
|
||||||
|
#executeSpec(spec, excluded, done) {
|
||||||
|
const config = this.#getConfig();
|
||||||
|
spec.execute(
|
||||||
|
this.#runQueueWithSkipPolicy.bind(this),
|
||||||
|
this.#globalErrors,
|
||||||
|
done,
|
||||||
|
excluded,
|
||||||
|
config.failSpecWithNoExpectations,
|
||||||
|
config.detectLateRejectionHandling
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#addBeforeAndAfterAlls(suite, willExecute, wrappedChildren) {
|
||||||
|
if (willExecute) {
|
||||||
|
return suite.beforeAllFns
|
||||||
|
.concat(wrappedChildren)
|
||||||
|
.concat(suite.afterAllFns);
|
||||||
|
} else {
|
||||||
|
return wrappedChildren;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#suiteSegmentStart(suite, next) {
|
||||||
|
this.#currentlyExecutingSuites.push(suite);
|
||||||
|
this.#runableResources.initForRunable(suite.id, suite.parentSuite.id);
|
||||||
|
this.#reportDispatcher.suiteStarted(suite.result).then(next);
|
||||||
|
suite.startTimer();
|
||||||
|
}
|
||||||
|
|
||||||
|
#suiteSegmentComplete(suite, result, next) {
|
||||||
|
suite.cleanupBeforeAfter();
|
||||||
|
|
||||||
|
if (suite !== this.currentSuite()) {
|
||||||
|
throw new Error('Tried to complete the wrong suite');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.#runableResources.clearForRunable(suite.id);
|
||||||
|
this.#currentlyExecutingSuites.pop();
|
||||||
|
|
||||||
|
if (result.status === 'failed') {
|
||||||
|
this.hasFailures = true;
|
||||||
|
}
|
||||||
|
suite.endTimer();
|
||||||
|
|
||||||
|
if (suite.hadBeforeAllFailure) {
|
||||||
|
this.#reportChildrenOfBeforeAllFailure(suite).then(() => {
|
||||||
|
this.#reportSuiteDone(suite, result, next);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.#reportSuiteDone(suite, result, next);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#runQueueWithSkipPolicy(options) {
|
||||||
|
if (options.isLeaf) {
|
||||||
|
// A spec
|
||||||
|
options.SkipPolicy = j$.CompleteOnFirstErrorSkipPolicy;
|
||||||
|
} else {
|
||||||
|
// A suite
|
||||||
|
if (this.#getConfig().stopOnSpecFailure) {
|
||||||
|
options.SkipPolicy = j$.CompleteOnFirstErrorSkipPolicy;
|
||||||
|
} else {
|
||||||
|
options.SkipPolicy = j$.SkipAfterBeforeAllErrorPolicy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.#runQueue(options);
|
||||||
|
}
|
||||||
|
|
||||||
#reportSuiteDone(suite, result, next) {
|
#reportSuiteDone(suite, result, next) {
|
||||||
suite.reportedDone = true;
|
suite.reportedDone = true;
|
||||||
this.#reportDispatcher.suiteDone(result).then(next);
|
this.#reportDispatcher.suiteDone(result).then(next);
|
||||||
|
|||||||
@@ -4,13 +4,10 @@ getJasmineRequireObj().TreeProcessor = function(j$) {
|
|||||||
|
|
||||||
class TreeProcessor {
|
class TreeProcessor {
|
||||||
#tree;
|
#tree;
|
||||||
#runQueue;
|
#executeTopSuite;
|
||||||
|
#executeSpec;
|
||||||
|
#executeSuiteSegment;
|
||||||
#runnableIds;
|
#runnableIds;
|
||||||
#nodeStart;
|
|
||||||
#nodeComplete;
|
|
||||||
#failSpecWithNoExpectations;
|
|
||||||
#detectLateRejectionHandling;
|
|
||||||
#globalErrors;
|
|
||||||
#orderChildren;
|
#orderChildren;
|
||||||
#excludeNode;
|
#excludeNode;
|
||||||
#stats;
|
#stats;
|
||||||
@@ -19,12 +16,9 @@ getJasmineRequireObj().TreeProcessor = function(j$) {
|
|||||||
constructor(attrs) {
|
constructor(attrs) {
|
||||||
this.#tree = attrs.tree;
|
this.#tree = attrs.tree;
|
||||||
this.#runnableIds = attrs.runnableIds;
|
this.#runnableIds = attrs.runnableIds;
|
||||||
this.#runQueue = attrs.runQueue;
|
this.#executeTopSuite = attrs.executeTopSuite;
|
||||||
this.#nodeStart = attrs.nodeStart || function() {};
|
this.#executeSpec = attrs.executeSpec;
|
||||||
this.#nodeComplete = attrs.nodeComplete || function() {};
|
this.#executeSuiteSegment = attrs.executeSuiteSegment;
|
||||||
this.#failSpecWithNoExpectations = !!attrs.failSpecWithNoExpectations;
|
|
||||||
this.#detectLateRejectionHandling = !!attrs.detectLateRejectionHandling;
|
|
||||||
this.#globalErrors = attrs.globalErrors;
|
|
||||||
|
|
||||||
this.#orderChildren =
|
this.#orderChildren =
|
||||||
attrs.orderChildren ||
|
attrs.orderChildren ||
|
||||||
@@ -55,20 +49,10 @@ getJasmineRequireObj().TreeProcessor = function(j$) {
|
|||||||
throw new Error('invalid order');
|
throw new Error('invalid order');
|
||||||
}
|
}
|
||||||
|
|
||||||
const childFns = this.#wrapChildren(this.#tree, 0);
|
const wrappedChildren = this.#wrapChildren(this.#tree, 0);
|
||||||
|
|
||||||
await new Promise(resolve => {
|
await new Promise(resolve => {
|
||||||
this.#runQueue({
|
this.#executeTopSuite(this.#tree, wrappedChildren, resolve);
|
||||||
queueableFns: childFns,
|
|
||||||
userContext: this.#tree.sharedUserContext(),
|
|
||||||
onException: function() {
|
|
||||||
this.#tree.handleException.apply(this.#tree, arguments);
|
|
||||||
}.bind(this),
|
|
||||||
onComplete: resolve,
|
|
||||||
onMultipleDone: this.#tree.onMultipleDone
|
|
||||||
? this.#tree.onMultipleDone.bind(this.#tree)
|
|
||||||
: null
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,55 +137,22 @@ getJasmineRequireObj().TreeProcessor = function(j$) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.#stats[node.id].willExecute) {
|
return result;
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
return node.beforeAllFns.concat(result).concat(node.afterAllFns);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#executeNode(node, segmentNumber) {
|
#executeNode(node, segmentNumber) {
|
||||||
if (node.children) {
|
if (node.children) {
|
||||||
return {
|
return {
|
||||||
fn: function(done) {
|
fn: done => {
|
||||||
const onStart = {
|
const wrappedChildren = this.#wrapChildren(node, segmentNumber);
|
||||||
fn: next => {
|
const willExecute = this.#stats[node.id].willExecute;
|
||||||
this.#nodeStart(node, next);
|
this.#executeSuiteSegment(node, willExecute, wrappedChildren, done);
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
this.#runQueue({
|
|
||||||
onComplete: function() {
|
|
||||||
const args = Array.prototype.slice.call(arguments, [0]);
|
|
||||||
node.cleanupBeforeAfter();
|
|
||||||
this.#nodeComplete(node, node.getResult(), () => {
|
|
||||||
done.apply(undefined, args);
|
|
||||||
});
|
|
||||||
}.bind(this),
|
|
||||||
queueableFns: [onStart].concat(
|
|
||||||
this.#wrapChildren(node, segmentNumber)
|
|
||||||
),
|
|
||||||
userContext: node.sharedUserContext(),
|
|
||||||
onException: function() {
|
|
||||||
node.handleException.apply(node, arguments);
|
|
||||||
},
|
|
||||||
onMultipleDone: node.onMultipleDone
|
|
||||||
? node.onMultipleDone.bind(node)
|
|
||||||
: null
|
|
||||||
});
|
|
||||||
}.bind(this)
|
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
return {
|
return {
|
||||||
fn: done => {
|
fn: done => {
|
||||||
node.execute(
|
this.#executeSpec(node, this.#stats[node.id].excluded, done);
|
||||||
this.#runQueue,
|
|
||||||
this.#globalErrors,
|
|
||||||
done,
|
|
||||||
this.#stats[node.id].excluded,
|
|
||||||
this.#failSpecWithNoExpectations,
|
|
||||||
this.#detectLateRejectionHandling
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user