Skip to content

Commit 977e592

Browse files
authored
chore: upgrade to Jest 28 (#113)
1 parent 6237176 commit 977e592

File tree

10 files changed

+542
-1047
lines changed

10 files changed

+542
-1047
lines changed

.vscode/settings.json

-6
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,5 @@
11
{
22
"editor.rulers": [80],
3-
"files.exclude": {
4-
"**/.git": true,
5-
"**/node_modules": true,
6-
"**/build": true
7-
},
8-
"prettier.parser": "flow",
93
"prettier.printWidth": 80,
104
"prettier.singleQuote": true,
115
"prettier.trailingComma": "all",

README.md

+5-3
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,8 @@ module.exports = createJestRunner(require.resolve('./run'));
7171
const fs = require('fs');
7272
const { pass, fail } = require('create-jest-runner');
7373

74-
module.exports = ({ testPath }) => {
74+
/** @type {import('create-jest-runner').RunTest} */
75+
const runTest = ({ testPath }) => {
7576
const start = Date.now();
7677
const contents = fs.readFileSync(testPath, 'utf8');
7778
const end = Date.now();
@@ -86,6 +87,8 @@ module.exports = ({ testPath }) => {
8687
test: { path: testPath, errorMessage, title: 'Check for ⚔️ 🏃' },
8788
});
8889
};
90+
91+
module.exports = runTest;
8992
```
9093

9194
## Create runner from binary
@@ -97,8 +100,7 @@ yarn create jest-runner my-runner
97100
npm init jest-runner my-runner
98101
```
99102

100-
**Note:** You will have to update the package name in `package.json` of the
101-
generated runner
103+
**Note:** You will have to update the package name in `package.json` of the generated runner.
102104

103105
## Add your runner to Jest config
104106

integrationTests/runner/run.js

+5-2
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@ const fs = require('fs');
22
// eslint-disable-next-line import/extensions, import/no-unresolved -- ignore build artifact
33
const { pass, fail, skip, todo } = require('../..');
44

5-
module.exports = ({ testPath }) => {
5+
/** @type {import('../..').RunTest} */
6+
const runTest = ({ testPath }) => {
67
const start = Date.now();
7-
// we don't want the timestamp in teh reporter result for our snapshots
8+
// we don't want the timestamp in the reporter result for our snapshots
89
const end = start;
910
const contents = fs.readFileSync(testPath, 'utf8');
1011

@@ -24,3 +25,5 @@ module.exports = ({ testPath }) => {
2425
test: { path: testPath, errorMessage, title: 'Check for ⚔️ 🏃' },
2526
});
2627
};
28+
29+
module.exports = runTest;

lib/createJestRunner.ts

+41-41
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
1-
import type { Config } from '@jest/types';
21
import type { TestResult } from '@jest/test-result';
3-
import type * as JestRunner from 'jest-runner';
4-
import { Worker } from 'jest-worker';
2+
import {
3+
CallbackTestRunner,
4+
OnTestFailure,
5+
OnTestStart,
6+
OnTestSuccess,
7+
Test,
8+
TestRunnerOptions,
9+
TestWatcher,
10+
} from 'jest-runner';
11+
import { Worker, JestWorkerFarm } from 'jest-worker';
512
import throat from 'throat';
6-
import type { CreateRunnerOptions, Path, TestRunner } from './types';
13+
import type { CreateRunnerOptions, RunTestOptions } from './types';
714

8-
function determineSlowTestResult(
9-
test: JestRunner.Test,
10-
result: TestResult,
11-
): TestResult {
15+
function determineSlowTestResult(test: Test, result: TestResult): TestResult {
1216
// See: https://github.com/facebook/jest/blob/acd7c83c8365140f4ecf44a456ff7366ffa31fa2/packages/jest-runner/src/runTest.ts#L287
1317
if (result.perfStats.runtime / 1000 > test.context.config.slowTestThreshold) {
1418
return { ...result, perfStats: { ...result.perfStats, slow: true } };
@@ -24,24 +28,19 @@ class CancelRun extends Error {
2428
}
2529

2630
export default function createRunner<
27-
ExtraOptionsType extends Record<string, unknown>,
31+
ExtraOptions extends Record<string, unknown>,
2832
>(
29-
runPath: Path,
30-
{ getExtraOptions }: CreateRunnerOptions<ExtraOptionsType> = {},
31-
): typeof TestRunner {
32-
return class BaseTestRunner implements TestRunner {
33-
constructor(
34-
public readonly _globalConfig: Config.GlobalConfig,
35-
public readonly _context: JestRunner.TestRunnerContext = {},
36-
) {}
37-
33+
runPath: string,
34+
{ getExtraOptions }: CreateRunnerOptions<ExtraOptions> = {},
35+
): typeof CallbackTestRunner {
36+
return class BaseTestRunner extends CallbackTestRunner {
3837
runTests(
39-
tests: Array<JestRunner.Test>,
40-
watcher: JestRunner.TestWatcher,
41-
onStart: JestRunner.OnTestStart,
42-
onResult: JestRunner.OnTestSuccess,
43-
onFailure: JestRunner.OnTestFailure,
44-
options: JestRunner.TestRunnerOptions,
38+
tests: Array<Test>,
39+
watcher: TestWatcher,
40+
onStart: OnTestStart,
41+
onResult: OnTestSuccess,
42+
onFailure: OnTestFailure,
43+
options: TestRunnerOptions,
4544
): Promise<void> {
4645
return options.serial
4746
? this._createInBandTestRun(
@@ -63,12 +62,12 @@ export default function createRunner<
6362
}
6463

6564
_createInBandTestRun(
66-
tests: Array<JestRunner.Test>,
67-
watcher: JestRunner.TestWatcher,
68-
onStart: JestRunner.OnTestStart,
69-
onResult: JestRunner.OnTestSuccess,
70-
onFailure: JestRunner.OnTestFailure,
71-
options: JestRunner.TestRunnerOptions,
65+
tests: Array<Test>,
66+
watcher: TestWatcher,
67+
onStart: OnTestStart,
68+
onResult: OnTestSuccess,
69+
onFailure: OnTestFailure,
70+
options: TestRunnerOptions,
7271
): Promise<void> {
7372
const mutex = throat(1);
7473
return tests.reduce(
@@ -110,29 +109,31 @@ export default function createRunner<
110109
}
111110

112111
_createParallelTestRun(
113-
tests: Array<JestRunner.Test>,
114-
watcher: JestRunner.TestWatcher,
115-
onStart: JestRunner.OnTestStart,
116-
onResult: JestRunner.OnTestSuccess,
117-
onFailure: JestRunner.OnTestFailure,
118-
options: JestRunner.TestRunnerOptions,
112+
tests: Array<Test>,
113+
watcher: TestWatcher,
114+
onStart: OnTestStart,
115+
onResult: OnTestSuccess,
116+
onFailure: OnTestFailure,
117+
options: TestRunnerOptions,
119118
): Promise<void> {
120119
const worker = new Worker(runPath, {
121120
exposedMethods: ['default'],
122121
numWorkers: this._globalConfig.maxWorkers,
123122
forkOptions: { stdio: 'inherit' },
124-
});
123+
}) as JestWorkerFarm<{
124+
default: (runTestOptions: RunTestOptions) => TestResult;
125+
}>;
125126

126127
const mutex = throat(this._globalConfig.maxWorkers);
127128

128-
const runTestInWorker = (test: JestRunner.Test) =>
129+
const runTestInWorker = (test: Test) =>
129130
mutex(() => {
130131
if (watcher.isInterrupted()) {
131132
throw new CancelRun();
132133
}
133134

134135
return onStart(test).then(() => {
135-
const baseOptions = {
136+
const runTestOptions: RunTestOptions = {
136137
config: test.context.config,
137138
globalConfig: this._globalConfig,
138139
testPath: test.path,
@@ -143,8 +144,7 @@ export default function createRunner<
143144
extraOptions: getExtraOptions ? getExtraOptions() : {},
144145
};
145146

146-
// @ts-expect-error -- the required module should have a default export
147-
return worker.default(baseOptions);
147+
return worker.default(runTestOptions);
148148
});
149149
});
150150

lib/fail.ts

+4-5
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,23 @@
11
import type { TestResult } from '@jest/test-result';
22
import toTestResult from './toTestResult';
3-
import type { Path } from './types';
43

54
interface Options {
65
start: number;
76
end: number;
8-
test: { title: string; path: Path; errorMessage?: string };
7+
test: { title: string; path: string; errorMessage?: string };
98
errorMessage?: string;
109
}
1110

1211
export default function fail(options: {
1312
start: number;
1413
end: number;
15-
test: { title: string; path: Path; errorMessage: string };
14+
test: { title: string; path: string; errorMessage: string };
1615
}): TestResult;
1716

1817
export default function fail(options: {
1918
start: number;
2019
end: number;
21-
test: { title: string; path: Path };
20+
test: { title: string; path: string };
2221
errorMessage: string;
2322
}): TestResult;
2423

@@ -30,7 +29,7 @@ export default function fail({
3029
}: Options): TestResult {
3130
// TODO: Currently the `fail` function allows 2 ways to pass an error message.
3231
// Both methods are currently in used by downstream packages.
33-
// The current behaviour is to favour `errorMessage` over `test.errorMessage`.
32+
// The current behavior is to favour `errorMessage` over `test.errorMessage`.
3433
const actualErrorMessage = errorMessage || test.errorMessage;
3534

3635
return toTestResult({

lib/index.ts

+2
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,5 @@ export { default as fail } from './fail';
33
export { default as pass } from './pass';
44
export { default as skip } from './skip';
55
export { default as todo } from './todo';
6+
7+
export type { RunTest, RunTestOptions } from './types';

lib/toTestResult.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import type { TestResult } from '@jest/test-result';
2-
import type { Milliseconds } from './types';
32

43
interface Options {
54
stats: {
@@ -13,7 +12,7 @@ interface Options {
1312
skipped: boolean;
1413
errorMessage?: string | null;
1514
tests: Array<{
16-
duration?: Milliseconds | null;
15+
duration?: number | null;
1716
errorMessage?: string;
1817
testPath?: string;
1918
title?: string;

lib/types.ts

+21-35
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,28 @@
1-
// Common type aliases for better code readability
2-
3-
import type {
4-
Config as JestConfig,
5-
TestResult as JestTestResult,
6-
} from '@jest/types';
7-
import type * as JestRunner from 'jest-runner';
8-
9-
export type Milliseconds = JestTestResult.Milliseconds;
10-
export type Path = JestConfig.Path;
11-
12-
export interface TestDetail {
13-
title: string;
14-
path: Path;
15-
}
1+
import type { TestContext, TestResult } from '@jest/test-result';
2+
import type { Config, TestRunnerOptions } from 'jest-runner';
163

174
export interface CreateRunnerOptions<
18-
ExtraOptionsType extends Record<string, unknown>,
5+
ExtraOptions extends Record<string, unknown>,
196
> {
20-
getExtraOptions?: () => ExtraOptionsType;
7+
getExtraOptions?: () => ExtraOptions;
218
}
229

23-
// Copied and adapted from https://github.com/facebook/jest/blob/2dafb09d51584d3785f3280f569784ec4334b5d8/packages/jest-runner/src/index.ts#L48-L285
24-
export declare abstract class TestRunner {
25-
readonly _globalConfig: JestConfig.GlobalConfig;
26-
27-
readonly _context: JestRunner.TestRunnerContext;
28-
29-
constructor(
30-
globalConfig: JestConfig.GlobalConfig,
31-
context?: JestRunner.TestRunnerContext,
32-
);
10+
export type RunTestOptions<
11+
ExtraOptions extends Record<string, unknown> = Record<string, unknown>,
12+
> = {
13+
config: Config.ProjectConfig;
14+
extraOptions: ExtraOptions;
15+
globalConfig: Config.GlobalConfig;
16+
rawModuleMap: ReturnType<TestContext['moduleMap']['getRawModuleMap']> | null;
17+
options: TestRunnerOptions;
18+
testPath: string;
19+
};
20+
21+
export type RunTest<
22+
ExtraOptions extends Record<string, unknown> = Record<string, unknown>,
23+
> = (options: RunTestOptions<ExtraOptions>) => TestResult | Promise<TestResult>;
3324

34-
runTests(
35-
tests: Array<JestRunner.Test>,
36-
watcher: JestRunner.TestWatcher,
37-
onStart: JestRunner.OnTestStart,
38-
onResult: JestRunner.OnTestSuccess,
39-
onFailure: JestRunner.OnTestFailure,
40-
options: JestRunner.TestRunnerOptions,
41-
): Promise<void>;
25+
export interface TestDetail {
26+
title: string;
27+
path: string;
4228
}

package.json

+7-12
Original file line numberDiff line numberDiff line change
@@ -31,46 +31,41 @@
3131
},
3232
"dependencies": {
3333
"chalk": "^4.1.0",
34-
"jest-worker": "^27.0.6",
34+
"jest-worker": "^28.0.2",
3535
"throat": "^6.0.1"
3636
},
3737
"devDependencies": {
3838
"@babel/cli": "^7.0.0",
3939
"@babel/core": "^7.0.0",
4040
"@babel/preset-env": "^7.0.0",
4141
"@babel/preset-typescript": "^7.0.0",
42-
"@jest/test-result": "^27.0.6",
43-
"@jest/types": "^27.0.6",
42+
"@jest/test-result": "^28.0.2",
4443
"@tsconfig/node12": "^1.0.9",
4544
"@types/node": "^16.11.4",
4645
"@typescript-eslint/eslint-plugin": "^5.14.0",
4746
"@typescript-eslint/parser": "^5.14.0",
48-
"babel-jest": "^27.0.6",
47+
"babel-jest": "^28.0.3",
4948
"eslint": "^8.10.0",
5049
"eslint-config-airbnb-base": "^15.0.0",
5150
"eslint-config-prettier": "^8.3.0",
5251
"eslint-plugin-import": "^2.7.0",
5352
"eslint-plugin-jest": "^26.1.1",
5453
"eslint-plugin-prettier": "^4.0.0",
5554
"execa": "^5.0.0",
56-
"jest": "^27.0.6",
57-
"jest-runner": "^27.0.6",
55+
"jest": "^28.0.3",
56+
"jest-runner": "^28.0.3",
5857
"prettier": "^2.0.5",
5958
"strip-ansi": "^6.0.0",
6059
"typescript": "^4.3.5"
6160
},
6261
"peerDependencies": {
63-
"@jest/test-result": "^27.0.0",
64-
"@jest/types": "^27.0.0",
65-
"jest-runner": "^27.0.0"
62+
"@jest/test-result": "^28.0.0",
63+
"jest-runner": "^28.0.0"
6664
},
6765
"peerDependenciesMeta": {
6866
"@jest/test-result": {
6967
"optional": true
7068
},
71-
"@jest/types": {
72-
"optional": true
73-
},
7469
"jest-runner": {
7570
"optional": true
7671
}

0 commit comments

Comments
 (0)