Remove mutual recursion between Runner and TreeProcessor
This commit is contained in:
@@ -9407,6 +9407,7 @@ getJasmineRequireObj().Runner = function(j$) {
|
|||||||
#runableResources;
|
#runableResources;
|
||||||
#runQueue;
|
#runQueue;
|
||||||
#TreeProcessor;
|
#TreeProcessor;
|
||||||
|
#treeProcessor;
|
||||||
#globalErrors;
|
#globalErrors;
|
||||||
#reportDispatcher;
|
#reportDispatcher;
|
||||||
#getConfig;
|
#getConfig;
|
||||||
@@ -9469,12 +9470,9 @@ getJasmineRequireObj().Runner = function(j$) {
|
|||||||
seed: j$.isNumber_(config.seed) ? config.seed + '' : config.seed
|
seed: j$.isNumber_(config.seed) ? config.seed + '' : config.seed
|
||||||
});
|
});
|
||||||
|
|
||||||
const processor = new this.#TreeProcessor({
|
this.#treeProcessor = new this.#TreeProcessor({
|
||||||
tree: this.#topSuite,
|
tree: this.#topSuite,
|
||||||
runnableIds: runablesToRun,
|
runnableIds: runablesToRun,
|
||||||
executeTopSuite: this.#executeTopSuite.bind(this),
|
|
||||||
executeSpec: this.#executeSpec.bind(this),
|
|
||||||
executeSuiteSegment: this.#executeSuiteSegment.bind(this),
|
|
||||||
orderChildren: function(node) {
|
orderChildren: function(node) {
|
||||||
return order.sort(node.children);
|
return order.sort(node.children);
|
||||||
},
|
},
|
||||||
@@ -9482,12 +9480,12 @@ getJasmineRequireObj().Runner = function(j$) {
|
|||||||
return !config.specFilter(spec);
|
return !config.specFilter(spec);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
processor.processTree();
|
this.#treeProcessor.processTree();
|
||||||
|
|
||||||
return this.#execute2(runablesToRun, order, processor);
|
return this.#execute2(runablesToRun, order);
|
||||||
}
|
}
|
||||||
|
|
||||||
async #execute2(runablesToRun, order, processor) {
|
async #execute2(runablesToRun, order) {
|
||||||
const totalSpecsDefined = this.#getTotalSpecsDefined();
|
const totalSpecsDefined = this.#getTotalSpecsDefined();
|
||||||
|
|
||||||
this.#runableResources.initForRunable(this.#topSuite.id);
|
this.#runableResources.initForRunable(this.#topSuite.id);
|
||||||
@@ -9511,7 +9509,7 @@ getJasmineRequireObj().Runner = function(j$) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.#currentlyExecutingSuites.push(this.#topSuite);
|
this.#currentlyExecutingSuites.push(this.#topSuite);
|
||||||
await processor.execute();
|
await this.#executeTopSuite();
|
||||||
|
|
||||||
if (this.#topSuite.hadBeforeAllFailure) {
|
if (this.#topSuite.hadBeforeAllFailure) {
|
||||||
await this.#reportChildrenOfBeforeAllFailure(this.#topSuite);
|
await this.#reportChildrenOfBeforeAllFailure(this.#topSuite);
|
||||||
@@ -9565,28 +9563,34 @@ getJasmineRequireObj().Runner = function(j$) {
|
|||||||
return jasmineDoneInfo;
|
return jasmineDoneInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TreeProcessor callback.
|
async #executeTopSuite() {
|
||||||
#executeTopSuite(topSuite, wrappedChildren, done) {
|
const wrappedChildren = this.#wrapNodes(
|
||||||
|
this.#treeProcessor.childrenOfTopSuite()
|
||||||
|
);
|
||||||
const queueableFns = this.#addBeforeAndAfterAlls(
|
const queueableFns = this.#addBeforeAndAfterAlls(
|
||||||
topSuite,
|
this.#topSuite,
|
||||||
true,
|
|
||||||
wrappedChildren
|
wrappedChildren
|
||||||
);
|
);
|
||||||
this.#runQueueWithSkipPolicy({
|
|
||||||
queueableFns,
|
await new Promise(resolve => {
|
||||||
userContext: topSuite.sharedUserContext(),
|
this.#runQueueWithSkipPolicy({
|
||||||
onException: function() {
|
queueableFns,
|
||||||
topSuite.handleException.apply(topSuite, arguments);
|
userContext: this.#topSuite.sharedUserContext(),
|
||||||
}.bind(this),
|
onException: function() {
|
||||||
onComplete: done,
|
this.#topSuite.handleException.apply(this.#topSuite, arguments);
|
||||||
onMultipleDone: topSuite.onMultipleDone
|
}.bind(this),
|
||||||
? topSuite.onMultipleDone.bind(topSuite)
|
onComplete: resolve,
|
||||||
: null
|
onMultipleDone: this.#topSuite.onMultipleDone
|
||||||
|
? this.#topSuite.onMultipleDone.bind(this.#topSuite)
|
||||||
|
: null
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// TreeProcessor callback. Mutually recursive with TreeProcessor##executeNode.
|
#executeSuiteSegment(suite, segmentNumber, done) {
|
||||||
#executeSuiteSegment(suite, excluded, wrappedChildren, done) {
|
const wrappedChildren = this.#wrapNodes(
|
||||||
|
this.#treeProcessor.childrenOfSuiteSegment(suite, segmentNumber)
|
||||||
|
);
|
||||||
const onStart = {
|
const onStart = {
|
||||||
fn: next => {
|
fn: next => {
|
||||||
this.#suiteSegmentStart(suite, next);
|
this.#suiteSegmentStart(suite, next);
|
||||||
@@ -9594,7 +9598,7 @@ getJasmineRequireObj().Runner = function(j$) {
|
|||||||
};
|
};
|
||||||
const queueableFns = [
|
const queueableFns = [
|
||||||
onStart,
|
onStart,
|
||||||
...this.#addBeforeAndAfterAlls(suite, excluded, wrappedChildren)
|
...this.#addBeforeAndAfterAlls(suite, wrappedChildren)
|
||||||
];
|
];
|
||||||
|
|
||||||
this.#runQueueWithSkipPolicy({
|
this.#runQueueWithSkipPolicy({
|
||||||
@@ -9617,27 +9621,40 @@ getJasmineRequireObj().Runner = function(j$) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// TreeProcessor callback.
|
#executeSpec(spec, done) {
|
||||||
#executeSpec(spec, excluded, done) {
|
|
||||||
const config = this.#getConfig();
|
const config = this.#getConfig();
|
||||||
spec.execute(
|
spec.execute(
|
||||||
this.#runQueueWithSkipPolicy.bind(this),
|
this.#runQueueWithSkipPolicy.bind(this),
|
||||||
this.#globalErrors,
|
this.#globalErrors,
|
||||||
done,
|
done,
|
||||||
excluded,
|
this.#treeProcessor.isExcluded(spec),
|
||||||
config.failSpecWithNoExpectations,
|
config.failSpecWithNoExpectations,
|
||||||
config.detectLateRejectionHandling
|
config.detectLateRejectionHandling
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#addBeforeAndAfterAlls(suite, willExecute, wrappedChildren) {
|
#wrapNodes(nodes) {
|
||||||
if (willExecute) {
|
return nodes.map(node => {
|
||||||
return suite.beforeAllFns
|
return {
|
||||||
.concat(wrappedChildren)
|
fn: done => {
|
||||||
.concat(suite.afterAllFns);
|
if (node.suite) {
|
||||||
} else {
|
this.#executeSuiteSegment(node.suite, node.segmentNumber, done);
|
||||||
|
} else {
|
||||||
|
this.#executeSpec(node.spec, done);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#addBeforeAndAfterAlls(suite, wrappedChildren) {
|
||||||
|
if (this.#treeProcessor.isExcluded(suite)) {
|
||||||
return wrappedChildren;
|
return wrappedChildren;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return suite.beforeAllFns
|
||||||
|
.concat(wrappedChildren)
|
||||||
|
.concat(suite.afterAllFns);
|
||||||
}
|
}
|
||||||
|
|
||||||
#suiteSegmentStart(suite, next) {
|
#suiteSegmentStart(suite, next) {
|
||||||
@@ -11386,9 +11403,6 @@ getJasmineRequireObj().TreeProcessor = function(j$) {
|
|||||||
|
|
||||||
class TreeProcessor {
|
class TreeProcessor {
|
||||||
#tree;
|
#tree;
|
||||||
#executeTopSuite;
|
|
||||||
#executeSpec;
|
|
||||||
#executeSuiteSegment;
|
|
||||||
#runnableIds;
|
#runnableIds;
|
||||||
#orderChildren;
|
#orderChildren;
|
||||||
#excludeNode;
|
#excludeNode;
|
||||||
@@ -11398,9 +11412,6 @@ 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.#executeTopSuite = attrs.executeTopSuite;
|
|
||||||
this.#executeSpec = attrs.executeSpec;
|
|
||||||
this.#executeSuiteSegment = attrs.executeSuiteSegment;
|
|
||||||
|
|
||||||
this.#orderChildren =
|
this.#orderChildren =
|
||||||
attrs.orderChildren ||
|
attrs.orderChildren ||
|
||||||
@@ -11412,7 +11423,7 @@ getJasmineRequireObj().TreeProcessor = function(j$) {
|
|||||||
function(node) {
|
function(node) {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
this.#stats = { valid: true };
|
this.#stats = {};
|
||||||
this.#processed = false;
|
this.#processed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -11422,22 +11433,27 @@ getJasmineRequireObj().TreeProcessor = function(j$) {
|
|||||||
return this.#stats;
|
return this.#stats;
|
||||||
}
|
}
|
||||||
|
|
||||||
async execute() {
|
childrenOfTopSuite() {
|
||||||
if (!this.#processed) {
|
return this.childrenOfSuiteSegment(this.#tree, 0);
|
||||||
this.processTree();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.#stats.valid) {
|
childrenOfSuiteSegment(suite, segmentNumber) {
|
||||||
throw new Error('invalid order');
|
const segmentChildren = this.#stats[suite.id].segments[segmentNumber]
|
||||||
}
|
.nodes;
|
||||||
|
return segmentChildren.map(function(child) {
|
||||||
const wrappedChildren = this.#wrapChildren(this.#tree, 0);
|
if (child.owner.children) {
|
||||||
|
return { suite: child.owner, segmentNumber: child.index };
|
||||||
await new Promise(resolve => {
|
} else {
|
||||||
this.#executeTopSuite(this.#tree, wrappedChildren, resolve);
|
return { spec: child.owner };
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isExcluded(node) {
|
||||||
|
const nodeStats = this.#stats[node.id];
|
||||||
|
return node.children ? !nodeStats.willExecute : nodeStats.excluded;
|
||||||
|
}
|
||||||
|
|
||||||
#runnableIndex(id) {
|
#runnableIndex(id) {
|
||||||
for (let i = 0; i < this.#runnableIds.length; i++) {
|
for (let i = 0; i < this.#runnableIds.length; i++) {
|
||||||
if (this.#runnableIds[i] === id) {
|
if (this.#runnableIds[i] === id) {
|
||||||
@@ -11475,15 +11491,8 @@ getJasmineRequireObj().TreeProcessor = function(j$) {
|
|||||||
|
|
||||||
for (let i = 0; i < orderedChildren.length; i++) {
|
for (let i = 0; i < orderedChildren.length; i++) {
|
||||||
const child = orderedChildren[i];
|
const child = orderedChildren[i];
|
||||||
|
|
||||||
this.#processNode(child, parentExcluded);
|
this.#processNode(child, parentExcluded);
|
||||||
|
|
||||||
if (!this.#stats.valid) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const childStats = this.#stats[child.id];
|
const childStats = this.#stats[child.id];
|
||||||
|
|
||||||
hasExecutableChild = hasExecutableChild || childStats.willExecute;
|
hasExecutableChild = hasExecutableChild || childStats.willExecute;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -11500,7 +11509,6 @@ getJasmineRequireObj().TreeProcessor = function(j$) {
|
|||||||
'The specified spec/suite order splits up a suite, running unrelated specs in the middle of it. This will become an error in a future release.'
|
'The specified spec/suite order splits up a suite, running unrelated specs in the middle of it. This will become an error in a future release.'
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
this.#stats = { valid: false };
|
|
||||||
throw new Error(
|
throw new Error(
|
||||||
'Invalid order: would cause a beforeAll or afterAll to be run multiple times'
|
'Invalid order: would cause a beforeAll or afterAll to be run multiple times'
|
||||||
);
|
);
|
||||||
@@ -11508,37 +11516,6 @@ getJasmineRequireObj().TreeProcessor = function(j$) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#wrapChildren(node, segmentNumber) {
|
|
||||||
const result = [],
|
|
||||||
segmentChildren = this.#stats[node.id].segments[segmentNumber].nodes;
|
|
||||||
|
|
||||||
for (let i = 0; i < segmentChildren.length; i++) {
|
|
||||||
result.push(
|
|
||||||
this.#executeNode(segmentChildren[i].owner, segmentChildren[i].index)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
#executeNode(node, segmentNumber) {
|
|
||||||
if (node.children) {
|
|
||||||
return {
|
|
||||||
fn: done => {
|
|
||||||
const wrappedChildren = this.#wrapChildren(node, segmentNumber);
|
|
||||||
const willExecute = this.#stats[node.id].willExecute;
|
|
||||||
this.#executeSuiteSegment(node, willExecute, wrappedChildren, done);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
return {
|
|
||||||
fn: done => {
|
|
||||||
this.#executeSpec(node, this.#stats[node.id].excluded, done);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function segmentChildren(node, orderedChildren, stats, executableIndex) {
|
function segmentChildren(node, orderedChildren, stats, executableIndex) {
|
||||||
|
|||||||
@@ -34,8 +34,6 @@ describe('TreeProcessor', function() {
|
|||||||
}),
|
}),
|
||||||
result = processor.processTree();
|
result = processor.processTree();
|
||||||
|
|
||||||
expect(result.valid).toBe(true);
|
|
||||||
|
|
||||||
expect(result[leaf.id]).toEqual({
|
expect(result[leaf.id]).toEqual({
|
||||||
excluded: false,
|
excluded: false,
|
||||||
willExecute: true,
|
willExecute: true,
|
||||||
@@ -51,8 +49,6 @@ describe('TreeProcessor', function() {
|
|||||||
}),
|
}),
|
||||||
result = processor.processTree();
|
result = processor.processTree();
|
||||||
|
|
||||||
expect(result.valid).toBe(true);
|
|
||||||
|
|
||||||
expect(result[leaf.id]).toEqual({
|
expect(result[leaf.id]).toEqual({
|
||||||
excluded: false,
|
excluded: false,
|
||||||
willExecute: false,
|
willExecute: false,
|
||||||
@@ -68,8 +64,6 @@ describe('TreeProcessor', function() {
|
|||||||
}),
|
}),
|
||||||
result = processor.processTree();
|
result = processor.processTree();
|
||||||
|
|
||||||
expect(result.valid).toBe(true);
|
|
||||||
|
|
||||||
expect(result[leaf.id]).toEqual({
|
expect(result[leaf.id]).toEqual({
|
||||||
excluded: true,
|
excluded: true,
|
||||||
willExecute: false,
|
willExecute: false,
|
||||||
@@ -88,8 +82,6 @@ describe('TreeProcessor', function() {
|
|||||||
}),
|
}),
|
||||||
result = processor.processTree();
|
result = processor.processTree();
|
||||||
|
|
||||||
expect(result.valid).toBe(true);
|
|
||||||
|
|
||||||
expect(result[leaf.id]).toEqual({
|
expect(result[leaf.id]).toEqual({
|
||||||
excluded: true,
|
excluded: true,
|
||||||
willExecute: false,
|
willExecute: false,
|
||||||
@@ -106,8 +98,6 @@ describe('TreeProcessor', function() {
|
|||||||
}),
|
}),
|
||||||
result = processor.processTree();
|
result = processor.processTree();
|
||||||
|
|
||||||
expect(result.valid).toBe(true);
|
|
||||||
|
|
||||||
expect(result[parent.id]).toEqual({
|
expect(result[parent.id]).toEqual({
|
||||||
excluded: false,
|
excluded: false,
|
||||||
willExecute: true,
|
willExecute: true,
|
||||||
@@ -130,8 +120,6 @@ describe('TreeProcessor', function() {
|
|||||||
}),
|
}),
|
||||||
result = processor.processTree();
|
result = processor.processTree();
|
||||||
|
|
||||||
expect(result.valid).toBe(true);
|
|
||||||
|
|
||||||
expect(result[parent.id]).toEqual({
|
expect(result[parent.id]).toEqual({
|
||||||
excluded: false,
|
excluded: false,
|
||||||
willExecute: false,
|
willExecute: false,
|
||||||
@@ -166,8 +154,6 @@ describe('TreeProcessor', function() {
|
|||||||
}),
|
}),
|
||||||
result = processor.processTree();
|
result = processor.processTree();
|
||||||
|
|
||||||
expect(result.valid).toBe(true);
|
|
||||||
|
|
||||||
expect(result[root.id]).toEqual({
|
expect(result[root.id]).toEqual({
|
||||||
excluded: false,
|
excluded: false,
|
||||||
willExecute: true,
|
willExecute: true,
|
||||||
@@ -217,7 +203,7 @@ describe('TreeProcessor', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('marks the run order invalid if it would re-enter a node that does not allow re-entry', async function() {
|
it('throws if the specified order would re-enter a node that does not allow re-entry', function() {
|
||||||
const leaf1 = new Leaf(),
|
const leaf1 = new Leaf(),
|
||||||
leaf2 = new Leaf(),
|
leaf2 = new Leaf(),
|
||||||
leaf3 = new Leaf(),
|
leaf3 = new Leaf(),
|
||||||
@@ -233,14 +219,9 @@ describe('TreeProcessor', function() {
|
|||||||
}).toThrowError(
|
}).toThrowError(
|
||||||
'Invalid order: would cause a beforeAll or afterAll to be run multiple times'
|
'Invalid order: would cause a beforeAll or afterAll to be run multiple times'
|
||||||
);
|
);
|
||||||
|
|
||||||
// Subsequent attempts to execute should fail
|
|
||||||
await expectAsync(processor.execute()).toBeRejectedWithError(
|
|
||||||
'invalid order'
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('marks the run order valid if a node being re-entered allows re-entry', function() {
|
it('does not throw if a node being re-entered allows re-entry', function() {
|
||||||
const leaf1 = new Leaf();
|
const leaf1 = new Leaf();
|
||||||
const leaf2 = new Leaf();
|
const leaf2 = new Leaf();
|
||||||
const leaf3 = new Leaf();
|
const leaf3 = new Leaf();
|
||||||
@@ -253,15 +234,14 @@ describe('TreeProcessor', function() {
|
|||||||
const env = jasmineUnderTest.getEnv();
|
const env = jasmineUnderTest.getEnv();
|
||||||
spyOn(env, 'deprecated');
|
spyOn(env, 'deprecated');
|
||||||
|
|
||||||
const result = processor.processTree();
|
processor.processTree();
|
||||||
|
|
||||||
expect(result.valid).toBe(true);
|
|
||||||
expect(env.deprecated).toHaveBeenCalledWith(
|
expect(env.deprecated).toHaveBeenCalledWith(
|
||||||
'The specified spec/suite order splits up a suite, running unrelated specs in the middle of it. This will become an error in a future release.'
|
'The specified spec/suite order splits up a suite, running unrelated specs in the middle of it. This will become an error in a future release.'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("marks the run order valid if a node which can't be re-entered is only entered once", function() {
|
it("does not throw if a node which can't be re-entered is only entered once", function() {
|
||||||
const leaf1 = new Leaf(),
|
const leaf1 = new Leaf(),
|
||||||
leaf2 = new Leaf(),
|
leaf2 = new Leaf(),
|
||||||
leaf3 = new Leaf(),
|
leaf3 = new Leaf(),
|
||||||
@@ -270,22 +250,20 @@ describe('TreeProcessor', function() {
|
|||||||
processor = new jasmineUnderTest.TreeProcessor({
|
processor = new jasmineUnderTest.TreeProcessor({
|
||||||
tree: root,
|
tree: root,
|
||||||
runnableIds: [leaf2.id, leaf1.id, leaf3.id]
|
runnableIds: [leaf2.id, leaf1.id, leaf3.id]
|
||||||
}),
|
});
|
||||||
result = processor.processTree();
|
|
||||||
|
|
||||||
expect(result.valid).toBe(true);
|
processor.processTree();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("marks the run order valid if a node which can't be re-entered is run directly", function() {
|
it("does not throw if a node which can't be re-entered is run directly", function() {
|
||||||
const noReentry = new Node({ noReenter: true }),
|
const noReentry = new Node({ noReenter: true }),
|
||||||
root = new Node({ children: [noReentry] }),
|
root = new Node({ children: [noReentry] }),
|
||||||
processor = new jasmineUnderTest.TreeProcessor({
|
processor = new jasmineUnderTest.TreeProcessor({
|
||||||
tree: root,
|
tree: root,
|
||||||
runnableIds: [root.id]
|
runnableIds: [root.id]
|
||||||
}),
|
});
|
||||||
result = processor.processTree();
|
|
||||||
|
|
||||||
expect(result.valid).toBe(true);
|
processor.processTree();
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO: Replace these with corresponding unit tests elsewhere, once things stabilize
|
// TODO: Replace these with corresponding unit tests elsewhere, once things stabilize
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ getJasmineRequireObj().Runner = function(j$) {
|
|||||||
#runableResources;
|
#runableResources;
|
||||||
#runQueue;
|
#runQueue;
|
||||||
#TreeProcessor;
|
#TreeProcessor;
|
||||||
|
#treeProcessor;
|
||||||
#globalErrors;
|
#globalErrors;
|
||||||
#reportDispatcher;
|
#reportDispatcher;
|
||||||
#getConfig;
|
#getConfig;
|
||||||
@@ -68,12 +69,9 @@ getJasmineRequireObj().Runner = function(j$) {
|
|||||||
seed: j$.isNumber_(config.seed) ? config.seed + '' : config.seed
|
seed: j$.isNumber_(config.seed) ? config.seed + '' : config.seed
|
||||||
});
|
});
|
||||||
|
|
||||||
const processor = new this.#TreeProcessor({
|
this.#treeProcessor = new this.#TreeProcessor({
|
||||||
tree: this.#topSuite,
|
tree: this.#topSuite,
|
||||||
runnableIds: runablesToRun,
|
runnableIds: runablesToRun,
|
||||||
executeTopSuite: this.#executeTopSuite.bind(this),
|
|
||||||
executeSpec: this.#executeSpec.bind(this),
|
|
||||||
executeSuiteSegment: this.#executeSuiteSegment.bind(this),
|
|
||||||
orderChildren: function(node) {
|
orderChildren: function(node) {
|
||||||
return order.sort(node.children);
|
return order.sort(node.children);
|
||||||
},
|
},
|
||||||
@@ -81,12 +79,12 @@ getJasmineRequireObj().Runner = function(j$) {
|
|||||||
return !config.specFilter(spec);
|
return !config.specFilter(spec);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
processor.processTree();
|
this.#treeProcessor.processTree();
|
||||||
|
|
||||||
return this.#execute2(runablesToRun, order, processor);
|
return this.#execute2(runablesToRun, order);
|
||||||
}
|
}
|
||||||
|
|
||||||
async #execute2(runablesToRun, order, processor) {
|
async #execute2(runablesToRun, order) {
|
||||||
const totalSpecsDefined = this.#getTotalSpecsDefined();
|
const totalSpecsDefined = this.#getTotalSpecsDefined();
|
||||||
|
|
||||||
this.#runableResources.initForRunable(this.#topSuite.id);
|
this.#runableResources.initForRunable(this.#topSuite.id);
|
||||||
@@ -110,7 +108,7 @@ getJasmineRequireObj().Runner = function(j$) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.#currentlyExecutingSuites.push(this.#topSuite);
|
this.#currentlyExecutingSuites.push(this.#topSuite);
|
||||||
await processor.execute();
|
await this.#executeTopSuite();
|
||||||
|
|
||||||
if (this.#topSuite.hadBeforeAllFailure) {
|
if (this.#topSuite.hadBeforeAllFailure) {
|
||||||
await this.#reportChildrenOfBeforeAllFailure(this.#topSuite);
|
await this.#reportChildrenOfBeforeAllFailure(this.#topSuite);
|
||||||
@@ -164,28 +162,34 @@ getJasmineRequireObj().Runner = function(j$) {
|
|||||||
return jasmineDoneInfo;
|
return jasmineDoneInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TreeProcessor callback.
|
async #executeTopSuite() {
|
||||||
#executeTopSuite(topSuite, wrappedChildren, done) {
|
const wrappedChildren = this.#wrapNodes(
|
||||||
|
this.#treeProcessor.childrenOfTopSuite()
|
||||||
|
);
|
||||||
const queueableFns = this.#addBeforeAndAfterAlls(
|
const queueableFns = this.#addBeforeAndAfterAlls(
|
||||||
topSuite,
|
this.#topSuite,
|
||||||
true,
|
|
||||||
wrappedChildren
|
wrappedChildren
|
||||||
);
|
);
|
||||||
this.#runQueueWithSkipPolicy({
|
|
||||||
queueableFns,
|
await new Promise(resolve => {
|
||||||
userContext: topSuite.sharedUserContext(),
|
this.#runQueueWithSkipPolicy({
|
||||||
onException: function() {
|
queueableFns,
|
||||||
topSuite.handleException.apply(topSuite, arguments);
|
userContext: this.#topSuite.sharedUserContext(),
|
||||||
}.bind(this),
|
onException: function() {
|
||||||
onComplete: done,
|
this.#topSuite.handleException.apply(this.#topSuite, arguments);
|
||||||
onMultipleDone: topSuite.onMultipleDone
|
}.bind(this),
|
||||||
? topSuite.onMultipleDone.bind(topSuite)
|
onComplete: resolve,
|
||||||
: null
|
onMultipleDone: this.#topSuite.onMultipleDone
|
||||||
|
? this.#topSuite.onMultipleDone.bind(this.#topSuite)
|
||||||
|
: null
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// TreeProcessor callback. Mutually recursive with TreeProcessor##executeNode.
|
#executeSuiteSegment(suite, segmentNumber, done) {
|
||||||
#executeSuiteSegment(suite, excluded, wrappedChildren, done) {
|
const wrappedChildren = this.#wrapNodes(
|
||||||
|
this.#treeProcessor.childrenOfSuiteSegment(suite, segmentNumber)
|
||||||
|
);
|
||||||
const onStart = {
|
const onStart = {
|
||||||
fn: next => {
|
fn: next => {
|
||||||
this.#suiteSegmentStart(suite, next);
|
this.#suiteSegmentStart(suite, next);
|
||||||
@@ -193,7 +197,7 @@ getJasmineRequireObj().Runner = function(j$) {
|
|||||||
};
|
};
|
||||||
const queueableFns = [
|
const queueableFns = [
|
||||||
onStart,
|
onStart,
|
||||||
...this.#addBeforeAndAfterAlls(suite, excluded, wrappedChildren)
|
...this.#addBeforeAndAfterAlls(suite, wrappedChildren)
|
||||||
];
|
];
|
||||||
|
|
||||||
this.#runQueueWithSkipPolicy({
|
this.#runQueueWithSkipPolicy({
|
||||||
@@ -216,27 +220,40 @@ getJasmineRequireObj().Runner = function(j$) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// TreeProcessor callback.
|
#executeSpec(spec, done) {
|
||||||
#executeSpec(spec, excluded, done) {
|
|
||||||
const config = this.#getConfig();
|
const config = this.#getConfig();
|
||||||
spec.execute(
|
spec.execute(
|
||||||
this.#runQueueWithSkipPolicy.bind(this),
|
this.#runQueueWithSkipPolicy.bind(this),
|
||||||
this.#globalErrors,
|
this.#globalErrors,
|
||||||
done,
|
done,
|
||||||
excluded,
|
this.#treeProcessor.isExcluded(spec),
|
||||||
config.failSpecWithNoExpectations,
|
config.failSpecWithNoExpectations,
|
||||||
config.detectLateRejectionHandling
|
config.detectLateRejectionHandling
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#addBeforeAndAfterAlls(suite, willExecute, wrappedChildren) {
|
#wrapNodes(nodes) {
|
||||||
if (willExecute) {
|
return nodes.map(node => {
|
||||||
return suite.beforeAllFns
|
return {
|
||||||
.concat(wrappedChildren)
|
fn: done => {
|
||||||
.concat(suite.afterAllFns);
|
if (node.suite) {
|
||||||
} else {
|
this.#executeSuiteSegment(node.suite, node.segmentNumber, done);
|
||||||
|
} else {
|
||||||
|
this.#executeSpec(node.spec, done);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#addBeforeAndAfterAlls(suite, wrappedChildren) {
|
||||||
|
if (this.#treeProcessor.isExcluded(suite)) {
|
||||||
return wrappedChildren;
|
return wrappedChildren;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return suite.beforeAllFns
|
||||||
|
.concat(wrappedChildren)
|
||||||
|
.concat(suite.afterAllFns);
|
||||||
}
|
}
|
||||||
|
|
||||||
#suiteSegmentStart(suite, next) {
|
#suiteSegmentStart(suite, next) {
|
||||||
|
|||||||
@@ -4,9 +4,6 @@ getJasmineRequireObj().TreeProcessor = function(j$) {
|
|||||||
|
|
||||||
class TreeProcessor {
|
class TreeProcessor {
|
||||||
#tree;
|
#tree;
|
||||||
#executeTopSuite;
|
|
||||||
#executeSpec;
|
|
||||||
#executeSuiteSegment;
|
|
||||||
#runnableIds;
|
#runnableIds;
|
||||||
#orderChildren;
|
#orderChildren;
|
||||||
#excludeNode;
|
#excludeNode;
|
||||||
@@ -16,9 +13,6 @@ 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.#executeTopSuite = attrs.executeTopSuite;
|
|
||||||
this.#executeSpec = attrs.executeSpec;
|
|
||||||
this.#executeSuiteSegment = attrs.executeSuiteSegment;
|
|
||||||
|
|
||||||
this.#orderChildren =
|
this.#orderChildren =
|
||||||
attrs.orderChildren ||
|
attrs.orderChildren ||
|
||||||
@@ -30,7 +24,7 @@ getJasmineRequireObj().TreeProcessor = function(j$) {
|
|||||||
function(node) {
|
function(node) {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
this.#stats = { valid: true };
|
this.#stats = {};
|
||||||
this.#processed = false;
|
this.#processed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,22 +34,27 @@ getJasmineRequireObj().TreeProcessor = function(j$) {
|
|||||||
return this.#stats;
|
return this.#stats;
|
||||||
}
|
}
|
||||||
|
|
||||||
async execute() {
|
childrenOfTopSuite() {
|
||||||
if (!this.#processed) {
|
return this.childrenOfSuiteSegment(this.#tree, 0);
|
||||||
this.processTree();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.#stats.valid) {
|
childrenOfSuiteSegment(suite, segmentNumber) {
|
||||||
throw new Error('invalid order');
|
const segmentChildren = this.#stats[suite.id].segments[segmentNumber]
|
||||||
}
|
.nodes;
|
||||||
|
return segmentChildren.map(function(child) {
|
||||||
const wrappedChildren = this.#wrapChildren(this.#tree, 0);
|
if (child.owner.children) {
|
||||||
|
return { suite: child.owner, segmentNumber: child.index };
|
||||||
await new Promise(resolve => {
|
} else {
|
||||||
this.#executeTopSuite(this.#tree, wrappedChildren, resolve);
|
return { spec: child.owner };
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isExcluded(node) {
|
||||||
|
const nodeStats = this.#stats[node.id];
|
||||||
|
return node.children ? !nodeStats.willExecute : nodeStats.excluded;
|
||||||
|
}
|
||||||
|
|
||||||
#runnableIndex(id) {
|
#runnableIndex(id) {
|
||||||
for (let i = 0; i < this.#runnableIds.length; i++) {
|
for (let i = 0; i < this.#runnableIds.length; i++) {
|
||||||
if (this.#runnableIds[i] === id) {
|
if (this.#runnableIds[i] === id) {
|
||||||
@@ -93,15 +92,8 @@ getJasmineRequireObj().TreeProcessor = function(j$) {
|
|||||||
|
|
||||||
for (let i = 0; i < orderedChildren.length; i++) {
|
for (let i = 0; i < orderedChildren.length; i++) {
|
||||||
const child = orderedChildren[i];
|
const child = orderedChildren[i];
|
||||||
|
|
||||||
this.#processNode(child, parentExcluded);
|
this.#processNode(child, parentExcluded);
|
||||||
|
|
||||||
if (!this.#stats.valid) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const childStats = this.#stats[child.id];
|
const childStats = this.#stats[child.id];
|
||||||
|
|
||||||
hasExecutableChild = hasExecutableChild || childStats.willExecute;
|
hasExecutableChild = hasExecutableChild || childStats.willExecute;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,7 +110,6 @@ getJasmineRequireObj().TreeProcessor = function(j$) {
|
|||||||
'The specified spec/suite order splits up a suite, running unrelated specs in the middle of it. This will become an error in a future release.'
|
'The specified spec/suite order splits up a suite, running unrelated specs in the middle of it. This will become an error in a future release.'
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
this.#stats = { valid: false };
|
|
||||||
throw new Error(
|
throw new Error(
|
||||||
'Invalid order: would cause a beforeAll or afterAll to be run multiple times'
|
'Invalid order: would cause a beforeAll or afterAll to be run multiple times'
|
||||||
);
|
);
|
||||||
@@ -126,37 +117,6 @@ getJasmineRequireObj().TreeProcessor = function(j$) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#wrapChildren(node, segmentNumber) {
|
|
||||||
const result = [],
|
|
||||||
segmentChildren = this.#stats[node.id].segments[segmentNumber].nodes;
|
|
||||||
|
|
||||||
for (let i = 0; i < segmentChildren.length; i++) {
|
|
||||||
result.push(
|
|
||||||
this.#executeNode(segmentChildren[i].owner, segmentChildren[i].index)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
#executeNode(node, segmentNumber) {
|
|
||||||
if (node.children) {
|
|
||||||
return {
|
|
||||||
fn: done => {
|
|
||||||
const wrappedChildren = this.#wrapChildren(node, segmentNumber);
|
|
||||||
const willExecute = this.#stats[node.id].willExecute;
|
|
||||||
this.#executeSuiteSegment(node, willExecute, wrappedChildren, done);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
return {
|
|
||||||
fn: done => {
|
|
||||||
this.#executeSpec(node, this.#stats[node.id].excluded, done);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function segmentChildren(node, orderedChildren, stats, executableIndex) {
|
function segmentChildren(node, orderedChildren, stats, executableIndex) {
|
||||||
|
|||||||
Reference in New Issue
Block a user