Skip to content

Commit 76e27c1

Browse files
committed
fix(source-maps): fix source maps options/calls
1 parent 60ab36e commit 76e27c1

12 files changed

Lines changed: 85 additions & 58 deletions

src/postprocess.ts

Lines changed: 60 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,6 @@
55
import * as __types__babel from 'babel-core';
66
import __types__istanbulPlugin from 'babel-plugin-istanbul';
77
import * as __types__jestPreset from 'babel-preset-jest';
8-
let babel: typeof __types__babel;
9-
let istanbulPlugin: typeof __types__istanbulPlugin;
10-
let jestPreset: typeof __types__jestPreset;
11-
function importBabelDeps() {
12-
if (babel) return; // tslint:disable-line
13-
// ensure we use the require from jest
14-
babel = require.main.require('@babel/core');
15-
istanbulPlugin = require.main.require('babel-plugin-istanbul').default;
16-
jestPreset = require.main.require('babel-preset-jest');
17-
}
188
import {
199
BabelTransformOptions,
2010
PostProcessHook,
@@ -23,6 +13,18 @@ import {
2313
import { logOnce } from './utils/logger';
2414
import getTSJestConfig from './utils/get-ts-jest-config';
2515

16+
let babel: typeof __types__babel;
17+
let istanbulPlugin: typeof __types__istanbulPlugin;
18+
let jestPreset: typeof __types__jestPreset;
19+
20+
function importBabelDeps() {
21+
if (babel) return; // tslint:disable-line
22+
// we must use babel until we handle hoisting of jest.mock() internally
23+
babel = require('@babel/core');
24+
istanbulPlugin = require('babel-plugin-istanbul').default;
25+
jestPreset = require('babel-preset-jest');
26+
}
27+
2628
// Function that takes the transpiled typescript and runs it through babel/whatever.
2729
export function postProcessCode(
2830
jestConfig: jest.ProjectConfig,
@@ -39,37 +41,43 @@ function createBabelTransformer(
3941
options: BabelTransformOptions,
4042
): PostProcessHook {
4143
importBabelDeps();
42-
options = {
43-
...options,
44-
plugins: options.plugins || [],
45-
presets: (options.presets || []).concat([jestPreset]),
46-
};
47-
delete options.cacheDirectory;
48-
delete options.filename;
44+
const presets = options.presets.slice();
45+
const plugins = options.plugins.slice();
46+
47+
// adds babel-preset-jest if not present
48+
if (!hasBabelAddon(presets, jestPreset)) {
49+
presets.push(jestPreset);
50+
}
51+
52+
// we need to know if there is istanbul plugin in the list so that we do not add it
53+
// in the case the user already has it configured
54+
const hasIstanbul = hasBabelAddon(plugins, istanbulPlugin);
55+
56+
// create a new object we'll use as options with the sliced presets and plugins
57+
const optionsBase = { ...options, presets, plugins };
4958

50-
return (
59+
delete optionsBase.cacheDirectory;
60+
61+
const babelTransformer = (
5162
codeSourcemapPair: jest.TransformedSource,
5263
filename: string,
5364
config: jest.ProjectConfig,
5465
transformOptions: JestCacheKeyOptions,
5566
): jest.TransformedSource => {
56-
const theseOptions = Object.assign(
57-
{ filename, inputSourceMap: codeSourcemapPair.map },
58-
options,
59-
);
67+
const inputSourceMap =
68+
typeof codeSourcemapPair.map === 'string'
69+
? JSON.parse(codeSourcemapPair.map)
70+
: codeSourcemapPair.map;
71+
const theseOptions = { ...optionsBase, filename, inputSourceMap };
6072
if (transformOptions && transformOptions.instrument) {
6173
theseOptions.auxiliaryCommentBefore = ' istanbul ignore next ';
6274
// Copied from jest-runtime transform.js
63-
theseOptions.plugins = theseOptions.plugins.concat([
64-
[
65-
istanbulPlugin,
66-
{
67-
// files outside `cwd` will not be instrumented
68-
cwd: config.rootDir,
69-
exclude: [],
70-
},
71-
],
72-
]);
75+
if (!hasIstanbul) {
76+
theseOptions.plugins = [
77+
...theseOptions.plugins,
78+
istanbulPluginConfig(config),
79+
];
80+
}
7381
}
7482

7583
// we typecast here because babel returns a more complete object than the one expected by jest
@@ -78,6 +86,8 @@ function createBabelTransformer(
7886
theseOptions,
7987
) as jest.TransformedSource;
8088
};
89+
90+
return babelTransformer;
8191
}
8292

8393
export const getPostProcessHook = (
@@ -96,7 +106,7 @@ export const getPostProcessHook = (
96106
babelrc: tsJestConfig.useBabelrc || false,
97107
plugins: toArray(tsJestBabelConfig.plugins),
98108
presets: toArray(tsJestBabelConfig.presets),
99-
sourceMaps: !tsJestConfig.disableSourceMapSupport,
109+
sourceMaps: tsJestConfig.disableSourceMapSupport ? false : 'both',
100110
};
101111

102112
logOnce('Using babel with options:', babelOptions);
@@ -107,3 +117,20 @@ export const getPostProcessHook = (
107117
function toArray<T>(iter?: Iterable<T> | null): T[] {
108118
return iter ? Array.from(iter) : [];
109119
}
120+
121+
function istanbulPluginConfig(jestConfig: jest.ProjectConfig) {
122+
return [
123+
istanbulPlugin,
124+
{
125+
// files outside `cwd` will not be instrumented
126+
cwd: jestConfig.rootDir,
127+
exclude: [],
128+
},
129+
];
130+
}
131+
132+
function hasBabelAddon(inputList: any[], ...addonMatches: any[]): boolean {
133+
return inputList.some(item => {
134+
return addonMatches.indexOf(Array.isArray(item) ? item[0] : item) !== -1;
135+
});
136+
}

src/preprocess.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ export default function preprocess(
4444

4545
const transpileOutput = transpileTypescript(filePath, src, compilerOptions);
4646

47+
// FIXME: this should be done in the typescript source, else it's invalidating source maps
4748
if (tsJestConfig.ignoreCoverageForAllDecorators === true) {
4849
transpileOutput.code = transpileOutput.code.replace(
4950
/\b__decorate\b/g,

src/transpiler.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,12 @@ export function transpileTypescript(
88
compilerOptions: ts.CompilerOptions,
99
): jest.TransformedSource {
1010
logOnce('Compiling via normal transpileModule call');
11-
const transpileOutput = transpileViaTranspileModule(
11+
const { outputText: code, sourceMapText: map } = transpileViaTranspileModule(
1212
filePath,
1313
fileSrc,
1414
compilerOptions,
1515
);
16-
return {
17-
code: transpileOutput.outputText,
18-
map: transpileOutput.sourceMapText,
19-
};
16+
return { code, map };
2017
}
2118

2219
/**

src/utils/get-ts-config.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ function getTSConfig_local(jestConfig: jest.ProjectConfig): CompilerOptions {
4545
// ts-jest will map lines numbers properly if inlineSourceMap and
4646
// inlineSources are set to true. The sourceMap configuration
4747
// is used to send the sourcemap back to Jest
48-
delete config.sourceMap;
49-
config.inlineSourceMap = true;
48+
config.inlineSourceMap = false;
49+
config.sourceMap = true;
5050
config.inlineSources = true;
5151

5252
// the coverage report is broken if `.outDir` is set

tests/__tests__/__snapshots__/ts-coverage-async.spec.ts.snap

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33
exports[`Typescript async coverage Should generate the correct async coverage numbers 1`] = `
44
"
55
=============================== Coverage summary ===============================
6-
Statements : 68.75% ( 11/16 )
6+
Statements : 71.43% ( 10/14 )
77
Branches : 33.33% ( 2/6 )
88
Functions : 66.67% ( 4/6 )
9-
Lines : 73.33% ( 11/15 )
9+
Lines : 66.67% ( 8/12 )
1010
================================================================================
1111
"
1212
`;

tests/__tests__/__snapshots__/ts-coverage.spec.ts.snap

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33
exports[`Typescript coverage Should generate the correct coverage numbers. 1`] = `
44
"
55
=============================== Coverage summary ===============================
6-
Statements : 68.75% ( 11/16 )
6+
Statements : 71.43% ( 10/14 )
77
Branches : 33.33% ( 2/6 )
88
Functions : 66.67% ( 4/6 )
9-
Lines : 73.33% ( 11/15 )
9+
Lines : 66.67% ( 8/12 )
1010
================================================================================
1111
"
1212
`;

tests/__tests__/__snapshots__/tsconfig-comments.spec.ts.snap

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,12 @@ Object {
66
"declaration": false,
77
"declarationMap": false,
88
"emitDeclarationOnly": false,
9-
"inlineSourceMap": true,
9+
"inlineSourceMap": false,
1010
"inlineSources": true,
1111
"jsx": 2,
1212
"module": 1,
1313
"pretty": false,
14+
"sourceMap": true,
1415
}
1516
`;
1617

@@ -20,10 +21,11 @@ Object {
2021
"declaration": false,
2122
"declarationMap": false,
2223
"emitDeclarationOnly": false,
23-
"inlineSourceMap": true,
24+
"inlineSourceMap": false,
2425
"inlineSources": true,
2526
"jsx": 2,
2627
"module": 1,
2728
"pretty": false,
29+
"sourceMap": true,
2830
}
2931
`;

tests/__tests__/__snapshots__/tsconfig-default.spec.ts.snap

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,13 @@ Object {
88
"declaration": false,
99
"declarationMap": false,
1010
"emitDeclarationOnly": false,
11-
"inlineSourceMap": true,
11+
"inlineSourceMap": false,
1212
"inlineSources": true,
1313
"jsx": 2,
1414
"module": 1,
1515
"moduleResolution": 2,
1616
"noEmitOnError": false,
17+
"sourceMap": true,
1718
"target": 2,
1819
}
1920
`;

tests/__tests__/__snapshots__/tsconfig-string.spec.ts.snap

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,14 @@ Object {
66
"declaration": false,
77
"declarationMap": false,
88
"emitDeclarationOnly": false,
9-
"inlineSourceMap": true,
9+
"inlineSourceMap": false,
1010
"inlineSources": true,
1111
"jsx": 2,
1212
"module": 1,
1313
"moduleResolution": 2,
1414
"noEmitOnError": true,
1515
"noImplicitAny": true,
16+
"sourceMap": true,
1617
"target": 1,
1718
}
1819
`;
@@ -23,12 +24,13 @@ Object {
2324
"declaration": false,
2425
"declarationMap": false,
2526
"emitDeclarationOnly": false,
26-
"inlineSourceMap": true,
27+
"inlineSourceMap": false,
2728
"inlineSources": true,
2829
"jsx": 2,
2930
"module": 1,
3031
"moduleResolution": 2,
3132
"noEmitOnError": true,
33+
"sourceMap": true,
3234
"target": 2,
3335
}
3436
`;
@@ -39,12 +41,13 @@ Object {
3941
"declaration": false,
4042
"declarationMap": false,
4143
"emitDeclarationOnly": false,
42-
"inlineSourceMap": true,
44+
"inlineSourceMap": false,
4345
"inlineSources": true,
4446
"jsx": 2,
4547
"module": 1,
4648
"moduleResolution": 2,
4749
"noEmitOnError": true,
50+
"sourceMap": true,
4851
"target": 2,
4952
}
5053
`;

tests/__tests__/jest-hoist.spec.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,6 @@ describe('Jest.mock() calls', () => {
1515
const stderr = result.stderr;
1616

1717
expect(stderr).toContain('Hello.ts:22:11');
18-
// TODO FIX COMMENT - sourcemap is accurate now
19-
// The actual error occurs at line 14. However, because the mock calls
20-
// are hoisted, this changes - in this case, to 22
21-
// The column numbers are accurate.
2218
expect(stderr).toContain('Hello.test.ts:14:19');
2319

2420
expect(result.status).toBe(1);

0 commit comments

Comments
 (0)