supercov 0.0.43 → 0.0.45
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 +23 -14
- package/docs/agent-loop.md +128 -39
- package/docs/assertion-agent.md +156 -0
- package/docs/assertion-evidence.md +9 -135
- package/docs/assertion-maps.md +252 -0
- package/docs/assertions.md +82 -0
- package/docs/cli.md +38 -23
- package/docs/coverage-model.md +18 -6
- package/docs/evidence.md +6 -6
- package/docs/getting-started.md +60 -72
- package/docs/performance.md +4 -4
- package/docs/troubleshooting.md +8 -8
- package/docs/verification.md +2 -2
- package/docs/workspace-isolation.md +1 -1
- package/package.json +34 -33
- package/runtime/javascript/nodeAssertAdapter.mjs +32 -8
- package/runtime/javascript/nodeTest.mjs +13 -5
- package/runtime/javascript/runnerEvidence.mjs +33 -11
- package/runtime/javascript/runtime.mjs +27 -23
- package/schemas/assertions.schema.json +276 -0
- package/analyzers/typescript/README.md +0 -55
- package/analyzers/typescript/bin/compiler-identity.mjs +0 -78
- package/analyzers/typescript/bin/identity.mjs +0 -67
- package/analyzers/typescript/bin/query.mjs +0 -29
- package/analyzers/typescript/dist/analyze.js +0 -3972
- package/analyzers/typescript/dist/archive.js +0 -309
- package/analyzers/typescript/dist/build-identity.json +0 -1
- package/analyzers/typescript/dist/compiler.js +0 -32
- package/analyzers/typescript/dist/frontend.js +0 -75
- package/analyzers/typescript/dist/native-frontend.js +0 -271
- package/analyzers/typescript/dist/pragmas.js +0 -143
- package/analyzers/typescript/dist/types.js +0 -1
- package/analyzers/typescript/package.json +0 -27
- package/analyzers/typescript/src/analyze.ts +0 -4538
- package/analyzers/typescript/src/archive.ts +0 -438
- package/analyzers/typescript/src/compiler.ts +0 -49
- package/analyzers/typescript/src/frontend.ts +0 -136
- package/analyzers/typescript/src/native-frontend.ts +0 -315
- package/analyzers/typescript/src/pragmas.ts +0 -218
- package/analyzers/typescript/src/types.ts +0 -45
- package/analyzers/typescript/tsconfig.json +0 -12
- package/docs/code-verification.md +0 -182
package/docs/getting-started.md
CHANGED
|
@@ -1,68 +1,50 @@
|
|
|
1
1
|
# Getting started
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
compare the result.
|
|
3
|
+
Open your project in a coding agent that can run terminal commands, then paste
|
|
4
|
+
this prompt:
|
|
6
5
|
|
|
7
|
-
```
|
|
8
|
-
npx supercov
|
|
6
|
+
```text supercov-prompt
|
|
7
|
+
Measure code coverage with npx supercov and write one missing test.
|
|
8
|
+
Only change tests. Rerun the full test suite and show me the test you
|
|
9
|
+
added and the before-and-after coverage.
|
|
9
10
|
```
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
|
|
12
|
+
Your agent can install Supercov if needed. It runs the commands and edits the
|
|
13
|
+
tests; you don't need to do those steps yourself.
|
|
13
14
|
|
|
14
|
-
|
|
15
|
+
When it finishes, review the test change and coverage comparison in your
|
|
16
|
+
conversation. Ask separately if you want a commit or pull request.
|
|
15
17
|
|
|
16
|
-
|
|
18
|
+
No account, config file, import, custom reporter, or hosted service is required.
|
|
19
|
+
Supercov supports JavaScript, TypeScript, Rust, Python, and Ruby today.
|
|
17
20
|
|
|
18
|
-
|
|
19
|
-
Windows (arm64 or x64);
|
|
20
|
-
- Node.js 22 or newer;
|
|
21
|
-
- a test command that already works in the repository; and
|
|
22
|
-
- for Rust, the Rust 1.95 toolchain;
|
|
23
|
-
- for Python, CPython 3.12 or newer with pytest or unittest;
|
|
24
|
-
- for Ruby, Ruby 3.4 or newer with RSpec, Minitest, test-unit or Cucumber (3.3 measures lines, methods and simple branches only).
|
|
21
|
+
## What the agent does
|
|
25
22
|
|
|
26
|
-
The
|
|
27
|
-
|
|
28
|
-
on PyPI as `supercov-cli` (`uvx --from supercov-cli supercov`) and on RubyGems
|
|
29
|
-
as `supercov` (`gem install supercov`), at the same version, and the source is
|
|
30
|
-
on crates.io (`cargo install supercov`). The first invocation may download
|
|
31
|
-
Supercov from the registry. Supercov itself does not upload your source or
|
|
32
|
-
coverage evidence to a Supercov service.
|
|
23
|
+
The commands below show how the agent measures coverage and checks its work.
|
|
24
|
+
You can also run them yourself if you prefer using the terminal.
|
|
33
25
|
|
|
34
|
-
|
|
26
|
+
### 1. Run your real test command
|
|
35
27
|
|
|
36
|
-
|
|
37
|
-
complete command you trust before merging or deploying:
|
|
28
|
+
The agent runs your repository's complete test suite through Supercov:
|
|
38
29
|
|
|
39
|
-
```sh
|
|
40
|
-
# JavaScript or TypeScript
|
|
30
|
+
```sh supercov-example
|
|
41
31
|
npx supercov -- npm test
|
|
42
|
-
npx supercov -- npx playwright test
|
|
43
|
-
npx supercov -- pnpm test:e2e
|
|
44
|
-
|
|
45
|
-
# Rust
|
|
46
|
-
npx supercov -- cargo test
|
|
47
|
-
npx supercov -- cargo nextest run
|
|
48
|
-
|
|
49
|
-
# Python
|
|
50
|
-
npx supercov -- pytest
|
|
51
|
-
|
|
52
|
-
# Ruby
|
|
53
|
-
npx supercov -- rspec
|
|
54
32
|
```
|
|
55
33
|
|
|
34
|
+
Everything after `--` is the command Supercov measures. The agent should use
|
|
35
|
+
the same complete command your project uses before merging or deploying.
|
|
36
|
+
If the project has several suites, tell it which one to use.
|
|
37
|
+
|
|
56
38
|
Supercov runs that command in an isolated, instrumented copy of the project.
|
|
57
39
|
The command keeps its normal arguments, environment, output, and exit status.
|
|
58
40
|
If one command launches several supported runners, their evidence lands in one
|
|
59
41
|
run.
|
|
60
42
|
|
|
61
|
-
|
|
43
|
+
### 2. Read the first result
|
|
62
44
|
|
|
63
|
-
|
|
45
|
+
The agent reads the newest run:
|
|
64
46
|
|
|
65
|
-
```sh
|
|
47
|
+
```sh supercov-example
|
|
66
48
|
npx supercov runs latest
|
|
67
49
|
```
|
|
68
50
|
|
|
@@ -76,18 +58,19 @@ An uncovered gap is a candidate for a test. A measurement limit is different:
|
|
|
76
58
|
it means Supercov cannot honestly account for that code yet. Do not try to test
|
|
77
59
|
away a measurement limit.
|
|
78
60
|
|
|
79
|
-
|
|
61
|
+
### 3. Choose one useful gap
|
|
80
62
|
|
|
81
|
-
|
|
63
|
+
The agent asks for a short list of gaps, then inspects one file. It uses your
|
|
64
|
+
project's file paths in place of the examples:
|
|
82
65
|
|
|
83
|
-
```sh
|
|
66
|
+
```sh supercov-example
|
|
84
67
|
npx supercov runs latest gaps --limit 10
|
|
85
68
|
npx supercov runs latest file app/checkout/session.ts
|
|
86
69
|
```
|
|
87
70
|
|
|
88
|
-
|
|
71
|
+
It can use more specific queries to understand the gap:
|
|
89
72
|
|
|
90
|
-
```sh
|
|
73
|
+
```sh supercov-example
|
|
91
74
|
npx supercov runs latest decision app/checkout/session.ts:64
|
|
92
75
|
npx supercov runs latest line app/checkout/session.ts:64
|
|
93
76
|
```
|
|
@@ -96,40 +79,45 @@ npx supercov runs latest line app/checkout/session.ts:64
|
|
|
96
79
|
outcomes and MC/DC witnesses. `line` shows the obligations and tests associated
|
|
97
80
|
with one source line.
|
|
98
81
|
|
|
99
|
-
|
|
82
|
+
### 4. Add a test and prove the gain
|
|
100
83
|
|
|
101
|
-
|
|
102
|
-
command and
|
|
84
|
+
The agent writes one focused test with a meaningful assertion. It then reruns
|
|
85
|
+
the same complete command and compares the two runs:
|
|
103
86
|
|
|
104
|
-
```sh
|
|
87
|
+
```sh supercov-example
|
|
105
88
|
npx supercov -- npm test
|
|
106
89
|
npx supercov diff <previous-run-id> latest
|
|
107
90
|
```
|
|
108
91
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
92
|
+
A useful change leaves the suite passing and shows the expected gain without
|
|
93
|
+
an unexplained loss elsewhere. Review what the new test actually checks, not
|
|
94
|
+
just the percentage.
|
|
112
95
|
|
|
113
|
-
|
|
96
|
+
For a recorded example and prompts for longer runs, see
|
|
97
|
+
[Agent workflow](agent-loop.md).
|
|
114
98
|
|
|
115
|
-
|
|
99
|
+
## Environment requirements
|
|
116
100
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
101
|
+
These requirements apply wherever the agent runs commands: your machine,
|
|
102
|
+
a container, or a remote workspace. The agent can check them and tell you
|
|
103
|
+
if anything is missing.
|
|
120
104
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
of an ordinary gap.
|
|
130
|
-
```
|
|
105
|
+
- macOS (arm64 or x64), Linux (arm64 or x64, glibc 2.28 or newer or musl), or
|
|
106
|
+
Windows (arm64 or x64);
|
|
107
|
+
- Node.js 22 or newer when using the npm package;
|
|
108
|
+
- a working test command, including its dependencies, environment variables,
|
|
109
|
+
and any local services;
|
|
110
|
+
- for Rust, the Rust 1.95 toolchain;
|
|
111
|
+
- for Python, CPython 3.12 or newer with pytest or unittest;
|
|
112
|
+
- for Ruby, Ruby 3.4 or newer with RSpec, Minitest, test-unit or Cucumber (3.3 measures lines, methods and simple branches only).
|
|
131
113
|
|
|
132
|
-
|
|
114
|
+
The CLI is a native binary. `npx supercov` picks the build for your operating
|
|
115
|
+
system and architecture, and nothing is compiled on install; the same binary is
|
|
116
|
+
on PyPI as `supercov-cli` (`uvx --from supercov-cli supercov`) and on RubyGems
|
|
117
|
+
as `supercov` (`gem install supercov`), at the same version, and the source is
|
|
118
|
+
on crates.io (`cargo install supercov`). The first invocation may download
|
|
119
|
+
Supercov from the registry. Supercov itself does not upload your source or
|
|
120
|
+
coverage evidence to a Supercov service.
|
|
133
121
|
|
|
134
122
|
## Files and cleanup
|
|
135
123
|
|
|
@@ -138,7 +126,7 @@ workspace for instrumented builds. These files are local and ignored by Git.
|
|
|
138
126
|
Supercov does not rewrite your source, tests, imports, runner configuration,
|
|
139
127
|
dependencies, or ordinary build output.
|
|
140
128
|
|
|
141
|
-
```sh
|
|
129
|
+
```sh supercov
|
|
142
130
|
npx supercov clean --dry-run # preview what would be removed
|
|
143
131
|
npx supercov clean --keep 20 # keep the 20 newest runs
|
|
144
132
|
npx supercov clean # remove all runs and the build cache
|
package/docs/performance.md
CHANGED
|
@@ -6,7 +6,7 @@ the isolated build when the relevant inputs have not changed.
|
|
|
6
6
|
|
|
7
7
|
## See where the time went
|
|
8
8
|
|
|
9
|
-
```sh
|
|
9
|
+
```sh supercov
|
|
10
10
|
npx supercov runs latest
|
|
11
11
|
```
|
|
12
12
|
|
|
@@ -42,7 +42,7 @@ possible mismatch triggers a fresh build rather than risking stale coverage.
|
|
|
42
42
|
|
|
43
43
|
A narrow test command can shorten the inner loop:
|
|
44
44
|
|
|
45
|
-
```sh
|
|
45
|
+
```sh supercov
|
|
46
46
|
npx supercov -- npx vitest run app/checkout/session.test.ts
|
|
47
47
|
```
|
|
48
48
|
|
|
@@ -54,7 +54,7 @@ baseline.
|
|
|
54
54
|
|
|
55
55
|
Compare the original and wrapped command under similar cache conditions:
|
|
56
56
|
|
|
57
|
-
```sh
|
|
57
|
+
```sh supercov
|
|
58
58
|
/usr/bin/time -p npm test
|
|
59
59
|
/usr/bin/time -p npx supercov -- npm test
|
|
60
60
|
```
|
|
@@ -73,7 +73,7 @@ than stored as a full report for every filter.
|
|
|
73
73
|
The isolated workspace may be larger because it can contain an instrumented
|
|
74
74
|
build cache. Supercov does not delete history in the background.
|
|
75
75
|
|
|
76
|
-
```sh
|
|
76
|
+
```sh supercov
|
|
77
77
|
npx supercov clean --dry-run
|
|
78
78
|
npx supercov clean --keep 20
|
|
79
79
|
npx supercov clean
|
package/docs/troubleshooting.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Start with the run summary. It usually tells you whether the problem is the test
|
|
4
4
|
command, source discovery, runner attribution, or a measurement boundary.
|
|
5
5
|
|
|
6
|
-
```sh
|
|
6
|
+
```sh supercov
|
|
7
7
|
npx supercov runs latest
|
|
8
8
|
npx supercov runs latest scope
|
|
9
9
|
npx supercov runs latest runners
|
|
@@ -28,13 +28,13 @@ would for another npm package.
|
|
|
28
28
|
Run the same command from the repository root. If first-party code lives in an
|
|
29
29
|
unusual directory, declare the source roots explicitly:
|
|
30
30
|
|
|
31
|
-
```sh
|
|
31
|
+
```sh supercov
|
|
32
32
|
SUPERCOV_SOURCE_ROOTS=src,app npx supercov -- npm test
|
|
33
33
|
```
|
|
34
34
|
|
|
35
35
|
Then inspect what Supercov included and excluded:
|
|
36
36
|
|
|
37
|
-
```sh
|
|
37
|
+
```sh supercov
|
|
38
38
|
npx supercov runs latest scope
|
|
39
39
|
```
|
|
40
40
|
|
|
@@ -45,7 +45,7 @@ warning. The goal is an honest boundary around code the repository owns.
|
|
|
45
45
|
|
|
46
46
|
First check runner and source scope:
|
|
47
47
|
|
|
48
|
-
```sh
|
|
48
|
+
```sh supercov
|
|
49
49
|
npx supercov runs latest runners
|
|
50
50
|
npx supercov runs latest scope
|
|
51
51
|
npx supercov runs latest gaps
|
|
@@ -67,7 +67,7 @@ file that cannot be compiled with them is measured through Ruby's `Coverage`
|
|
|
67
67
|
module alone rather than failing the run. To put a file on that path
|
|
68
68
|
deliberately, name a fragment of its path:
|
|
69
69
|
|
|
70
|
-
```sh
|
|
70
|
+
```sh supercov
|
|
71
71
|
SUPERCOV_RUBY_SKIP_PROBES=app/models/order.rb npx supercov -- bundle exec rspec
|
|
72
72
|
```
|
|
73
73
|
|
|
@@ -82,7 +82,7 @@ workspace after relevant source, tests, dependencies, configuration, or
|
|
|
82
82
|
toolchain inputs change. Rerun the same complete command to create a current
|
|
83
83
|
baseline:
|
|
84
84
|
|
|
85
|
-
```sh
|
|
85
|
+
```sh supercov
|
|
86
86
|
npx supercov -- npm test
|
|
87
87
|
```
|
|
88
88
|
|
|
@@ -133,7 +133,7 @@ mode still match.
|
|
|
133
133
|
|
|
134
134
|
Inspect the recorded phases with:
|
|
135
135
|
|
|
136
|
-
```sh
|
|
136
|
+
```sh supercov
|
|
137
137
|
npx supercov runs latest
|
|
138
138
|
```
|
|
139
139
|
|
|
@@ -143,7 +143,7 @@ See [Speed and storage](performance.md) for practical ways to shorten a loop.
|
|
|
143
143
|
|
|
144
144
|
Preview cleanup, then choose how much history to keep:
|
|
145
145
|
|
|
146
|
-
```sh
|
|
146
|
+
```sh supercov
|
|
147
147
|
npx supercov clean --dry-run
|
|
148
148
|
npx supercov clean --keep 20
|
|
149
149
|
npx supercov clean
|
package/docs/verification.md
CHANGED
|
@@ -16,7 +16,7 @@ Before merging, check three things:
|
|
|
16
16
|
3. **The test protects behavior.** It should make a meaningful assertion without
|
|
17
17
|
weakening existing assertions or changing application code for the metric.
|
|
18
18
|
|
|
19
|
-
```sh
|
|
19
|
+
```sh supercov
|
|
20
20
|
npx supercov diff <baseline-run> <new-run>
|
|
21
21
|
npx supercov runs <new-run> test "new test name"
|
|
22
22
|
```
|
|
@@ -34,7 +34,7 @@ Supercov separates four states:
|
|
|
34
34
|
- **stale** — the run is valid history but no longer describes the current
|
|
35
35
|
workspace.
|
|
36
36
|
|
|
37
|
-
```sh
|
|
37
|
+
```sh supercov
|
|
38
38
|
npx supercov runs latest
|
|
39
39
|
npx supercov runs latest scope
|
|
40
40
|
npx supercov runs latest gaps
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "supercov",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"description": "Coverage for coding agents and software factories
|
|
3
|
+
"version": "0.0.45",
|
|
4
|
+
"description": "Coverage for coding agents and software factories \ud83c\udf19",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -15,20 +15,21 @@
|
|
|
15
15
|
"files": [
|
|
16
16
|
"bin",
|
|
17
17
|
"runtime/javascript",
|
|
18
|
-
"docs",
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
"
|
|
18
|
+
"docs/getting-started.md",
|
|
19
|
+
"docs/agent-loop.md",
|
|
20
|
+
"docs/assertions.md",
|
|
21
|
+
"docs/assertion-evidence.md",
|
|
22
|
+
"docs/assertion-maps.md",
|
|
23
|
+
"docs/assertion-agent.md",
|
|
24
|
+
"docs/troubleshooting.md",
|
|
25
|
+
"docs/cli.md",
|
|
26
|
+
"docs/coverage-model.md",
|
|
27
|
+
"docs/evidence.md",
|
|
28
|
+
"docs/supported-suites.md",
|
|
29
|
+
"docs/verification.md",
|
|
30
|
+
"docs/performance.md",
|
|
31
|
+
"docs/workspace-isolation.md",
|
|
32
|
+
"schemas",
|
|
32
33
|
"README.md"
|
|
33
34
|
],
|
|
34
35
|
"engines": {
|
|
@@ -47,7 +48,6 @@
|
|
|
47
48
|
},
|
|
48
49
|
"scripts": {
|
|
49
50
|
"build": "cargo build -p supercov",
|
|
50
|
-
"build:asserted-typescript": "npm --prefix analyzers/typescript run build",
|
|
51
51
|
"sync:rust-assets": "node scripts/sync-rust-package-assets.mjs",
|
|
52
52
|
"test:rust-assets": "node scripts/sync-rust-package-assets.mjs --check",
|
|
53
53
|
"check:rustc-backend-spike": "(cd spikes/rustc-backend && RUSTC_BOOTSTRAP=1 RUSTUP_TOOLCHAIN=1.95.0 cargo fmt --check && RUSTC_BOOTSTRAP=1 RUSTUP_TOOLCHAIN=1.95.0 cargo clippy --all-targets -- -D warnings)",
|
|
@@ -55,11 +55,8 @@
|
|
|
55
55
|
"test:rust-compiler-spikes": "cargo build -p supercov && node scripts/rust-libtest-companion-spike.mjs && node scripts/rust-async-attribution-spike.mjs && node scripts/rust-subprocess-attribution-spike.mjs && node scripts/rust-custom-harness-spike.mjs && node scripts/rust-libtest-builder-lifecycle-spike.mjs",
|
|
56
56
|
"test": "cargo test --workspace",
|
|
57
57
|
"test:runtime": "node --test tests/runtime/*.test.mjs",
|
|
58
|
-
"test:asserted-typescript": "npm --prefix analyzers/typescript test",
|
|
59
|
-
"test:asserted-integration": "cargo build -p supercov && npm --prefix analyzers/typescript run build && SUPERCOV_ASSERTED_INTEGRATION=1 node --test analyzers/typescript/tests/archive.integration.test.mjs",
|
|
60
|
-
"test:asserted-package": "cargo build -p supercov && npm run build:asserted-typescript && node scripts/asserted-packed-integration.mjs",
|
|
61
58
|
"test:fixture": "cargo build -p supercov && node scripts/rust-fixture-matrix.mjs",
|
|
62
|
-
"test:packed-npx": "cargo build --release -p supercov &&
|
|
59
|
+
"test:packed-npx": "cargo build --release -p supercov && node scripts/packed-npx-integration.mjs",
|
|
63
60
|
"test:isolation": "cargo build -p supercov && node scripts/isolation-integration.mjs",
|
|
64
61
|
"test:filesystem": "cargo test --workspace && cargo build -p supercov && node scripts/workspace-crash-integration.mjs",
|
|
65
62
|
"test:watchdog": "cargo build -p supercov && node scripts/watchdog-integration.mjs",
|
|
@@ -67,7 +64,7 @@
|
|
|
67
64
|
"test:agent": "cargo build -p supercov && node scripts/agent-query-eval.mjs",
|
|
68
65
|
"test:engine": "cargo fmt --all -- --check && cargo clippy --workspace --all-targets -- -D warnings && cargo test --workspace && cargo build -p supercov && npm run test:runtime && npm run test:rust-assets && node scripts/rust-process-supervision.mjs && node scripts/rust-direct-node-integration.mjs && node scripts/rust-public-run-integration.mjs && node scripts/rust-embedded-runtime-integration.mjs && node scripts/rust-direct-vitest-integration.mjs && node scripts/rust-direct-jest-integration.mjs && node scripts/rust-direct-playwright-integration.mjs && node scripts/rust-custom-browser-playwright-integration.mjs && node scripts/rust-generic-esbuild-integration.mjs && node scripts/rust-generic-tsc-integration.mjs && node scripts/rust-generic-build-matrix.mjs && node scripts/rust-vite-playwright-integration.mjs",
|
|
69
66
|
"test:platform": "cargo test --workspace && cargo build -p supercov && node scripts/rust-process-supervision.mjs && node scripts/workspace-crash-integration.mjs",
|
|
70
|
-
"test:native-package": "cargo build --release -p supercov &&
|
|
67
|
+
"test:native-package": "cargo build --release -p supercov && node scripts/native-package-integration.mjs && node scripts/native-release-set-integration.mjs",
|
|
71
68
|
"test:pypi-wheel": "node scripts/pypi-wheel-integration.mjs",
|
|
72
69
|
"test:pypi-registry": "node scripts/pypi-registry-integration.mjs",
|
|
73
70
|
"build:rubygem": "cargo build --release -p supercov && node scripts/build-rubygem.mjs",
|
|
@@ -78,28 +75,31 @@
|
|
|
78
75
|
"test:test262": "cargo build --release -p supercov && node scripts/test262-equivalence.mjs",
|
|
79
76
|
"benchmark:check": "cargo build --release -p supercov && node scripts/rust-transform-benchmark.mjs",
|
|
80
77
|
"benchmark:python-monitoring": "cargo build -p supercov && node scripts/python-monitoring-benchmark.mjs",
|
|
81
|
-
"check": "cargo fmt --all -- --check && cargo clippy --workspace --all-targets -- -D warnings && npm run test && npm run test:runtime && npm run test:rust-assets && npm run test:
|
|
78
|
+
"check": "cargo fmt --all -- --check && cargo clippy --workspace --all-targets -- -D warnings && npm run test && npm run test:runtime && npm run test:rust-assets && npm run test:assertion-maps && node scripts/package-preflight.mjs && node scripts/verify-binstall-metadata.mjs --offline",
|
|
82
79
|
"release:check": "cargo clean && node scripts/sweep-target.mjs && npm run check && npm run test:engine && npm run test:fixture && npm run test:watchdog && npm run test:engine-contract && npm run test:agent && npm run test:child-attribution && npm run test:host-loader && npm run test:python-monitoring && npm run test:ruby-coverage && npm run test:rust-public-cargo && npm run test:packed-npx && npm run test:clang-mcdc && npm run benchmark:check",
|
|
83
80
|
"release:bump": "node scripts/bump-version.mjs",
|
|
84
81
|
"sweep": "node scripts/sweep-target.mjs",
|
|
85
82
|
"oracle:rust": "cargo build --release -p supercov && node scripts/rust-coverage-oracle.mjs",
|
|
86
|
-
"prepack": "
|
|
83
|
+
"prepack": "node scripts/package-preflight.mjs",
|
|
87
84
|
"prepublishOnly": "npm run release:check",
|
|
88
85
|
"test:child-attribution": "cargo build -p supercov && node scripts/rust-child-attribution-integration.mjs",
|
|
89
86
|
"test:host-loader": "cargo build -p supercov && node scripts/rust-host-loader-integration.mjs",
|
|
90
87
|
"test:python-monitoring": "cargo build -p supercov && node scripts/python-monitoring-integration.mjs",
|
|
91
88
|
"test:ruby-coverage": "cargo build -p supercov && node scripts/ruby-coverage-integration.mjs",
|
|
92
|
-
"test:rust-public-cargo": "cargo build -p supercov && node scripts/rust-public-cargo-integration.mjs"
|
|
89
|
+
"test:rust-public-cargo": "cargo build -p supercov && node scripts/rust-public-cargo-integration.mjs",
|
|
90
|
+
"test:assertion-maps": "cargo build -p supercov && node scripts/assertion-map-schema.mjs --check && node scripts/assertion-map-integration.mjs && node scripts/assertion-map-js-integration.mjs",
|
|
91
|
+
"test:assertion-maps:js": "cargo build -p supercov && node scripts/assertion-map-schema.mjs --check && node scripts/assertion-map-js-integration.mjs",
|
|
92
|
+
"sync:assertion-schema": "cargo build -p supercov && node scripts/assertion-map-schema.mjs"
|
|
93
93
|
},
|
|
94
94
|
"optionalDependencies": {
|
|
95
|
-
"@supercov/cli-darwin-arm64": "0.0.
|
|
96
|
-
"@supercov/cli-darwin-x64": "0.0.
|
|
97
|
-
"@supercov/cli-linux-arm64-gnu": "0.0.
|
|
98
|
-
"@supercov/cli-linux-arm64-musl": "0.0.
|
|
99
|
-
"@supercov/cli-linux-x64-gnu": "0.0.
|
|
100
|
-
"@supercov/cli-linux-x64-musl": "0.0.
|
|
101
|
-
"@supercov/cli-win32-arm64": "0.0.
|
|
102
|
-
"@supercov/cli-win32-x64": "0.0.
|
|
95
|
+
"@supercov/cli-darwin-arm64": "0.0.45",
|
|
96
|
+
"@supercov/cli-darwin-x64": "0.0.45",
|
|
97
|
+
"@supercov/cli-linux-arm64-gnu": "0.0.45",
|
|
98
|
+
"@supercov/cli-linux-arm64-musl": "0.0.45",
|
|
99
|
+
"@supercov/cli-linux-x64-gnu": "0.0.45",
|
|
100
|
+
"@supercov/cli-linux-x64-musl": "0.0.45",
|
|
101
|
+
"@supercov/cli-win32-arm64": "0.0.45",
|
|
102
|
+
"@supercov/cli-win32-x64": "0.0.45"
|
|
103
103
|
},
|
|
104
104
|
"peerDependencies": {
|
|
105
105
|
"@playwright/test": ">=1.55.0",
|
|
@@ -123,6 +123,7 @@
|
|
|
123
123
|
"@types/node": "^24.0.0",
|
|
124
124
|
"esbuild": "^0.28.2",
|
|
125
125
|
"expect": "30.4.1",
|
|
126
|
+
"jest": "30.5.1",
|
|
126
127
|
"next": "^16.3.2",
|
|
127
128
|
"react": "^19.2.4",
|
|
128
129
|
"react-dom": "^19.2.4",
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { withNodeAssertionPhase } from "./runtime.mjs";
|
|
2
|
+
import { relative, sep } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
2
4
|
const ASSERTION_METHODS = new Set([
|
|
3
5
|
"deepEqual",
|
|
4
6
|
"deepStrictEqual",
|
|
@@ -19,18 +21,40 @@ const ASSERTION_METHODS = new Set([
|
|
|
19
21
|
"strictEqual",
|
|
20
22
|
"throws",
|
|
21
23
|
]);
|
|
22
|
-
function assertionSource() {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
function assertionSource(boundary) {
|
|
25
|
+
// Omit our own frames by function identity, not basename: a user's helper
|
|
26
|
+
// may itself be called runtime.mjs or nodeAssertAdapter.mjs. Never search
|
|
27
|
+
// deeper for a plausible-looking caller when the immediate frame is opaque.
|
|
28
|
+
// A loader may have transformed this file without composing source maps.
|
|
29
|
+
// Qualify stack coordinates so they cannot masquerade as the original
|
|
30
|
+
// source positions emitted by lexical probes and used for oracle matching.
|
|
31
|
+
try {
|
|
32
|
+
const error = {};
|
|
33
|
+
Error.captureStackTrace(error, boundary);
|
|
34
|
+
if (typeof error.stack !== "string")
|
|
35
|
+
return undefined;
|
|
36
|
+
const entry = error.stack.split("\n")[1]?.trim();
|
|
37
|
+
const match = entry && /(?:^at (?:async )?| \()((?:file:\/\/\/|\/|[A-Za-z]:[\\/]).*):(\d+):(\d+)\)?$/.exec(entry);
|
|
38
|
+
if (!match)
|
|
39
|
+
return undefined;
|
|
40
|
+
const file = match[1].startsWith("file:") ? fileURLToPath(match[1]) : match[1];
|
|
41
|
+
const roots = [process.env.SUPERCOV_PROJECT_ROOT, process.env.SUPERCOV_SOURCE_PROJECT_ROOT, process.cwd()].filter(Boolean);
|
|
42
|
+
for (const root of roots) {
|
|
43
|
+
const path = relative(root, file);
|
|
44
|
+
if (path !== ".." && !path.startsWith(`..${sep}`) && !/^(?:[A-Za-z]:|[\\/])/.test(path))
|
|
45
|
+
return `runtime-stack:${path.split(sep).join("/")}:${match[2]}:${match[3]}`;
|
|
46
|
+
}
|
|
47
|
+
return `runtime-stack:${file.split(sep).join("/")}:${match[2]}:${match[3]}`;
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
// Custom stack formatters must not change the user's assertion outcome.
|
|
27
51
|
return undefined;
|
|
28
|
-
|
|
52
|
+
}
|
|
29
53
|
}
|
|
30
54
|
function wrapAssertion(original, operation) {
|
|
31
55
|
return new Proxy(original, {
|
|
32
|
-
apply(target, thisArgument, argumentsList) {
|
|
33
|
-
return withNodeAssertionPhase(operation, assertionSource(), () => Reflect.apply(target, thisArgument, argumentsList));
|
|
56
|
+
apply: function assertionApply(target, thisArgument, argumentsList) {
|
|
57
|
+
return withNodeAssertionPhase(operation, () => assertionSource(assertionApply), () => Reflect.apply(target, thisArgument, argumentsList));
|
|
34
58
|
},
|
|
35
59
|
});
|
|
36
60
|
}
|
|
@@ -2,7 +2,7 @@ import * as native from "node:test";
|
|
|
2
2
|
import { fileURLToPath } from "node:url";
|
|
3
3
|
import vm from "node:vm";
|
|
4
4
|
import { beginBufferedServerEvidence, flushBufferedServerEvidence, takeNodeAssertionPhases, withCoverageCarrier, } from "./runtime.mjs";
|
|
5
|
-
import { callerLocation, runnerExecutionScope, writeRunnerEvidence, } from "./runnerEvidence.mjs";
|
|
5
|
+
import { callerLocation, runnerExecutionScope, runnerTestId, writeRunnerEvidence, } from "./runnerEvidence.mjs";
|
|
6
6
|
function callbackIndex(args) {
|
|
7
7
|
for (let index = args.length - 1; index >= 0; index -= 1)
|
|
8
8
|
if (typeof args[index] === "function")
|
|
@@ -86,16 +86,18 @@ function restoreUserError(error, depth = 0) {
|
|
|
86
86
|
}
|
|
87
87
|
return error;
|
|
88
88
|
}
|
|
89
|
-
|
|
89
|
+
const registrationCounts = new Map();
|
|
90
|
+
function wrappedRegistration(original, parentTestId) {
|
|
90
91
|
const wrapped = function supercovNodeTest(...args) {
|
|
91
92
|
const index = callbackIndex(args);
|
|
92
93
|
if (index < 0)
|
|
93
94
|
return Reflect.apply(original, this, args);
|
|
94
95
|
const callback = args[index];
|
|
95
|
-
const location = callerLocation(
|
|
96
|
+
const location = callerLocation(supercovNodeTest);
|
|
96
97
|
const identity = {
|
|
97
98
|
runner: "node:test",
|
|
98
99
|
name: testName(args, callback),
|
|
100
|
+
...(parentTestId ? { parentTestId } : {}),
|
|
99
101
|
...location,
|
|
100
102
|
// Source-map producers disagree about whether a call expression maps to
|
|
101
103
|
// its first token or the first token on its source line. The line and
|
|
@@ -104,6 +106,12 @@ function wrappedRegistration(original) {
|
|
|
104
106
|
// keeps one identity when esbuild, Babel, SWC, or TypeScript rewrites it.
|
|
105
107
|
...(location.line === undefined ? {} : { column: 1 }),
|
|
106
108
|
};
|
|
109
|
+
// Allocate at registration, never callback completion: concurrent tests
|
|
110
|
+
// can finish in any order. Count each source/name within its parent.
|
|
111
|
+
const registrationKey = runnerTestId(identity);
|
|
112
|
+
const registrationOrdinal = registrationCounts.get(registrationKey) ?? 0;
|
|
113
|
+
registrationCounts.set(registrationKey, registrationOrdinal + 1);
|
|
114
|
+
identity.registrationOrdinal = registrationOrdinal;
|
|
107
115
|
const scope = runnerExecutionScope(identity);
|
|
108
116
|
const options = testOptions(args, index);
|
|
109
117
|
const evidenceDirectory = process.env["SUPERCOV_EVIDENCE_DIR"];
|
|
@@ -129,7 +137,7 @@ function wrappedRegistration(original) {
|
|
|
129
137
|
};
|
|
130
138
|
}
|
|
131
139
|
if (property === "test" && typeof value === "function")
|
|
132
|
-
return wrappedRegistration(value.bind(target));
|
|
140
|
+
return wrappedRegistration(value.bind(target), scope.testId);
|
|
133
141
|
return typeof value === "function" ? value.bind(target) : value;
|
|
134
142
|
},
|
|
135
143
|
});
|
|
@@ -192,7 +200,7 @@ function wrappedRegistration(original) {
|
|
|
192
200
|
Object.defineProperty(wrapped, property, {
|
|
193
201
|
configurable: true,
|
|
194
202
|
enumerable: true,
|
|
195
|
-
value: wrappedRegistration(member),
|
|
203
|
+
value: wrappedRegistration(member, parentTestId),
|
|
196
204
|
});
|
|
197
205
|
}
|
|
198
206
|
return wrapped;
|