Move beforeAll failure reporting into TreeRunner

This commit is contained in:
Steve Gravrock
2025-08-30 07:42:29 -07:00
parent 4b7d5e3623
commit 50e566bd67
4 changed files with 79 additions and 104 deletions

View File

@@ -9472,17 +9472,10 @@ getJasmineRequireObj().Runner = function(j$) {
reportDispatcher: this.#reportDispatcher, reportDispatcher: this.#reportDispatcher,
runQueue: this.#runQueue, runQueue: this.#runQueue,
getConfig: this.#getConfig, getConfig: this.#getConfig,
reportChildrenOfBeforeAllFailure: this.#reportChildrenOfBeforeAllFailure.bind(
this
),
currentRunableTracker: this.#currentRunableTracker currentRunableTracker: this.#currentRunableTracker
}); });
const { hasFailures } = await treeRunner.execute(); const { hasFailures } = await treeRunner.execute();
if (this.#topSuite.hadBeforeAllFailure) {
await this.#reportChildrenOfBeforeAllFailure(this.#topSuite);
}
this.#runableResources.clearForRunable(this.#topSuite.id); this.#runableResources.clearForRunable(this.#topSuite.id);
this.#currentRunableTracker.popSuite(); this.#currentRunableTracker.popSuite();
let overallStatus, incompleteReason, incompleteCode; let overallStatus, incompleteReason, incompleteCode;
@@ -9527,47 +9520,6 @@ getJasmineRequireObj().Runner = function(j$) {
await this.#reportDispatcher.jasmineDone(jasmineDoneInfo); await this.#reportDispatcher.jasmineDone(jasmineDoneInfo);
return jasmineDoneInfo; return jasmineDoneInfo;
} }
// TODO: de-duplicate w/TreeRunner
#reportSpecDone(spec, result, next) {
spec.reportedDone = true;
this.#reportDispatcher.specDone(result).then(next);
}
async #reportChildrenOfBeforeAllFailure(suite) {
for (const child of suite.children) {
if (child instanceof j$.Suite) {
await this.#reportDispatcher.suiteStarted(child.result);
await this.#reportChildrenOfBeforeAllFailure(child);
// Marking the suite passed is consistent with how suites that
// contain failed specs but no suite-level failures are reported.
child.result.status = 'passed';
await this.#reportDispatcher.suiteDone(child.result);
} else {
/* a spec */
await this.#reportDispatcher.specStarted(child.result);
child.addExpectationResult(
false,
{
passed: false,
message:
'Not run because a beforeAll function failed. The ' +
'beforeAll failure will be reported on the suite that ' +
'caused it.'
},
true
);
child.result.status = 'failed';
await new Promise(resolve => {
this.#reportSpecDone(child, child.result, resolve);
});
}
}
}
} }
return Runner; return Runner;
@@ -11442,7 +11394,6 @@ getJasmineRequireObj().TreeRunner = function(j$) {
#reportDispatcher; #reportDispatcher;
#runQueue; #runQueue;
#getConfig; #getConfig;
#reportChildrenOfBeforeAllFailure;
#currentRunableTracker; #currentRunableTracker;
#hasFailures; #hasFailures;
@@ -11454,8 +11405,6 @@ getJasmineRequireObj().TreeRunner = function(j$) {
this.#reportDispatcher = attrs.reportDispatcher; this.#reportDispatcher = attrs.reportDispatcher;
this.#runQueue = attrs.runQueue; this.#runQueue = attrs.runQueue;
this.#getConfig = attrs.getConfig; this.#getConfig = attrs.getConfig;
this.#reportChildrenOfBeforeAllFailure =
attrs.reportChildrenOfBeforeAllFailure;
this.#currentRunableTracker = attrs.currentRunableTracker; this.#currentRunableTracker = attrs.currentRunableTracker;
} }
@@ -11485,6 +11434,10 @@ getJasmineRequireObj().TreeRunner = function(j$) {
}); });
}); });
if (topSuite.hadBeforeAllFailure) {
await this.#reportChildrenOfBeforeAllFailure(topSuite);
}
return { hasFailures: this.#hasFailures }; return { hasFailures: this.#hasFailures };
} }
@@ -11682,6 +11635,38 @@ getJasmineRequireObj().TreeRunner = function(j$) {
await this.#reportDispatcher.specDone(spec.result); await this.#reportDispatcher.specDone(spec.result);
} }
async #reportChildrenOfBeforeAllFailure(suite) {
for (const child of suite.children) {
if (child instanceof j$.Suite) {
await this.#reportDispatcher.suiteStarted(child.result);
await this.#reportChildrenOfBeforeAllFailure(child);
// Marking the suite passed is consistent with how suites that
// contain failed specs but no suite-level failures are reported.
child.result.status = 'passed';
await this.#reportDispatcher.suiteDone(child.result);
} else {
/* a spec */
await this.#reportDispatcher.specStarted(child.result);
child.addExpectationResult(
false,
{
passed: false,
message:
'Not run because a beforeAll function failed. The ' +
'beforeAll failure will be reported on the suite that ' +
'caused it.'
},
true
);
child.result.status = 'failed';
await this.#reportSpecDone(child);
}
}
}
#addBeforeAndAfterAlls(suite, wrappedChildren) { #addBeforeAndAfterAlls(suite, wrappedChildren) {
if (this.#executionTree.isExcluded(suite)) { if (this.#executionTree.isExcluded(suite)) {
return wrappedChildren; return wrappedChildren;

View File

@@ -406,6 +406,8 @@ describe('TreeRunner', function() {
parentSuite: suite, parentSuite: suite,
queueableFn: { fn() {} } queueableFn: { fn() {} }
}); });
suite.addChild(spec);
topSuite.addChild(suite);
const executionTree = { const executionTree = {
topSuite, topSuite,
childrenOfTopSuite() { childrenOfTopSuite() {
@@ -447,9 +449,12 @@ describe('TreeRunner', function() {
suiteRunQueueOpts.queueableFns[0].fn(); suiteRunQueueOpts.queueableFns[0].fn();
suite.hadBeforeAllFailure = true; suite.hadBeforeAllFailure = true;
suiteRunQueueOpts.onComplete(); suiteRunQueueOpts.onComplete();
await Promise.resolve();
expect(reportChildrenOfBeforeAllFailure).toHaveBeenCalledBefore( while (reportDispatcher.suiteDone.calls.count() === 0) {
await Promise.resolve();
}
expect(reportDispatcher.specDone).toHaveBeenCalledBefore(
reportDispatcher.suiteDone reportDispatcher.suiteDone
); );
await expectAsync(executePromise).toBePending(); await expectAsync(executePromise).toBePending();

View File

@@ -115,17 +115,10 @@ getJasmineRequireObj().Runner = function(j$) {
reportDispatcher: this.#reportDispatcher, reportDispatcher: this.#reportDispatcher,
runQueue: this.#runQueue, runQueue: this.#runQueue,
getConfig: this.#getConfig, getConfig: this.#getConfig,
reportChildrenOfBeforeAllFailure: this.#reportChildrenOfBeforeAllFailure.bind(
this
),
currentRunableTracker: this.#currentRunableTracker currentRunableTracker: this.#currentRunableTracker
}); });
const { hasFailures } = await treeRunner.execute(); const { hasFailures } = await treeRunner.execute();
if (this.#topSuite.hadBeforeAllFailure) {
await this.#reportChildrenOfBeforeAllFailure(this.#topSuite);
}
this.#runableResources.clearForRunable(this.#topSuite.id); this.#runableResources.clearForRunable(this.#topSuite.id);
this.#currentRunableTracker.popSuite(); this.#currentRunableTracker.popSuite();
let overallStatus, incompleteReason, incompleteCode; let overallStatus, incompleteReason, incompleteCode;
@@ -170,47 +163,6 @@ getJasmineRequireObj().Runner = function(j$) {
await this.#reportDispatcher.jasmineDone(jasmineDoneInfo); await this.#reportDispatcher.jasmineDone(jasmineDoneInfo);
return jasmineDoneInfo; return jasmineDoneInfo;
} }
// TODO: de-duplicate w/TreeRunner
#reportSpecDone(spec, result, next) {
spec.reportedDone = true;
this.#reportDispatcher.specDone(result).then(next);
}
async #reportChildrenOfBeforeAllFailure(suite) {
for (const child of suite.children) {
if (child instanceof j$.Suite) {
await this.#reportDispatcher.suiteStarted(child.result);
await this.#reportChildrenOfBeforeAllFailure(child);
// Marking the suite passed is consistent with how suites that
// contain failed specs but no suite-level failures are reported.
child.result.status = 'passed';
await this.#reportDispatcher.suiteDone(child.result);
} else {
/* a spec */
await this.#reportDispatcher.specStarted(child.result);
child.addExpectationResult(
false,
{
passed: false,
message:
'Not run because a beforeAll function failed. The ' +
'beforeAll failure will be reported on the suite that ' +
'caused it.'
},
true
);
child.result.status = 'failed';
await new Promise(resolve => {
this.#reportSpecDone(child, child.result, resolve);
});
}
}
}
} }
return Runner; return Runner;

