supercov 3.0.4 → 3.0.5
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/cli.md +24 -2
- package/docs/coverage-model.md +37 -0
- package/docs/troubleshooting.md +6 -1
- package/docs/workspace-isolation.md +17 -4
- package/package.json +10 -9
- package/runtime/javascript/register.mjs +18 -0
- package/runtime/javascript/runtime.mjs +1 -1
package/docs/cli.md
CHANGED
|
@@ -142,14 +142,14 @@ npx supercov runs <run-id> [query] [options]
|
|
|
142
142
|
| --- | --- |
|
|
143
143
|
| no query | Read the overall result, test outcome, completeness, and timings |
|
|
144
144
|
| `gaps` | See only files with uncovered behavior or measurement limits |
|
|
145
|
-
| `files` | See every included file, including fully covered files |
|
|
145
|
+
| `files` | See every included file, including fully covered files; `--group dir` shows coverage by directory, split by test kind |
|
|
146
146
|
| `file <path>` | Inspect the open obligations in one file |
|
|
147
147
|
| `decision <id \| path:line>` | Understand missing boolean outcomes and MC/DC witnesses |
|
|
148
148
|
| `line <path:line>` | See one line's state, obligations, and covering tests |
|
|
149
149
|
| `test <id \| name>` | See the coverage attributed to one test |
|
|
150
150
|
| `kinds` | Group coverage by test level, such as unit or E2E |
|
|
151
151
|
| `runners` | Group coverage by test runner |
|
|
152
|
-
| `scope` |
|
|
152
|
+
| `scope` | See what is source and what is not, by directory and reason; `--files` lists every file |
|
|
153
153
|
| `assertions` | Read the share of executed statements the tests assert, and the ones they do not; `assertions assess` works it out |
|
|
154
154
|
| `source <path>` | Read matching current project source with line numbers |
|
|
155
155
|
| `minimize` | Find a small test subset that preserves a coverage target |
|
|
@@ -164,6 +164,27 @@ npx supercov runs latest line app/routes/checkout.ts:57
|
|
|
164
164
|
npx supercov runs latest test "checkout retry"
|
|
165
165
|
```
|
|
166
166
|
|
|
167
|
+
To see where the coverage is, read it by directory. Each row is a directory,
|
|
168
|
+
with what it holds and how much of it each kind of test covers; `--depth`
|
|
169
|
+
keeps more levels, and `--metric` picks branches, functions, statements or
|
|
170
|
+
MC/DC instead of lines:
|
|
171
|
+
|
|
172
|
+
```sh supercov
|
|
173
|
+
npx supercov runs latest files --group dir
|
|
174
|
+
npx supercov runs latest files --group dir --depth 2 --metric branches
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
```
|
|
178
|
+
Directory Files Lines e2e unit All
|
|
179
|
+
app 4 15 86.67% 0.00% 100.00%
|
|
180
|
+
lib 1 10 90.00% 40.00% 90.00%
|
|
181
|
+
components 1 2 100.00% 0.00% 100.00%
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
In `--json`, every file of `files` and `gaps` carries `totals` and `covered`
|
|
185
|
+
for each metric beside what is missing, so a percentage can be worked out for
|
|
186
|
+
any file or set of files.
|
|
187
|
+
|
|
167
188
|
Run any query with `--help` to see only the options valid for that query:
|
|
168
189
|
|
|
169
190
|
```sh supercov
|
|
@@ -509,6 +530,7 @@ terminal or offline environment after the package has been downloaded.
|
|
|
509
530
|
| --- | --- |
|
|
510
531
|
| `SUPERCOV_SOURCE_ROOTS` | Comma-separated directories or files that hold your own code, in any language; everything else is left out |
|
|
511
532
|
| `SUPERCOV_TEST_KIND` | Label the wrapped command as a test level such as `unit` or `e2e` |
|
|
533
|
+
| `SUPERCOV_KEEP_WORKSPACE` | Set to `1` to leave the instrumented copy of the project in `.supercov/workspaces/` after the run, to inspect what the command ran. It is kept without this when the build Supercov runs before the tests fails |
|
|
512
534
|
| `SUPERCOV_BUILD_COMMAND` | The build a JavaScript project's tests need, as words or a JSON array, such as `yarn workspace web build` in a monorepo whose root `build` builds every package. Without it Supercov runs the project's `build` script, through the package manager that started the tests, when the tests need built output |
|
|
513
535
|
|
|
514
536
|
Examples:
|
package/docs/coverage-model.md
CHANGED
|
@@ -94,6 +94,18 @@ Both are useful:
|
|
|
94
94
|
- exact evidence helps you inspect or minimize individual tests;
|
|
95
95
|
- aggregate evidence still shows whether the whole suite reached the source.
|
|
96
96
|
|
|
97
|
+
Code that runs while no test is running counts in the run's total and in no
|
|
98
|
+
test's: a server starting before the first test, modules loading, work between
|
|
99
|
+
tests. When a run has any, the summary's `By test kind` table ends with a
|
|
100
|
+
`no test` row for what only that covered, which is why a run with one kind of
|
|
101
|
+
test can show a total above that kind's own:
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
By test kind
|
|
105
|
+
e2e 3 test(s) lines 80.00% branches 66.67% MC/DC 25.00%
|
|
106
|
+
no test lines 17.14% branches 0.00% MC/DC 0.00%
|
|
107
|
+
```
|
|
108
|
+
|
|
97
109
|
See [Supported suites](supported-suites.md) for the attribution available from
|
|
98
110
|
each runner.
|
|
99
111
|
|
|
@@ -128,6 +140,17 @@ If the summary reports ambiguous source scope, inspect it:
|
|
|
128
140
|
npx supercov runs latest scope
|
|
129
141
|
```
|
|
130
142
|
|
|
143
|
+
It prints the scope by directory and reason, the ambiguous places first, and
|
|
144
|
+
the `SUPERCOV_SOURCE_ROOTS` value that would settle them. The summary names
|
|
145
|
+
the same places under `Instrumentation`. Add `--files` to list every file.
|
|
146
|
+
|
|
147
|
+
```
|
|
148
|
+
Files Status Directory Reason
|
|
149
|
+
79 AMBIGUOUS components unclassified first-party source
|
|
150
|
+
227 INCLUDED app discovered package source root
|
|
151
|
+
311 EXCLUDED tests test or fixture source
|
|
152
|
+
```
|
|
153
|
+
|
|
131
154
|
When first-party source lives in unusual directories, declare it explicitly:
|
|
132
155
|
|
|
133
156
|
```sh supercov
|
|
@@ -145,6 +168,20 @@ without a conventional source directory is measured as a whole. Functions passed
|
|
|
145
168
|
to compile-time style macros (`stylex.create(...)`) are left as written because
|
|
146
169
|
the bundler consumes them at build time; nothing about them runs.
|
|
147
170
|
|
|
171
|
+
Inside the roots, tests, fixtures, tool scripts and configuration files are
|
|
172
|
+
still recognised by their path and left out. A root you name settles what it
|
|
173
|
+
names: with `SUPERCOV_SOURCE_ROOTS=src,scripts` the `scripts/` directory is
|
|
174
|
+
source, and so is `src/test-utils` when it is named as a root. Only what lies
|
|
175
|
+
below a named root is still judged by its path, and a root that is a single
|
|
176
|
+
file is always measured.
|
|
177
|
+
|
|
178
|
+
In a Next.js application, root `components/` and `pages/`, and the root files
|
|
179
|
+
Next.js reads by name (`proxy`, `middleware`, `instrumentation`) are source
|
|
180
|
+
without being declared. Under `app/` a folder is a URL segment, so the files
|
|
181
|
+
the App Router serves (`route.ts`, `page.tsx`, `layout.tsx` and the rest) are
|
|
182
|
+
source whatever their folders are called: `app/api/wordpress/test/route.ts` is
|
|
183
|
+
the handler of `/api/wordpress/test`, not a test.
|
|
184
|
+
|
|
148
185
|
Choose roots that describe code the repository owns. Do not include dependencies
|
|
149
186
|
or generated output merely to make a warning disappear.
|
|
150
187
|
|
package/docs/troubleshooting.md
CHANGED
|
@@ -32,7 +32,8 @@ unusual directory, declare the source roots explicitly:
|
|
|
32
32
|
SUPERCOV_SOURCE_ROOTS=src,app npx supercov -- npm test
|
|
33
33
|
```
|
|
34
34
|
|
|
35
|
-
Then inspect what Supercov included and excluded
|
|
35
|
+
Then inspect what Supercov included and excluded, by directory, or file by
|
|
36
|
+
file with `--files`:
|
|
36
37
|
|
|
37
38
|
```sh supercov
|
|
38
39
|
npx supercov runs latest scope
|
|
@@ -41,6 +42,10 @@ npx supercov runs latest scope
|
|
|
41
42
|
Do not broaden the roots to dependencies or generated output merely to remove a
|
|
42
43
|
warning. The goal is an honest boundary around code the repository owns.
|
|
43
44
|
|
|
45
|
+
A file `scope` lists as `test or fixture source` or `conventional tool script`
|
|
46
|
+
was recognised by its path. If it is your code, name its directory, or the file
|
|
47
|
+
itself, as a root: a named root is source whatever it is called.
|
|
48
|
+
|
|
44
49
|
## Too much is measured
|
|
45
50
|
|
|
46
51
|
Vendored or generated code beside your own is measured like the rest of the
|
|
@@ -34,6 +34,8 @@ and the instrumented copy is not what you wrote:
|
|
|
34
34
|
|
|
35
35
|
- Linters, formatters and `tsc --noEmit` (ESLint, Prettier, standard, xo and
|
|
36
36
|
the like) read each file as you wrote it, and don't see `.supercov`.
|
|
37
|
+
- The type check `next build` runs reads each file as you wrote it too, while
|
|
38
|
+
the build itself compiles the instrumented copy.
|
|
37
39
|
- Coverage tools the command runs itself (tap, c8, nyc, Jest's and Vitest's
|
|
38
40
|
`--coverage`) still collect and report coverage. They measure the
|
|
39
41
|
instrumented copy, and report close to what they report without Supercov,
|
|
@@ -42,12 +44,23 @@ and the instrumented copy is not what you wrote:
|
|
|
42
44
|
|
|
43
45
|
Files the wrapped command creates or changes inside the isolated workspace are
|
|
44
46
|
synced back to the project after the run, so `supercov -- npm test -- -u`
|
|
45
|
-
updates snapshots in the repository exactly as `npm test -- -u` would.
|
|
47
|
+
updates snapshots in the repository exactly as `npm test -- -u` would. Three
|
|
46
48
|
exceptions are reported instead of applied: changes the command makes to
|
|
47
49
|
instrumented source files (the instrumented copies must never overwrite your
|
|
48
|
-
sources) and deletions (never propagated
|
|
49
|
-
|
|
50
|
-
not
|
|
50
|
+
sources), a build the command made from them, and deletions (never propagated
|
|
51
|
+
automatically). Such a build stays behind whole: when a file in `.next/`,
|
|
52
|
+
`dist/` or another directory that git ignores or the project does not have was
|
|
53
|
+
built from instrumented source, nothing in that directory is copied, so the
|
|
54
|
+
project never holds an instrumented build. Changes inside any `node_modules`
|
|
55
|
+
directory are neither applied nor reported: dependency trees are not command
|
|
56
|
+
outputs.
|
|
57
|
+
|
|
58
|
+
The run prints where the synced files went, what stayed behind and what the
|
|
59
|
+
command deleted, by top-level directory (`test-results/ 6`, `.next/ 2547`).
|
|
60
|
+
|
|
61
|
+
When the build Supercov runs before the tests fails, the instrumented copy is
|
|
62
|
+
left in `.supercov/workspaces/` until the next run, and the run prints its
|
|
63
|
+
path. `SUPERCOV_KEEP_WORKSPACE=1` leaves it after any run.
|
|
51
64
|
|
|
52
65
|
## Files Supercov creates
|
|
53
66
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "supercov",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.5",
|
|
4
4
|
"description": "Coverage, security and code quality for coding agents",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"coverage",
|
|
@@ -66,6 +66,7 @@
|
|
|
66
66
|
"sync:rust-assets": "node scripts/sync-rust-package-assets.mjs",
|
|
67
67
|
"test:rust-assets": "node scripts/sync-rust-package-assets.mjs --check",
|
|
68
68
|
"test": "cargo test --workspace",
|
|
69
|
+
"test:next-playwright": "cargo build -p supercov && npm --prefix tests/fixtures/next-playwright ci && node scripts/next-playwright-integration.mjs",
|
|
69
70
|
"test:react": "cargo build -p supercov && node scripts/rust-vitest-projects-integration.mjs && npm --prefix examples/react-verification ci && npm --prefix examples/react-verification run demo && node scripts/react-hydration-compatibility.mjs",
|
|
70
71
|
"test:release-tooling": "node --test tests/release/*.test.mjs",
|
|
71
72
|
"test:runtime": "node --test tests/runtime/*.test.mjs",
|
|
@@ -118,14 +119,14 @@
|
|
|
118
119
|
"test:windows-tls": "node scripts/windows-tls-test.mjs"
|
|
119
120
|
},
|
|
120
121
|
"optionalDependencies": {
|
|
121
|
-
"@supercov/cli-darwin-arm64": "3.0.
|
|
122
|
-
"@supercov/cli-darwin-x64": "3.0.
|
|
123
|
-
"@supercov/cli-linux-arm64-gnu": "3.0.
|
|
124
|
-
"@supercov/cli-linux-arm64-musl": "3.0.
|
|
125
|
-
"@supercov/cli-linux-x64-gnu": "3.0.
|
|
126
|
-
"@supercov/cli-linux-x64-musl": "3.0.
|
|
127
|
-
"@supercov/cli-win32-arm64": "3.0.
|
|
128
|
-
"@supercov/cli-win32-x64": "3.0.
|
|
122
|
+
"@supercov/cli-darwin-arm64": "3.0.5",
|
|
123
|
+
"@supercov/cli-darwin-x64": "3.0.5",
|
|
124
|
+
"@supercov/cli-linux-arm64-gnu": "3.0.5",
|
|
125
|
+
"@supercov/cli-linux-arm64-musl": "3.0.5",
|
|
126
|
+
"@supercov/cli-linux-x64-gnu": "3.0.5",
|
|
127
|
+
"@supercov/cli-linux-x64-musl": "3.0.5",
|
|
128
|
+
"@supercov/cli-win32-arm64": "3.0.5",
|
|
129
|
+
"@supercov/cli-win32-x64": "3.0.5"
|
|
129
130
|
},
|
|
130
131
|
"peerDependencies": {
|
|
131
132
|
"@playwright/test": ">=1.55.0",
|
|
@@ -178,6 +178,24 @@ const isAnalysisEntrypoint = new RegExp(`/node_modules/(?:\\.bin/(?:${analysisTo
|
|
|
178
178
|
process.argv.includes("--noEmit"));
|
|
179
179
|
if (isAnalysisEntrypoint)
|
|
180
180
|
installAuthoredSourceView();
|
|
181
|
+
// `next build` type-checks in a worker of its own instead of running tsc. A
|
|
182
|
+
// probe in a condition stops TypeScript narrowing through it, so an inferred
|
|
183
|
+
// return type widens, and a file outside the source roots that calls the
|
|
184
|
+
// function fails the build on code nobody wrote ("'client' is possibly
|
|
185
|
+
// 'null'"). Only that worker gets the authored view: the bundler, and `next
|
|
186
|
+
// dev`, which sets TypeScript up in its main process, must read the copies.
|
|
187
|
+
else if (/\/node_modules\/next\/dist\/compiled\/jest-worker\/processChild\.js$/.test(entrypoint) ||
|
|
188
|
+
(!workerThreads.isMainThread && /\/node_modules\/(?:\.bin\/next$|next\/dist\/)/.test(entrypoint))) {
|
|
189
|
+
const compile = Module.prototype._compile;
|
|
190
|
+
let installed = false;
|
|
191
|
+
Module.prototype._compile = function _compile(content, filename, ...rest) {
|
|
192
|
+
if (!installed && /[\\/]next[\\/]dist[\\/]lib[\\/]verify-typescript-setup\.js$/.test(filename)) {
|
|
193
|
+
installed = true;
|
|
194
|
+
installAuthoredSourceView();
|
|
195
|
+
}
|
|
196
|
+
return Reflect.apply(compile, this, [content, filename, ...rest]);
|
|
197
|
+
};
|
|
198
|
+
}
|
|
181
199
|
function installAuthoredSourceView() {
|
|
182
200
|
let authored;
|
|
183
201
|
try {
|
|
@@ -890,7 +890,7 @@ function cleanInstrumentationStack(error) {
|
|
|
890
890
|
if (!error || typeof error !== "object" || typeof error.stack !== "string")
|
|
891
891
|
return error;
|
|
892
892
|
const lines = error.stack.split("\n");
|
|
893
|
-
const visible = lines.filter((line, index) => index === 0 || !/[\\/]\.supercov[\\/](?:playwright|nodeTest|vitest|runtime|launchSupervisor|nodeAssert|nodeAssertStrict|nodeAssertAdapter|register|resolve-loader)\.(?:js|mjs)(?::|\))/u.test(line));
|
|
893
|
+
const visible = lines.filter((line, index) => index === 0 || !/[\\/]\.supercov[\\/](?:node_modules[\\/])?(?:playwright|nodeTest|vitest|runtime|launchSupervisor|nodeAssert|nodeAssertStrict|nodeAssertAdapter|register|resolve-loader)\.(?:js|mjs)(?::|\))/u.test(line));
|
|
894
894
|
if (visible.length !== lines.length) {
|
|
895
895
|
try {
|
|
896
896
|
error.stack = visible.join("\n");
|