@rpcbase/test 0.357.0 → 0.359.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.
Files changed (41) hide show
  1. package/dist/clearDatabase.js +12 -10
  2. package/dist/clearDatabase.js.map +1 -1
  3. package/dist/cli.js +556 -439
  4. package/dist/cli.js.map +1 -1
  5. package/dist/coverage/collect.js +101 -63
  6. package/dist/coverage/collect.js.map +1 -1
  7. package/dist/coverage/config-loader.js +230 -180
  8. package/dist/coverage/config-loader.js.map +1 -1
  9. package/dist/coverage/config.js +100 -76
  10. package/dist/coverage/config.js.map +1 -1
  11. package/dist/coverage/console-text-report.js +220 -175
  12. package/dist/coverage/console-text-report.js.map +1 -1
  13. package/dist/coverage/files.js +58 -45
  14. package/dist/coverage/files.js.map +1 -1
  15. package/dist/coverage/fixtures.js +38 -27
  16. package/dist/coverage/fixtures.js.map +1 -1
  17. package/dist/coverage/global-setup.js +18 -15
  18. package/dist/coverage/global-setup.js.map +1 -1
  19. package/dist/coverage/index.js +55 -38
  20. package/dist/coverage/index.js.map +1 -1
  21. package/dist/coverage/report.js +466 -341
  22. package/dist/coverage/report.js.map +1 -1
  23. package/dist/coverage/reporter.js +60 -47
  24. package/dist/coverage/reporter.js.map +1 -1
  25. package/dist/coverage/v8-tracker.js +147 -115
  26. package/dist/coverage/v8-tracker.js.map +1 -1
  27. package/dist/index.js +75 -46
  28. package/dist/index.js.map +1 -1
  29. package/dist/runners/playwright.js +563 -438
  30. package/dist/runners/playwright.js.map +1 -1
  31. package/dist/runners/process.d.ts.map +1 -1
  32. package/dist/runners/process.js +183 -125
  33. package/dist/runners/process.js.map +1 -1
  34. package/dist/runners/vitest.js +171 -124
  35. package/dist/runners/vitest.js.map +1 -1
  36. package/dist/serverCoverage.js +42 -28
  37. package/dist/serverCoverage.js.map +1 -1
  38. package/dist/vitest.config.d.ts +1 -1
  39. package/dist/vitest.config.js +74 -62
  40. package/dist/vitest.config.js.map +1 -1
  41. package/package.json +4 -4
@@ -1,397 +1,522 @@
1
- import { findCoverageFiles } from "./files.js";
2
- import { createCollectCoverageMatcher, toPosix } from "./collect.js";
3
- import { generateConsoleTextCoverageReport } from "./console-text-report.js";
4
- import fsPromises from "node:fs/promises";
1
+ import fs from "node:fs/promises";
5
2
  import path from "node:path";
6
3
  import { fileURLToPath } from "node:url";
7
- import picomatch from "picomatch";
8
4
  import * as libCoverage from "istanbul-lib-coverage";
9
5
  import * as libInstrument from "istanbul-lib-instrument";
10
6
  import fg from "fast-glob";
7
+ import picomatch from "picomatch";
11
8
  import v8ToIstanbul from "v8-to-istanbul";
