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