mirror of https://github.com/facebook/jest.git
Only match relative paths when specifying paths (#12519)
Co-authored-by: Brandon Chinn <brandonchinn178@gmail.com>
This commit is contained in:
parent
46285d8bd2
commit
41133b526d
|
@ -25,6 +25,9 @@
|
|||
- `[jest-runtime]` Properly handle re-exported native modules in ESM via CJS ([#14589](https://github.com/jestjs/jest/pull/14589))
|
||||
- `[jest-util]` Make sure `isInteractive` works in a browser ([#14552](https://github.com/jestjs/jest/pull/14552))
|
||||
- `[pretty-format]` [**BREAKING**] Print `ArrayBuffer` and `DataView` correctly ([#14290](https://github.com/facebook/jest/pull/14290))
|
||||
- `[jest-cli]` When specifying paths on the command line, only match against the relative paths of the test files ([#12519](https://github.com/facebook/jest/pull/12519))
|
||||
- [**BREAKING**] Changes `testPathPattern` configuration option to `testPathPatterns`, which now takes a list of patterns instead of the regex.
|
||||
- [**BREAKING**] `--testPathPattern` is now `--testPathPatterns`
|
||||
|
||||
### Performance
|
||||
|
||||
|
|
|
@ -481,11 +481,11 @@ The regex is matched against the full name, which is a combination of the test n
|
|||
|
||||
### `--testPathIgnorePatterns=<regex>|[array]`
|
||||
|
||||
A single or array of regexp pattern strings that are tested against all tests paths before executing the test. Contrary to `--testPathPattern`, it will only run those tests with a path that does not match with the provided regexp expressions.
|
||||
A single or array of regexp pattern strings that are tested against all tests paths before executing the test. Contrary to `--testPathPatterns`, it will only run those tests with a path that does not match with the provided regexp expressions.
|
||||
|
||||
To pass as an array use escaped parentheses and space delimited regexps such as `\(/node_modules/ /tests/e2e/\)`. Alternatively, you can omit parentheses by combining regexps into a single regexp like `/node_modules/|/tests/e2e/`. These two examples are equivalent.
|
||||
|
||||
### `--testPathPattern=<regex>`
|
||||
### `--testPathPatterns=<regex>`
|
||||
|
||||
A regexp pattern string that is matched against all tests paths before executing the test. On Windows, you will need to use `/` as a path separator or escape `\` as `\\`.
|
||||
|
||||
|
|
|
@ -787,7 +787,7 @@ While code transformation is applied to the linked setup-file, Jest will **not**
|
|||
|
||||
```js title="setup.js"
|
||||
module.exports = async function (globalConfig, projectConfig) {
|
||||
console.log(globalConfig.testPathPattern);
|
||||
console.log(globalConfig.testPathPatterns);
|
||||
console.log(projectConfig.cache);
|
||||
|
||||
// Set reference to mongod in order to close the server during teardown.
|
||||
|
@ -797,7 +797,7 @@ module.exports = async function (globalConfig, projectConfig) {
|
|||
|
||||
```js title="teardown.js"
|
||||
module.exports = async function (globalConfig, projectConfig) {
|
||||
console.log(globalConfig.testPathPattern);
|
||||
console.log(globalConfig.testPathPatterns);
|
||||
console.log(projectConfig.cache);
|
||||
|
||||
await globalThis.__MONGOD__.stop();
|
||||
|
|
|
@ -172,7 +172,7 @@ For stability and safety reasons, only part of the global configuration keys can
|
|||
- [`onlyFailures`](configuration#onlyfailures-boolean)
|
||||
- [`reporters`](configuration#reporters-arraymodulename--modulename-options)
|
||||
- [`testNamePattern`](cli#--testnamepatternregex)
|
||||
- [`testPathPattern`](cli#--testpathpatternregex)
|
||||
- [`testPathPatterns`](cli#--testpathpatternsregex)
|
||||
- [`updateSnapshot`](cli#--updatesnapshot)
|
||||
- [`verbose`](configuration#verbose-boolean)
|
||||
|
||||
|
|
|
@ -13,5 +13,5 @@ exports[`CLI accepts exact file names if matchers matched 2`] = `
|
|||
Tests: 1 passed, 1 total
|
||||
Snapshots: 0 total
|
||||
Time: <<REPLACED>>
|
||||
Ran all test suites matching /.\\/foo\\/bar.spec.js/i."
|
||||
Ran all test suites matching ./foo/bar.spec.js."
|
||||
`;
|
||||
|
|
|
@ -82,7 +82,7 @@ exports[`Custom Reporters Integration default reporters enabled 2`] = `
|
|||
Tests: 1 passed, 1 total
|
||||
Snapshots: 0 total
|
||||
Time: <<REPLACED>>
|
||||
Ran all test suites matching /add.test.js/i."
|
||||
Ran all test suites matching add.test.js."
|
||||
`;
|
||||
|
||||
exports[`Custom Reporters Integration default reporters enabled 3`] = `
|
||||
|
|
|
@ -7,7 +7,7 @@ Object {
|
|||
Tests: 1 skipped, 1 total
|
||||
Snapshots: 0 total
|
||||
Time: <<REPLACED>>
|
||||
Ran all test suites matching /hookInDescribeWithSkippedTest.test.js/i.",
|
||||
Ran all test suites matching hookInDescribeWithSkippedTest.test.js.",
|
||||
}
|
||||
`;
|
||||
|
||||
|
@ -34,7 +34,7 @@ Object {
|
|||
Tests: 1 passed, 1 total
|
||||
Snapshots: 0 total
|
||||
Time: <<REPLACED>>
|
||||
Ran all test suites matching /hookInEmptyDescribe.test.js/i.",
|
||||
Ran all test suites matching hookInEmptyDescribe.test.js.",
|
||||
}
|
||||
`;
|
||||
|
||||
|
@ -61,7 +61,7 @@ Object {
|
|||
Tests: 1 passed, 1 total
|
||||
Snapshots: 0 total
|
||||
Time: <<REPLACED>>
|
||||
Ran all test suites matching /hookInEmptyNestedDescribe.test.js/i.",
|
||||
Ran all test suites matching hookInEmptyNestedDescribe.test.js.",
|
||||
}
|
||||
`;
|
||||
|
||||
|
@ -133,6 +133,6 @@ Object {
|
|||
Tests: 1 passed, 1 total
|
||||
Snapshots: 0 total
|
||||
Time: <<REPLACED>>
|
||||
Ran all test suites matching /multipleHooksInEmptyDescribe.test.js/i.",
|
||||
Ran all test suites matching multipleHooksInEmptyDescribe.test.js.",
|
||||
}
|
||||
`;
|
||||
|
|
|
@ -5,7 +5,7 @@ exports[`--findRelatedTests flag coverage configuration is applied correctly 1`]
|
|||
Tests: 1 passed, 1 total
|
||||
Snapshots: 0 total
|
||||
Time: <<REPLACED>>
|
||||
Ran all test suites related to files matching /a.js|b.js/i."
|
||||
Ran all test suites related to files matching a.js|b.js."
|
||||
`;
|
||||
|
||||
exports[`--findRelatedTests flag coverage configuration is applied correctly 2`] = `
|
||||
|
@ -50,7 +50,7 @@ exports[`--findRelatedTests flag generates coverage report for filename 4`] = `
|
|||
Tests: 1 passed, 1 total
|
||||
Snapshots: 0 total
|
||||
Time: <<REPLACED>>
|
||||
Ran all test suites related to files matching /a.js/i."
|
||||
Ran all test suites related to files matching a.js."
|
||||
`;
|
||||
|
||||
exports[`--findRelatedTests flag generates coverage report for filename 5`] = `
|
||||
|
|
|
@ -5,7 +5,7 @@ exports[`does not enforce import assertions 1`] = `
|
|||
Tests: 2 passed, 2 total
|
||||
Snapshots: 0 total
|
||||
Time: <<REPLACED>>
|
||||
Ran all test suites matching /native-esm-missing-import-assertions.test.js/i."
|
||||
Ran all test suites matching native-esm-missing-import-assertions.test.js."
|
||||
`;
|
||||
|
||||
exports[`on node >=16.11.0 support re-exports from CJS of dual packages 1`] = `
|
||||
|
@ -13,7 +13,7 @@ exports[`on node >=16.11.0 support re-exports from CJS of dual packages 1`] = `
|
|||
Tests: 1 passed, 1 total
|
||||
Snapshots: 0 total
|
||||
Time: <<REPLACED>>
|
||||
Ran all test suites matching /native-esm-deep-cjs-reexport.test.js/i."
|
||||
Ran all test suites matching native-esm-deep-cjs-reexport.test.js."
|
||||
`;
|
||||
|
||||
exports[`on node >=16.12.0 supports import assertions 1`] = `
|
||||
|
@ -21,7 +21,7 @@ exports[`on node >=16.12.0 supports import assertions 1`] = `
|
|||
Tests: 2 passed, 2 total
|
||||
Snapshots: 0 total
|
||||
Time: <<REPLACED>>
|
||||
Ran all test suites matching /native-esm-import-assertions.test.js/i."
|
||||
Ran all test suites matching native-esm-import-assertions.test.js."
|
||||
`;
|
||||
|
||||
exports[`properly handle re-exported native modules in ESM via CJS 1`] = `
|
||||
|
@ -29,7 +29,7 @@ exports[`properly handle re-exported native modules in ESM via CJS 1`] = `
|
|||
Tests: 1 passed, 1 total
|
||||
Snapshots: 0 total
|
||||
Time: <<REPLACED>>
|
||||
Ran all test suites matching /native-esm-native-module.test.js/i."
|
||||
Ran all test suites matching native-esm-native-module.test.js."
|
||||
`;
|
||||
|
||||
exports[`runs WebAssembly (Wasm) test with native ESM 1`] = `
|
||||
|
@ -37,7 +37,7 @@ exports[`runs WebAssembly (Wasm) test with native ESM 1`] = `
|
|||
Tests: 6 passed, 6 total
|
||||
Snapshots: 0 total
|
||||
Time: <<REPLACED>>
|
||||
Ran all test suites matching /native-esm-wasm.test.js/i."
|
||||
Ran all test suites matching native-esm-wasm.test.js."
|
||||
`;
|
||||
|
||||
exports[`runs test with native ESM 1`] = `
|
||||
|
@ -45,7 +45,7 @@ exports[`runs test with native ESM 1`] = `
|
|||
Tests: 33 passed, 33 total
|
||||
Snapshots: 0 total
|
||||
Time: <<REPLACED>>
|
||||
Ran all test suites matching /native-esm.test.js/i."
|
||||
Ran all test suites matching native-esm.test.js."
|
||||
`;
|
||||
|
||||
exports[`support re-exports from CJS of core module 1`] = `
|
||||
|
@ -53,7 +53,7 @@ exports[`support re-exports from CJS of core module 1`] = `
|
|||
Tests: 1 passed, 1 total
|
||||
Snapshots: 0 total
|
||||
Time: <<REPLACED>>
|
||||
Ran all test suites matching /native-esm-core-cjs-reexport.test.js/i."
|
||||
Ran all test suites matching native-esm-core-cjs-reexport.test.js."
|
||||
`;
|
||||
|
||||
exports[`supports top-level await 1`] = `
|
||||
|
@ -61,5 +61,5 @@ exports[`supports top-level await 1`] = `
|
|||
Tests: 1 passed, 1 total
|
||||
Snapshots: 0 total
|
||||
Time: <<REPLACED>>
|
||||
Ran all test suites matching /native-esm.tla.test.js/i."
|
||||
Ran all test suites matching native-esm.tla.test.js."
|
||||
`;
|
||||
|
|
|
@ -22,7 +22,7 @@ Object {
|
|||
Tests: 1 passed, 1 total
|
||||
Snapshots: 0 total
|
||||
Time: <<REPLACED>>
|
||||
Ran all test suites matching /unhandledRejectionAfterAll.test.js/i.",
|
||||
Ran all test suites matching unhandledRejectionAfterAll.test.js.",
|
||||
}
|
||||
`;
|
||||
|
||||
|
@ -63,7 +63,7 @@ Object {
|
|||
Tests: 2 failed, 2 total
|
||||
Snapshots: 0 total
|
||||
Time: <<REPLACED>>
|
||||
Ran all test suites matching /unhandledRejectionAfterEach.test.js/i.",
|
||||
Ran all test suites matching unhandledRejectionAfterEach.test.js.",
|
||||
}
|
||||
`;
|
||||
|
||||
|
@ -89,7 +89,7 @@ Object {
|
|||
Tests: 1 failed, 1 total
|
||||
Snapshots: 0 total
|
||||
Time: <<REPLACED>>
|
||||
Ran all test suites matching /unhandledRejectionBeforeAll.test.js/i.",
|
||||
Ran all test suites matching unhandledRejectionBeforeAll.test.js.",
|
||||
}
|
||||
`;
|
||||
|
||||
|
@ -130,7 +130,7 @@ Object {
|
|||
Tests: 2 failed, 2 total
|
||||
Snapshots: 0 total
|
||||
Time: <<REPLACED>>
|
||||
Ran all test suites matching /unhandledRejectionBeforeEach.test.js/i.",
|
||||
Ran all test suites matching unhandledRejectionBeforeEach.test.js.",
|
||||
}
|
||||
`;
|
||||
|
||||
|
@ -217,7 +217,7 @@ Object {
|
|||
Tests: 4 failed, 4 total
|
||||
Snapshots: 0 total
|
||||
Time: <<REPLACED>>
|
||||
Ran all test suites matching /unhandledRejectionTest.test.js/i.",
|
||||
Ran all test suites matching unhandledRejectionTest.test.js.",
|
||||
}
|
||||
`;
|
||||
|
||||
|
@ -231,6 +231,6 @@ Object {
|
|||
Tests: 3 passed, 3 total
|
||||
Snapshots: 0 total
|
||||
Time: <<REPLACED>>
|
||||
Ran all test suites matching /rejectionHandled.test.js/i.",
|
||||
Ran all test suites matching rejectionHandled.test.js.",
|
||||
}
|
||||
`;
|
||||
|
|
|
@ -139,7 +139,7 @@ exports[`--showConfig outputs config info and exits 1`] = `
|
|||
"printBasicPrototype": false
|
||||
},
|
||||
"testFailureExitCode": 1,
|
||||
"testPathPattern": "",
|
||||
"testPathPatterns": [],
|
||||
"testSequencer": "<<REPLACED_JEST_PACKAGES_DIR>>/jest-test-sequencer/build/index.js",
|
||||
"updateSnapshot": "none",
|
||||
"useStderr": false,
|
||||
|
|
|
@ -85,7 +85,7 @@ exports[`Snapshot works with escaped characters 1`] = `
|
|||
Tests: 1 passed, 1 total
|
||||
Snapshots: 1 written, 1 total
|
||||
Time: <<REPLACED>>
|
||||
Ran all test suites matching /snapshot.test.js/i."
|
||||
Ran all test suites matching snapshot.test.js."
|
||||
`;
|
||||
|
||||
exports[`Snapshot works with escaped characters 2`] = `
|
||||
|
@ -93,7 +93,7 @@ exports[`Snapshot works with escaped characters 2`] = `
|
|||
Tests: 2 passed, 2 total
|
||||
Snapshots: 1 written, 1 passed, 2 total
|
||||
Time: <<REPLACED>>
|
||||
Ran all test suites matching /snapshot.test.js/i."
|
||||
Ran all test suites matching snapshot.test.js."
|
||||
`;
|
||||
|
||||
exports[`Snapshot works with escaped characters 3`] = `
|
||||
|
@ -101,7 +101,7 @@ exports[`Snapshot works with escaped characters 3`] = `
|
|||
Tests: 2 passed, 2 total
|
||||
Snapshots: 2 passed, 2 total
|
||||
Time: <<REPLACED>>
|
||||
Ran all test suites matching /snapshot.test.js/i."
|
||||
Ran all test suites matching snapshot.test.js."
|
||||
`;
|
||||
|
||||
exports[`Snapshot works with escaped regex 1`] = `
|
||||
|
@ -109,7 +109,7 @@ exports[`Snapshot works with escaped regex 1`] = `
|
|||
Tests: 2 passed, 2 total
|
||||
Snapshots: 2 written, 2 total
|
||||
Time: <<REPLACED>>
|
||||
Ran all test suites matching /snapshotEscapeRegex.js/i."
|
||||
Ran all test suites matching snapshotEscapeRegex.js."
|
||||
`;
|
||||
|
||||
exports[`Snapshot works with escaped regex 2`] = `
|
||||
|
@ -117,7 +117,7 @@ exports[`Snapshot works with escaped regex 2`] = `
|
|||
Tests: 2 passed, 2 total
|
||||
Snapshots: 2 passed, 2 total
|
||||
Time: <<REPLACED>>
|
||||
Ran all test suites matching /snapshotEscapeRegex.js/i."
|
||||
Ran all test suites matching snapshotEscapeRegex.js."
|
||||
`;
|
||||
|
||||
exports[`Snapshot works with template literal substitutions 1`] = `
|
||||
|
@ -125,7 +125,7 @@ exports[`Snapshot works with template literal substitutions 1`] = `
|
|||
Tests: 1 passed, 1 total
|
||||
Snapshots: 1 written, 1 total
|
||||
Time: <<REPLACED>>
|
||||
Ran all test suites matching /snapshotEscapeSubstitution.test.js/i."
|
||||
Ran all test suites matching snapshotEscapeSubstitution.test.js."
|
||||
`;
|
||||
|
||||
exports[`Snapshot works with template literal substitutions 2`] = `
|
||||
|
@ -133,5 +133,5 @@ exports[`Snapshot works with template literal substitutions 2`] = `
|
|||
Tests: 1 passed, 1 total
|
||||
Snapshots: 1 passed, 1 total
|
||||
Time: <<REPLACED>>
|
||||
Ran all test suites matching /snapshotEscapeSubstitution.test.js/i."
|
||||
Ran all test suites matching snapshotEscapeSubstitution.test.js."
|
||||
`;
|
||||
|
|
|
@ -5,7 +5,7 @@ exports[`Stack Trace does not print a stack trace for errors when --noStackTrace
|
|||
Tests: 3 failed, 3 total
|
||||
Snapshots: 0 total
|
||||
Time: <<REPLACED>>
|
||||
Ran all test suites matching /testError.test.js/i."
|
||||
Ran all test suites matching testError.test.js."
|
||||
`;
|
||||
|
||||
exports[`Stack Trace does not print a stack trace for matching errors when --noStackTrace is given 1`] = `
|
||||
|
@ -13,7 +13,7 @@ exports[`Stack Trace does not print a stack trace for matching errors when --noS
|
|||
Tests: 1 failed, 1 total
|
||||
Snapshots: 0 total
|
||||
Time: <<REPLACED>>
|
||||
Ran all test suites matching /stackTrace.test.js/i."
|
||||
Ran all test suites matching stackTrace.test.js."
|
||||
`;
|
||||
|
||||
exports[`Stack Trace does not print a stack trace for runtime errors when --noStackTrace is given 1`] = `
|
||||
|
@ -21,7 +21,7 @@ exports[`Stack Trace does not print a stack trace for runtime errors when --noSt
|
|||
Tests: 0 total
|
||||
Snapshots: 0 total
|
||||
Time: <<REPLACED>>
|
||||
Ran all test suites matching /runtimeError.test.js/i."
|
||||
Ran all test suites matching runtimeError.test.js."
|
||||
`;
|
||||
|
||||
exports[`Stack Trace prints a stack trace for errors 1`] = `
|
||||
|
@ -29,7 +29,7 @@ exports[`Stack Trace prints a stack trace for errors 1`] = `
|
|||
Tests: 3 failed, 3 total
|
||||
Snapshots: 0 total
|
||||
Time: <<REPLACED>>
|
||||
Ran all test suites matching /testError.test.js/i."
|
||||
Ran all test suites matching testError.test.js."
|
||||
`;
|
||||
|
||||
exports[`Stack Trace prints a stack trace for errors without message in stack trace 1`] = `
|
||||
|
@ -37,7 +37,7 @@ exports[`Stack Trace prints a stack trace for errors without message in stack tr
|
|||
Tests: 1 failed, 1 total
|
||||
Snapshots: 0 total
|
||||
Time: <<REPLACED>>
|
||||
Ran all test suites matching /stackTraceWithoutMessage.test.js/i."
|
||||
Ran all test suites matching stackTraceWithoutMessage.test.js."
|
||||
`;
|
||||
|
||||
exports[`Stack Trace prints a stack trace for matching errors 1`] = `
|
||||
|
@ -45,7 +45,7 @@ exports[`Stack Trace prints a stack trace for matching errors 1`] = `
|
|||
Tests: 1 failed, 1 total
|
||||
Snapshots: 0 total
|
||||
Time: <<REPLACED>>
|
||||
Ran all test suites matching /stackTrace.test.js/i."
|
||||
Ran all test suites matching stackTrace.test.js."
|
||||
`;
|
||||
|
||||
exports[`Stack Trace prints a stack trace for runtime errors 1`] = `
|
||||
|
@ -53,5 +53,5 @@ exports[`Stack Trace prints a stack trace for runtime errors 1`] = `
|
|||
Tests: 0 total
|
||||
Snapshots: 0 total
|
||||
Time: <<REPLACED>>
|
||||
Ran all test suites matching /runtimeError.test.js/i."
|
||||
Ran all test suites matching runtimeError.test.js."
|
||||
`;
|
||||
|
|
|
@ -11,7 +11,7 @@ Test Suites: 1 passed, 1 total
|
|||
Tests: 2 todo, 1 passed, 3 total
|
||||
Snapshots: 0 total
|
||||
Time: <<REPLACED>>
|
||||
Ran all test suites matching /only-todo.test.js/i."
|
||||
Ran all test suites matching only-todo.test.js."
|
||||
`;
|
||||
|
||||
exports[`shows error messages when called with invalid argument 1`] = `
|
||||
|
|
|
@ -66,7 +66,7 @@ exports[`can press "p" to filter by file name: test summary 2`] = `
|
|||
Tests: 2 passed, 2 total
|
||||
Snapshots: 0 total
|
||||
Time: <<REPLACED>>
|
||||
Ran all test suites matching /bar/i."
|
||||
Ran all test suites matching bar."
|
||||
`;
|
||||
|
||||
exports[`can press "t" to filter by test name 1`] = `
|
||||
|
|
|
@ -33,7 +33,7 @@ describe('--findRelatedTests flag', () => {
|
|||
const {stderr} = runJest(DIR, ['--findRelatedTests', 'a.js']);
|
||||
expect(stderr).toMatch('PASS __tests__/test.test.js');
|
||||
|
||||
const summaryMsg = 'Ran all test suites related to files matching /a.js/i.';
|
||||
const summaryMsg = 'Ran all test suites related to files matching a.js.';
|
||||
expect(stderr).toMatch(summaryMsg);
|
||||
});
|
||||
|
||||
|
@ -59,7 +59,7 @@ describe('--findRelatedTests flag', () => {
|
|||
const {stderr} = runJest(DIR, ['--findRelatedTests', 'A.JS']);
|
||||
expect(stderr).toMatch('PASS __tests__/test.test.js');
|
||||
|
||||
const summaryMsg = 'Ran all test suites related to files matching /A.JS/i.';
|
||||
const summaryMsg = 'Ran all test suites related to files matching A.JS.';
|
||||
expect(stderr).toMatch(summaryMsg);
|
||||
});
|
||||
|
||||
|
@ -112,7 +112,7 @@ describe('--findRelatedTests flag', () => {
|
|||
expect(stderr).toMatch('PASS __tests__/test.test.js');
|
||||
expect(stderr).not.toMatch('PASS __tests__/test-skip-deps.test.js');
|
||||
|
||||
const summaryMsg = 'Ran all test suites related to files matching /a.js/i.';
|
||||
const summaryMsg = 'Ran all test suites related to files matching a.js.';
|
||||
expect(stderr).toMatch(summaryMsg);
|
||||
});
|
||||
|
||||
|
@ -162,7 +162,7 @@ describe('--findRelatedTests flag', () => {
|
|||
expect(stderr).toMatch('PASS __tests__/test.test.js');
|
||||
expect(stderr).not.toMatch('PASS __tests__/test-skip-deps.test.js');
|
||||
|
||||
const summaryMsg = 'Ran all test suites related to files matching /a.js/i.';
|
||||
const summaryMsg = 'Ran all test suites related to files matching a.js.';
|
||||
expect(stderr).toMatch(summaryMsg);
|
||||
});
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@ test('globalSetup is triggered once before all test suites', () => {
|
|||
const setupPath = path.join(e2eDir, 'setup.js');
|
||||
const result = runWithJson(e2eDir, [
|
||||
`--globalSetup=${setupPath}`,
|
||||
'--testPathPattern=__tests__',
|
||||
'--testPathPatterns=__tests__',
|
||||
]);
|
||||
|
||||
expect(result.exitCode).toBe(0);
|
||||
|
@ -70,7 +70,7 @@ test('jest throws an error when globalSetup does not export a function', () => {
|
|||
const setupPath = path.resolve(__dirname, '../global-setup/invalidSetup.js');
|
||||
const {exitCode, stderr} = runJest(e2eDir, [
|
||||
`--globalSetup=${setupPath}`,
|
||||
'--testPathPattern=__tests__',
|
||||
'--testPathPatterns=__tests__',
|
||||
]);
|
||||
|
||||
expect(exitCode).toBe(1);
|
||||
|
@ -83,15 +83,13 @@ test('jest throws an error when globalSetup does not export a function', () => {
|
|||
test('globalSetup function gets global config object and project config as parameters', () => {
|
||||
const setupPath = path.resolve(e2eDir, 'setupWithConfig.js');
|
||||
|
||||
const testPathPattern = 'pass';
|
||||
|
||||
const result = runJest(e2eDir, [
|
||||
`--globalSetup=${setupPath}`,
|
||||
`--testPathPattern=${testPathPattern}`,
|
||||
'--testPathPatterns=pass',
|
||||
'--cache=true',
|
||||
]);
|
||||
|
||||
expect(result.stdout).toBe(`${testPathPattern}\ntrue`);
|
||||
expect(result.stdout).toBe("[ 'pass' ]\ntrue");
|
||||
});
|
||||
|
||||
test('should call globalSetup function of multiple projects', () => {
|
||||
|
@ -111,7 +109,7 @@ test('should not call a globalSetup of a project if there are no tests to run fr
|
|||
|
||||
const result = runWithJson(e2eDir, [
|
||||
`--config=${configPath}`,
|
||||
'--testPathPattern=project-1',
|
||||
'--testPathPatterns=project-1',
|
||||
]);
|
||||
|
||||
expect(result.exitCode).toBe(0);
|
||||
|
@ -140,15 +138,13 @@ test('should not call any globalSetup if there are no tests to run', () => {
|
|||
test('globalSetup works with default export', () => {
|
||||
const setupPath = path.resolve(e2eDir, 'setupWithDefaultExport.js');
|
||||
|
||||
const testPathPattern = 'pass';
|
||||
|
||||
const result = runJest(e2eDir, [
|
||||
`--globalSetup=${setupPath}`,
|
||||
`--testPathPattern=${testPathPattern}`,
|
||||
'--testPathPatterns=pass',
|
||||
'--cache=true',
|
||||
]);
|
||||
|
||||
expect(result.stdout).toBe(`${testPathPattern}\ntrue`);
|
||||
expect(result.stdout).toBe("[ 'pass' ]\ntrue");
|
||||
});
|
||||
|
||||
test('globalSetup throws with named export', () => {
|
||||
|
@ -156,7 +152,7 @@ test('globalSetup throws with named export', () => {
|
|||
|
||||
const {exitCode, stderr} = runJest(e2eDir, [
|
||||
`--globalSetup=${setupPath}`,
|
||||
'--testPathPattern=__tests__',
|
||||
'--testPathPatterns=__tests__',
|
||||
]);
|
||||
|
||||
expect(exitCode).toBe(1);
|
||||
|
|
|
@ -40,7 +40,7 @@ test('globalTeardown is triggered once after all test suites', () => {
|
|||
const teardownPath = path.resolve(e2eDir, 'teardown.js');
|
||||
const result = runWithJson('global-teardown', [
|
||||
`--globalTeardown=${teardownPath}`,
|
||||
'--testPathPattern=__tests__',
|
||||
'--testPathPatterns=__tests__',
|
||||
]);
|
||||
|
||||
expect(result.exitCode).toBe(0);
|
||||
|
@ -54,7 +54,7 @@ test('jest throws an error when globalTeardown does not export a function', () =
|
|||
const teardownPath = path.resolve(e2eDir, 'invalidTeardown.js');
|
||||
const {exitCode, stderr} = runJest(e2eDir, [
|
||||
`--globalTeardown=${teardownPath}`,
|
||||
'--testPathPattern=__tests__',
|
||||
'--testPathPatterns=__tests__',
|
||||
]);
|
||||
|
||||
expect(exitCode).toBe(1);
|
||||
|
@ -67,15 +67,13 @@ test('jest throws an error when globalTeardown does not export a function', () =
|
|||
test('globalSetup function gets global config object and project config as parameters', () => {
|
||||
const teardownPath = path.resolve(e2eDir, 'teardownWithConfig.js');
|
||||
|
||||
const testPathPattern = 'pass';
|
||||
|
||||
const result = runJest(e2eDir, [
|
||||
`--globalTeardown=${teardownPath}`,
|
||||
`--testPathPattern=${testPathPattern}`,
|
||||
'--testPathPatterns=pass',
|
||||
'--cache=true',
|
||||
]);
|
||||
|
||||
expect(result.stdout).toBe(`${testPathPattern}\ntrue`);
|
||||
expect(result.stdout).toBe("[ 'pass' ]\ntrue");
|
||||
});
|
||||
|
||||
test('should call globalTeardown function of multiple projects', () => {
|
||||
|
@ -95,7 +93,7 @@ test('should not call a globalTeardown of a project if there are no tests to run
|
|||
|
||||
const result = runWithJson('global-teardown', [
|
||||
`--config=${configPath}`,
|
||||
'--testPathPattern=project-1',
|
||||
'--testPathPatterns=project-1',
|
||||
]);
|
||||
|
||||
expect(result.exitCode).toBe(0);
|
||||
|
@ -108,15 +106,13 @@ test('should not call a globalTeardown of a project if there are no tests to run
|
|||
test('globalTeardown works with default export', () => {
|
||||
const teardownPath = path.resolve(e2eDir, 'teardownWithDefaultExport.js');
|
||||
|
||||
const testPathPattern = 'pass';
|
||||
|
||||
const result = runJest(e2eDir, [
|
||||
`--globalTeardown=${teardownPath}`,
|
||||
`--testPathPattern=${testPathPattern}`,
|
||||
'--testPathPatterns=pass',
|
||||
'--cache=true',
|
||||
]);
|
||||
|
||||
expect(result.stdout).toBe(`${testPathPattern}\ntrue`);
|
||||
expect(result.stdout).toBe("[ 'pass' ]\ntrue");
|
||||
});
|
||||
|
||||
test('globalTeardown throws with named export', () => {
|
||||
|
@ -127,7 +123,7 @@ test('globalTeardown throws with named export', () => {
|
|||
|
||||
const {exitCode, stderr} = runJest(e2eDir, [
|
||||
`--globalTeardown=${teardownPath}`,
|
||||
'--testPathPattern=__tests__',
|
||||
'--testPathPatterns=__tests__',
|
||||
]);
|
||||
|
||||
expect(exitCode).toBe(1);
|
||||
|
|
|
@ -13,7 +13,7 @@ const DIR = path.resolve(__dirname, '../no-tests-found-test');
|
|||
describe('No tests are found', () => {
|
||||
test('fails the test suite in standard situation', () => {
|
||||
const {exitCode, stdout} = runJest(DIR, [
|
||||
'--testPathPattern',
|
||||
'--testPathPatterns',
|
||||
'/non/existing/path/',
|
||||
]);
|
||||
|
||||
|
@ -26,7 +26,7 @@ describe('No tests are found', () => {
|
|||
|
||||
test("doesn't fail the test suite if --passWithNoTests passed", () => {
|
||||
const {exitCode, stdout} = runJest(DIR, [
|
||||
'--testPathPattern',
|
||||
'--testPathPatterns',
|
||||
'/non/existing/path/',
|
||||
'--passWithNoTests',
|
||||
]);
|
||||
|
|
|
@ -246,7 +246,7 @@ test('collect test coverage when using onlyChanged', () => {
|
|||
expect(exitCode).toBe(0);
|
||||
});
|
||||
|
||||
test('onlyChanged in config is overwritten by --all or testPathPattern', () => {
|
||||
test('onlyChanged in config is overwritten by --all or testPathPatterns', () => {
|
||||
writeFiles(DIR, {
|
||||
'.watchmanconfig': '',
|
||||
'__tests__/file1.test.js': "require('../file1'); test('file1', () => {});",
|
||||
|
|
|
@ -25,14 +25,14 @@ test('prints a message with path pattern at the end', () => {
|
|||
let stderr;
|
||||
|
||||
({stderr} = runJest(DIR, ['a']));
|
||||
expect(stderr).toMatch('Ran all test suites matching /a/i');
|
||||
expect(stderr).toMatch('Ran all test suites matching a');
|
||||
|
||||
({stderr} = runJest(DIR, ['a', 'b']));
|
||||
expect(stderr).toMatch('Ran all test suites matching /a|b/i');
|
||||
expect(stderr).toMatch('Ran all test suites matching a|b');
|
||||
|
||||
({stderr} = runJest(DIR, ['--testPathPattern', 'a']));
|
||||
expect(stderr).toMatch('Ran all test suites matching /a/i');
|
||||
({stderr} = runJest(DIR, ['--testPathPatterns', 'a']));
|
||||
expect(stderr).toMatch('Ran all test suites matching a');
|
||||
|
||||
({stderr} = runJest(DIR, ['--testPathPattern', 'a|b']));
|
||||
expect(stderr).toMatch('Ran all test suites matching /a|b/i');
|
||||
({stderr} = runJest(DIR, ['--testPathPatterns', 'a|b']));
|
||||
expect(stderr).toMatch('Ran all test suites matching a|b');
|
||||
});
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
function invalidSetupWithNamedExport(jestConfig): void {
|
||||
console.log(jestConfig.testPathPattern);
|
||||
console.log(jestConfig.testPathPatterns);
|
||||
}
|
||||
|
||||
export {invalidSetupWithNamedExport};
|
||||
|
|
|
@ -6,6 +6,6 @@
|
|||
*/
|
||||
|
||||
module.exports = function (globalConfig, projectConfig) {
|
||||
console.log(globalConfig.testPathPattern);
|
||||
console.log(globalConfig.testPathPatterns);
|
||||
console.log(projectConfig.cache);
|
||||
};
|
||||
|
|
|
@ -6,6 +6,6 @@
|
|||
*/
|
||||
|
||||
export default function (globalConfig, projectConfig): void {
|
||||
console.log(globalConfig.testPathPattern);
|
||||
console.log(globalConfig.testPathPatterns);
|
||||
console.log(projectConfig.cache);
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
function invalidTeardownWithNamedExport(jestConfig): void {
|
||||
console.log(jestConfig.testPathPattern);
|
||||
console.log(jestConfig.testPathPatterns);
|
||||
}
|
||||
|
||||
export {invalidTeardownWithNamedExport};
|
||||
|
|
|
@ -6,6 +6,6 @@
|
|||
*/
|
||||
|
||||
module.exports = function (globalConfig, projectConfig) {
|
||||
console.log(globalConfig.testPathPattern);
|
||||
console.log(globalConfig.testPathPatterns);
|
||||
console.log(projectConfig.cache);
|
||||
};
|
||||
|
|
|
@ -6,6 +6,6 @@
|
|||
*/
|
||||
|
||||
export default function (globalConfig, projectConfig): void {
|
||||
console.log(globalConfig.testPathPattern);
|
||||
console.log(globalConfig.testPathPatterns);
|
||||
console.log(projectConfig.cache);
|
||||
}
|
||||
|
|
|
@ -97,7 +97,7 @@ export function check(argv: Config.Argv): true {
|
|||
}
|
||||
|
||||
export const usage =
|
||||
'Usage: $0 [--config=<pathToConfigFile>] [TestPathPattern]';
|
||||
'Usage: $0 [--config=<pathToConfigFile>] [TestPathPatterns]';
|
||||
export const docs = 'Documentation: https://jestjs.io/';
|
||||
|
||||
// The default values are all set in jest-config
|
||||
|
@ -431,7 +431,7 @@ export const options: {[key: string]: Options} = {
|
|||
},
|
||||
passWithNoTests: {
|
||||
description:
|
||||
'Will not fail if no tests are found (for example while using `--testPathPattern`.)',
|
||||
'Will not fail if no tests are found (for example while using `--testPathPatterns`.)',
|
||||
type: 'boolean',
|
||||
},
|
||||
preset: {
|
||||
|
@ -609,7 +609,7 @@ export const options: {[key: string]: Options} = {
|
|||
string: true,
|
||||
type: 'array',
|
||||
},
|
||||
testPathPattern: {
|
||||
testPathPatterns: {
|
||||
description:
|
||||
'A regexp pattern string that is matched against all tests ' +
|
||||
'paths before executing the test.',
|
||||
|
|
|
@ -8,6 +8,15 @@
|
|||
import chalk = require('chalk');
|
||||
import type {DeprecatedOptions} from 'jest-validate';
|
||||
|
||||
function formatDeprecation(message: string): string {
|
||||
const lines = [
|
||||
message.replace(/\*(.+?)\*/g, (_, s) => chalk.bold(`"${s}"`)),
|
||||
'',
|
||||
'Please update your configuration.',
|
||||
];
|
||||
return lines.map(s => ` ${s}`).join('\n');
|
||||
}
|
||||
|
||||
const deprecatedOptions: DeprecatedOptions = {
|
||||
browser: () =>
|
||||
` Option ${chalk.bold(
|
||||
|
@ -78,6 +87,11 @@ const deprecatedOptions: DeprecatedOptions = {
|
|||
Please update your configuration.
|
||||
`,
|
||||
|
||||
testPathPattern: () =>
|
||||
formatDeprecation(
|
||||
'Option *testPathPattern* was replaced by *testPathPatterns*.',
|
||||
),
|
||||
|
||||
testURL: (_options: {testURL?: string}) => ` Option ${chalk.bold(
|
||||
'"testURL"',
|
||||
)} was replaced by passing the URL via ${chalk.bold(
|
||||
|
|
|
@ -482,9 +482,9 @@ exports[`testMatch throws if testRegex and testMatch are both specified 1`] = `
|
|||
<red></color>"
|
||||
`;
|
||||
|
||||
exports[`testPathPattern <regexForTestFiles> ignores invalid regular expressions and logs a warning 1`] = `"<red> Invalid testPattern a( supplied. Running all tests instead.</color>"`;
|
||||
exports[`testPathPatterns <regexForTestFiles> ignores invalid regular expressions and logs a warning 1`] = `"<red> Invalid testPattern a( supplied. Running all tests instead.</color>"`;
|
||||
|
||||
exports[`testPathPattern --testPathPattern ignores invalid regular expressions and logs a warning 1`] = `"<red> Invalid testPattern a( supplied. Running all tests instead.</color>"`;
|
||||
exports[`testPathPatterns --testPathPatterns ignores invalid regular expressions and logs a warning 1`] = `"<red> Invalid testPattern a( supplied. Running all tests instead.</color>"`;
|
||||
|
||||
exports[`testTimeout should throw an error if timeout is a negative number 1`] = `
|
||||
"<red><bold><bold>● </intensity><bold>Validation Error</intensity>:</color>
|
||||
|
|
|
@ -1585,7 +1585,7 @@ describe('watchPlugins', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('testPathPattern', () => {
|
||||
describe('testPathPatterns', () => {
|
||||
const initialOptions = {rootDir: '/root'};
|
||||
const consoleLog = console.log;
|
||||
|
||||
|
@ -1600,11 +1600,11 @@ describe('testPathPattern', () => {
|
|||
it('defaults to empty', async () => {
|
||||
const {options} = await normalize(initialOptions, {} as Config.Argv);
|
||||
|
||||
expect(options.testPathPattern).toBe('');
|
||||
expect(options.testPathPatterns).toEqual([]);
|
||||
});
|
||||
|
||||
const cliOptions = [
|
||||
{name: '--testPathPattern', property: 'testPathPattern'},
|
||||
{name: '--testPathPatterns', property: 'testPathPatterns'},
|
||||
{name: '<regexForTestFiles>', property: '_'},
|
||||
];
|
||||
for (const opt of cliOptions) {
|
||||
|
@ -1613,14 +1613,14 @@ describe('testPathPattern', () => {
|
|||
const argv = {[opt.property]: ['a/b']} as Config.Argv;
|
||||
const {options} = await normalize(initialOptions, argv);
|
||||
|
||||
expect(options.testPathPattern).toBe('a/b');
|
||||
expect(options.testPathPatterns).toEqual(['a/b']);
|
||||
});
|
||||
|
||||
it('ignores invalid regular expressions and logs a warning', async () => {
|
||||
const argv = {[opt.property]: ['a(']} as Config.Argv;
|
||||
const {options} = await normalize(initialOptions, argv);
|
||||
|
||||
expect(options.testPathPattern).toBe('');
|
||||
expect(options.testPathPatterns).toEqual([]);
|
||||
expect(jest.mocked(console.log).mock.calls[0][0]).toMatchSnapshot();
|
||||
});
|
||||
|
||||
|
@ -1628,78 +1628,24 @@ describe('testPathPattern', () => {
|
|||
const argv = {[opt.property]: ['a/b', 'c/d']} as Config.Argv;
|
||||
const {options} = await normalize(initialOptions, argv);
|
||||
|
||||
expect(options.testPathPattern).toBe('a/b|c/d');
|
||||
});
|
||||
|
||||
it('coerces all patterns to strings', async () => {
|
||||
const argv = {[opt.property]: [1]} as Config.Argv;
|
||||
const {options} = await normalize(initialOptions, argv);
|
||||
|
||||
expect(options.testPathPattern).toBe('1');
|
||||
});
|
||||
|
||||
describe('posix', () => {
|
||||
it('should not escape the pattern', async () => {
|
||||
const argv = {
|
||||
[opt.property]: ['a\\/b', 'a/b', 'a\\b', 'a\\\\b'],
|
||||
} as Config.Argv;
|
||||
const {options} = await normalize(initialOptions, argv);
|
||||
|
||||
expect(options.testPathPattern).toBe('a\\/b|a/b|a\\b|a\\\\b');
|
||||
});
|
||||
});
|
||||
|
||||
describe('win32', () => {
|
||||
beforeEach(() => {
|
||||
jest.mock(
|
||||
'path',
|
||||
() => jest.requireActual<typeof import('path')>('path').win32,
|
||||
);
|
||||
(
|
||||
require('jest-resolve') as typeof import('jest-resolve')
|
||||
).default.findNodeModule = findNodeModule;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.resetModules();
|
||||
});
|
||||
|
||||
it('preserves any use of "\\"', async () => {
|
||||
const argv = {[opt.property]: ['a\\b', 'c\\\\d']} as Config.Argv;
|
||||
const {options} = await (
|
||||
require('../normalize') as typeof import('../normalize')
|
||||
).default(initialOptions, argv);
|
||||
|
||||
expect(options.testPathPattern).toBe('a\\b|c\\\\d');
|
||||
});
|
||||
|
||||
it('replaces POSIX path separators', async () => {
|
||||
const argv = {[opt.property]: ['a/b']} as Config.Argv;
|
||||
const {options} = await (
|
||||
require('../normalize') as typeof import('../normalize')
|
||||
).default(initialOptions, argv);
|
||||
|
||||
expect(options.testPathPattern).toBe('a\\\\b');
|
||||
});
|
||||
|
||||
it('replaces POSIX paths in multiple args', async () => {
|
||||
const argv = {[opt.property]: ['a/b', 'c/d']} as Config.Argv;
|
||||
const {options} = await (
|
||||
require('../normalize') as typeof import('../normalize')
|
||||
).default(initialOptions, argv);
|
||||
|
||||
expect(options.testPathPattern).toBe('a\\\\b|c\\\\d');
|
||||
});
|
||||
expect(options.testPathPatterns).toEqual(['a/b', 'c/d']);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
it('coerces <regexForTestFiles> patterns to strings', async () => {
|
||||
const argv = {_: [1]} as Config.Argv;
|
||||
const {options} = await normalize(initialOptions, argv);
|
||||
|
||||
expect(options.testPathPatterns).toEqual(['1']);
|
||||
});
|
||||
|
||||
it('joins multiple --testPathPatterns and <regexForTestFiles>', async () => {
|
||||
const {options} = await normalize(initialOptions, {
|
||||
_: ['a', 'b'],
|
||||
testPathPattern: ['c', 'd'],
|
||||
testPathPatterns: ['c', 'd'],
|
||||
} as Config.Argv);
|
||||
expect(options.testPathPattern).toBe('a|b|c|d');
|
||||
expect(options.testPathPatterns).toEqual(['a', 'b', 'c', 'd']);
|
||||
});
|
||||
|
||||
it('gives precedence to --all', async () => {
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
/**
|
||||
* 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 validatePattern from '../validatePattern';
|
||||
|
||||
describe('validate pattern function', () => {
|
||||
it('without passed args returns true', () => {
|
||||
const isValid = validatePattern();
|
||||
|
||||
expect(isValid).toBeTruthy();
|
||||
});
|
||||
|
||||
it('returns true for empty pattern', () => {
|
||||
const isValid = validatePattern('');
|
||||
|
||||
expect(isValid).toBeTruthy();
|
||||
});
|
||||
|
||||
it('returns true for valid pattern', () => {
|
||||
const isValid = validatePattern('abc+');
|
||||
|
||||
expect(isValid).toBeTruthy();
|
||||
});
|
||||
|
||||
it('returns false for invalid pattern', () => {
|
||||
const isValid = validatePattern('\\');
|
||||
|
||||
expect(isValid).toBeFalsy();
|
||||
});
|
||||
});
|
|
@ -131,7 +131,7 @@ const groupOptions = (
|
|||
snapshotFormat: options.snapshotFormat,
|
||||
testFailureExitCode: options.testFailureExitCode,
|
||||
testNamePattern: options.testNamePattern,
|
||||
testPathPattern: options.testPathPattern,
|
||||
testPathPatterns: options.testPathPatterns,
|
||||
testResultsProcessor: options.testResultsProcessor,
|
||||
testSequencer: options.testSequencer,
|
||||
testTimeout: options.testTimeout,
|
||||
|
|
|
@ -22,6 +22,7 @@ import Resolver, {
|
|||
resolveWatchPlugin,
|
||||
} from 'jest-resolve';
|
||||
import {
|
||||
TestPathPatterns,
|
||||
clearLine,
|
||||
replacePathSepForGlob,
|
||||
requireOrImportModule,
|
||||
|
@ -49,7 +50,6 @@ import {
|
|||
replaceRootDirInPath,
|
||||
resolve,
|
||||
} from './utils';
|
||||
import validatePattern from './validatePattern';
|
||||
|
||||
const ERROR = `${BULLET}Validation Error`;
|
||||
const PRESET_EXTENSIONS = ['.json', '.js', '.cjs', '.mjs'];
|
||||
|
@ -391,44 +391,39 @@ const normalizeReporters = ({
|
|||
});
|
||||
};
|
||||
|
||||
const buildTestPathPattern = (argv: Config.Argv): string => {
|
||||
const buildTestPathPatterns = (
|
||||
argv: Config.Argv,
|
||||
rootDir: string,
|
||||
): TestPathPatterns => {
|
||||
const patterns = [];
|
||||
|
||||
if (argv._) {
|
||||
patterns.push(...argv._);
|
||||
patterns.push(...argv._.map(x => x.toString()));
|
||||
}
|
||||
if (argv.testPathPattern) {
|
||||
patterns.push(...argv.testPathPattern);
|
||||
if (argv.testPathPatterns) {
|
||||
patterns.push(...argv.testPathPatterns);
|
||||
}
|
||||
|
||||
const replacePosixSep = (pattern: string | number) => {
|
||||
// yargs coerces positional args into numbers
|
||||
const patternAsString = pattern.toString();
|
||||
if (path.sep === '/') {
|
||||
return patternAsString;
|
||||
}
|
||||
return patternAsString.replace(/\//g, '\\\\');
|
||||
};
|
||||
const config = {rootDir};
|
||||
const testPathPatterns = new TestPathPatterns(patterns, config);
|
||||
|
||||
const testPathPattern = patterns.map(replacePosixSep).join('|');
|
||||
if (validatePattern(testPathPattern)) {
|
||||
return testPathPattern;
|
||||
} else {
|
||||
showTestPathPatternError(testPathPattern);
|
||||
return '';
|
||||
try {
|
||||
testPathPatterns.validate();
|
||||
} catch {
|
||||
clearLine(process.stdout);
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(
|
||||
chalk.red(
|
||||
` Invalid testPattern ${testPathPatterns.toPretty()} supplied. ` +
|
||||
'Running all tests instead.',
|
||||
),
|
||||
);
|
||||
|
||||
return new TestPathPatterns([], config);
|
||||
}
|
||||
};
|
||||
|
||||
const showTestPathPatternError = (testPathPattern: string) => {
|
||||
clearLine(process.stdout);
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(
|
||||
chalk.red(
|
||||
` Invalid testPattern ${testPathPattern} supplied. ` +
|
||||
'Running all tests instead.',
|
||||
),
|
||||
);
|
||||
return testPathPatterns;
|
||||
};
|
||||
|
||||
function validateExtensionsToTreatAsEsm(
|
||||
|
@ -1007,7 +1002,8 @@ export default async function normalize(
|
|||
}
|
||||
|
||||
newOptions.nonFlagArgs = argv._?.map(arg => `${arg}`);
|
||||
newOptions.testPathPattern = buildTestPathPattern(argv);
|
||||
const testPathPatterns = buildTestPathPatterns(argv, options.rootDir);
|
||||
newOptions.testPathPatterns = testPathPatterns.patterns;
|
||||
newOptions.json = !!argv.json;
|
||||
|
||||
newOptions.testFailureExitCode = parseInt(
|
||||
|
@ -1026,7 +1022,7 @@ export default async function normalize(
|
|||
if (argv.all) {
|
||||
newOptions.onlyChanged = false;
|
||||
newOptions.onlyFailures = false;
|
||||
} else if (newOptions.testPathPattern) {
|
||||
} else if (testPathPatterns.isSet()) {
|
||||
// When passing a test path pattern we don't want to only monitor changed
|
||||
// files unless `--watch` is also passed.
|
||||
newOptions.onlyChanged = newOptions.watch;
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export default function validatePattern(pattern?: string): boolean {
|
||||
if (pattern) {
|
||||
try {
|
||||
// eslint-disable-next-line no-new
|
||||
new RegExp(pattern, 'i');
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
|
@ -15,7 +15,7 @@ import {replaceRootDirInPath} from 'jest-config';
|
|||
import {escapePathForRegex} from 'jest-regex-util';
|
||||
import {DependencyResolver} from 'jest-resolve-dependencies';
|
||||
import {buildSnapshotResolver} from 'jest-snapshot';
|
||||
import {globsToMatcher, testPathPatternToRegExp} from 'jest-util';
|
||||
import {TestPathPatterns, globsToMatcher} from 'jest-util';
|
||||
import type {Filter, Stats, TestPathCases} from './types';
|
||||
|
||||
export type SearchResult = {
|
||||
|
@ -110,7 +110,7 @@ export default class SearchSource {
|
|||
|
||||
private _filterTestPathsWithStats(
|
||||
allPaths: Array<Test>,
|
||||
testPathPattern: string,
|
||||
testPathPatterns: TestPathPatterns,
|
||||
): SearchResult {
|
||||
const data: {
|
||||
stats: Stats;
|
||||
|
@ -128,13 +128,12 @@ export default class SearchSource {
|
|||
};
|
||||
|
||||
const testCases = Array.from(this._testPathCases); // clone
|
||||
if (testPathPattern) {
|
||||
const regex = testPathPatternToRegExp(testPathPattern);
|
||||
if (testPathPatterns.isSet()) {
|
||||
testCases.push({
|
||||
isMatch: (path: string) => regex.test(path),
|
||||
stat: 'testPathPattern',
|
||||
isMatch: (path: string) => testPathPatterns.isMatch(path),
|
||||
stat: 'testPathPatterns',
|
||||
});
|
||||
data.stats.testPathPattern = 0;
|
||||
data.stats.testPathPatterns = 0;
|
||||
}
|
||||
|
||||
data.tests = allPaths.filter(test => {
|
||||
|
@ -152,10 +151,10 @@ export default class SearchSource {
|
|||
return data;
|
||||
}
|
||||
|
||||
private _getAllTestPaths(testPathPattern: string): SearchResult {
|
||||
private _getAllTestPaths(testPathPatterns: TestPathPatterns): SearchResult {
|
||||
return this._filterTestPathsWithStats(
|
||||
toTests(this._context, this._context.hasteFS.getAllFiles()),
|
||||
testPathPattern,
|
||||
testPathPatterns,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -163,8 +162,8 @@ export default class SearchSource {
|
|||
return this._testPathCases.every(testCase => testCase.isMatch(path));
|
||||
}
|
||||
|
||||
findMatchingTests(testPathPattern: string): SearchResult {
|
||||
return this._getAllTestPaths(testPathPattern);
|
||||
findMatchingTests(testPathPatterns: TestPathPatterns): SearchResult {
|
||||
return this._getAllTestPaths(testPathPatterns);
|
||||
}
|
||||
|
||||
async findRelatedTests(
|
||||
|
@ -287,10 +286,10 @@ export default class SearchSource {
|
|||
paths,
|
||||
globalConfig.collectCoverage,
|
||||
);
|
||||
} else if (globalConfig.testPathPattern == null) {
|
||||
return {tests: []};
|
||||
} else {
|
||||
return this.findMatchingTests(globalConfig.testPathPattern);
|
||||
return this.findMatchingTests(
|
||||
TestPathPatterns.fromGlobalConfig(globalConfig),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -109,7 +109,8 @@ describe('SearchSource', () => {
|
|||
const {searchSource, config} = await initSearchSource(initialOptions);
|
||||
const {tests: paths} = await searchSource.getTestPaths({
|
||||
...config,
|
||||
testPathPattern: '',
|
||||
...initialOptions,
|
||||
testPathPatterns: [],
|
||||
});
|
||||
return paths.map(({path: p}) => path.relative(rootDir, p)).sort();
|
||||
};
|
||||
|
|
|
@ -92,7 +92,10 @@ exports[`Watch mode flows Pressing "P" enters pattern mode 9`] = `
|
|||
Object {
|
||||
"onlyChanged": false,
|
||||
"passWithNoTests": true,
|
||||
"testPathPattern": "p.*3",
|
||||
"rootDir": "",
|
||||
"testPathPatterns": Array [
|
||||
"p.*3",
|
||||
],
|
||||
"watch": true,
|
||||
"watchAll": false,
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ describe('getNoTestsFoundMessage', () => {
|
|||
function createGlobalConfig(options?: Partial<Config.GlobalConfig>) {
|
||||
return makeGlobalConfig({
|
||||
rootDir: '/root/dir',
|
||||
testPathPattern: '/path/pattern',
|
||||
testPathPatterns: ['/path/pattern'],
|
||||
...options,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -22,6 +22,8 @@ describe('runJest', () => {
|
|||
changedFilesPromise: Promise.resolve({repos: {git: {size: 0}}}),
|
||||
contexts: [],
|
||||
globalConfig: {
|
||||
rootDir: '',
|
||||
testPathPatterns: [],
|
||||
testSequencer: require.resolve('@jest/test-sequencer'),
|
||||
watch: true,
|
||||
},
|
||||
|
|
|
@ -140,7 +140,11 @@ describe('Watch mode flows', () => {
|
|||
testRegex: [],
|
||||
};
|
||||
pipe = {write: jest.fn()};
|
||||
globalConfig = {watch: true};
|
||||
globalConfig = {
|
||||
rootDir: '',
|
||||
testPathPatterns: [],
|
||||
watch: true,
|
||||
};
|
||||
hasteMapInstances = [{on: () => {}}];
|
||||
contexts = [{config}];
|
||||
stdin = new MockStdin();
|
||||
|
@ -152,7 +156,7 @@ describe('Watch mode flows', () => {
|
|||
});
|
||||
|
||||
it('Correctly passing test path pattern', async () => {
|
||||
globalConfig.testPathPattern = 'test-*';
|
||||
globalConfig.testPathPatterns = ['test-*'];
|
||||
|
||||
await watch(globalConfig, contexts, pipe, hasteMapInstances, stdin);
|
||||
|
||||
|
@ -671,7 +675,7 @@ describe('Watch mode flows', () => {
|
|||
${'✖︎'} | ${'skipFilter'}
|
||||
${'✖︎'} | ${'testFailureExitCode'}
|
||||
${'✔︎'} | ${'testNamePattern'}
|
||||
${'✔︎'} | ${'testPathPattern'}
|
||||
${'✔︎'} | ${'testPathPatterns'}
|
||||
${'✖︎'} | ${'testResultsProcessor'}
|
||||
${'✔︎'} | ${'updateSnapshot'}
|
||||
${'✖︎'} | ${'useStderr'}
|
||||
|
@ -898,7 +902,7 @@ describe('Watch mode flows', () => {
|
|||
await nextTick();
|
||||
|
||||
expect(runJestMock.mock.calls[0][0].globalConfig).toMatchObject({
|
||||
testPathPattern: 'file',
|
||||
testPathPatterns: ['file'],
|
||||
watch: true,
|
||||
watchAll: false,
|
||||
});
|
||||
|
@ -922,7 +926,7 @@ describe('Watch mode flows', () => {
|
|||
|
||||
expect(runJestMock.mock.calls[1][0].globalConfig).toMatchObject({
|
||||
testNamePattern: 'test',
|
||||
testPathPattern: 'file',
|
||||
testPathPatterns: ['file'],
|
||||
watch: true,
|
||||
watchAll: false,
|
||||
});
|
||||
|
|
|
@ -70,7 +70,11 @@ const watch = require('../watch').default;
|
|||
|
||||
const nextTick = () => new Promise(res => process.nextTick(res));
|
||||
|
||||
const globalConfig = {watch: true};
|
||||
const globalConfig = {
|
||||
rootDir: '',
|
||||
testPathPatterns: [],
|
||||
watch: true,
|
||||
};
|
||||
|
||||
afterEach(runJestMock.mockReset);
|
||||
|
||||
|
|
|
@ -83,6 +83,8 @@ jest.doMock(
|
|||
const watch = require('../watch').default;
|
||||
|
||||
const globalConfig = {
|
||||
rootDir: '',
|
||||
testPathPatterns: [],
|
||||
watch: true,
|
||||
};
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import chalk = require('chalk');
|
||||
import type {Config} from '@jest/types';
|
||||
import {pluralize} from 'jest-util';
|
||||
import {TestPathPatterns, pluralize} from 'jest-util';
|
||||
import type {TestRunData} from './types';
|
||||
|
||||
export default function getNoTestFound(
|
||||
|
@ -26,8 +26,9 @@ export default function getNoTestFound(
|
|||
.map(p => `"${p}"`)
|
||||
.join(', ')}`;
|
||||
} else {
|
||||
const testPathPatterns = TestPathPatterns.fromGlobalConfig(globalConfig);
|
||||
dataMessage = `Pattern: ${chalk.yellow(
|
||||
globalConfig.testPathPattern,
|
||||
testPathPatterns.toPretty(),
|
||||
)} - 0 matches`;
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import chalk = require('chalk');
|
||||
import type {Config} from '@jest/types';
|
||||
import {pluralize} from 'jest-util';
|
||||
import {TestPathPatterns, pluralize} from 'jest-util';
|
||||
import type {Stats, TestRunData} from './types';
|
||||
|
||||
export default function getNoTestFoundVerbose(
|
||||
|
@ -56,8 +56,9 @@ export default function getNoTestFoundVerbose(
|
|||
.map(p => `"${p}"`)
|
||||
.join(', ')}`;
|
||||
} else {
|
||||
const testPathPatterns = TestPathPatterns.fromGlobalConfig(globalConfig);
|
||||
dataMessage = `Pattern: ${chalk.yellow(
|
||||
globalConfig.testPathPattern,
|
||||
testPathPatterns.toPretty(),
|
||||
)} - 0 matches`;
|
||||
}
|
||||
|
||||
|
|
|
@ -109,7 +109,7 @@ exports[`prints the config object 1`] = `
|
|||
"snapshotFormat": {},
|
||||
"testFailureExitCode": 1,
|
||||
"testNamePattern": "",
|
||||
"testPathPattern": "",
|
||||
"testPathPatterns": [],
|
||||
"testSequencer": "@jest/test-sequencer",
|
||||
"testTimeout": 5000,
|
||||
"updateSnapshot": "none",
|
||||
|
|
|
@ -7,14 +7,15 @@
|
|||
|
||||
import chalk = require('chalk');
|
||||
import type {Config} from '@jest/types';
|
||||
import {isNonNullable} from 'jest-util';
|
||||
import {TestPathPatterns, isNonNullable} from 'jest-util';
|
||||
|
||||
const activeFilters = (globalConfig: Config.GlobalConfig): string => {
|
||||
const {testNamePattern, testPathPattern} = globalConfig;
|
||||
if (testNamePattern || testPathPattern) {
|
||||
const {testNamePattern} = globalConfig;
|
||||
const testPathPatterns = TestPathPatterns.fromGlobalConfig(globalConfig);
|
||||
if (testNamePattern || testPathPatterns.isSet()) {
|
||||
const filters = [
|
||||
testPathPattern
|
||||
? chalk.dim('filename ') + chalk.yellow(`/${testPathPattern}/`)
|
||||
testPathPatterns.isSet()
|
||||
? chalk.dim('filename ') + chalk.yellow(testPathPatterns.toPretty())
|
||||
: null,
|
||||
testNamePattern
|
||||
? chalk.dim('test name ') + chalk.yellow(`/${testNamePattern}/`)
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
import type {Config} from '@jest/types';
|
||||
import {replacePathSepForRegex} from 'jest-regex-util';
|
||||
import {TestPathPatterns} from 'jest-util';
|
||||
import type {AllowedConfigOptions} from 'jest-watcher';
|
||||
|
||||
type ExtraConfigOptions = Partial<
|
||||
|
@ -31,15 +31,14 @@ export default function updateGlobalConfig(
|
|||
newConfig.testNamePattern = options.testNamePattern || '';
|
||||
}
|
||||
|
||||
if (options.testPathPattern !== undefined) {
|
||||
newConfig.testPathPattern =
|
||||
replacePathSepForRegex(options.testPathPattern) || '';
|
||||
if (options.testPathPatterns !== undefined) {
|
||||
newConfig.testPathPatterns = options.testPathPatterns;
|
||||
}
|
||||
|
||||
newConfig.onlyChanged =
|
||||
!newConfig.watchAll &&
|
||||
!newConfig.testNamePattern &&
|
||||
!newConfig.testPathPattern;
|
||||
!TestPathPatterns.fromGlobalConfig(newConfig).isSet();
|
||||
|
||||
if (typeof options.bail === 'boolean') {
|
||||
newConfig.bail = options.bail ? 1 : 0;
|
||||
|
|
|
@ -58,7 +58,7 @@ export default class FailedTestsInteractivePlugin extends BaseWatchPlugin {
|
|||
updateConfigAndRun({
|
||||
mode: 'watch',
|
||||
testNamePattern: failure ? `^${failure.fullName}$` : '',
|
||||
testPathPattern: failure?.path || '',
|
||||
testPathPatterns: failure ? [failure.path] : [],
|
||||
});
|
||||
|
||||
if (!this._manager.isActive()) {
|
||||
|
|
|
@ -48,7 +48,7 @@ class TestPathPatternPlugin extends BaseWatchPlugin {
|
|||
|
||||
testPathPatternPrompt.run(
|
||||
(value: string) => {
|
||||
updateConfigAndRun({mode: 'watch', testPathPattern: value});
|
||||
updateConfigAndRun({mode: 'watch', testPathPatterns: [value]});
|
||||
res();
|
||||
},
|
||||
rej,
|
||||
|
|
|
@ -70,7 +70,7 @@ class UpdateSnapshotInteractivePlugin extends BaseWatchPlugin {
|
|||
updateConfigAndRun({
|
||||
mode: 'watch',
|
||||
testNamePattern: assertion ? `^${assertion.fullName}$` : '',
|
||||
testPathPattern: assertion ? assertion.path : '',
|
||||
testPathPatterns: assertion ? [assertion.path] : [],
|
||||
|
||||
updateSnapshot: shouldUpdateSnapshot ? 'all' : 'none',
|
||||
});
|
||||
|
|
|
@ -40,7 +40,7 @@ describe('FailedTestsInteractive', () => {
|
|||
expect(mockUpdate).toHaveBeenCalledWith({
|
||||
mode: 'watch',
|
||||
testNamePattern: `^${testAggregate.testResults[0].testResults[0].fullName}$`,
|
||||
testPathPattern: testAggregate.testResults[0].testFilePath,
|
||||
testPathPatterns: [testAggregate.testResults[0].testFilePath],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -12,7 +12,7 @@ export type Stats = {
|
|||
testMatch: number;
|
||||
testPathIgnorePatterns: number;
|
||||
testRegex: number;
|
||||
testPathPattern?: number;
|
||||
testPathPatterns?: number;
|
||||
};
|
||||
|
||||
export type TestRunData = Array<{
|
||||
|
@ -31,7 +31,7 @@ export type TestPathCases = Array<{
|
|||
}>;
|
||||
|
||||
export type TestPathCasesWithPathPattern = TestPathCases & {
|
||||
testPathPattern: (path: string) => boolean;
|
||||
testPathPatterns: (path: string) => boolean;
|
||||
};
|
||||
|
||||
export type FilterResult = {
|
||||
|
|
|
@ -15,6 +15,7 @@ import type {Config} from '@jest/types';
|
|||
import type {IHasteMap as HasteMap} from 'jest-haste-map';
|
||||
import {formatExecError} from 'jest-message-util';
|
||||
import {
|
||||
TestPathPatterns,
|
||||
isInteractive,
|
||||
preRunMessage,
|
||||
requireOrImportModule,
|
||||
|
@ -120,7 +121,7 @@ export default async function watch(
|
|||
onlyFailures,
|
||||
reporters,
|
||||
testNamePattern,
|
||||
testPathPattern,
|
||||
testPathPatterns,
|
||||
updateSnapshot,
|
||||
verbose,
|
||||
}: AllowedConfigOptions = {}) => {
|
||||
|
@ -140,7 +141,7 @@ export default async function watch(
|
|||
onlyFailures,
|
||||
reporters,
|
||||
testNamePattern,
|
||||
testPathPattern,
|
||||
testPathPatterns,
|
||||
updateSnapshot,
|
||||
verbose,
|
||||
});
|
||||
|
@ -227,9 +228,12 @@ export default async function watch(
|
|||
|
||||
const emitFileChange = () => {
|
||||
if (hooks.isUsed('onFileChange')) {
|
||||
const testPathPatterns = new TestPathPatterns([], globalConfig);
|
||||
const projects = searchSources.map(({context, searchSource}) => ({
|
||||
config: context.config,
|
||||
testPaths: searchSource.findMatchingTests('').tests.map(t => t.path),
|
||||
testPaths: searchSource
|
||||
.findMatchingTests(testPathPatterns)
|
||||
.tests.map(t => t.path),
|
||||
}));
|
||||
hooks.getEmitter().onFileChange({projects});
|
||||
}
|
||||
|
@ -404,7 +408,7 @@ export default async function watch(
|
|||
globalConfig = updateGlobalConfig(globalConfig, {
|
||||
mode: 'watchAll',
|
||||
testNamePattern: '',
|
||||
testPathPattern: '',
|
||||
testPathPatterns: [],
|
||||
});
|
||||
startRun(globalConfig);
|
||||
break;
|
||||
|
@ -412,7 +416,7 @@ export default async function watch(
|
|||
updateConfigAndRun({
|
||||
mode: 'watch',
|
||||
testNamePattern: '',
|
||||
testPathPattern: '',
|
||||
testPathPatterns: [],
|
||||
});
|
||||
break;
|
||||
case 'f':
|
||||
|
@ -425,7 +429,7 @@ export default async function watch(
|
|||
globalConfig = updateGlobalConfig(globalConfig, {
|
||||
mode: 'watch',
|
||||
testNamePattern: '',
|
||||
testPathPattern: '',
|
||||
testPathPatterns: [],
|
||||
});
|
||||
startRun(globalConfig);
|
||||
break;
|
||||
|
@ -528,10 +532,11 @@ const usage = (
|
|||
watchPlugins: Array<WatchPlugin>,
|
||||
delimiter = '\n',
|
||||
) => {
|
||||
const testPathPatterns = TestPathPatterns.fromGlobalConfig(globalConfig);
|
||||
const messages = [
|
||||
activeFilters(globalConfig),
|
||||
|
||||
globalConfig.testPathPattern || globalConfig.testNamePattern
|
||||
testPathPatterns.isSet() || globalConfig.testNamePattern
|
||||
? `${chalk.dim(' \u203A Press ')}c${chalk.dim(' to clear filters.')}`
|
||||
: null,
|
||||
`\n${chalk.bold('Watch Usage')}`,
|
||||
|
@ -549,7 +554,7 @@ const usage = (
|
|||
)}`,
|
||||
|
||||
(globalConfig.watchAll ||
|
||||
globalConfig.testPathPattern ||
|
||||
testPathPatterns.isSet() ||
|
||||
globalConfig.testNamePattern) &&
|
||||
!globalConfig.noSCM
|
||||
? `${chalk.dim(' \u203A Press ')}o${chalk.dim(
|
||||
|
|
|
@ -12,7 +12,7 @@ import type {
|
|||
TestContext,
|
||||
} from '@jest/test-result';
|
||||
import type {Config} from '@jest/types';
|
||||
import {testPathPatternToRegExp} from 'jest-util';
|
||||
import {TestPathPatterns} from 'jest-util';
|
||||
import BaseReporter from './BaseReporter';
|
||||
import getResultHeader from './getResultHeader';
|
||||
import getSnapshotSummary from './getSnapshotSummary';
|
||||
|
@ -212,15 +212,14 @@ export default class SummaryReporter extends BaseReporter {
|
|||
testContexts: Set<TestContext>,
|
||||
globalConfig: Config.GlobalConfig,
|
||||
) {
|
||||
const testPathPatterns = TestPathPatterns.fromGlobalConfig(globalConfig);
|
||||
|
||||
const getMatchingTestsInfo = () => {
|
||||
const prefix = globalConfig.findRelatedTests
|
||||
? ' related to files matching '
|
||||
: ' matching ';
|
||||
|
||||
return (
|
||||
chalk.dim(prefix) +
|
||||
testPathPatternToRegExp(globalConfig.testPathPattern).toString()
|
||||
);
|
||||
return chalk.dim(prefix) + testPathPatterns.toPretty();
|
||||
};
|
||||
|
||||
let testInfo = '';
|
||||
|
@ -229,7 +228,7 @@ export default class SummaryReporter extends BaseReporter {
|
|||
testInfo = chalk.dim(' within paths');
|
||||
} else if (globalConfig.onlyChanged) {
|
||||
testInfo = chalk.dim(' related to changed files');
|
||||
} else if (globalConfig.testPathPattern) {
|
||||
} else if (testPathPatterns.isSet()) {
|
||||
testInfo = getMatchingTestsInfo();
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ const now = Date.now;
|
|||
const write = process.stderr.write;
|
||||
const globalConfig = {
|
||||
rootDir: 'root',
|
||||
testPathPatterns: [],
|
||||
watch: false,
|
||||
};
|
||||
|
||||
|
|
|
@ -412,7 +412,7 @@ export type GlobalConfig = {
|
|||
errorOnDeprecated: boolean;
|
||||
testFailureExitCode: number;
|
||||
testNamePattern?: string;
|
||||
testPathPattern: string;
|
||||
testPathPatterns: Array<string>;
|
||||
testResultsProcessor?: string;
|
||||
testSequencer: string;
|
||||
testTimeout?: number;
|
||||
|
@ -569,7 +569,7 @@ export type Argv = Arguments<
|
|||
testMatch: Array<string>;
|
||||
testNamePattern: string;
|
||||
testPathIgnorePatterns: Array<string>;
|
||||
testPathPattern: Array<string>;
|
||||
testPathPatterns: Array<string>;
|
||||
testRegex: string | Array<string>;
|
||||
testResultsProcessor: string;
|
||||
testRunner: string;
|
||||
|
|
|
@ -78,9 +78,9 @@ Used to set properties with specified values within a global object. It is desig
|
|||
|
||||
It defines constants and conditional values for handling platform-specific behaviors in a terminal environment. It determines if the current platform is Windows ('win32') and sets up constants for various symbols and terminal screen clearing escape sequences accordingly, ensuring proper display and behavior on both Windows and non-Windows operating systems.
|
||||
|
||||
## `testPathPatternToRegExp`
|
||||
## `TestPathPatterns`
|
||||
|
||||
This function is used for consistency when serializing/deserializing global configurations and ensures that consistent regular expressions are produced for matching test paths.
|
||||
This class takes test patterns and provides the API for deciding if a test matches any of the patterns.
|
||||
|
||||
## `tryRealpath`
|
||||
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
/**
|
||||
* 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 type {Config} from '@jest/types';
|
||||
import {escapePathForRegex, replacePathSepForRegex} from 'jest-regex-util';
|
||||
|
||||
type PatternsConfig = {
|
||||
rootDir: string;
|
||||
};
|
||||
|
||||
export default class TestPathPatterns {
|
||||
private _regexString: string | null = null;
|
||||
|
||||
constructor(
|
||||
readonly patterns: Array<string>,
|
||||
private readonly config: PatternsConfig,
|
||||
) {}
|
||||
|
||||
static fromGlobalConfig(globalConfig: Config.GlobalConfig): TestPathPatterns {
|
||||
return new TestPathPatterns(globalConfig.testPathPatterns, globalConfig);
|
||||
}
|
||||
|
||||
private get regexString(): string {
|
||||
if (this._regexString !== null) {
|
||||
return this._regexString;
|
||||
}
|
||||
|
||||
const rootDir = this.config.rootDir.replace(/\/*$/, '/');
|
||||
const rootDirRegex = escapePathForRegex(rootDir);
|
||||
|
||||
const regexString = this.patterns
|
||||
.map(p => {
|
||||
// absolute paths passed on command line should stay same
|
||||
if (p.match(/^\//)) {
|
||||
return p;
|
||||
}
|
||||
|
||||
// explicit relative paths should resolve against rootDir
|
||||
if (p.match(/^\.\//)) {
|
||||
return p.replace(/^\.\//, rootDirRegex);
|
||||
}
|
||||
|
||||
// all other patterns should only match the relative part of the test
|
||||
return `${rootDirRegex}(.*)?${p}`;
|
||||
})
|
||||
.map(replacePathSepForRegex)
|
||||
.join('|');
|
||||
|
||||
this._regexString = regexString;
|
||||
return regexString;
|
||||
}
|
||||
|
||||
private toRegex(): RegExp {
|
||||
return new RegExp(this.regexString, 'i');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if there are any patterns.
|
||||
*/
|
||||
isSet(): boolean {
|
||||
return this.patterns.length > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Throw an error if the patterns don't form a valid regex.
|
||||
*/
|
||||
validate(): void {
|
||||
this.toRegex();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the given ABSOLUTE path matches the patterns.
|
||||
*
|
||||
* Throws an error if the patterns form an invalid regex (see `validate`).
|
||||
*/
|
||||
isMatch(path: string): boolean {
|
||||
return this.toRegex().test(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a human-friendly version of the pattern regex.
|
||||
*/
|
||||
toPretty(): string {
|
||||
return this.patterns.join('|');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,163 @@
|
|||
/**
|
||||
* 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 type * as path from 'path';
|
||||
import TestPathPatterns from '../TestPathPatterns';
|
||||
|
||||
const mockSep = jest.fn();
|
||||
jest.mock('path', () => {
|
||||
return {
|
||||
...(jest.requireActual('path') as typeof path),
|
||||
get sep() {
|
||||
return mockSep() || '/';
|
||||
},
|
||||
};
|
||||
});
|
||||
beforeEach(() => {
|
||||
jest.resetAllMocks();
|
||||
});
|
||||
|
||||
const config = {rootDir: ''};
|
||||
|
||||
describe('TestPathPatterns', () => {
|
||||
describe('isSet', () => {
|
||||
it('returns false if no patterns specified', () => {
|
||||
const testPathPatterns = new TestPathPatterns([], config);
|
||||
expect(testPathPatterns.isSet()).toBe(false);
|
||||
});
|
||||
|
||||
it('returns true if patterns specified', () => {
|
||||
const testPathPatterns = new TestPathPatterns(['a'], config);
|
||||
expect(testPathPatterns.isSet()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('validate', () => {
|
||||
it('succeeds for empty patterns', () => {
|
||||
const testPathPatterns = new TestPathPatterns([], config);
|
||||
expect(() => testPathPatterns.validate()).not.toThrow();
|
||||
});
|
||||
|
||||
it('succeeds for valid patterns', () => {
|
||||
const testPathPatterns = new TestPathPatterns(['abc+', 'z.*'], config);
|
||||
expect(() => testPathPatterns.validate()).not.toThrow();
|
||||
});
|
||||
|
||||
it('fails for at least one invalid pattern', () => {
|
||||
const testPathPatterns = new TestPathPatterns(
|
||||
['abc+', '(', 'z.*'],
|
||||
config,
|
||||
);
|
||||
expect(() => testPathPatterns.validate()).toThrow(
|
||||
'Invalid regular expression',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isMatch', () => {
|
||||
it('returns true with no patterns', () => {
|
||||
const testPathPatterns = new TestPathPatterns([], config);
|
||||
expect(testPathPatterns.isMatch('/a/b')).toBe(true);
|
||||
});
|
||||
|
||||
it('returns true for same path', () => {
|
||||
const testPathPatterns = new TestPathPatterns(['/a/b'], config);
|
||||
expect(testPathPatterns.isMatch('/a/b')).toBe(true);
|
||||
});
|
||||
|
||||
it('returns true for same path with case insensitive', () => {
|
||||
const testPathPatternsUpper = new TestPathPatterns(['/A/B'], config);
|
||||
expect(testPathPatternsUpper.isMatch('/a/b')).toBe(true);
|
||||
expect(testPathPatternsUpper.isMatch('/A/B')).toBe(true);
|
||||
|
||||
const testPathPatternsLower = new TestPathPatterns(['/a/b'], config);
|
||||
expect(testPathPatternsLower.isMatch('/A/B')).toBe(true);
|
||||
expect(testPathPatternsLower.isMatch('/a/b')).toBe(true);
|
||||
});
|
||||
|
||||
it('returns true for contained path', () => {
|
||||
const testPathPatterns = new TestPathPatterns(['b/c'], config);
|
||||
expect(testPathPatterns.isMatch('/a/b/c/d')).toBe(true);
|
||||
});
|
||||
|
||||
it('returns true for explicit relative path', () => {
|
||||
const testPathPatterns = new TestPathPatterns(['./b/c'], {
|
||||
rootDir: '/a',
|
||||
});
|
||||
expect(testPathPatterns.isMatch('/a/b/c')).toBe(true);
|
||||
});
|
||||
|
||||
it('returns true for partial file match', () => {
|
||||
const testPathPatterns = new TestPathPatterns(['aaa'], config);
|
||||
expect(testPathPatterns.isMatch('/foo/..aaa..')).toBe(true);
|
||||
expect(testPathPatterns.isMatch('/foo/..aaa')).toBe(true);
|
||||
expect(testPathPatterns.isMatch('/foo/aaa..')).toBe(true);
|
||||
});
|
||||
|
||||
it('returns true for path suffix', () => {
|
||||
const testPathPatterns = new TestPathPatterns(['c/d'], config);
|
||||
expect(testPathPatterns.isMatch('/a/b/c/d')).toBe(true);
|
||||
});
|
||||
|
||||
it('returns true if regex matches', () => {
|
||||
const testPathPatterns = new TestPathPatterns(['ab*c?'], config);
|
||||
|
||||
expect(testPathPatterns.isMatch('/foo/a')).toBe(true);
|
||||
expect(testPathPatterns.isMatch('/foo/ab')).toBe(true);
|
||||
expect(testPathPatterns.isMatch('/foo/abb')).toBe(true);
|
||||
expect(testPathPatterns.isMatch('/foo/ac')).toBe(true);
|
||||
expect(testPathPatterns.isMatch('/foo/abc')).toBe(true);
|
||||
expect(testPathPatterns.isMatch('/foo/abbc')).toBe(true);
|
||||
|
||||
expect(testPathPatterns.isMatch('/foo/bc')).toBe(false);
|
||||
});
|
||||
|
||||
it('returns true only if matches relative path', () => {
|
||||
const testPathPatterns = new TestPathPatterns(['home'], {
|
||||
rootDir: '/home/myuser/',
|
||||
});
|
||||
expect(testPathPatterns.isMatch('/home/myuser/LoginPage.js')).toBe(false);
|
||||
expect(testPathPatterns.isMatch('/home/myuser/HomePage.js')).toBe(true);
|
||||
});
|
||||
|
||||
it('matches absolute paths regardless of rootDir', () => {
|
||||
const testPathPatterns = new TestPathPatterns(['/a/b'], {
|
||||
rootDir: '/foo/bar',
|
||||
});
|
||||
expect(testPathPatterns.isMatch('/a/b')).toBe(true);
|
||||
});
|
||||
|
||||
it('returns true if match any paths', () => {
|
||||
const testPathPatterns = new TestPathPatterns(['a/b', 'c/d'], config);
|
||||
|
||||
expect(testPathPatterns.isMatch('/foo/a/b')).toBe(true);
|
||||
expect(testPathPatterns.isMatch('/foo/c/d')).toBe(true);
|
||||
|
||||
expect(testPathPatterns.isMatch('/foo/a')).toBe(false);
|
||||
expect(testPathPatterns.isMatch('/foo/b/c')).toBe(false);
|
||||
});
|
||||
|
||||
it('does not normalize Windows paths on POSIX', () => {
|
||||
mockSep.mockReturnValue('/');
|
||||
const testPathPatterns = new TestPathPatterns(['a\\z', 'a\\\\z'], config);
|
||||
expect(testPathPatterns.isMatch('/foo/a/z')).toBe(false);
|
||||
});
|
||||
|
||||
it('normalizes paths for Windows', () => {
|
||||
mockSep.mockReturnValue('\\');
|
||||
const testPathPatterns = new TestPathPatterns(['a/b'], config);
|
||||
expect(testPathPatterns.isMatch('\\foo\\a\\b')).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('toPretty', () => {
|
||||
it('renders a human-readable string', () => {
|
||||
const testPathPatterns = new TestPathPatterns(['a/b', 'c/d'], config);
|
||||
expect(testPathPatterns.toPretty()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,3 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`TestPathPatterns toPretty renders a human-readable string 1`] = `"a/b|c/d"`;
|
|
@ -21,7 +21,7 @@ export {default as deepCyclicCopy} from './deepCyclicCopy';
|
|||
export {default as convertDescriptorToString} from './convertDescriptorToString';
|
||||
export {specialChars};
|
||||
export {default as replacePathSepForGlob} from './replacePathSepForGlob';
|
||||
export {default as testPathPatternToRegExp} from './testPathPatternToRegExp';
|
||||
export {default as TestPathPatterns} from './TestPathPatterns';
|
||||
export {default as globsToMatcher} from './globsToMatcher';
|
||||
export {preRunMessage};
|
||||
export {default as pluralize} from './pluralize';
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
/**
|
||||
* 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 type {Config} from '@jest/types';
|
||||
|
||||
// Because we serialize/deserialize globalConfig when we spawn workers,
|
||||
// we can't pass regular expression. Using this shared function on both sides
|
||||
// will ensure that we produce consistent regexp for testPathPattern.
|
||||
export default function testPathPatternToRegExp(
|
||||
testPathPattern: Config.GlobalConfig['testPathPattern'],
|
||||
): RegExp {
|
||||
return new RegExp(testPathPattern, 'i');
|
||||
}
|
|
@ -62,7 +62,7 @@ export type AllowedConfigOptions = Partial<
|
|||
| 'onlyFailures'
|
||||
| 'reporters'
|
||||
| 'testNamePattern'
|
||||
| 'testPathPattern'
|
||||
| 'testPathPatterns'
|
||||
| 'updateSnapshot'
|
||||
| 'verbose'
|
||||
> & {mode: 'watch' | 'watchAll'}
|
||||
|
|
|
@ -55,7 +55,7 @@ const DEFAULT_GLOBAL_CONFIG: Config.GlobalConfig = {
|
|||
snapshotFormat: {},
|
||||
testFailureExitCode: 1,
|
||||
testNamePattern: '',
|
||||
testPathPattern: '',
|
||||
testPathPatterns: [],
|
||||
testResultsProcessor: undefined,
|
||||
testSequencer: '@jest/test-sequencer',
|
||||
testTimeout: 5000,
|
||||
|
|
Loading…
Reference in New Issue