12
- //#region src/coverage/report.ts
13
- var TEXT_REPORT_FILENAME = "coverage.txt";
14
- var CoverageThresholdError = class extends Error {
15
- constructor(message) {
16
- super(message);
17
- this.name = "CoverageThresholdError";
18
- }
19
- };
9
+ import { createCollectCoverageMatcher, toPosix } from "./collect.js";
10
+ import { generateConsoleTextCoverageReport } from "./console-text-report.js";
11
+ import { findCoverageFiles } from "./files.js";
12
+ const TEXT_REPORT_FILENAME = "coverage.txt";
13
+ class CoverageThresholdError extends Error {
14
+ constructor(message) {
15
+ super(message);
16
+ this.name = "CoverageThresholdError";
17
+ }
18
+ }
20
19
  async function generateCoverageReport(config) {
21
- const coverageFiles = await findCoverageFiles(config);
22
- if (coverageFiles.length === 0) {
23
- console.warn("[coverage] no V8 coverage artifacts were generated");
24
- return;
25
- }
26
- const coverageLib = resolveCoverageLib();
27
- const coverageMap = coverageLib.createCoverageMap({});
28
- const matchesCollectCoverageFrom = createCollectCoverageMatcher(config.collectCoverageFrom, config.rootDir);
29
- for (const file of coverageFiles) {
30
- const payload = await readCoverageFile(file);
31
- if (!payload) continue;
32
- for (const script of payload.scripts) await mergeScriptCoverage(coverageMap, script, config, matchesCollectCoverageFrom);
33
- }
34
- if (config.includeAllFiles) await includeUntestedFiles(coverageMap, config, matchesCollectCoverageFrom);
35
- if (coverageMap.files().length === 0) {
36
- console.warn("[coverage] no library files matched the coverage filters");
37
- return;
38
- }
39
- await fsPromises.rm(config.coverageReportDir, {
40
- recursive: true,
41
- force: true
42
- });
43
- await fsPromises.mkdir(config.coverageReportDir, { recursive: true });
44
- const { createContext, reports } = await loadIstanbulModules();
45
- const context = createContext({
46
- dir: config.coverageReportDir,
47
- coverageMap,
48
- defaultSummarizer: "pkg"
49
- });
50
- const { output: reportOutput, summarizer } = generateConsoleTextCoverageReport(reports, context);
51
- process.stdout.write(reportOutput);
52
- reports.create("text", {
53
- file: TEXT_REPORT_FILENAME,
54
- summarizer
55
- }).execute(context);
56
- console.log(`[coverage] Full text report saved to ${path.join(config.coverageReportDir, TEXT_REPORT_FILENAME)}`);
57
- enforceThresholds(coverageMap.getCoverageSummary(), config.thresholds, "global");
58
- const targets = Array.isArray(config.thresholdTargets) ? config.thresholdTargets : [];
59
- if (targets.length > 0) {
60
- const fileSummaries = buildFileSummaries(coverageMap, config.rootDir);
61
- for (const target of targets) {
62
- const matchResult = collectTargetSummary(fileSummaries, createGlobMatcher(target.pattern), coverageLib);
63
- if (matchResult.matched === 0) {
64
- console.warn(`[coverage] threshold pattern "${target.pattern}" did not match any files — skipping`);
65
- continue;
66
- }
67
- enforceThresholds(matchResult.summary, target.thresholds, target.pattern);
68
- }
69
- }
20
+ const coverageFiles = await findCoverageFiles(config);
21
+ if (coverageFiles.length === 0) {
22
+ console.warn("[coverage] no V8 coverage artifacts were generated");
23
+ return;
24
+ }
25
+ const coverageLib = resolveCoverageLib();
26
+ const coverageMap = coverageLib.createCoverageMap({});
27
+ const matchesCollectCoverageFrom = createCollectCoverageMatcher(config.collectCoverageFrom, config.rootDir);
28
+ for (const file of coverageFiles) {
29
+ const payload = await readCoverageFile(file);
30
+ if (!payload) {
31
+ continue;
32
+ }
33
+ for (const script of payload.scripts) {
34
+ await mergeScriptCoverage(coverageMap, script, config, matchesCollectCoverageFrom);
35
+ }
36
+ }
37
+ if (config.includeAllFiles) {
38
+ await includeUntestedFiles(coverageMap, config, matchesCollectCoverageFrom);
39
+ }
40
+ if (coverageMap.files().length === 0) {
41
+ console.warn("[coverage] no library files matched the coverage filters");
42
+ return;
43
+ }
44
+ await fs.rm(config.coverageReportDir, {
45
+ recursive: true,
46
+ force: true
47
+ });
48
+ await fs.mkdir(config.coverageReportDir, {
49
+ recursive: true
50
+ });
51
+ const {
52
+ createContext,
53
+ reports
54
+ } = await loadIstanbulModules();
55
+ const context = createContext({
56
+ dir: config.coverageReportDir,
57
+ coverageMap,
58
+ defaultSummarizer: "pkg"
59
+ });
60
+ const {
61
+ output: reportOutput,
62
+ summarizer
63
+ } = generateConsoleTextCoverageReport(reports, context);
64
+ process.stdout.write(reportOutput);
65
+ reports.create("text", {
66
+ file: TEXT_REPORT_FILENAME,
67
+ summarizer
68
+ }).execute(context);
69
+ console.log(`[coverage] Full text report saved to ${path.join(config.coverageReportDir, TEXT_REPORT_FILENAME)}`);
70
+ const summary = coverageMap.getCoverageSummary();
71
+ enforceThresholds(summary, config.thresholds, "global");
72
+ const targets = Array.isArray(config.thresholdTargets) ? config.thresholdTargets : [];
73
+ if (targets.length > 0) {
74
+ const fileSummaries = buildFileSummaries(coverageMap, config.rootDir);
75
+ for (const target of targets) {
76
+ const matcher = createGlobMatcher(target.pattern);
77
+ const matchResult = collectTargetSummary(fileSummaries, matcher, coverageLib);
78
+ if (matchResult.matched === 0) {
79
+ console.warn(`[coverage] threshold pattern "${target.pattern}" did not match any files — skipping`);
80
+ continue;
81
+ }
82
+ enforceThresholds(matchResult.summary, target.thresholds, target.pattern);
83
+ }
84
+ }
70
85
  }
71
86
  async function collectCoveredFiles(config) {
72
- const coverageFiles = await findCoverageFiles(config);
73
- if (coverageFiles.length === 0) return [];
74
- const coverageMap = resolveCoverageLib().createCoverageMap({});
75
- const matchesCollectCoverageFrom = createCollectCoverageMatcher(config.collectCoverageFrom, config.rootDir);
76
- for (const file of coverageFiles) {
77
- const payload = await readCoverageFile(file);
78
- if (!payload) continue;
79
- for (const script of payload.scripts) await mergeScriptCoverage(coverageMap, script, config, matchesCollectCoverageFrom);
80
- }
81
- return coverageMap.files().sort();
87
+ const coverageFiles = await findCoverageFiles(config);
88
+ if (coverageFiles.length === 0) {
89
+ return [];
90
+ }
91
+ const coverageLib = resolveCoverageLib();
92
+ const coverageMap = coverageLib.createCoverageMap({});
93
+ const matchesCollectCoverageFrom = createCollectCoverageMatcher(config.collectCoverageFrom, config.rootDir);
94
+ for (const file of coverageFiles) {
95
+ const payload = await readCoverageFile(file);
96
+ if (!payload) {
97
+ continue;
98
+ }
99
+ for (const script of payload.scripts) {
100
+ await mergeScriptCoverage(coverageMap, script, config, matchesCollectCoverageFrom);
101
+ }
102
+ }
103
+ return coverageMap.files().sort();
82
104
  }
