Skip to content

Commit

Permalink
Map code coverage from transformers (#2290)
Browse files Browse the repository at this point in the history
* source map support for coverage

* be less dangerous

only enforce files in src/ having @flow since everything else may not be run through babel

* lazy require for istanbul-lib-source-maps

* add documentation for mapCoverage config option

* store source maps on disk instead of in worker process memory

* add mapCoverage to CLI, switch off by default

* move source map info from coverage object to jest-runtime

* tweak docs, fix a test
  • Loading branch information
jwbay authored and aaronabramov committed Mar 3, 2017
1 parent d85989d commit c6d2b08
Show file tree
Hide file tree
Showing 28 changed files with 770 additions and 57 deletions.
7 changes: 4 additions & 3 deletions dangerfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,9 @@ const raiseIssueAboutPaths = (
};

const newJsFiles = danger.git.created_files.filter(path => path.endsWith('js'));
const isNotInTestFiles = path => !(includes(path, '__tests__')
|| includes(path, '__mocks__'));
const isSourceFile = path =>
includes(path, '/src/') &&
!includes(path, '__tests__');

// New JS files should have the FB copyright header + flow
const facebookLicenseHeaderComponents = [
Expand Down Expand Up @@ -80,7 +81,7 @@ if (noFBCopyrightFiles.length > 0) {
// Ensure the majority of all files use Flow
// Does not run for test files, and also offers a warning not an error.
const noFlowFiles = newJsFiles
.filter(isNotInTestFiles)
.filter(isSourceFile)
.filter(filepath => {
const content = fs.readFileSync(filepath).toString();
return !includes(content, '@flow');
Expand Down
17 changes: 17 additions & 0 deletions docs/Configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,23 @@ For example, the following would create a global `__DEV__` variable set to `true

Note that, if you specify a global reference value (like an object or array) here, and some code mutates that value in the midst of running a test, that mutation will *not* be persisted across test runs for other test files.

### `mapCoverage` [boolean]

##### available in Jest **20.0.0+**

Default: `false`

If you have [transformers](#transform-object-string-string) configured that emit source maps, Jest will use them to try and map code coverage against the original source code when writing [reports](#coveragereporters-array-string) and checking [thresholds](#coveragethreshold-object). This is done on a best-effort basis as some compile-to-JavaScript languages may provide more accurate source maps than others. This can also be resource-intensive. If Jest is taking a long time to calculate coverage at the end of a test run, try setting this option to `false`.

Both inline source maps and source maps returned directly from a transformer are supported. Source map URLs are not supported because Jest may not be able to locate them. To return source maps from a transformer, the `process` function can return an object like the following. The `map` property may either be the source map object, or the source map object as a JSON string.

```js
return {
code: 'the code',
map: 'the source map',
};
```

### `moduleFileExtensions` [array<string>]
Default: `["js", "json", "jsx", "node"]`

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,348 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`maps code coverage against original source 1`] = `
Object {
"covered.ts": Object {
"b": Object {
"0": Array [
1,
0,
],
"1": Array [
1,
0,
],
"2": Array [
1,
0,
0,
],
"3": Array [
1,
0,
],
},
"branchMap": Object {
"0": Object {
"loc": Object {
"end": Object {
"column": 9,
"line": 5,
},
"start": Object {
"column": 8,
"line": 5,
},
},
"locations": Array [
Object {
"end": Object {
"column": 9,
"line": 5,
},
"start": Object {
"column": 8,
"line": 5,
},
},
Object {
"end": Object {
"column": 9,
"line": 6,
},
"start": Object {
"column": 8,
"line": 6,
},
},
],
"type": "cond-expr",
},
"1": Object {
"loc": Object {
"end": Object {
"column": 37,
"line": 7,
},
"start": Object {
"column": 36,
"line": 7,
},
},
"locations": Array [
Object {
"end": Object {
"column": 37,
"line": 7,
},
"start": Object {
"column": 36,
"line": 7,
},
},
Object {
"end": Object {
"column": 41,
"line": 7,
},
"start": Object {
"column": 40,
"line": 7,
},
},
],
"type": "cond-expr",
},
"2": Object {
"loc": Object {
"end": Object {
"column": 33,
"line": 8,
},
"start": Object {
"column": 29,
"line": 8,
},
},
"locations": Array [
Object {
"end": Object {
"column": 33,
"line": 8,
},
"start": Object {
"column": 29,
"line": 8,
},
},
Object {
"end": Object {
"column": 41,
"line": 8,
},
"start": Object {
"column": 37,
"line": 8,
},
},
Object {
"end": Object {
"column": 50,
"line": 8,
},
"start": Object {
"column": 45,
"line": 8,
},
},
],
"type": "binary-expr",
},
"3": Object {
"loc": Object {
"end": Object {
"column": 42,
"line": 9,
},
"start": Object {
"column": 32,
"line": 9,
},
},
"locations": Array [
Object {
"end": Object {
"column": 42,
"line": 9,
},
"start": Object {
"column": 32,
"line": 9,
},
},
Object {
"end": Object {
"column": 55,
"line": 9,
},
"start": Object {
"column": 45,
"line": 9,
},
},
],
"type": "cond-expr",
},
},
"f": Object {
"0": 1,
"1": 0,
"2": 0,
},
"fnMap": Object {
"0": Object {
"decl": Object {
"end": Object {
"column": 28,
"line": 3,
},
"start": Object {
"column": 9,
"line": 3,
},
},
"loc": Object {
"end": Object {
"column": 1,
"line": 12,
},
"start": Object {
"column": 49,
"line": 3,
},
},
"name": "difference",
},
"1": Object {
"decl": Object {
"end": Object {
"column": 37,
"line": 9,
},
"start": Object {
"column": 32,
"line": 9,
},
},
"loc": Object {
"end": Object {
"column": 42,
"line": 9,
},
"start": Object {
"column": 32,
"line": 9,
},
},
"name": "(anonymous_1)",
},
"2": Object {
"decl": Object {
"end": Object {
"column": 50,
"line": 9,
},
"start": Object {
"column": 45,
"line": 9,
},
},
"loc": Object {
"end": Object {
"column": 55,
"line": 9,
},
"start": Object {
"column": 45,
"line": 9,
},
},
"name": "(anonymous_2)",
},
},
"path": "covered.ts",
"s": Object {
"0": 1,
"1": 1,
"2": 1,
"3": 1,
"4": 1,
"5": 0,
"6": 0,
"7": 1,
},
"statementMap": Object {
"0": Object {
"end": Object {
"column": 1,
"line": 12,
},
"start": Object {
"column": 0,
"line": 3,
},
},
"1": Object {
"end": Object {
"column": 9,
"line": 6,
},
"start": Object {
"column": 29,
"line": 4,
},
},
"2": Object {
"end": Object {
"column": 41,
"line": 7,
},
"start": Object {
"column": 29,
"line": 7,
},
},
"3": Object {
"end": Object {
"column": 50,
"line": 8,
},
"start": Object {
"column": 29,
"line": 8,
},
},
"4": Object {
"end": Object {
"column": 55,
"line": 9,
},
"start": Object {
"column": 25,
"line": 9,
},
},
"5": Object {
"end": Object {
"column": 42,
"line": 9,
},
"start": Object {
"column": 38,
"line": 9,
},
},
"6": Object {
"end": Object {
"column": 55,
"line": 9,
},
"start": Object {
"column": 51,
"line": 9,
},
},
"7": Object {
"end": Object {
"column": 17,
"line": 11,
},
"start": Object {
"column": 4,
"line": 11,
},
},
},
},
}
`;
Loading

0 comments on commit c6d2b08

Please sign in to comment.