diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d66593d8068..6511d5f559a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -55,6 +55,7 @@ - `[jest-runtime]` Fix transform cache invalidation when requiring a test file from multiple projects ([#7186](https://github.com/facebook/jest/pull/7186)) - `[jest-changed-files]` Return correctly the changed files when using `lastCommit=true` on Mercurial repositories ([#7228](https://github.com/facebook/jest/pull/7228)) - `[babel-jest]` Cache includes babel environment variables ([#7239](https://github.com/facebook/jest/pull/7239)) +- `[jest-config]` Use strings instead of `RegExp` instances in normalized configuration ([#7251](https://github.com/facebook/jest/pull/7251)) ### Chore & Maintenance diff --git a/TestUtils.js b/TestUtils.js index a65743e66145..3734d8ec5a55 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/e2e/__tests__/__snapshots__/coverage_report.test.js.snap b/e2e/__tests__/__snapshots__/coverage_report.test.js.snap index 0e2fae8499c8..e741fd69db6a 100644 --- a/e2e/__tests__/__snapshots__/coverage_report.test.js.snap +++ b/e2e/__tests__/__snapshots__/coverage_report.test.js.snap @@ -42,6 +42,23 @@ All files | 85.71 | 100 | 50 | 100 | | exports[`does not output coverage report when html is requested 1`] = `""`; +exports[`generates coverage when using the testRegex config param 1`] = ` +"-------------------------------------|----------|----------|----------|----------|-------------------| +File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s | +-------------------------------------|----------|----------|----------|----------|-------------------| +All files | 56.52 | 0 | 50 | 55.56 | | + coverage-report | 41.18 | 0 | 25 | 42.86 | | + OtherFile.js | 100 | 100 | 100 | 100 | | + Sum.js | 85.71 | 100 | 50 | 100 | | + SumDependency.js | 0 | 0 | 0 | 0 | 8,10,12 | + notRequiredInTestSuite.js | 0 | 0 | 0 | 0 | 8,15,16,17,19 | + coverage-report/cached-duplicates/a | 100 | 100 | 100 | 100 | | + Identical.js | 100 | 100 | 100 | 100 | | + coverage-report/cached-duplicates/b | 100 | 100 | 100 | 100 | | + Identical.js | 100 | 100 | 100 | 100 | | +-------------------------------------|----------|----------|----------|----------|-------------------|" +`; + exports[`json reporter printing with --coverage 1`] = ` "Test Suites: 1 failed, 1 total Tests: 1 failed, 2 passed, 3 total diff --git a/e2e/__tests__/coverage_report.test.js b/e2e/__tests__/coverage_report.test.js index 66bbbd19d064..d12b0f2f7b3a 100644 --- a/e2e/__tests__/coverage_report.test.js +++ b/e2e/__tests__/coverage_report.test.js @@ -185,3 +185,13 @@ test('collects coverage from duplicate files avoiding shared cache', () => { expect(stdout).toMatchSnapshot(); expect(status).toBe(0); }); + +test('generates coverage when using the testRegex config param ', () => { + const {stdout, status} = runJest(DIR, [ + '--no-cache', + '--testRegex=__tests__', + '--coverage', + ]); + expect(stdout).toMatchSnapshot(); + expect(status).toBe(0); +}); diff --git a/packages/jest-cli/src/SearchSource.js b/packages/jest-cli/src/SearchSource.js index af000440a0c0..dae434cf7b41 100644 --- a/packages/jest-cli/src/SearchSource.js +++ b/packages/jest-cli/src/SearchSource.js @@ -51,12 +51,12 @@ const globsToMatcher = (globs: ?Array) => { return path => micromatch([path], globs, {dot: true}).length > 0; }; -const regexToMatcher = (testRegex: Array) => { +const regexToMatcher = (testRegex: Array) => { if (!testRegex.length) { return () => true; } - return path => testRegex.some(e => e.test(path)); + return path => testRegex.some(testRegex => new RegExp(testRegex).test(path)); }; const toTests = (context, tests) => diff --git a/packages/jest-cli/src/__tests__/generateEmptyCoverage.test.js b/packages/jest-cli/src/__tests__/generateEmptyCoverage.test.js index fe69dc6a43f4..8245f914e312 100644 --- a/packages/jest-cli/src/__tests__/generateEmptyCoverage.test.js +++ b/packages/jest-cli/src/__tests__/generateEmptyCoverage.test.js @@ -14,7 +14,6 @@ const os = require('os'); const {makeGlobalConfig, makeProjectConfig} = require('../../../../TestUtils'); jest.mock('jest-runtime', () => { - // $FlowFixMe requireActual const realRuntime = jest.requireActual('jest-runtime'); realRuntime.shouldInstrument = () => true; return realRuntime; diff --git a/packages/jest-config/src/ValidConfig.js b/packages/jest-config/src/ValidConfig.js index 608dc770ab76..cb732dc76555 100644 --- a/packages/jest-config/src/ValidConfig.js +++ b/packages/jest-config/src/ValidConfig.js @@ -10,7 +10,7 @@ import type {InitialOptions} from 'types/Config'; import {replacePathSepForRegex} from 'jest-regex-util'; -import {MultipleValidOptions} from 'jest-validate'; +import {multipleValidOptions} from 'jest-validate'; import {NODE_MODULES} from './constants'; const NODE_MODULES_REGEXP = replacePathSepForRegex(NODE_MODULES); @@ -101,7 +101,7 @@ export default ({ testMatch: ['**/__tests__/**/*.js?(x)', '**/?(*.)+(spec|test).js?(x)'], testNamePattern: 'test signature', testPathIgnorePatterns: [NODE_MODULES_REGEXP], - testRegex: MultipleValidOptions( + testRegex: multipleValidOptions( '(/__tests__/.*|(\\.|/)(test|spec))\\.jsx?$', ['/__tests__/\\.test\\.jsx?$', '/__tests__/\\.spec\\.jsx?$'], ), diff --git a/packages/jest-config/src/__tests__/__snapshots__/normalize.test.js.snap b/packages/jest-config/src/__tests__/__snapshots__/normalize.test.js.snap index 9eb36c229fa6..c8edc2f5911b 100644 --- a/packages/jest-config/src/__tests__/__snapshots__/normalize.test.js.snap +++ b/packages/jest-config/src/__tests__/__snapshots__/normalize.test.js.snap @@ -90,17 +90,6 @@ exports[`testMatch throws if testRegex and testMatch are both specified 1`] = ` " `; -exports[`testMatch throws if testRegex is provided an invalid regex string 1`] = ` -"Validation Error: - -Error parsing configuration for testRegex: \\"foo(bar\\" could not be parsed. -Error: Invalid regular expression: /foo(bar/: Unterminated group - - Configuration Documentation: - https://jestjs.io/docs/configuration.html -" -`; - exports[`testPathPattern ignores invalid regular expressions and logs a warning 1`] = `" Invalid testPattern a( supplied. Running all tests instead."`; exports[`testPathPattern --testPathPattern ignores invalid regular expressions and logs a warning 1`] = `" Invalid testPattern a( supplied. Running all tests instead."`; diff --git a/packages/jest-config/src/__tests__/normalize.test.js b/packages/jest-config/src/__tests__/normalize.test.js index 030ef345e050..48c2fc306b01 100644 --- a/packages/jest-config/src/__tests__/normalize.test.js +++ b/packages/jest-config/src/__tests__/normalize.test.js @@ -860,7 +860,7 @@ describe('testRegex', () => { expect(options.testRegex).toEqual([]); }); - it('testRegex string is mapped to array of RegExp objects', () => { + it('testRegex string is mapped to an array', () => { const {options} = normalize( { rootDir: '/root', @@ -869,9 +869,9 @@ describe('testRegex', () => { {}, ); - expect(options.testRegex).toEqual([/.*/]); + expect(options.testRegex).toEqual(['.*']); }); - it('testRegex array is mapped to array of RegExp objects', () => { + it('testRegex array is preserved', () => { const {options} = normalize( { rootDir: '/root', @@ -880,7 +880,7 @@ describe('testRegex', () => { {}, ); - expect(options.testRegex).toEqual([/.*/, /foo\.bar/]); + expect(options.testRegex).toEqual(['.*', 'foo\\.bar']); }); }); @@ -922,18 +922,6 @@ describe('testMatch', () => { }).toThrowErrorMatchingSnapshot(); }); - it('throws if testRegex is provided an invalid regex string', () => { - expect(() => { - normalize( - { - rootDir: '/root', - testRegex: 'foo(bar', - }, - {}, - ); - }).toThrowErrorMatchingSnapshot(); - }); - it('normalizes testMatch', () => { const {options} = normalize( { diff --git a/packages/jest-config/src/normalize.js b/packages/jest-config/src/normalize.js index 97e568153cc3..018f223d87f9 100644 --- a/packages/jest-config/src/normalize.js +++ b/packages/jest-config/src/normalize.js @@ -569,23 +569,9 @@ export default function normalize(options: InitialOptions, argv: Argv) { ); break; case 'testRegex': - const valueOrEmptyArray = options[key] || []; - const valueArray = Array.isArray(valueOrEmptyArray) - ? valueOrEmptyArray - : [valueOrEmptyArray]; - - value = valueArray.map(replacePathSepForRegex).map(pattern => { - try { - return new RegExp(pattern); - } catch (err) { - throw createConfigError( - `Error parsing configuration for ${chalk.bold( - key, - )}: "${pattern}" could not be parsed.\n` + - `Error: ${err.message}`, - ); - } - }); + value = options[key] + ? [].concat(options[key]).map(replacePathSepForRegex) + : []; break; case 'moduleFileExtensions': { value = options[key]; diff --git a/packages/jest-runtime/src/__tests__/should_instrument.test.js b/packages/jest-runtime/src/__tests__/should_instrument.test.js index 9003579b427d..47d84a96994e 100644 --- a/packages/jest-runtime/src/__tests__/should_instrument.test.js +++ b/packages/jest-runtime/src/__tests__/should_instrument.test.js @@ -29,13 +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/], + testRegex: ['.*\\_(test)\\.(js)$', '.*\\.(test)\\.(js)$', 'never'], }); }); @@ -121,13 +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/], + 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 1f0317f8d715..26189a5a4f0b 100644 --- a/packages/jest-runtime/src/should_instrument.js +++ b/packages/jest-runtime/src/should_instrument.js @@ -37,7 +37,7 @@ export default function shouldInstrument( if ( config.testRegex && - config.testRegex.some(regex => regex.test(filename)) + config.testRegex.some(regex => new RegExp(regex).test(filename)) ) { return false; } diff --git a/packages/jest-validate/README.md b/packages/jest-validate/README.md index f846b615fbc3..efe749a25838 100644 --- a/packages/jest-validate/README.md +++ b/packages/jest-validate/README.md @@ -141,11 +141,11 @@ This will output: ## Example validating multiple types ```js -import {MultipleValidOptions} from 'jest-validate'; +import {multipleValidOptions} from 'jest-validate'; validate(config, { // `bar` will accept either a string or a number - bar: MultipleValidOptions('string is ok', 2), + bar: multipleValidOptions('string is ok', 2), }); ``` diff --git a/packages/jest-validate/src/__tests__/validate.test.js b/packages/jest-validate/src/__tests__/validate.test.js index 59aed5ace5d1..a03895a813c6 100644 --- a/packages/jest-validate/src/__tests__/validate.test.js +++ b/packages/jest-validate/src/__tests__/validate.test.js @@ -9,7 +9,7 @@ 'use strict'; import validate from '../validate'; -import {MultipleValidOptions} from '../condition'; +import {multipleValidOptions} from '../condition'; import jestValidateExampleConfig from '../example_config'; import jestValidateDefaultConfig from '../default_config'; @@ -210,7 +210,7 @@ test('works with custom deprecations', () => { test('works with multiple valid types', () => { const exampleConfig = { - foo: MultipleValidOptions('text', ['text']), + foo: multipleValidOptions('text', ['text']), }; expect( @@ -239,7 +239,7 @@ test('works with multiple valid types', () => { test('reports errors nicely when failing with multiple valid options', () => { const exampleConfig = { - foo: MultipleValidOptions('text', ['text']), + foo: multipleValidOptions('text', ['text']), }; expect(() => @@ -254,7 +254,7 @@ test('reports errors nicely when failing with multiple valid options', () => { test('Repeated types within multiple valid examples are coalesced in error report', () => { const exampleConfig = { - foo: MultipleValidOptions('foo', 'bar', 2), + foo: multipleValidOptions('foo', 'bar', 2), }; expect(() => diff --git a/packages/jest-validate/src/condition.js b/packages/jest-validate/src/condition.js index d3dc05c36d55..5f84b5d2fee2 100644 --- a/packages/jest-validate/src/condition.js +++ b/packages/jest-validate/src/condition.js @@ -9,7 +9,7 @@ const toString = Object.prototype.toString; -const MultipleValidOptionsSymbol = Symbol('JEST_MULTIPLE_VALID_OPTIONS'); +const MULTIPLE_VALID_OPTIONS_SYMBOL = Symbol('JEST_MULTIPLE_VALID_OPTIONS'); function validationConditionSingle(option: any, validOption: any): boolean { return ( @@ -22,10 +22,9 @@ function validationConditionSingle(option: any, validOption: any): boolean { export function getValues(validOption: any) { if ( Array.isArray(validOption) && - validOption.length && - validOption[0] === MultipleValidOptionsSymbol + validOption[MULTIPLE_VALID_OPTIONS_SYMBOL] ) { - return validOption.slice(1); + return validOption; } return [validOption]; } @@ -34,6 +33,9 @@ export function validationCondition(option: any, validOption: any): boolean { return getValues(validOption).some(e => validationConditionSingle(option, e)); } -export function MultipleValidOptions(...args: Array) { - return [MultipleValidOptionsSymbol, ...args]; +export function multipleValidOptions(...args: Array) { + const options = [...args]; + // $FlowFixMe + options[MULTIPLE_VALID_OPTIONS_SYMBOL] = true; + return options; } diff --git a/packages/jest-validate/src/index.js b/packages/jest-validate/src/index.js index eca9c33fb8b5..3a62ea7e5315 100644 --- a/packages/jest-validate/src/index.js +++ b/packages/jest-validate/src/index.js @@ -15,14 +15,14 @@ import { } from './utils'; import validate from './validate'; import validateCLIOptions from './validate_cli_options'; -import {MultipleValidOptions} from './condition'; +import {multipleValidOptions} from './condition'; module.exports = { - MultipleValidOptions, ValidationError, createDidYouMeanMessage, format, logValidationWarning, + multipleValidOptions, validate, validateCLIOptions, }; diff --git a/types/Config.js b/types/Config.js index 7de867ffcbf9..c152976c0957 100644 --- a/types/Config.js +++ b/types/Config.js @@ -74,7 +74,7 @@ export type DefaultOptions = {| testLocationInResults: boolean, testMatch: Array, testPathIgnorePatterns: Array, - testRegex: Array, + testRegex: Array, testResultsProcessor: ?string, testRunner: ?string, testURL: string, @@ -166,7 +166,7 @@ export type InitialOptions = { testNamePattern?: string, testPathDirs?: Array, testPathIgnorePatterns?: Array, - testRegex?: string | Array, + testRegex?: string | Array, testResultsProcessor?: ?string, testRunner?: string, testURL?: string, @@ -283,7 +283,7 @@ export type ProjectConfig = {| testMatch: Array, testLocationInResults: boolean, testPathIgnorePatterns: Array, - testRegex: Array, + testRegex: Array, testRunner: string, testURL: string, timers: 'real' | 'fake',