View File

@@ -7,7 +7,6 @@ getJasmineRequireObj().TreeRunner = function(j$) {
#reportDispatcher; #reportDispatcher;
#runQueue; #runQueue;
#getConfig; #getConfig;
#reportChildrenOfBeforeAllFailure;
#currentRunableTracker; #currentRunableTracker;
#hasFailures; #hasFailures;
@@ -19,8 +18,6 @@ getJasmineRequireObj().TreeRunner = function(j$) {
this.#reportDispatcher = attrs.reportDispatcher; this.#reportDispatcher = attrs.reportDispatcher;
this.#runQueue = attrs.runQueue; this.#runQueue = attrs.runQueue;
this.#getConfig = attrs.getConfig; this.#getConfig = attrs.getConfig;
this.#reportChildrenOfBeforeAllFailure =
attrs.reportChildrenOfBeforeAllFailure;
this.#currentRunableTracker = attrs.currentRunableTracker; this.#currentRunableTracker = attrs.currentRunableTracker;
} }
@@ -50,6 +47,10 @@ getJasmineRequireObj().TreeRunner = function(j$) {
}); });
}); });
if (topSuite.hadBeforeAllFailure) {
await this.#reportChildrenOfBeforeAllFailure(topSuite);
}
return { hasFailures: this.#hasFailures }; return { hasFailures: this.#hasFailures };
} }
@@ -247,6 +248,38 @@ getJasmineRequireObj().TreeRunner = function(j$) {
await this.#reportDispatcher.specDone(spec.result); await this.#reportDispatcher.specDone(spec.result);
} }
async #reportChildrenOfBeforeAllFailure(suite) {
for (const child of suite.children) {
if (child instanceof j$.Suite) {
await this.#reportDispatcher.suiteStarted(child.result);
await this.#reportChildrenOfBeforeAllFailure(child);
// Marking the suite passed is consistent with how suites that
// contain failed specs but no suite-level failures are reported.
child.result.status = 'passed';
await this.#reportDispatcher.suiteDone(child.result);
} else {
/* a spec */
await this.#reportDispatcher.specStarted(child.result);
child.addExpectationResult(
false,
{
passed: false,
message:
'Not run because a beforeAll function failed. The ' +
'beforeAll failure will be reported on the suite that ' +
'caused it.'
},
true
);
child.result.status = 'failed';
await this.#reportSpecDone(child);
}
}
}
#addBeforeAndAfterAlls(suite, wrappedChildren) { #addBeforeAndAfterAlls(suite, wrappedChildren) {
if (this.#executionTree.isExcluded(suite)) { if (this.#executionTree.isExcluded(suite)) {
return wrappedChildren; return wrappedChildren;