diff --git a/integration_tests/__tests__/__snapshots__/show_config.test.js.snap b/integration_tests/__tests__/__snapshots__/show_config.test.js.snap index c0cc76370e97..c4f023851bac 100644 --- a/integration_tests/__tests__/__snapshots__/show_config.test.js.snap +++ b/integration_tests/__tests__/__snapshots__/show_config.test.js.snap @@ -51,7 +51,8 @@ exports[`--showConfig outputs config info and exits 1`] = ` \\"timers\\": \\"real\\", \\"transformIgnorePatterns\\": [ \\"/node_modules/\\" - ] + ], + \\"watchPathIgnorePatterns\\": [] } ], \\"globalConfig\\": { diff --git a/packages/jest-cli/src/cli/args.js b/packages/jest-cli/src/cli/args.js index aacc6265b864..2bf27d2a39a9 100644 --- a/packages/jest-cli/src/cli/args.js +++ b/packages/jest-cli/src/cli/args.js @@ -542,6 +542,13 @@ const options = { '`--watch` option.', type: 'boolean', }, + watchPathIgnorePatterns: { + description: + 'An array of regexp pattern strings that are matched ' + + 'against all paths before trigger test re-run in watch mode. ' + + 'If the test path matches any of the patterns, it will be skipped.', + type: 'array', + }, watchman: { default: undefined, description: diff --git a/packages/jest-cli/src/lib/__tests__/is_valid_path.test.js b/packages/jest-cli/src/lib/__tests__/is_valid_path.test.js index 270f2ca82d87..c234583a3971 100644 --- a/packages/jest-cli/src/lib/__tests__/is_valid_path.test.js +++ b/packages/jest-cli/src/lib/__tests__/is_valid_path.test.js @@ -20,6 +20,7 @@ const rootDir = path.resolve(path.sep, 'root'); const config = makeProjectConfig({ rootDir, roots: [path.resolve(rootDir, 'src'), path.resolve(rootDir, 'lib')], + watchPathIgnorePatterns: ['pacts/'], }); it('is valid when it is a file inside roots', () => { @@ -87,3 +88,13 @@ it('is not valid when it is a file in the coverage dir', () => { ), ).toBe(false); }); + +it('is not valid when it is a file match one of the watchPathIgnorePatterns', () => { + expect( + isValidPath( + makeGlobalConfig({rootDir}), + config, + path.resolve(rootDir, 'pacts', 'todoapp-todoservice.json'), + ), + ).toBe(false); +}); diff --git a/packages/jest-cli/src/lib/is_valid_path.js b/packages/jest-cli/src/lib/is_valid_path.js index 15e5ca51553a..54ce5f21a548 100644 --- a/packages/jest-cli/src/lib/is_valid_path.js +++ b/packages/jest-cli/src/lib/is_valid_path.js @@ -19,6 +19,7 @@ function isValidPath( ) { return ( !filePath.includes(globalConfig.coverageDirectory) && + !config.watchPathIgnorePatterns.some(pattern => filePath.match(pattern)) && !filePath.endsWith(`.${SNAPSHOT_EXTENSION}`) ); } diff --git a/packages/jest-config/src/__tests__/normalize.test.js b/packages/jest-config/src/__tests__/normalize.test.js index 956f1da06910..57812320784f 100644 --- a/packages/jest-config/src/__tests__/normalize.test.js +++ b/packages/jest-config/src/__tests__/normalize.test.js @@ -383,6 +383,57 @@ describe('coveragePathIgnorePatterns', () => { }); }); +describe('watchPathIgnorePatterns', () => { + it('does not normalize paths relative to rootDir', () => { + // This is a list of patterns, so we can't assume any of them are + // directories + const {options} = normalize( + { + rootDir: '/root/path/foo', + watchPathIgnorePatterns: ['bar/baz', 'qux/quux'], + }, + {}, + ); + + expect(options.watchPathIgnorePatterns).toEqual([ + joinForPattern('bar', 'baz'), + joinForPattern('qux', 'quux'), + ]); + }); + + it('does not normalize trailing slashes', () => { + // This is a list of patterns, so we can't assume any of them are + // directories + const {options} = normalize( + { + rootDir: '/root/path/foo', + watchPathIgnorePatterns: ['bar/baz', 'qux/quux/'], + }, + {}, + ); + + expect(options.watchPathIgnorePatterns).toEqual([ + joinForPattern('bar', 'baz'), + joinForPattern('qux', 'quux', ''), + ]); + }); + + it('substitutes tokens', () => { + const {options} = normalize( + { + rootDir: '/root/path/foo', + watchPathIgnorePatterns: ['hasNoToken', '/hasAToken'], + }, + {}, + ); + + expect(options.watchPathIgnorePatterns).toEqual([ + 'hasNoToken', + joinForPattern('', 'root', 'path', 'foo', 'hasAToken'), + ]); + }); +}); + describe('testPathIgnorePatterns', () => { it('does not normalize paths relative to rootDir', () => { // This is a list of patterns, so we can't assume any of them are diff --git a/packages/jest-config/src/defaults.js b/packages/jest-config/src/defaults.js index 08c098309685..5053a35f4bb2 100644 --- a/packages/jest-config/src/defaults.js +++ b/packages/jest-config/src/defaults.js @@ -66,5 +66,6 @@ module.exports = ({ useStderr: false, verbose: null, watch: false, + watchPathIgnorePatterns: [], watchman: true, }: DefaultOptions); diff --git a/packages/jest-config/src/index.js b/packages/jest-config/src/index.js index d5ff0416e7c6..decf9f41ab5b 100644 --- a/packages/jest-config/src/index.js +++ b/packages/jest-config/src/index.js @@ -149,6 +149,7 @@ const getConfigs = ( transform: options.transform, transformIgnorePatterns: options.transformIgnorePatterns, unmockedModulePathPatterns: options.unmockedModulePathPatterns, + watchPathIgnorePatterns: options.watchPathIgnorePatterns, }), }; }; diff --git a/packages/jest-config/src/normalize.js b/packages/jest-config/src/normalize.js index 6bf35faca52c..c823adc13602 100644 --- a/packages/jest-config/src/normalize.js +++ b/packages/jest-config/src/normalize.js @@ -415,6 +415,7 @@ function normalize(options: InitialOptions, argv: Argv) { case 'modulePathIgnorePatterns': case 'testPathIgnorePatterns': case 'transformIgnorePatterns': + case 'watchPathIgnorePatterns': case 'unmockedModulePathPatterns': value = normalizeUnmockedModulePathPatterns(options, key); break; diff --git a/packages/jest-config/src/valid_config.js b/packages/jest-config/src/valid_config.js index 448336755176..0aa0f32e9a47 100644 --- a/packages/jest-config/src/valid_config.js +++ b/packages/jest-config/src/valid_config.js @@ -94,5 +94,6 @@ module.exports = ({ useStderr: false, verbose: false, watch: false, + watchPathIgnorePatterns: [], watchman: true, }: InitialOptions); diff --git a/packages/jest-validate/src/__tests__/fixtures/jest_config.js b/packages/jest-validate/src/__tests__/fixtures/jest_config.js index 3bdf3db011c2..e57191c922e1 100644 --- a/packages/jest-validate/src/__tests__/fixtures/jest_config.js +++ b/packages/jest-validate/src/__tests__/fixtures/jest_config.js @@ -55,6 +55,7 @@ const defaultConfig = { useStderr: false, verbose: null, watch: false, + watchPathIgnorePatterns: [], }; const validConfig = { diff --git a/test_utils.js b/test_utils.js index 82f55427b889..9468a9ceb682 100644 --- a/test_utils.js +++ b/test_utils.js @@ -91,6 +91,7 @@ const DEFAULT_PROJECT_CONFIG: ProjectConfig = { transform: [], transformIgnorePatterns: [], unmockedModulePathPatterns: null, + watchPathIgnorePatterns: [], }; const makeGlobalConfig = (overrides: Object = {}): GlobalConfig => { diff --git a/types/Argv.js b/types/Argv.js index 2c61efa2db67..fbb5f0ee9e36 100644 --- a/types/Argv.js +++ b/types/Argv.js @@ -78,6 +78,7 @@ export type Argv = {| timers: 'real' | 'fake', transform: string, transformIgnorePatterns: Array, + watchPathIgnorePatterns: Array, unmockedModulePathPatterns: ?Array, updateSnapshot: boolean, useStderr: boolean, diff --git a/types/Config.js b/types/Config.js index 8d17d4b06ced..47ab2ac9c116 100644 --- a/types/Config.js +++ b/types/Config.js @@ -55,6 +55,7 @@ export type DefaultOptions = {| testURL: string, timers: 'real' | 'fake', transformIgnorePatterns: Array, + watchPathIgnorePatterns: Array, useStderr: boolean, verbose: ?boolean, watch: boolean, @@ -126,6 +127,7 @@ export type InitialOptions = { timers?: 'real' | 'fake', transform?: {[key: string]: string}, transformIgnorePatterns?: Array, + watchPathIgnorePatterns?: Array, unmockedModulePathPatterns?: Array, updateSnapshot?: boolean, useStderr?: boolean, @@ -213,5 +215,6 @@ export type ProjectConfig = {| timers: 'real' | 'fake', transform: Array<[string, Path]>, transformIgnorePatterns: Array, + watchPathIgnorePatterns: Array, unmockedModulePathPatterns: ?Array, |};