mirror of https://github.com/facebook/jest.git
jest-circus runs children in shuffled order (#12922)
This commit is contained in:
parent
ab510f5c9e
commit
cbe0ac1b76
|
@ -3,6 +3,7 @@
|
||||||
### Features
|
### Features
|
||||||
|
|
||||||
- `[jest-changed-files]` Support Sapling ([#13941](https://github.com/facebook/jest/pull/13941))
|
- `[jest-changed-files]` Support Sapling ([#13941](https://github.com/facebook/jest/pull/13941))
|
||||||
|
- `[jest-circus, @jest/cli, jest-config]` Add feature to randomize order of tests via CLI flag or through the config file([#12922](https://github.com/facebook/jest/pull/12922))
|
||||||
- `[jest-cli, jest-config, @jest/core, jest-haste-map, @jest/reporters, jest-runner, jest-runtime, @jest/types]` Add `workerThreads` configuration option to allow using [worker threads](https://nodejs.org/dist/latest/docs/api/worker_threads.html) for parallelization ([#13939](https://github.com/facebook/jest/pull/13939))
|
- `[jest-cli, jest-config, @jest/core, jest-haste-map, @jest/reporters, jest-runner, jest-runtime, @jest/types]` Add `workerThreads` configuration option to allow using [worker threads](https://nodejs.org/dist/latest/docs/api/worker_threads.html) for parallelization ([#13939](https://github.com/facebook/jest/pull/13939))
|
||||||
- `[jest-config]` Add `openHandlesTimeout` option to configure possible open handles warning. ([#13875](https://github.com/facebook/jest/pull/13875))
|
- `[jest-config]` Add `openHandlesTimeout` option to configure possible open handles warning. ([#13875](https://github.com/facebook/jest/pull/13875))
|
||||||
- `[@jest/create-cache-key-function]` Allow passing `length` argument to `createCacheKey()` function and set its default value to `16` on Windows ([#13827](https://github.com/facebook/jest/pull/13827))
|
- `[@jest/create-cache-key-function]` Allow passing `length` argument to `createCacheKey()` function and set its default value to `16` on Windows ([#13827](https://github.com/facebook/jest/pull/13827))
|
||||||
|
|
16
docs/CLI.md
16
docs/CLI.md
|
@ -332,6 +332,22 @@ If configuration files are found in the specified paths, _all_ projects specifie
|
||||||
|
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
### `--randomize`
|
||||||
|
|
||||||
|
Shuffle the order of the tests within a file. The shuffling is based on the seed. See [`--seed=<num>`](#--seednum) for more info.
|
||||||
|
|
||||||
|
Seed value is displayed when this option is set. Equivalent to setting the CLI option [`--showSeed`](#--showseed).
|
||||||
|
|
||||||
|
```bash
|
||||||
|
jest --randomize --seed 1234
|
||||||
|
```
|
||||||
|
|
||||||
|
:::note
|
||||||
|
|
||||||
|
This option is only supported using the default `jest-circus` test runner.
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
### `--reporters`
|
### `--reporters`
|
||||||
|
|
||||||
Run tests with specified reporters. [Reporter options](configuration#reporters-arraymodulename--modulename-options) are not available via CLI. Example with multiple reporters:
|
Run tests with specified reporters. [Reporter options](configuration#reporters-arraymodulename--modulename-options) are not available via CLI. Example with multiple reporters:
|
||||||
|
|
|
@ -1222,6 +1222,12 @@ With the `projects` option enabled, Jest will copy the root-level configuration
|
||||||
|
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
### `randomize` \[boolean]
|
||||||
|
|
||||||
|
Default: `false`
|
||||||
|
|
||||||
|
The equivalent of the [`--randomize`](CLI.md#--randomize) flag to randomize the order of the tests in a file.
|
||||||
|
|
||||||
### `reporters` \[array<moduleName | \[moduleName, options]>]
|
### `reporters` \[array<moduleName | \[moduleName, options]>]
|
||||||
|
|
||||||
Default: `undefined`
|
Default: `undefined`
|
||||||
|
|
|
@ -0,0 +1,89 @@
|
||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`works with each 1`] = `
|
||||||
|
" ✓ test1
|
||||||
|
✓ test2
|
||||||
|
✓ test3
|
||||||
|
describe2
|
||||||
|
✓ test4
|
||||||
|
✓ test6
|
||||||
|
✓ test5
|
||||||
|
describe1
|
||||||
|
✓ test4
|
||||||
|
✓ test6
|
||||||
|
✓ test5
|
||||||
|
describe3
|
||||||
|
✓ test11
|
||||||
|
✓ test12
|
||||||
|
✓ test10
|
||||||
|
describe4
|
||||||
|
✓ test14
|
||||||
|
✓ test15
|
||||||
|
✓ test13"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`works with hooks 1`] = `
|
||||||
|
" ✓ test1
|
||||||
|
✓ test2
|
||||||
|
✓ test3
|
||||||
|
describe2
|
||||||
|
✓ test7
|
||||||
|
✓ test9
|
||||||
|
✓ test8
|
||||||
|
describe1
|
||||||
|
✓ test4
|
||||||
|
✓ test6
|
||||||
|
✓ test5
|
||||||
|
describe3
|
||||||
|
✓ test11
|
||||||
|
✓ test12
|
||||||
|
✓ test10
|
||||||
|
describe4
|
||||||
|
✓ test14
|
||||||
|
✓ test15
|
||||||
|
✓ test13"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`works with passing tests 1`] = `
|
||||||
|
" ✓ test1
|
||||||
|
✓ test2
|
||||||
|
✓ test3
|
||||||
|
describe2
|
||||||
|
✓ test7
|
||||||
|
✓ test9
|
||||||
|
✓ test8
|
||||||
|
describe1
|
||||||
|
✓ test4
|
||||||
|
✓ test6
|
||||||
|
✓ test5
|
||||||
|
describe3
|
||||||
|
✓ test11
|
||||||
|
✓ test12
|
||||||
|
✓ test10
|
||||||
|
describe4
|
||||||
|
✓ test14
|
||||||
|
✓ test15
|
||||||
|
✓ test13"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`works with snapshots 1`] = `
|
||||||
|
" ✓ test1
|
||||||
|
✓ test2
|
||||||
|
✓ test3
|
||||||
|
describe2
|
||||||
|
✓ test4
|
||||||
|
✓ test6
|
||||||
|
✓ test5
|
||||||
|
describe1
|
||||||
|
✓ test4
|
||||||
|
✓ test6
|
||||||
|
✓ test5
|
||||||
|
describe3
|
||||||
|
✓ test11
|
||||||
|
✓ test12
|
||||||
|
✓ test10
|
||||||
|
describe4
|
||||||
|
✓ test14
|
||||||
|
✓ test15
|
||||||
|
✓ test13"
|
||||||
|
`;
|
|
@ -0,0 +1,85 @@
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import * as path from 'path';
|
||||||
|
import {skipSuiteOnJasmine} from '@jest/test-utils';
|
||||||
|
import {extractSummary} from '../Utils';
|
||||||
|
import runJest, {RunJestResult} from '../runJest';
|
||||||
|
|
||||||
|
skipSuiteOnJasmine();
|
||||||
|
|
||||||
|
const dir = path.resolve(__dirname, '../randomize');
|
||||||
|
|
||||||
|
const trimFirstLine = (str: string): string =>
|
||||||
|
str.split('\n').slice(1).join('\n');
|
||||||
|
|
||||||
|
function runJestTwice(
|
||||||
|
dir: string,
|
||||||
|
args: Array<string>,
|
||||||
|
): [RunJestResult, RunJestResult] {
|
||||||
|
return [
|
||||||
|
runJest(dir, [...args, '--randomize']),
|
||||||
|
runJest(dir, [...args, '--config', 'different-config.json']),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
test('works with passing tests', () => {
|
||||||
|
const [result1, result2] = runJestTwice(dir, [
|
||||||
|
'success.test.js',
|
||||||
|
'--seed',
|
||||||
|
'123',
|
||||||
|
]);
|
||||||
|
|
||||||
|
const rest1 = trimFirstLine(extractSummary(result1.stderr).rest);
|
||||||
|
const rest2 = trimFirstLine(extractSummary(result2.stderr).rest);
|
||||||
|
|
||||||
|
expect(rest1).toEqual(rest2);
|
||||||
|
expect(rest1).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('works with each', () => {
|
||||||
|
const [result1, result2] = runJestTwice(dir, [
|
||||||
|
'each.test.js',
|
||||||
|
'--seed',
|
||||||
|
'123',
|
||||||
|
]);
|
||||||
|
|
||||||
|
const rest1 = trimFirstLine(extractSummary(result1.stderr).rest);
|
||||||
|
const rest2 = trimFirstLine(extractSummary(result2.stderr).rest);
|
||||||
|
|
||||||
|
expect(rest1).toEqual(rest2);
|
||||||
|
expect(rest1).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('works with hooks', () => {
|
||||||
|
const [result1, result2] = runJestTwice(dir, [
|
||||||
|
'hooks.test.js',
|
||||||
|
'--seed',
|
||||||
|
'123',
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Change in formatting could change this one
|
||||||
|
const rest1 = trimFirstLine(extractSummary(result1.stderr).rest);
|
||||||
|
const rest2 = trimFirstLine(extractSummary(result2.stderr).rest);
|
||||||
|
|
||||||
|
expect(rest1).toEqual(rest2);
|
||||||
|
expect(rest1).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('works with snapshots', () => {
|
||||||
|
const [result1, result2] = runJestTwice(dir, [
|
||||||
|
'snapshots.test.js',
|
||||||
|
'--seed',
|
||||||
|
'123',
|
||||||
|
]);
|
||||||
|
|
||||||
|
const rest1 = trimFirstLine(extractSummary(result1.stderr).rest);
|
||||||
|
const rest2 = trimFirstLine(extractSummary(result2.stderr).rest);
|
||||||
|
|
||||||
|
expect(rest1).toEqual(rest2);
|
||||||
|
expect(rest1).toMatchSnapshot();
|
||||||
|
});
|
|
@ -14,39 +14,41 @@ const dir = path.resolve(__dirname, '../jest-object');
|
||||||
const randomSeedValueRegExp = /Seed:\s+<<REPLACED>>/;
|
const randomSeedValueRegExp = /Seed:\s+<<REPLACED>>/;
|
||||||
const seedValueRegExp = /Seed:\s+1234/;
|
const seedValueRegExp = /Seed:\s+1234/;
|
||||||
|
|
||||||
test('--showSeed changes report to output seed', () => {
|
describe.each(['showSeed', 'randomize'])('Option %s', option => {
|
||||||
const {stderr} = runJest(dir, ['--showSeed', '--no-cache']);
|
test(`--${option} changes report to output seed`, () => {
|
||||||
|
const {stderr} = runJest(dir, [`--${option}`, '--no-cache']);
|
||||||
|
|
||||||
const {summary} = extractSummary(stderr);
|
const {summary} = extractSummary(stderr);
|
||||||
|
|
||||||
expect(replaceSeed(summary)).toMatch(randomSeedValueRegExp);
|
expect(replaceSeed(summary)).toMatch(randomSeedValueRegExp);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('if --showSeed is not present the report will not show the seed', () => {
|
test(`if --${option} is not present the report will not show the seed`, () => {
|
||||||
const {stderr} = runJest(dir, ['--seed', '1234']);
|
const {stderr} = runJest(dir, ['--seed', '1234']);
|
||||||
|
|
||||||
const {summary} = extractSummary(stderr);
|
const {summary} = extractSummary(stderr);
|
||||||
|
|
||||||
expect(replaceSeed(summary)).not.toMatch(randomSeedValueRegExp);
|
expect(replaceSeed(summary)).not.toMatch(randomSeedValueRegExp);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('if showSeed is present in the config the report will show the seed', () => {
|
test(`if ${option} is present in the config the report will show the seed`, () => {
|
||||||
const {stderr} = runJest(dir, [
|
const {stderr} = runJest(dir, [
|
||||||
'--seed',
|
'--seed',
|
||||||
'1234',
|
'1234',
|
||||||
'--config',
|
'--config',
|
||||||
'different-config.json',
|
`${option}-config.json`,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const {summary} = extractSummary(stderr);
|
const {summary} = extractSummary(stderr);
|
||||||
|
|
||||||
expect(summary).toMatch(seedValueRegExp);
|
expect(summary).toMatch(seedValueRegExp);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('--seed --showSeed will show the seed in the report', () => {
|
test(`--seed --${option} will show the seed in the report`, () => {
|
||||||
const {stderr} = runJest(dir, ['--showSeed', '--seed', '1234']);
|
const {stderr} = runJest(dir, [`--${option}`, '--seed', '1234']);
|
||||||
|
|
||||||
const {summary} = extractSummary(stderr);
|
const {summary} = extractSummary(stderr);
|
||||||
|
|
||||||
expect(summary).toMatch(seedValueRegExp);
|
expect(summary).toMatch(seedValueRegExp);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"displayName": "Config from randomize-config.json file",
|
||||||
|
"randomize": true
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"displayName": "Config from showSeed-config.json file",
|
||||||
|
"showSeed": true
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`describe1 test4 1`] = `4`;
|
||||||
|
|
||||||
|
exports[`describe1 test5 1`] = `5`;
|
||||||
|
|
||||||
|
exports[`describe1 test6 1`] = `6`;
|
||||||
|
|
||||||
|
exports[`describe2 test4 1`] = `4`;
|
||||||
|
|
||||||
|
exports[`describe2 test5 1`] = `5`;
|
||||||
|
|
||||||
|
exports[`describe2 test6 1`] = `6`;
|
||||||
|
|
||||||
|
exports[`describe3 describe4 test13 1`] = `13`;
|
||||||
|
|
||||||
|
exports[`describe3 describe4 test14 1`] = `14`;
|
||||||
|
|
||||||
|
exports[`describe3 describe4 test15 1`] = `15`;
|
||||||
|
|
||||||
|
exports[`describe3 test10 1`] = `10`;
|
||||||
|
|
||||||
|
exports[`describe3 test11 1`] = `11`;
|
||||||
|
|
||||||
|
exports[`describe3 test12 1`] = `12`;
|
||||||
|
|
||||||
|
exports[`test1 1`] = `1`;
|
||||||
|
|
||||||
|
exports[`test2 1`] = `2`;
|
||||||
|
|
||||||
|
exports[`test3 1`] = `3`;
|
|
@ -0,0 +1,28 @@
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
it.each([1, 2, 3])('test%d', () => {
|
||||||
|
expect(true).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe.each([1, 2])('describe%d', () => {
|
||||||
|
it.each([4, 5, 6])('test%d', () => {
|
||||||
|
expect(true).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('describe3', () => {
|
||||||
|
it.each([10, 11, 12])('test%d', () => {
|
||||||
|
expect(true).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('describe4', () => {
|
||||||
|
it.each([13, 14, 15])('test%d', () => {
|
||||||
|
expect(true).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,98 @@
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
process.stdout.write('This is before all\n');
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
process.stdout.write('This is before each\n');
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
process.stdout.write('This is after each\n');
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(() => {
|
||||||
|
process.stdout.write('This is after all\n');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('test1', () => {
|
||||||
|
process.stdout.write('test1\n');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('test2', () => {
|
||||||
|
process.stdout.write('test2\n');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('test3', () => {
|
||||||
|
process.stdout.write('test3\n');
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('describe1', () => {
|
||||||
|
it('test4', () => {
|
||||||
|
process.stdout.write('test4\n');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('test5', () => {
|
||||||
|
process.stdout.write('test5\n');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('test6', () => {
|
||||||
|
process.stdout.write('test6\n');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('describe2', () => {
|
||||||
|
afterAll(() => {
|
||||||
|
process.stdout.write('This is after all describe2\n');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('test7', () => {
|
||||||
|
process.stdout.write('test7\n');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('test8', () => {
|
||||||
|
process.stdout.write('test8\n');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('test9', () => {
|
||||||
|
process.stdout.write('test9\n');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('describe3', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
process.stdout.write('This is before each describe3\n');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('test10', () => {
|
||||||
|
process.stdout.write('test10\n');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('test11', () => {
|
||||||
|
process.stdout.write('test11\n');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('test12', () => {
|
||||||
|
process.stdout.write('test12\n');
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('describe4', () => {
|
||||||
|
it('test13', () => {
|
||||||
|
process.stdout.write('test13\n');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('test14', () => {
|
||||||
|
process.stdout.write('test14\n');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('test15', () => {
|
||||||
|
process.stdout.write('test15\n');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,28 @@
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
it.each([1, 2, 3])('test%d', n => {
|
||||||
|
expect(n).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe.each([1, 2])('describe%d', () => {
|
||||||
|
it.each([4, 5, 6])('test%d', n => {
|
||||||
|
expect(n).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('describe3', () => {
|
||||||
|
it.each([10, 11, 12])('test%d', n => {
|
||||||
|
expect(n).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('describe4', () => {
|
||||||
|
it.each([13, 14, 15])('test%d', n => {
|
||||||
|
expect(n).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,74 @@
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
it('test1', () => {
|
||||||
|
expect(true).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('test2', () => {
|
||||||
|
expect(true).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('test3', () => {
|
||||||
|
expect(true).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('describe1', () => {
|
||||||
|
it('test4', () => {
|
||||||
|
expect(true).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('test5', () => {
|
||||||
|
expect(true).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('test6', () => {
|
||||||
|
expect(true).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('describe2', () => {
|
||||||
|
it('test7', () => {
|
||||||
|
expect(true).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('test8', () => {
|
||||||
|
expect(true).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('test9', () => {
|
||||||
|
expect(true).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('describe3', () => {
|
||||||
|
it('test10', () => {
|
||||||
|
expect(true).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('test11', () => {
|
||||||
|
expect(true).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('test12', () => {
|
||||||
|
expect(true).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('describe4', () => {
|
||||||
|
it('test13', () => {
|
||||||
|
expect(true).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('test14', () => {
|
||||||
|
expect(true).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('test15', () => {
|
||||||
|
expect(true).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -1,4 +1,4 @@
|
||||||
{
|
{
|
||||||
"displayName": "Config from different-config.json file",
|
"displayName": "Config from different-config.json file",
|
||||||
"showSeed": true
|
"randomize": true
|
||||||
}
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"jest": {
|
||||||
|
"testEnvironment": "node"
|
||||||
|
}
|
||||||
|
}
|
|
@ -35,6 +35,7 @@
|
||||||
"jest-util": "workspace:^",
|
"jest-util": "workspace:^",
|
||||||
"p-limit": "^3.1.0",
|
"p-limit": "^3.1.0",
|
||||||
"pretty-format": "workspace:^",
|
"pretty-format": "workspace:^",
|
||||||
|
"pure-rand": "^6.0.0",
|
||||||
"slash": "^3.0.0",
|
"slash": "^3.0.0",
|
||||||
"stack-utils": "^2.0.3"
|
"stack-utils": "^2.0.3"
|
||||||
},
|
},
|
||||||
|
|
|
@ -26,7 +26,10 @@ interface Result extends ExecaSyncReturnValue {
|
||||||
error: string;
|
error: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const runTest = (source: string) => {
|
export const runTest = (
|
||||||
|
source: string,
|
||||||
|
opts?: {seed?: number; randomize?: boolean},
|
||||||
|
) => {
|
||||||
const filename = createHash('sha1')
|
const filename = createHash('sha1')
|
||||||
.update(source)
|
.update(source)
|
||||||
.digest('hex')
|
.digest('hex')
|
||||||
|
@ -44,7 +47,9 @@ export const runTest = (source: string) => {
|
||||||
global.afterAll = circus.afterAll;
|
global.afterAll = circus.afterAll;
|
||||||
|
|
||||||
const testEventHandler = require('${TEST_EVENT_HANDLER_PATH}').default;
|
const testEventHandler = require('${TEST_EVENT_HANDLER_PATH}').default;
|
||||||
const addEventHandler = require('${CIRCUS_STATE_PATH}').addEventHandler;
|
const {addEventHandler, getState} = require('${CIRCUS_STATE_PATH}');
|
||||||
|
getState().randomize = ${opts?.randomize};
|
||||||
|
getState().seed = ${opts?.seed ?? 0};
|
||||||
addEventHandler(testEventHandler);
|
addEventHandler(testEventHandler);
|
||||||
|
|
||||||
${source};
|
${source};
|
||||||
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`failures 1`] = `
|
||||||
|
"start_describe_definition: describe
|
||||||
|
add_hook: beforeEach
|
||||||
|
add_hook: afterEach
|
||||||
|
add_test: one
|
||||||
|
add_test: two
|
||||||
|
finish_describe_definition: describe
|
||||||
|
run_start
|
||||||
|
run_describe_start: ROOT_DESCRIBE_BLOCK
|
||||||
|
run_describe_start: describe
|
||||||
|
test_start: one
|
||||||
|
hook_start: beforeEach
|
||||||
|
hook_success: beforeEach
|
||||||
|
test_fn_start: one
|
||||||
|
test_fn_failure: one
|
||||||
|
hook_start: afterEach
|
||||||
|
hook_failure: afterEach
|
||||||
|
test_done: one
|
||||||
|
test_start: two
|
||||||
|
hook_start: beforeEach
|
||||||
|
hook_success: beforeEach
|
||||||
|
test_fn_start: two
|
||||||
|
test_fn_success: two
|
||||||
|
hook_start: afterEach
|
||||||
|
hook_failure: afterEach
|
||||||
|
test_done: two
|
||||||
|
run_describe_finish: describe
|
||||||
|
run_describe_finish: ROOT_DESCRIBE_BLOCK
|
||||||
|
run_finish
|
||||||
|
|
||||||
|
unhandledErrors: 0"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`function descriptors 1`] = `
|
||||||
|
"start_describe_definition: describer
|
||||||
|
add_test: One
|
||||||
|
finish_describe_definition: describer
|
||||||
|
run_start
|
||||||
|
run_describe_start: ROOT_DESCRIBE_BLOCK
|
||||||
|
run_describe_start: describer
|
||||||
|
test_start: One
|
||||||
|
test_fn_start: One
|
||||||
|
test_fn_success: One
|
||||||
|
test_done: One
|
||||||
|
run_describe_finish: describer
|
||||||
|
run_describe_finish: ROOT_DESCRIBE_BLOCK
|
||||||
|
run_finish
|
||||||
|
|
||||||
|
unhandledErrors: 0"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`simple test 1`] = `
|
||||||
|
"start_describe_definition: describe
|
||||||
|
add_hook: beforeEach
|
||||||
|
add_hook: afterEach
|
||||||
|
add_test: one
|
||||||
|
add_test: two
|
||||||
|
finish_describe_definition: describe
|
||||||
|
run_start
|
||||||
|
run_describe_start: ROOT_DESCRIBE_BLOCK
|
||||||
|
run_describe_start: describe
|
||||||
|
test_start: one
|
||||||
|
hook_start: beforeEach
|
||||||
|
hook_success: beforeEach
|
||||||
|
test_fn_start: one
|
||||||
|
test_fn_success: one
|
||||||
|
hook_start: afterEach
|
||||||
|
hook_success: afterEach
|
||||||
|
test_done: one
|
||||||
|
test_start: two
|
||||||
|
hook_start: beforeEach
|
||||||
|
hook_success: beforeEach
|
||||||
|
test_fn_start: two
|
||||||
|
test_fn_success: two
|
||||||
|
hook_start: afterEach
|
||||||
|
hook_success: afterEach
|
||||||
|
test_done: two
|
||||||
|
run_describe_finish: describe
|
||||||
|
run_describe_finish: ROOT_DESCRIBE_BLOCK
|
||||||
|
run_finish
|
||||||
|
|
||||||
|
unhandledErrors: 0"
|
||||||
|
`;
|
|
@ -0,0 +1,106 @@
|
||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`rngBuilder creates a randomizer given seed 1 1`] = `
|
||||||
|
Array [
|
||||||
|
0,
|
||||||
|
2,
|
||||||
|
4,
|
||||||
|
0,
|
||||||
|
2,
|
||||||
|
8,
|
||||||
|
5,
|
||||||
|
9,
|
||||||
|
9,
|
||||||
|
5,
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`rngBuilder creates a randomizer given seed 2 1`] = `
|
||||||
|
Array [
|
||||||
|
10,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
7,
|
||||||
|
4,
|
||||||
|
4,
|
||||||
|
5,
|
||||||
|
0,
|
||||||
|
10,
|
||||||
|
3,
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`rngBuilder creates a randomizer given seed 4 1`] = `
|
||||||
|
Array [
|
||||||
|
8,
|
||||||
|
10,
|
||||||
|
3,
|
||||||
|
2,
|
||||||
|
5,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
8,
|
||||||
|
5,
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`rngBuilder creates a randomizer given seed 8 1`] = `
|
||||||
|
Array [
|
||||||
|
4,
|
||||||
|
6,
|
||||||
|
0,
|
||||||
|
5,
|
||||||
|
10,
|
||||||
|
0,
|
||||||
|
3,
|
||||||
|
9,
|
||||||
|
5,
|
||||||
|
6,
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`rngBuilder creates a randomizer given seed 16 1`] = `
|
||||||
|
Array [
|
||||||
|
7,
|
||||||
|
9,
|
||||||
|
3,
|
||||||
|
2,
|
||||||
|
8,
|
||||||
|
1,
|
||||||
|
6,
|
||||||
|
1,
|
||||||
|
10,
|
||||||
|
1,
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`shuffleArray shuffles list ["a", "b", "c", "d"] 1`] = `
|
||||||
|
Array [
|
||||||
|
"c",
|
||||||
|
"b",
|
||||||
|
"a",
|
||||||
|
"d",
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`shuffleArray shuffles list ["a", "b", "c"] 1`] = `
|
||||||
|
Array [
|
||||||
|
"b",
|
||||||
|
"a",
|
||||||
|
"c",
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`shuffleArray shuffles list ["a", "b"] 1`] = `
|
||||||
|
Array [
|
||||||
|
"a",
|
||||||
|
"b",
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`shuffleArray shuffles list ["a"] 1`] = `
|
||||||
|
Array [
|
||||||
|
"a",
|
||||||
|
]
|
||||||
|
`;
|
|
@ -0,0 +1,53 @@
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {runTest} from '../__mocks__/testUtils';
|
||||||
|
|
||||||
|
test('simple test', () => {
|
||||||
|
const {stdout} = runTest(
|
||||||
|
`
|
||||||
|
describe('describe', () => {
|
||||||
|
beforeEach(() => {});
|
||||||
|
afterEach(() => {});
|
||||||
|
test('one', () => {});
|
||||||
|
test('two', () => {});
|
||||||
|
})
|
||||||
|
`,
|
||||||
|
{randomize: true, seed: 3},
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(stdout).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('function descriptors', () => {
|
||||||
|
const {stdout} = runTest(
|
||||||
|
`
|
||||||
|
describe(function describer() {}, () => {
|
||||||
|
test(class One {}, () => {});
|
||||||
|
})
|
||||||
|
`,
|
||||||
|
{randomize: true, seed: 3},
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(stdout).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('failures', () => {
|
||||||
|
const {stdout} = runTest(
|
||||||
|
`
|
||||||
|
describe('describe', () => {
|
||||||
|
beforeEach(() => {});
|
||||||
|
afterEach(() => { throw new Error('banana')});
|
||||||
|
test('one', () => { throw new Error('kentucky')});
|
||||||
|
test('two', () => {});
|
||||||
|
})
|
||||||
|
`,
|
||||||
|
{randomize: true, seed: 3},
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(stdout).toMatchSnapshot();
|
||||||
|
});
|
|
@ -0,0 +1,37 @@
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import shuffleArray, {rngBuilder} from '../shuffleArray';
|
||||||
|
|
||||||
|
describe('rngBuilder', () => {
|
||||||
|
// Breaking these orders would be a breaking change
|
||||||
|
// Some people will be using seeds relying on a particular order
|
||||||
|
test.each([1, 2, 4, 8, 16])('creates a randomizer given seed %s', seed => {
|
||||||
|
const rng = rngBuilder(seed);
|
||||||
|
const results = Array(10)
|
||||||
|
.fill(0)
|
||||||
|
.map(() => rng.next(0, 10));
|
||||||
|
expect(results).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('shuffleArray', () => {
|
||||||
|
test('empty array is shuffled', () => {
|
||||||
|
const shuffled = shuffleArray([], rngBuilder(seed));
|
||||||
|
expect(shuffled).toEqual([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Breaking these orders would be a breaking change
|
||||||
|
// Some people will be using seeds relying on a particular order
|
||||||
|
const seed = 321;
|
||||||
|
test.each([[['a']], [['a', 'b']], [['a', 'b', 'c']], [['a', 'b', 'c', 'd']]])(
|
||||||
|
'shuffles list %p',
|
||||||
|
l => {
|
||||||
|
expect(shuffleArray(l, rngBuilder(seed))).toMatchSnapshot();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
|
@ -63,6 +63,9 @@ export const initialize = async ({
|
||||||
}
|
}
|
||||||
getRunnerState().maxConcurrency = globalConfig.maxConcurrency;
|
getRunnerState().maxConcurrency = globalConfig.maxConcurrency;
|
||||||
|
|
||||||
|
getRunnerState().randomize = globalConfig.randomize;
|
||||||
|
getRunnerState().seed = globalConfig.seed;
|
||||||
|
|
||||||
// @ts-expect-error: missing `concurrent` which is added later
|
// @ts-expect-error: missing `concurrent` which is added later
|
||||||
const globalsObject: Global.TestFrameworkGlobals = {
|
const globalsObject: Global.TestFrameworkGlobals = {
|
||||||
...globals,
|
...globals,
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
import pLimit = require('p-limit');
|
import pLimit = require('p-limit');
|
||||||
import type {Circus} from '@jest/types';
|
import type {Circus} from '@jest/types';
|
||||||
|
import shuffleArray, {RandomNumberGenerator, rngBuilder} from './shuffleArray';
|
||||||
import {dispatch, getState} from './state';
|
import {dispatch, getState} from './state';
|
||||||
import {RETRY_TIMES} from './types';
|
import {RETRY_TIMES} from './types';
|
||||||
import {
|
import {
|
||||||
|
@ -19,9 +20,10 @@ import {
|
||||||
} from './utils';
|
} from './utils';
|
||||||
|
|
||||||
const run = async (): Promise<Circus.RunResult> => {
|
const run = async (): Promise<Circus.RunResult> => {
|
||||||
const {rootDescribeBlock} = getState();
|
const {rootDescribeBlock, seed, randomize} = getState();
|
||||||
|
const rng = randomize ? rngBuilder(seed) : undefined;
|
||||||
await dispatch({name: 'run_start'});
|
await dispatch({name: 'run_start'});
|
||||||
await _runTestsForDescribeBlock(rootDescribeBlock, true);
|
await _runTestsForDescribeBlock(rootDescribeBlock, rng, true);
|
||||||
await dispatch({name: 'run_finish'});
|
await dispatch({name: 'run_finish'});
|
||||||
return makeRunResult(
|
return makeRunResult(
|
||||||
getState().rootDescribeBlock,
|
getState().rootDescribeBlock,
|
||||||
|
@ -31,6 +33,7 @@ const run = async (): Promise<Circus.RunResult> => {
|
||||||
|
|
||||||
const _runTestsForDescribeBlock = async (
|
const _runTestsForDescribeBlock = async (
|
||||||
describeBlock: Circus.DescribeBlock,
|
describeBlock: Circus.DescribeBlock,
|
||||||
|
rng: RandomNumberGenerator | undefined,
|
||||||
isRootBlock = false,
|
isRootBlock = false,
|
||||||
) => {
|
) => {
|
||||||
await dispatch({describeBlock, name: 'run_describe_start'});
|
await dispatch({describeBlock, name: 'run_describe_start'});
|
||||||
|
@ -68,10 +71,13 @@ const _runTestsForDescribeBlock = async (
|
||||||
const retryTimes = parseInt(global[RETRY_TIMES], 10) || 0;
|
const retryTimes = parseInt(global[RETRY_TIMES], 10) || 0;
|
||||||
const deferredRetryTests = [];
|
const deferredRetryTests = [];
|
||||||
|
|
||||||
|
if (rng) {
|
||||||
|
describeBlock.children = shuffleArray(describeBlock.children, rng);
|
||||||
|
}
|
||||||
for (const child of describeBlock.children) {
|
for (const child of describeBlock.children) {
|
||||||
switch (child.type) {
|
switch (child.type) {
|
||||||
case 'describeBlock': {
|
case 'describeBlock': {
|
||||||
await _runTestsForDescribeBlock(child);
|
await _runTestsForDescribeBlock(child, rng);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'test': {
|
case 'test': {
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {unsafeUniformIntDistribution, xoroshiro128plus} from 'pure-rand';
|
||||||
|
|
||||||
|
// Generates [from, to] inclusive
|
||||||
|
export type RandomNumberGenerator = {
|
||||||
|
next: (from: number, to: number) => number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const rngBuilder = (seed: number): RandomNumberGenerator => {
|
||||||
|
const gen = xoroshiro128plus(seed);
|
||||||
|
return {next: (from, to) => unsafeUniformIntDistribution(from, to, gen)};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Fisher-Yates shuffle
|
||||||
|
// This is performed in-place
|
||||||
|
export default function shuffleArray<T>(
|
||||||
|
array: Array<T>,
|
||||||
|
random: RandomNumberGenerator,
|
||||||
|
): Array<T> {
|
||||||
|
const length = array.length;
|
||||||
|
if (length === 0) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < length; i++) {
|
||||||
|
const n = random.next(i, length - 1);
|
||||||
|
const value = array[i];
|
||||||
|
array[i] = array[n];
|
||||||
|
array[n] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return array;
|
||||||
|
}
|
|
@ -30,6 +30,7 @@ const createState = (): Circus.State => {
|
||||||
maxConcurrency: 5,
|
maxConcurrency: 5,
|
||||||
parentProcess: null,
|
parentProcess: null,
|
||||||
rootDescribeBlock: ROOT_DESCRIBE_BLOCK,
|
rootDescribeBlock: ROOT_DESCRIBE_BLOCK,
|
||||||
|
seed: 0,
|
||||||
testNamePattern: null,
|
testNamePattern: null,
|
||||||
testTimeout: 5000,
|
testTimeout: 5000,
|
||||||
unhandledErrors: [],
|
unhandledErrors: [],
|
||||||
|
|
|
@ -455,6 +455,11 @@ export const options: {[key: string]: Options} = {
|
||||||
string: true,
|
string: true,
|
||||||
type: 'array',
|
type: 'array',
|
||||||
},
|
},
|
||||||
|
randomize: {
|
||||||
|
description:
|
||||||
|
'Shuffle the order of the tests within a file. In order to choose the seed refer to the `--seed` CLI option.',
|
||||||
|
type: 'boolean',
|
||||||
|
},
|
||||||
reporters: {
|
reporters: {
|
||||||
description: 'A list of custom reporters for the test suite.',
|
description: 'A list of custom reporters for the test suite.',
|
||||||
string: true,
|
string: true,
|
||||||
|
|
|
@ -121,6 +121,7 @@ export const initialOptions: Config.InitialOptions = {
|
||||||
preset: 'react-native',
|
preset: 'react-native',
|
||||||
prettierPath: '<rootDir>/node_modules/prettier',
|
prettierPath: '<rootDir>/node_modules/prettier',
|
||||||
projects: ['project-a', 'project-b/'],
|
projects: ['project-a', 'project-b/'],
|
||||||
|
randomize: false,
|
||||||
reporters: [
|
reporters: [
|
||||||
'default',
|
'default',
|
||||||
'custom-reporter-1',
|
'custom-reporter-1',
|
||||||
|
|
|
@ -2150,14 +2150,14 @@ describe('seed', () => {
|
||||||
seed: 2 ** 33,
|
seed: 2 ** 33,
|
||||||
} as Config.Argv),
|
} as Config.Argv),
|
||||||
).rejects.toThrow(
|
).rejects.toThrow(
|
||||||
'seed value must be between `-0x80000000` and `0x7fffffff` inclusive - is 8589934592',
|
'seed value must be between `-0x80000000` and `0x7fffffff` inclusive - instead it is 8589934592',
|
||||||
);
|
);
|
||||||
await expect(
|
await expect(
|
||||||
normalize({rootDir: '/root/'}, {
|
normalize({rootDir: '/root/'}, {
|
||||||
seed: -(2 ** 33),
|
seed: -(2 ** 33),
|
||||||
} as Config.Argv),
|
} as Config.Argv),
|
||||||
).rejects.toThrow(
|
).rejects.toThrow(
|
||||||
'seed value must be between `-0x80000000` and `0x7fffffff` inclusive - is -8589934592',
|
'seed value must be between `-0x80000000` and `0x7fffffff` inclusive - instead it is -8589934592',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -2182,4 +2182,34 @@ describe('showSeed', () => {
|
||||||
const {options} = await normalize({rootDir: '/root/'}, {} as Config.Argv);
|
const {options} = await normalize({rootDir: '/root/'}, {} as Config.Argv);
|
||||||
expect(options.showSeed).toBeFalsy();
|
expect(options.showSeed).toBeFalsy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('showSeed is true when randomize is set', async () => {
|
||||||
|
const {options} = await normalize(
|
||||||
|
{randomize: true, rootDir: '/root/'},
|
||||||
|
{} as Config.Argv,
|
||||||
|
);
|
||||||
|
expect(options.showSeed).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('randomize', () => {
|
||||||
|
test('randomize is set when argv flag is set', async () => {
|
||||||
|
const {options} = await normalize({rootDir: '/root/'}, {
|
||||||
|
randomize: true,
|
||||||
|
} as Config.Argv);
|
||||||
|
expect(options.randomize).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('randomize is set when the config is set', async () => {
|
||||||
|
const {options} = await normalize(
|
||||||
|
{randomize: true, rootDir: '/root/'},
|
||||||
|
{} as Config.Argv,
|
||||||
|
);
|
||||||
|
expect(options.randomize).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('randomize is false when neither is set', async () => {
|
||||||
|
const {options} = await normalize({rootDir: '/root/'}, {} as Config.Argv);
|
||||||
|
expect(options.randomize).toBeFalsy();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -117,6 +117,7 @@ const groupOptions = (
|
||||||
outputFile: options.outputFile,
|
outputFile: options.outputFile,
|
||||||
passWithNoTests: options.passWithNoTests,
|
passWithNoTests: options.passWithNoTests,
|
||||||
projects: options.projects,
|
projects: options.projects,
|
||||||
|
randomize: options.randomize,
|
||||||
replname: options.replname,
|
replname: options.replname,
|
||||||
reporters: options.reporters,
|
reporters: options.reporters,
|
||||||
rootDir: options.rootDir,
|
rootDir: options.rootDir,
|
||||||
|
|
|
@ -915,6 +915,7 @@ export default async function normalize(
|
||||||
case 'openHandlesTimeout':
|
case 'openHandlesTimeout':
|
||||||
case 'outputFile':
|
case 'outputFile':
|
||||||
case 'passWithNoTests':
|
case 'passWithNoTests':
|
||||||
|
case 'randomize':
|
||||||
case 'replname':
|
case 'replname':
|
||||||
case 'resetMocks':
|
case 'resetMocks':
|
||||||
case 'resetModules':
|
case 'resetModules':
|
||||||
|
@ -1028,11 +1029,14 @@ export default async function normalize(
|
||||||
newOptions.onlyChanged = newOptions.watch;
|
newOptions.onlyChanged = newOptions.watch;
|
||||||
}
|
}
|
||||||
|
|
||||||
newOptions.showSeed = newOptions.showSeed || argv.showSeed;
|
newOptions.randomize = newOptions.randomize || argv.randomize;
|
||||||
|
|
||||||
|
newOptions.showSeed =
|
||||||
|
newOptions.randomize || newOptions.showSeed || argv.showSeed;
|
||||||
|
|
||||||
const upperBoundSeedValue = 2 ** 31;
|
const upperBoundSeedValue = 2 ** 31;
|
||||||
|
|
||||||
// xoroshiro128plus is used in v8 and is used here (at time of writing)
|
// bounds are determined by xoroshiro128plus which is used in v8 and is used here (at time of writing)
|
||||||
newOptions.seed =
|
newOptions.seed =
|
||||||
argv.seed ??
|
argv.seed ??
|
||||||
Math.floor((2 ** 32 - 1) * Math.random() - upperBoundSeedValue);
|
Math.floor((2 ** 32 - 1) * Math.random() - upperBoundSeedValue);
|
||||||
|
@ -1042,7 +1046,7 @@ export default async function normalize(
|
||||||
) {
|
) {
|
||||||
throw new ValidationError(
|
throw new ValidationError(
|
||||||
'Validation Error',
|
'Validation Error',
|
||||||
`seed value must be between \`-0x80000000\` and \`0x7fffffff\` inclusive - is ${newOptions.seed}`,
|
`seed value must be between \`-0x80000000\` and \`0x7fffffff\` inclusive - instead it is ${newOptions.seed}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -215,7 +215,9 @@ export type State = {
|
||||||
// the original ones.
|
// the original ones.
|
||||||
originalGlobalErrorHandlers?: GlobalErrorHandlers;
|
originalGlobalErrorHandlers?: GlobalErrorHandlers;
|
||||||
parentProcess: Process | null; // process object from the outer scope
|
parentProcess: Process | null; // process object from the outer scope
|
||||||
|
randomize?: boolean;
|
||||||
rootDescribeBlock: DescribeBlock;
|
rootDescribeBlock: DescribeBlock;
|
||||||
|
seed: number;
|
||||||
testNamePattern?: RegExp | null;
|
testNamePattern?: RegExp | null;
|
||||||
testTimeout: number;
|
testTimeout: number;
|
||||||
unhandledErrors: Array<Exception>;
|
unhandledErrors: Array<Exception>;
|
||||||
|
|
|
@ -281,6 +281,7 @@ export type InitialOptions = Partial<{
|
||||||
preset: string | null | undefined;
|
preset: string | null | undefined;
|
||||||
prettierPath: string | null | undefined;
|
prettierPath: string | null | undefined;
|
||||||
projects: Array<string | InitialProjectOptions>;
|
projects: Array<string | InitialProjectOptions>;
|
||||||
|
randomize: boolean;
|
||||||
replname: string | null | undefined;
|
replname: string | null | undefined;
|
||||||
resetMocks: boolean;
|
resetMocks: boolean;
|
||||||
resetModules: boolean;
|
resetModules: boolean;
|
||||||
|
@ -396,6 +397,7 @@ export type GlobalConfig = {
|
||||||
openHandlesTimeout: number;
|
openHandlesTimeout: number;
|
||||||
passWithNoTests: boolean;
|
passWithNoTests: boolean;
|
||||||
projects: Array<string>;
|
projects: Array<string>;
|
||||||
|
randomize?: boolean;
|
||||||
replname?: string;
|
replname?: string;
|
||||||
reporters?: Array<ReporterConfig>;
|
reporters?: Array<ReporterConfig>;
|
||||||
runTestsByPath: boolean;
|
runTestsByPath: boolean;
|
||||||
|
@ -541,6 +543,7 @@ export type Argv = Arguments<
|
||||||
preset: string | null | undefined;
|
preset: string | null | undefined;
|
||||||
prettierPath: string | null | undefined;
|
prettierPath: string | null | undefined;
|
||||||
projects: Array<string>;
|
projects: Array<string>;
|
||||||
|
randomize: boolean;
|
||||||
reporters: Array<string>;
|
reporters: Array<string>;
|
||||||
resetMocks: boolean;
|
resetMocks: boolean;
|
||||||
resetModules: boolean;
|
resetModules: boolean;
|
||||||
|
|
|
@ -12604,6 +12604,7 @@ __metadata:
|
||||||
jest-util: "workspace:^"
|
jest-util: "workspace:^"
|
||||||
p-limit: ^3.1.0
|
p-limit: ^3.1.0
|
||||||
pretty-format: "workspace:^"
|
pretty-format: "workspace:^"
|
||||||
|
pure-rand: ^6.0.0
|
||||||
slash: ^3.0.0
|
slash: ^3.0.0
|
||||||
stack-utils: ^2.0.3
|
stack-utils: ^2.0.3
|
||||||
languageName: unknown
|
languageName: unknown
|
||||||
|
|
Loading…
Reference in New Issue