83
105
  async function loadIstanbulModules() {
84
- maybeForceColor();
85
- const [libReportMod, reportsMod] = await Promise.all([import("istanbul-lib-report"), import("istanbul-reports")]);
86
- const createContext = typeof libReportMod.createContext === "function" ? libReportMod.createContext : libReportMod.default?.createContext;
87
- if (typeof createContext !== "function") throw new Error("istanbul-lib-report exports are unavailable");
88
- return {
89
- createContext,
90
- reports: reportsMod.default ?? reportsMod
91
- };
106
+ maybeForceColor();
107
+ const [libReportMod, reportsMod] = await Promise.all([import("istanbul-lib-report"), import("istanbul-reports")]);
108
+ const createContext = typeof libReportMod.createContext === "function" ? libReportMod.createContext : libReportMod.default?.createContext;
109
+ if (typeof createContext !== "function") {
110
+ throw new Error("istanbul-lib-report exports are unavailable");
111
+ }
112
+ return {
113
+ createContext,
114
+ reports: reportsMod.default ?? reportsMod
115
+ };
92
116
  }
93
117
  function maybeForceColor() {
94
- if (process.stdout.isTTY) return;
95
- if (process.env.FORCE_COLOR !== void 0) return;
96
- if (process.env.NO_COLOR !== void 0 || process.env.NODE_DISABLE_COLORS !== void 0) return;
97
- if (process.env.CI !== void 0) return;
98
- process.env.FORCE_COLOR = "1";
118
+ if (process.stdout.isTTY) {
119
+ return;
120
+ }
121
+ if (process.env.FORCE_COLOR !== void 0) {
122
+ return;
123
+ }
124
+ if (process.env.NO_COLOR !== void 0 || process.env.NODE_DISABLE_COLORS !== void 0) {
125
+ return;
126
+ }
127
+ if (process.env.CI !== void 0) {
128
+ return;
129
+ }
130
+ process.env.FORCE_COLOR = "1";
99
131
  }
100
132
  async function mergeScriptCoverage(coverageMap, script, config, matchesCollectCoverageFrom) {
101
- const scriptPath = script.absolutePath;
102
- if (!scriptPath) return;
103
- if (isNodeModulesPath(scriptPath)) return;
104
- if (isViteVirtualModulePath(scriptPath)) return;
105
- let source = script.source && script.source.length > 0 ? script.source : "";
106
- if (!source) try {
107
- source = await fsPromises.readFile(scriptPath, "utf8");
108
- } catch (error) {
109
- const base = path.basename(scriptPath);
110
- if (error?.code === "ENOENT" && base && !base.includes(".")) return;
111
- if (error?.code === "ENOENT" && !matchesCollectCoverageFrom(scriptPath)) return;
112
- throw error;
113
- }
114
- const sourceMap = await loadSourceMapForScript(scriptPath, source);
115
- const converter = v8ToIstanbul(scriptPath, 0, sourceMap ? {
116
- source,
117
- sourceMap: { sourcemap: sourceMap }
118
- } : { source });
119
- await converter.load();
120
- converter.applyCoverage(script.functions);
121
- const filtered = filterCoverageMap(converter.toIstanbul(), config, matchesCollectCoverageFrom);
122
- if (Object.keys(filtered).length > 0) coverageMap.merge(filtered);
133
+ const scriptPath = script.absolutePath;
134
+ if (!scriptPath) {
135
+ return;
136
+ }
137
+ if (isNodeModulesPath(scriptPath)) {
138
+ return;
139
+ }
140
+ if (isViteVirtualModulePath(scriptPath)) {
141
+ return;
142
+ }
143
+ let source = script.source && script.source.length > 0 ? script.source : "";
144
+ if (!source) {
145
+ try {
146
+ source = await fs.readFile(scriptPath, "utf8");
147
+ } catch (error) {
148
+ const base = path.basename(scriptPath);
149
+ if (error?.code === "ENOENT" && base && !base.includes(".")) {
150
+ return;
151
+ }
152
+ if (error?.code === "ENOENT" && !matchesCollectCoverageFrom(scriptPath)) {
153
+ return;
154
+ }
155
+ throw error;
156
+ }
157
+ }
158
+ const sourceMap = await loadSourceMapForScript(scriptPath, source);
159
+ const converter = v8ToIstanbul(scriptPath, 0, sourceMap ? {
160
+ source,
161
+ sourceMap: {
162
+ sourcemap: sourceMap
163
+ }
164
+ } : {
165
+ source
166
+ });
167
+ await converter.load();
168
+ converter.applyCoverage(script.functions);
169
+ const filtered = filterCoverageMap(converter.toIstanbul(), config, matchesCollectCoverageFrom);
170
+ if (Object.keys(filtered).length > 0) {
171
+ coverageMap.merge(filtered);
172
+ }
123
173
  }
124
174
  async function readCoverageFile(file) {
125
- try {
126
- const raw = await fsPromises.readFile(file, "utf8");
127
- return JSON.parse(raw);
128
- } catch (error) {
129
- console.warn(`[coverage] failed to parse ${file}:`, error);
130
- return null;
131
- }
175
+ try {
176
+ const raw = await fs.readFile(file, "utf8");
177
+ return JSON.parse(raw);
178
+ } catch (error) {
179
+ console.warn(`[coverage] failed to parse ${file}:`, error);
180
+ return null;
181
+ }
132
182
  }
133
183
  function enforceThresholds(summary, thresholds, label = "global") {
134
- const failures = [];
135
- for (const metric of Object.keys(thresholds)) {
136
- const minimum = thresholds[metric];
137
- const actual = summary[metric]?.pct ?? 0;
138
- if (actual < minimum) failures.push({
139
- metric,
140
- actual,
141
- minimum
142
- });
143
- }
144
- if (failures.length === 0) return;
145
- throw new CoverageThresholdError(`[coverage] thresholds not met (target: ${label}) — ${failures.map(({ metric, actual, minimum }) => `${metric}: ${actual.toFixed(2)}% < ${minimum}%`).join("; ")}`);
184
+ const failures = [];
185
+ for (const metric of Object.keys(thresholds)) {
186
+ const minimum = thresholds[metric];
187
+ const actual = summary[metric]?.pct ?? 0;
188
+ if (actual < minimum) {
189
+ failures.push({
190
+ metric,
191
+ actual,
192
+ minimum
193
+ });
194
+ }
195
+ }
196
+ if (failures.length === 0) {
197
+ return;
198
+ }
199
+ const details = failures.map(({
200
+ metric,
201
+ actual,
202
+ minimum
203
+ }) => `${metric}: ${actual.toFixed(2)}% < ${minimum}%`).join("; ");
204
+ throw new CoverageThresholdError(`[coverage] thresholds not met (target: ${label}) — ${details}`);
146
205
  }
147
206
  function resolveCoverageLib() {
148
- const candidate = libCoverage;
149
- if (typeof candidate.createCoverageMap === "function") return candidate;
150
- if (candidate.default && typeof candidate.default.createCoverageMap === "function") return candidate.default;
151
- throw new Error("istanbul-lib-coverage exports are unavailable");
207
+ const candidate = libCoverage;
208
+ if (typeof candidate.createCoverageMap === "function") {
209
+ return candidate;
210
+ }
211
+ if (candidate.default && typeof candidate.default.createCoverageMap === "function") {
212
+ return candidate.default;
213
+ }
214
+ throw new Error("istanbul-lib-coverage exports are unavailable");
152
215
  }
153
216
  function resolveInstrumentLib() {
154
- const candidate = libInstrument;
155
- if (typeof candidate.createInstrumenter === "function") return candidate;
156
- if (candidate.default && typeof candidate.default.createInstrumenter === "function") return candidate.default;
157
- throw new Error("istanbul-lib-instrument exports are unavailable");
217
+ const candidate = libInstrument;
218
+ if (typeof candidate.createInstrumenter === "function") {
219
+ return candidate;
220
+ }
221
+ if (candidate.default && typeof candidate.default.createInstrumenter === "function") {
222
+ return candidate.default;
223
+ }
224
+ throw new Error("istanbul-lib-instrument exports are unavailable");
158
225
  }
159
226
  async function includeUntestedFiles(coverageMap, config, matchesCollectCoverageFrom) {
160
- const existing = new Set(coverageMap.files().map((filePath) => path.resolve(String(filePath ?? ""))));
161
- const candidates = await findCollectCoverageFiles(config, matchesCollectCoverageFrom);
162
- if (candidates.length === 0) return;
163
- const instrumenter = resolveInstrumentLib().createInstrumenter({
164
- esModules: true,
165
- parserPlugins: [
166
- "typescript",
167
- "jsx",
168
- "classProperties",
169
- "classPrivateProperties",
170
- "classPrivateMethods",
171
- "decorators-legacy",
172
- "importMeta",
173
- "topLevelAwait"
174
- ]
175
- });
176
- for (const filePath of candidates) {
177
- const normalized = path.resolve(filePath);
178
- if (existing.has(normalized)) continue;
179
- const source = await fsPromises.readFile(normalized, "utf8").catch(() => null);
180
- if (source === null) continue;
181
- try {
182
- instrumenter.instrumentSync(source, normalized);
183
- const fileCoverage = instrumenter.lastFileCoverage();
184
- if (!fileCoverage) continue;
185
- coverageMap.addFileCoverage(fileCoverage);
186
- existing.add(normalized);
187
- } catch (error) {
188
- const relative = path.relative(config.rootDir, normalized);
189
- console.warn(`[coverage] failed to instrument ${relative && !relative.startsWith("..") ? relative : normalized}:`, error);
190
- }
191
- }
227
+ const existing = new Set(coverageMap.files().map((filePath) => path.resolve(String(filePath ?? ""))));
228
+ const candidates = await findCollectCoverageFiles(config, matchesCollectCoverageFrom);
229
+ if (candidates.length === 0) {
230
+ return;
231
+ }
232
+ const instrumentLib = resolveInstrumentLib();
233
+ const instrumenter = instrumentLib.createInstrumenter({
234
+ esModules: true,
235
+ parserPlugins: ["typescript", "jsx", "classProperties", "classPrivateProperties", "classPrivateMethods", "decorators-legacy", "importMeta", "topLevelAwait"]
236
+ });
237
+ for (const filePath of candidates) {
238
+ const normalized = path.resolve(filePath);
239
+ if (existing.has(normalized)) {
240
+ continue;
241
+ }
242
+ const source = await fs.readFile(normalized, "utf8").catch(() => null);
243
+ if (source === null) {
244
+ continue;
245
+ }
246
+ try {
247
+ instrumenter.instrumentSync(source, normalized);
248
+ const fileCoverage = instrumenter.lastFileCoverage();
249
+ if (!fileCoverage) {
250
+ continue;
251
+ }
252
+ coverageMap.addFileCoverage(fileCoverage);
253
+ existing.add(normalized);
254
+ } catch (error) {
255
+ const relative = path.relative(config.rootDir, normalized);
256
+ console.warn(`[coverage] failed to instrument ${relative && !relative.startsWith("..") ? relative : normalized}:`, error);
257
+ }
258
+ }
192
259
  }
