supercov 4.24.6 → 4.24.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/docs/supported-suites.md
CHANGED
|
@@ -77,6 +77,13 @@ Bun keeps its own formatted reporter titles. Async test bodies retain their
|
|
|
77
77
|
identity across `await`, including concurrent execution. Lifecycle hooks have
|
|
78
78
|
separate setup identities and do not credit their coverage to the test body.
|
|
79
79
|
|
|
80
|
+
Bun can also run another test runner by its entry point, such as
|
|
81
|
+
`bun node_modules/vitest/vitest.mjs run` or `bun node_modules/mocha/bin/mocha.js`.
|
|
82
|
+
The Bun adapter sets that runner up as Node's preload would: Vitest gets
|
|
83
|
+
Supercov's generated config, which merges the project's own (including one given
|
|
84
|
+
by `--config`), and Mocha's runner is patched before it loads. Their tests are
|
|
85
|
+
attributed as they are under Node.
|
|
86
|
+
|
|
80
87
|
Callback completion supplies the recorded outcome. If Bun interrupts a callback
|
|
81
88
|
before it completes, Supercov preserves its named coverage with an **unknown**
|
|
82
89
|
outcome. Bun's final runner verdict can additionally reflect a timeout, hook
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "supercov",
|
|
3
|
-
"version": "4.24.
|
|
3
|
+
"version": "4.24.7",
|
|
4
4
|
"description": "Coverage, security and code quality for coding agents",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"coverage",
|
|
@@ -123,14 +123,14 @@
|
|
|
123
123
|
"test:windows-tls": "node scripts/windows-tls-test.mjs"
|
|
124
124
|
},
|
|
125
125
|
"optionalDependencies": {
|
|
126
|
-
"@supercov/cli-darwin-arm64": "4.24.
|
|
127
|
-
"@supercov/cli-darwin-x64": "4.24.
|
|
128
|
-
"@supercov/cli-linux-arm64-gnu": "4.24.
|
|
129
|
-
"@supercov/cli-linux-arm64-musl": "4.24.
|
|
130
|
-
"@supercov/cli-linux-x64-gnu": "4.24.
|
|
131
|
-
"@supercov/cli-linux-x64-musl": "4.24.
|
|
132
|
-
"@supercov/cli-win32-arm64": "4.24.
|
|
133
|
-
"@supercov/cli-win32-x64": "4.24.
|
|
126
|
+
"@supercov/cli-darwin-arm64": "4.24.7",
|
|
127
|
+
"@supercov/cli-darwin-x64": "4.24.7",
|
|
128
|
+
"@supercov/cli-linux-arm64-gnu": "4.24.7",
|
|
129
|
+
"@supercov/cli-linux-arm64-musl": "4.24.7",
|
|
130
|
+
"@supercov/cli-linux-x64-gnu": "4.24.7",
|
|
131
|
+
"@supercov/cli-linux-x64-musl": "4.24.7",
|
|
132
|
+
"@supercov/cli-win32-arm64": "4.24.7",
|
|
133
|
+
"@supercov/cli-win32-x64": "4.24.7"
|
|
134
134
|
},
|
|
135
135
|
"peerDependencies": {
|
|
136
136
|
"@playwright/test": ">=1.55.0",
|
|
@@ -5,6 +5,10 @@
|
|
|
5
5
|
// existing API so both keep native test registration and execution semantics.
|
|
6
6
|
import * as runtime from "./runtime.mjs";
|
|
7
7
|
import { callerLocation, runnerExecutionScope, runnerTestId, writeRunnerEvidence } from "./runnerEvidence.mjs";
|
|
8
|
+
import { adaptRunnerEntry } from "./runnerEntry.mjs";
|
|
9
|
+
|
|
10
|
+
// Bun runs no Node preload: a runner it starts is adapted here.
|
|
11
|
+
await adaptRunnerEntry(process.argv[1]?.replaceAll("\\", "/") ?? "");
|
|
8
12
|
|
|
9
13
|
const adapted = new WeakSet();
|
|
10
14
|
const nativeJest = Bun.jest;
|
|
@@ -12,6 +12,7 @@ import path, { basename, dirname, isAbsolute, relative, resolve, sep } from "nod
|
|
|
12
12
|
import { fileURLToPath } from "node:url";
|
|
13
13
|
import { installLaunchSupervisor, wrapImportedCapability } from "./launchSupervisor.mjs";
|
|
14
14
|
import { __supercovBindCapabilityWrapper } from "./capability.mjs";
|
|
15
|
+
import { adaptRunnerEntry, noteSkippedCoverageThresholds } from "./runnerEntry.mjs";
|
|
15
16
|
installLaunchSupervisor();
|
|
16
17
|
// Playwright 1.59 writes each file it compiles into its cache in place and
|
|
17
18
|
// reads it back unchecked: a process that read one while another wrote it
|
|
@@ -167,7 +168,6 @@ syncBuiltinESMExports();
|
|
|
167
168
|
// is Vitest, replace its config with our generated merging config before the
|
|
168
169
|
// CLI parses argv. This is what makes `supercov -- npm test` work
|
|
169
170
|
// without editing package scripts, Vitest configs, setup files, or test imports.
|
|
170
|
-
const generatedVitestConfig = process.env.SUPERCOV_GENERATED_VITEST_CONFIG;
|
|
171
171
|
const generatedPlaywrightConfig = process.env.SUPERCOV_GENERATED_PLAYWRIGHT_CONFIG;
|
|
172
172
|
const entrypoint = process.argv[1]?.replaceAll("\\", "/") ?? "";
|
|
173
173
|
// Node's own test coverage filters files by `--test-coverage-include` and
|
|
@@ -789,19 +789,9 @@ function installAuthoredSourceView() {
|
|
|
789
789
|
};
|
|
790
790
|
syncBuiltinESMExports();
|
|
791
791
|
}
|
|
792
|
-
//
|
|
793
|
-
//
|
|
794
|
-
|
|
795
|
-
// every branch (80%, 83.33%, 87.5%). The tool still runs and reports; its
|
|
796
|
-
// thresholds are not checked, and the run says so once. Jest's and Vitest's
|
|
797
|
-
// thresholds are dropped from the configurations Supercov hands them, which
|
|
798
|
-
// call this too.
|
|
799
|
-
process.__SUPERCOV_SKIPPED_COVERAGE_THRESHOLDS__ ??= (tool) => {
|
|
800
|
-
if (process.__SUPERCOV_SKIPPED_COVERAGE_THRESHOLDS_NOTED__)
|
|
801
|
-
return;
|
|
802
|
-
process.__SUPERCOV_SKIPPED_COVERAGE_THRESHOLDS_NOTED__ = true;
|
|
803
|
-
console.error(`[supercov] ${tool}'s coverage thresholds were not checked: under Supercov, ${tool} measures the instrumented copy, probes included. Supercov's own report has this run's coverage.`);
|
|
804
|
-
};
|
|
792
|
+
// Jest's and Vitest's thresholds are dropped from the configurations Supercov
|
|
793
|
+
// hands them, which call this too.
|
|
794
|
+
process.__SUPERCOV_SKIPPED_COVERAGE_THRESHOLDS__ ??= noteSkippedCoverageThresholds;
|
|
805
795
|
const coverageTool = /\/node_modules\/(?:\.bin\/(c8|nyc)|(c8|nyc)\/bin\/(?:c8|nyc)\.js)$/.exec(entrypoint);
|
|
806
796
|
if (coverageTool)
|
|
807
797
|
skipCoverageThresholds(coverageTool[1] ?? coverageTool[2]);
|
|
@@ -1004,59 +994,7 @@ register(new URL("./resolve-loader.mjs", import.meta.url), {
|
|
|
1004
994
|
if (process.env.SUPERCOV_DEBUG === "1") {
|
|
1005
995
|
console.error("[supercov] preload", { entrypoint });
|
|
1006
996
|
}
|
|
1007
|
-
|
|
1008
|
-
// Worker processes inherit this marker. In particular, do not eagerly load
|
|
1009
|
-
// Playwright's expect implementation in a Vitest worker: both runners use
|
|
1010
|
-
// the Jest matcher registry symbol and intentionally cannot coexist there.
|
|
1011
|
-
process.env.SUPERCOV_INSIDE_VITEST = "1";
|
|
1012
|
-
let originalConfig;
|
|
1013
|
-
for (let index = 2; index < process.argv.length; index += 1) {
|
|
1014
|
-
const argument = process.argv[index];
|
|
1015
|
-
if (argument === "--config" || argument === "-c") {
|
|
1016
|
-
const configured = process.argv[index + 1];
|
|
1017
|
-
const resolvedConfig = configured
|
|
1018
|
-
? resolve(process.cwd(), configured)
|
|
1019
|
-
: undefined;
|
|
1020
|
-
if (resolvedConfig && resolvedConfig !== resolve(generatedVitestConfig)) {
|
|
1021
|
-
originalConfig = resolvedConfig;
|
|
1022
|
-
}
|
|
1023
|
-
process.argv.splice(index, configured ? 2 : 1);
|
|
1024
|
-
index -= 1;
|
|
1025
|
-
}
|
|
1026
|
-
else if (argument?.startsWith("--config=")) {
|
|
1027
|
-
const resolvedConfig = resolve(process.cwd(), argument.slice("--config=".length));
|
|
1028
|
-
if (resolvedConfig !== resolve(generatedVitestConfig)) {
|
|
1029
|
-
originalConfig = resolvedConfig;
|
|
1030
|
-
}
|
|
1031
|
-
process.argv.splice(index, 1);
|
|
1032
|
-
index -= 1;
|
|
1033
|
-
}
|
|
1034
|
-
}
|
|
1035
|
-
// Thresholds on the command line override the configuration's, which the
|
|
1036
|
-
// generated config leaves out (see the coverage tools above). Vitest 0.x
|
|
1037
|
-
// took them directly under --coverage.
|
|
1038
|
-
for (let index = 2; index < process.argv.length; index += 1) {
|
|
1039
|
-
const argument = process.argv[index];
|
|
1040
|
-
if (!/^--coverage\.(?:thresholds(?:\.[^=]+)?|lines|functions|branches|statements|perFile|100|thresholdAutoUpdate)(?:=|$)/.test(argument))
|
|
1041
|
-
continue;
|
|
1042
|
-
const valued = !argument.includes("=") && /^(?:\d+(?:\.\d+)?|true|false)$/.test(process.argv[index + 1] ?? "");
|
|
1043
|
-
process.argv.splice(index, valued ? 2 : 1);
|
|
1044
|
-
index -= 1;
|
|
1045
|
-
process.__SUPERCOV_SKIPPED_COVERAGE_THRESHOLDS__("Vitest");
|
|
1046
|
-
}
|
|
1047
|
-
if (originalConfig) {
|
|
1048
|
-
process.env.SUPERCOV_ORIGINAL_VITEST_CONFIG = originalConfig;
|
|
1049
|
-
}
|
|
1050
|
-
process.argv.push("--config", generatedVitestConfig);
|
|
1051
|
-
if (process.env.SUPERCOV_DEBUG === "1") {
|
|
1052
|
-
console.error("[supercov] Vitest argv configured", {
|
|
1053
|
-
entrypoint,
|
|
1054
|
-
originalConfig,
|
|
1055
|
-
generatedVitestConfig,
|
|
1056
|
-
argv: process.argv.slice(2),
|
|
1057
|
-
});
|
|
1058
|
-
}
|
|
1059
|
-
}
|
|
997
|
+
await adaptRunnerEntry(entrypoint);
|
|
1060
998
|
if ((isJestEntrypoint || process.env.JEST_WORKER_ID) && process.env.SUPERCOV_EVIDENCE_DIR) {
|
|
1061
999
|
// Jest evaluates instrumented modules in its own module system, past the
|
|
1062
1000
|
// loader hook that imports the runtime on first use elsewhere, and
|
|
@@ -1068,32 +1006,6 @@ if ((isJestEntrypoint || process.env.JEST_WORKER_ID) && process.env.SUPERCOV_EVI
|
|
|
1068
1006
|
globalThis.__SUPERCOV_DIRECT_RUNTIME__ ??= await import("./runtime.mjs");
|
|
1069
1007
|
process.__SUPERCOV_DIRECT_RUNTIME__ ??= globalThis.__SUPERCOV_DIRECT_RUNTIME__;
|
|
1070
1008
|
}
|
|
1071
|
-
// The Mocha CLI, the child it forks for Node options, and each --parallel
|
|
1072
|
-
// worker run tests through Mocha's Runner, which the adapter patches before
|
|
1073
|
-
// Mocha loads it.
|
|
1074
|
-
const isMochaEntrypoint = /\/node_modules\/(?:\.bin\/_?mocha|mocha\/(?:bin\/_?mocha(?:\.js)?|lib\/cli\/cli\.js|lib\/nodejs\/worker\.c?js))$/.test(entrypoint);
|
|
1075
|
-
if (isMochaEntrypoint && process.env.SUPERCOV_EVIDENCE_DIR) {
|
|
1076
|
-
globalThis.__SUPERCOV_DIRECT_RUNTIME__ ??= await import("./runtime.mjs");
|
|
1077
|
-
process.__SUPERCOV_DIRECT_RUNTIME__ ??= globalThis.__SUPERCOV_DIRECT_RUNTIME__;
|
|
1078
|
-
const { adaptMocha } = await import(new URL("./mocha.mjs", import.meta.url).href);
|
|
1079
|
-
await adaptMocha(entrypoint);
|
|
1080
|
-
}
|
|
1081
|
-
// An AVA worker, a thread or a child process, runs one test file through
|
|
1082
|
-
// AVA's Runner, which the adapter patches before the worker loads it.
|
|
1083
|
-
if (/\/node_modules\/ava\/lib\/worker\/base\.js$/.test(entrypoint) && process.env.SUPERCOV_EVIDENCE_DIR) {
|
|
1084
|
-
globalThis.__SUPERCOV_DIRECT_RUNTIME__ ??= await import("./runtime.mjs");
|
|
1085
|
-
process.__SUPERCOV_DIRECT_RUNTIME__ ??= globalThis.__SUPERCOV_DIRECT_RUNTIME__;
|
|
1086
|
-
const { adaptAva } = await import(new URL("./ava.mjs", import.meta.url).href);
|
|
1087
|
-
await adaptAva(entrypoint);
|
|
1088
|
-
}
|
|
1089
|
-
// The tap CLI runs each test file as a process of its own, marked with
|
|
1090
|
-
// TAP_CHILD_ID; the adapter patches tap's TestBase before the file loads it.
|
|
1091
|
-
if (process.env.TAP_CHILD_ID && process.env.SUPERCOV_EVIDENCE_DIR && entrypoint) {
|
|
1092
|
-
globalThis.__SUPERCOV_DIRECT_RUNTIME__ ??= await import("./runtime.mjs");
|
|
1093
|
-
process.__SUPERCOV_DIRECT_RUNTIME__ ??= globalThis.__SUPERCOV_DIRECT_RUNTIME__;
|
|
1094
|
-
const { adaptTap } = await import(new URL("./tap.mjs", import.meta.url).href);
|
|
1095
|
-
await adaptTap(entrypoint);
|
|
1096
|
-
}
|
|
1097
1009
|
if (isJestEntrypoint && process.env.SUPERCOV_EVIDENCE_DIR) {
|
|
1098
1010
|
// Jest reads one configuration. Ours (jest.config.mjs) reads the user's
|
|
1099
1011
|
// the way Jest would and adds the adapter and reporter; an explicit
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
// A runner started by its own entry point -- Vitest, Mocha, an AVA worker, a
|
|
2
|
+
// tap child -- is adapted as it starts: Vitest takes the run's generated
|
|
3
|
+
// config, the others' runners are patched before they load. Without it every
|
|
4
|
+
// probe a test reaches is counted as background. Node runs this from
|
|
5
|
+
// register.mjs before the CLI parses argv; Bun loads no Node preload, so its
|
|
6
|
+
// adapter does instead.
|
|
7
|
+
import { resolve } from "node:path";
|
|
8
|
+
|
|
9
|
+
// A project's own coverage tool measures what runs, and under Supercov that is
|
|
10
|
+
// the instrumented copy, whose probes are branches no test was written to
|
|
11
|
+
// cover: c8, Jest and Vitest each failed a 100% gate on a suite that covers
|
|
12
|
+
// every branch (80%, 83.33%, 87.5%). The tool still runs and reports; its
|
|
13
|
+
// thresholds are not checked, and the run says so once.
|
|
14
|
+
export function noteSkippedCoverageThresholds(tool) {
|
|
15
|
+
if (process.__SUPERCOV_SKIPPED_COVERAGE_THRESHOLDS_NOTED__)
|
|
16
|
+
return;
|
|
17
|
+
process.__SUPERCOV_SKIPPED_COVERAGE_THRESHOLDS_NOTED__ = true;
|
|
18
|
+
console.error(`[supercov] ${tool}'s coverage thresholds were not checked: under Supercov, ${tool} measures the instrumented copy, probes included. Supercov's own report has this run's coverage.`);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** Point a Vitest process at the run's generated config. */
|
|
22
|
+
function useGeneratedVitestConfig(entrypoint) {
|
|
23
|
+
const generatedVitestConfig = process.env.SUPERCOV_GENERATED_VITEST_CONFIG;
|
|
24
|
+
if (!generatedVitestConfig || !/\/vitest(?:\.m?js)?$/.test(entrypoint))
|
|
25
|
+
return;
|
|
26
|
+
// Worker processes inherit this marker. In particular, do not eagerly load
|
|
27
|
+
// Playwright's expect implementation in a Vitest worker: both runners use
|
|
28
|
+
// the Jest matcher registry symbol and intentionally cannot coexist there.
|
|
29
|
+
process.env.SUPERCOV_INSIDE_VITEST = "1";
|
|
30
|
+
let originalConfig;
|
|
31
|
+
for (let index = 2; index < process.argv.length; index += 1) {
|
|
32
|
+
const argument = process.argv[index];
|
|
33
|
+
if (argument === "--config" || argument === "-c") {
|
|
34
|
+
const configured = process.argv[index + 1];
|
|
35
|
+
const resolvedConfig = configured
|
|
36
|
+
? resolve(process.cwd(), configured)
|
|
37
|
+
: undefined;
|
|
38
|
+
if (resolvedConfig && resolvedConfig !== resolve(generatedVitestConfig)) {
|
|
39
|
+
originalConfig = resolvedConfig;
|
|
40
|
+
}
|
|
41
|
+
process.argv.splice(index, configured ? 2 : 1);
|
|
42
|
+
index -= 1;
|
|
43
|
+
}
|
|
44
|
+
else if (argument?.startsWith("--config=")) {
|
|
45
|
+
const resolvedConfig = resolve(process.cwd(), argument.slice("--config=".length));
|
|
46
|
+
if (resolvedConfig !== resolve(generatedVitestConfig)) {
|
|
47
|
+
originalConfig = resolvedConfig;
|
|
48
|
+
}
|
|
49
|
+
process.argv.splice(index, 1);
|
|
50
|
+
index -= 1;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
// Thresholds on the command line override the configuration's, which the
|
|
54
|
+
// generated config leaves out (see the coverage tools above). Vitest 0.x
|
|
55
|
+
// took them directly under --coverage.
|
|
56
|
+
for (let index = 2; index < process.argv.length; index += 1) {
|
|
57
|
+
const argument = process.argv[index];
|
|
58
|
+
if (!/^--coverage\.(?:thresholds(?:\.[^=]+)?|lines|functions|branches|statements|perFile|100|thresholdAutoUpdate)(?:=|$)/.test(argument))
|
|
59
|
+
continue;
|
|
60
|
+
const valued = !argument.includes("=") && /^(?:\d+(?:\.\d+)?|true|false)$/.test(process.argv[index + 1] ?? "");
|
|
61
|
+
process.argv.splice(index, valued ? 2 : 1);
|
|
62
|
+
index -= 1;
|
|
63
|
+
noteSkippedCoverageThresholds("Vitest");
|
|
64
|
+
}
|
|
65
|
+
if (originalConfig) {
|
|
66
|
+
process.env.SUPERCOV_ORIGINAL_VITEST_CONFIG = originalConfig;
|
|
67
|
+
}
|
|
68
|
+
process.argv.push("--config", generatedVitestConfig);
|
|
69
|
+
if (process.env.SUPERCOV_DEBUG === "1") {
|
|
70
|
+
console.error("[supercov] Vitest argv configured", {
|
|
71
|
+
entrypoint,
|
|
72
|
+
originalConfig,
|
|
73
|
+
generatedVitestConfig,
|
|
74
|
+
argv: process.argv.slice(2),
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** Adapt the runner whose entry point `entrypoint` is, if any. */
|
|
80
|
+
export async function adaptRunnerEntry(entrypoint) {
|
|
81
|
+
useGeneratedVitestConfig(entrypoint);
|
|
82
|
+
// The Mocha CLI, the child it forks for Node options, and each --parallel
|
|
83
|
+
// worker run tests through Mocha's Runner, which the adapter patches before
|
|
84
|
+
// Mocha loads it.
|
|
85
|
+
const isMochaEntrypoint = /\/node_modules\/(?:\.bin\/_?mocha|mocha\/(?:bin\/_?mocha(?:\.js)?|lib\/cli\/cli\.js|lib\/nodejs\/worker\.c?js))$/.test(entrypoint);
|
|
86
|
+
if (isMochaEntrypoint && process.env.SUPERCOV_EVIDENCE_DIR) {
|
|
87
|
+
globalThis.__SUPERCOV_DIRECT_RUNTIME__ ??= await import("./runtime.mjs");
|
|
88
|
+
process.__SUPERCOV_DIRECT_RUNTIME__ ??= globalThis.__SUPERCOV_DIRECT_RUNTIME__;
|
|
89
|
+
const { adaptMocha } = await import(new URL("./mocha.mjs", import.meta.url).href);
|
|
90
|
+
await adaptMocha(entrypoint);
|
|
91
|
+
}
|
|
92
|
+
// An AVA worker, a thread or a child process, runs one test file through
|
|
93
|
+
// AVA's Runner, which the adapter patches before the worker loads it.
|
|
94
|
+
if (/\/node_modules\/ava\/lib\/worker\/base\.js$/.test(entrypoint) && process.env.SUPERCOV_EVIDENCE_DIR) {
|
|
95
|
+
globalThis.__SUPERCOV_DIRECT_RUNTIME__ ??= await import("./runtime.mjs");
|
|
96
|
+
process.__SUPERCOV_DIRECT_RUNTIME__ ??= globalThis.__SUPERCOV_DIRECT_RUNTIME__;
|
|
97
|
+
const { adaptAva } = await import(new URL("./ava.mjs", import.meta.url).href);
|
|
98
|
+
await adaptAva(entrypoint);
|
|
99
|
+
}
|
|
100
|
+
// The tap CLI runs each test file as a process of its own, marked with
|
|
101
|
+
// TAP_CHILD_ID; the adapter patches tap's TestBase before the file loads it.
|
|
102
|
+
if (process.env.TAP_CHILD_ID && process.env.SUPERCOV_EVIDENCE_DIR && entrypoint) {
|
|
103
|
+
globalThis.__SUPERCOV_DIRECT_RUNTIME__ ??= await import("./runtime.mjs");
|
|
104
|
+
process.__SUPERCOV_DIRECT_RUNTIME__ ??= globalThis.__SUPERCOV_DIRECT_RUNTIME__;
|
|
105
|
+
const { adaptTap } = await import(new URL("./tap.mjs", import.meta.url).href);
|
|
106
|
+
await adaptTap(entrypoint);
|
|
107
|
+
}
|
|
108
|
+
}
|