diff --git a/CHANGELOG.md b/CHANGELOG.md index 60c67811be0f..406439dec54c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -45,6 +45,7 @@ - `[jest-config]` Allow % based configuration of `--max-workers` ([#7494](https://github.com/facebook/jest/pull/7494)) - `[jest-runner]` Instantiate the test environment class with the current `testPath` ([#7442](https://github.com/facebook/jest/pull/7442)) - `[jest-config]` Always resolve jest-environment-jsdom from jest-config ([#7476](https://github.com/facebook/jest/pull/7476)) +- `[jest-cli]` Run code transforms over `global{Setup,Teardown}` ([#7562](https://github.com/facebook/jest/pull/7562)) ### Fixes diff --git a/e2e/global-setup/babel.config.js b/e2e/global-setup/babel.config.js new file mode 100644 index 000000000000..dcda2fba8b21 --- /dev/null +++ b/e2e/global-setup/babel.config.js @@ -0,0 +1,5 @@ +// Copyright (c) 2014-present, Facebook, Inc. All rights reserved. + +module.exports = { + presets: ['@babel/preset-flow'], +}; diff --git a/e2e/global-setup/setup.js b/e2e/global-setup/setup.js index a1bccb1b815d..0bd3b2d28b5d 100644 --- a/e2e/global-setup/setup.js +++ b/e2e/global-setup/setup.js @@ -13,7 +13,8 @@ const path = require('path'); const DIR = path.join(os.tmpdir(), 'jest-global-setup'); module.exports = function() { - return new Promise((resolve, reject) => { + // This uses a flow annotation to show it can be transpiled + return new Promise((resolve, reject: any) => { mkdirp.sync(DIR); const fileId = crypto.randomBytes(20).toString('hex'); fs.writeFileSync(path.join(DIR, fileId), 'setup'); diff --git a/packages/jest-cli/package.json b/packages/jest-cli/package.json index a3f983466ea1..59e7d2422adf 100644 --- a/packages/jest-cli/package.json +++ b/packages/jest-cli/package.json @@ -32,6 +32,8 @@ "jest-worker": "^23.2.0", "micromatch": "^2.3.11", "node-notifier": "^5.2.1", + "p-each-series": "^1.0.0", + "pirates": "^4.0.0", "prompts": "^1.1.0", "realpath-native": "^1.0.0", "rimraf": "^2.5.4", diff --git a/packages/jest-cli/src/runGlobalHook.js b/packages/jest-cli/src/runGlobalHook.js index 4fec38ce2a43..b779d12c8b58 100644 --- a/packages/jest-cli/src/runGlobalHook.js +++ b/packages/jest-cli/src/runGlobalHook.js @@ -6,9 +6,22 @@ * * @flow */ + import type {GlobalConfig} from 'types/Config'; import type {Test} from 'types/TestRunner'; +import {extname, resolve} from 'path'; +import pEachSeries from 'p-each-series'; +import {addHook} from 'pirates'; +import {ScriptTransformer} from 'jest-runtime'; + +const inJestsSource = __dirname.includes('packages/jest-cli'); +let packagesRoot; + +if (inJestsSource) { + packagesRoot = resolve(__dirname, '../../'); +} + export default ({ allTests, globalConfig, @@ -17,7 +30,7 @@ export default ({ allTests: Array, globalConfig: GlobalConfig, moduleName: 'globalSetup' | 'globalTeardown', -}): Promise => { +}): Promise => { const globalModulePaths = new Set( allTests.map(test => test.context.config[moduleName]), ); @@ -27,24 +40,48 @@ export default ({ } if (globalModulePaths.size > 0) { - return Promise.all( - Array.from(globalModulePaths).map(async modulePath => { - if (!modulePath) { - return null; - } - - // $FlowFixMe - const globalModule = require(modulePath); - - if (typeof globalModule !== 'function') { - throw new TypeError( - `${moduleName} file must export a function at ${modulePath}`, - ); - } - - return globalModule(globalConfig); - }), - ); + return pEachSeries(Array.from(globalModulePaths), async modulePath => { + if (!modulePath) { + return; + } + + const projectConfig = + allTests + .map(t => t.context.config) + .find(c => c[moduleName] === modulePath) || + // Fallback to first one + allTests[0].context.config; + + const transformer = new ScriptTransformer(projectConfig); + + const revertHook = addHook( + (code, filename) => + transformer.transformSource(filename, code, false).code || code, + { + exts: [extname(modulePath)], + matcher(filename) { + // `babel-jest` etc would normally be caught by `node_modules`, but not in Jest's own repo + if (inJestsSource && filename.includes(packagesRoot)) { + return false; + } + return transformer._shouldTransform(filename); + }, + }, + ); + + // $FlowFixMe + const globalModule = require(modulePath); + + if (typeof globalModule !== 'function') { + throw new TypeError( + `${moduleName} file must export a function at ${modulePath}`, + ); + } + + await globalModule(globalConfig); + + revertHook(); + }); } return Promise.resolve(); diff --git a/yarn.lock b/yarn.lock index 389533396255..5888922bb840 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9858,6 +9858,13 @@ p-defer@^1.0.0: resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c" integrity sha1-n26xgvbJqozXQwBKfU+WsZaw+ww= +p-each-series@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-each-series/-/p-each-series-1.0.0.tgz#930f3d12dd1f50e7434457a22cd6f04ac6ad7f71" + integrity sha1-kw89Et0fUOdDRFeiLNbwSsatf3E= + dependencies: + p-reduce "^1.0.0" + p-finally@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae"