From fb5b31d1435e0d56a3301b1032a4a53dbca3e64e Mon Sep 17 00:00:00 2001 From: Jamie Treworgy Date: Thu, 18 Oct 2018 09:40:22 -0400 Subject: [PATCH] Allow array of regexp strings for testRegex --- .vscode/settings.json | 6 ++- CHANGELOG.md | 1 + TestUtils.js | 2 +- docs/Configuration.md | 6 +-- .../__snapshots__/show_config.test.js.snap | 2 +- packages/jest-cli/src/SearchSource.js | 9 ++--- .../src/__tests__/runJestWithCoverage.test.js | 2 +- packages/jest-cli/src/__tests__/watch.test.js | 2 +- packages/jest-cli/src/cli/args.js | 5 ++- .../__tests__/__snapshots__/init.test.js.snap | 4 +- packages/jest-config/src/Defaults.js | 2 +- packages/jest-config/src/Descriptions.js | 3 +- packages/jest-config/src/ValidConfig.js | 7 +++- .../src/__tests__/normalize.test.js | 38 ++++++++++++++++++- packages/jest-config/src/normalize.js | 10 +++-- packages/jest-editor-support/src/Settings.js | 4 +- .../src/__tests__/should_instrument.test.js | 18 +++++++-- .../jest-runtime/src/should_instrument.js | 5 ++- types/Argv.js | 2 +- types/Config.js | 6 +-- 20 files changed, 99 insertions(+), 35 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index c4951686b125..0b867bdd9628 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,11 +1,13 @@ { - "editor.rulers": [80], + "editor.rulers": [ + 80 + ], "files.exclude": { "**/.git": true, "**/node_modules": true, "**/build": true }, - "editor.formatOnSave": true, + "editor.formatOnSave": false, "flow.useNPMPackagedFlow": true, "javascript.validate.enable": false, "jest.pathToJest": "yarn jest --", diff --git a/CHANGELOG.md b/CHANGELOG.md index a0d426b17566..6f44e009c9d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ - `[jest-haste-map]` Make `ignorePattern` optional ([#7166](https://github.com/facebook/jest/pull/7166)) - `[jest-runtime]` Remove `cacheDirectory` from `ignorePattern` for `HasteMap` if not necessary ([#7166](https://github.com/facebook/jest/pull/7166)) - `[jest-validate]` Add syntax to validate multiple permitted types +- `[jest-config]` Accept an array as as well as a string for `testRegex` ### Fixes diff --git a/TestUtils.js b/TestUtils.js index 3cd6e43ecb3e..c179cc13a9de 100644 --- a/TestUtils.js +++ b/TestUtils.js @@ -109,7 +109,7 @@ const DEFAULT_PROJECT_CONFIG: ProjectConfig = { testLocationInResults: false, testMatch: [], testPathIgnorePatterns: [], - testRegex: '.test.js$', + testRegex: ['.test.js$'], testRunner: 'jest-jasmine2', testURL: '', timers: 'real', diff --git a/docs/Configuration.md b/docs/Configuration.md index 4cb938e87af2..bef4ec88cbbd 100644 --- a/docs/Configuration.md +++ b/docs/Configuration.md @@ -804,7 +804,7 @@ The glob patterns Jest uses to detect test files. By default it looks for `.js` See the [micromatch](https://github.com/jonschlinkert/micromatch) package for details of the patterns you can specify. -See also [`testRegex` [string]](#testregex-string), but note that you cannot specify both options. +See also [`testRegex` [string | Array]](#testregex-string), but note that you cannot specify both options. ### `testPathIgnorePatterns` [array] @@ -814,11 +814,11 @@ An array of regexp pattern strings that are matched against all test paths befor These pattern strings match against the full path. Use the `` string token to include the path to your project's root directory to prevent it from accidentally ignoring all of your files in different environments that may have different root directories. Example: `["/build/", "/node_modules/"]`. -### `testRegex` [string] +### `testRegex` [string | Array] Default: `(/__tests__/.*|(\\.|/)(test|spec))\\.jsx?$` -The pattern Jest uses to detect test files. By default it looks for `.js` and `.jsx` files inside of `__tests__` folders, as well as any files with a suffix of `.test` or `.spec` (e.g. `Component.test.js` or `Component.spec.js`). It will also find files called `test.js` or `spec.js`. See also [`testMatch` [array]](#testmatch-array-string), but note that you cannot specify both options. +The pattern or patterns Jest uses to detect test files. By default it looks for `.js` and `.jsx` files inside of `__tests__` folders, as well as any files with a suffix of `.test` or `.spec` (e.g. `Component.test.js` or `Component.spec.js`). It will also find files called `test.js` or `spec.js`. See also [`testMatch` [array]](#testmatch-array-string), but note that you cannot specify both options. The following is a visualization of the default regex: diff --git a/e2e/__tests__/__snapshots__/show_config.test.js.snap b/e2e/__tests__/__snapshots__/show_config.test.js.snap index 64bb26ca8e28..2e4b59ee8531 100644 --- a/e2e/__tests__/__snapshots__/show_config.test.js.snap +++ b/e2e/__tests__/__snapshots__/show_config.test.js.snap @@ -58,7 +58,7 @@ exports[`--showConfig outputs config info and exits 1`] = ` \\"testPathIgnorePatterns\\": [ \\"/node_modules/\\" ], - \\"testRegex\\": \\"\\", + \\"testRegex\\": [], \\"testRunner\\": \\"<>/jest-jasmine2/build/index.js\\", \\"testURL\\": \\"http://localhost\\", \\"timers\\": \\"real\\", diff --git a/packages/jest-cli/src/SearchSource.js b/packages/jest-cli/src/SearchSource.js index 020425067b5a..91c93e1d2ac5 100644 --- a/packages/jest-cli/src/SearchSource.js +++ b/packages/jest-cli/src/SearchSource.js @@ -51,13 +51,12 @@ const globsToMatcher = (globs: ?Array) => { return path => micromatch([path], globs, {dot: true}).length > 0; }; -const regexToMatcher = (testRegex: string) => { - if (!testRegex) { +const regexToMatcher = (testRegex: Array) => { + if (!testRegex.length) { return () => true; } - - const regex = new RegExp(testRegex); - return path => regex.test(path); + const testRegexParsed = testRegex.map(e => new RegExp(e)); + return path => testRegexParsed.some(e => e.test(path)); }; const toTests = (context, tests) => diff --git a/packages/jest-cli/src/__tests__/runJestWithCoverage.test.js b/packages/jest-cli/src/__tests__/runJestWithCoverage.test.js index 4081497655ba..247fcf2c7b11 100644 --- a/packages/jest-cli/src/__tests__/runJestWithCoverage.test.js +++ b/packages/jest-cli/src/__tests__/runJestWithCoverage.test.js @@ -51,7 +51,7 @@ jest.mock( }, ); -const config = {roots: [], testPathIgnorePatterns: [], testRegex: ''}; +const config = {roots: [], testPathIgnorePatterns: [], testRegex: []}; let globalConfig; const defaults = { changedFilesPromise: Promise.resolve({ diff --git a/packages/jest-cli/src/__tests__/watch.test.js b/packages/jest-cli/src/__tests__/watch.test.js index 3607381f684d..4acc234db99e 100644 --- a/packages/jest-cli/src/__tests__/watch.test.js +++ b/packages/jest-cli/src/__tests__/watch.test.js @@ -105,7 +105,7 @@ describe('Watch mode flows', () => { let stdin; beforeEach(() => { - const config = {roots: [], testPathIgnorePatterns: [], testRegex: ''}; + const config = {roots: [], testPathIgnorePatterns: [], testRegex: []}; pipe = {write: jest.fn()}; globalConfig = {watch: true}; hasteMapInstances = [{on: () => {}}]; diff --git a/packages/jest-cli/src/cli/args.js b/packages/jest-cli/src/cli/args.js index c758ff14e56e..b374adeba2ef 100644 --- a/packages/jest-cli/src/cli/args.js +++ b/packages/jest-cli/src/cli/args.js @@ -576,8 +576,9 @@ export const options = { type: 'array', }, testRegex: { - description: 'The regexp pattern Jest uses to detect test files.', - type: 'string', + description: + 'A string or array of string regexp patterns that Jest uses to detect test files.', + type: 'array', }, testResultsProcessor: { description: diff --git a/packages/jest-cli/src/lib/__tests__/__snapshots__/init.test.js.snap b/packages/jest-cli/src/lib/__tests__/__snapshots__/init.test.js.snap index adf63d20d15c..9ec33fc8447b 100644 --- a/packages/jest-cli/src/lib/__tests__/__snapshots__/init.test.js.snap +++ b/packages/jest-cli/src/lib/__tests__/__snapshots__/init.test.js.snap @@ -164,8 +164,8 @@ module.exports = { // \\"/node_modules/\\" // ], - // The regexp pattern Jest uses to detect test files - // testRegex: \\"\\", + // The regexp pattern or array of patterns that Jest uses to detect test files + // testRegex: [], // This option allows the use of a custom results processor // testResultsProcessor: null, diff --git a/packages/jest-config/src/Defaults.js b/packages/jest-config/src/Defaults.js index fefe239a189a..1b549e1059e1 100644 --- a/packages/jest-config/src/Defaults.js +++ b/packages/jest-config/src/Defaults.js @@ -70,7 +70,7 @@ export default ({ testLocationInResults: false, testMatch: ['**/__tests__/**/*.js?(x)', '**/?(*.)+(spec|test).js?(x)'], testPathIgnorePatterns: [NODE_MODULES_REGEXP], - testRegex: '', + testRegex: [], testResultsProcessor: null, testRunner: 'jasmine2', testURL: 'http://localhost', diff --git a/packages/jest-config/src/Descriptions.js b/packages/jest-config/src/Descriptions.js index fc8cafb8e785..6989be5e1dad 100644 --- a/packages/jest-config/src/Descriptions.js +++ b/packages/jest-config/src/Descriptions.js @@ -71,7 +71,8 @@ export default ({ testMatch: 'The glob patterns Jest uses to detect test files', testPathIgnorePatterns: 'An array of regexp pattern strings that are matched against all test paths, matched tests are skipped', - testRegex: 'The regexp pattern Jest uses to detect test files', + testRegex: + 'The regexp pattern or array of patterns that Jest uses to detect test files', testResultsProcessor: 'This option allows the use of a custom results processor', testRunner: 'This option allows use of a custom test runner', diff --git a/packages/jest-config/src/ValidConfig.js b/packages/jest-config/src/ValidConfig.js index edd84404cff3..5adea130ea24 100644 --- a/packages/jest-config/src/ValidConfig.js +++ b/packages/jest-config/src/ValidConfig.js @@ -10,6 +10,7 @@ import type {InitialOptions} from 'types/Config'; import {replacePathSepForRegex} from 'jest-regex-util'; +import {MultipleValidOptions} from 'jest-validate'; import {NODE_MODULES} from './constants'; const NODE_MODULES_REGEXP = replacePathSepForRegex(NODE_MODULES); @@ -100,7 +101,11 @@ export default ({ testMatch: ['**/__tests__/**/*.js?(x)', '**/?(*.)+(spec|test).js?(x)'], testNamePattern: 'test signature', testPathIgnorePatterns: [NODE_MODULES_REGEXP], - testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.jsx?$', + testRegex: ([ + MultipleValidOptions, + '(/__tests__/.*|(\\.|/)(test|spec))\\.jsx?$', + [], + ]: any), testResultsProcessor: 'processor-node-module', testRunner: 'jasmine2', testURL: 'http://localhost', diff --git a/packages/jest-config/src/__tests__/normalize.test.js b/packages/jest-config/src/__tests__/normalize.test.js index 801ab1f0318b..e39f98ee48d5 100644 --- a/packages/jest-config/src/__tests__/normalize.test.js +++ b/packages/jest-config/src/__tests__/normalize.test.js @@ -804,6 +804,42 @@ describe('Upgrade help', () => { }); }); +describe('testRegex', () => { + it('testRegex empty string is mapped to empty array', () => { + const {options} = normalize( + { + rootDir: '/root', + testRegex: '', + }, + {}, + ); + + expect(options.testRegex).toEqual([]); + }); + it('testRegex string is mapped to array', () => { + const {options} = normalize( + { + rootDir: '/root', + testRegex: '.*', + }, + {}, + ); + + expect(options.testRegex).toEqual(['.*']); + }); + it('testRegex array is passed through', () => { + const {options} = normalize( + { + rootDir: '/root', + testRegex: ['.*'], + }, + {}, + ); + + expect(options.testRegex).toEqual(['.*']); + }); +}); + describe('testMatch', () => { it('testMatch default not applied if testRegex is set', () => { const {options} = normalize( @@ -826,7 +862,7 @@ describe('testMatch', () => { {}, ); - expect(options.testRegex).toBe(''); + expect(options.testRegex).toEqual([]); }); it('throws if testRegex and testMatch are both specified', () => { diff --git a/packages/jest-config/src/normalize.js b/packages/jest-config/src/normalize.js index a7da8a1a41d7..36c4f01a36ca 100644 --- a/packages/jest-config/src/normalize.js +++ b/packages/jest-config/src/normalize.js @@ -547,7 +547,11 @@ export default function normalize(options: InitialOptions, argv: Argv) { ); break; case 'testRegex': - value = options[key] && replacePathSepForRegex(options[key]); + const valueOrEmptyArray = options[key] || []; + const valueArray = Array.isArray(valueOrEmptyArray) + ? valueOrEmptyArray + : [valueOrEmptyArray]; + value = valueArray.map(replacePathSepForRegex); break; case 'moduleFileExtensions': { value = options[key]; @@ -701,14 +705,14 @@ export default function normalize(options: InitialOptions, argv: Argv) { } } - if (options.testRegex && options.testMatch) { + if (newOptions.testRegex.length && options.testMatch) { throw createConfigError( ` Configuration options ${chalk.bold('testMatch')} and` + ` ${chalk.bold('testRegex')} cannot be used together.`, ); } - if (options.testRegex && !options.testMatch) { + if (newOptions.testRegex.length && !options.testMatch) { // Prevent the default testMatch conflicting with any explicitly // configured `testRegex` value newOptions.testMatch = []; diff --git a/packages/jest-editor-support/src/Settings.js b/packages/jest-editor-support/src/Settings.js index d9cac96c91a4..d11da69ab998 100644 --- a/packages/jest-editor-support/src/Settings.js +++ b/packages/jest-editor-support/src/Settings.js @@ -28,7 +28,7 @@ import {createProcess} from './Process'; type Glob = string; type ConfigRepresentation = { - testRegex: string, + testRegex: string | Array, testMatch: Array, }; @@ -59,7 +59,7 @@ export default class Settings extends EventEmitter { // Defaults for a Jest project this.settings = { testMatch: ['**/__tests__/**/*.js?(x)', '**/?(*.)+(spec|test).js?(x)'], - testRegex: '(/__tests__/.*|\\.(test|spec))\\.jsx?$', + testRegex: ['(/__tests__/.*|\\.(test|spec))\\.jsx?$'], }; this.configs = [this.settings]; diff --git a/packages/jest-runtime/src/__tests__/should_instrument.test.js b/packages/jest-runtime/src/__tests__/should_instrument.test.js index a6891c48f15d..47d84a96994e 100644 --- a/packages/jest-runtime/src/__tests__/should_instrument.test.js +++ b/packages/jest-runtime/src/__tests__/should_instrument.test.js @@ -29,7 +29,13 @@ describe('should_instrument', () => { it('when testRegex provided and file is not a test file', () => { testShouldInstrument('source_file.js', defaultOptions, { - testRegex: '.*\\.(test)\\.(js)$', + testRegex: ['.*\\.(test)\\.(js)$'], + }); + }); + + it('when more than one testRegex is provided and filename is not a test file', () => { + testShouldInstrument('source_file.js', defaultOptions, { + testRegex: ['.*\\_(test)\\.(js)$', '.*\\.(test)\\.(js)$', 'never'], }); }); @@ -88,7 +94,7 @@ describe('should_instrument', () => { testShouldInstrument('do/collect/sum.coverage.test.js', defaultOptions, { forceCoverageMatch: ['**/*.(coverage).(test).js'], rootDir: '/', - testRegex: '.*\\.(test)\\.(js)$', + testRegex: ['.*\\.(test)\\.(js)$'], }); }); }); @@ -115,7 +121,13 @@ describe('should_instrument', () => { it('when testRegex provided and filename is a test file', () => { testShouldInstrument(defaultFilename, defaultOptions, { - testRegex: '.*\\.(test)\\.(js)$', + testRegex: ['.*\\.(test)\\.(js)$'], + }); + }); + + it('when more than one testRegex is provided and filename matches one of the patterns', () => { + testShouldInstrument(defaultFilename, defaultOptions, { + testRegex: ['.*\\_(test)\\.(js)$', '.*\\.(test)\\.(js)$', 'never'], }); }); diff --git a/packages/jest-runtime/src/should_instrument.js b/packages/jest-runtime/src/should_instrument.js index 7d9f76e6ee90..a0b300c56abe 100644 --- a/packages/jest-runtime/src/should_instrument.js +++ b/packages/jest-runtime/src/should_instrument.js @@ -35,7 +35,10 @@ export default function shouldInstrument( return true; } - if (config.testRegex && filename.match(config.testRegex)) { + if ( + config.testRegex && + config.testRegex.some(regex => filename.match(regex)) + ) { return false; } diff --git a/types/Argv.js b/types/Argv.js index ef157f155dfd..cc552d883996 100644 --- a/types/Argv.js +++ b/types/Argv.js @@ -81,7 +81,7 @@ export type Argv = {| testNamePattern: string, testPathIgnorePatterns: Array, testPathPattern: Array, - testRegex: string, + testRegex: string | Array, testResultsProcessor: ?string, testRunner: string, testURL: string, diff --git a/types/Config.js b/types/Config.js index b08323e950bb..53d6577a0a24 100644 --- a/types/Config.js +++ b/types/Config.js @@ -74,7 +74,7 @@ export type DefaultOptions = {| testLocationInResults: boolean, testMatch: Array, testPathIgnorePatterns: Array, - testRegex: string, + testRegex: Array, testResultsProcessor: ?string, testRunner: ?string, testURL: string, @@ -165,7 +165,7 @@ export type InitialOptions = { testNamePattern?: string, testPathDirs?: Array, testPathIgnorePatterns?: Array, - testRegex?: string, + testRegex?: string | Array, testResultsProcessor?: ?string, testRunner?: string, testURL?: string, @@ -282,7 +282,7 @@ export type ProjectConfig = {| testMatch: Array, testLocationInResults: boolean, testPathIgnorePatterns: Array, - testRegex: string, + testRegex: Array, testRunner: string, testURL: string, timers: 'real' | 'fake',