From 952479dc2f339d69b3f6eeaa2902f13760e95114 Mon Sep 17 00:00:00 2001 From: cpojer Date: Thu, 27 Apr 2017 15:46:16 +0100 Subject: [PATCH 1/3] Finalize the split between configs. --- .../__snapshots__/failures-test.js.snap | 4 +- .../__snapshots__/showConfig-test.js.snap | 39 ++--- integration_tests/__tests__/config-test.js | 2 +- .../__tests__/generateEmptyCoverage-test.js | 3 +- packages/jest-cli/src/cli/runCLI.js | 1 + .../jest-cli/src/generateEmptyCoverage.js | 10 +- .../src/reporters/CoverageReporter.js | 42 +++-- packages/jest-cli/src/runJest.js | 5 +- packages/jest-cli/src/runTest.js | 12 +- packages/jest-config/src/defaults.js | 4 +- packages/jest-config/src/index.js | 39 ++++- packages/jest-config/src/normalize.js | 23 ++- packages/jest-config/src/validConfig.js | 5 +- packages/jest-jasmine2/src/index.js | 8 +- .../jest-jasmine2/src/setup-jest-globals.js | 20 +-- packages/jest-repl/src/cli/repl.js | 17 +- .../jest-runtime/src/ScriptTransformer.js | 19 +-- .../src/__tests__/ScriptTransformer-test.js | 52 +++--- .../src/__tests__/instrumentation-test.js | 7 +- packages/jest-runtime/src/cli/index.js | 6 +- packages/jest-runtime/src/index.js | 41 ++++- packages/jest-runtime/src/shouldInstrument.js | 20 ++- .../src/__tests__/fixtures/jestConfig.js | 1 - types/Config.js | 154 ++++++++---------- 24 files changed, 295 insertions(+), 239 deletions(-) diff --git a/integration_tests/__tests__/__snapshots__/failures-test.js.snap b/integration_tests/__tests__/__snapshots__/failures-test.js.snap index 75ae6bd1df25..f488a79d1701 100644 --- a/integration_tests/__tests__/__snapshots__/failures-test.js.snap +++ b/integration_tests/__tests__/__snapshots__/failures-test.js.snap @@ -70,7 +70,7 @@ Object { Expected two assertions to be called but only received one assertion call. - at addAssertionErrors (../../packages/jest-jasmine2/build/setup-jest-globals.js:56:21) + at addAssertionErrors (../../packages/jest-jasmine2/build/setup-jest-globals.js:62:21) ● .assertions() › throws on redeclare of assertion count @@ -87,7 +87,7 @@ Object { Expected zero assertions to be called but only received one assertion call. - at addAssertionErrors (../../packages/jest-jasmine2/build/setup-jest-globals.js:56:21) + at addAssertionErrors (../../packages/jest-jasmine2/build/setup-jest-globals.js:62:21) .assertions() ✕ throws diff --git a/integration_tests/__tests__/__snapshots__/showConfig-test.js.snap b/integration_tests/__tests__/__snapshots__/showConfig-test.js.snap index 2fd294f7e92d..8c3fcce1da6d 100644 --- a/integration_tests/__tests__/__snapshots__/showConfig-test.js.snap +++ b/integration_tests/__tests__/__snapshots__/showConfig-test.js.snap @@ -4,25 +4,17 @@ exports[`jest --showConfig outputs config info and exits 1`] = ` { "config": { "automock": false, - "bail": false, "browser": false, + "cache": false, "cacheDirectory": "/tmp/jest", "clearMocks": false, "coveragePathIgnorePatterns": [ "/node_modules/" ], - "coverageReporters": [ - "json", - "text", - "lcov", - "clover" - ], - "expand": false, "globals": {}, "haste": { "providesModuleNodeModules": [] }, - "mapCoverage": false, "moduleDirectories": [ "node_modules" ], @@ -34,14 +26,17 @@ exports[`jest --showConfig outputs config info and exits 1`] = ` ], "moduleNameMapper": {}, "modulePathIgnorePatterns": [], - "noStackTrace": false, - "notify": false, + "name": "[md5 hash]", "preset": null, "resetMocks": false, "resetModules": false, + "rootDir": "/mocked/root/path/jest/integration_tests/verbose_reporter", "roots": [ "/mocked/root/path/jest/integration_tests/verbose_reporter" ], + "setupFiles": [ + "/mocked/root/path/jest/node_modules/regenerator-runtime/runtime.js" + ], "snapshotSerializers": [], "testEnvironment": "/mocked/root/path/jest/packages/jest-environment-node/build/index.js", "testMatch": [ @@ -52,36 +47,22 @@ exports[`jest --showConfig outputs config info and exits 1`] = ` "/node_modules/" ], "testRegex": "", - "testResultsProcessor": null, + "testRunner": "/mocked/root/path/jest/packages/jest-jasmine2/build/index.js", "testURL": "about:blank", "timers": "real", - "transformIgnorePatterns": [ - "/node_modules/" - ], - "useStderr": false, - "verbose": null, - "watch": false, - "rootDir": "/mocked/root/path/jest/integration_tests/verbose_reporter", - "name": "[md5 hash]", - "setupFiles": [ - "/mocked/root/path/jest/node_modules/regenerator-runtime/runtime.js" - ], - "testRunner": "/mocked/root/path/jest/packages/jest-jasmine2/build/index.js", "transform": [ [ "^.+\\\\.jsx?$", "/mocked/root/path/jest/integration_tests/verbose_reporter/node_modules/babel-jest/build/index.js" ] ], - "cache": false, - "watchman": true + "transformIgnorePatterns": [ + "/node_modules/" + ] }, "framework": "jasmine2", "globalConfig": { "bail": false, - "coveragePathIgnorePatterns": [ - "/node_modules/" - ], "coverageReporters": [ "json", "text", diff --git a/integration_tests/__tests__/config-test.js b/integration_tests/__tests__/config-test.js index e178c12a6732..2d966bfab458 100644 --- a/integration_tests/__tests__/config-test.js +++ b/integration_tests/__tests__/config-test.js @@ -48,5 +48,5 @@ test('watchman config option is respected over default argv', () => { '--debug', ]); - expect(stdout).toMatch('"watchman": false,'); + expect(stdout).toMatch('"watchman": false'); }); diff --git a/packages/jest-cli/src/__tests__/generateEmptyCoverage-test.js b/packages/jest-cli/src/__tests__/generateEmptyCoverage-test.js index 820b21174655..cdde4d7d9de7 100644 --- a/packages/jest-cli/src/__tests__/generateEmptyCoverage-test.js +++ b/packages/jest-cli/src/__tests__/generateEmptyCoverage-test.js @@ -36,8 +36,7 @@ module.exports = { it('generates an empty coverage object for a file without running it', () => { expect( - generateEmptyCoverage(src, '/sum.js', { - baseCacheDir: os.tmpdir(), + generateEmptyCoverage(src, '/sum.js', {}, { cacheDirectory: os.tmpdir(), rootDir: os.tmpdir(), }).coverage, diff --git a/packages/jest-cli/src/cli/runCLI.js b/packages/jest-cli/src/cli/runCLI.js index 2f2af18f6d3e..240a10d6a51b 100644 --- a/packages/jest-cli/src/cli/runCLI.js +++ b/packages/jest-cli/src/cli/runCLI.js @@ -55,6 +55,7 @@ module.exports = async ( maxWorkers: getMaxWorkers(argv), resetCache: !config.cache, watch: globalConfig.watch, + watchman: globalConfig.watchman, }); hasteMapInstances[index] = hasteMapInstance; return createContext(config, await hasteMapInstance.build()); diff --git a/packages/jest-cli/src/generateEmptyCoverage.js b/packages/jest-cli/src/generateEmptyCoverage.js index 99ab4a350203..8262bb16d4d3 100644 --- a/packages/jest-cli/src/generateEmptyCoverage.js +++ b/packages/jest-cli/src/generateEmptyCoverage.js @@ -10,7 +10,7 @@ 'use strict'; -import type {ProjectConfig, Path} from 'types/Config'; +import type {GlobalConfig, ProjectConfig, Path} from 'types/Config'; const IstanbulInstrument = require('istanbul-lib-instrument'); @@ -19,9 +19,15 @@ const {ScriptTransformer, shouldInstrument} = require('jest-runtime'); module.exports = function( source: string, filename: Path, + globalConfig: GlobalConfig, config: ProjectConfig, ) { - if (shouldInstrument(filename, config)) { + const coverageOptions = { + collectCoverage: globalConfig.collectCoverage, + collectCoverageFrom: globalConfig.collectCoverageFrom, + collectCoverageOnlyFrom: globalConfig.collectCoverageOnlyFrom, + }; + if (shouldInstrument(filename, coverageOptions, config)) { // Transform file without instrumentation first, to make sure produced // source code is ES6 (no flowtypes etc.) and can be instrumented const transformResult = new ScriptTransformer(config).transformSource( diff --git a/packages/jest-cli/src/reporters/CoverageReporter.js b/packages/jest-cli/src/reporters/CoverageReporter.js index e5d05adc8851..4785d155d0f3 100644 --- a/packages/jest-cli/src/reporters/CoverageReporter.js +++ b/packages/jest-cli/src/reporters/CoverageReporter.js @@ -61,25 +61,25 @@ class CoverageReporter extends BaseReporter { onRunComplete( contexts: Set, - config: GlobalConfig, + globalConfig: GlobalConfig, aggregatedResults: AggregatedResult, ) { - this._addUntestedFiles(contexts); + this._addUntestedFiles(globalConfig, contexts); let map = this._coverageMap; let sourceFinder: Object; - if (config.mapCoverage) { + if (globalConfig.mapCoverage) { ({map, sourceFinder} = this._sourceMapStore.transformCoverage(map)); } const reporter = createReporter(); try { - if (config.coverageDirectory) { - reporter.dir = config.coverageDirectory; + if (globalConfig.coverageDirectory) { + reporter.dir = globalConfig.coverageDirectory; } - let coverageReporters = config.coverageReporters || []; + let coverageReporters = globalConfig.coverageReporters || []; if ( - !config.useStderr && + !globalConfig.useStderr && coverageReporters.length && coverageReporters.indexOf('text') === -1 ) { @@ -101,16 +101,19 @@ class CoverageReporter extends BaseReporter { ); } - this._checkThreshold(map, config); + this._checkThreshold(globalConfig, map); } - _addUntestedFiles(contexts: Set) { + _addUntestedFiles(globalConfig: GlobalConfig, contexts: Set) { const files = []; contexts.forEach(context => { const config = context.config; - if (config.collectCoverageFrom && config.collectCoverageFrom.length) { + if ( + globalConfig.collectCoverageFrom && + globalConfig.collectCoverageFrom.length + ) { context.hasteFS - .matchFilesWithGlob(config.collectCoverageFrom, config.rootDir) + .matchFilesWithGlob(globalConfig.collectCoverageFrom, config.rootDir) .forEach(filePath => files.push({ config, @@ -129,7 +132,12 @@ class CoverageReporter extends BaseReporter { if (!this._coverageMap.data[path]) { try { const source = fs.readFileSync(path).toString(); - const result = generateEmptyCoverage(source, path, config); + const result = generateEmptyCoverage( + source, + path, + globalConfig, + config, + ); if (result) { this._coverageMap.addFileCoverage(result.coverage); if (result.sourceMapPath) { @@ -155,8 +163,8 @@ class CoverageReporter extends BaseReporter { } } - _checkThreshold(map: CoverageMap, config: GlobalConfig) { - if (config.coverageThreshold) { + _checkThreshold(globalConfig: GlobalConfig, map: CoverageMap) { + if (globalConfig.coverageThreshold) { const results = map.getCoverageSummary().toJSON(); function check(name, thresholds, actuals) { @@ -188,7 +196,11 @@ class CoverageReporter extends BaseReporter { return errors; }, []); } - const errors = check('global', config.coverageThreshold.global, results); + const errors = check( + 'global', + globalConfig.coverageThreshold.global, + results, + ); if (errors.length > 0) { this.log(`${FAIL_COLOR(errors.join('\n'))}`); diff --git a/packages/jest-cli/src/runJest.js b/packages/jest-cli/src/runJest.js index cc9905292d2f..0d8d1ecf08ea 100644 --- a/packages/jest-cli/src/runJest.js +++ b/packages/jest-cli/src/runJest.js @@ -26,7 +26,10 @@ const TestSequencer = require('./TestSequencer'); const setConfig = (contexts, newConfig) => contexts.forEach( - context => (context.config = Object.assign({}, context.config, newConfig)), + context => + (context.config = Object.freeze( + Object.assign({}, context.config, newConfig), + )), ); const formatTestPathPattern = pattern => { diff --git a/packages/jest-cli/src/runTest.js b/packages/jest-cli/src/runTest.js index fcc8ebf13551..909f16c497a1 100644 --- a/packages/jest-cli/src/runTest.js +++ b/packages/jest-cli/src/runTest.js @@ -52,14 +52,14 @@ function runTest( /* $FlowFixMe */ const TestRunner = require(config.testRunner); /* $FlowFixMe */ - const ModuleLoader = require(config.moduleLoader || 'jest-runtime'); + const Runtime = require(config.moduleLoader || 'jest-runtime'); const env = new TestEnvironment(config); const TestConsole = globalConfig.verbose ? Console - : config.silent ? NullConsole : BufferedConsole; + : globalConfig.silent ? NullConsole : BufferedConsole; const testConsole = new TestConsole( - config.useStderr ? process.stderr : process.stdout, + globalConfig.useStderr ? process.stderr : process.stdout, process.stderr, (type, message) => getConsoleOutput( @@ -71,7 +71,11 @@ function runTest( ); const cacheFS = {[path]: testSource}; setGlobal(env.global, 'console', testConsole); - const runtime = new ModuleLoader(config, env, resolver, cacheFS); + const runtime = new Runtime(config, env, resolver, cacheFS, { + collectCoverage: globalConfig.collectCoverage, + collectCoverageFrom: globalConfig.collectCoverageFrom, + collectCoverageOnlyFrom: globalConfig.collectCoverageOnlyFrom, + }); const start = Date.now(); return TestRunner(globalConfig, config, env, runtime, path) .then((result: TestResult) => { diff --git a/packages/jest-config/src/defaults.js b/packages/jest-config/src/defaults.js index 55c5ce1d3d54..a6ec0c8b1e8e 100644 --- a/packages/jest-config/src/defaults.js +++ b/packages/jest-config/src/defaults.js @@ -10,7 +10,7 @@ 'use strict'; -import type {DefaultConfig} from 'types/Config'; +import type {DefaultOptions} from 'types/Config'; const constants = require('./constants'); const os = require('os'); @@ -66,4 +66,4 @@ module.exports = ({ useStderr: false, verbose: null, watch: false, -}: DefaultConfig); +}: DefaultOptions); diff --git a/packages/jest-config/src/index.js b/packages/jest-config/src/index.js index 8f0de26e1c34..0d6596c2c485 100644 --- a/packages/jest-config/src/index.js +++ b/packages/jest-config/src/index.js @@ -73,13 +73,11 @@ const getConfigs = ( collectCoverageFrom: options.collectCoverageFrom, collectCoverageOnlyFrom: options.collectCoverageOnlyFrom, coverageDirectory: options.coverageDirectory, - coveragePathIgnorePatterns: options.coveragePathIgnorePatterns, coverageReporters: options.coverageReporters, coverageThreshold: options.coverageThreshold, expand: options.expand, forceExit: options.forceExit, logHeapUsage: options.logHeapUsage, - logTransformErrors: options.logTransformErrors, mapCoverage: options.mapCoverage, noStackTrace: options.noStackTrace, notify: options.notify, @@ -95,7 +93,42 @@ const getConfigs = ( watch: options.watch, watchman: options.watchman, }), - projectConfig: options, + projectConfig: Object.freeze({ + automock: options.automock, + browser: options.browser, + cache: options.cache, + cacheDirectory: options.cacheDirectory, + clearMocks: options.clearMocks, + coveragePathIgnorePatterns: options.coveragePathIgnorePatterns, + globals: options.globals, + haste: options.haste, + moduleDirectories: options.moduleDirectories, + moduleFileExtensions: options.moduleFileExtensions, + moduleLoader: options.moduleLoader, + moduleNameMapper: options.moduleNameMapper, + modulePathIgnorePatterns: options.modulePathIgnorePatterns, + modulePaths: options.modulePaths, + name: options.name, + preset: options.preset, + resetMocks: options.resetMocks, + resetModules: options.resetModules, + resolver: options.resolver, + rootDir: options.rootDir, + roots: options.roots, + setupFiles: options.setupFiles, + setupTestFrameworkScriptFile: options.setupTestFrameworkScriptFile, + snapshotSerializers: options.snapshotSerializers, + testEnvironment: options.testEnvironment, + testMatch: options.testMatch, + testPathIgnorePatterns: options.testPathIgnorePatterns, + testRegex: options.testRegex, + testRunner: options.testRunner, + testURL: options.testURL, + timers: options.timers, + transform: options.transform, + transformIgnorePatterns: options.transformIgnorePatterns, + unmockedModulePathPatterns: options.unmockedModulePathPatterns, + }), }; }; diff --git a/packages/jest-config/src/normalize.js b/packages/jest-config/src/normalize.js index 326b098b54a4..27f2a98edab2 100644 --- a/packages/jest-config/src/normalize.js +++ b/packages/jest-config/src/normalize.js @@ -10,7 +10,7 @@ 'use strict'; -import type {InitialConfig} from 'types/Config'; +import type {InitialOptions} from 'types/Config'; const { BULLET, @@ -37,7 +37,7 @@ const ERROR = `${BULLET}Validation Error`; const createConfigError = message => new ValidationError(ERROR, message, DOCUMENTATION_NOTE); -const setupPreset = (config: InitialConfig, configPreset: string) => { +const setupPreset = (config: InitialOptions, configPreset: string) => { let preset; const presetPath = _replaceRootDirInPath(config.rootDir, configPreset); const presetModule = Resolver.findNodeModule( @@ -74,7 +74,7 @@ const setupPreset = (config: InitialConfig, configPreset: string) => { return Object.assign({}, preset, config); }; -const setupBabelJest = (config: InitialConfig) => { +const setupBabelJest = (config: InitialOptions) => { let babelJest; const basedir = config.rootDir; @@ -110,7 +110,7 @@ const setupBabelJest = (config: InitialConfig) => { }; const normalizeCollectCoverageOnlyFrom = ( - config: InitialConfig, + config: InitialOptions, key: string, ) => { return Object.keys(config[key]).reduce((normObj, filePath) => { @@ -123,7 +123,7 @@ const normalizeCollectCoverageOnlyFrom = ( }, Object.create(null)); }; -const normalizeCollectCoverageFrom = (config: InitialConfig, key: string) => { +const normalizeCollectCoverageFrom = (config: InitialOptions, key: string) => { let value; if (!config[key]) { value = []; @@ -143,7 +143,7 @@ const normalizeCollectCoverageFrom = (config: InitialConfig, key: string) => { }; const normalizeUnmockedModulePathPatterns = ( - config: InitialConfig, + config: InitialOptions, key: string, ) => { // _replaceRootDirTags is specifically well-suited for substituting @@ -157,7 +157,7 @@ const normalizeUnmockedModulePathPatterns = ( ); }; -const normalizePreprocessor = (config: InitialConfig) => { +const normalizePreprocessor = (config: InitialOptions) => { /* eslint-disable max-len */ if (config.scriptPreprocessor && config.transform) { throw createConfigError( @@ -188,7 +188,7 @@ const normalizePreprocessor = (config: InitialConfig) => { delete config.preprocessorIgnorePatterns; }; -const normalizeMissingOptions = (config: InitialConfig) => { +const normalizeMissingOptions = (config: InitialOptions) => { if (!config.name) { config.name = crypto.createHash('md5').update(config.rootDir).digest('hex'); } @@ -210,7 +210,7 @@ const normalizeMissingOptions = (config: InitialConfig) => { return config; }; -const normalizeRootDir = (config: InitialConfig) => { +const normalizeRootDir = (config: InitialOptions) => { // Assert that there *is* a rootDir if (!config.hasOwnProperty('rootDir')) { throw createConfigError( @@ -220,7 +220,7 @@ const normalizeRootDir = (config: InitialConfig) => { config.rootDir = path.normalize(config.rootDir); }; -const normalizeArgv = (config: InitialConfig, argv: Object) => { +const normalizeArgv = (config: InitialOptions, argv: Object) => { if (argv.testRunner) { config.testRunner = argv.testRunner; } @@ -242,7 +242,7 @@ const normalizeArgv = (config: InitialConfig, argv: Object) => { } }; -function normalize(config: InitialConfig, argv: Object = {}) { +function normalize(config: InitialOptions, argv: Object = {}) { const {hasDeprecationWarnings} = validate(config, { comment: DOCUMENTATION_NOTE, deprecatedConfig: DEPRECATED_CONFIG, @@ -347,7 +347,6 @@ function normalize(config: InitialConfig, argv: Object = {}) { case 'coverageThreshold': case 'globals': case 'logHeapUsage': - case 'logTransformErrors': case 'mapCoverage': case 'moduleDirectories': case 'moduleFileExtensions': diff --git a/packages/jest-config/src/validConfig.js b/packages/jest-config/src/validConfig.js index f43b6de2d02d..70cddbe162ae 100644 --- a/packages/jest-config/src/validConfig.js +++ b/packages/jest-config/src/validConfig.js @@ -10,7 +10,7 @@ 'use strict'; -import type {InitialConfig} from 'types/Config'; +import type {InitialOptions} from 'types/Config'; const constants = require('./constants'); const {replacePathSepForRegex} = require('jest-regex-util'); @@ -44,7 +44,6 @@ module.exports = ({ providesModuleNodeModules: ['react', 'react-native'], }, logHeapUsage: true, - logTransformErrors: true, mapCoverage: false, moduleDirectories: ['node_modules'], moduleFileExtensions: ['js', 'json', 'jsx', 'node'], @@ -86,4 +85,4 @@ module.exports = ({ verbose: false, watch: false, watchman: true, -}: InitialConfig); +}: InitialOptions); diff --git a/packages/jest-jasmine2/src/index.js b/packages/jest-jasmine2/src/index.js index 14fa6f5cf809..bc8ef96d59fd 100644 --- a/packages/jest-jasmine2/src/index.js +++ b/packages/jest-jasmine2/src/index.js @@ -9,8 +9,8 @@ */ 'use strict'; -import type {GlobalConfig, ProjectConfig} from 'types/Config'; import type {Environment} from 'types/Environment'; +import type {GlobalConfig, ProjectConfig} from 'types/Config'; import type {TestResult} from 'types/TestResult'; import type Runtime from 'jest-runtime'; @@ -77,7 +77,11 @@ function jasmine2( const snapshotState = runtime.requireInternalModule( path.resolve(__dirname, './setup-jest-globals.js'), - )({config, testPath, updateSnapshot: globalConfig.updateSnapshot}); + )({ + config, + globalConfig, + testPath, + }); if (config.setupTestFrameworkScriptFile) { runtime.requireModule(config.setupTestFrameworkScriptFile); diff --git a/packages/jest-jasmine2/src/setup-jest-globals.js b/packages/jest-jasmine2/src/setup-jest-globals.js index 50d567f4c7a4..23c9ea2c0f1c 100644 --- a/packages/jest-jasmine2/src/setup-jest-globals.js +++ b/packages/jest-jasmine2/src/setup-jest-globals.js @@ -10,7 +10,7 @@ 'use strict'; -import type {Path, ProjectConfig} from 'types/Config'; +import type {GlobalConfig, Path, ProjectConfig} from 'types/Config'; const {getState, setState} = require('jest-matchers'); const {initializeSnapshotState, addSerializer} = require('jest-snapshot'); @@ -21,6 +21,12 @@ const { pluralize, } = require('jest-matcher-utils'); +export type SetupOptions = {| + config: ProjectConfig, + globalConfig: GlobalConfig, + testPath: Path, +|}; + // Get suppressed errors form jest-matchers that weren't throw during // test execution and add them to the test result, potentially failing // a passing test. @@ -98,13 +104,7 @@ const patchJasmine = () => { })(global.jasmine.Spec); }; -type Options = { - testPath: Path, - config: ProjectConfig, - updateSnapshot: boolean, -}; - -module.exports = ({config, testPath, updateSnapshot}: Options) => { +module.exports = ({config, globalConfig, testPath}: SetupOptions) => { // Jest tests snapshotSerializers in order preceding built-in serializers. // Therefore, add in reverse because the last added is the first tested. config.snapshotSerializers.concat().reverse().forEach(path => { @@ -115,9 +115,9 @@ module.exports = ({config, testPath, updateSnapshot}: Options) => { patchJasmine(); const snapshotState = initializeSnapshotState( testPath, - updateSnapshot, + globalConfig.updateSnapshot, '', - config.expand, + globalConfig.expand, ); setState({snapshotState}); // Return it back to the outer scope (test runner outside the VM). diff --git a/packages/jest-repl/src/cli/repl.js b/packages/jest-repl/src/cli/repl.js index 7b1143b02d4f..58e4863aa136 100644 --- a/packages/jest-repl/src/cli/repl.js +++ b/packages/jest-repl/src/cli/repl.js @@ -11,7 +11,10 @@ 'use strict'; -declare var jestConfig: Object; +import type {GlobalConfig, ProjectConfig} from 'types/Config'; + +declare var jestGlobalConfig: GlobalConfig; +declare var jestProjectConfig: ProjectConfig; declare var jest: Object; const path = require('path'); @@ -26,8 +29,8 @@ const evalCommand = (cmd, context, filename, callback, config) => { if (transformer) { cmd = transformer.process( cmd, - jestConfig.replname || 'jest.js', - jestConfig, + jestGlobalConfig.replname || 'jest.js', + jestProjectConfig, ); } result = vm.runInThisContext(cmd); @@ -50,11 +53,11 @@ const isRecoverableError = error => { return false; }; -if (jestConfig.transform) { +if (jestProjectConfig.transform) { let transformerPath = null; - for (let i = 0; i < jestConfig.transform.length; i++) { - if (new RegExp(jestConfig.transform[i][0]).test('foobar.js')) { - transformerPath = jestConfig.transform[i][1]; + for (let i = 0; i < jestProjectConfig.transform.length; i++) { + if (new RegExp(jestProjectConfig.transform[i][0]).test('foobar.js')) { + transformerPath = jestProjectConfig.transform[i][1]; break; } } diff --git a/packages/jest-runtime/src/ScriptTransformer.js b/packages/jest-runtime/src/ScriptTransformer.js index 5827286d6e8f..99c2ed32c6f1 100644 --- a/packages/jest-runtime/src/ScriptTransformer.js +++ b/packages/jest-runtime/src/ScriptTransformer.js @@ -9,7 +9,7 @@ */ 'use strict'; -import type {Path, ProjectConfig} from 'types/Config'; +import type {Glob, Path, ProjectConfig} from 'types/Config'; import type { Transformer, TransformedSource, @@ -28,7 +28,10 @@ const slash = require('slash'); const VERSION = require('../package.json').version; -type Options = {| +export type Options = {| + collectCoverage: boolean, + collectCoverageFrom: Array, + collectCoverageOnlyFrom: ?{[key: string]: boolean}, isInternalModule?: boolean, |}; @@ -268,16 +271,6 @@ class ScriptTransformer { e.stack = e.codeFrame; } - if (this._config.logTransformErrors) { - console.error( - `FILENAME: ${filename}\n` + - `TRANSFORM: ${willTransform.toString()}\n` + - `INSTRUMENT: ${instrument.toString()}\n` + - `SOURCE:\n` + - String(wrappedCode), - ); - } - throw e; } } @@ -287,7 +280,7 @@ class ScriptTransformer { options: Options, fileSource?: string, ): TransformResult { - const instrument = shouldInstrument(filename, this._config); + const instrument = shouldInstrument(filename, options, this._config); const scriptCacheKey = getScriptCacheKey( filename, this._config, diff --git a/packages/jest-runtime/src/__tests__/ScriptTransformer-test.js b/packages/jest-runtime/src/__tests__/ScriptTransformer-test.js index e29c87e2555e..58102e95ed85 100644 --- a/packages/jest-runtime/src/__tests__/ScriptTransformer-test.js +++ b/packages/jest-runtime/src/__tests__/ScriptTransformer-test.js @@ -146,9 +146,10 @@ describe('ScriptTransformer', () => { beforeEach(reset); it('transforms a file properly', () => { - config.collectCoverage = true; const scriptTransformer = new ScriptTransformer(config); - const response = scriptTransformer.transform('/fruits/banana.js').script; + const response = scriptTransformer.transform('/fruits/banana.js', { + collectCoverage: true, + }).script; expect(response instanceof vm.Script).toBe(true); expect(vm.Script.mock.calls[0][0]).toMatchSnapshot(); @@ -158,24 +159,24 @@ describe('ScriptTransformer', () => { expect(fs.readFileSync).toBeCalledWith('/fruits/banana.js', 'utf8'); // in-memory cache - const response2 = scriptTransformer.transform('/fruits/banana.js').script; + const response2 = scriptTransformer.transform('/fruits/banana.js', { + collectCoverage: true, + }).script; expect(response2).toBe(response); - scriptTransformer.transform('/fruits/kiwi.js'); + scriptTransformer.transform('/fruits/kiwi.js', { + collectCoverage: true, + }); const snapshot = vm.Script.mock.calls[1][0]; expect(snapshot).toMatchSnapshot(); - new ScriptTransformer( - Object.assign({}, config, {collectCoverage: true}), - ).transform('/fruits/kiwi.js'); + scriptTransformer.transform('/fruits/kiwi.js', {collectCoverage: true}); expect(vm.Script.mock.calls[0][0]).not.toEqual(snapshot); expect(vm.Script.mock.calls[0][0]).not.toMatch(/instrumented kiwi/); // If we disable coverage, we get a different result. - new ScriptTransformer( - Object.assign({}, config, {collectCoverage: false}), - ).transform('/fruits/kiwi.js'); + scriptTransformer.transform('/fruits/kiwi.js', {collectCoverage: false}); expect(vm.Script.mock.calls[1][0]).toEqual(snapshot); }); @@ -184,13 +185,13 @@ describe('ScriptTransformer', () => { transform: [['^.+\\.js$', 'test-preprocessor']], }); const scriptTransformer = new ScriptTransformer(config); - scriptTransformer.transform('/fruits/banana.js'); + scriptTransformer.transform('/fruits/banana.js', {}); expect(require('test-preprocessor').getCacheKey).toBeCalled(); expect(vm.Script.mock.calls[0][0]).toMatchSnapshot(); - scriptTransformer.transform('/node_modules/react.js'); + scriptTransformer.transform('/node_modules/react.js', {}); // ignores preprocessor expect(vm.Script.mock.calls[1][0]).toMatchSnapshot(); }); @@ -204,22 +205,21 @@ describe('ScriptTransformer', () => { }); const scriptTransformer = new ScriptTransformer(config); - scriptTransformer.transform('/fruits/banana.js'); - scriptTransformer.transform('/styles/App.css'); + scriptTransformer.transform('/fruits/banana.js', {}); + scriptTransformer.transform('/styles/App.css', {}); expect(require('test-preprocessor').getCacheKey).toBeCalled(); expect(require('css-preprocessor').getCacheKey).toBeCalled(); expect(vm.Script.mock.calls[0][0]).toMatchSnapshot(); expect(vm.Script.mock.calls[1][0]).toMatchSnapshot(); - scriptTransformer.transform('/node_modules/react.js'); + scriptTransformer.transform('/node_modules/react.js', {}); // ignores preprocessor expect(vm.Script.mock.calls[2][0]).toMatchSnapshot(); }); it('writes source map if preprocessor supplies it', () => { config = Object.assign(config, { - collectCoverage: true, mapCoverage: true, transform: [['^.+\\.js$', 'preprocessor-with-sourcemaps']], }); @@ -235,7 +235,9 @@ describe('ScriptTransformer', () => { map, }); - const result = scriptTransformer.transform('/fruits/banana.js'); + const result = scriptTransformer.transform('/fruits/banana.js', { + collectCoverage: true, + }); expect(result.sourceMapPath).toEqual(expect.any(String)); expect(fs.writeFileSync).toBeCalledWith( result.sourceMapPath, @@ -246,7 +248,6 @@ describe('ScriptTransformer', () => { it('writes source map if preprocessor inlines it', () => { config = Object.assign(config, { - collectCoverage: true, mapCoverage: true, transform: [['^.+\\.js$', 'preprocessor-with-sourcemaps']], }); @@ -264,7 +265,9 @@ describe('ScriptTransformer', () => { require('preprocessor-with-sourcemaps').process.mockReturnValue(content); - const result = scriptTransformer.transform('/fruits/banana.js'); + const result = scriptTransformer.transform('/fruits/banana.js', { + collectCoverage: true, + }); expect(result.sourceMapPath).toEqual(expect.any(String)); expect(fs.writeFileSync).toBeCalledWith( result.sourceMapPath, @@ -275,7 +278,6 @@ describe('ScriptTransformer', () => { it('does not write source map if mapCoverage config option is false', () => { config = Object.assign(config, { - collectCoverage: true, mapCoverage: false, transform: [['^.+\\.js$', 'preprocessor-with-sourcemaps']], }); @@ -291,7 +293,9 @@ describe('ScriptTransformer', () => { map, }); - const result = scriptTransformer.transform('/fruits/banana.js'); + const result = scriptTransformer.transform('/fruits/banana.js', { + collectCoverage: true, + }); expect(result.sourceMapPath).toBeFalsy(); expect(fs.writeFileSync).toHaveBeenCalledTimes(1); }); @@ -301,7 +305,7 @@ describe('ScriptTransformer', () => { transform: [['^.+\\.js$', 'test-preprocessor']], }); let scriptTransformer = new ScriptTransformer(transformConfig); - scriptTransformer.transform('/fruits/banana.js'); + scriptTransformer.transform('/fruits/banana.js', {}); const cachePath = getCachePath(mockFs, config); expect(fs.writeFileSync).toBeCalled(); @@ -315,7 +319,7 @@ describe('ScriptTransformer', () => { // Restore the cached fs mockFs = mockFsCopy; scriptTransformer = new ScriptTransformer(transformConfig); - scriptTransformer.transform('/fruits/banana.js'); + scriptTransformer.transform('/fruits/banana.js', {}); expect(fs.readFileSync.mock.calls.length).toBe(2); expect(fs.readFileSync).toBeCalledWith('/fruits/banana.js', 'utf8'); @@ -328,7 +332,7 @@ describe('ScriptTransformer', () => { mockFs = mockFsCopy; transformConfig.cache = false; scriptTransformer = new ScriptTransformer(transformConfig); - scriptTransformer.transform('/fruits/banana.js'); + scriptTransformer.transform('/fruits/banana.js', {}); expect(fs.readFileSync.mock.calls.length).toBe(1); expect(fs.readFileSync).toBeCalledWith('/fruits/banana.js', 'utf8'); diff --git a/packages/jest-runtime/src/__tests__/instrumentation-test.js b/packages/jest-runtime/src/__tests__/instrumentation-test.js index 2872f9c593bf..f83fe5a8a5da 100644 --- a/packages/jest-runtime/src/__tests__/instrumentation-test.js +++ b/packages/jest-runtime/src/__tests__/instrumentation-test.js @@ -25,12 +25,11 @@ it('instruments files', () => { const config = { cache: false, cacheDirectory: os.tmpdir(), - collectCoverage: true, rootDir: '/', }; - const instrumented = new ScriptTransformer(config).transform( - FILE_PATH_TO_INSTRUMENT, - ).script; + const instrumented = new ScriptTransformer( + config, + ).transform(FILE_PATH_TO_INSTRUMENT, {collectCoverage: true}).script; expect(instrumented instanceof vm.Script).toBe(true); // We can't really snapshot the resulting coverage, because it depends on // absolute path of the file, which will be different on different diff --git a/packages/jest-runtime/src/cli/index.js b/packages/jest-runtime/src/cli/index.js index d70cdc509543..49157c322511 100644 --- a/packages/jest-runtime/src/cli/index.js +++ b/packages/jest-runtime/src/cli/index.js @@ -57,7 +57,7 @@ function run(cliArgv?: Object, cliInfo?: Array) { const info = cliInfo ? ', ' + cliInfo.join(', ') : ''; console.log(`Using Jest Runtime v${VERSION}${info}`); } - readConfig(argv, root).then(({config}) => { + readConfig(argv, root).then(({config, globalConfig}) => { // Always disable automocking in scripts. config = Object.assign({}, config, { automock: false, @@ -65,6 +65,7 @@ function run(cliArgv?: Object, cliInfo?: Array) { }); Runtime.createContext(config, { maxWorkers: os.cpus().length - 1, + watchman: globalConfig.watchman, }) .then(hasteMap => { /* $FlowFixMe */ @@ -76,7 +77,8 @@ function run(cliArgv?: Object, cliInfo?: Array) { 'console', new Console(process.stdout, process.stderr), ); - env.global.jestConfig = config; + env.global.jestProjectConfig = config; + env.global.jestGlobalConfig = globalConfig; const runtime = new Runtime(config, env, hasteMap.resolver); runtime.requireModule(testFilePath); diff --git a/packages/jest-runtime/src/index.js b/packages/jest-runtime/src/index.js index 5b93cd41e9a0..f8b8d5591bfb 100644 --- a/packages/jest-runtime/src/index.js +++ b/packages/jest-runtime/src/index.js @@ -10,7 +10,7 @@ 'use strict'; -import type {Path, ProjectConfig} from 'types/Config'; +import type {Glob, Path, ProjectConfig} from 'types/Config'; import type {Console} from 'console'; import type {Environment} from 'types/Environment'; import type {Context} from 'types/Context'; @@ -43,12 +43,19 @@ type HasteMapOptions = {| maxWorkers: number, resetCache: boolean, watch?: boolean, + watchman: boolean, |}; type InternalModuleOptions = {| isInternalModule: boolean, |}; +type CoverageOptions = { + collectCoverage: boolean, + collectCoverageFrom: Array, + collectCoverageOnlyFrom: ?{[key: string]: boolean}, +}; + type BooleanObject = {[key: string]: boolean}; type CacheFS = {[path: Path]: string}; @@ -80,16 +87,17 @@ class Runtime { _cacheFS: CacheFS; _config: ProjectConfig; + _coverageOptions: CoverageOptions; _currentlyExecutingModulePath: string; _environment: Environment; _explicitShouldMock: BooleanObject; + _internalModuleRegistry: {[key: string]: Module}; _isCurrentlyExecutingManualMock: ?string; _mockFactories: {[key: string]: () => any}; _mockMetaDataCache: {[key: string]: MockFunctionMetadata}; _mockRegistry: {[key: string]: any}; _moduleMocker: ModuleMocker; _moduleRegistry: {[key: string]: Module}; - _internalModuleRegistry: {[key: string]: Module}; _resolver: Resolver; _shouldAutoMock: boolean; _shouldMockModuleCache: BooleanObject; @@ -105,9 +113,15 @@ class Runtime { environment: Environment, resolver: Resolver, cacheFS?: CacheFS, + coverageOptions?: CoverageOptions, ) { this._cacheFS = cacheFS || Object.create(null); this._config = config; + this._coverageOptions = coverageOptions || { + collectCoverage: false, + collectCoverageFrom: [], + collectCoverageOnlyFrom: null, + }; this._currentlyExecutingModulePath = ''; this._environment = environment; this._explicitShouldMock = Object.create(null); @@ -161,8 +175,20 @@ class Runtime { } } - static shouldInstrument(filename: Path, config: ProjectConfig) { - return shouldInstrument(filename, config); + static shouldInstrument( + filename: Path, + options: CoverageOptions, + config: ProjectConfig, + ) { + return shouldInstrument( + filename, + { + collectCoverage: options.collectCoverage, + collectCoverageFrom: options.collectCoverageFrom, + collectCoverageOnlyFrom: options.collectCoverageOnlyFrom, + }, + config, + ); } static createContext( @@ -171,6 +197,7 @@ class Runtime { console?: Console, maxWorkers: number, watch?: boolean, + watchman: boolean, }, ): Promise { createDirectory(config.cacheDirectory); @@ -179,6 +206,7 @@ class Runtime { maxWorkers: options.maxWorkers, resetCache: !config.cache, watch: options.watch, + watchman: options.watchman, }); return instance.build().then( hasteMap => ({ @@ -215,7 +243,7 @@ class Runtime { resetCache: options && options.resetCache, retainAllFiles: false, roots: config.roots, - useWatchman: config.watchman, + useWatchman: options && options.watchman, watch: options && options.watch, }); } @@ -468,6 +496,9 @@ class Runtime { const transformedFile = this._scriptTransformer.transform( filename, { + collectCoverage: this._coverageOptions.collectCoverage, + collectCoverageFrom: this._coverageOptions.collectCoverageFrom, + collectCoverageOnlyFrom: this._coverageOptions.collectCoverageOnlyFrom, isInternalModule, }, this._cacheFS[filename], diff --git a/packages/jest-runtime/src/shouldInstrument.js b/packages/jest-runtime/src/shouldInstrument.js index c54a38ef8a45..03b7e635a963 100644 --- a/packages/jest-runtime/src/shouldInstrument.js +++ b/packages/jest-runtime/src/shouldInstrument.js @@ -10,6 +10,7 @@ 'use strict'; import type {Path, ProjectConfig} from 'types/Config'; +import type {Options} from './ScriptTransformer'; const {escapePathForRegex} = require('jest-regex-util'); const micromatch = require('micromatch'); @@ -19,8 +20,12 @@ const MOCKS_PATTERN = new RegExp( escapePathForRegex(path.sep + '__mocks__' + path.sep), ); -const shouldInstrument = (filename: Path, config: ProjectConfig): boolean => { - if (!config.collectCoverage) { +const shouldInstrument = ( + filename: Path, + options: Options, + config: ProjectConfig, +): boolean => { + if (!options.collectCoverage) { return false; } @@ -39,18 +44,19 @@ const shouldInstrument = (filename: Path, config: ProjectConfig): boolean => { if ( // This configuration field contains an object in the form of: // {'path/to/file.js': true} - config.collectCoverageOnlyFrom && - !config.collectCoverageOnlyFrom[filename] + options.collectCoverageOnlyFrom && + !options.collectCoverageOnlyFrom[filename] ) { return false; } if ( - !config.collectCoverageOnlyFrom && // still cover if `only` is specified - config.collectCoverageFrom && + // still cover if `only` is specified + !options.collectCoverageOnlyFrom && + options.collectCoverageFrom && !micromatch( [path.relative(config.rootDir, filename)], - config.collectCoverageFrom, + options.collectCoverageFrom, ).length ) { return false; diff --git a/packages/jest-validate/src/__tests__/fixtures/jestConfig.js b/packages/jest-validate/src/__tests__/fixtures/jestConfig.js index a049c46ad3fc..6210c1da2450 100644 --- a/packages/jest-validate/src/__tests__/fixtures/jestConfig.js +++ b/packages/jest-validate/src/__tests__/fixtures/jestConfig.js @@ -86,7 +86,6 @@ const validConfig = { providesModuleNodeModules: ['react', 'react-native'], }, logHeapUsage: true, - logTransformErrors: true, moduleDirectories: ['node_modules'], moduleFileExtensions: ['js', 'json', 'jsx', 'node'], moduleLoader: '', diff --git a/types/Config.js b/types/Config.js index e268217199f4..218b8c76f52b 100644 --- a/types/Config.js +++ b/types/Config.js @@ -21,92 +21,7 @@ export type HasteConfig = {| export type ConfigGlobals = Object; -export type GlobalConfig = {| - bail: boolean, - collectCoverage: boolean, - collectCoverageFrom: Array, - collectCoverageOnlyFrom: {[key: string]: boolean}, - coverageDirectory: string, - coveragePathIgnorePatterns: Array, - coverageReporters: Array, - coverageThreshold: {global: {[key: string]: number}}, - expand: boolean, - forceExit: boolean, - logHeapUsage: boolean, - logTransformErrors: ?boolean, - mapCoverage: boolean, - noStackTrace: boolean, - notify: boolean, - replname: ?string, - rootDir: Path, - silent: boolean, - testNamePattern: string, - testPathPattern: string, - testResultsProcessor: ?string, - updateSnapshot: boolean, - useStderr: boolean, - verbose: ?boolean, - watch: boolean, - watchman: boolean, -|}; - -export type ProjectConfig = {| - automock: boolean, - bail: boolean, - browser: boolean, - cache: boolean, - cacheDirectory: Path, - clearMocks: boolean, - collectCoverage: boolean, - collectCoverageFrom: Array, - collectCoverageOnlyFrom: {[key: string]: boolean}, - coverageDirectory: string, - coveragePathIgnorePatterns: Array, - coverageReporters: Array, - coverageThreshold: {global: {[key: string]: number}}, - expand: boolean, - forceExit: boolean, - globals: ConfigGlobals, - haste: HasteConfig, - logHeapUsage: boolean, - logTransformErrors: ?boolean, - mapCoverage: boolean, - moduleDirectories: Array, - moduleFileExtensions: Array, - moduleLoader: Path, - moduleNameMapper: {[key: string]: string} | Array<[string, string]>, - modulePathIgnorePatterns: Array, - modulePaths: Array, - name: string, - noStackTrace: boolean, - notify: boolean, - preset: ?string, - replname: ?string, - resetMocks: boolean, - resetModules: boolean, - resolver: ?Path, - rootDir: Path, - roots: Array, - setupFiles: Array, - setupTestFrameworkScriptFile: Path, - silent: boolean, - snapshotSerializers: Array, - testEnvironment: string, - testMatch: Array, - testPathIgnorePatterns: Array, - testRegex: string, - testResultsProcessor: ?string, - testRunner: string, - testURL: string, - timers: 'real' | 'fake', - transform: Array<[string, Path]>, - transformIgnorePatterns: Array, - unmockedModulePathPatterns: ?Array, - useStderr: boolean, - watchman: boolean, -|}; - -export type DefaultConfig = {| +export type DefaultOptions = {| automock: boolean, bail: boolean, browser: boolean, @@ -142,7 +57,7 @@ export type DefaultConfig = {| watch: boolean, |}; -export type InitialConfig = {| +export type InitialOptions = {| automock?: boolean, bail?: boolean, browser?: boolean, @@ -161,7 +76,6 @@ export type InitialConfig = {| globals?: ConfigGlobals, haste?: HasteConfig, logHeapUsage?: boolean, - logTransformErrors?: ?boolean, mapCoverage?: boolean, moduleDirectories?: Array, moduleFileExtensions?: Array, @@ -203,3 +117,67 @@ export type InitialConfig = {| watch?: boolean, watchman?: boolean, |}; + +export type GlobalConfig = {| + bail: boolean, + collectCoverage: boolean, + collectCoverageFrom: Array, + collectCoverageOnlyFrom: ?{[key: string]: boolean}, + coverageDirectory: string, + coverageReporters: Array, + coverageThreshold: {global: {[key: string]: number}}, + expand: boolean, + forceExit: boolean, + logHeapUsage: boolean, + mapCoverage: boolean, + noStackTrace: boolean, + notify: boolean, + replname: ?string, + rootDir: Path, + silent: boolean, + testNamePattern: string, + testPathPattern: string, + testResultsProcessor: ?string, + updateSnapshot: boolean, + useStderr: boolean, + verbose: ?boolean, + watch: boolean, + watchman: boolean, +|}; + +export type ProjectConfig = {| + automock: boolean, + browser: boolean, + cache: boolean, + cacheDirectory: Path, + clearMocks: boolean, + coveragePathIgnorePatterns: Array, + globals: ConfigGlobals, + haste: HasteConfig, + moduleDirectories: Array, + moduleFileExtensions: Array, + moduleLoader: Path, + moduleNameMapper: {[key: string]: string} | Array<[string, string]>, + modulePathIgnorePatterns: Array, + modulePaths: Array, + name: string, + preset: ?string, + resetMocks: boolean, + resetModules: boolean, + resolver: ?Path, + rootDir: Path, + roots: Array, + setupFiles: Array, + setupTestFrameworkScriptFile: Path, + snapshotSerializers: Array, + testEnvironment: string, + testMatch: Array, + testPathIgnorePatterns: Array, + testRegex: string, + testRunner: string, + testURL: string, + timers: 'real' | 'fake', + transform: Array<[string, Path]>, + transformIgnorePatterns: Array, + unmockedModulePathPatterns: ?Array, +|}; From 2e9da86f62c343a45b281051e88d2ee3578078ee Mon Sep 17 00:00:00 2001 From: cpojer Date: Thu, 27 Apr 2017 18:59:22 +0100 Subject: [PATCH 2/3] Coverage mapping --- .../__tests__/generateEmptyCoverage-test.js | 13 ++++--- .../jest-cli/src/generateEmptyCoverage.js | 2 ++ packages/jest-cli/src/runTest.js | 6 +++- .../jest-runtime/src/ScriptTransformer.js | 36 +++++++++++++++---- .../src/__tests__/ScriptTransformer-test.js | 8 ++--- packages/jest-runtime/src/index.js | 4 +++ 6 files changed, 54 insertions(+), 15 deletions(-) diff --git a/packages/jest-cli/src/__tests__/generateEmptyCoverage-test.js b/packages/jest-cli/src/__tests__/generateEmptyCoverage-test.js index cdde4d7d9de7..c34801e7b2a9 100644 --- a/packages/jest-cli/src/__tests__/generateEmptyCoverage-test.js +++ b/packages/jest-cli/src/__tests__/generateEmptyCoverage-test.js @@ -36,9 +36,14 @@ module.exports = { it('generates an empty coverage object for a file without running it', () => { expect( - generateEmptyCoverage(src, '/sum.js', {}, { - cacheDirectory: os.tmpdir(), - rootDir: os.tmpdir(), - }).coverage, + generateEmptyCoverage( + src, + '/sum.js', + {}, + { + cacheDirectory: os.tmpdir(), + rootDir: os.tmpdir(), + }, + ).coverage, ).toMatchSnapshot(); }); diff --git a/packages/jest-cli/src/generateEmptyCoverage.js b/packages/jest-cli/src/generateEmptyCoverage.js index 8262bb16d4d3..fa32de468066 100644 --- a/packages/jest-cli/src/generateEmptyCoverage.js +++ b/packages/jest-cli/src/generateEmptyCoverage.js @@ -26,6 +26,7 @@ module.exports = function( collectCoverage: globalConfig.collectCoverage, collectCoverageFrom: globalConfig.collectCoverageFrom, collectCoverageOnlyFrom: globalConfig.collectCoverageOnlyFrom, + mapCoverage: globalConfig.mapCoverage, }; if (shouldInstrument(filename, coverageOptions, config)) { // Transform file without instrumentation first, to make sure produced @@ -34,6 +35,7 @@ module.exports = function( filename, source, false, + globalConfig.mapCoverage, ); const instrumenter = IstanbulInstrument.createInstrumenter(); instrumenter.instrumentSync(transformResult.code, filename); diff --git a/packages/jest-cli/src/runTest.js b/packages/jest-cli/src/runTest.js index 909f16c497a1..0386c61f9b22 100644 --- a/packages/jest-cli/src/runTest.js +++ b/packages/jest-cli/src/runTest.js @@ -12,6 +12,7 @@ import type {GlobalConfig, Path, ProjectConfig} from 'types/Config'; import type {TestResult} from 'types/TestResult'; import type {Resolver} from 'types/Resolve'; +import type RuntimeClass from 'jest-runtime'; const BufferedConsole = require('./lib/BufferedConsole'); const {Console, NullConsole, setGlobal} = require('jest-util'); @@ -52,7 +53,9 @@ function runTest( /* $FlowFixMe */ const TestRunner = require(config.testRunner); /* $FlowFixMe */ - const Runtime = require(config.moduleLoader || 'jest-runtime'); + const Runtime = (require(config.moduleLoader || 'jest-runtime'): Class< + RuntimeClass + >); const env = new TestEnvironment(config); const TestConsole = globalConfig.verbose @@ -75,6 +78,7 @@ function runTest( collectCoverage: globalConfig.collectCoverage, collectCoverageFrom: globalConfig.collectCoverageFrom, collectCoverageOnlyFrom: globalConfig.collectCoverageOnlyFrom, + mapCoverage: globalConfig.mapCoverage, }); const start = Date.now(); return TestRunner(globalConfig, config, env, runtime, path) diff --git a/packages/jest-runtime/src/ScriptTransformer.js b/packages/jest-runtime/src/ScriptTransformer.js index 99c2ed32c6f1..768793bc5e3d 100644 --- a/packages/jest-runtime/src/ScriptTransformer.js +++ b/packages/jest-runtime/src/ScriptTransformer.js @@ -33,6 +33,7 @@ export type Options = {| collectCoverageFrom: Array, collectCoverageOnlyFrom: ?{[key: string]: boolean}, isInternalModule?: boolean, + mapCoverage: boolean, |}; const cache: Map = new Map(); @@ -50,7 +51,12 @@ class ScriptTransformer { this._transformCache = new Map(); } - _getCacheKey(fileData: string, filename: Path, instrument: boolean): string { + _getCacheKey( + fileData: string, + filename: Path, + instrument: boolean, + mapCoverage: boolean, + ): string { if (!configToJsonMap.has(this._config)) { // We only need this set of config options that can likely influence // cached output instead of all config options. @@ -69,6 +75,7 @@ class ScriptTransformer { .update(fileData) .update(configString) .update(instrument ? 'instrument' : '') + .update(mapCoverage ? 'mapCoverage' : '') .digest('hex'); } } @@ -77,13 +84,19 @@ class ScriptTransformer { filename: Path, content: string, instrument: boolean, + mapCoverage: boolean, ): Path { const baseCacheDir = getCacheFilePath( this._config.cacheDirectory, 'jest-transform-cache-' + this._config.name, VERSION, ); - const cacheKey = this._getCacheKey(content, filename, instrument); + const cacheKey = this._getCacheKey( + content, + filename, + instrument, + mapCoverage, + ); // Create sub folders based on the cacheKey to avoid creating one // directory with many files. const cacheDir = path.join(baseCacheDir, cacheKey[0] + cacheKey[1]); @@ -160,9 +173,19 @@ class ScriptTransformer { }).code; } - transformSource(filename: Path, content: string, instrument: boolean) { + transformSource( + filename: Path, + content: string, + instrument: boolean, + mapCoverage: boolean, + ) { const transform = this._getTransformer(filename); - const cacheFilePath = this._getFileCachePath(filename, content, instrument); + const cacheFilePath = this._getFileCachePath( + filename, + content, + instrument, + mapCoverage, + ); let sourceMapPath = cacheFilePath + '.map'; // Ignore cache if `config.cache` is set (--no-cache) let code = this._config.cache @@ -193,7 +216,7 @@ class ScriptTransformer { } } - if (this._config.mapCoverage) { + if (mapCoverage) { if (!transformed.map) { const convert = require('convert-source-map'); const inlineSourceMap = convert.fromSource(transformed.code); @@ -215,7 +238,7 @@ class ScriptTransformer { code = transformed.code; } - if (instrument && transformed.map && this._config.mapCoverage) { + if (instrument && transformed.map && mapCoverage) { const sourceMapContent = typeof transformed.map === 'string' ? transformed.map : JSON.stringify(transformed.map); @@ -254,6 +277,7 @@ class ScriptTransformer { filename, content, instrument, + !!(options && options.mapCoverage), ); wrappedCode = wrap(transformedSource.code); diff --git a/packages/jest-runtime/src/__tests__/ScriptTransformer-test.js b/packages/jest-runtime/src/__tests__/ScriptTransformer-test.js index 58102e95ed85..0530e2b18cb7 100644 --- a/packages/jest-runtime/src/__tests__/ScriptTransformer-test.js +++ b/packages/jest-runtime/src/__tests__/ScriptTransformer-test.js @@ -220,7 +220,6 @@ describe('ScriptTransformer', () => { it('writes source map if preprocessor supplies it', () => { config = Object.assign(config, { - mapCoverage: true, transform: [['^.+\\.js$', 'preprocessor-with-sourcemaps']], }); const scriptTransformer = new ScriptTransformer(config); @@ -237,6 +236,7 @@ describe('ScriptTransformer', () => { const result = scriptTransformer.transform('/fruits/banana.js', { collectCoverage: true, + mapCoverage: true, }); expect(result.sourceMapPath).toEqual(expect.any(String)); expect(fs.writeFileSync).toBeCalledWith( @@ -248,7 +248,6 @@ describe('ScriptTransformer', () => { it('writes source map if preprocessor inlines it', () => { config = Object.assign(config, { - mapCoverage: true, transform: [['^.+\\.js$', 'preprocessor-with-sourcemaps']], }); const scriptTransformer = new ScriptTransformer(config); @@ -267,6 +266,7 @@ describe('ScriptTransformer', () => { const result = scriptTransformer.transform('/fruits/banana.js', { collectCoverage: true, + mapCoverage: true, }); expect(result.sourceMapPath).toEqual(expect.any(String)); expect(fs.writeFileSync).toBeCalledWith( @@ -276,9 +276,8 @@ describe('ScriptTransformer', () => { ); }); - it('does not write source map if mapCoverage config option is false', () => { + it('does not write source map if mapCoverage option is false', () => { config = Object.assign(config, { - mapCoverage: false, transform: [['^.+\\.js$', 'preprocessor-with-sourcemaps']], }); const scriptTransformer = new ScriptTransformer(config); @@ -295,6 +294,7 @@ describe('ScriptTransformer', () => { const result = scriptTransformer.transform('/fruits/banana.js', { collectCoverage: true, + mapCoverage: false, }); expect(result.sourceMapPath).toBeFalsy(); expect(fs.writeFileSync).toHaveBeenCalledTimes(1); diff --git a/packages/jest-runtime/src/index.js b/packages/jest-runtime/src/index.js index f8b8d5591bfb..e670f838d55d 100644 --- a/packages/jest-runtime/src/index.js +++ b/packages/jest-runtime/src/index.js @@ -54,6 +54,7 @@ type CoverageOptions = { collectCoverage: boolean, collectCoverageFrom: Array, collectCoverageOnlyFrom: ?{[key: string]: boolean}, + mapCoverage: boolean, }; type BooleanObject = {[key: string]: boolean}; @@ -121,6 +122,7 @@ class Runtime { collectCoverage: false, collectCoverageFrom: [], collectCoverageOnlyFrom: null, + mapCoverage: false, }; this._currentlyExecutingModulePath = ''; this._environment = environment; @@ -186,6 +188,7 @@ class Runtime { collectCoverage: options.collectCoverage, collectCoverageFrom: options.collectCoverageFrom, collectCoverageOnlyFrom: options.collectCoverageOnlyFrom, + mapCoverage: options.mapCoverage, }, config, ); @@ -500,6 +503,7 @@ class Runtime { collectCoverageFrom: this._coverageOptions.collectCoverageFrom, collectCoverageOnlyFrom: this._coverageOptions.collectCoverageOnlyFrom, isInternalModule, + mapCoverage: this._coverageOptions.mapCoverage, }, this._cacheFS[filename], ); From 36d9b982251b4357cbe72a01d7d23806bc67e572 Mon Sep 17 00:00:00 2001 From: cpojer Date: Fri, 28 Apr 2017 00:49:48 +0100 Subject: [PATCH 3/3] Rename `config` to `globalConfig` --- packages/jest-cli/src/TestRunner.js | 33 +++++++++++-------- .../jest-cli/src/reporters/BaseReporter.js | 4 +-- .../jest-cli/src/reporters/DefaultReporter.js | 2 +- .../jest-cli/src/reporters/NotifyReporter.js | 2 +- 4 files changed, 23 insertions(+), 18 deletions(-) diff --git a/packages/jest-cli/src/TestRunner.js b/packages/jest-cli/src/TestRunner.js index 2edcced303da..3b53f0b990ff 100644 --- a/packages/jest-cli/src/TestRunner.js +++ b/packages/jest-cli/src/TestRunner.js @@ -56,12 +56,12 @@ type OnTestSuccess = (test: Test, result: TestResult) => void; const TEST_WORKER_PATH = require.resolve('./TestWorker'); class TestRunner { - _config: GlobalConfig; + _globalConfig: GlobalConfig; _options: Options; _dispatcher: ReporterDispatcher; - constructor(config: GlobalConfig, options: Options) { - this._config = config; + constructor(globalConfig: GlobalConfig, options: Options) { + this._globalConfig = globalConfig; this._dispatcher = new ReporterDispatcher(); this._options = options; this._setupReporters(); @@ -125,7 +125,7 @@ class TestRunner { testResult.failureMessage = formatExecError( testResult, test.context.config, - this._config, + this._globalConfig, test.path, ); addResult(aggregatedResults, testResult); @@ -136,18 +136,19 @@ class TestRunner { contexts.forEach(context => { const status = snapshot.cleanup( context.hasteFS, - this._config.updateSnapshot, + this._globalConfig.updateSnapshot, ); aggregatedResults.snapshot.filesRemoved += status.filesRemoved; }); - aggregatedResults.snapshot.didUpdate = this._config.updateSnapshot; - aggregatedResults.snapshot.failure = !!(!this._config.updateSnapshot && + aggregatedResults.snapshot.didUpdate = this._globalConfig.updateSnapshot; + aggregatedResults.snapshot.failure = !!(!this._globalConfig + .updateSnapshot && (aggregatedResults.snapshot.unchecked || aggregatedResults.snapshot.unmatched || aggregatedResults.snapshot.filesRemoved)); }; - this._dispatcher.onRunStart(this._config, aggregatedResults, { + this._dispatcher.onRunStart(this._globalConfig, aggregatedResults, { estimatedTime, showStatus: !runInBand, }); @@ -165,7 +166,11 @@ class TestRunner { updateSnapshotState(); aggregatedResults.wasInterrupted = watcher.isInterrupted(); - this._dispatcher.onRunComplete(contexts, this._config, aggregatedResults); + this._dispatcher.onRunComplete( + contexts, + this._globalConfig, + aggregatedResults, + ); const anyTestFailures = !(aggregatedResults.numFailedTests === 0 && aggregatedResults.numRuntimeErrorTestSuites === 0); @@ -197,7 +202,7 @@ class TestRunner { this._dispatcher.onTestStart(test); return runTest( test.path, - this._config, + this._globalConfig, test.context.config, test.context.resolver, ); @@ -237,7 +242,7 @@ class TestRunner { this._dispatcher.onTestStart(test); return worker({ config: test.context.config, - globalConfig: this._config, + globalConfig: this._globalConfig, path: test.path, rawModuleMap: watcher.isWatchMode() ? test.context.moduleMap.getRawModuleMap() @@ -277,7 +282,7 @@ class TestRunner { } _setupReporters() { - const {collectCoverage, expand, notify, verbose} = this._config; + const {collectCoverage, expand, notify, verbose} = this._globalConfig; this.addReporter( verbose @@ -303,13 +308,13 @@ class TestRunner { aggregatedResults: AggregatedResult, watcher: TestWatcher, ) { - if (this._config.bail && aggregatedResults.numFailedTests !== 0) { + if (this._globalConfig.bail && aggregatedResults.numFailedTests !== 0) { if (watcher.isWatchMode()) { watcher.setState({interrupted: true}); } else { this._dispatcher.onRunComplete( contexts, - this._config, + this._globalConfig, aggregatedResults, ); process.exit(1); diff --git a/packages/jest-cli/src/reporters/BaseReporter.js b/packages/jest-cli/src/reporters/BaseReporter.js index f9d3782c213b..4d97be9f8188 100644 --- a/packages/jest-cli/src/reporters/BaseReporter.js +++ b/packages/jest-cli/src/reporters/BaseReporter.js @@ -25,7 +25,7 @@ class BaseReporter { } onRunStart( - config: GlobalConfig, + globalConfig: GlobalConfig, results: AggregatedResult, options: ReporterOnStartOptions, ) { @@ -38,7 +38,7 @@ class BaseReporter { onRunComplete( contexts: Set, - config: GlobalConfig, + globalConfig: GlobalConfig, aggregatedResults: AggregatedResult, ): ?Promise {} diff --git a/packages/jest-cli/src/reporters/DefaultReporter.js b/packages/jest-cli/src/reporters/DefaultReporter.js index 8ca17f9b60c3..7d1095a00f33 100644 --- a/packages/jest-cli/src/reporters/DefaultReporter.js +++ b/packages/jest-cli/src/reporters/DefaultReporter.js @@ -112,7 +112,7 @@ class DefaultReporter extends BaseReporter { } onRunStart( - config: GlobalConfig, + globalConfig: GlobalConfig, aggregatedResults: AggregatedResult, options: ReporterOnStartOptions, ) { diff --git a/packages/jest-cli/src/reporters/NotifyReporter.js b/packages/jest-cli/src/reporters/NotifyReporter.js index 93772a412fe4..dd165edb3a00 100644 --- a/packages/jest-cli/src/reporters/NotifyReporter.js +++ b/packages/jest-cli/src/reporters/NotifyReporter.js @@ -32,7 +32,7 @@ class NotifyReporter extends BaseReporter { onRunComplete( contexts: Set, - config: GlobalConfig, + globalConfig: GlobalConfig, result: AggregatedResult, ): void { const success =