193
- var DEFAULT_COLLECT_COVERAGE_IGNORES = [
194
- "**/.git/**",
195
- "**/.next/**",
196
- "**/.turbo/**",
197
- "**/.vite/**",
198
- "**/.vitest/**",
199
- "**/build/**",
200
- "**/coverage/**",
201
- "**/dist/**",
202
- "**/node_modules/**",
203
- "**/playwright-report/**",
204
- "**/spec/**",
205
- "**/test/**",
206
- "**/test-results/**",
207
- "**/tests/**",
208
- "**/__tests__/**",
209
- "**/*.d.ts",
210
- "**/*.map"
211
- ];
260
+ const DEFAULT_COLLECT_COVERAGE_IGNORES = ["**/.git/**", "**/.next/**", "**/.turbo/**", "**/.vite/**", "**/.vitest/**", "**/build/**", "**/coverage/**", "**/dist/**", "**/node_modules/**", "**/playwright-report/**", "**/spec/**", "**/test/**", "**/test-results/**", "**/tests/**", "**/__tests__/**", "**/*.d.ts", "**/*.map"];
212
261
  async function findCollectCoverageFiles(config, matchesCollectCoverageFrom) {
213
- const patterns = Array.isArray(config.collectCoverageFrom) ? config.collectCoverageFrom : [];
214
- if (patterns.length === 0) return [];
215
- const rawFiles = await fg(patterns, {
216
- cwd: config.rootDir,
217
- absolute: true,
218
- dot: true,
219
- onlyFiles: true,
220
- unique: true,
221
- followSymbolicLinks: false,
222
- ignore: DEFAULT_COLLECT_COVERAGE_IGNORES
223
- }).catch(() => []);
224
- const collected = /* @__PURE__ */ new Set();
225
- for (const file of rawFiles) {
226
- const normalized = path.resolve(String(file ?? ""));
227
- if (!normalized) continue;
228
- if (normalized.endsWith(".d.ts") || normalized.endsWith(".map")) continue;
229
- if (isNodeModulesPath(normalized)) continue;
230
- if (isViteVirtualModulePath(normalized)) continue;
231
- if (!matchesCollectCoverageFrom(normalized)) continue;
232
- collected.add(normalized);
233
- }
234
- return Array.from(collected).sort();
262
+ const patterns = Array.isArray(config.collectCoverageFrom) ? config.collectCoverageFrom : [];
263
+ if (patterns.length === 0) {
264
+ return [];
265
+ }
266
+ const rawFiles = await fg(patterns, {
267
+ cwd: config.rootDir,
268
+ absolute: true,
269
+ dot: true,
270
+ onlyFiles: true,
271
+ unique: true,
272
+ followSymbolicLinks: false,
273
+ ignore: DEFAULT_COLLECT_COVERAGE_IGNORES
274
+ }).catch(() => []);
275
+ const collected = /* @__PURE__ */ new Set();
276
+ for (const file of rawFiles) {
277
+ const normalized = path.resolve(String(file ?? ""));
278
+ if (!normalized) {
279
+ continue;
280
+ }
281
+ if (normalized.endsWith(".d.ts") || normalized.endsWith(".map")) {
282
+ continue;
283
+ }
284
+ if (isNodeModulesPath(normalized)) {
285
+ continue;
286
+ }
287
+ if (isViteVirtualModulePath(normalized)) {
288
+ continue;
289
+ }
290
+ if (!matchesCollectCoverageFrom(normalized)) {
291
+ continue;
292
+ }
293
+ collected.add(normalized);
294
+ }
295
+ return Array.from(collected).sort();
235
296
  }
