Skip to content

Commit

Permalink
move source map info from coverage object to jest-runtime
Browse files Browse the repository at this point in the history
  • Loading branch information
jwbay committed Feb 16, 2017
1 parent ad11e77 commit ecbde20
Show file tree
Hide file tree
Showing 13 changed files with 134 additions and 106 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ module.exports = {
}
);
return {
content: result.outputText,
sourceMap: JSON.parse(result.sourceMapText),
code: result.outputText,
map: JSON.parse(result.sourceMapText),
};
}
return src;
Expand Down
1 change: 1 addition & 0 deletions packages/jest-cli/src/TestRunner.js
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,7 @@ const buildFailureTestResult = (
unmatched: 0,
updated: 0,
},
sourceMaps: {},
testExecError: err,
testFilePath: testPath,
testResults: [],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,5 @@ it('generates an empty coverage object for a file without running it', () => {
baseCacheDir: os.tmpdir(),
cacheDirectory: os.tmpdir(),
rootDir: os.tmpdir(),
})).toMatchSnapshot();
}).coverage).toMatchSnapshot();
});
9 changes: 6 additions & 3 deletions packages/jest-cli/src/generateEmptyCoverage.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,13 @@ module.exports = function(source: string, filename: Path, config: Config) {
if (shouldInstrument(filename, config)) {
// Transform file without instrumentation first, to make sure produced
// source code is ES6 (no flowtypes etc.) and can be instrumented
source = transformSource(filename, config, source, false);
const transformResult = transformSource(filename, config, source, false);
const instrumenter = IstanbulInstrument.createInstrumenter();
instrumenter.instrumentSync(source, filename);
return instrumenter.fileCoverage;
instrumenter.instrumentSync(transformResult.code, filename);
return {
coverage: instrumenter.fileCoverage,
sourceMapPath: transformResult.sourceMapPath,
};
} else {
return null;
}
Expand Down
28 changes: 16 additions & 12 deletions packages/jest-cli/src/reporters/CoverageReporter.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,18 +45,16 @@ class CoverageReporter extends BaseReporter {
aggregatedResults: AggregatedResult,
) {
if (testResult.coverage) {
if (config.mapCoverage) {
Object.keys(testResult.coverage).map(path => {
// $FlowFixMe - ignores null check above
const {inputSourceMapPath} = testResult.coverage[path];
if (inputSourceMapPath) {
this._sourceMapStore.registerURL(path, inputSourceMapPath);
}
});
}
this._coverageMap.merge(testResult.coverage);
// Remove coverage data to free up some memory.
delete testResult.coverage;

Object.keys(testResult.sourceMaps).forEach(sourcePath => {
this._sourceMapStore.registerURL(
sourcePath,
testResult.sourceMaps[sourcePath]
);
});
}
}

Expand Down Expand Up @@ -117,9 +115,15 @@ class CoverageReporter extends BaseReporter {
if (!this._coverageMap.data[filename]) {
try {
const source = fs.readFileSync(filename).toString();
const coverage = generateEmptyCoverage(source, filename, config);
if (coverage) {
this._coverageMap.addFileCoverage(coverage);
const result = generateEmptyCoverage(source, filename, config);
if (result) {
this._coverageMap.addFileCoverage(result.coverage);
if (result.sourceMapPath) {
this._sourceMapStore.registerURL(
filename,
result.sourceMapPath
);
}
}
} catch (e) {
console.error(chalk.red(`
Expand Down
1 change: 1 addition & 0 deletions packages/jest-cli/src/runTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ function runTest(path: Path, config: Config, resolver: Resolver) {
result.perfStats = {end: Date.now(), start};
result.testFilePath = path;
result.coverage = runtime.getAllCoverageInfo();
result.sourceMaps = runtime.getSourceMapInfo();
result.console = testConsole.getBuffer();
result.skipped = testCount === result.numPendingTests;
return result;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,3 @@
exports[`transform does not instrument with source map if mapCoverage config option is false 1`] = `
"({\\"Object.<anonymous>\\":function(module,exports,require,__dirname,__filename,global,jest){/* istanbul ignore next */var cov_25u22311x4 = function () {var path = \\"/fruits/banana.js\\",hash = \\"4a81f91764b586e5729481ba491440a08d658002\\",global = new Function('return this')(),gcv = \\"__coverage__\\",coverageData = { path: \\"/fruits/banana.js\\", statementMap: { \\"0\\": { start: { line: 1, column: 0 }, end: { line: 1, column: 7 } } }, fnMap: {}, branchMap: {}, s: { \\"0\\": 0 }, f: {}, b: {}, _coverageSchema: \\"332fd63041d2c1bcb487cc26dd0d5f7d97098a6c\\" },coverage = global[gcv] || (global[gcv] = {});if (coverage[path] && coverage[path].hash === hash) {return coverage[path];}coverageData.hash = hash;return coverage[path] = coverageData;}();++cov_25u22311x4.s[0];content;
}});"
`;

exports[`transform instruments with source map if preprocessor inlines it 1`] = `
"({\\"Object.<anonymous>\\":function(module,exports,require,__dirname,__filename,global,jest){/* istanbul ignore next */var cov_25u22311x4 = function () {var path = \\"/fruits/banana.js\\",hash = \\"051b2f7208d7f64ba1cda9a8fec8ebb925b6a32a\\",global = new Function('return this')(),gcv = \\"__coverage__\\",coverageData = { path: \\"/fruits/banana.js\\", statementMap: { \\"0\\": { start: { line: 1, column: 8 }, end: { line: 1, column: 9 } } }, fnMap: {}, branchMap: {}, s: { \\"0\\": 0 }, f: {}, b: {}, _coverageSchema: \\"332fd63041d2c1bcb487cc26dd0d5f7d97098a6c\\" },coverage = global[gcv] || (global[gcv] = {});if (coverage[path] && coverage[path].hash === hash) {return coverage[path];}coverageData.hash = hash;return coverage[path] = coverageData;}();var x = /* istanbul ignore next */(++cov_25u22311x4.s[0], 1);
;global.__coverage__['/fruits/banana.js'].inputSourceMapPath = '/cache/jest-transform-cache-test/ab/banana_ab.map';
}});"
`;

exports[`transform instruments with source map if preprocessor supplies it 1`] = `
"({\\"Object.<anonymous>\\":function(module,exports,require,__dirname,__filename,global,jest){/* istanbul ignore next */var cov_25u22311x4 = function () {var path = \\"/fruits/banana.js\\",hash = \\"4a81f91764b586e5729481ba491440a08d658002\\",global = new Function('return this')(),gcv = \\"__coverage__\\",coverageData = { path: \\"/fruits/banana.js\\", statementMap: { \\"0\\": { start: { line: 1, column: 0 }, end: { line: 1, column: 7 } } }, fnMap: {}, branchMap: {}, s: { \\"0\\": 0 }, f: {}, b: {}, _coverageSchema: \\"332fd63041d2c1bcb487cc26dd0d5f7d97098a6c\\" },coverage = global[gcv] || (global[gcv] = {});if (coverage[path] && coverage[path].hash === hash) {return coverage[path];}coverageData.hash = hash;return coverage[path] = coverageData;}();++cov_25u22311x4.s[0];content;
;global.__coverage__['/fruits/banana.js'].inputSourceMapPath = '/cache/jest-transform-cache-test/ab/banana_ab.map';
}});"
`;

exports[`transform transforms a file properly 1`] = `
"({\\"Object.<anonymous>\\":function(module,exports,require,__dirname,__filename,global,jest){/* istanbul ignore next */var cov_25u22311x4 = function () {var path = \\"/fruits/banana.js\\",hash = \\"04636d4ae73b4b3e24bf6fba39e08c946fd0afb5\\",global = new Function('return this')(),gcv = \\"__coverage__\\",coverageData = { path: \\"/fruits/banana.js\\", statementMap: { \\"0\\": { start: { line: 1, column: 0 }, end: { line: 1, column: 26 } } }, fnMap: {}, branchMap: {}, s: { \\"0\\": 0 }, f: {}, b: {}, _coverageSchema: \\"332fd63041d2c1bcb487cc26dd0d5f7d97098a6c\\" },coverage = global[gcv] || (global[gcv] = {});if (coverage[path] && coverage[path].hash === hash) {return coverage[path];}coverageData.hash = hash;return coverage[path] = coverageData;}();++cov_25u22311x4.s[0];module.exports = \\"banana\\";
}});"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ it('instruments files', () => {
collectCoverage: true,
rootDir: '/',
};
const instrumented = transform(FILE_PATH_TO_INSTRUMENT, config);
const instrumented = transform(FILE_PATH_TO_INSTRUMENT, config).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
Expand Down
37 changes: 15 additions & 22 deletions packages/jest-runtime/src/__tests__/transform-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ describe('transform', () => {

it('transforms a file properly', () => {
config.collectCoverage = true;
const response = transform('/fruits/banana.js', config);
const response = transform('/fruits/banana.js', config).script;

expect(response instanceof vm.Script).toBe(true);
expect(vm.Script.mock.calls[0][0]).toMatchSnapshot();
Expand All @@ -166,7 +166,7 @@ describe('transform', () => {
expect(fs.readFileSync).toBeCalledWith('/fruits/banana.js', 'utf8');

// in-memory cache
const response2 = transform('/fruits/banana.js', config);
const response2 = transform('/fruits/banana.js', config).script;
expect(response2).toBe(response);

transform('/fruits/kiwi.js', config);
Expand Down Expand Up @@ -227,40 +227,32 @@ describe('transform', () => {
});

it('instruments with source map if preprocessor supplies it', () => {
if (skipOnWindows.test()) { //snapshot has os-dependent path separators
return;
}

config = Object.assign(config, {
collectCoverage: true,
mapCoverage: true,
transform: [['^.+\\.js$', 'preprocessor-with-sourcemaps']],
});

const sourceMap = {
const map = {
mappings: ';AAAA',
version: 3,
};

require('preprocessor-with-sourcemaps').process.mockReturnValue({
content: 'content',
sourceMap,
code: 'content',
map,
});

transform('/fruits/banana.js', config);
expect(vm.Script.mock.calls[0][0]).toMatchSnapshot();
const result = transform('/fruits/banana.js', config);
expect(result.sourceMapPath).toEqual(expect.any(String));
expect(fs.writeFileSync).toBeCalledWith(
'/cache/jest-transform-cache-test/ab/banana_ab.map',
JSON.stringify(sourceMap),
result.sourceMapPath,
JSON.stringify(map),
'utf8',
);
});

it('instruments with source map if preprocessor inlines it', () => {
if (skipOnWindows.test()) { //snapshot has os-dependent path separators
return;
}

config = Object.assign(config, {
collectCoverage: true,
mapCoverage: true,
Expand All @@ -278,10 +270,10 @@ describe('transform', () => {

require('preprocessor-with-sourcemaps').process.mockReturnValue(content);

transform('/fruits/banana.js', config);
expect(vm.Script.mock.calls[0][0]).toMatchSnapshot();
const result = transform('/fruits/banana.js', config);
expect(result.sourceMapPath).toEqual(expect.any(String));
expect(fs.writeFileSync).toBeCalledWith(
'/cache/jest-transform-cache-test/ab/banana_ab.map',
result.sourceMapPath,
sourceMap,
'utf8',
);
Expand All @@ -304,8 +296,9 @@ describe('transform', () => {
sourceMap,
});

transform('/fruits/banana.js', config);
expect(vm.Script.mock.calls[0][0]).toMatchSnapshot();
const result = transform('/fruits/banana.js', config);
expect(result.sourceMapPath).toBeFalsy();
expect(fs.writeFileSync).toHaveBeenCalledTimes(1);
});

it('reads values from the cache', () => {
Expand Down
23 changes: 21 additions & 2 deletions packages/jest-runtime/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ class Runtime {
_shouldAutoMock: boolean;
_shouldMockModuleCache: BooleanObject;
_shouldUnmockTransitiveDependenciesCache: BooleanObject;
_sourceMapRegistry: {[key: string]: string};
_transitiveShouldMock: BooleanObject;
_unmockList: ?RegExp;
_virtualMocks: BooleanObject;
Expand All @@ -99,6 +100,7 @@ class Runtime {
this._moduleRegistry = Object.create(null);
this._internalModuleRegistry = Object.create(null);
this._mockRegistry = Object.create(null);
this._sourceMapRegistry = Object.create(null);
this._config = config;
this._environment = environment;
this._resolver = resolver;
Expand Down Expand Up @@ -391,6 +393,15 @@ class Runtime {
return this._environment.global.__coverage__;
}

getSourceMapInfo() {
return Object.keys(this._sourceMapRegistry).reduce((result, sourcePath) => {
if (fs.existsSync(this._sourceMapRegistry[sourcePath])) {
result[sourcePath] = this._sourceMapRegistry[sourcePath];
}
return result;
}, {});
}

setMock(
from: string,
moduleName: string,
Expand Down Expand Up @@ -438,9 +449,17 @@ class Runtime {
localModule.paths = this._resolver.getModulePaths(dirname);
localModule.require = this._createRequireImplementation(filename, options);

const script = transform(filename, this._config, {isInternalModule});
const transformedFile = transform(
filename,
this._config,
{isInternalModule}
);

if (transformedFile.sourceMapPath) {
this._sourceMapRegistry[filename] = transformedFile.sourceMapPath;
}

const wrapper = this._environment.runScript(script)[
const wrapper = this._environment.runScript(transformedFile.script)[
transform.EVAL_RESULT_VARIABLE
];
wrapper.call(
Expand Down
Loading

0 comments on commit ecbde20

Please sign in to comment.