supercov 4.7.0 → 4.8.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/coverage-model.md +10 -1
- package/package.json +10 -10
- package/runtime/javascript/runtime.mjs +32 -2
package/docs/coverage-model.md
CHANGED
|
@@ -96,7 +96,16 @@ Both are useful:
|
|
|
96
96
|
|
|
97
97
|
Code that runs while no test is running counts in the run's total and in no
|
|
98
98
|
test's: a server starting before the first test, modules loading, work between
|
|
99
|
-
tests.
|
|
99
|
+
tests.
|
|
100
|
+
|
|
101
|
+
A request to your app server that names no test -- a webhook from a mock
|
|
102
|
+
Stripe server Supercov does not measure -- is credited to the test running when
|
|
103
|
+
the server handled it, if that test was the only one running then. A mock that
|
|
104
|
+
runs under Supercov passes the test's identity on in its own requests, and its
|
|
105
|
+
webhook is credited exactly. The run's
|
|
106
|
+
`Attribution` line counts those tests as `with server work credited by time`,
|
|
107
|
+
and each one's `runs <id> test` page says so. Work done while tests ran at
|
|
108
|
+
once, or while none ran, stays no test's. When a run has any, the summary's `By test kind` table ends with a
|
|
100
109
|
`no test` row for what only that covered, which is why a run with one kind of
|
|
101
110
|
test can show a total above that kind's own:
|
|
102
111
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "supercov",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.8.0",
|
|
4
4
|
"description": "Coverage, security and code quality for coding agents",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"coverage",
|
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
"eval:skill": "claude plugin eval plugins/supercov --scaffold --trust-plugin --no-publish --model claude-sonnet-5 --judge-model claude-haiku-4-5 --threshold 0.66 --tag behavior trigger --allow-tools Bash Edit Write --max-cost-usd 15",
|
|
84
84
|
"eval:skill-triggers": "claude plugin eval plugins/supercov --scaffold --trust-plugin --no-publish --model claude-sonnet-5 --judge-model claude-haiku-4-5 --threshold 0.66 --tag trigger --ablation none --max-cost-usd 5",
|
|
85
85
|
"test:engine": "cargo fmt --all -- --check && cargo clippy --workspace --all-targets -- -D warnings && cargo test --workspace && npm run test:runtime && npm run test:rust-assets && npm run test:engine-integrations",
|
|
86
|
-
"test:engine-integrations": "cargo build -p supercov && node scripts/html-report-integration.mjs && 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/mocha-failure-output.mjs && node scripts/failure-output.mjs node ava tap && node scripts/side-by-side.mjs node && node scripts/merge-across.mjs && node scripts/rust-direct-playwright-integration.mjs && node scripts/rust-custom-browser-playwright-integration.mjs && node scripts/cross-origin-requests.mjs && node scripts/rust-classic-browser-integration.mjs && node scripts/rust-top-packages-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",
|
|
86
|
+
"test:engine-integrations": "cargo build -p supercov && node scripts/html-report-integration.mjs && 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/mocha-failure-output.mjs && node scripts/failure-output.mjs node ava tap && node scripts/side-by-side.mjs node && node scripts/merge-across.mjs && node scripts/rust-direct-playwright-integration.mjs && node scripts/rust-custom-browser-playwright-integration.mjs && node scripts/cross-origin-requests.mjs && node scripts/background-by-time.mjs && node scripts/rust-classic-browser-integration.mjs && node scripts/rust-top-packages-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",
|
|
87
87
|
"test:platform": "cargo test --workspace && cargo build -p supercov && node scripts/rust-process-supervision.mjs && node scripts/workspace-crash-integration.mjs",
|
|
88
88
|
"test:native-package": "cargo build --release -p supercov && node scripts/native-package-integration.mjs && node scripts/native-release-set-integration.mjs",
|
|
89
89
|
"test:pypi-wheel": "node scripts/pypi-wheel-integration.mjs",
|
|
@@ -120,14 +120,14 @@
|
|
|
120
120
|
"test:windows-tls": "node scripts/windows-tls-test.mjs"
|
|
121
121
|
},
|
|
122
122
|
"optionalDependencies": {
|
|
123
|
-
"@supercov/cli-darwin-arm64": "4.
|
|
124
|
-
"@supercov/cli-darwin-x64": "4.
|
|
125
|
-
"@supercov/cli-linux-arm64-gnu": "4.
|
|
126
|
-
"@supercov/cli-linux-arm64-musl": "4.
|
|
127
|
-
"@supercov/cli-linux-x64-gnu": "4.
|
|
128
|
-
"@supercov/cli-linux-x64-musl": "4.
|
|
129
|
-
"@supercov/cli-win32-arm64": "4.
|
|
130
|
-
"@supercov/cli-win32-x64": "4.
|
|
123
|
+
"@supercov/cli-darwin-arm64": "4.8.0",
|
|
124
|
+
"@supercov/cli-darwin-x64": "4.8.0",
|
|
125
|
+
"@supercov/cli-linux-arm64-gnu": "4.8.0",
|
|
126
|
+
"@supercov/cli-linux-arm64-musl": "4.8.0",
|
|
127
|
+
"@supercov/cli-linux-x64-gnu": "4.8.0",
|
|
128
|
+
"@supercov/cli-linux-x64-musl": "4.8.0",
|
|
129
|
+
"@supercov/cli-win32-arm64": "4.8.0",
|
|
130
|
+
"@supercov/cli-win32-x64": "4.8.0"
|
|
131
131
|
},
|
|
132
132
|
"peerDependencies": {
|
|
133
133
|
"@playwright/test": ">=1.55.0",
|
|
@@ -461,7 +461,16 @@ function attemptKey(scope) {
|
|
|
461
461
|
function serverRecordKey(record) {
|
|
462
462
|
var _a8;
|
|
463
463
|
const suffix = record.type === "decision" ? `${record.meta.id}:${vectorKey(record.vector)}` : record.id;
|
|
464
|
-
|
|
464
|
+
// Each request that names no test keeps its own first hits: the report
|
|
465
|
+
// credits them to the test running when it came, and a later request's
|
|
466
|
+
// work belongs to whichever test was running then.
|
|
467
|
+
const request = record.request ? `request-${record.request}:` : "";
|
|
468
|
+
return `${request}${(_a8 = record.phaseId) != null ? _a8 : "unscoped"}:${record.type}:${suffix}`;
|
|
469
|
+
}
|
|
470
|
+
// Numbers the requests a server handles that name no test.
|
|
471
|
+
function nextUnscopedRequest() {
|
|
472
|
+
state.unscopedRequests = (state.unscopedRequests || 0) + 1;
|
|
473
|
+
return state.unscopedRequests;
|
|
465
474
|
}
|
|
466
475
|
function beginBufferedServerEvidence(scope) {
|
|
467
476
|
if (isBrowser)
|
|
@@ -794,7 +803,11 @@ function appendServer(record) {
|
|
|
794
803
|
try {
|
|
795
804
|
const directory = scope ? serverEvidenceDirectory(scope) : void 0;
|
|
796
805
|
const path = scope ? serverEvidencePath(scope) : void 0;
|
|
797
|
-
|
|
806
|
+
// Work done while handling a request that named no test -- a webhook a
|
|
807
|
+
// mock server sends -- says so, with the request's number.
|
|
808
|
+
const stored = serverPhaseStorage == null ? void 0 : serverPhaseStorage.getStore();
|
|
809
|
+
const unscopedRequest = !scope && stored && stored.request ? { request: stored.request } : {};
|
|
810
|
+
const serialized = __spreadValues(__spreadValues(__spreadValues({}, record), scope ? { scope } : {}), unscopedRequest);
|
|
798
811
|
if (scope && state.bufferedAttempts.has(attemptKey(scope))) {
|
|
799
812
|
const key = attemptKey(scope);
|
|
800
813
|
const buffered = (_c = state.serverBuffers.get(key)) != null ? _c : {
|
|
@@ -1387,9 +1400,24 @@ function installNodeRequestPropagation() {
|
|
|
1387
1400
|
// the server process were created by a shared before hook.
|
|
1388
1401
|
const incoming = requestCoverageContext(args[0]);
|
|
1389
1402
|
if (incoming) context = incoming.scope ? incoming : context != null ? context : currentRequestContext();
|
|
1403
|
+
// A request that names no test, to a server no test owns, is numbered:
|
|
1404
|
+
// the report credits its work to the test running when it came.
|
|
1405
|
+
if (incoming && serverPhaseStorage && !(context && (context.scope || context.phaseId)))
|
|
1406
|
+
context = { request: nextUnscopedRequest() };
|
|
1407
|
+
// Node emits a request's body and its response's events outside the
|
|
1408
|
+
// handler's context, so a handler that reads the body -- `req.on('end')`
|
|
1409
|
+
// -- ran as no test's. The request and response carry it with them.
|
|
1410
|
+
if (incoming && context) {
|
|
1411
|
+
for (const emitter of args.slice(0, 2)) {
|
|
1412
|
+
if (emitter && typeof emitter === "object" && typeof emitter.emit === "function")
|
|
1413
|
+
emitterCoverageContexts.set(emitter, context);
|
|
1414
|
+
}
|
|
1415
|
+
}
|
|
1390
1416
|
}
|
|
1391
1417
|
const invoke = () => Reflect.apply(original, this, [event, ...args]);
|
|
1392
1418
|
try {
|
|
1419
|
+
if (context && context.request && !context.scope)
|
|
1420
|
+
return serverPhaseStorage.run(context, () => withProbeV2Context(context, invoke));
|
|
1393
1421
|
return context ? withCoverageCarrier({ version: 1, ...context }, invoke) : invoke();
|
|
1394
1422
|
} finally {
|
|
1395
1423
|
if (event === "close") emitterCoverageContexts.delete(this);
|
|
@@ -1410,6 +1438,8 @@ function withRequestPhase(handler, event) {
|
|
|
1410
1438
|
// owner. Shared servers have no captured test scope and stay unattributed.
|
|
1411
1439
|
const inheritedContext = requestContext && requestContext.scope ? {} : registeredContext.scope ? registeredContext : requestContext === void 0 ? currentRequestContext() : {};
|
|
1412
1440
|
const context = __spreadValues(__spreadValues({}, ((_a8 = requestContext == null ? void 0 : requestContext.scope) != null ? _a8 : inheritedContext.scope) ? { scope: (_b = requestContext == null ? void 0 : requestContext.scope) != null ? _b : inheritedContext.scope } : {}), ((_c = requestContext == null ? void 0 : requestContext.phaseId) != null ? _c : inheritedContext.phaseId) ? { phaseId: (_d = requestContext == null ? void 0 : requestContext.phaseId) != null ? _d : inheritedContext.phaseId } : {});
|
|
1441
|
+
if (requestContext !== void 0 && !context.scope)
|
|
1442
|
+
context.request = nextUnscopedRequest();
|
|
1413
1443
|
const invoke = () => {
|
|
1414
1444
|
if (event === "connection" && context.scope && args[0] &&
|
|
1415
1445
|
typeof args[0] === "object" && typeof args[0].emit === "function")
|