Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exposes globalConfig to custom test sequencers #14535

Merged
merged 11 commits into from
Sep 19, 2023
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

### Features

- `[jest-test-sequencer, jest-core]` Exposes globalConfig & contexts to TestSequencer ([#14535](https://github.com/jestjs/jest/pull/14535))

### Fixes

- `[jest-leak-detector]` Make leak-detector more aggressive when running GC ([#14526](https://github.com/jestjs/jest/pull/14526))
Expand Down
52 changes: 52 additions & 0 deletions e2e/__tests__/customTestSequencers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,55 @@ test('run failed tests async', () => {
.split('\n');
expect(sequence).toEqual(['./c.test.js', './d.test.js']);
});

test('run tests based on even seed', () => {
const result = runJest(
dir,
[
'-i',
'--config',
JSON.stringify({
testSequencer: '<rootDir>/testSequencerWithSeed.js',
}),
'--seed=2',
],
{},
);
expect(result.exitCode).toBe(0);
const sequence = extractSummary(result.stderr)
.rest.replace(/PASS /g, '')
.split('\n');
expect(sequence).toEqual([
'./a.test.js',
'./b.test.js',
'./c.test.js',
'./d.test.js',
'./e.test.js',
]);
});

test('run tests based on odd seed', () => {
const result = runJest(
dir,
[
'-i',
'--config',
JSON.stringify({
testSequencer: '<rootDir>/testSequencerWithSeed.js',
}),
'--seed=1',
],
{},
);
expect(result.exitCode).toBe(0);
const sequence = extractSummary(result.stderr)
.rest.replace(/PASS /g, '')
.split('\n');
expect(sequence).toEqual([
'./e.test.js',
'./d.test.js',
'./c.test.js',
'./b.test.js',
'./a.test.js',
]);
});
31 changes: 31 additions & 0 deletions e2e/custom-test-sequencer/testSequencerWithSeed.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

const Sequencer = require('@jest/test-sequencer').default;

class CustomSequencer extends Sequencer {
constructor(_options) {
super(_options);
this.globalConfig = _options.globalConfig;
}

sort(tests) {
const copyTests = Array.from(tests);
const seed = this.globalConfig.seed;
const sortedTests = copyTests.sort((testA, testB) =>
testA.path > testB.path ? 1 : -1,
);

if (seed % 2 === 0) {
return sortedTests;
} else {
return sortedTests.reverse();
}
}
}

module.exports = CustomSequencer;
2 changes: 1 addition & 1 deletion packages/jest-core/src/runJest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ export default async function runJest({
const Sequencer: typeof TestSequencer = await requireOrImportModule(
globalConfig.testSequencer,
);
const sequencer = new Sequencer();
const sequencer = new Sequencer({contexts, globalConfig});
let allTests: Array<Test> = [];

if (changedFilesPromise && globalConfig.watch) {
Expand Down
9 changes: 9 additions & 0 deletions packages/jest-test-sequencer/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,17 @@ import * as path from 'path';
import * as fs from 'graceful-fs';
import slash = require('slash');
import type {AggregatedResult, Test, TestContext} from '@jest/test-result';
import type {Config} from '@jest/types';
import HasteMap from 'jest-haste-map';

const FAIL = 0;
const SUCCESS = 1;

export type TestSequencerOptions = {
contexts: ReadonlyArray<TestContext>;
globalConfig: Config.GlobalConfig;
};

type Cache = {
[key: string]:
| [testStatus: typeof FAIL | typeof SUCCESS, testDuration: number]
Expand Down Expand Up @@ -46,6 +52,9 @@ type ShardPositionOptions = ShardOptions & {
export default class TestSequencer {
private readonly _cache = new Map<TestContext, Cache>();

// eslint-disable-next-line @typescript-eslint/no-empty-function
constructor(_options?: TestSequencerOptions) {}

_getCachePath(testContext: TestContext): string {
const {config} = testContext;
const HasteMapClass = HasteMap.getStatic(config);
Expand Down