supercov 4.2.0 → 4.3.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/docs/assertions.md +2 -0
- package/docs/cli.md +18 -2
- package/docs/quality.md +6 -0
- package/docs/security.md +6 -0
- package/package.json +9 -9
- package/runtime/javascript/playwright.mjs +30 -3
package/docs/assertions.md
CHANGED
|
@@ -86,6 +86,8 @@ npx supercov runs latest assertions
|
|
|
86
86
|
Supercov renders what the test ran -- its code, its helpers, and the source it
|
|
87
87
|
executed -- and asks [Jev](https://typesafe.ai) whether the test would fail for
|
|
88
88
|
each statement's change. It prints an estimate first; `--dry-run` sends nothing.
|
|
89
|
+
The estimate gives the first round and the most the pass can send, which is
|
|
90
|
+
what it sends when no test is judged to catch anything.
|
|
89
91
|
It needs a TypeSafe AI API key in `TYPESAFE_API_KEY`.
|
|
90
92
|
|
|
91
93
|
`assertions` reads the saved result with no network and no key, a page at a
|
package/docs/cli.md
CHANGED
|
@@ -61,7 +61,8 @@ the score is arithmetic this command does over the answers. Text reports a band,
|
|
|
61
61
|
`good`, `fair` or `weak`; `--json` carries the number and every check with what
|
|
62
62
|
is known about it. `--all` includes test files, generated output and anything
|
|
63
63
|
outside a source root, all of which are left out by default. `--dry-run` prints
|
|
64
|
-
the exact requests and contacts nothing
|
|
64
|
+
the exact requests and contacts nothing; how many there are and what they cost
|
|
65
|
+
is one line on stderr.
|
|
65
66
|
|
|
66
67
|
`quality diff` reports what changed between two assessments: which files lost
|
|
67
68
|
or gained health, each check that moved in them with its value before and after,
|
|
@@ -354,7 +355,17 @@ npx supercov diff <older-run> <newer-run>
|
|
|
354
355
|
|
|
355
356
|
`diff` reports gains and losses. Use it after adding a test to prove that the
|
|
356
357
|
expected behavior became covered without an unexplained regression elsewhere.
|
|
357
|
-
Neither input run is changed.
|
|
358
|
+
Neither input run is changed. Under the totals it lists what was lost, marked
|
|
359
|
+
`-`, and then what was gained, marked `+`:
|
|
360
|
+
|
|
361
|
+
```
|
|
362
|
+
gained: 1 lines, 1 branches, 0 MC/DC conditions
|
|
363
|
+
lost: 1 lines, 1 branches, 0 MC/DC conditions
|
|
364
|
+
- line src/fee.js:5
|
|
365
|
+
- branch src/fee.js:2 false
|
|
366
|
+
+ line src/fee.js:3
|
|
367
|
+
+ branch src/fee.js:2 true
|
|
368
|
+
```
|
|
358
369
|
|
|
359
370
|
Two runs of the same code can differ a little: what an end-to-end suite
|
|
360
371
|
reaches depends on timing, on the order of tests, and on state outside the
|
|
@@ -497,6 +508,11 @@ Merge creates a new run. The inputs must describe the same source,
|
|
|
497
508
|
configuration, toolchain, schema, and coverage denominator. Supercov rejects an
|
|
498
509
|
incompatible merge rather than publishing a misleading aggregate.
|
|
499
510
|
|
|
511
|
+
`assertions assess` assesses a merged run across every suite merged into it,
|
|
512
|
+
reusing the answers saved when its parts were assessed. `tests affected` is
|
|
513
|
+
asked of the runs that were merged, which hold the record of what each test
|
|
514
|
+
ran.
|
|
515
|
+
|
|
500
516
|
## Clean local data
|
|
501
517
|
|
|
502
518
|
```sh supercov
|
package/docs/quality.md
CHANGED
|
@@ -153,6 +153,12 @@ Source roots come from your package manifests and from what they declare, so a
|
|
|
153
153
|
Test files, generated output, tool scripts, examples, benchmarks and
|
|
154
154
|
documentation are left out, each with its reason. `--all` includes everything.
|
|
155
155
|
|
|
156
|
+
A JavaScript or TypeScript file a coverage run would measure is always read,
|
|
157
|
+
by `quality` and by `security`: the App Router handler at
|
|
158
|
+
`app/api/wordpress/test/route.ts` is a route, not a test, and a root named in
|
|
159
|
+
`SUPERCOV_SOURCE_ROOTS` is not second-guessed by its own name. Generated and
|
|
160
|
+
vendored files stay out.
|
|
161
|
+
|
|
156
162
|
If some of your code sits somewhere none of that recognises, Supercov asks Jev
|
|
157
163
|
about those paths with your whole tree as context, and says how many it decided
|
|
158
164
|
that way. To decide yourself:
|
package/docs/security.md
CHANGED
|
@@ -183,6 +183,12 @@ many of its measured lines no test reached. A handler that builds a query from
|
|
|
183
183
|
request input is one thing; the same handler that no test ever executes is a
|
|
184
184
|
stronger claim, and one that needs both halves of this product to make.
|
|
185
185
|
|
|
186
|
+
When the run's assertions were assessed (`runs <run> assertions assess`), the
|
|
187
|
+
report also says which flagged lines a test is judged to catch a change to, and
|
|
188
|
+
which flagged files tests run without catching any line of. A run that was not
|
|
189
|
+
assessed says so instead: nobody asked its tests, which is not the same as
|
|
190
|
+
their catching nothing.
|
|
191
|
+
|
|
186
192
|
## What a change introduced
|
|
187
193
|
|
|
188
194
|
```bash
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "supercov",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.3.0",
|
|
4
4
|
"description": "Coverage, security and code quality for coding agents",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"coverage",
|
|
@@ -119,14 +119,14 @@
|
|
|
119
119
|
"test:windows-tls": "node scripts/windows-tls-test.mjs"
|
|
120
120
|
},
|
|
121
121
|
"optionalDependencies": {
|
|
122
|
-
"@supercov/cli-darwin-arm64": "4.
|
|
123
|
-
"@supercov/cli-darwin-x64": "4.
|
|
124
|
-
"@supercov/cli-linux-arm64-gnu": "4.
|
|
125
|
-
"@supercov/cli-linux-arm64-musl": "4.
|
|
126
|
-
"@supercov/cli-linux-x64-gnu": "4.
|
|
127
|
-
"@supercov/cli-linux-x64-musl": "4.
|
|
128
|
-
"@supercov/cli-win32-arm64": "4.
|
|
129
|
-
"@supercov/cli-win32-x64": "4.
|
|
122
|
+
"@supercov/cli-darwin-arm64": "4.3.0",
|
|
123
|
+
"@supercov/cli-darwin-x64": "4.3.0",
|
|
124
|
+
"@supercov/cli-linux-arm64-gnu": "4.3.0",
|
|
125
|
+
"@supercov/cli-linux-arm64-musl": "4.3.0",
|
|
126
|
+
"@supercov/cli-linux-x64-gnu": "4.3.0",
|
|
127
|
+
"@supercov/cli-linux-x64-musl": "4.3.0",
|
|
128
|
+
"@supercov/cli-win32-arm64": "4.3.0",
|
|
129
|
+
"@supercov/cli-win32-x64": "4.3.0"
|
|
130
130
|
},
|
|
131
131
|
"peerDependencies": {
|
|
132
132
|
"@playwright/test": ">=1.55.0",
|
|
@@ -198,6 +198,7 @@ class CoveragePhaseController {
|
|
|
198
198
|
cdpSessions = new Map();
|
|
199
199
|
newDocumentScriptIds = new Map();
|
|
200
200
|
pendingRegistrations = new Set();
|
|
201
|
+
pageRegistrations = new WeakMap();
|
|
201
202
|
scriptUpdate = Promise.resolve();
|
|
202
203
|
proxyCache = new WeakMap();
|
|
203
204
|
runtimeSnapshots;
|
|
@@ -381,8 +382,27 @@ class CoveragePhaseController {
|
|
|
381
382
|
}
|
|
382
383
|
}
|
|
383
384
|
}
|
|
384
|
-
|
|
385
|
-
|
|
385
|
+
/**
|
|
386
|
+
* A page is registered once, and whoever asks while that is under way
|
|
387
|
+
* waits for it. Playwright announces a page to the context's listener
|
|
388
|
+
* before the fixture that hands it to the test has it, so the listener
|
|
389
|
+
* started the registration and the fixture, finding the page known,
|
|
390
|
+
* returned at once: the test's first `page.goto` began before the page had
|
|
391
|
+
* the session a phase is installed through. The document it loaded did not
|
|
392
|
+
* know its phase, and its hits were left to be placed by their time.
|
|
393
|
+
*/
|
|
394
|
+
registerPage(page) {
|
|
395
|
+
if (this.disposed)
|
|
396
|
+
return Promise.resolve();
|
|
397
|
+
let registration = this.pageRegistrations.get(page);
|
|
398
|
+
if (!registration) {
|
|
399
|
+
registration = this.registerNewPage(page);
|
|
400
|
+
this.pageRegistrations.set(page, registration);
|
|
401
|
+
}
|
|
402
|
+
return registration;
|
|
403
|
+
}
|
|
404
|
+
async registerNewPage(page) {
|
|
405
|
+
if (this.pages.has(page))
|
|
386
406
|
return;
|
|
387
407
|
timingCount("registerPage");
|
|
388
408
|
this.pages.add(page);
|
|
@@ -393,8 +413,15 @@ class CoveragePhaseController {
|
|
|
393
413
|
adopted: !this.contexts.has(context) && tracked && !headersKnown,
|
|
394
414
|
});
|
|
395
415
|
const cdp = await page.context().newCDPSession(page).catch(() => undefined);
|
|
396
|
-
if (cdp)
|
|
416
|
+
if (cdp) {
|
|
417
|
+
// Chromium runs a session's new-document scripts only once the
|
|
418
|
+
// session has enabled the Page domain. Without it the script that
|
|
419
|
+
// tells a document its phase was accepted and never ran: a page
|
|
420
|
+
// learned its phase only from the next action, after it had
|
|
421
|
+
// loaded, and everything it ran while loading was placed by time.
|
|
422
|
+
await cdp.send("Page.enable").catch(() => undefined);
|
|
397
423
|
this.cdpSessions.set(page, cdp);
|
|
424
|
+
}
|
|
398
425
|
const phaseId = this.requestPhaseId();
|
|
399
426
|
if (phaseId)
|
|
400
427
|
await this.activatePage(page, phaseId);
|