236
297
  function buildFileSummaries(coverageMap, rootDir) {
237
- const normalizedRoot = path.resolve(rootDir);
238
- return coverageMap.files().map((filePath) => {
239
- const normalizedAbsolute = path.resolve(filePath);
240
- const summary = coverageMap.fileCoverageFor(filePath).toSummary();
241
- const relativePath = path.relative(normalizedRoot, normalizedAbsolute);
242
- const candidates = /* @__PURE__ */ new Set();
243
- if (relativePath) {
244
- const relativePosix = toPosix(relativePath);
245
- candidates.add(relativePosix);
246
- candidates.add(`./${relativePosix}`);
247
- } else candidates.add(toPosix(path.basename(normalizedAbsolute)));
248
- return {
249
- summary,
250
- candidates: Array.from(candidates)
251
- };
252
- });
298
+ const normalizedRoot = path.resolve(rootDir);
299
+ return coverageMap.files().map((filePath) => {
300
+ const normalizedAbsolute = path.resolve(filePath);
301
+ const summary = coverageMap.fileCoverageFor(filePath).toSummary();
302
+ const relativePath = path.relative(normalizedRoot, normalizedAbsolute);
303
+ const candidates = /* @__PURE__ */ new Set();
304
+ if (relativePath) {
305
+ const relativePosix = toPosix(relativePath);
306
+ candidates.add(relativePosix);
307
+ candidates.add(`./${relativePosix}`);
308
+ } else {
309
+ candidates.add(toPosix(path.basename(normalizedAbsolute)));
310
+ }
311
+ return {
312
+ summary,
313
+ candidates: Array.from(candidates)
314
+ };
315
+ });
253
316
  }
254
317
  function collectTargetSummary(fileSummaries, matcher, coverageLib) {
255
- const summary = coverageLib.createCoverageSummary();
256
- let matched = 0;
257
- for (const file of fileSummaries) if (file.candidates.some((candidate) => matcher(candidate))) {
258
- summary.merge(file.summary);
259
- matched += 1;
260
- }
261
- return {
262
- summary,
263
- matched
264
- };
318
+ const summary = coverageLib.createCoverageSummary();
319
+ let matched = 0;
320
+ for (const file of fileSummaries) {
321
+ if (file.candidates.some((candidate) => matcher(candidate))) {
322
+ summary.merge(file.summary);
323
+ matched += 1;
324
+ }
325
+ }
326
+ return {
327
+ summary,
328
+ matched
329
+ };
265
330
  }
266
331
  function createGlobMatcher(pattern) {
267
- const normalized = toPosix(String(pattern ?? "")).trim();
268
- if (!normalized) return () => false;
269
- if (isAbsoluteGlobPattern(normalized)) throw new Error(`[coverage] threshold patterns must be relative (absolute paths are not supported): "${pattern}"`);
270
- return picomatch(normalized, { dot: true });
332
+ const normalized = toPosix(String(pattern ?? "")).trim();
333
+ if (!normalized) {
334
+ return () => false;
335
+ }
336
+ if (isAbsoluteGlobPattern(normalized)) {
337
+ throw new Error(`[coverage] threshold patterns must be relative (absolute paths are not supported): "${pattern}"`);
338
+ }
339
+ return picomatch(normalized, {
340
+ dot: true
341
+ });
271
342
  }
272
343
  function isAbsoluteGlobPattern(pattern) {
273
- const normalized = String(pattern ?? "").trim();
274
- if (!normalized) return false;
275
- if (normalized.startsWith("/")) return true;
276
- if (normalized.startsWith("file://")) return true;
277
- return /^[A-Za-z]:\//.test(normalized);
344
+ const normalized = String(pattern ?? "").trim();
345
+ if (!normalized) {
346
+ return false;
347
+ }
348
+ if (normalized.startsWith("/")) {
349
+ return true;
350
+ }
351
+ if (normalized.startsWith("file://")) {
352
+ return true;
353
+ }
354
+ return /^[A-Za-z]:\//.test(normalized);
278
355
  }
279
356
  function stripQuery(url) {
280
- const queryIndex = url.indexOf("?");
281
- const hashIndex = url.indexOf("#");
282
- const endIndex = Math.min(queryIndex === -1 ? Number.POSITIVE_INFINITY : queryIndex, hashIndex === -1 ? Number.POSITIVE_INFINITY : hashIndex);
283
- if (!Number.isFinite(endIndex)) return url;
284
- return url.slice(0, endIndex);
357
+ const queryIndex = url.indexOf("?");
358
+ const hashIndex = url.indexOf("#");
359
+ const endIndex = Math.min(queryIndex === -1 ? Number.POSITIVE_INFINITY : queryIndex, hashIndex === -1 ? Number.POSITIVE_INFINITY : hashIndex);
360
+ if (!Number.isFinite(endIndex)) {
361
+ return url;
362
+ }
363
+ return url.slice(0, endIndex);
285
364
  }
