Skip to content

Commit b097e43

Browse files
authored
fix: perform global teardown if bailing from failed tests (#15833)
1 parent e656444 commit b097e43

File tree

2 files changed

+61
-4
lines changed

2 files changed

+61
-4
lines changed

packages/jest-core/src/TestScheduler.ts

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ import {
4141
import {ErrorWithStack, invariant, requireOrImportModule} from 'jest-util';
4242
import type {TestWatcher} from 'jest-watcher';
4343
import ReporterDispatcher from './ReporterDispatcher';
44+
import runGlobalHook from './runGlobalHook';
4445
import {shouldRunInBand} from './testSchedulerHelper';
4546

4647
export type ReporterConstructor = new (
@@ -150,7 +151,12 @@ class TestScheduler {
150151
testResult,
151152
aggregatedResults,
152153
);
153-
return this._bailIfNeeded(testContexts, aggregatedResults, watcher);
154+
return this._bailIfNeeded(
155+
testContexts,
156+
aggregatedResults,
157+
watcher,
158+
tests,
159+
);
154160
};
155161

156162
const onFailure = async (test: Test, error: SerializableError) => {
@@ -408,6 +414,7 @@ class TestScheduler {
408414
testContexts: Set<TestContext>,
409415
aggregatedResults: AggregatedResult,
410416
watcher: TestWatcher,
417+
allTests: Array<Test>,
411418
): Promise<void> {
412419
if (
413420
this._globalConfig.bail !== 0 &&
@@ -421,8 +428,17 @@ class TestScheduler {
421428
try {
422429
await this._dispatcher.onRunComplete(testContexts, aggregatedResults);
423430
} finally {
424-
const exitCode = this._globalConfig.testFailureExitCode;
425-
exit(exitCode);
431+
// Perform global teardown if client configures `bail`
432+
if (allTests.length > 0) {
433+
performance.mark('jest/globalTeardown:start');
434+
await runGlobalHook({
435+
allTests,
436+
globalConfig: this._globalConfig,
437+
moduleName: 'globalTeardown',
438+
});
439+
performance.mark('jest/globalTeardown:end');
440+
exit(this._globalConfig.testFailureExitCode);
441+
}
426442
}
427443
}
428444
}

packages/jest-core/src/__tests__/TestScheduler.test.js

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import {makeGlobalConfig, makeProjectConfig} from '@jest/test-utils';
1818
import * as transform from '@jest/transform';
1919
import {createTestScheduler} from '../TestScheduler';
2020
import * as testSchedulerHelper from '../testSchedulerHelper';
21+
import * as runGlobalHook from '../runGlobalHook';
2122

2223
jest
2324
.mock('ci-info', () => ({GITHUB_ACTIONS: true}))
@@ -35,7 +36,8 @@ jest
3536
__esModule: true,
3637
...jest.requireActual('@jest/transform'),
3738
};
38-
});
39+
})
40+
.mock('exit-x', () => ({__esModule: true, default: jest.fn()}));
3941
const mockSerialRunner = {
4042
isSerial: true,
4143
runTests: jest.fn(),
@@ -53,10 +55,13 @@ jest.mock('jest-runner-parallel', () => jest.fn(() => mockParallelRunner), {
5355

5456
const spyShouldRunInBand = jest.spyOn(testSchedulerHelper, 'shouldRunInBand');
5557

58+
const spyRunGlobalHook = jest.spyOn(runGlobalHook, 'default');
59+
5660
beforeEach(() => {
5761
mockSerialRunner.runTests.mockClear();
5862
mockParallelRunner.runTests.mockClear();
5963
spyShouldRunInBand.mockClear();
64+
spyRunGlobalHook.mockClear();
6065
});
6166

6267
describe('reporters', () => {
@@ -449,6 +454,42 @@ test('should bail after `n` failures', async () => {
449454
expect(setState).toHaveBeenCalledWith({interrupted: true});
450455
});
451456

457+
test('should bail after `n` failures and perform global teardown', async () => {
458+
const scheduler = await createTestScheduler(
459+
makeGlobalConfig({bail: 3}),
460+
{},
461+
{},
462+
);
463+
const test = {
464+
context: {
465+
config: makeProjectConfig({
466+
moduleFileExtensions: ['.js'],
467+
rootDir: './',
468+
runner: 'jest-runner-serial',
469+
transform: [],
470+
}),
471+
hasteFS: {
472+
matchFiles: jest.fn(() => []),
473+
},
474+
},
475+
path: './test/path.js',
476+
};
477+
478+
const tests = [test];
479+
const setState = jest.fn();
480+
await scheduler.scheduleTests(tests, {
481+
isInterrupted: jest.fn(),
482+
isWatchMode: () => false,
483+
setState,
484+
});
485+
await mockSerialRunner.runTests.mock.calls[0][3](test, {
486+
numFailingTests: 3,
487+
snapshot: {},
488+
testResults: [{}],
489+
});
490+
expect(spyRunGlobalHook.mock.calls[0][0].moduleName).toBe('globalTeardown');
491+
});
492+
452493
test('should not bail if less than `n` failures', async () => {
453494
const scheduler = await createTestScheduler(
454495
makeGlobalConfig({bail: 2}),

0 commit comments

Comments
 (0)