@specific.dev/spectest 0.90.2 → 0.90.3
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/dist/browser-coverage.d.ts +5 -5
- package/dist/browser-coverage.js +11 -14
- package/dist/coverage.d.ts +1 -1
- package/dist/coverage.js +3 -3
- package/package.json +1 -1
- package/src/browser-coverage.ts +11 -13
- package/src/coverage.test.ts +50 -0
- package/src/coverage.ts +3 -3
|
@@ -22,10 +22,10 @@ export declare function foldBrowserCoverage(service: string, files: FileCounts):
|
|
|
22
22
|
/** Harvest every live session, so a capture sees the counters of code
|
|
23
23
|
* that ran since the last browser op. */
|
|
24
24
|
export declare function harvestAllBrowserCoverage(): Promise<void>;
|
|
25
|
-
/**
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
export declare function
|
|
25
|
+
/** Take one service's lcov report and clear only its totals. Other
|
|
26
|
+
* services retain their coverage until their own capture. Each capture
|
|
27
|
+
* is a delta; after every service is captured, a forked child inherits
|
|
28
|
+
* empty totals from its parent. */
|
|
29
|
+
export declare function takeBrowserCoverageReport(service: string): string;
|
|
30
30
|
/** The current totals, without clearing them (tests). */
|
|
31
31
|
export declare function browserCoverageReports(): Map<string, string>;
|
package/dist/browser-coverage.js
CHANGED
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
//
|
|
13
13
|
// Harvest runs before every browser step (a click that navigates
|
|
14
14
|
// cross-site replaces the renderer, and the old counters with it) and at
|
|
15
|
-
// every coverage capture. `
|
|
16
|
-
// one
|
|
15
|
+
// every coverage capture. `takeBrowserCoverageReport` renders and clears
|
|
16
|
+
// one service's totals for the `case-coverage` bundle.
|
|
17
17
|
//
|
|
18
18
|
// Configured by the daemon at /load with the host → service table; a
|
|
19
19
|
// project with no `coverage: { browser: true }` service never attaches
|
|
@@ -196,18 +196,15 @@ function parseDataUrl(ref) {
|
|
|
196
196
|
export async function harvestAllBrowserCoverage() {
|
|
197
197
|
await Promise.all([...LIVE_COLLECTORS].map((c) => harvestBrowserCoverage(c.cdp)));
|
|
198
198
|
}
|
|
199
|
-
/**
|
|
200
|
-
*
|
|
201
|
-
*
|
|
202
|
-
*
|
|
203
|
-
export function
|
|
204
|
-
const
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
}
|
|
209
|
-
TOTALS.clear();
|
|
210
|
-
return out;
|
|
199
|
+
/** Take one service's lcov report and clear only its totals. Other
|
|
200
|
+
* services retain their coverage until their own capture. Each capture
|
|
201
|
+
* is a delta; after every service is captured, a forked child inherits
|
|
202
|
+
* empty totals from its parent. */
|
|
203
|
+
export function takeBrowserCoverageReport(service) {
|
|
204
|
+
const files = TOTALS.get(service);
|
|
205
|
+
const report = files ? lcovDocument(files) : "TN:\n";
|
|
206
|
+
TOTALS.delete(service);
|
|
207
|
+
return report;
|
|
211
208
|
}
|
|
212
209
|
/** The current totals, without clearing them (tests). */
|
|
213
210
|
export function browserCoverageReports() {
|
package/dist/coverage.d.ts
CHANGED
|
@@ -294,7 +294,7 @@ export declare function collectNodeReports(dir: string): Promise<NodeReportStats
|
|
|
294
294
|
* loads from this service's origins, maps it back to source through the
|
|
295
295
|
* served source map, and writes one lcov per capture (`browser.lcov`)
|
|
296
296
|
* holding what ran since the previous capture: every live session is
|
|
297
|
-
* harvested first, and
|
|
297
|
+
* harvested first, and only this service's totals are taken and cleared. Nothing ran ⇒
|
|
298
298
|
* an lcov with no records, which is a report saying so.
|
|
299
299
|
*/
|
|
300
300
|
export declare function browser(): CoverageAdapter;
|
package/dist/coverage.js
CHANGED
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
// import * as coverage from "@specific.dev/spectest/coverage";
|
|
28
28
|
// coverage: { adapters: [coverage.node(), coverage.browser()] }
|
|
29
29
|
import { createHash } from "node:crypto";
|
|
30
|
-
import { harvestAllBrowserCoverage,
|
|
30
|
+
import { harvestAllBrowserCoverage, takeBrowserCoverageReport } from "./browser-coverage.js";
|
|
31
31
|
import { COVERAGE_CONTAINER_DIR } from "./harness/coverage.js";
|
|
32
32
|
export { COVERAGE_CONTAINER_DIR };
|
|
33
33
|
/** Where `node()` mounts its hook inside the container. */
|
|
@@ -810,7 +810,7 @@ export async function collectNodeReports(dir) {
|
|
|
810
810
|
* loads from this service's origins, maps it back to source through the
|
|
811
811
|
* served source map, and writes one lcov per capture (`browser.lcov`)
|
|
812
812
|
* holding what ran since the previous capture: every live session is
|
|
813
|
-
* harvested first, and
|
|
813
|
+
* harvested first, and only this service's totals are taken and cleared. Nothing ran ⇒
|
|
814
814
|
* an lcov with no records, which is a report saying so.
|
|
815
815
|
*/
|
|
816
816
|
export function browser() {
|
|
@@ -822,7 +822,7 @@ export function browser() {
|
|
|
822
822
|
},
|
|
823
823
|
async capture(ctx) {
|
|
824
824
|
await harvestAllBrowserCoverage();
|
|
825
|
-
const lcov =
|
|
825
|
+
const lcov = takeBrowserCoverageReport(ctx.service);
|
|
826
826
|
await ctx.writeReport("browser.lcov", lcov);
|
|
827
827
|
},
|
|
828
828
|
};
|
package/package.json
CHANGED
package/src/browser-coverage.ts
CHANGED
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
//
|
|
13
13
|
// Harvest runs before every browser step (a click that navigates
|
|
14
14
|
// cross-site replaces the renderer, and the old counters with it) and at
|
|
15
|
-
// every coverage capture. `
|
|
16
|
-
// one
|
|
15
|
+
// every coverage capture. `takeBrowserCoverageReport` renders and clears
|
|
16
|
+
// one service's totals for the `case-coverage` bundle.
|
|
17
17
|
//
|
|
18
18
|
// Configured by the daemon at /load with the host → service table; a
|
|
19
19
|
// project with no `coverage: { browser: true }` service never attaches
|
|
@@ -220,17 +220,15 @@ export async function harvestAllBrowserCoverage(): Promise<void> {
|
|
|
220
220
|
await Promise.all([...LIVE_COLLECTORS].map((c) => harvestBrowserCoverage(c.cdp)));
|
|
221
221
|
}
|
|
222
222
|
|
|
223
|
-
/**
|
|
224
|
-
*
|
|
225
|
-
*
|
|
226
|
-
*
|
|
227
|
-
export function
|
|
228
|
-
const
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
TOTALS.clear();
|
|
233
|
-
return out;
|
|
223
|
+
/** Take one service's lcov report and clear only its totals. Other
|
|
224
|
+
* services retain their coverage until their own capture. Each capture
|
|
225
|
+
* is a delta; after every service is captured, a forked child inherits
|
|
226
|
+
* empty totals from its parent. */
|
|
227
|
+
export function takeBrowserCoverageReport(service: string): string {
|
|
228
|
+
const files = TOTALS.get(service);
|
|
229
|
+
const report = files ? lcovDocument(files) : "TN:\n";
|
|
230
|
+
TOTALS.delete(service);
|
|
231
|
+
return report;
|
|
234
232
|
}
|
|
235
233
|
|
|
236
234
|
/** The current totals, without clearing them (tests). */
|
package/src/coverage.test.ts
CHANGED
|
@@ -135,6 +135,56 @@ describe("units", () => {
|
|
|
135
135
|
});
|
|
136
136
|
|
|
137
137
|
describe("browserCoverage", () => {
|
|
138
|
+
for (const order of ["dashboard first", "admin first", "concurrent"] as const) {
|
|
139
|
+
test(`services retain their own coverage and deltas: ${order}`, async () => {
|
|
140
|
+
const reports = new Map<string, string>();
|
|
141
|
+
const contexts = ["dashboard", "admin"].map((service): CoverageCaptureContext => ({
|
|
142
|
+
...fakeCtx("unused"),
|
|
143
|
+
service,
|
|
144
|
+
async writeReport(name, content) {
|
|
145
|
+
expect(name).toBe("browser.lcov");
|
|
146
|
+
reports.set(service, content);
|
|
147
|
+
},
|
|
148
|
+
}));
|
|
149
|
+
if (order === "admin first") contexts.reverse();
|
|
150
|
+
const capture = async () => {
|
|
151
|
+
if (order === "concurrent") {
|
|
152
|
+
await Promise.all(contexts.map((ctx) => browser().capture!(ctx)));
|
|
153
|
+
} else {
|
|
154
|
+
for (const ctx of contexts) await browser().capture!(ctx);
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
foldBrowserCoverage("dashboard", new Map([["src/dashboard.ts", new Map([[1, 2]])]]));
|
|
158
|
+
foldBrowserCoverage("admin", new Map([["src/admin.ts", new Map([[3, 4]])]]));
|
|
159
|
+
await capture();
|
|
160
|
+
expect(reports.get("dashboard")).toBe("TN:\nSF:src/dashboard.ts\nDA:1,2\nLF:1\nLH:1\nend_of_record\n");
|
|
161
|
+
expect(reports.get("admin")).toBe("TN:\nSF:src/admin.ts\nDA:3,4\nLF:1\nLH:1\nend_of_record\n");
|
|
162
|
+
|
|
163
|
+
await capture();
|
|
164
|
+
expect(reports.get("dashboard")).toBe("TN:\n");
|
|
165
|
+
expect(reports.get("admin")).toBe("TN:\n");
|
|
166
|
+
|
|
167
|
+
foldBrowserCoverage("admin", new Map([["src/admin.ts", new Map([[3, 1]])]]));
|
|
168
|
+
await capture();
|
|
169
|
+
expect(reports.get("dashboard")).toBe("TN:\n");
|
|
170
|
+
expect(reports.get("admin")).toBe("TN:\nSF:src/admin.ts\nDA:3,1\nLF:1\nLH:1\nend_of_record\n");
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
test("capturing a service with no coverage preserves other services' totals", async () => {
|
|
175
|
+
const reports = new Map<string, string>();
|
|
176
|
+
foldBrowserCoverage("dashboard", new Map([["src/dashboard.ts", new Map([[1, 2]])]]));
|
|
177
|
+
for (const service of ["admin", "dashboard"]) {
|
|
178
|
+
await browser().capture!({
|
|
179
|
+
...fakeCtx("unused"),
|
|
180
|
+
service,
|
|
181
|
+
async writeReport(_name, content) { reports.set(service, content); },
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
expect(reports.get("admin")).toBe("TN:\n");
|
|
185
|
+
expect(reports.get("dashboard")).toBe("TN:\nSF:src/dashboard.ts\nDA:1,2\nLF:1\nLH:1\nend_of_record\n");
|
|
186
|
+
});
|
|
187
|
+
|
|
138
188
|
test("writes an empty lcov when nothing ran for the service", async () => {
|
|
139
189
|
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "spectest-cov-"));
|
|
140
190
|
await browser().capture!(fakeCtx(dir));
|
package/src/coverage.ts
CHANGED
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
import { createHash } from "node:crypto";
|
|
31
31
|
|
|
32
32
|
import type { ServiceConfig } from "./index.js";
|
|
33
|
-
import { harvestAllBrowserCoverage,
|
|
33
|
+
import { harvestAllBrowserCoverage, takeBrowserCoverageReport } from "./browser-coverage.js";
|
|
34
34
|
|
|
35
35
|
import { COVERAGE_CONTAINER_DIR, type CoverageReportsMode } from "./harness/coverage.js";
|
|
36
36
|
export { COVERAGE_CONTAINER_DIR, type CoverageReportsMode };
|
|
@@ -969,7 +969,7 @@ export async function collectNodeReports(dir: string): Promise<NodeReportStats>
|
|
|
969
969
|
* loads from this service's origins, maps it back to source through the
|
|
970
970
|
* served source map, and writes one lcov per capture (`browser.lcov`)
|
|
971
971
|
* holding what ran since the previous capture: every live session is
|
|
972
|
-
* harvested first, and
|
|
972
|
+
* harvested first, and only this service's totals are taken and cleared. Nothing ran ⇒
|
|
973
973
|
* an lcov with no records, which is a report saying so.
|
|
974
974
|
*/
|
|
975
975
|
export function browser(): CoverageAdapter {
|
|
@@ -981,7 +981,7 @@ export function browser(): CoverageAdapter {
|
|
|
981
981
|
},
|
|
982
982
|
async capture(ctx) {
|
|
983
983
|
await harvestAllBrowserCoverage();
|
|
984
|
-
const lcov =
|
|
984
|
+
const lcov = takeBrowserCoverageReport(ctx.service);
|
|
985
985
|
await ctx.writeReport("browser.lcov", lcov);
|
|
986
986
|
},
|
|
987
987
|
};
|