286
365
  function extractSourceMappingUrl(source) {
287
- const regex = /\/\/[#@]\s*sourceMappingURL=([^\s]+)/g;
288
- let last = null;
289
- let match = null;
290
- while ((match = regex.exec(source)) !== null) last = match[1];
291
- return typeof last === "string" && last.length > 0 ? last : null;
366
+ const regex = /\/\/[#@]\s*sourceMappingURL=([^\s]+)/g;
367
+ let last = null;
368
+ let match = null;
369
+ while ((match = regex.exec(source)) !== null) {
370
+ last = match[1];
371
+ }
372
+ return typeof last === "string" && last.length > 0 ? last : null;
292
373
  }
293
374
  function resolveSourceMapPath(scriptPath, mappingUrl) {
294
- const cleaned = stripQuery(mappingUrl);
295
- if (cleaned.startsWith("file://")) return fileURLToPath(cleaned);
296
- if (path.isAbsolute(cleaned)) return cleaned;
297
- return path.resolve(path.dirname(scriptPath), cleaned);
375
+ const cleaned = stripQuery(mappingUrl);
376
+ if (cleaned.startsWith("file://")) {
377
+ return fileURLToPath(cleaned);
378
+ }
379
+ if (path.isAbsolute(cleaned)) {
380
+ return cleaned;
381
+ }
382
+ return path.resolve(path.dirname(scriptPath), cleaned);
298
383
  }
299
384
  function filterCoverageMap(map, config, matchesCollectCoverageFrom) {
300
- if (!map || typeof map !== "object") return {};
301
- const filtered = {};
302
- for (const [filePath, fileCoverage] of Object.entries(map)) {
303
- const absolutePath = resolveCoveragePath(filePath, config.rootDir);
304
- if (!absolutePath) continue;
305
- if (absolutePath.endsWith(".d.ts") || absolutePath.endsWith(".map")) continue;
306
- if (isNodeModulesPath(absolutePath)) continue;
307
- if (isViteVirtualModulePath(absolutePath)) continue;
308
- if (!matchesCollectCoverageFrom(absolutePath)) continue;
309
- if (fileCoverage && typeof fileCoverage === "object") filtered[absolutePath] = {
310
- ...fileCoverage,
311
- path: absolutePath
312
- };
313
- else filtered[absolutePath] = fileCoverage;
314
- }
315
- return filtered;
385
+ if (!map || typeof map !== "object") {
386
+ return {};
387
+ }
388
+ const filtered = {};
389
+ for (const [filePath, fileCoverage] of Object.entries(map)) {
390
+ const absolutePath = resolveCoveragePath(filePath, config.rootDir);
391
+ if (!absolutePath) {
392
+ continue;
393
+ }
394
+ if (absolutePath.endsWith(".d.ts") || absolutePath.endsWith(".map")) {
395
+ continue;
396
+ }
397
+ if (isNodeModulesPath(absolutePath)) {
398
+ continue;
399
+ }
400
+ if (isViteVirtualModulePath(absolutePath)) {
401
+ continue;
402
+ }
403
+ if (!matchesCollectCoverageFrom(absolutePath)) {
404
+ continue;
405
+ }
406
+ if (fileCoverage && typeof fileCoverage === "object") {
407
+ filtered[absolutePath] = {
408
+ ...fileCoverage,
409
+ path: absolutePath
410
+ };
411
+ } else {
412
+ filtered[absolutePath] = fileCoverage;
413
+ }
414
+ }
415
+ return filtered;
316
416
  }
317
417
  function resolveCoveragePath(filePath, rootDir) {
318
- const raw = String(filePath ?? "").trim();
319
- if (!raw) return null;
320
- const cleaned = stripQuery(raw);
321
- if (cleaned.startsWith("file://")) try {
322
- return path.normalize(fileURLToPath(cleaned));
323
- } catch {
324
- return null;
325
- }
326
- if (path.isAbsolute(cleaned)) return path.normalize(cleaned);
327
- if (cleaned.includes("://")) return null;
328
- return path.normalize(path.resolve(rootDir, cleaned));
418
+ const raw = String(filePath ?? "").trim();
419
+ if (!raw) {
420
+ return null;
421
+ }
422
+ const cleaned = stripQuery(raw);
423
+ if (cleaned.startsWith("file://")) {
424
+ try {
425
+ return path.normalize(fileURLToPath(cleaned));
426
+ } catch {
427
+ return null;
428
+ }
429
+ }
430
+ if (path.isAbsolute(cleaned)) {
431
+ return path.normalize(cleaned);
432
+ }
433
+ if (cleaned.includes("://")) {
434
+ return null;
435
+ }
436
+ return path.normalize(path.resolve(rootDir, cleaned));
329
437
  }
330
438
  function isNodeModulesPath(filePath) {
331
- return path.normalize(String(filePath ?? "")).split(path.sep).includes("node_modules");
439
+ return path.normalize(String(filePath ?? "")).split(path.sep).includes("node_modules");
332
440
  }
333
441
  function isViteVirtualModulePath(filePath) {
334
- const normalized = path.normalize(String(filePath ?? ""));
335
- const baseName = path.basename(normalized);
336
- return baseName === "__vite-browser-external" || baseName.startsWith("__vite-browser-external:") || baseName.startsWith("__vite-");
442
+ const normalized = path.normalize(String(filePath ?? ""));
443
+ const baseName = path.basename(normalized);
444
+ return baseName === "__vite-browser-external" || baseName.startsWith("__vite-browser-external:") || baseName.startsWith("__vite-");
337
445
  }
338
446
  function parseSourceMapPayload(raw) {
339
- if (!raw || typeof raw !== "object") return null;
340
- const sources = raw.sources;
341
- if (!Array.isArray(sources) || sources.length === 0) return null;
342
- return raw;
447
+ if (!raw || typeof raw !== "object") {
448
+ return null;
449
+ }
450
+ const sources = raw.sources;
451
+ if (!Array.isArray(sources) || sources.length === 0) {
452
+ return null;
453
+ }
454
+ return raw;
343
455
  }
344
456
  function normalizeSourceMap(sourceMap, scriptPath) {
345
- const root = typeof sourceMap.sourceRoot === "string" ? sourceMap.sourceRoot.replace("file://", "") : "";
346
- const dir = path.dirname(scriptPath);
347
- const fixedSources = sourceMap.sources.map((source) => {
348
- const cleaned = stripQuery(String(source ?? ""));
349
- if (cleaned.startsWith("file://")) try {
350
- return path.normalize(fileURLToPath(cleaned));
351
- } catch {
352
- return cleaned;
353
- }
354
- const withoutWebpack = cleaned.replace(/^webpack:\/\//, "");
355
- const candidate = path.join(root, withoutWebpack);
356
- if (path.isAbsolute(candidate)) return path.normalize(candidate);
357
- const normalizedCandidate = candidate.split("/").join(path.sep);
358
- if (dir.endsWith(`${path.sep}dist`) && !normalizedCandidate.startsWith(`..${path.sep}`)) {
359
- if (normalizedCandidate.startsWith(`src${path.sep}`) || normalizedCandidate.startsWith(`lib${path.sep}`)) return path.normalize(path.resolve(dir, "..", normalizedCandidate));
360
- }
361
- return path.normalize(path.resolve(dir, normalizedCandidate));
362
- });
363
- return {
364
- ...sourceMap,
365
- sources: fixedSources
366
- };
457
+ const root = typeof sourceMap.sourceRoot === "string" ? sourceMap.sourceRoot.replace("file://", "") : "";
458
+ const dir = path.dirname(scriptPath);
459
+ const fixedSources = sourceMap.sources.map((source) => {
460
+ const raw = String(source ?? "");
461
+ const cleaned = stripQuery(raw);
462
+ if (cleaned.startsWith("file://")) {
463
+ try {
464
+ return path.normalize(fileURLToPath(cleaned));
465
+ } catch {
466
+ return cleaned;
467
+ }
468
+ }
469
+ const withoutWebpack = cleaned.replace(/^webpack:\/\//, "");
470
+ const candidate = path.join(root, withoutWebpack);
471
+ if (path.isAbsolute(candidate)) {
472
+ return path.normalize(candidate);
473
+ }
474
+ const normalizedCandidate = candidate.split("/").join(path.sep);
475
+ if (dir.endsWith(`${path.sep}dist`) && !normalizedCandidate.startsWith(`..${path.sep}`)) {
476
+ if (normalizedCandidate.startsWith(`src${path.sep}`) || normalizedCandidate.startsWith(`lib${path.sep}`)) {
477
+ return path.normalize(path.resolve(dir, "..", normalizedCandidate));
478
+ }
479
+ }
480
+ return path.normalize(path.resolve(dir, normalizedCandidate));
481
+ });
482
+ return {
483
+ ...sourceMap,
484
+ sources: fixedSources
485
+ };
367
486
  }
368
487
  async function loadSourceMapForScript(scriptPath, source) {
369
- const mappingUrl = extractSourceMappingUrl(source);
370
- if (!mappingUrl) return null;
371
- const cleaned = stripQuery(mappingUrl);
372
- if (cleaned.startsWith("data:")) {
373
- const commaIndex = cleaned.indexOf(",");
374
- if (commaIndex === -1) return null;
375
- const meta = cleaned.slice(0, commaIndex);
376
- const payload = cleaned.slice(commaIndex + 1);
377
- const raw = meta.includes(";base64") ? Buffer.from(payload, "base64").toString("utf8") : decodeURIComponent(payload);
378
- try {
379
- const parsed = parseSourceMapPayload(JSON.parse(raw));
380
- return parsed ? normalizeSourceMap(parsed, scriptPath) : null;
381
- } catch {
382
- return null;
383
- }
384
- }
385
- try {
386
- const mapPath = resolveSourceMapPath(scriptPath, cleaned);
387
- const raw = await fsPromises.readFile(mapPath, "utf8");
388
- const parsed = parseSourceMapPayload(JSON.parse(raw));
389
- return parsed ? normalizeSourceMap(parsed, scriptPath) : null;
390
- } catch {
391
- return null;
392
- }
488
+ const mappingUrl = extractSourceMappingUrl(source);
489
+ if (!mappingUrl) {
490
+ return null;
491
+ }
492
+ const cleaned = stripQuery(mappingUrl);
493
+ if (cleaned.startsWith("data:")) {
494
+ const commaIndex = cleaned.indexOf(",");
495
+ if (commaIndex === -1) {
496
+ return null;
497
+ }
498
+ const meta = cleaned.slice(0, commaIndex);
499
+ const payload = cleaned.slice(commaIndex + 1);
500
+ const raw = meta.includes(";base64") ? Buffer.from(payload, "base64").toString("utf8") : decodeURIComponent(payload);
501
+ try {
502
+ const parsed = parseSourceMapPayload(JSON.parse(raw));
503
+ return parsed ? normalizeSourceMap(parsed, scriptPath) : null;
504
+ } catch {
505
+ return null;
506
+ }
507
+ }
508
+ try {
509
+ const mapPath = resolveSourceMapPath(scriptPath, cleaned);
510
+ const raw = await fs.readFile(mapPath, "utf8");
511
+ const parsed = parseSourceMapPayload(JSON.parse(raw));
512
+ return parsed ? normalizeSourceMap(parsed, scriptPath) : null;
513
+ } catch {
514
+ return null;
515
+ }
393
516
  }
394
- //#endregion
395
- export { CoverageThresholdError, collectCoveredFiles, generateCoverageReport };
396
-
397
- //# sourceMappingURL=report.js.map
517
+ export {
518
+ CoverageThresholdError,
519
+ collectCoveredFiles,
520
+ generateCoverageReport
521
+ };
522
+ //# sourceMappingURL=report.js.map