From b6534053db81a9ac7d274b290e25ecce5f13020e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Norte?= Date: Wed, 20 Feb 2019 15:19:38 +0000 Subject: [PATCH] Ignore rootDir to determine the cache key of transformed files in babel-jest --- CHANGELOG.md | 1 + packages/babel-jest/package.json | 1 + packages/babel-jest/src/__tests__/index.ts | 36 ++++++++++++++++++++ packages/babel-jest/src/index.ts | 38 +++++++++++++++++----- 4 files changed, 68 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bdf022c9ad6e..cc05844a801d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - `[expect]`: Improve report when matcher fails, part 8 ([#7876](https://github.com/facebook/jest/pull/7876)) - `[pretty-format]` Support `React.memo` ([#7891](https://github.com/facebook/jest/pull/7891)) - `[jest-config]` Print error information on preset normalization error ([#7935](https://github.com/facebook/jest/pull/7935)) +- `[babel-jest]` Ignore `rootDir` to determine the cache key of transformed files ([#7947](https://github.com/facebook/jest/pull/7947)) ### Fixes diff --git a/packages/babel-jest/package.json b/packages/babel-jest/package.json index 226e23853ce9..641e2f6d31a4 100644 --- a/packages/babel-jest/package.json +++ b/packages/babel-jest/package.json @@ -17,6 +17,7 @@ "babel-plugin-istanbul": "^5.1.0", "babel-preset-jest": "^24.1.0", "chalk": "^2.4.2", + "jest-regex-util": "^24.0.0", "slash": "^2.0.0" }, "devDependencies": { diff --git a/packages/babel-jest/src/__tests__/index.ts b/packages/babel-jest/src/__tests__/index.ts index 6b3d264a883f..a86b82ae2247 100644 --- a/packages/babel-jest/src/__tests__/index.ts +++ b/packages/babel-jest/src/__tests__/index.ts @@ -39,3 +39,39 @@ test(`Returns source string with inline maps when no transformOptions is passed` expect(result.map.sources).toEqual(['dummy_path.js']); expect(JSON.stringify(result.map.sourcesContent)).toMatch('customMultiply'); }); + +test('getCacheKey does not depend on the rootDir', () => { + const getCacheKeyArgs = rootDir => { + const config = { + cwd: rootDir, + rootDir, + }; + + return [ + '// Some code', + `${rootDir}/foo/bar.js`, + JSON.stringify(config), + {config, instrument: true, rootDir: config.rootDir}, + ]; + }; + + jest.mock('@babel/core'); + + require('@babel/core').loadPartialConfig = options => ({ + babelrc: `${options.cwd}/foo/.babelrc`, + config: `${options.cwd}/babel.config.js`, + options: { + cwd: options.cwd, + someOtherOption: `${options.cwd}/foo`, + }, + }); + + const cacheKeyForRoot1 = babelJest.getCacheKey( + ...getCacheKeyArgs('/root1/dir'), + ); + const cacheKeyForRoot2 = babelJest.getCacheKey( + ...getCacheKeyArgs('/root2/dir'), + ); + + expect(cacheKeyForRoot1).toEqual(cacheKeyForRoot2); +}); diff --git a/packages/babel-jest/src/index.ts b/packages/babel-jest/src/index.ts index 2df36fe37d22..12c3e5441ccb 100644 --- a/packages/babel-jest/src/index.ts +++ b/packages/babel-jest/src/index.ts @@ -17,6 +17,7 @@ import { transformSync as babelTransform, } from '@babel/core'; import chalk from 'chalk'; +import {escapeStrForRegex} from 'jest-regex-util'; import slash from 'slash'; const THIS_FILE = fs.readFileSync(__filename); @@ -65,33 +66,54 @@ const createTransformer = ( return babelConfig; } + const rootDirRegExpCache: {[rootDir: string]: RegExp} = Object.create(null); + + function getRootDirRegExp(rootDir: Config.Path): RegExp { + if (!rootDirRegExpCache[rootDir]) { + // "/path/to/root/dir" or + // "path/to/root/dir/inner + rootDirRegExpCache[rootDir] = new RegExp( + `(['"])${escapeStrForRegex(rootDir)}(\\1|${escapeStrForRegex( + path.sep, + )})`, + 'g', + ); + } + + return rootDirRegExpCache[rootDir]; + } + const transformer: BabelJestTransformer = { canInstrument: true, createTransformer, getCacheKey( fileData, filename, - configString, + _configString, {config, instrument, rootDir}, ) { const babelOptions = loadBabelConfig(config.cwd, filename); - const configPath = [ - babelOptions.config || '', - babelOptions.babelrc || '', - ]; + const configPath = [babelOptions.config, babelOptions.babelrc].map( + configPath => configPath && path.relative(rootDir, configPath), + ); return crypto .createHash('md5') .update(THIS_FILE) .update('\0', 'utf8') - .update(JSON.stringify(babelOptions.options)) + .update( + // Not pretty but not coupled to a specific signature of the + // babel options to relativize paths + JSON.stringify(babelOptions.options).replace( + getRootDirRegExp(rootDir), + '$1$2', + ), + ) .update('\0', 'utf8') .update(fileData) .update('\0', 'utf8') .update(path.relative(rootDir, filename)) .update('\0', 'utf8') - .update(configString) - .update('\0', 'utf8') .update(configPath.join('')) .update('\0', 'utf8') .update(instrument ? 'instrument' : '')