Skip to content

Commit

Permalink
feat: pass ESM options to Babel (#9766)
Browse files Browse the repository at this point in the history
  • Loading branch information
SimenB committed Apr 5, 2020
1 parent 8aea972 commit bb720d2
Show file tree
Hide file tree
Showing 13 changed files with 150 additions and 37 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Expand Up @@ -2,6 +2,8 @@

### Features

- `[babel-jest]` Support passing `supportsDynamicImport` and `supportsStaticESM` ([#9766](https://github.com/facebook/jest/pull/9766))

### Fixes

### Chore & Maintenance
Expand Down
2 changes: 1 addition & 1 deletion e2e/__tests__/__snapshots__/transform.test.ts.snap
Expand Up @@ -6,7 +6,7 @@ FAIL __tests__/ignoredFile.test.js
babel-jest: Babel ignores __tests__/ignoredFile.test.js - make sure to include the file in Jest's transformIgnorePatterns as well.
at loadBabelConfig (../../../packages/babel-jest/build/index.js:191:13)
at loadBabelConfig (../../../packages/babel-jest/build/index.js:227:13)
`;

exports[`babel-jest instruments only specific files and collects coverage 1`] = `
Expand Down
2 changes: 1 addition & 1 deletion packages/babel-jest/package.json
Expand Up @@ -20,7 +20,7 @@
"dependencies": {
"@jest/transform": "^25.2.6",
"@jest/types": "^25.2.6",
"@types/babel__core": "^7.1.0",
"@types/babel__core": "^7.1.7",
"babel-plugin-istanbul": "^6.0.0",
"babel-preset-jest": "^25.2.6",
"chalk": "^3.0.0",
Expand Down
70 changes: 66 additions & 4 deletions packages/babel-jest/src/__tests__/index.ts
Expand Up @@ -5,9 +5,18 @@
* LICENSE file in the root directory of this source tree.
*/

import babelJest from '../index';
import babelJest = require('../index');
import {loadPartialConfig} from '../loadBabelConfig';
import {makeProjectConfig} from '../../../../TestUtils';

jest.mock('../loadBabelConfig', () => {
const actual = jest.requireActual('@babel/core');

return {
loadPartialConfig: jest.fn((...args) => actual.loadPartialConfig(...args)),
};
});

//Mock data for all the tests
const sourceString = `
const sum = (a, b) => a+b;
Expand All @@ -21,7 +30,11 @@ const customMultiply = (obj, mul) => {
customMultiply({a: 32, dummy: "test"}, 2);
`;

test(`Returns source string with inline maps when no transformOptions is passed`, () => {
beforeEach(() => {
jest.clearAllMocks();
});

test('Returns source string with inline maps when no transformOptions is passed', () => {
const result = babelJest.process(
sourceString,
'dummy_path.js',
Expand All @@ -32,6 +45,55 @@ test(`Returns source string with inline maps when no transformOptions is passed`
expect(result.map).toBeDefined();
expect(result.code).toMatch('//# sourceMappingURL');
expect(result.code).toMatch('customMultiply');
expect(result.map.sources).toEqual(['dummy_path.js']);
expect(JSON.stringify(result.map.sourcesContent)).toMatch('customMultiply');
expect(result.map!.sources).toEqual(['dummy_path.js']);
expect(JSON.stringify(result.map!.sourcesContent)).toMatch('customMultiply');
});

describe('caller option correctly merges from defaults and options', () => {
test.each([
[
{
supportsDynamicImport: true,
supportsStaticESM: true,
},
{
supportsDynamicImport: true,
supportsStaticESM: true,
},
],
[
{
supportsDynamicImport: false,
supportsStaticESM: false,
},
{
supportsDynamicImport: false,
supportsStaticESM: false,
},
],
[
{supportsStaticESM: false},
{
supportsDynamicImport: false,
supportsStaticESM: false,
},
],
[
{supportsDynamicImport: true},
{
supportsDynamicImport: true,
supportsStaticESM: false,
},
],
])('%j -> %j', (input, output) => {
babelJest.process(sourceString, 'dummy_path.js', makeProjectConfig(), {
instrument: false,
...input,
});

expect(loadPartialConfig).toHaveBeenCalledTimes(1);
expect(loadPartialConfig).toHaveBeenCalledWith(
expect.objectContaining({caller: {name: 'babel-jest', ...output}}),
);
});
});
65 changes: 48 additions & 17 deletions packages/babel-jest/src/index.ts
Expand Up @@ -8,14 +8,19 @@
import {createHash} from 'crypto';
import * as fs from 'fs';
import * as path from 'path';
import type {Transformer} from '@jest/transform';
import type {
TransformOptions as JestTransformOptions,
Transformer,
} from '@jest/transform';
import type {Config} from '@jest/types';
import {
PartialConfig,
PluginItem,
TransformCaller,
TransformOptions,
transformSync as babelTransform,
loadPartialConfig,
} from '@babel/core';
import {loadPartialConfig} from './loadBabelConfig';
import chalk = require('chalk');
import slash = require('slash');

Expand All @@ -27,28 +32,51 @@ const babelIstanbulPlugin = require.resolve('babel-plugin-istanbul');
interface BabelJestTransformer extends Transformer {
canInstrument: true;
}
interface BabelJestTransformOptions extends TransformOptions {
caller: TransformCaller;
compact: false;
plugins: Array<PluginItem>;
presets: Array<PluginItem>;
sourceMaps: 'both';
}

const createTransformer = (
options: TransformOptions = {},
inputOptions: TransformOptions = {},
): BabelJestTransformer => {
options = {
...options,
const options: BabelJestTransformOptions = {
...inputOptions,
caller: {
name: 'babel-jest',
supportsDynamicImport: false,
supportsStaticESM: false,
...inputOptions.caller,
},
compact: false,
plugins: (options && options.plugins) || [],
presets: ((options && options.presets) || []).concat(jestPresetPath),
plugins: inputOptions.plugins ?? [],
presets: (inputOptions.presets ?? []).concat(jestPresetPath),
sourceMaps: 'both',
};

function loadBabelConfig(
cwd: Config.Path,
filename: Config.Path,
transformOptions?: JestTransformOptions,
): PartialConfig {
// `cwd` first to allow incoming options to override it
const babelConfig = loadPartialConfig({cwd, ...options, filename});
const babelConfig = loadPartialConfig({
cwd,
...options,
caller: {
...options.caller,
supportsDynamicImport:
transformOptions?.supportsDynamicImport ??
options.caller.supportsDynamicImport,
supportsStaticESM:
transformOptions?.supportsStaticESM ??
options.caller.supportsStaticESM,
},
filename,
});

if (!babelConfig) {
throw new Error(
Expand All @@ -65,13 +93,14 @@ const createTransformer = (

return {
canInstrument: true,
getCacheKey(
fileData,
filename,
configString,
{config, instrument, rootDir},
) {
const babelOptions = loadBabelConfig(config.cwd, filename);
getCacheKey(fileData, filename, configString, cacheKeyOptions) {
const {config, instrument, rootDir} = cacheKeyOptions;

const babelOptions = loadBabelConfig(
config.cwd,
filename,
cacheKeyOptions,
);
const configPath = [
babelOptions.config || '',
babelOptions.babelrc || '',
Expand All @@ -98,9 +127,11 @@ const createTransformer = (
.digest('hex');
},
process(src, filename, config, transformOptions) {
const babelOptions = {...loadBabelConfig(config.cwd, filename).options};
const babelOptions = {
...loadBabelConfig(config.cwd, filename, transformOptions).options,
};

if (transformOptions && transformOptions.instrument) {
if (transformOptions?.instrument) {
babelOptions.auxiliaryCommentBefore = ' istanbul ignore next ';
// Copied from jest-runtime transform.js
babelOptions.plugins = (babelOptions.plugins || []).concat([
Expand Down
9 changes: 9 additions & 0 deletions packages/babel-jest/src/loadBabelConfig.ts
@@ -0,0 +1,9 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

// this is a separate file so it can be mocked in tests
export {loadPartialConfig} from '@babel/core';
6 changes: 1 addition & 5 deletions packages/jest-runtime/src/index.ts
Expand Up @@ -497,11 +497,7 @@ class Runtime {
): TransformationOptions {
return {
...options,
changedFiles: this._coverageOptions.changedFiles,
collectCoverage: this._coverageOptions.collectCoverage,
collectCoverageFrom: this._coverageOptions.collectCoverageFrom,
collectCoverageOnlyFrom: this._coverageOptions.collectCoverageOnlyFrom,
coverageProvider: this._coverageOptions.coverageProvider,
...this._coverageOptions,
};
}

Expand Down
1 change: 1 addition & 0 deletions packages/jest-runtime/tsconfig.json
Expand Up @@ -17,6 +17,7 @@
{"path": "../jest-snapshot"},
{"path": "../jest-source-map"},
{"path": "../jest-test-result"},
{"path": "../jest-transform"},
{"path": "../jest-types"},
{"path": "../jest-util"},
{"path": "../jest-validate"},
Expand Down
4 changes: 4 additions & 0 deletions packages/jest-transform/src/ScriptTransformer.ts
Expand Up @@ -101,6 +101,8 @@ export default class ScriptTransformer {
config: this._config,
instrument,
rootDir: this._config.rootDir,
supportsDynamicImport: false,
supportsStaticESM: false,
}),
)
.update(CACHE_VERSION)
Expand Down Expand Up @@ -285,6 +287,8 @@ export default class ScriptTransformer {
if (transform && shouldCallTransform) {
const processed = transform.process(content, filename, this._config, {
instrument,
supportsDynamicImport: false,
supportsStaticESM: false,
});

if (typeof processed === 'string') {
Expand Down
Expand Up @@ -71,6 +71,8 @@ Object {
},
"instrument": true,
"rootDir": "/",
"supportsDynamicImport": false,
"supportsStaticESM": false,
}
`;

Expand Down
1 change: 1 addition & 0 deletions packages/jest-transform/src/index.ts
Expand Up @@ -15,6 +15,7 @@ export type {
Transformer,
ShouldInstrumentOptions,
Options as TransformationOptions,
TransformOptions,
TransformResult,
TransformedSource,
} from './types';
Expand Down
15 changes: 10 additions & 5 deletions packages/jest-transform/src/types.ts
Expand Up @@ -22,6 +22,8 @@ export type Options = ShouldInstrumentOptions &
Partial<{
isCoreModule: boolean;
isInternalModule: boolean;
supportsDynamicImport: boolean;
supportsStaticESM: boolean;
}>;

// extends directly after https://github.com/sandersn/downlevel-dts/issues/33 is fixed
Expand All @@ -38,15 +40,18 @@ export type TransformedSource =

export type TransformResult = TransformTypes.TransformResult;

export type TransformOptions = {
export interface TransformOptions {
instrument: boolean;
};
// names are copied from babel
supportsDynamicImport?: boolean;
supportsStaticESM?: boolean;
}

export type CacheKeyOptions = {
// TODO: For Jest 26 we should combine these into one options shape
export interface CacheKeyOptions extends TransformOptions {
config: Config.ProjectConfig;
instrument: boolean;
rootDir: string;
};
}

export interface Transformer {
canInstrument?: boolean;
Expand Down
8 changes: 4 additions & 4 deletions yarn.lock
Expand Up @@ -2137,10 +2137,10 @@
resolved "https://registry.yarnpkg.com/@types/babel__code-frame/-/babel__code-frame-7.0.1.tgz#baf2529c4abbfb5e4008c845efcfe39a187e2f99"
integrity sha512-FFfbQozKxYmOnCKFYV+EQprjBI7u2yaNc2ly/K9AhzyC8MzXtCtSRqptpw+HUJxhwCOo5mLwf1ATmzyhOaVbDg==

"@types/babel__core@^7.0.0", "@types/babel__core@^7.0.4", "@types/babel__core@^7.1.0":
version "7.1.6"
resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.6.tgz#16ff42a5ae203c9af1c6e190ed1f30f83207b610"
integrity sha512-tTnhWszAqvXnhW7m5jQU9PomXSiKXk2sFxpahXvI20SZKu9ylPi8WtIxueZ6ehDWikPT0jeFujMj3X4ZHuf3Tg==
"@types/babel__core@^7.0.0", "@types/babel__core@^7.0.4", "@types/babel__core@^7.1.0", "@types/babel__core@^7.1.7":
version "7.1.7"
resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.7.tgz#1dacad8840364a57c98d0dd4855c6dd3752c6b89"
integrity sha512-RL62NqSFPCDK2FM1pSDH0scHpJvsXtZNiYlMB73DgPBaG1E38ZYVL+ei5EkWRbr+KC4YNiAUNBnRj+bgwpgjMw==
dependencies:
"@babel/parser" "^7.1.0"
"@babel/types" "^7.0.0"
Expand Down

0 comments on commit bb720d2

Please sign in to comment.