Skip to content

Commit 26447d7

Browse files
committed
almost working coverage
1 parent 83da92a commit 26447d7

File tree

4 files changed

+76
-7
lines changed

4 files changed

+76
-7
lines changed

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
},
1515
"dependencies": {
1616
"@jest/expect": "^29.0.1",
17+
"@jest/transform": "^29.0.1",
18+
"collect-v8-coverage": "^1.0.1",
1719
"jest-circus": "^29.0.1",
1820
"jest-each": "^29.0.1",
1921
"jest-mock": "^29.0.1",

src/index.js

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
11
import { Piscina } from "piscina";
22
import supportsColor from "supports-color";
33
import { MessageChannel } from "worker_threads";
4+
import { shouldInstrument } from "@jest/transform";
5+
import { fileURLToPath } from "url";
46

57
/** @typedef {import("@jest/test-result").Test} Test */
68

79
export default class LightRunner {
810
// TODO: Use real private fields when we drop support for Node.js v12
911
_config;
1012
_piscina;
13+
_testContext;
1114

12-
constructor(config) {
15+
constructor(config, testContext) {
1316
this._config = config;
17+
this._testContext = testContext;
1418

1519
// Jest's logic to decide when to spawn workers and when to run in the
1620
// main thread is quite complex:
@@ -36,6 +40,36 @@ export default class LightRunner {
3640
});
3741
}
3842

43+
filterCoverage(result, projectConfig) {
44+
if (!result.v8Coverage) {
45+
return result;
46+
}
47+
48+
const coverageOptions = {
49+
changedFiles: this._testContext.changedFiles,
50+
collectCoverage: true,
51+
collectCoverageFrom: this._config.collectCoverageFrom,
52+
collectCoverageOnlyFrom: this._config.collectCoverageOnlyFrom,
53+
coverageProvider: this._config.coverageProvider,
54+
sourcesRelatedToTestsInChangedFiles:
55+
this._testContext.sourcesRelatedToTestsInChangedFiles,
56+
};
57+
58+
return {
59+
...result,
60+
v8Coverage: result.v8Coverage
61+
.filter(res => res.url.startsWith("file://"))
62+
.map(res => ({ ...res, url: fileURLToPath(res.url) }))
63+
.filter(
64+
({ url }) =>
65+
// TODO: will this work on windows? It might be better if `shouldInstrument` deals with it anyways
66+
url.startsWith(projectConfig.rootDir) &&
67+
shouldInstrument(url, coverageOptions, projectConfig)
68+
)
69+
.map(result => ({ result })),
70+
};
71+
}
72+
3973
/**
4074
* @param {Array<Test>} tests
4175
* @param {*} watcher
@@ -44,7 +78,12 @@ export default class LightRunner {
4478
* @param {*} onFailure
4579
*/
4680
runTests(tests, watcher, onStart, onResult, onFailure) {
47-
const { updateSnapshot, testNamePattern } = this._config;
81+
const {
82+
updateSnapshot,
83+
testNamePattern,
84+
collectCoverage,
85+
coverageProvider,
86+
} = this._config;
4887

4988
return Promise.all(
5089
tests.map(test => {
@@ -54,11 +93,21 @@ export default class LightRunner {
5493

5594
return this._piscina
5695
.run(
57-
{ test, updateSnapshot, testNamePattern, port: mc.port1 },
96+
{
97+
test,
98+
updateSnapshot,
99+
testNamePattern,
100+
port: mc.port1,
101+
collectV8Coverage: collectCoverage && coverageProvider === "v8",
102+
},
58103
{ transferList: [mc.port1] }
59104
)
60105
.then(
61-
result => void onResult(test, result),
106+
result =>
107+
void onResult(
108+
test,
109+
this.filterCoverage(result, test.context.config)
110+
),
62111
error => void onFailure(test, error)
63112
);
64113
})

src/worker-runner.js

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { expect } from "expect";
66
import * as circus from "jest-circus";
77
import { inspect } from "util";
88
import { isWorkerThread } from "piscina";
9+
import { CoverageInstrumenter } from "collect-v8-coverage";
910

1011
/** @typedef {{ failures: number, passes: number, pending: number, start: number, end: number }} Stats */
1112
/** @typedef {{ ancestors: string[], title: string, duration: number, errors: Error[], skipped: boolean }} InternalTestResult */
@@ -54,6 +55,7 @@ export default async function run({
5455
updateSnapshot,
5556
testNamePattern,
5657
port,
58+
collectV8Coverage,
5759
}) {
5860
const projectSnapshotSerializers = await initialSetup(test.context.config);
5961

@@ -67,6 +69,13 @@ export default async function run({
6769
/** @type {Array<InternalTestResult>} */
6870
const results = [];
6971

72+
let instrumenter = null;
73+
if (collectV8Coverage) {
74+
instrumenter = new CoverageInstrumenter();
75+
76+
await instrumenter.startInstrumenting();
77+
}
78+
7079
const { tests, hasFocusedTests } = await loadTests(test.path);
7180

7281
const snapshotResolver = await snapshot.buildSnapshotResolver(
@@ -86,13 +95,18 @@ export default async function run({
8695
await runTestBlock(tests, hasFocusedTests, testNamePatternRE, results, stats);
8796
stats.end = performance.now();
8897

98+
let v8Coverage = undefined;
99+
if (instrumenter) {
100+
v8Coverage = await instrumenter.stopInstrumenting();
101+
}
102+
89103
snapshotState.save();
90104

91105
// Restore the project-level serializers, so that serializers
92106
// installed by one test file don't leak to other files.
93107
arrayReplace(snapshot.getSerializers(), projectSnapshotSerializers);
94108

95-
return toTestResult(stats, results, test);
109+
return toTestResult(stats, results, test, v8Coverage);
96110
}
97111

98112
async function loadTests(testFile) {
@@ -236,9 +250,10 @@ function callAsync(fn) {
236250
* @param {Stats} stats
237251
* @param {Array<InternalTestResult>} tests
238252
* @param {import("@jest/test-result").Test} testInput
253+
* @param {import("@jest/test-result").V8CoverageResult} v8Coverage
239254
* @returns {import("@jest/test-result").TestResult}
240255
*/
241-
function toTestResult(stats, tests, { path, context }) {
256+
function toTestResult(stats, tests, { path, context }, v8Coverage) {
242257
const { start, end } = stats;
243258
const runtime = end - start;
244259

@@ -285,6 +300,7 @@ function toTestResult(stats, tests, { path, context }) {
285300
title: test.title,
286301
};
287302
}),
303+
v8Coverage,
288304
};
289305
}
290306

yarn.lock

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1031,7 +1031,7 @@ __metadata:
10311031
languageName: node
10321032
linkType: hard
10331033

1034-
"collect-v8-coverage@npm:^1.0.0":
1034+
"collect-v8-coverage@npm:^1.0.0, collect-v8-coverage@npm:^1.0.1":
10351035
version: 1.0.1
10361036
resolution: "collect-v8-coverage@npm:1.0.1"
10371037
checksum: 4efe0a1fccd517b65478a2364b33dadd0a43fc92a56f59aaece9b6186fe5177b2de471253587de7c91516f07c7268c2f6770b6cbcffc0e0ece353b766ec87e55
@@ -1655,6 +1655,8 @@ __metadata:
16551655
resolution: "jest-light-runner@workspace:."
16561656
dependencies:
16571657
"@jest/expect": ^29.0.1
1658+
"@jest/transform": ^29.0.1
1659+
collect-v8-coverage: ^1.0.1
16581660
jest-circus: ^29.0.1
16591661
jest-each: ^29.0.1
16601662
jest-mock: ^29.0.1

0 commit comments

Comments
 (0)