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

Add option testSequencer allow user use custom sequencer. #8223

Merged
merged 30 commits into from Apr 2, 2019
Merged
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
cac8a66
move testSequencer to individual package
WeiAnAn Mar 26, 2019
27b7eba
add testSequencer option to let user use custom sequencer
WeiAnAn Mar 26, 2019
4b12436
giving testSequencer own normalize function
WeiAnAn Mar 26, 2019
aeea6ad
lint
WeiAnAn Mar 26, 2019
5093f46
remove test comment
WeiAnAn Mar 27, 2019
b94e545
keep export default
WeiAnAn Mar 27, 2019
ca3305e
use interopRequireDefault to import package
WeiAnAn Mar 27, 2019
b5c593a
correct `testSequencer` default package name
WeiAnAn Mar 27, 2019
9223489
add runInBand arg to assure running test in sequence
WeiAnAn Mar 27, 2019
ec029bb
update changelog
WeiAnAn Mar 27, 2019
02f14fa
just only implement sort function in test
WeiAnAn Mar 27, 2019
46ef8f0
add a dependency on @jest/test-scheduler to jest-config so it works i…
WeiAnAn Mar 27, 2019
30ac7e5
remove wrong dependency
WeiAnAn Mar 27, 2019
4bc5a01
let tests easier
WeiAnAn Mar 27, 2019
409a9ba
update docs
WeiAnAn Mar 27, 2019
abc58e2
fix wrong option name
WeiAnAn Mar 27, 2019
934f77c
lint
WeiAnAn Mar 27, 2019
1b3f0ef
add Test type in configuration
WeiAnAn Mar 28, 2019
35b2177
Merge branch 'master' into custom-sequencer
WeiAnAn Mar 29, 2019
f8b9b17
Update docs/CLI.md
jeysal Mar 30, 2019
4efe85c
keep example as js instead of ts
WeiAnAn Mar 30, 2019
20910a9
update changelog which affect multiple packages to one line.
WeiAnAn Mar 30, 2019
2e8fe7b
add @jest/test-sequencer to dependency
WeiAnAn Mar 30, 2019
7d58433
merge master
WeiAnAn Mar 30, 2019
9662a12
update changelog
WeiAnAn Mar 30, 2019
7e8d15a
move @jest/test-sequencer to dev dependency
WeiAnAn Mar 30, 2019
0866aba
Update @jest/core package.json
WeiAnAn Apr 2, 2019
5ffb812
merge version 24.6
WeiAnAn Apr 2, 2019
745cad3
update version to 24.6.0
WeiAnAn Apr 2, 2019
301a5cd
sort
SimenB Apr 2, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Expand Up @@ -10,6 +10,8 @@
- `[pretty-format]` Support React.Suspense ([#8180](https://github.com/facebook/jest/pull/8180))
- `[jest-snapshot]` Indent inline snapshots ([#8198](https://github.com/facebook/jest/pull/8198))
- `[jest-config]` Support colors in `displayName` configuration ([#8025](https://github.com/facebook/jest/pull/8025))
- `[@jest/core, @jest/test-sequencer]` Move `testSequencer` to individual package `@jest/test-sequencer` ([#8223](https://github.com/facebook/jest/pull/8223))
- `[@jest/core, jest-cli, jest-config]` Add option `testSequencer` allow user use custom sequencer. ([#8223](https://github.com/facebook/jest/pull/8223))

### Fixes

Expand Down
4 changes: 4 additions & 0 deletions docs/CLI.md
Expand Up @@ -297,6 +297,10 @@ An array of regexp pattern strings that is tested against all tests paths before

Lets you specify a custom test runner.

### `--testSequencer=<path>`

Lets you specify a custom test sequencer. Please refer to the documentation of the corresponding configuration property for details.

### `--updateSnapshot`

Alias: `-u`. Use this flag to re-record every snapshot that fails during this test run. Can be used together with a test suite pattern or with `--testNamePattern` to re-record snapshots.
Expand Down
25 changes: 25 additions & 0 deletions docs/Configuration.md
Expand Up @@ -1018,6 +1018,31 @@ function testRunner(

An example of such function can be found in our default [jasmine2 test runner package](https://github.com/facebook/jest/blob/master/packages/jest-jasmine2/src/index.js).

### `testSequencer` [string]

Default: `@jest/test-sequencer`

This option allows you to use a custom sequencer instead of Jest's default.

Example:

Sort test path alphabetically

```js
const Sequencer = require('@jest/test-sequencer').default;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could do import Sequencer from '@jest/test-sequencer'; instead to avoid the .default part. Fine as-is though


class CustomSequencer extends Sequencer {
sort(tests) {
WeiAnAn marked this conversation as resolved.
Show resolved Hide resolved
// Test structure information
// https://github.com/facebook/jest/blob/6b8b1404a1d9254e7d5d90a8934087a9c9899dab/packages/jest-runner/src/types.ts#L17-L21
const copyTests = Array.from(tests);
return copyTests.sort((testA, testB) => (testA.path > testB.path ? 1 : -1));
}
}

module.exports = CustomSequencer;
```

### `testURL` [string]

Default: `http://localhost`
Expand Down
1 change: 1 addition & 0 deletions e2e/__tests__/__snapshots__/showConfig.test.ts.snap
Expand Up @@ -117,6 +117,7 @@ exports[`--showConfig outputs config info and exits 1`] = `
"testFailureExitCode": 1,
"testPathPattern": "",
"testResultsProcessor": null,
"testSequencer": "@jest/test-sequencer",
"updateSnapshot": "all",
"useStderr": false,
"verbose": null,
Expand Down
26 changes: 26 additions & 0 deletions e2e/__tests__/customTestSequencers.test.ts
@@ -0,0 +1,26 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

import path from 'path';
import runJest from '../runJest';
import {extractSummary} from '../Utils';
const dir = path.resolve(__dirname, '../custom-test-sequencer');

test('run prioritySequence first', () => {
const result = runJest(dir, ['-i']);
expect(result.status).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',
]);
});
7 changes: 7 additions & 0 deletions e2e/custom-test-sequencer/a.test.js
@@ -0,0 +1,7 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
test('a', () => {});
7 changes: 7 additions & 0 deletions e2e/custom-test-sequencer/b.test.js
@@ -0,0 +1,7 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
test('b', () => {});
7 changes: 7 additions & 0 deletions e2e/custom-test-sequencer/c.test.js
@@ -0,0 +1,7 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
test('c', () => {});
7 changes: 7 additions & 0 deletions e2e/custom-test-sequencer/d.test.js
@@ -0,0 +1,7 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
test('d', () => {});
7 changes: 7 additions & 0 deletions e2e/custom-test-sequencer/e.test.js
@@ -0,0 +1,7 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
test('e', () => {});
6 changes: 6 additions & 0 deletions e2e/custom-test-sequencer/package.json
@@ -0,0 +1,6 @@
{
"jest": {
"testEnvironment": "node",
"testSequencer": "<rootDir>/testSequencer.js"
}
}
17 changes: 17 additions & 0 deletions e2e/custom-test-sequencer/testSequencer.js
@@ -0,0 +1,17 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* 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 {
sort(tests) {
SimenB marked this conversation as resolved.
Show resolved Hide resolved
WeiAnAn marked this conversation as resolved.
Show resolved Hide resolved
const copyTests = Array.from(tests);
return copyTests.sort((testA, testB) => (testA.path > testB.path ? 1 : -1));
}
}

module.exports = CustomSequencer;
7 changes: 7 additions & 0 deletions packages/jest-cli/src/cli/args.ts
Expand Up @@ -615,6 +615,13 @@ export const options = {
'`<rootDir>/path/to/testRunner.js`.',
type: 'string' as 'string',
},
testSequencer: {
thymikee marked this conversation as resolved.
Show resolved Hide resolved
description:
'Allows to specify a custom test sequencer. The default is ' +
'`@jest/test-sequencer`. A path to a custom test sequencer can be ' +
'provided: `<rootDir>/path/to/testSequencer.js`',
type: 'string' as 'string',
},
testURL: {
description: 'This option sets the URL for the jsdom environment.',
type: 'string' as 'string',
Expand Down
1 change: 1 addition & 0 deletions packages/jest-config/package.json
Expand Up @@ -12,6 +12,7 @@
"dependencies": {
"@babel/core": "^7.1.0",
"@jest/types": "^24.5.0",
"@jest/test-sequencer": "^24.5.0",
"babel-jest": "^24.5.0",
"chalk": "^2.0.1",
"glob": "^7.1.1",
Expand Down
1 change: 1 addition & 0 deletions packages/jest-config/src/Defaults.ts
Expand Up @@ -71,6 +71,7 @@ const defaultOptions: Config.DefaultOptions = {
testRegex: [],
testResultsProcessor: null,
testRunner: 'jasmine2',
testSequencer: '@jest/test-sequencer',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This value doesn't get fully resolved unless explicitly set, so it cannot work with PnP. It should be done like here: https://github.com/WeiAnAn/jest/blob/301a5cda50bf82617fe776938ee3fbd1c24b4a7c/packages/jest-config/src/normalize.ts#L477-L479

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We resolve it in normalize already don't we?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm checking, but I think it only get resolved when the testSequence option is explicitly set - otherwise it uses the default value as-is.

testURL: 'http://localhost',
timers: 'real',
transform: null,
Expand Down
1 change: 1 addition & 0 deletions packages/jest-config/src/ValidConfig.ts
Expand Up @@ -114,6 +114,7 @@ const initialOptions: Config.InitialOptions = {
),
testResultsProcessor: 'processor-node-module',
testRunner: 'jasmine2',
testSequencer: '@jest/test-sequencer',
testURL: 'http://localhost',
timers: 'real',
transform: {
Expand Down
1 change: 1 addition & 0 deletions packages/jest-config/src/index.ts
Expand Up @@ -148,6 +148,7 @@ const groupOptions = (
testNamePattern: options.testNamePattern,
testPathPattern: options.testPathPattern,
testResultsProcessor: options.testResultsProcessor,
testSequencer: options.testSequencer,
updateSnapshot: options.updateSnapshot,
useStderr: options.useStderr,
verbose: options.verbose,
Expand Down
12 changes: 12 additions & 0 deletions packages/jest-config/src/normalize.ts
Expand Up @@ -29,6 +29,7 @@ import {
getRunner,
getWatchPlugin,
resolve,
getSequencer,
} from './utils';
import {DEFAULT_JS_PATTERN, DEFAULT_REPORTER_LABEL} from './constants';
import {validateReporters} from './ReporterValidationErrors';
Expand Down Expand Up @@ -588,6 +589,17 @@ export default function normalize(
});
}
break;
case 'testSequencer':
{
const option = oldOptions[key];
value =
option &&
getSequencer(newOptions.resolver, {
WeiAnAn marked this conversation as resolved.
Show resolved Hide resolved
filePath: option,
rootDir: options.rootDir,
});
}
break;
case 'prettierPath':
{
// We only want this to throw if "prettierPath" is explicitly passed
Expand Down
12 changes: 12 additions & 0 deletions packages/jest-config/src/utils.ts
Expand Up @@ -223,3 +223,15 @@ export const isJSONString = (text?: JSONString | string): text is JSONString =>
typeof text === 'string' &&
text.startsWith('{') &&
text.endsWith('}');

export const getSequencer = (
resolver: string | undefined | null,
{filePath, rootDir}: {filePath: string; rootDir: Config.Path},
) =>
resolveWithPrefix(resolver, {
filePath,
humanOptionName: 'Jest Sequencer',
optionName: 'testSequencer',
prefix: 'jest-sequencer-',
rootDir,
});
3 changes: 2 additions & 1 deletion packages/jest-core/package.json
Expand Up @@ -40,7 +40,8 @@
"@types/micromatch": "^3.1.0",
"@types/p-each-series": "^1.0.0",
"@types/rimraf": "^2.0.2",
"@types/strip-ansi": "^3.0.0"
"@types/strip-ansi": "^3.0.0",
"@jest/test-sequencer": "^24.5.0"
WeiAnAn marked this conversation as resolved.
Show resolved Hide resolved
},
"engines": {
"node": ">= 6"
Expand Down
2 changes: 1 addition & 1 deletion packages/jest-core/src/__tests__/run_jest.test.js
Expand Up @@ -16,7 +16,7 @@ describe('runJest', () => {
await runJest({
changedFilesPromise: Promise.resolve({repos: {git: {size: 0}}}),
contexts: [],
globalConfig: {watch: true},
globalConfig: {testSequencer: '@jest/test-sequencer', watch: true},
onComplete: () => null,
outputStream: {},
startRun: {},
Expand Down
9 changes: 6 additions & 3 deletions packages/jest-core/src/runJest.ts
Expand Up @@ -9,7 +9,7 @@ import path from 'path';
import chalk from 'chalk';
import {sync as realpath} from 'realpath-native';
import {CustomConsole} from '@jest/console';
import {formatTestResults} from 'jest-util';
import {formatTestResults, interopRequireDefault} from 'jest-util';
import exit from 'exit';
import fs from 'graceful-fs';
import {JestHook, JestHookEmitter} from 'jest-watcher';
Expand All @@ -20,12 +20,12 @@ import {
AggregatedResult,
makeEmptyAggregatedTestResult,
} from '@jest/test-result';
import TestSequencer from '@jest/test-sequencer'; // eslint-disable-line import/no-extraneous-dependencies
import {ChangedFiles, ChangedFilesPromise} from 'jest-changed-files';
import getNoTestsFoundMessage from './getNoTestsFoundMessage';
import runGlobalHook from './runGlobalHook';
import SearchSource from './SearchSource';
import TestScheduler, {TestSchedulerContext} from './TestScheduler';
import TestSequencer from './TestSequencer';
import FailedTestsCache from './FailedTestsCache';
import collectNodeHandles from './collectHandles';
import TestWatcher from './TestWatcher';
Expand Down Expand Up @@ -143,7 +143,10 @@ export default (async function runJest({
failedTestsCache?: FailedTestsCache;
filter?: Filter;
}) {
const sequencer = new TestSequencer();
const Sequencer: typeof TestSequencer = interopRequireDefault(
require(globalConfig.testSequencer),
).default;
const sequencer = new Sequencer();
let allTests: Array<Test> = [];

if (changedFilesPromise && globalConfig.watch) {
Expand Down
1 change: 1 addition & 0 deletions packages/jest-core/tsconfig.json
Expand Up @@ -17,6 +17,7 @@
{"path": "../jest-runtime"},
{"path": "../jest-snapshot"},
{"path": "../jest-test-result"},
{"path": "../jest-test-sequencer"},
{"path": "../jest-types"},
{"path": "../jest-transform"},
{"path": "../jest-util"},
Expand Down
3 changes: 3 additions & 0 deletions packages/jest-test-sequencer/.npmignore
@@ -0,0 +1,3 @@
**/__mocks__/**
**/__tests__/**
src
25 changes: 25 additions & 0 deletions packages/jest-test-sequencer/package.json
@@ -0,0 +1,25 @@
{
"name": "@jest/test-sequencer",
"version": "24.5.0",
"repository": {
"type": "git",
"url": "https://github.com/facebook/jest.git",
"directory": "packages/test-sequencer"
},
"license": "MIT",
"main": "build/index.js",
"types": "build/index.d.ts",
"dependencies": {
"@jest/test-result": "^24.5.0",
"jest-haste-map": "^24.5.0",
"jest-runtime": "^24.5.0",
"jest-runner": "^24.5.0"
},
"engines": {
"node": ">= 6"
},
"publishConfig": {
"access": "public"
},
"gitHead": "800533020f5b2f153615c821ed7cb12fd868fa6f"
}
Expand Up @@ -6,7 +6,7 @@
*/
'use strict';

import TestSequencer from '../TestSequencer';
import TestSequencer from '../index';

jest.mock('fs');

Expand Down
13 changes: 13 additions & 0 deletions packages/jest-test-sequencer/tsconfig.json
@@ -0,0 +1,13 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"rootDir": "src",
"outDir": "build"
},
"references": [
{"path": "../jest-haste-map"},
{"path": "../jest-runner"},
{"path": "../jest-test-result"},
{"path": "../jest-types"}
]
}
4 changes: 4 additions & 0 deletions packages/jest-types/src/Config.ts
Expand Up @@ -88,6 +88,7 @@ export type DefaultOptions = {
testRegex: Array<string>;
testResultsProcessor: string | null | undefined;
testRunner: string | null | undefined;
testSequencer: string;
testURL: string;
timers: 'real' | 'fake';
transform:
Expand Down Expand Up @@ -203,6 +204,7 @@ export type InitialOptions = {
testRegex?: string | Array<string>;
testResultsProcessor?: string | null | undefined;
testRunner?: string;
testSequencer?: string;
testURL?: string;
timers?: 'real' | 'fake';
transform?: {
Expand Down Expand Up @@ -340,6 +342,7 @@ export type GlobalConfig = {
testNamePattern: string;
testPathPattern: string;
testResultsProcessor: string | null | undefined;
testSequencer: string;
updateSnapshot: SnapshotUpdateState;
useStderr: boolean;
verbose: boolean | null | undefined;
Expand Down Expand Up @@ -483,6 +486,7 @@ export type Argv = Arguments<
testRegex: string | Array<string>;
testResultsProcessor: string | null | undefined;
testRunner: string;
testSequencer: string;
testURL: string;
timers: string;
transform: string;
Expand Down