supercov 0.0.0
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/README.md +201 -0
- package/bin/supercov.js +26 -0
- package/package.json +57 -0
- package/src/analyze.ts +993 -0
- package/src/cli.ts +336 -0
- package/src/instrumenter.ts +1254 -0
- package/src/integrity.ts +187 -0
- package/src/playwright.ts +1009 -0
- package/src/playwrightReporter.ts +55 -0
- package/src/project.ts +149 -0
- package/src/provenance.ts +69 -0
- package/src/query.ts +1354 -0
- package/src/queueAdapters.ts +104 -0
- package/src/register.mjs +123 -0
- package/src/reporter.ts +431 -0
- package/src/resolve-loader.mjs +45 -0
- package/src/runtime.ts +656 -0
- package/src/transport.ts +132 -0
- package/src/types.ts +412 -0
- package/src/vitePlugin.ts +121 -0
- package/src/vitest.ts +101 -0
- package/src/vitestReporter.ts +72 -0
package/README.md
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
# supercov
|
|
2
|
+
|
|
3
|
+
Zero-edit, runner-aware coverage-completeness command for JavaScript test
|
|
4
|
+
suites.
|
|
5
|
+
|
|
6
|
+
```sh
|
|
7
|
+
npx supercov -- npm test
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
For local development before publication, a Supercov contributor can expose
|
|
11
|
+
the checkout globally. Consumer repositories still remain untouched:
|
|
12
|
+
|
|
13
|
+
```sh
|
|
14
|
+
# In the supercov repository.
|
|
15
|
+
npm install
|
|
16
|
+
npm link
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Verifying the instrumenter
|
|
20
|
+
|
|
21
|
+
The coverage engine has three independent test layers:
|
|
22
|
+
|
|
23
|
+
- semantic differential fixtures execute original and instrumented programs
|
|
24
|
+
in isolated scopes and compare return values, thrown errors, and observable
|
|
25
|
+
side-effect order;
|
|
26
|
+
- a deterministic generated corpus exercises 160 nested combinations of
|
|
27
|
+
short-circuiting, ternaries, coercion, and thrown expressions on every run;
|
|
28
|
+
- coverage oracles assert exact decision vectors, MC/DC witnesses, and branch
|
|
29
|
+
alternatives independently of program behavior.
|
|
30
|
+
|
|
31
|
+
```sh
|
|
32
|
+
npm test
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
The differential suite includes getters, proxies, optional calls and `this`,
|
|
36
|
+
computed logical assignments, defaults, `try`/`catch`/`finally`, iterator
|
|
37
|
+
closing, switch fallthrough, labeled loops, async functions, and generators.
|
|
38
|
+
Every generated failure prints its reproducible seed and expression.
|
|
39
|
+
|
|
40
|
+
## Agent query workflow
|
|
41
|
+
|
|
42
|
+
Each run is stored locally as a compressed, immutable report under
|
|
43
|
+
`.supercov/runs/<run-id>/`. Its `report.json.gz`, `run.json`, and
|
|
44
|
+
`report.html` keep the machine report, run metadata, and human report together.
|
|
45
|
+
Agents should use bounded CLI queries instead of loading the complete report
|
|
46
|
+
into context.
|
|
47
|
+
|
|
48
|
+
```sh
|
|
49
|
+
# Orient using only a few lines.
|
|
50
|
+
npx supercov runs --limit 5
|
|
51
|
+
npx supercov runs latest coverage
|
|
52
|
+
npx supercov runs latest coverage --filter passed
|
|
53
|
+
npx supercov runs latest coverage --filter failed
|
|
54
|
+
npx supercov runs latest coverage kinds
|
|
55
|
+
npx supercov runs latest coverage runners
|
|
56
|
+
npx supercov runs latest coverage --kind e2e
|
|
57
|
+
npx supercov runs latest coverage files
|
|
58
|
+
npx supercov runs latest coverage gaps --limit 10
|
|
59
|
+
npx supercov runs latest coverage gaps --kind e2e --limit 10
|
|
60
|
+
|
|
61
|
+
# Drill into one target selected from the gap list.
|
|
62
|
+
npx supercov runs latest coverage file app/routes/example.ts
|
|
63
|
+
npx supercov runs latest coverage decision app/routes/example.ts:42
|
|
64
|
+
npx supercov runs latest coverage covers app/routes/example.ts:57
|
|
65
|
+
|
|
66
|
+
# Understand redundancy/contribution and validate a newly written test. Replace
|
|
67
|
+
# "latest" with the immutable run ID when an agent continues work later.
|
|
68
|
+
npx supercov runs latest coverage test "test title fragment"
|
|
69
|
+
npx supercov diff <older-run> <newer-run>
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Coverage queries use `--filter all` by default, matching conventional coverage
|
|
73
|
+
tools: every executed attempt contributes, including attempts that later fail.
|
|
74
|
+
Use `--filter passed` for verified coverage from successful attempts of
|
|
75
|
+
ultimately passing tests, or `--filter failed` to inspect only execution from
|
|
76
|
+
failed attempts (including failed retries of flaky tests). Reports record
|
|
77
|
+
attempt status and classify each test as passed, failed, flaky, skipped, timed
|
|
78
|
+
out, interrupted, or unknown. The HTML equivalents are `report.html`,
|
|
79
|
+
`report-passed.html`, and `report-failed.html`.
|
|
80
|
+
|
|
81
|
+
The run ID is positional because all coverage queries operate on one immutable
|
|
82
|
+
run. `latest` is a convenience selector for interactive use. Every query
|
|
83
|
+
accepts `--json` and—where the result can be long—`--limit` and `--offset`.
|
|
84
|
+
Every collection is paginated at 20 items by default and prints its range plus
|
|
85
|
+
a copyable next-page command; generated commands omit the default limit.
|
|
86
|
+
Text output is concise for an interactive agent; JSON is the stable machine
|
|
87
|
+
interface that can later back hosted coverage tools without changing the
|
|
88
|
+
stored schema.
|
|
89
|
+
|
|
90
|
+
For a conventional Vite project, the CLI:
|
|
91
|
+
|
|
92
|
+
1. creates ignored Vite, Vitest, and Playwright overlays under
|
|
93
|
+
`.supercov/`;
|
|
94
|
+
2. inventories every `app/**/*.ts(x)` and `src/**/*.ts(x)` file for the
|
|
95
|
+
denominator, then
|
|
96
|
+
instruments modules loaded by Vite without changing the project's config;
|
|
97
|
+
3. redirects existing `@playwright/test` imports at module-load time and injects
|
|
98
|
+
a Vitest setup through the child runner's generated config, without changing
|
|
99
|
+
specs, imports, package scripts, or checked-in configs;
|
|
100
|
+
4. runs the exact command following `--`;
|
|
101
|
+
5. attributes every source hit and decision vector to its individual test,
|
|
102
|
+
automatically wraps Playwright actions and assertions, and records the
|
|
103
|
+
action/assertion phase responsible for each correlated hit; then merges
|
|
104
|
+
server and browser evidence into HTML and JSON reports; and
|
|
105
|
+
6. restores an ordinary application build even after a failed test command.
|
|
106
|
+
|
|
107
|
+
The automatic adapters currently support standard Playwright suites (ESM and
|
|
108
|
+
CommonJS specs in arbitrary project directories), Vitest, and the Essential
|
|
109
|
+
Apps isolated Playwright VM runner. A single command such as
|
|
110
|
+
`supercov -- npm test` can collect Vitest and Playwright evidence into
|
|
111
|
+
the same run. The application build must currently be Vite-based. Jest,
|
|
112
|
+
`node:test`, non-Vite build systems, browser component runners, and distributed
|
|
113
|
+
multi-host merging still require adapters; they are not silently reported as
|
|
114
|
+
covered.
|
|
115
|
+
|
|
116
|
+
Each test carries two independent provenance fields:
|
|
117
|
+
|
|
118
|
+
- `runner`: the process that executed it, such as `playwright` or `vitest`;
|
|
119
|
+
- `kind`: its semantic level, such as `e2e`, `integration`, `component`, or
|
|
120
|
+
`unit`.
|
|
121
|
+
|
|
122
|
+
Kind is resolved in descending confidence from an explicit
|
|
123
|
+
`SUPERCOV_TEST_KIND`, Playwright project name, test path, then runner
|
|
124
|
+
default (Playwright is E2E; Vitest is unit). The report preserves how the label
|
|
125
|
+
was established, so an inferred kind is never presented as user-declared.
|
|
126
|
+
Vitest module-import/setup execution is retained as a separate setup scope,
|
|
127
|
+
not mislabeled as a test case.
|
|
128
|
+
|
|
129
|
+
Filtered queries recompute every obligation from the selected tests. MC/DC is
|
|
130
|
+
especially important: the command recomputes independence witness pairs rather
|
|
131
|
+
than filtering an already-computed percentage. Therefore a witness assembled
|
|
132
|
+
from one unit vector and one E2E vector counts for the combined suite but not
|
|
133
|
+
for either filtered subset. With `--kind e2e`, gap and file queries also
|
|
134
|
+
distinguish obligations covered only by other test levels from obligations
|
|
135
|
+
uncovered everywhere.
|
|
136
|
+
|
|
137
|
+
The JSON report contains both per-test and per-test-file coverage data. MC/DC
|
|
138
|
+
stores vector-level provenance rather than only a decision-level test list, so
|
|
139
|
+
a later suite minimizer can recompute valid independence pairs for any proposed
|
|
140
|
+
subset. This matters because the two vectors in a witness pair may come from
|
|
141
|
+
different tests.
|
|
142
|
+
|
|
143
|
+
The same report also contains an action/assertion trace without requiring spec
|
|
144
|
+
changes. Calls such as `page.goto()`, `locator.click()`, and `locator.fill()`
|
|
145
|
+
open action phases; Playwright `expect()` matchers open assertion phases. The
|
|
146
|
+
phase travels on browser requests into automatically wrapped Remix loaders,
|
|
147
|
+
actions, and the server document renderer. Node async context preserves that
|
|
148
|
+
ID through awaited helpers. An assertion also retains the preceding action ID,
|
|
149
|
+
making chains such as “click -> application lines/decisions -> visible
|
|
150
|
+
assertion” queryable in JSON and visible in HTML.
|
|
151
|
+
|
|
152
|
+
Server evidence is safe when Playwright uses multiple workers against one
|
|
153
|
+
application server. Every routed request carries a run/worker/test/retry scope;
|
|
154
|
+
Node async context retains that scope and its current phase across awaited
|
|
155
|
+
work. The server writes to a distinct attempt path, and the collecting fixture
|
|
156
|
+
accepts only records bearing that attempt ID. No worker deletes, reads, or
|
|
157
|
+
attributes another worker's live evidence file.
|
|
158
|
+
|
|
159
|
+
Detached work is never silently dropped or guessed onto the currently active
|
|
160
|
+
test. HTTP callbacks inherit the carrier automatically; child processes inherit
|
|
161
|
+
it through their environment; and exported queue helpers support BullMQ,
|
|
162
|
+
Bee-Queue, pg-boss, Agenda, and in-process schedulers. Evidence that arrives
|
|
163
|
+
without a carrier is persisted under a first-class `background/unattributed`
|
|
164
|
+
scope. It is visible in the all-attempt report and excluded from passed-only
|
|
165
|
+
per-test coverage.
|
|
166
|
+
|
|
167
|
+
The Playwright adapter covers the page and request fixtures, API request
|
|
168
|
+
contexts, user-created browser contexts/pages, popups and all their frames,
|
|
169
|
+
dedicated/service workers, WebSocket handshake headers, and test-spawned child
|
|
170
|
+
processes. A two-worker generic fixture exercises these surfaces without
|
|
171
|
+
changing its test imports or Playwright config.
|
|
172
|
+
|
|
173
|
+
Every run stores SHA-256 fingerprints for source, tests, dependency lockfiles,
|
|
174
|
+
test/build configuration, and the instrumenter, plus its report schema and Git
|
|
175
|
+
revision/dirty state. Queries compare the stored fingerprint with the current
|
|
176
|
+
workspace, visibly mark stale runs, and reject evidence carrying a different
|
|
177
|
+
run scope.
|
|
178
|
+
|
|
179
|
+
For Chromium documents exposed through the page target, a pre-document probe
|
|
180
|
+
also installs the phase before application JavaScript starts. Chromium may run
|
|
181
|
+
a newly created cross-origin iframe in a separate target that cannot be safely
|
|
182
|
+
paused and attached during navigation; its earliest browser probes use the
|
|
183
|
+
timing fallback until the frame is live. This affects only action-level causal
|
|
184
|
+
precision, not structural coverage or exact test-case provenance.
|
|
185
|
+
|
|
186
|
+
Code reached outside a recognized Playwright action, such as setup work or a
|
|
187
|
+
project-specific helper that performs HTTP requests directly, still has exact
|
|
188
|
+
test-case attribution but may not have an explicit action-phase ID. The report
|
|
189
|
+
labels explicit browser/server events separately from events assigned by the
|
|
190
|
+
isolated VM's timing fallback. Only explicit phases can raise confidence to
|
|
191
|
+
`asserted`; a timing-correlated event remains execution-only. Each line, point,
|
|
192
|
+
branch alternative, vector, and MC/DC condition therefore distinguishes
|
|
193
|
+
unexecuted, executed, action-linked, and assertion-linked evidence, as well as
|
|
194
|
+
unit-only versus E2E coverage.
|
|
195
|
+
|
|
196
|
+
The v2 denominator additionally measures optional-chain short-circuiting,
|
|
197
|
+
logical assignments, parameter/destructuring defaults, try versus catch,
|
|
198
|
+
zero versus entered `for-in`/`for-of`, and implicit switch no-match. Direct
|
|
199
|
+
`eval`/`Function` source cannot receive a stable pre-run denominator; when such
|
|
200
|
+
code is discovered the report records its exact location as a completeness
|
|
201
|
+
blocker instead of allowing a misleading 100% verdict.
|
package/bin/supercov.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { spawn } from "node:child_process";
|
|
4
|
+
import { createRequire } from "node:module";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
|
|
7
|
+
const cli = fileURLToPath(new URL("../src/cli.ts", import.meta.url));
|
|
8
|
+
const require = createRequire(import.meta.url);
|
|
9
|
+
const tsx = require.resolve("tsx");
|
|
10
|
+
const child = spawn(
|
|
11
|
+
process.execPath,
|
|
12
|
+
["--import", tsx, cli, ...process.argv.slice(2)],
|
|
13
|
+
{
|
|
14
|
+
stdio: "inherit",
|
|
15
|
+
env: process.env,
|
|
16
|
+
},
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
child.on("error", (error) => {
|
|
20
|
+
console.error("[supercov] failed to start", error);
|
|
21
|
+
process.exitCode = 1;
|
|
22
|
+
});
|
|
23
|
+
child.on("exit", (code, signal) => {
|
|
24
|
+
if (signal) process.kill(process.pid, signal);
|
|
25
|
+
else process.exitCode = code ?? 1;
|
|
26
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "supercov",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"description": "Zero-edit, runner-aware coverage completeness for JavaScript test suites",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"files": [
|
|
7
|
+
"bin",
|
|
8
|
+
"src",
|
|
9
|
+
"README.md"
|
|
10
|
+
],
|
|
11
|
+
"engines": {
|
|
12
|
+
"node": ">=22"
|
|
13
|
+
},
|
|
14
|
+
"bin": {
|
|
15
|
+
"supercov": "bin/supercov.js"
|
|
16
|
+
},
|
|
17
|
+
"exports": {
|
|
18
|
+
"./playwright": "./src/playwright.ts",
|
|
19
|
+
"./register": "./src/register.mjs",
|
|
20
|
+
"./vite": "./src/vitePlugin.ts",
|
|
21
|
+
"./vitest": "./src/vitest.ts"
|
|
22
|
+
},
|
|
23
|
+
"scripts": {
|
|
24
|
+
"test": "vitest run tests/unit",
|
|
25
|
+
"test:types": "tsc --noEmit",
|
|
26
|
+
"test:fixture": "npm --prefix tests/fixtures/generic-playwright run test:coverage",
|
|
27
|
+
"check": "npm run test && npm run test:types",
|
|
28
|
+
"prepublishOnly": "npm run check"
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"@babel/generator": "^8.0.0",
|
|
32
|
+
"@babel/parser": "^8.0.4",
|
|
33
|
+
"@babel/traverse": "^8.0.4",
|
|
34
|
+
"@babel/types": "^8.0.4",
|
|
35
|
+
"tsx": "^4.20.6"
|
|
36
|
+
},
|
|
37
|
+
"peerDependencies": {
|
|
38
|
+
"@playwright/test": ">=1.50.0",
|
|
39
|
+
"vite": ">=5.0.0",
|
|
40
|
+
"vitest": ">=2.0.0"
|
|
41
|
+
},
|
|
42
|
+
"peerDependenciesMeta": {
|
|
43
|
+
"@playwright/test": {
|
|
44
|
+
"optional": true
|
|
45
|
+
},
|
|
46
|
+
"vitest": {
|
|
47
|
+
"optional": true
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"@playwright/test": "1.62.1",
|
|
52
|
+
"@types/node": "^24.0.0",
|
|
53
|
+
"typescript": "7.0.2",
|
|
54
|
+
"vite": "8.2.2",
|
|
55
|
+
"vitest": "4.1.11"
|
|
56
|
+
}
|
|
57
|
+
}
|