diff --git a/docs/Configuration.md b/docs/Configuration.md index f90fe2749dd9..ae880b3b30e3 100644 --- a/docs/Configuration.md +++ b/docs/Configuration.md @@ -150,11 +150,6 @@ For example, the following would create a global `__DEV__` variable set to `true Note that, if you specify a global reference value (like an object or array) here, and some code mutates that value in the midst of running a test, that mutation will *not* be persisted across test runs for other test files. -### `mocksPattern` [string] -Default: `(?:[\\/]|^)__mocks__[\\/]` - -A pattern that is matched against file paths to determine which folder contains manual mocks. - ### `moduleFileExtensions` [array] Default: `["js", "json", "jsx", "node"]` @@ -232,6 +227,15 @@ Oftentimes, you'll want to set this to `'src'` or `'lib'`, corresponding to wher *Note that using `''` as a string token in any other path-based config settings will refer back to this value. So, for example, if you want your [`setupFiles`](#setupfiles-array) config entry to point at the `env-setup.js` file at the root of your project, you could set its value to `["/env-setup.js"]`.* +### `roots` [array] +Default: `[""]` + +A list of paths to directories that Jest should use to search for files in. + +There are times where you only want Jest to search in a single sub-directory (such as cases where you have a `src/` directory in your repo), but prevent it from accessing the rest of the repo. + +*Note: While `rootDir` is mostly used as a token to be re-used in other configuration options, `roots` is used by the internals of Jest to locate **test files and source files**. By default, `roots` has a single entry `` but there are cases where you want to have multiple roots within one project, for example `roots: ["/src/", "/tests/"]`.* + ### `setupFiles` [array] Default: `[]` @@ -330,13 +334,6 @@ for details of the patterns you can specify. See also [`testRegex` [string]](#testregex-string), but note that you cannot specify both options. -### `testPathDirs` [array] -Default: `[""]` - -A list of paths to directories that Jest should use to search for tests in. - -There are times where you only want Jest to search in a single sub-directory (such as cases where you have a `src/` directory in your repo), but not the rest of the repo. - ### `testPathIgnorePatterns` [array] Default: `["/node_modules/"]` diff --git a/packages/jest-cli/src/SearchSource.js b/packages/jest-cli/src/SearchSource.js index a7664ac625ec..4ce92db18b9a 100644 --- a/packages/jest-cli/src/SearchSource.js +++ b/packages/jest-cli/src/SearchSource.js @@ -28,8 +28,8 @@ const { } = require('jest-util'); type SearchSourceConfig = { + roots: Array, testMatch: Array, - testPathDirs: Array, testRegex: string, testPathIgnorePatterns: Array, }; @@ -94,11 +94,11 @@ class SearchSource { _hasteContext: HasteContext; _config: SearchSourceConfig; _options: ResolveModuleConfig; - _testPathDirPattern: RegExp; + _rootPattern: RegExp; _testIgnorePattern: ?RegExp; _testPathCases: { + roots: (path: Path) => boolean, testMatch: (path: Path) => boolean, - testPathDirs: (path: Path) => boolean, testRegex: (path: Path) => boolean, testPathIgnorePatterns: (path: Path) => boolean, }; @@ -114,8 +114,8 @@ class SearchSource { skipNodeResolution: false, }; - this._testPathDirPattern = - new RegExp(config.testPathDirs.map( + this._rootPattern = + new RegExp(config.roots.map( dir => escapePathForRegex(dir), ).join('|')); @@ -124,8 +124,8 @@ class SearchSource { ignorePattern.length ? new RegExp(ignorePattern.join('|')) : null; this._testPathCases = { + roots: path => this._rootPattern.test(path), testMatch: globsToMatcher(config.testMatch), - testPathDirs: path => this._testPathDirPattern.test(path), testPathIgnorePatterns: path => ( !this._testIgnorePattern || !this._testIgnorePattern.test(path) @@ -212,7 +212,7 @@ class SearchSource { } findChangedTests(options: Options): Promise { - return Promise.all(this._config.testPathDirs.map(determineSCM)) + return Promise.all(this._config.roots.map(determineSCM)) .then(repos => { if (!repos.every(([gitRepo, hgRepo]) => gitRepo || hgRepo)) { return { diff --git a/packages/jest-cli/src/__tests__/SearchSource-test.js b/packages/jest-cli/src/__tests__/SearchSource-test.js index a85d256027d3..34c33db0fa3d 100644 --- a/packages/jest-cli/src/__tests__/SearchSource-test.js +++ b/packages/jest-cli/src/__tests__/SearchSource-test.js @@ -43,7 +43,7 @@ describe('SearchSource', () => { config = normalizeConfig({ name, rootDir: '.', - testPathDirs: [], + roots: [], }); Runtime.createHasteContext(config, {maxWorkers}).then(hasteMap => { searchSource = new SearchSource(hasteMap, config); @@ -59,8 +59,8 @@ describe('SearchSource', () => { config = normalizeConfig({ name, rootDir: '.', + roots: [], testMatch: null, - testPathDirs: [], testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.jsx?$', }); Runtime.createHasteContext(config, {maxWorkers}).then(hasteMap => { diff --git a/packages/jest-cli/src/__tests__/watch-test.js b/packages/jest-cli/src/__tests__/watch-test.js index 892cddf59f4a..6e232eb1afdc 100644 --- a/packages/jest-cli/src/__tests__/watch-test.js +++ b/packages/jest-cli/src/__tests__/watch-test.js @@ -44,7 +44,7 @@ describe('Watch mode flows', () => { hasteMap = {on: () => {}}; argv = {}; hasteContext = {}; - config = {testPathDirs: [], testPathIgnorePatterns: [], testRegex: ''}; + config = {roots: [], testPathIgnorePatterns: [], testRegex: ''}; stdin = new MockStdin(); }); @@ -99,7 +99,7 @@ describe('Watch mode flows', () => { stdin.emit(KEYS.U); expect(runJestMock.mock.calls[0][1]).toEqual({ - testPathDirs: [], + roots: [], testPathIgnorePatterns: [], testRegex: '', updateSnapshot: true, diff --git a/packages/jest-cli/src/lib/__tests__/logDebugMessages-test.js b/packages/jest-cli/src/lib/__tests__/logDebugMessages-test.js index aa1a3eebbcf6..d0c796268769 100644 --- a/packages/jest-cli/src/lib/__tests__/logDebugMessages-test.js +++ b/packages/jest-cli/src/lib/__tests__/logDebugMessages-test.js @@ -34,7 +34,7 @@ describe('logDebugMessages', () => { logDebugMessages({ automock: false, rootDir: '/path/to/dir', - testPathDirs: ['path/to/dir/test'], + roots: ['path/to/dir/test'], testRunner: 'myRunner', watch: true, }, pipe); @@ -42,7 +42,7 @@ describe('logDebugMessages', () => { `config = { "automock": false, "rootDir": "/path/to/dir", - "testPathDirs": [ + "roots": [ "path/to/dir/test" ], "testRunner": "myRunner", diff --git a/packages/jest-config/src/__tests__/normalize-test.js b/packages/jest-config/src/__tests__/normalize-test.js index e7f24b418abf..2e5c5f3ed009 100644 --- a/packages/jest-config/src/__tests__/normalize-test.js +++ b/packages/jest-config/src/__tests__/normalize-test.js @@ -190,8 +190,8 @@ function testPathArray(key) { }); } -describe('testPathDirs', () => { - testPathArray('testPathDirs'); +describe('roots', () => { + testPathArray('roots'); }); describe('transform', () => { diff --git a/packages/jest-config/src/defaults.js b/packages/jest-config/src/defaults.js index 5985647540dd..26e58f8da909 100644 --- a/packages/jest-config/src/defaults.js +++ b/packages/jest-config/src/defaults.js @@ -31,7 +31,6 @@ module.exports = ({ haste: { providesModuleNodeModules: [], }, - mocksPattern: '__mocks__', moduleDirectories: ['node_modules'], moduleFileExtensions: [ 'js', @@ -46,13 +45,13 @@ module.exports = ({ preset: null, resetMocks: false, resetModules: false, + roots: [''], snapshotSerializers: [], testEnvironment: 'jest-environment-jsdom', testMatch: [ '**/__tests__/**/*.js?(x)', '**/?(*.)(spec|test).js?(x)', ], - testPathDirs: [''], testPathIgnorePatterns: [NODE_MODULES_REGEXP], testRegex: '', testResultsProcessor: null, diff --git a/packages/jest-config/src/deprecated.js b/packages/jest-config/src/deprecated.js index 245fb09a6488..4a10133b245a 100644 --- a/packages/jest-config/src/deprecated.js +++ b/packages/jest-config/src/deprecated.js @@ -34,6 +34,17 @@ const deprecatedOptions = { } Please update your configuration.`, + + testPathDirs: (config: Object) => + ` Option ${chalk.bold('"testPathDirs"')} was replaced by ${chalk.bold('"roots"')}. + + Jest now treats your current configuration as: + { + ${chalk.bold('"roots"')}: ${chalk.bold(format(config.testPathDirs))} + } + + Please update your configuration. + `, }; /* eslint-enable max-len */ diff --git a/packages/jest-config/src/normalize.js b/packages/jest-config/src/normalize.js index 0c9fe1ede325..7bf8b4d23642 100644 --- a/packages/jest-config/src/normalize.js +++ b/packages/jest-config/src/normalize.js @@ -258,6 +258,9 @@ function normalize(config: InitialConfig, argv: Object = {}) { if (config.testEnvironment) { config.testEnvironment = getTestEnvironment(config); } + if (!config.roots && config.testPathDirs) { + config.roots = config.testPathDirs; + } const babelJest = setupBabelJest(config); const newConfig = Object.assign({}, DEFAULT_CONFIG); @@ -273,7 +276,7 @@ function normalize(config: InitialConfig, argv: Object = {}) { //$FlowFixMe value = config[key].map(resolve.bind(null, config.rootDir, key)); break; - case 'testPathDirs': + case 'roots': //$FlowFixMe value = config[key].map(filePath => path.resolve( config.rootDir, @@ -331,7 +334,6 @@ function normalize(config: InitialConfig, argv: Object = {}) { case 'haste': case 'logHeapUsage': case 'logTransformErrors': - case 'mocksPattern': case 'moduleDirectories': case 'moduleFileExtensions': case 'moduleLoader': diff --git a/packages/jest-config/src/validConfig.js b/packages/jest-config/src/validConfig.js index 3a62fc23cfae..fd04cac9cd8f 100644 --- a/packages/jest-config/src/validConfig.js +++ b/packages/jest-config/src/validConfig.js @@ -44,7 +44,6 @@ module.exports = ({ }, logHeapUsage: true, logTransformErrors: true, - mocksPattern: '__mocks__', moduleDirectories: ['node_modules'], moduleFileExtensions: ['js', 'json', 'jsx', 'node'], moduleLoader: '', @@ -60,6 +59,7 @@ module.exports = ({ resetMocks: false, resetModules: false, rootDir: '/', + roots: [''], setupFiles: ['/setup.js'], setupTestFrameworkScriptFile: '/testSetupFile.js', silent: true, @@ -67,7 +67,6 @@ module.exports = ({ testEnvironment: 'jest-environment-jsdom', testMatch: ['**/__tests__/**/*.js?(x)', '**/?(*.)(spec|test).js?(x)'], testNamePattern: 'test signature', - testPathDirs: [''], testPathIgnorePatterns: [NODE_MODULES_REGEXP], testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.jsx?$', testResultsProcessor: 'processor-node-module', diff --git a/packages/jest-editor-support/src/parsers/BabylonParser.js b/packages/jest-editor-support/src/parsers/BabylonParser.js index 1eb2417ef224..9d934e641b6e 100644 --- a/packages/jest-editor-support/src/parsers/BabylonParser.js +++ b/packages/jest-editor-support/src/parsers/BabylonParser.js @@ -51,7 +51,9 @@ const babylonParser = (file: string) => { const babelRC = getBabelRC(file, {useCache: true}); const babel = JSON.parse(babelRC); - const plugins = Array.isArray(babel.plugins) ? babel.plugins.concat(['flow']) : ['flow']; + const plugins = Array.isArray(babel.plugins) + ? babel.plugins.concat(['flow']) + : ['flow']; const config = {plugins, sourceType: 'module'}; const ast = babylon.parse(data, config); @@ -63,7 +65,7 @@ const babylonParser = (file: string) => { block.name = node.expression.arguments[0].value; block.start = node.loc.start; block.end = node.loc.end; - + block.start.column += 1; block.file = file; @@ -72,7 +74,7 @@ const babylonParser = (file: string) => { // An `expect` was found in the AST // So take the AST node and create an object for us - // to store for later usage + // to store for later usage const foundExpectNode = (node: any, file: string) => { const expect = new Expect(); expect.start = node.loc.start; @@ -147,7 +149,7 @@ const babylonParser = (file: string) => { if (!root.body.hasOwnProperty(node)) { return; } - + // Pull out the node const element = root.body[node]; @@ -173,7 +175,7 @@ const babylonParser = (file: string) => { .filter(argument => isFunctionDeclaration(argument.type)) .forEach(argument => searchNodes(argument.body, file)); } - + if (isFunctionCall(element)) { element.expression.arguments .filter(argument => isFunctionDeclaration(argument.type)) diff --git a/packages/jest-haste-map/src/getMockName.js b/packages/jest-haste-map/src/getMockName.js index 8c83081da98d..c064d9b91341 100644 --- a/packages/jest-haste-map/src/getMockName.js +++ b/packages/jest-haste-map/src/getMockName.js @@ -11,11 +11,11 @@ const path = require('path'); -const mocksPattern = '__mocks__'; +const MOCKS_PATTERN = path.sep + '__mocks__' + path.sep; const getMockName = (filePath: string) => { - const mockPath = filePath.split(mocksPattern)[1]; - return mockPath.substring(1, mockPath.lastIndexOf(path.extname(mockPath))); + const mockPath = filePath.split(MOCKS_PATTERN)[1]; + return mockPath.substring(0, mockPath.lastIndexOf(path.extname(mockPath))); }; module.exports = getMockName; diff --git a/packages/jest-runtime/src/__tests__/transform-test.js b/packages/jest-runtime/src/__tests__/transform-test.js index b7d41907ec97..3b8c94dd065f 100644 --- a/packages/jest-runtime/src/__tests__/transform-test.js +++ b/packages/jest-runtime/src/__tests__/transform-test.js @@ -14,7 +14,11 @@ const skipOnWindows = require('skipOnWindows'); jest .mock('graceful-fs') .mock('jest-file-exists') - .mock('jest-util') + .mock('jest-util', () => { + const util = require.requireActual('jest-util'); + util.createDirectory = jest.fn(); + return util; + }) .mock('vm'); jest.mock( diff --git a/packages/jest-runtime/src/index.js b/packages/jest-runtime/src/index.js index 29dc52d0af77..5e679e2a44c9 100644 --- a/packages/jest-runtime/src/index.js +++ b/packages/jest-runtime/src/index.js @@ -27,6 +27,7 @@ const shouldInstrument = require('./shouldInstrument'); const transform = require('./transform'); const { createDirectory, + escapePathForRegex, } = require('jest-util'); type Module = {| @@ -81,7 +82,6 @@ class Runtime { _mockFactories: {[key: string]: () => any}; _mockMetaDataCache: {[key: string]: MockFunctionMetadata}; _mockRegistry: {[key: string]: any}; - _mocksPattern: ?RegExp; _moduleMocker: ModuleMocker; _moduleRegistry: {[key: string]: Module}; _internalModuleRegistry: {[key: string]: Module}; @@ -110,8 +110,6 @@ class Runtime { this._explicitShouldMock = Object.create(null); this._isCurrentlyExecutingManualMock = null; this._mockFactories = Object.create(null); - this._mocksPattern = - config.mocksPattern ? new RegExp(config.mocksPattern) : null; this._shouldAutoMock = config.automock; this._virtualMocks = Object.create(null); @@ -204,13 +202,13 @@ class Runtime { extensions: [SNAPSHOT_EXTENSION].concat(config.moduleFileExtensions), ignorePattern, maxWorkers: (options && options.maxWorkers) || 1, - mocksPattern: config.mocksPattern, + mocksPattern: escapePathForRegex(path.sep + '__mocks__' + path.sep), name: config.name, platforms: config.haste.platforms || ['ios', 'android'], providesModuleNodeModules: config.haste.providesModuleNodeModules, resetCache: options && options.resetCache, retainAllFiles: false, - roots: config.testPathDirs, + roots: config.roots, useWatchman: config.watchman, watch: options && options.watch, }); diff --git a/packages/jest-runtime/src/shouldInstrument.js b/packages/jest-runtime/src/shouldInstrument.js index 228d4e14756a..c4d3998cd6df 100644 --- a/packages/jest-runtime/src/shouldInstrument.js +++ b/packages/jest-runtime/src/shouldInstrument.js @@ -11,9 +11,13 @@ import type {Config, Path} from 'types/Config'; +const {escapePathForRegex} = require('jest-util'); const micromatch = require('micromatch'); const path = require('path'); +const MOCKS_PATTERN = + new RegExp(escapePathForRegex(path.sep + '__mocks__' + path.sep)); + const shouldInstrument = (filename: Path, config: Config): boolean => { if (!config.collectCoverage) { return false; @@ -58,7 +62,7 @@ const shouldInstrument = (filename: Path, config: Config): boolean => { return false; } - if (config.mocksPattern && filename.match(config.mocksPattern)) { + if (MOCKS_PATTERN.test(filename)) { return false; } diff --git a/packages/jest-runtime/src/transform.js b/packages/jest-runtime/src/transform.js index 1c52d9819650..7ecc0ae918ae 100644 --- a/packages/jest-runtime/src/transform.js +++ b/packages/jest-runtime/src/transform.js @@ -57,12 +57,11 @@ const getCacheKey = ( collectCoverageOnlyFrom: config.collectCoverageOnlyFrom, coveragePathIgnorePatterns: config.coveragePathIgnorePatterns, haste: config.haste, - mocksPattern: config.mocksPattern, moduleFileExtensions: config.moduleFileExtensions, moduleNameMapper: config.moduleNameMapper, rootDir: config.rootDir, + roots: config.roots, testMatch: config.testMatch, - testPathDirs: config.testPathDirs, testRegex: config.testRegex, transformIgnorePatterns: config.transformIgnorePatterns, })); diff --git a/packages/jest-validate/src/__tests__/fixtures/jestConfig.js b/packages/jest-validate/src/__tests__/fixtures/jestConfig.js index 667e2ca5c6ff..92c636023393 100644 --- a/packages/jest-validate/src/__tests__/fixtures/jestConfig.js +++ b/packages/jest-validate/src/__tests__/fixtures/jestConfig.js @@ -35,7 +35,6 @@ const defaultConfig = { haste: { providesModuleNodeModules: [], }, - mocksPattern: '__mocks__', moduleDirectories: ['node_modules'], moduleFileExtensions: [ 'js', @@ -50,9 +49,9 @@ const defaultConfig = { preset: null, resetMocks: false, resetModules: false, + roots: [''], snapshotSerializers: [], testEnvironment: 'jest-environment-jsdom', - testPathDirs: [''], testPathIgnorePatterns: [NODE_MODULES_REGEXP], testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.jsx?$', testResultsProcessor: null, @@ -91,7 +90,6 @@ const validConfig = { }, logHeapUsage: true, logTransformErrors: true, - mocksPattern: '__mocks__', moduleDirectories: ['node_modules'], moduleFileExtensions: ['js', 'json', 'jsx', 'node'], moduleLoader: '', @@ -107,13 +105,13 @@ const validConfig = { resetMocks: false, resetModules: false, rootDir: '/', + roots: [''], setupFiles: ['/setup.js'], setupTestFrameworkScriptFile: '/testSetupFile.js', silent: true, snapshotSerializers: ['my-serializer-module'], testEnvironment: 'jest-environment-jsdom', testNamePattern: 'test signature', - testPathDirs: [''], testPathIgnorePatterns: [NODE_MODULES_REGEXP], testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.jsx?$', testResultsProcessor: 'processor-node-module', diff --git a/types/Config.js b/types/Config.js index 26e05a41adf9..ebaa9643c4f9 100644 --- a/types/Config.js +++ b/types/Config.js @@ -30,7 +30,6 @@ export type DefaultConfig = {| expand: boolean, globals: ConfigGlobals, haste: HasteConfig, - mocksPattern: string, moduleDirectories: Array, moduleFileExtensions: Array, moduleNameMapper: {[key: string]: string}, @@ -40,10 +39,10 @@ export type DefaultConfig = {| preset: ?string, resetMocks: boolean, resetModules: boolean, + roots: Array, snapshotSerializers: Array, testEnvironment: string, testMatch: Array, - testPathDirs: Array, testPathIgnorePatterns: Array, testRegex: string, testResultsProcessor: ?string, @@ -74,7 +73,6 @@ export type Config = {| haste: HasteConfig, logHeapUsage: boolean, logTransformErrors: ?boolean, - mocksPattern: string, moduleDirectories: Array, moduleFileExtensions: Array, moduleLoader: Path, @@ -89,6 +87,7 @@ export type Config = {| resetMocks: boolean, resetModules: boolean, rootDir: Path, + roots: Array, setupFiles: Array, setupTestFrameworkScriptFile: Path, silent: boolean, @@ -96,7 +95,6 @@ export type Config = {| testEnvironment: string, testMatch: Array, testNamePattern: string, - testPathDirs: Array, testPathIgnorePatterns: Array, testRegex: string, testResultsProcessor: ?string, @@ -132,7 +130,6 @@ export type InitialConfig = {| haste?: HasteConfig, logHeapUsage?: boolean, logTransformErrors?: ?boolean, - mocksPattern?: string, moduleDirectories?: Array, moduleFileExtensions?: Array, moduleLoader?: Path, @@ -148,6 +145,7 @@ export type InitialConfig = {| resetMocks?: boolean, resetModules?: boolean, rootDir: Path, + roots?: Array, scriptPreprocessor?: string, setupFiles?: Array, setupTestFrameworkScriptFile?: Path, @@ -156,7 +154,6 @@ export type InitialConfig = {| testEnvironment?: string, testMatch?: Array, testNamePattern?: string, - testPathDirs?: Array, testPathIgnorePatterns?: Array, testRegex?: string, testResultsProcessor?: ?string,