@rpcbase/test 0.319.0 → 0.320.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/README.md CHANGED
@@ -8,7 +8,6 @@ Create `spec/coverage.config.ts` (or `.js` / `.json`) in your package:
8
8
 
9
9
  ```ts
10
10
  export default {
11
- testResultsDir: "test-results",
12
11
  thresholds: {
13
12
  statements: 75,
14
13
  lines: 75,
@@ -19,6 +18,7 @@ export default {
19
18
  ```
20
19
 
21
20
  Only `RB_DISABLE_COVERAGE=1` skips the hooks; every other option lives inside this config file.
21
+ Coverage artifacts are written to `build/playwright/coverage/` and `build/vitest/coverage/`, with the report in `build/coverage/report/`.
22
22
 
23
23
  ### Default file collection
24
24
 
package/dist/cli.js CHANGED
@@ -98,7 +98,9 @@ async function runVitest(coverage, combinedConfig, { disableCoverage = false } =
98
98
  env.RB_DISABLE_COVERAGE = "1";
99
99
  }
100
100
  if (coverage?.enabled && !disableCoverage) {
101
- env.NODE_V8_COVERAGE = resolveNodeCoverageDir(combinedConfig ?? coverage.config);
101
+ const nodeCoverageDir = resolveNodeCoverageDir(combinedConfig ?? coverage.config);
102
+ await fs.mkdir(nodeCoverageDir, { recursive: true });
103
+ env.NODE_V8_COVERAGE = nodeCoverageDir;
102
104
  }
103
105
  await spawnWithLogs({
104
106
  name: "Vitest",
@@ -576,8 +578,7 @@ function findVitestConfig(baseDir) {
576
578
  async function loadVitestCoverageConfig() {
577
579
  const options = await loadCoverageOptions({
578
580
  optional: true,
579
- candidates: VITEST_COVERAGE_CANDIDATES,
580
- defaultTestResultsDir: "test-results-vitest"
581
+ candidates: VITEST_COVERAGE_CANDIDATES
581
582
  });
582
583
  if (!options) {
583
584
  return null;
@@ -611,10 +612,10 @@ function resolveCombinedCoverage(playwrightCoverage, vitestCoverage) {
611
612
  async function cleanCoverageArtifacts(config) {
612
613
  await removeCoverageFiles(config);
613
614
  await fs.rm(config.coverageReportDir, { recursive: true, force: true });
614
- await fs.rm(path.join(config.testResultsRoot, "node-coverage"), { recursive: true, force: true });
615
+ await fs.rm(resolveNodeCoverageDir(config), { recursive: true, force: true });
615
616
  }
616
617
  function resolveNodeCoverageDir(config) {
617
- return path.join(config.testResultsRoot, "node-coverage", "vitest");
618
+ return path.join(config.rootDir, "build", "vitest", "test-results", "node-coverage");
618
619
  }
619
620
  async function convertNodeCoverage(coverage) {
620
621
  const { config, nodeCoverageDir } = coverage;
@@ -652,7 +653,7 @@ async function convertNodeCoverage(coverage) {
652
653
  if (scripts.length === 0) {
653
654
  return;
654
655
  }
655
- const outDir = path.join(config.testResultsRoot, "vitest");
656
+ const outDir = path.join(config.rootDir, "build", "vitest", "coverage");
656
657
  await fs.mkdir(outDir, { recursive: true });
657
658
  const outputFile = path.join(outDir, config.coverageFileName);
658
659
  await fs.writeFile(outputFile, JSON.stringify({ testId: "vitest", scripts }, null, 2), "utf8");
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sources":["../src/cli.ts"],"sourcesContent":["import { spawn, spawnSync } from \"node:child_process\"\nimport fs from \"node:fs\"\nimport fsPromises from \"node:fs/promises\"\nimport path from \"node:path\"\nimport { createRequire } from \"node:module\"\nimport { fileURLToPath } from \"node:url\"\n\nimport fg from \"fast-glob\"\n\nimport { createCoverageConfig } from \"./coverage/config\"\nimport { createCollectCoverageMatcher, isInsideAnyRoot, resolveCollectCoverageRoots } from \"./coverage/collect\"\nimport { loadCoverageOptions } from \"./coverage/config-loader\"\nimport { removeCoverageFiles } from \"./coverage/files\"\nimport { collectCoveredFiles, CoverageThresholdError, generateCoverageReport } from \"./coverage/report\"\nimport type { CoverageConfig } from \"./coverage/types\"\n\n\nconst require = createRequire(import.meta.url)\nconst moduleDir = path.dirname(fileURLToPath(import.meta.url))\n\nconst shouldForceTty =\n !process.stdout.isTTY\n && process.env.FORCE_COLOR === \"true\"\n\nif (shouldForceTty) {\n require(\"./register-tty.cjs\")\n}\n\n\nconst VITEST_COVERAGE_CANDIDATES = [\"src/coverage.json\"]\n\nconst COMBINED_COVERAGE_ENV_VAR = \"RB_TEST_COMBINED_COVERAGE\"\n\nconst isAider = process.env.IS_AIDER === \"yes\"\n\nif (process.env.IS_AIDER !== undefined && process.env.IS_AIDER !== \"yes\") {\n console.warn(\"Warning: IS_AIDER is set to a value other than 'yes'.\")\n}\n\ntype CoverageState = { config: CoverageConfig; enabled: boolean } | null\n\nasync function runTests(): Promise<void> {\n const userArgs = process.argv.slice(2)\n const buildSpecsMap = userArgs.includes(\"--build-specs-map\")\n const auto = userArgs.includes(\"--auto\")\n const showMapping = userArgs.includes(\"--show-mapping\")\n const filteredArgs = userArgs.filter((arg) => arg !== \"--build-specs-map\" && arg !== \"--auto\" && arg !== \"--show-mapping\")\n\n if (buildSpecsMap && auto) {\n throw new Error(\"[rb-test] --auto cannot be combined with --build-specs-map\")\n }\n\n if (showMapping && !auto) {\n throw new Error(\"[rb-test] --show-mapping requires --auto\")\n }\n\n const playwrightCoverage = await loadPlaywrightCoverageConfig()\n const vitestCoverage = await loadVitestCoverageConfig()\n const combinedCoverage = resolveCombinedCoverage(playwrightCoverage, vitestCoverage)\n\n if (buildSpecsMap) {\n await buildSpecsMapFromCoverage({\n userArgs: filteredArgs,\n playwrightCoverage,\n vitestCoverage,\n combinedCoverage,\n })\n return\n }\n\n const shouldGenerateCoverageReport = combinedCoverage?.enabled && !auto\n\n if (shouldGenerateCoverageReport) {\n await cleanCoverageArtifacts(combinedCoverage.config)\n }\n\n let testError = null\n\n try {\n await runVitest(vitestCoverage, combinedCoverage?.config ?? null, { disableCoverage: auto })\n console.log(\"\\nRunning Playwright Tests...\")\n const playwrightArgs = auto\n ? await resolveAutoPlaywrightArgs({\n userArgs: filteredArgs,\n playwrightCoverage,\n vitestCoverage,\n showMapping,\n })\n : userArgs\n if (playwrightArgs) {\n await runPlaywright(playwrightArgs, { disableCoverage: auto })\n }\n } catch (error: any) {\n testError = error\n }\n\n if (shouldGenerateCoverageReport) {\n if (testError) {\n console.warn(\"[coverage] skipping report generation because tests failed\")\n } else {\n try {\n await finalizeCoverage(combinedCoverage.config)\n } catch (error) {\n testError = error\n }\n }\n }\n\n if (testError) {\n throw testError\n }\n}\n\nrunTests()\n .then(() => process.exit(0))\n .catch((error) => {\n if (!(error instanceof CoverageThresholdError)) {\n console.error(error?.stack ?? String(error))\n }\n process.exit(1)\n })\n\nasync function runVitest(\n coverage: CoverageState,\n combinedConfig: CoverageConfig | null,\n { disableCoverage = false }: { disableCoverage?: boolean } = {},\n): Promise<void> {\n const vitestArgs = [\"run\", \"--passWithNoTests\"]\n const vitestConfig = resolveVitestConfig()\n\n if (vitestConfig) {\n vitestArgs.push(\"--config\", vitestConfig)\n }\n const launcher = resolveVitestLauncher()\n const env = withRegisterShim(process.env)\n\n if (disableCoverage) {\n env.RB_DISABLE_COVERAGE = \"1\"\n }\n\n if (coverage?.enabled && !disableCoverage) {\n env.NODE_V8_COVERAGE = resolveNodeCoverageDir(combinedConfig ?? coverage.config)\n }\n\n await spawnWithLogs({\n name: \"Vitest\",\n launcher,\n args: vitestArgs,\n env,\n successMessage: \"Vitest suite passed!\",\n failureMessage: \"Vitest failed\",\n })\n\n if (coverage?.enabled && !disableCoverage) {\n await convertNodeCoverage({\n config: combinedConfig ?? coverage.config,\n nodeCoverageDir: resolveNodeCoverageDir(combinedConfig ?? coverage.config),\n })\n }\n}\n\nasync function buildSpecsMapFromCoverage({\n userArgs,\n combinedCoverage,\n}: {\n userArgs: string[]\n combinedCoverage: CoverageState\n [key: string]: unknown\n}): Promise<void> {\n if (!combinedCoverage?.enabled) {\n throw new Error(\"[specs-map] Coverage must be enabled to build the specs map.\")\n }\n\n const config = combinedCoverage.config\n const workspaceRoot = findWorkspaceRoot(process.cwd())\n\n const specSourceFiles = await findSpecSourceFiles(config.rootDir)\n if (specSourceFiles.length === 0) {\n throw new Error(\"[specs-map] No spec files found under spec/**/*.spec.ts\")\n }\n\n const filesMapDir = path.join(config.testResultsRoot, \"files-map\")\n await fsPromises.rm(filesMapDir, { recursive: true, force: true })\n await fsPromises.mkdir(filesMapDir, { recursive: true })\n\n for (const specSourceFile of specSourceFiles) {\n const specProjectPath = path.relative(config.rootDir, specSourceFile)\n const specWorkspacePath = toPosixPath(path.relative(workspaceRoot, specSourceFile))\n const testFile = resolvePlaywrightSpecFile(specProjectPath)\n\n console.log(`\\n[specs-map] Running ${specWorkspacePath}`)\n\n await removeCoverageFiles(config)\n\n let error = null\n let failed = false\n try {\n await runPlaywright([...userArgs, testFile])\n } catch (runError: any) {\n error = runError\n failed = true\n console.error(`[specs-map] Failed: ${specWorkspacePath}`)\n console.error(runError?.stack ?? String(runError))\n }\n\n const coveredFiles = await collectCoveredFiles(config)\n const impactedFiles = coveredFiles\n .map((filePath) => toPosixPath(path.relative(workspaceRoot, filePath)))\n .filter((relativePath) => relativePath && !relativePath.startsWith(\"../\") && relativePath !== \"..\")\n .sort()\n\n const outputFile = path.join(filesMapDir, `${specProjectPath}.json`)\n await fsPromises.mkdir(path.dirname(outputFile), { recursive: true })\n await fsPromises.writeFile(\n outputFile,\n JSON.stringify(\n {\n spec: specWorkspacePath,\n files: impactedFiles,\n failed,\n },\n null,\n 2,\n ),\n \"utf8\",\n )\n\n if (failed) {\n throw error\n }\n }\n}\n\ntype GitChange =\n | { kind: \"rename\"; oldPath: string; newPath: string }\n | { kind: \"path\"; path: string }\n\nasync function resolveAutoPlaywrightArgs({\n userArgs,\n playwrightCoverage,\n vitestCoverage,\n showMapping = false,\n}: {\n userArgs: string[]\n playwrightCoverage: CoverageState\n vitestCoverage: CoverageState\n showMapping?: boolean\n [key: string]: unknown\n}): Promise<string[] | null> {\n const config = playwrightCoverage?.config ?? vitestCoverage?.config ?? null\n if (!config) {\n console.warn(\"[auto] Coverage config not found; running full Playwright suite.\")\n return userArgs\n }\n\n const filesMapDir = path.join(config.testResultsRoot, \"files-map\")\n const mapFiles = await findFilesMapJson(filesMapDir)\n if (mapFiles.length === 0) {\n console.warn(\"[auto] Specs map not found; running full Playwright suite.\")\n return userArgs\n }\n\n const workspaceRoot = findWorkspaceRoot(process.cwd())\n const gitChanges = getGitChanges(workspaceRoot)\n const renameMap = new Map<string, string>(\n gitChanges\n .filter((change): change is { kind: \"rename\"; oldPath: string; newPath: string } => change.kind === \"rename\")\n .map((change) => [change.oldPath, change.newPath]),\n )\n\n const specRootAbs = path.join(config.rootDir, \"spec\")\n const matchesCollectCoverageFrom = createCollectCoverageMatcher(config.collectCoverageFrom, config.rootDir)\n\n const directSpecChanges = new Set<string>()\n const sourceChanges: GitChange[] = []\n\n for (const change of gitChanges) {\n if (change.kind === \"rename\") {\n const oldAbs = path.join(workspaceRoot, change.oldPath)\n const newAbs = path.join(workspaceRoot, change.newPath)\n\n if (isSpecSourceFile(newAbs, specRootAbs) && fs.existsSync(newAbs)) {\n directSpecChanges.add(change.newPath)\n }\n\n const oldMatches = matchesCollectCoverageFrom(oldAbs)\n const newMatches = matchesCollectCoverageFrom(newAbs)\n if (oldMatches || newMatches) {\n sourceChanges.push(change)\n }\n continue\n }\n\n const abs = path.join(workspaceRoot, change.path)\n\n if (isSpecSourceFile(abs, specRootAbs) && fs.existsSync(abs)) {\n directSpecChanges.add(change.path)\n }\n\n if (matchesCollectCoverageFrom(abs)) {\n sourceChanges.push(change)\n }\n }\n\n if (directSpecChanges.size === 0 && sourceChanges.length === 0) {\n console.log(\"[auto] No relevant git changes.\")\n return null\n }\n\n const parsedMaps: Array<{ spec: string; files: string[] }> = []\n for (const file of mapFiles) {\n const json = await readJson(file)\n if (!json) {\n continue\n }\n\n if (json.failed === true) {\n console.warn(\"[auto] Specs map contains failed entries; running full Playwright suite.\")\n return userArgs\n }\n\n const spec = typeof json?.spec === \"string\" ? json.spec : null\n if (!spec) {\n continue\n }\n\n const files = Array.isArray(json?.files)\n ? (json.files as unknown[]).filter((entry): entry is string => typeof entry === \"string\")\n : []\n parsedMaps.push({ spec, files })\n }\n\n if (parsedMaps.length === 0) {\n console.warn(\"[auto] Specs map is empty; running full Playwright suite.\")\n return userArgs\n }\n\n const specsByImpactedFile = new Map<string, string[]>()\n\n for (const entry of parsedMaps) {\n const resolvedSpec = resolveRenamedPath(entry.spec, renameMap)\n for (const file of entry.files) {\n const list = specsByImpactedFile.get(file) ?? []\n list.push(resolvedSpec)\n specsByImpactedFile.set(file, list)\n }\n }\n\n const unmappedSourceChanges = sourceChanges.filter((change) => {\n if (change.kind === \"path\") {\n return !specsByImpactedFile.has(change.path)\n }\n return !specsByImpactedFile.has(change.oldPath) && !specsByImpactedFile.has(change.newPath)\n })\n\n if (unmappedSourceChanges.length > 0) {\n console.warn(\"[auto] Unmapped source changes detected:\")\n for (const change of unmappedSourceChanges) {\n if (change.kind === \"path\") {\n console.warn(` - ${change.path}`)\n } else {\n console.warn(` - ${change.oldPath} -> ${change.newPath}`)\n }\n }\n }\n\n const selectedSpecs = new Set<string>(directSpecChanges)\n const triggersBySpec = new Map<string, Set<string>>()\n\n for (const spec of directSpecChanges) {\n if (showMapping) {\n triggersBySpec.set(spec, new Set([spec]))\n }\n }\n\n for (const change of sourceChanges) {\n if (change.kind === \"path\") {\n const specs = specsByImpactedFile.get(change.path) ?? []\n specs.forEach((spec) => selectedSpecs.add(spec))\n if (showMapping) {\n for (const spec of specs) {\n const current = triggersBySpec.get(spec) ?? new Set()\n current.add(change.path)\n triggersBySpec.set(spec, current)\n }\n }\n continue\n }\n\n const oldSpecs = specsByImpactedFile.get(change.oldPath) ?? []\n oldSpecs.forEach((spec) => selectedSpecs.add(spec))\n const newSpecs = specsByImpactedFile.get(change.newPath) ?? []\n newSpecs.forEach((spec) => selectedSpecs.add(spec))\n if (showMapping) {\n const key = `${change.oldPath} -> ${change.newPath}`\n const allSpecs = new Set([...oldSpecs, ...newSpecs])\n for (const spec of allSpecs) {\n const current = triggersBySpec.get(spec) ?? new Set()\n current.add(key)\n triggersBySpec.set(spec, current)\n }\n }\n }\n\n const missingSpecs: string[] = []\n const specsToRun = Array.from(selectedSpecs)\n .filter((spec) => {\n const abs = path.join(workspaceRoot, spec)\n if (fs.existsSync(abs)) {\n return true\n }\n missingSpecs.push(spec)\n return false\n })\n .sort()\n if (missingSpecs.length > 0) {\n console.warn(`[auto] Ignoring ${missingSpecs.length} missing spec file(s):`)\n for (const spec of missingSpecs.sort()) {\n console.warn(` - ${spec}`)\n }\n }\n\n if (specsToRun.length === 0) {\n console.log(\"[auto] No impacted specs.\")\n return null\n }\n\n if (showMapping) {\n console.log(\"[auto] Mapping:\")\n for (const spec of specsToRun) {\n const triggers = Array.from(triggersBySpec.get(spec) ?? []).sort()\n if (triggers.length === 0) {\n continue\n }\n console.log(` - ${spec}`)\n for (const trigger of triggers) {\n console.log(` <- ${trigger}`)\n }\n }\n }\n\n const playwrightFiles = specsToRun\n .map((specWorkspacePath) => path.join(workspaceRoot, specWorkspacePath))\n .filter((specAbs) => isSubpath(specAbs, config.rootDir))\n .map((specAbs) => {\n const specProjectPath = path.relative(config.rootDir, specAbs)\n return resolvePlaywrightSpecFile(specProjectPath)\n })\n\n const totalSpecFiles = (await findSpecSourceFiles(config.rootDir)).length\n console.log(`[auto] Running ${playwrightFiles.length}/${totalSpecFiles} spec file(s).`)\n return [...userArgs, ...playwrightFiles]\n}\n\nasync function findFilesMapJson(filesMapDir: string): Promise<string[]> {\n const patterns = [\"spec/**/*.spec.ts.json\", \"spec/**/*.spec.tsx.json\"]\n const matches = await fg(patterns, { cwd: filesMapDir, absolute: true, onlyFiles: true }).catch(() => [])\n return matches.sort()\n}\n\nfunction getGitChanges(workspaceRoot: string): GitChange[] {\n const result = spawnSync(\"git\", [\"status\", \"--porcelain=1\", \"-z\"], {\n cwd: workspaceRoot,\n encoding: \"utf8\",\n })\n\n if (result.status !== 0) {\n throw new Error(`[auto] Failed to read git status: ${result.stderr || \"unknown error\"}`)\n }\n\n const tokens = String(result.stdout ?? \"\").split(\"\\0\").filter(Boolean)\n const changes: GitChange[] = []\n\n for (let i = 0; i < tokens.length; i += 1) {\n const record = tokens[i]\n if (record.length < 4) {\n continue\n }\n\n const status = record.slice(0, 2)\n const pathPart = toPosixPath(record.slice(3))\n\n if (isRenameOrCopyStatus(status)) {\n const next = tokens[i + 1]\n if (typeof next !== \"string\") {\n continue\n }\n changes.push({\n kind: \"rename\",\n oldPath: pathPart,\n newPath: toPosixPath(next),\n })\n i += 1\n continue\n }\n\n changes.push({\n kind: \"path\",\n path: pathPart,\n })\n }\n\n return changes\n}\n\nfunction isRenameOrCopyStatus(status: string): boolean {\n return status.includes(\"R\") || status.includes(\"C\")\n}\n\nfunction resolveRenamedPath(original: string, renameMap: Map<string, string>): string {\n let current = original\n const visited = new Set<string>()\n\n while (!visited.has(current)) {\n const next = renameMap.get(current)\n if (!next) {\n break\n }\n visited.add(current)\n current = next\n }\n\n return current\n}\n\nfunction isSubpath(candidate: string, root: string): boolean {\n const relative = path.relative(root, candidate)\n return relative === \"\" || (!relative.startsWith(\"..\") && !path.isAbsolute(relative))\n}\n\nfunction isSpecSourceFile(absolutePath: string, specRootAbsolute: string): boolean {\n if (!isSubpath(absolutePath, specRootAbsolute)) {\n return false\n }\n\n return absolutePath.endsWith(\".spec.ts\")\n || absolutePath.endsWith(\".spec.tsx\")\n}\n\nasync function findSpecSourceFiles(projectRoot: string): Promise<string[]> {\n const patterns = [\"spec/**/*.spec.ts\", \"spec/**/*.spec.tsx\"]\n const matches = await fg(patterns, { cwd: projectRoot, absolute: true, onlyFiles: true })\n return matches.sort()\n}\n\nfunction resolvePlaywrightSpecFile(specProjectPath: string): string {\n const buildSpecRoot = path.join(process.cwd(), \"build\", \"spec\")\n const isBuildSpecProject = fs.existsSync(buildSpecRoot)\n\n if (!isBuildSpecProject) {\n return specProjectPath\n }\n\n const builtCandidate = normalizeBuiltSpecPath(path.join(\"build\", specProjectPath))\n const builtAbsolute = path.resolve(process.cwd(), builtCandidate)\n if (!fs.existsSync(builtAbsolute)) {\n throw new Error(`[specs-map] Missing built spec file: ${builtCandidate}`)\n }\n\n return builtCandidate\n}\n\nfunction normalizeBuiltSpecPath(filePath: string): string {\n if (filePath.endsWith(\".ts\") || filePath.endsWith(\".tsx\")) {\n return `${filePath.replace(/\\.tsx?$/, \"\")}.js`\n }\n return filePath\n}\n\nfunction toPosixPath(input: unknown): string {\n return String(input ?? \"\").split(path.sep).join(\"/\")\n}\n\nfunction findWorkspaceRoot(projectRoot: string): string {\n let dir = path.resolve(projectRoot)\n\n while (true) {\n const pkgPath = path.join(dir, \"package.json\")\n try {\n if (fs.existsSync(pkgPath)) {\n const parsed = JSON.parse(fs.readFileSync(pkgPath, \"utf8\"))\n if (parsed && typeof parsed === \"object\" && parsed.workspaces) {\n return dir\n }\n }\n } catch {\n //\n }\n\n const parent = path.dirname(dir)\n if (parent === dir) {\n return path.resolve(projectRoot)\n }\n dir = parent\n }\n}\n\nfunction runPlaywright(\n userArgs: string[],\n { disableCoverage = false }: { disableCoverage?: boolean } = {},\n): Promise<void> {\n // Determine config file path\n const configPath = fs.existsSync(\n path.join(process.cwd(), \"playwright.config.ts\"),\n )\n ? path.join(process.cwd(), \"playwright.config.ts\")\n : path.join(moduleDir, \"playwright.config.ts\")\n\n const hasCustomConfig = userArgs.some((arg) => {\n if (arg === \"--config\" || arg === \"-c\") {\n return true\n }\n\n return arg.startsWith(\"--config=\")\n })\n\n const playwrightArgs = [\"test\"]\n\n if (!hasCustomConfig) {\n playwrightArgs.push(\"--config\", configPath)\n }\n\n playwrightArgs.push(...userArgs)\n\n ensureJsxRuntimeShim(process.cwd())\n const launcher = resolvePlaywrightLauncher()\n const env = withRegisterShim(process.env)\n env[COMBINED_COVERAGE_ENV_VAR] = \"1\"\n if (disableCoverage) {\n env.RB_DISABLE_COVERAGE = \"1\"\n }\n\n return spawnWithLogs({\n name: \"Playwright\",\n launcher,\n args: playwrightArgs,\n env,\n successMessage: \"Playwright suite passed!\",\n failureMessage: \"Playwright failed\",\n })\n}\n\ntype SpawnLauncher = {\n command: string\n args?: string[]\n}\n\nfunction resolvePlaywrightLauncher(): SpawnLauncher {\n const cliPath = resolveCliPath()\n if (cliPath) {\n return {\n command: process.execPath,\n args: [cliPath],\n }\n }\n\n const localBin = path.resolve(process.cwd(), \"node_modules/.bin/playwright\")\n if (fs.existsSync(localBin)) {\n return {\n command: localBin,\n args: [],\n }\n }\n\n return {\n command: \"playwright\",\n args: [],\n }\n}\n\nfunction resolveCliPath(): string | null {\n const searchRoots = [process.cwd(), moduleDir]\n\n for (const base of searchRoots) {\n try {\n const pkgPath = require.resolve(\"@playwright/test/package.json\", { paths: [base] })\n const cliPath = path.join(path.dirname(pkgPath), \"cli.js\")\n if (fs.existsSync(cliPath)) {\n return cliPath\n }\n } catch (_error) {\n // continue searching\n }\n }\n\n return null\n}\n\nfunction resolveVitestLauncher(): SpawnLauncher {\n const searchRoots = [process.cwd(), moduleDir]\n\n for (const base of searchRoots) {\n try {\n const pkgPath = require.resolve(\"vitest/package.json\", { paths: [base] })\n const pkgDir = path.dirname(pkgPath)\n const pkgJson = JSON.parse(fs.readFileSync(pkgPath, \"utf8\"))\n const binPath = typeof pkgJson.bin === \"string\" ? pkgJson.bin : pkgJson.bin?.vitest\n if (binPath) {\n return {\n command: process.execPath,\n args: [path.join(pkgDir, binPath)],\n }\n }\n } catch (_error) {\n // continue searching\n }\n }\n\n const localBin = path.resolve(process.cwd(), \"node_modules/.bin/vitest\")\n if (fs.existsSync(localBin)) {\n return {\n command: localBin,\n args: [],\n }\n }\n\n return {\n command: \"vitest\",\n args: [],\n }\n}\n\nfunction resolveVitestConfig(): string | null {\n const userConfig = findVitestConfig(process.cwd())\n if (userConfig) {\n return userConfig\n }\n\n const bundledConfig = path.join(moduleDir, \"vitest.config.js\")\n return fs.existsSync(bundledConfig) ? bundledConfig : null\n}\n\nfunction findVitestConfig(baseDir: string): string | null {\n const candidates = [\n \"vitest.config.ts\",\n \"vitest.config.js\",\n \"vitest.config.mjs\",\n ]\n\n for (const file of candidates) {\n const fullPath = path.join(baseDir, file)\n if (fs.existsSync(fullPath)) {\n return fullPath\n }\n }\n\n return null\n}\n\nasync function loadVitestCoverageConfig(): Promise<CoverageState> {\n const options = await loadCoverageOptions({\n optional: true,\n candidates: VITEST_COVERAGE_CANDIDATES,\n defaultTestResultsDir: \"test-results-vitest\",\n })\n if (!options) {\n return null\n }\n\n const config = createCoverageConfig(options)\n\n return {\n config,\n enabled: config.coverageEnabled,\n }\n}\n\nasync function loadPlaywrightCoverageConfig(): Promise<CoverageState> {\n const options = await loadCoverageOptions({ optional: true })\n if (!options) {\n return null\n }\n\n const config = createCoverageConfig(options)\n\n return {\n config,\n enabled: config.coverageEnabled,\n }\n}\n\nfunction resolveCombinedCoverage(playwrightCoverage: CoverageState, vitestCoverage: CoverageState): CoverageState {\n if (playwrightCoverage?.enabled) {\n return playwrightCoverage\n }\n\n if (vitestCoverage?.enabled) {\n return vitestCoverage\n }\n\n return null\n}\n\nasync function cleanCoverageArtifacts(config: CoverageConfig): Promise<void> {\n await removeCoverageFiles(config)\n await fsPromises.rm(config.coverageReportDir, { recursive: true, force: true })\n await fsPromises.rm(path.join(config.testResultsRoot, \"node-coverage\"), { recursive: true, force: true })\n}\n\nfunction resolveNodeCoverageDir(config: CoverageConfig): string {\n return path.join(config.testResultsRoot, \"node-coverage\", \"vitest\")\n}\n\nasync function convertNodeCoverage(coverage: { config: CoverageConfig; nodeCoverageDir: string }): Promise<void> {\n const { config, nodeCoverageDir } = coverage\n\n const entries = await fsPromises.readdir(nodeCoverageDir).catch(() => [])\n const scripts = []\n const scriptRoots = resolveCollectCoverageRoots(config.collectCoverageFrom, config.rootDir)\n\n for (const entry of entries) {\n if (!entry.endsWith(\".json\")) {\n continue\n }\n\n const fullPath = path.join(nodeCoverageDir, entry)\n const payload = await readJson(fullPath)\n const results = Array.isArray(payload?.result) ? payload.result : []\n\n for (const script of results) {\n const normalized = normalizeNodeScriptUrl(script.url, config.rootDir)\n if (!normalized) {\n continue\n }\n\n if (isNodeModulesPath(normalized.absolutePath)) {\n continue\n }\n\n if (!isInsideAnyRoot(normalized.absolutePath, scriptRoots)) {\n continue\n }\n\n const source = await fsPromises.readFile(normalized.absolutePath, \"utf8\").catch(() => \"\")\n\n scripts.push({\n absolutePath: normalized.absolutePath,\n relativePath: normalized.relativePath,\n source,\n functions: script.functions ?? [],\n url: script.url,\n })\n }\n }\n\n if (scripts.length === 0) {\n return\n }\n\n const outDir = path.join(config.testResultsRoot, \"vitest\")\n await fsPromises.mkdir(outDir, { recursive: true })\n const outputFile = path.join(outDir, config.coverageFileName)\n await fsPromises.writeFile(outputFile, JSON.stringify({ testId: \"vitest\", scripts }, null, 2), \"utf8\")\n}\n\nasync function finalizeCoverage(config: CoverageConfig): Promise<void> {\n try {\n await generateCoverageReport(config)\n } catch (error: any) {\n if (error instanceof CoverageThresholdError) {\n console.error(error.message)\n }\n throw error\n }\n}\n\nasync function readJson(filePath: string): Promise<any | null> {\n try {\n const raw = await fsPromises.readFile(filePath, \"utf8\")\n return JSON.parse(raw)\n } catch {\n return null\n }\n}\n\nfunction normalizeNodeScriptUrl(\n rawUrl: string,\n rootDir: string,\n): { absolutePath: string; relativePath: string } | null {\n if (!rawUrl || rawUrl.startsWith(\"node:\")) {\n return null\n }\n\n let absolutePath = null\n\n try {\n if (rawUrl.startsWith(\"file://\")) {\n absolutePath = fileURLToPath(rawUrl)\n }\n } catch (_err) {\n // ignore invalid URLs\n }\n\n if (!absolutePath && path.isAbsolute(rawUrl)) {\n absolutePath = rawUrl\n }\n\n if (!absolutePath) {\n return null\n }\n\n const normalized = path.normalize(absolutePath)\n\n return {\n absolutePath: normalized,\n relativePath: path.relative(rootDir, normalized),\n }\n}\n\nfunction isNodeModulesPath(filePath: unknown): boolean {\n return path\n .normalize(String(filePath ?? \"\"))\n .split(path.sep)\n .includes(\"node_modules\")\n}\n\nfunction spawnWithLogs({\n name,\n launcher,\n args,\n env,\n successMessage,\n failureMessage,\n}: {\n name: string\n launcher: SpawnLauncher\n args: string[]\n env: NodeJS.ProcessEnv\n successMessage?: string\n failureMessage?: string\n}): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n const stdoutBuffer: string[] = []\n const stderrBuffer: string[] = []\n\n const child = spawn(\n launcher.command,\n [...(launcher.args || []), ...args],\n {\n shell: false,\n env,\n },\n )\n\n child.stdout?.on(\"data\", (data) => {\n if (!isAider) {\n process.stdout.write(data)\n }\n stdoutBuffer.push(data.toString())\n })\n\n child.stderr?.on(\"data\", (data) => {\n if (!isAider) {\n process.stderr.write(data)\n }\n stderrBuffer.push(data.toString())\n })\n\n child.on(\"close\", (code) => {\n if (code === 0) {\n if (successMessage) {\n console.log(successMessage)\n }\n resolve()\n } else {\n console.error(failureMessage || `${name} failed:`)\n\n if (isAider) {\n if (stdoutBuffer.length > 0) {\n console.error(stdoutBuffer.join(\"\"))\n }\n\n if (stderrBuffer.length > 0) {\n console.error(stderrBuffer.join(\"\"))\n }\n }\n\n reject(new Error(`${name} failed with exit code: ${code}`))\n }\n })\n\n child.on(\"error\", (error) => {\n console.error(`Error spawning ${name}:`, error)\n reject(error)\n })\n })\n}\n\nfunction withRegisterShim(baseEnv: NodeJS.ProcessEnv): NodeJS.ProcessEnv {\n const nodeOptions = appendNodeRequire(baseEnv.NODE_OPTIONS, path.join(moduleDir, \"register-tty.cjs\"))\n return {\n ...baseEnv,\n NODE_OPTIONS: nodeOptions,\n }\n}\n\nfunction ensureJsxRuntimeShim(projectRoot: string): void {\n const shimDir = path.join(projectRoot, \"node_modules\", \"playwright\")\n fs.mkdirSync(shimDir, { recursive: true })\n const shims = [\n { file: \"jsx-runtime.js\", target: \"react/jsx-runtime\" },\n { file: \"jsx-dev-runtime.js\", target: \"react/jsx-dev-runtime\" },\n ]\n\n for (const { file, target } of shims) {\n const filePath = path.join(shimDir, file)\n if (!fs.existsSync(filePath)) {\n const content = `export * from \"${target}\";\\nexport { default } from \"${target}\";\\n`\n fs.writeFileSync(filePath, content, \"utf8\")\n }\n }\n}\n\nfunction appendNodeRequire(existing: string | undefined, modulePath: string): string {\n const flag = `--require=${modulePath}`\n if (!existing || existing.length === 0) {\n return flag\n }\n return `${existing} ${flag}`\n}\n"],"names":["require","fsPromises","fs"],"mappings":"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"}
1
+ {"version":3,"file":"cli.js","sources":["../src/cli.ts"],"sourcesContent":["import { spawn, spawnSync } from \"node:child_process\"\nimport fs from \"node:fs\"\nimport fsPromises from \"node:fs/promises\"\nimport path from \"node:path\"\nimport { createRequire } from \"node:module\"\nimport { fileURLToPath } from \"node:url\"\n\nimport fg from \"fast-glob\"\n\nimport { createCoverageConfig } from \"./coverage/config\"\nimport { createCollectCoverageMatcher, isInsideAnyRoot, resolveCollectCoverageRoots } from \"./coverage/collect\"\nimport { loadCoverageOptions } from \"./coverage/config-loader\"\nimport { removeCoverageFiles } from \"./coverage/files\"\nimport { collectCoveredFiles, CoverageThresholdError, generateCoverageReport } from \"./coverage/report\"\nimport type { CoverageConfig } from \"./coverage/types\"\n\n\nconst require = createRequire(import.meta.url)\nconst moduleDir = path.dirname(fileURLToPath(import.meta.url))\n\nconst shouldForceTty =\n !process.stdout.isTTY\n && process.env.FORCE_COLOR === \"true\"\n\nif (shouldForceTty) {\n require(\"./register-tty.cjs\")\n}\n\n\nconst VITEST_COVERAGE_CANDIDATES = [\"src/coverage.json\"]\n\nconst COMBINED_COVERAGE_ENV_VAR = \"RB_TEST_COMBINED_COVERAGE\"\n\nconst isAider = process.env.IS_AIDER === \"yes\"\n\nif (process.env.IS_AIDER !== undefined && process.env.IS_AIDER !== \"yes\") {\n console.warn(\"Warning: IS_AIDER is set to a value other than 'yes'.\")\n}\n\ntype CoverageState = { config: CoverageConfig; enabled: boolean } | null\n\nasync function runTests(): Promise<void> {\n const userArgs = process.argv.slice(2)\n const buildSpecsMap = userArgs.includes(\"--build-specs-map\")\n const auto = userArgs.includes(\"--auto\")\n const showMapping = userArgs.includes(\"--show-mapping\")\n const filteredArgs = userArgs.filter((arg) => arg !== \"--build-specs-map\" && arg !== \"--auto\" && arg !== \"--show-mapping\")\n\n if (buildSpecsMap && auto) {\n throw new Error(\"[rb-test] --auto cannot be combined with --build-specs-map\")\n }\n\n if (showMapping && !auto) {\n throw new Error(\"[rb-test] --show-mapping requires --auto\")\n }\n\n const playwrightCoverage = await loadPlaywrightCoverageConfig()\n const vitestCoverage = await loadVitestCoverageConfig()\n const combinedCoverage = resolveCombinedCoverage(playwrightCoverage, vitestCoverage)\n\n if (buildSpecsMap) {\n await buildSpecsMapFromCoverage({\n userArgs: filteredArgs,\n playwrightCoverage,\n vitestCoverage,\n combinedCoverage,\n })\n return\n }\n\n const shouldGenerateCoverageReport = combinedCoverage?.enabled && !auto\n\n if (shouldGenerateCoverageReport) {\n await cleanCoverageArtifacts(combinedCoverage.config)\n }\n\n let testError = null\n\n try {\n await runVitest(vitestCoverage, combinedCoverage?.config ?? null, { disableCoverage: auto })\n console.log(\"\\nRunning Playwright Tests...\")\n const playwrightArgs = auto\n ? await resolveAutoPlaywrightArgs({\n userArgs: filteredArgs,\n playwrightCoverage,\n vitestCoverage,\n showMapping,\n })\n : userArgs\n if (playwrightArgs) {\n await runPlaywright(playwrightArgs, { disableCoverage: auto })\n }\n } catch (error: any) {\n testError = error\n }\n\n if (shouldGenerateCoverageReport) {\n if (testError) {\n console.warn(\"[coverage] skipping report generation because tests failed\")\n } else {\n try {\n await finalizeCoverage(combinedCoverage.config)\n } catch (error) {\n testError = error\n }\n }\n }\n\n if (testError) {\n throw testError\n }\n}\n\nrunTests()\n .then(() => process.exit(0))\n .catch((error) => {\n if (!(error instanceof CoverageThresholdError)) {\n console.error(error?.stack ?? String(error))\n }\n process.exit(1)\n })\n\nasync function runVitest(\n coverage: CoverageState,\n combinedConfig: CoverageConfig | null,\n { disableCoverage = false }: { disableCoverage?: boolean } = {},\n): Promise<void> {\n const vitestArgs = [\"run\", \"--passWithNoTests\"]\n const vitestConfig = resolveVitestConfig()\n\n if (vitestConfig) {\n vitestArgs.push(\"--config\", vitestConfig)\n }\n const launcher = resolveVitestLauncher()\n const env = withRegisterShim(process.env)\n\n if (disableCoverage) {\n env.RB_DISABLE_COVERAGE = \"1\"\n }\n\n if (coverage?.enabled && !disableCoverage) {\n // Vitest runs in a Node.js process, so we use Node's built-in V8 coverage output (NODE_V8_COVERAGE) here.\n // Playwright coverage is collected separately via CDP in Chromium; server coverage is handled via /api/dev/coverage start/stop.\n const nodeCoverageDir = resolveNodeCoverageDir(combinedConfig ?? coverage.config)\n await fsPromises.mkdir(nodeCoverageDir, { recursive: true })\n env.NODE_V8_COVERAGE = nodeCoverageDir\n }\n\n await spawnWithLogs({\n name: \"Vitest\",\n launcher,\n args: vitestArgs,\n env,\n successMessage: \"Vitest suite passed!\",\n failureMessage: \"Vitest failed\",\n })\n\n if (coverage?.enabled && !disableCoverage) {\n await convertNodeCoverage({\n config: combinedConfig ?? coverage.config,\n nodeCoverageDir: resolveNodeCoverageDir(combinedConfig ?? coverage.config),\n })\n }\n}\n\nasync function buildSpecsMapFromCoverage({\n userArgs,\n combinedCoverage,\n}: {\n userArgs: string[]\n combinedCoverage: CoverageState\n [key: string]: unknown\n}): Promise<void> {\n if (!combinedCoverage?.enabled) {\n throw new Error(\"[specs-map] Coverage must be enabled to build the specs map.\")\n }\n\n const config = combinedCoverage.config\n const workspaceRoot = findWorkspaceRoot(process.cwd())\n\n const specSourceFiles = await findSpecSourceFiles(config.rootDir)\n if (specSourceFiles.length === 0) {\n throw new Error(\"[specs-map] No spec files found under spec/**/*.spec.ts\")\n }\n\n const filesMapDir = path.join(config.testResultsRoot, \"files-map\")\n await fsPromises.rm(filesMapDir, { recursive: true, force: true })\n await fsPromises.mkdir(filesMapDir, { recursive: true })\n\n for (const specSourceFile of specSourceFiles) {\n const specProjectPath = path.relative(config.rootDir, specSourceFile)\n const specWorkspacePath = toPosixPath(path.relative(workspaceRoot, specSourceFile))\n const testFile = resolvePlaywrightSpecFile(specProjectPath)\n\n console.log(`\\n[specs-map] Running ${specWorkspacePath}`)\n\n await removeCoverageFiles(config)\n\n let error = null\n let failed = false\n try {\n await runPlaywright([...userArgs, testFile])\n } catch (runError: any) {\n error = runError\n failed = true\n console.error(`[specs-map] Failed: ${specWorkspacePath}`)\n console.error(runError?.stack ?? String(runError))\n }\n\n const coveredFiles = await collectCoveredFiles(config)\n const impactedFiles = coveredFiles\n .map((filePath) => toPosixPath(path.relative(workspaceRoot, filePath)))\n .filter((relativePath) => relativePath && !relativePath.startsWith(\"../\") && relativePath !== \"..\")\n .sort()\n\n const outputFile = path.join(filesMapDir, `${specProjectPath}.json`)\n await fsPromises.mkdir(path.dirname(outputFile), { recursive: true })\n await fsPromises.writeFile(\n outputFile,\n JSON.stringify(\n {\n spec: specWorkspacePath,\n files: impactedFiles,\n failed,\n },\n null,\n 2,\n ),\n \"utf8\",\n )\n\n if (failed) {\n throw error\n }\n }\n}\n\ntype GitChange =\n | { kind: \"rename\"; oldPath: string; newPath: string }\n | { kind: \"path\"; path: string }\n\nasync function resolveAutoPlaywrightArgs({\n userArgs,\n playwrightCoverage,\n vitestCoverage,\n showMapping = false,\n}: {\n userArgs: string[]\n playwrightCoverage: CoverageState\n vitestCoverage: CoverageState\n showMapping?: boolean\n [key: string]: unknown\n}): Promise<string[] | null> {\n const config = playwrightCoverage?.config ?? vitestCoverage?.config ?? null\n if (!config) {\n console.warn(\"[auto] Coverage config not found; running full Playwright suite.\")\n return userArgs\n }\n\n const filesMapDir = path.join(config.testResultsRoot, \"files-map\")\n const mapFiles = await findFilesMapJson(filesMapDir)\n if (mapFiles.length === 0) {\n console.warn(\"[auto] Specs map not found; running full Playwright suite.\")\n return userArgs\n }\n\n const workspaceRoot = findWorkspaceRoot(process.cwd())\n const gitChanges = getGitChanges(workspaceRoot)\n const renameMap = new Map<string, string>(\n gitChanges\n .filter((change): change is { kind: \"rename\"; oldPath: string; newPath: string } => change.kind === \"rename\")\n .map((change) => [change.oldPath, change.newPath]),\n )\n\n const specRootAbs = path.join(config.rootDir, \"spec\")\n const matchesCollectCoverageFrom = createCollectCoverageMatcher(config.collectCoverageFrom, config.rootDir)\n\n const directSpecChanges = new Set<string>()\n const sourceChanges: GitChange[] = []\n\n for (const change of gitChanges) {\n if (change.kind === \"rename\") {\n const oldAbs = path.join(workspaceRoot, change.oldPath)\n const newAbs = path.join(workspaceRoot, change.newPath)\n\n if (isSpecSourceFile(newAbs, specRootAbs) && fs.existsSync(newAbs)) {\n directSpecChanges.add(change.newPath)\n }\n\n const oldMatches = matchesCollectCoverageFrom(oldAbs)\n const newMatches = matchesCollectCoverageFrom(newAbs)\n if (oldMatches || newMatches) {\n sourceChanges.push(change)\n }\n continue\n }\n\n const abs = path.join(workspaceRoot, change.path)\n\n if (isSpecSourceFile(abs, specRootAbs) && fs.existsSync(abs)) {\n directSpecChanges.add(change.path)\n }\n\n if (matchesCollectCoverageFrom(abs)) {\n sourceChanges.push(change)\n }\n }\n\n if (directSpecChanges.size === 0 && sourceChanges.length === 0) {\n console.log(\"[auto] No relevant git changes.\")\n return null\n }\n\n const parsedMaps: Array<{ spec: string; files: string[] }> = []\n for (const file of mapFiles) {\n const json = await readJson(file)\n if (!json) {\n continue\n }\n\n if (json.failed === true) {\n console.warn(\"[auto] Specs map contains failed entries; running full Playwright suite.\")\n return userArgs\n }\n\n const spec = typeof json?.spec === \"string\" ? json.spec : null\n if (!spec) {\n continue\n }\n\n const files = Array.isArray(json?.files)\n ? (json.files as unknown[]).filter((entry): entry is string => typeof entry === \"string\")\n : []\n parsedMaps.push({ spec, files })\n }\n\n if (parsedMaps.length === 0) {\n console.warn(\"[auto] Specs map is empty; running full Playwright suite.\")\n return userArgs\n }\n\n const specsByImpactedFile = new Map<string, string[]>()\n\n for (const entry of parsedMaps) {\n const resolvedSpec = resolveRenamedPath(entry.spec, renameMap)\n for (const file of entry.files) {\n const list = specsByImpactedFile.get(file) ?? []\n list.push(resolvedSpec)\n specsByImpactedFile.set(file, list)\n }\n }\n\n const unmappedSourceChanges = sourceChanges.filter((change) => {\n if (change.kind === \"path\") {\n return !specsByImpactedFile.has(change.path)\n }\n return !specsByImpactedFile.has(change.oldPath) && !specsByImpactedFile.has(change.newPath)\n })\n\n if (unmappedSourceChanges.length > 0) {\n console.warn(\"[auto] Unmapped source changes detected:\")\n for (const change of unmappedSourceChanges) {\n if (change.kind === \"path\") {\n console.warn(` - ${change.path}`)\n } else {\n console.warn(` - ${change.oldPath} -> ${change.newPath}`)\n }\n }\n }\n\n const selectedSpecs = new Set<string>(directSpecChanges)\n const triggersBySpec = new Map<string, Set<string>>()\n\n for (const spec of directSpecChanges) {\n if (showMapping) {\n triggersBySpec.set(spec, new Set([spec]))\n }\n }\n\n for (const change of sourceChanges) {\n if (change.kind === \"path\") {\n const specs = specsByImpactedFile.get(change.path) ?? []\n specs.forEach((spec) => selectedSpecs.add(spec))\n if (showMapping) {\n for (const spec of specs) {\n const current = triggersBySpec.get(spec) ?? new Set()\n current.add(change.path)\n triggersBySpec.set(spec, current)\n }\n }\n continue\n }\n\n const oldSpecs = specsByImpactedFile.get(change.oldPath) ?? []\n oldSpecs.forEach((spec) => selectedSpecs.add(spec))\n const newSpecs = specsByImpactedFile.get(change.newPath) ?? []\n newSpecs.forEach((spec) => selectedSpecs.add(spec))\n if (showMapping) {\n const key = `${change.oldPath} -> ${change.newPath}`\n const allSpecs = new Set([...oldSpecs, ...newSpecs])\n for (const spec of allSpecs) {\n const current = triggersBySpec.get(spec) ?? new Set()\n current.add(key)\n triggersBySpec.set(spec, current)\n }\n }\n }\n\n const missingSpecs: string[] = []\n const specsToRun = Array.from(selectedSpecs)\n .filter((spec) => {\n const abs = path.join(workspaceRoot, spec)\n if (fs.existsSync(abs)) {\n return true\n }\n missingSpecs.push(spec)\n return false\n })\n .sort()\n if (missingSpecs.length > 0) {\n console.warn(`[auto] Ignoring ${missingSpecs.length} missing spec file(s):`)\n for (const spec of missingSpecs.sort()) {\n console.warn(` - ${spec}`)\n }\n }\n\n if (specsToRun.length === 0) {\n console.log(\"[auto] No impacted specs.\")\n return null\n }\n\n if (showMapping) {\n console.log(\"[auto] Mapping:\")\n for (const spec of specsToRun) {\n const triggers = Array.from(triggersBySpec.get(spec) ?? []).sort()\n if (triggers.length === 0) {\n continue\n }\n console.log(` - ${spec}`)\n for (const trigger of triggers) {\n console.log(` <- ${trigger}`)\n }\n }\n }\n\n const playwrightFiles = specsToRun\n .map((specWorkspacePath) => path.join(workspaceRoot, specWorkspacePath))\n .filter((specAbs) => isSubpath(specAbs, config.rootDir))\n .map((specAbs) => {\n const specProjectPath = path.relative(config.rootDir, specAbs)\n return resolvePlaywrightSpecFile(specProjectPath)\n })\n\n const totalSpecFiles = (await findSpecSourceFiles(config.rootDir)).length\n console.log(`[auto] Running ${playwrightFiles.length}/${totalSpecFiles} spec file(s).`)\n return [...userArgs, ...playwrightFiles]\n}\n\nasync function findFilesMapJson(filesMapDir: string): Promise<string[]> {\n const patterns = [\"spec/**/*.spec.ts.json\", \"spec/**/*.spec.tsx.json\"]\n const matches = await fg(patterns, { cwd: filesMapDir, absolute: true, onlyFiles: true }).catch(() => [])\n return matches.sort()\n}\n\nfunction getGitChanges(workspaceRoot: string): GitChange[] {\n const result = spawnSync(\"git\", [\"status\", \"--porcelain=1\", \"-z\"], {\n cwd: workspaceRoot,\n encoding: \"utf8\",\n })\n\n if (result.status !== 0) {\n throw new Error(`[auto] Failed to read git status: ${result.stderr || \"unknown error\"}`)\n }\n\n const tokens = String(result.stdout ?? \"\").split(\"\\0\").filter(Boolean)\n const changes: GitChange[] = []\n\n for (let i = 0; i < tokens.length; i += 1) {\n const record = tokens[i]\n if (record.length < 4) {\n continue\n }\n\n const status = record.slice(0, 2)\n const pathPart = toPosixPath(record.slice(3))\n\n if (isRenameOrCopyStatus(status)) {\n const next = tokens[i + 1]\n if (typeof next !== \"string\") {\n continue\n }\n changes.push({\n kind: \"rename\",\n oldPath: pathPart,\n newPath: toPosixPath(next),\n })\n i += 1\n continue\n }\n\n changes.push({\n kind: \"path\",\n path: pathPart,\n })\n }\n\n return changes\n}\n\nfunction isRenameOrCopyStatus(status: string): boolean {\n return status.includes(\"R\") || status.includes(\"C\")\n}\n\nfunction resolveRenamedPath(original: string, renameMap: Map<string, string>): string {\n let current = original\n const visited = new Set<string>()\n\n while (!visited.has(current)) {\n const next = renameMap.get(current)\n if (!next) {\n break\n }\n visited.add(current)\n current = next\n }\n\n return current\n}\n\nfunction isSubpath(candidate: string, root: string): boolean {\n const relative = path.relative(root, candidate)\n return relative === \"\" || (!relative.startsWith(\"..\") && !path.isAbsolute(relative))\n}\n\nfunction isSpecSourceFile(absolutePath: string, specRootAbsolute: string): boolean {\n if (!isSubpath(absolutePath, specRootAbsolute)) {\n return false\n }\n\n return absolutePath.endsWith(\".spec.ts\")\n || absolutePath.endsWith(\".spec.tsx\")\n}\n\nasync function findSpecSourceFiles(projectRoot: string): Promise<string[]> {\n const patterns = [\"spec/**/*.spec.ts\", \"spec/**/*.spec.tsx\"]\n const matches = await fg(patterns, { cwd: projectRoot, absolute: true, onlyFiles: true })\n return matches.sort()\n}\n\nfunction resolvePlaywrightSpecFile(specProjectPath: string): string {\n const buildSpecRoot = path.join(process.cwd(), \"build\", \"spec\")\n const isBuildSpecProject = fs.existsSync(buildSpecRoot)\n\n if (!isBuildSpecProject) {\n return specProjectPath\n }\n\n const builtCandidate = normalizeBuiltSpecPath(path.join(\"build\", specProjectPath))\n const builtAbsolute = path.resolve(process.cwd(), builtCandidate)\n if (!fs.existsSync(builtAbsolute)) {\n throw new Error(`[specs-map] Missing built spec file: ${builtCandidate}`)\n }\n\n return builtCandidate\n}\n\nfunction normalizeBuiltSpecPath(filePath: string): string {\n if (filePath.endsWith(\".ts\") || filePath.endsWith(\".tsx\")) {\n return `${filePath.replace(/\\.tsx?$/, \"\")}.js`\n }\n return filePath\n}\n\nfunction toPosixPath(input: unknown): string {\n return String(input ?? \"\").split(path.sep).join(\"/\")\n}\n\nfunction findWorkspaceRoot(projectRoot: string): string {\n let dir = path.resolve(projectRoot)\n\n while (true) {\n const pkgPath = path.join(dir, \"package.json\")\n try {\n if (fs.existsSync(pkgPath)) {\n const parsed = JSON.parse(fs.readFileSync(pkgPath, \"utf8\"))\n if (parsed && typeof parsed === \"object\" && parsed.workspaces) {\n return dir\n }\n }\n } catch {\n //\n }\n\n const parent = path.dirname(dir)\n if (parent === dir) {\n return path.resolve(projectRoot)\n }\n dir = parent\n }\n}\n\nfunction runPlaywright(\n userArgs: string[],\n { disableCoverage = false }: { disableCoverage?: boolean } = {},\n): Promise<void> {\n // Determine config file path\n const configPath = fs.existsSync(\n path.join(process.cwd(), \"playwright.config.ts\"),\n )\n ? path.join(process.cwd(), \"playwright.config.ts\")\n : path.join(moduleDir, \"playwright.config.ts\")\n\n const hasCustomConfig = userArgs.some((arg) => {\n if (arg === \"--config\" || arg === \"-c\") {\n return true\n }\n\n return arg.startsWith(\"--config=\")\n })\n\n const playwrightArgs = [\"test\"]\n\n if (!hasCustomConfig) {\n playwrightArgs.push(\"--config\", configPath)\n }\n\n playwrightArgs.push(...userArgs)\n\n ensureJsxRuntimeShim(process.cwd())\n const launcher = resolvePlaywrightLauncher()\n const env = withRegisterShim(process.env)\n env[COMBINED_COVERAGE_ENV_VAR] = \"1\"\n if (disableCoverage) {\n env.RB_DISABLE_COVERAGE = \"1\"\n }\n\n return spawnWithLogs({\n name: \"Playwright\",\n launcher,\n args: playwrightArgs,\n env,\n successMessage: \"Playwright suite passed!\",\n failureMessage: \"Playwright failed\",\n })\n}\n\ntype SpawnLauncher = {\n command: string\n args?: string[]\n}\n\nfunction resolvePlaywrightLauncher(): SpawnLauncher {\n const cliPath = resolveCliPath()\n if (cliPath) {\n return {\n command: process.execPath,\n args: [cliPath],\n }\n }\n\n const localBin = path.resolve(process.cwd(), \"node_modules/.bin/playwright\")\n if (fs.existsSync(localBin)) {\n return {\n command: localBin,\n args: [],\n }\n }\n\n return {\n command: \"playwright\",\n args: [],\n }\n}\n\nfunction resolveCliPath(): string | null {\n const searchRoots = [process.cwd(), moduleDir]\n\n for (const base of searchRoots) {\n try {\n const pkgPath = require.resolve(\"@playwright/test/package.json\", { paths: [base] })\n const cliPath = path.join(path.dirname(pkgPath), \"cli.js\")\n if (fs.existsSync(cliPath)) {\n return cliPath\n }\n } catch (_error) {\n // continue searching\n }\n }\n\n return null\n}\n\nfunction resolveVitestLauncher(): SpawnLauncher {\n const searchRoots = [process.cwd(), moduleDir]\n\n for (const base of searchRoots) {\n try {\n const pkgPath = require.resolve(\"vitest/package.json\", { paths: [base] })\n const pkgDir = path.dirname(pkgPath)\n const pkgJson = JSON.parse(fs.readFileSync(pkgPath, \"utf8\"))\n const binPath = typeof pkgJson.bin === \"string\" ? pkgJson.bin : pkgJson.bin?.vitest\n if (binPath) {\n return {\n command: process.execPath,\n args: [path.join(pkgDir, binPath)],\n }\n }\n } catch (_error) {\n // continue searching\n }\n }\n\n const localBin = path.resolve(process.cwd(), \"node_modules/.bin/vitest\")\n if (fs.existsSync(localBin)) {\n return {\n command: localBin,\n args: [],\n }\n }\n\n return {\n command: \"vitest\",\n args: [],\n }\n}\n\nfunction resolveVitestConfig(): string | null {\n const userConfig = findVitestConfig(process.cwd())\n if (userConfig) {\n return userConfig\n }\n\n const bundledConfig = path.join(moduleDir, \"vitest.config.js\")\n return fs.existsSync(bundledConfig) ? bundledConfig : null\n}\n\nfunction findVitestConfig(baseDir: string): string | null {\n const candidates = [\n \"vitest.config.ts\",\n \"vitest.config.js\",\n \"vitest.config.mjs\",\n ]\n\n for (const file of candidates) {\n const fullPath = path.join(baseDir, file)\n if (fs.existsSync(fullPath)) {\n return fullPath\n }\n }\n\n return null\n}\n\nasync function loadVitestCoverageConfig(): Promise<CoverageState> {\n const options = await loadCoverageOptions({\n optional: true,\n candidates: VITEST_COVERAGE_CANDIDATES,\n })\n if (!options) {\n return null\n }\n\n const config = createCoverageConfig(options)\n\n return {\n config,\n enabled: config.coverageEnabled,\n }\n}\n\nasync function loadPlaywrightCoverageConfig(): Promise<CoverageState> {\n const options = await loadCoverageOptions({ optional: true })\n if (!options) {\n return null\n }\n\n const config = createCoverageConfig(options)\n\n return {\n config,\n enabled: config.coverageEnabled,\n }\n}\n\nfunction resolveCombinedCoverage(playwrightCoverage: CoverageState, vitestCoverage: CoverageState): CoverageState {\n if (playwrightCoverage?.enabled) {\n return playwrightCoverage\n }\n\n if (vitestCoverage?.enabled) {\n return vitestCoverage\n }\n\n return null\n}\n\nasync function cleanCoverageArtifacts(config: CoverageConfig): Promise<void> {\n await removeCoverageFiles(config)\n await fsPromises.rm(config.coverageReportDir, { recursive: true, force: true })\n await fsPromises.rm(resolveNodeCoverageDir(config), { recursive: true, force: true })\n}\n\nfunction resolveNodeCoverageDir(config: CoverageConfig): string {\n return path.join(config.rootDir, \"build\", \"vitest\", \"test-results\", \"node-coverage\")\n}\n\nasync function convertNodeCoverage(coverage: { config: CoverageConfig; nodeCoverageDir: string }): Promise<void> {\n const { config, nodeCoverageDir } = coverage\n\n const entries = await fsPromises.readdir(nodeCoverageDir).catch(() => [])\n const scripts = []\n const scriptRoots = resolveCollectCoverageRoots(config.collectCoverageFrom, config.rootDir)\n\n for (const entry of entries) {\n if (!entry.endsWith(\".json\")) {\n continue\n }\n\n const fullPath = path.join(nodeCoverageDir, entry)\n const payload = await readJson(fullPath)\n const results = Array.isArray(payload?.result) ? payload.result : []\n\n for (const script of results) {\n const normalized = normalizeNodeScriptUrl(script.url, config.rootDir)\n if (!normalized) {\n continue\n }\n\n if (isNodeModulesPath(normalized.absolutePath)) {\n continue\n }\n\n if (!isInsideAnyRoot(normalized.absolutePath, scriptRoots)) {\n continue\n }\n\n const source = await fsPromises.readFile(normalized.absolutePath, \"utf8\").catch(() => \"\")\n\n scripts.push({\n absolutePath: normalized.absolutePath,\n relativePath: normalized.relativePath,\n source,\n functions: script.functions ?? [],\n url: script.url,\n })\n }\n }\n\n if (scripts.length === 0) {\n return\n }\n\n const outDir = path.join(config.rootDir, \"build\", \"vitest\", \"coverage\")\n await fsPromises.mkdir(outDir, { recursive: true })\n const outputFile = path.join(outDir, config.coverageFileName)\n await fsPromises.writeFile(outputFile, JSON.stringify({ testId: \"vitest\", scripts }, null, 2), \"utf8\")\n}\n\nasync function finalizeCoverage(config: CoverageConfig): Promise<void> {\n try {\n await generateCoverageReport(config)\n } catch (error: any) {\n if (error instanceof CoverageThresholdError) {\n console.error(error.message)\n }\n throw error\n }\n}\n\nasync function readJson(filePath: string): Promise<any | null> {\n try {\n const raw = await fsPromises.readFile(filePath, \"utf8\")\n return JSON.parse(raw)\n } catch {\n return null\n }\n}\n\nfunction normalizeNodeScriptUrl(\n rawUrl: string,\n rootDir: string,\n): { absolutePath: string; relativePath: string } | null {\n if (!rawUrl || rawUrl.startsWith(\"node:\")) {\n return null\n }\n\n let absolutePath = null\n\n try {\n if (rawUrl.startsWith(\"file://\")) {\n absolutePath = fileURLToPath(rawUrl)\n }\n } catch (_err) {\n // ignore invalid URLs\n }\n\n if (!absolutePath && path.isAbsolute(rawUrl)) {\n absolutePath = rawUrl\n }\n\n if (!absolutePath) {\n return null\n }\n\n const normalized = path.normalize(absolutePath)\n\n return {\n absolutePath: normalized,\n relativePath: path.relative(rootDir, normalized),\n }\n}\n\nfunction isNodeModulesPath(filePath: unknown): boolean {\n return path\n .normalize(String(filePath ?? \"\"))\n .split(path.sep)\n .includes(\"node_modules\")\n}\n\nfunction spawnWithLogs({\n name,\n launcher,\n args,\n env,\n successMessage,\n failureMessage,\n}: {\n name: string\n launcher: SpawnLauncher\n args: string[]\n env: NodeJS.ProcessEnv\n successMessage?: string\n failureMessage?: string\n}): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n const stdoutBuffer: string[] = []\n const stderrBuffer: string[] = []\n\n const child = spawn(\n launcher.command,\n [...(launcher.args || []), ...args],\n {\n shell: false,\n env,\n },\n )\n\n child.stdout?.on(\"data\", (data) => {\n if (!isAider) {\n process.stdout.write(data)\n }\n stdoutBuffer.push(data.toString())\n })\n\n child.stderr?.on(\"data\", (data) => {\n if (!isAider) {\n process.stderr.write(data)\n }\n stderrBuffer.push(data.toString())\n })\n\n child.on(\"close\", (code) => {\n if (code === 0) {\n if (successMessage) {\n console.log(successMessage)\n }\n resolve()\n } else {\n console.error(failureMessage || `${name} failed:`)\n\n if (isAider) {\n if (stdoutBuffer.length > 0) {\n console.error(stdoutBuffer.join(\"\"))\n }\n\n if (stderrBuffer.length > 0) {\n console.error(stderrBuffer.join(\"\"))\n }\n }\n\n reject(new Error(`${name} failed with exit code: ${code}`))\n }\n })\n\n child.on(\"error\", (error) => {\n console.error(`Error spawning ${name}:`, error)\n reject(error)\n })\n })\n}\n\nfunction withRegisterShim(baseEnv: NodeJS.ProcessEnv): NodeJS.ProcessEnv {\n const nodeOptions = appendNodeRequire(baseEnv.NODE_OPTIONS, path.join(moduleDir, \"register-tty.cjs\"))\n return {\n ...baseEnv,\n NODE_OPTIONS: nodeOptions,\n }\n}\n\nfunction ensureJsxRuntimeShim(projectRoot: string): void {\n const shimDir = path.join(projectRoot, \"node_modules\", \"playwright\")\n fs.mkdirSync(shimDir, { recursive: true })\n const shims = [\n { file: \"jsx-runtime.js\", target: \"react/jsx-runtime\" },\n { file: \"jsx-dev-runtime.js\", target: \"react/jsx-dev-runtime\" },\n ]\n\n for (const { file, target } of shims) {\n const filePath = path.join(shimDir, file)\n if (!fs.existsSync(filePath)) {\n const content = `export * from \"${target}\";\\nexport { default } from \"${target}\";\\n`\n fs.writeFileSync(filePath, content, \"utf8\")\n }\n }\n}\n\nfunction appendNodeRequire(existing: string | undefined, modulePath: string): string {\n const flag = `--require=${modulePath}`\n if (!existing || existing.length === 0) {\n return flag\n }\n return `${existing} ${flag}`\n}\n"],"names":["require","fsPromises","fs"],"mappings":"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"}
@@ -2,10 +2,9 @@ import { CoverageHarnessOptions } from './types';
2
2
  type LoadCoverageOptionsArgs = {
3
3
  optional?: boolean;
4
4
  candidates?: string[];
5
- defaultTestResultsDir?: string;
6
5
  };
7
6
  declare const DEFAULT_COVERAGE_CANDIDATES: string[];
8
- export declare function loadCoverageOptions({ optional, candidates, defaultTestResultsDir, }?: LoadCoverageOptionsArgs): Promise<CoverageHarnessOptions | null>;
9
- export declare function loadCoverageOptionsSync({ optional, candidates, defaultTestResultsDir, }?: LoadCoverageOptionsArgs): CoverageHarnessOptions | null;
7
+ export declare function loadCoverageOptions({ optional, candidates, }?: LoadCoverageOptionsArgs): Promise<CoverageHarnessOptions | null>;
8
+ export declare function loadCoverageOptionsSync({ optional, candidates, }?: LoadCoverageOptionsArgs): CoverageHarnessOptions | null;
10
9
  export { DEFAULT_COVERAGE_CANDIDATES };
11
10
  //# sourceMappingURL=config-loader.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"config-loader.d.ts","sourceRoot":"","sources":["../../src/coverage/config-loader.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAA;AAKrD,KAAK,uBAAuB,GAAG;IAC7B,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAA;IACrB,qBAAqB,CAAC,EAAE,MAAM,CAAA;CAC/B,CAAA;AAED,QAAA,MAAM,2BAA2B,UAMhC,CAAA;AAUD,wBAAsB,mBAAmB,CAAC,EACxC,QAAgB,EAChB,UAAwC,EACxC,qBAAqB,GACtB,GAAE,uBAA4B,GAAG,OAAO,CAAC,sBAAsB,GAAG,IAAI,CAAC,CA4BvE;AAED,wBAAgB,uBAAuB,CAAC,EACtC,QAAgB,EAChB,UAAwC,EACxC,qBAAqB,GACtB,GAAE,uBAA4B,GAAG,sBAAsB,GAAG,IAAI,CA4B9D;AAuRD,OAAO,EAAE,2BAA2B,EAAE,CAAA"}
1
+ {"version":3,"file":"config-loader.d.ts","sourceRoot":"","sources":["../../src/coverage/config-loader.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAA;AAKrD,KAAK,uBAAuB,GAAG;IAC7B,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAA;CACtB,CAAA;AAED,QAAA,MAAM,2BAA2B,UAMhC,CAAA;AAUD,wBAAsB,mBAAmB,CAAC,EACxC,QAAgB,EAChB,UAAwC,GACzC,GAAE,uBAA4B,GAAG,OAAO,CAAC,sBAAsB,GAAG,IAAI,CAAC,CA4BvE;AAED,wBAAgB,uBAAuB,CAAC,EACtC,QAAgB,EAChB,UAAwC,GACzC,GAAE,uBAA4B,GAAG,sBAAsB,GAAG,IAAI,CA4B9D;AAiRD,OAAO,EAAE,2BAA2B,EAAE,CAAA"}
@@ -23,8 +23,7 @@ const LEGACY_COVERAGE_CANDIDATES = [
23
23
  ];
24
24
  async function loadCoverageOptions({
25
25
  optional = false,
26
- candidates = DEFAULT_COVERAGE_CANDIDATES,
27
- defaultTestResultsDir
26
+ candidates = DEFAULT_COVERAGE_CANDIDATES
28
27
  } = {}) {
29
28
  const projectRoot = process.cwd();
30
29
  const legacy = await findCoverageFile(projectRoot, LEGACY_COVERAGE_CANDIDATES);
@@ -48,12 +47,11 @@ async function loadCoverageOptions({
48
47
  if (!raw || typeof raw !== "object") {
49
48
  throw new Error(`Coverage config at ${resolved} must export an object.`);
50
49
  }
51
- return await normalizeOptions(raw, resolved, defaultTestResultsDir);
50
+ return await normalizeOptions(raw, resolved);
52
51
  }
53
52
  function loadCoverageOptionsSync({
54
53
  optional = false,
55
- candidates = DEFAULT_COVERAGE_CANDIDATES,
56
- defaultTestResultsDir
54
+ candidates = DEFAULT_COVERAGE_CANDIDATES
57
55
  } = {}) {
58
56
  const projectRoot = process.cwd();
59
57
  const legacy = findCoverageFileSync(projectRoot, LEGACY_COVERAGE_CANDIDATES);
@@ -77,7 +75,7 @@ function loadCoverageOptionsSync({
77
75
  if (!raw || typeof raw !== "object") {
78
76
  throw new Error(`Coverage config at ${resolved} must export an object.`);
79
77
  }
80
- return normalizeOptionsSync(raw, resolved, defaultTestResultsDir);
78
+ return normalizeOptionsSync(raw, resolved);
81
79
  }
82
80
  async function findCoverageFile(root, candidates) {
83
81
  for (const relative of candidates) {
@@ -254,7 +252,7 @@ function isDirectorySync(filePath) {
254
252
  return false;
255
253
  }
256
254
  }
257
- async function normalizeOptions(rawOptions, filePath, defaultTestResultsDir) {
255
+ async function normalizeOptions(rawOptions, filePath) {
258
256
  const options = { ...rawOptions };
259
257
  const configDir = path.dirname(filePath);
260
258
  const rootDir = path.resolve(configDir, "..");
@@ -262,14 +260,12 @@ async function normalizeOptions(rawOptions, filePath, defaultTestResultsDir) {
262
260
  return {
263
261
  rootDir,
264
262
  collectCoverageFrom,
265
- testResultsDir: options.testResultsDir ?? defaultTestResultsDir ?? "test-results",
266
- coverageReportSubdir: options.coverageReportSubdir ?? "coverage",
267
263
  coverageFileName: options.coverageFileName ?? "v8-coverage.json",
268
264
  includeAllFiles: options.includeAllFiles,
269
265
  thresholds: options.thresholds ?? {}
270
266
  };
271
267
  }
272
- function normalizeOptionsSync(rawOptions, filePath, defaultTestResultsDir) {
268
+ function normalizeOptionsSync(rawOptions, filePath) {
273
269
  const options = { ...rawOptions };
274
270
  const configDir = path.dirname(filePath);
275
271
  const rootDir = path.resolve(configDir, "..");
@@ -277,8 +273,6 @@ function normalizeOptionsSync(rawOptions, filePath, defaultTestResultsDir) {
277
273
  return {
278
274
  rootDir,
279
275
  collectCoverageFrom,
280
- testResultsDir: options.testResultsDir ?? defaultTestResultsDir ?? "test-results",
281
- coverageReportSubdir: options.coverageReportSubdir ?? "coverage",
282
276
  coverageFileName: options.coverageFileName ?? "v8-coverage.json",
283
277
  includeAllFiles: options.includeAllFiles,
284
278
  thresholds: options.thresholds ?? {}
@@ -1 +1 @@
1
- {"version":3,"file":"config-loader.js","sources":["../../src/coverage/config-loader.ts"],"sourcesContent":["import fs from \"node:fs/promises\"\nimport fsSync from \"node:fs\"\nimport path from \"node:path\"\nimport os from \"node:os\"\nimport crypto from \"node:crypto\"\nimport { createRequire } from \"node:module\"\nimport { pathToFileURL } from \"node:url\"\n\nimport { build, buildSync } from \"esbuild\"\n\nimport type { CoverageHarnessOptions } from \"./types\"\n\n\nconst require = createRequire(import.meta.url)\n\ntype LoadCoverageOptionsArgs = {\n optional?: boolean\n candidates?: string[]\n defaultTestResultsDir?: string\n}\n\nconst DEFAULT_COVERAGE_CANDIDATES = [\n \"spec/coverage.config.ts\",\n \"spec/coverage.config.js\",\n \"spec/coverage.config.mjs\",\n \"spec/coverage.config.cjs\",\n \"spec/coverage.config.json\",\n]\n\nconst LEGACY_COVERAGE_CANDIDATES = [\n \"spec/coverage.ts\",\n \"spec/coverage.js\",\n \"spec/coverage.mjs\",\n \"spec/coverage.cjs\",\n \"spec/coverage.json\",\n]\n\nexport async function loadCoverageOptions({\n optional = false,\n candidates = DEFAULT_COVERAGE_CANDIDATES,\n defaultTestResultsDir,\n}: LoadCoverageOptionsArgs = {}): Promise<CoverageHarnessOptions | null> {\n const projectRoot = process.cwd()\n const legacy = await findCoverageFile(projectRoot, LEGACY_COVERAGE_CANDIDATES)\n if (legacy) {\n const ext = path.extname(legacy)\n const suggested = path.join(\"spec\", `coverage.config${ext}`)\n throw new Error(\n `Legacy coverage config detected (${path.relative(projectRoot, legacy)}). Rename it to ${suggested}.`,\n )\n }\n\n const resolved = await findCoverageFile(projectRoot, candidates)\n\n if (!resolved) {\n if (optional) {\n return null\n }\n throw new Error(\n \"Coverage config not found. Create `spec/coverage.config.{ts,js,json}` with your coverage settings.\",\n )\n }\n\n const raw = await importCoverageModule(resolved)\n if (!raw || typeof raw !== \"object\") {\n throw new Error(`Coverage config at ${resolved} must export an object.`)\n }\n\n return await normalizeOptions(raw, resolved, defaultTestResultsDir)\n}\n\nexport function loadCoverageOptionsSync({\n optional = false,\n candidates = DEFAULT_COVERAGE_CANDIDATES,\n defaultTestResultsDir,\n}: LoadCoverageOptionsArgs = {}): CoverageHarnessOptions | null {\n const projectRoot = process.cwd()\n const legacy = findCoverageFileSync(projectRoot, LEGACY_COVERAGE_CANDIDATES)\n if (legacy) {\n const ext = path.extname(legacy)\n const suggested = path.join(\"spec\", `coverage.config${ext}`)\n throw new Error(\n `Legacy coverage config detected (${path.relative(projectRoot, legacy)}). Rename it to ${suggested}.`,\n )\n }\n\n const resolved = findCoverageFileSync(projectRoot, candidates)\n\n if (!resolved) {\n if (optional) {\n return null\n }\n throw new Error(\n \"Coverage config not found. Create `spec/coverage.config.{ts,js,json}` with your coverage settings.\",\n )\n }\n\n const raw = importCoverageModuleSync(resolved)\n if (!raw || typeof raw !== \"object\") {\n throw new Error(`Coverage config at ${resolved} must export an object.`)\n }\n\n return normalizeOptionsSync(raw, resolved, defaultTestResultsDir)\n}\n\nasync function findCoverageFile(root: string, candidates: string[]): Promise<string | null> {\n for (const relative of candidates) {\n const candidate = path.resolve(root, relative)\n try {\n await fs.access(candidate)\n return candidate\n } catch {\n // continue\n }\n }\n return null\n}\n\nfunction findCoverageFileSync(root: string, candidates: string[]): string | null {\n for (const relative of candidates) {\n const candidate = path.resolve(root, relative)\n try {\n fsSync.accessSync(candidate)\n return candidate\n } catch {\n // continue\n }\n }\n return null\n}\n\nasync function importCoverageModule(filePath: string): Promise<unknown> {\n const ext = path.extname(filePath)\n\n if (ext === \".json\") {\n const raw = await fs.readFile(filePath, \"utf8\")\n return JSON.parse(raw)\n }\n\n if (ext === \".ts\") {\n const compiledUrl = await compileTsModule(filePath)\n return loadModule(compiledUrl)\n }\n\n const moduleUrl = pathToFileURL(filePath).href\n return loadModule(moduleUrl)\n}\n\nfunction importCoverageModuleSync(filePath: string): unknown {\n const ext = path.extname(filePath)\n\n if (ext === \".json\") {\n const raw = fsSync.readFileSync(filePath, \"utf8\")\n return JSON.parse(raw)\n }\n\n if (ext === \".cjs\") {\n return loadModuleSync(filePath)\n }\n\n const compiledPath = compileCjsModuleSync(filePath)\n return loadModuleSync(compiledPath)\n}\n\nasync function compileTsModule(filePath: string): Promise<string> {\n const stat = await fs.stat(filePath)\n const hash = crypto\n .createHash(\"sha1\")\n .update(filePath)\n .update(String(stat.mtimeMs))\n .digest(\"hex\")\n\n const outDir = path.join(os.tmpdir(), \"rpcbase-test\")\n await fs.mkdir(outDir, { recursive: true })\n const outfile = path.join(outDir, `coverage-${hash}.mjs`)\n\n await build({\n entryPoints: [filePath],\n outfile,\n platform: \"node\",\n format: \"esm\",\n bundle: false,\n sourcemap: \"inline\",\n logLevel: \"silent\",\n })\n\n return pathToFileURL(outfile).href\n}\n\nfunction compileCjsModuleSync(filePath: string): string {\n const stat = fsSync.statSync(filePath)\n const hash = crypto\n .createHash(\"sha1\")\n .update(filePath)\n .update(String(stat.mtimeMs))\n .digest(\"hex\")\n\n const outDir = path.join(os.tmpdir(), \"rpcbase-test\")\n fsSync.mkdirSync(outDir, { recursive: true })\n const outfile = path.join(outDir, `coverage-${hash}.cjs`)\n\n buildSync({\n entryPoints: [filePath],\n outfile,\n platform: \"node\",\n format: \"cjs\",\n bundle: false,\n sourcemap: \"inline\",\n logLevel: \"silent\",\n })\n\n return outfile\n}\n\nasync function loadModule(url: string): Promise<unknown> {\n const imported = await import(url)\n if (imported && typeof imported.default === \"object\") {\n return imported.default\n }\n return imported\n}\n\nfunction loadModuleSync(modulePath: string): unknown {\n const imported = require(modulePath)\n if (imported && typeof imported.default === \"object\") {\n return imported.default\n }\n return imported\n}\n\nconst DEFAULT_COLLECT_COVERAGE_EXTENSIONS = \"ts,tsx,js,jsx,mjs,cjs\"\nconst DEFAULT_COLLECT_COVERAGE_TEST_EXCLUDE = `!**/*.test.{${DEFAULT_COLLECT_COVERAGE_EXTENSIONS}}`\n\nasync function resolveCollectCoverageFrom(rawPatterns: unknown, rootDir: string): Promise<string[]> {\n const resolvedRootDir = path.resolve(String(rootDir ?? \"\"))\n\n const normalized = Array.isArray(rawPatterns)\n ? rawPatterns\n .map((pattern) => String(pattern ?? \"\").trim())\n .filter((pattern) => pattern.length > 0)\n : []\n\n const excludes = normalized.filter((pattern) => pattern.startsWith(\"!\"))\n const hasIncludes = normalized.some((pattern) => !pattern.startsWith(\"!\"))\n if (hasIncludes) {\n return withDefaultExcludes(normalized)\n }\n\n const defaults = await inferDefaultCollectCoverageFrom(resolvedRootDir)\n if (defaults.length === 0) {\n throw new Error(\n \"Coverage config: couldn't infer a default `collectCoverageFrom` (src/ directory missing). Provide `collectCoverageFrom` with at least one positive glob pattern.\",\n )\n }\n\n return withDefaultExcludes([...defaults, ...excludes])\n}\n\nfunction resolveCollectCoverageFromSync(rawPatterns: unknown, rootDir: string): string[] {\n const resolvedRootDir = path.resolve(String(rootDir ?? \"\"))\n\n const normalized = Array.isArray(rawPatterns)\n ? rawPatterns\n .map((pattern) => String(pattern ?? \"\").trim())\n .filter((pattern) => pattern.length > 0)\n : []\n\n const excludes = normalized.filter((pattern) => pattern.startsWith(\"!\"))\n const hasIncludes = normalized.some((pattern) => !pattern.startsWith(\"!\"))\n if (hasIncludes) {\n return withDefaultExcludes(normalized)\n }\n\n const defaults = inferDefaultCollectCoverageFromSync(resolvedRootDir)\n if (defaults.length === 0) {\n throw new Error(\n \"Coverage config: couldn't infer a default `collectCoverageFrom` (src/ directory missing). Provide `collectCoverageFrom` with at least one positive glob pattern.\",\n )\n }\n\n return withDefaultExcludes([...defaults, ...excludes])\n}\n\nasync function inferDefaultCollectCoverageFrom(rootDir: string): Promise<string[]> {\n const srcDir = path.join(rootDir, \"src\")\n if (await isDirectory(srcDir)) {\n return [`src/**/*.{${DEFAULT_COLLECT_COVERAGE_EXTENSIONS}}`]\n }\n\n return []\n}\n\nfunction inferDefaultCollectCoverageFromSync(rootDir: string): string[] {\n const srcDir = path.join(rootDir, \"src\")\n if (isDirectorySync(srcDir)) {\n return [`src/**/*.{${DEFAULT_COLLECT_COVERAGE_EXTENSIONS}}`]\n }\n\n return []\n}\n\nfunction withDefaultExcludes(patterns: string[]): string[] {\n if (!Array.isArray(patterns) || patterns.length === 0) {\n return patterns\n }\n\n const hasTestExclude = patterns.some((pattern) => {\n const raw = String(pattern ?? \"\")\n if (!raw.startsWith(\"!\")) {\n return false\n }\n return /\\.test(?:\\.|\\{|$)/.test(raw.slice(1))\n })\n if (hasTestExclude) {\n return patterns\n }\n\n return [...patterns, DEFAULT_COLLECT_COVERAGE_TEST_EXCLUDE]\n}\n\nasync function isDirectory(filePath: string): Promise<boolean> {\n try {\n const stat = await fs.stat(filePath)\n return stat.isDirectory()\n } catch {\n return false\n }\n}\n\nfunction isDirectorySync(filePath: string): boolean {\n try {\n const stat = fsSync.statSync(filePath)\n return stat.isDirectory()\n } catch {\n return false\n }\n}\n\nasync function normalizeOptions(\n rawOptions: any,\n filePath: string,\n defaultTestResultsDir: string | undefined,\n): Promise<CoverageHarnessOptions> {\n const options = { ...rawOptions }\n const configDir = path.dirname(filePath)\n const rootDir = path.resolve(configDir, \"..\")\n\n const collectCoverageFrom = await resolveCollectCoverageFrom(options.collectCoverageFrom, rootDir)\n\n return {\n rootDir,\n collectCoverageFrom,\n testResultsDir: options.testResultsDir ?? defaultTestResultsDir ?? \"test-results\",\n coverageReportSubdir: options.coverageReportSubdir ?? \"coverage\",\n coverageFileName: options.coverageFileName ?? \"v8-coverage.json\",\n includeAllFiles: options.includeAllFiles,\n thresholds: options.thresholds ?? {},\n }\n}\n\nfunction normalizeOptionsSync(\n rawOptions: any,\n filePath: string,\n defaultTestResultsDir: string | undefined,\n): CoverageHarnessOptions {\n const options = { ...rawOptions }\n const configDir = path.dirname(filePath)\n const rootDir = path.resolve(configDir, \"..\")\n\n const collectCoverageFrom = resolveCollectCoverageFromSync(options.collectCoverageFrom, rootDir)\n\n return {\n rootDir,\n collectCoverageFrom,\n testResultsDir: options.testResultsDir ?? defaultTestResultsDir ?? \"test-results\",\n coverageReportSubdir: options.coverageReportSubdir ?? \"coverage\",\n coverageFileName: options.coverageFileName ?? \"v8-coverage.json\",\n includeAllFiles: options.includeAllFiles,\n thresholds: options.thresholds ?? {},\n }\n}\n\nexport { DEFAULT_COVERAGE_CANDIDATES }\n"],"names":["require","fs","fsSync"],"mappings":"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"}
1
+ {"version":3,"file":"config-loader.js","sources":["../../src/coverage/config-loader.ts"],"sourcesContent":["import fs from \"node:fs/promises\"\nimport fsSync from \"node:fs\"\nimport path from \"node:path\"\nimport os from \"node:os\"\nimport crypto from \"node:crypto\"\nimport { createRequire } from \"node:module\"\nimport { pathToFileURL } from \"node:url\"\n\nimport { build, buildSync } from \"esbuild\"\n\nimport type { CoverageHarnessOptions } from \"./types\"\n\n\nconst require = createRequire(import.meta.url)\n\ntype LoadCoverageOptionsArgs = {\n optional?: boolean\n candidates?: string[]\n}\n\nconst DEFAULT_COVERAGE_CANDIDATES = [\n \"spec/coverage.config.ts\",\n \"spec/coverage.config.js\",\n \"spec/coverage.config.mjs\",\n \"spec/coverage.config.cjs\",\n \"spec/coverage.config.json\",\n]\n\nconst LEGACY_COVERAGE_CANDIDATES = [\n \"spec/coverage.ts\",\n \"spec/coverage.js\",\n \"spec/coverage.mjs\",\n \"spec/coverage.cjs\",\n \"spec/coverage.json\",\n]\n\nexport async function loadCoverageOptions({\n optional = false,\n candidates = DEFAULT_COVERAGE_CANDIDATES,\n}: LoadCoverageOptionsArgs = {}): Promise<CoverageHarnessOptions | null> {\n const projectRoot = process.cwd()\n const legacy = await findCoverageFile(projectRoot, LEGACY_COVERAGE_CANDIDATES)\n if (legacy) {\n const ext = path.extname(legacy)\n const suggested = path.join(\"spec\", `coverage.config${ext}`)\n throw new Error(\n `Legacy coverage config detected (${path.relative(projectRoot, legacy)}). Rename it to ${suggested}.`,\n )\n }\n\n const resolved = await findCoverageFile(projectRoot, candidates)\n\n if (!resolved) {\n if (optional) {\n return null\n }\n throw new Error(\n \"Coverage config not found. Create `spec/coverage.config.{ts,js,json}` with your coverage settings.\",\n )\n }\n\n const raw = await importCoverageModule(resolved)\n if (!raw || typeof raw !== \"object\") {\n throw new Error(`Coverage config at ${resolved} must export an object.`)\n }\n\n return await normalizeOptions(raw, resolved)\n}\n\nexport function loadCoverageOptionsSync({\n optional = false,\n candidates = DEFAULT_COVERAGE_CANDIDATES,\n}: LoadCoverageOptionsArgs = {}): CoverageHarnessOptions | null {\n const projectRoot = process.cwd()\n const legacy = findCoverageFileSync(projectRoot, LEGACY_COVERAGE_CANDIDATES)\n if (legacy) {\n const ext = path.extname(legacy)\n const suggested = path.join(\"spec\", `coverage.config${ext}`)\n throw new Error(\n `Legacy coverage config detected (${path.relative(projectRoot, legacy)}). Rename it to ${suggested}.`,\n )\n }\n\n const resolved = findCoverageFileSync(projectRoot, candidates)\n\n if (!resolved) {\n if (optional) {\n return null\n }\n throw new Error(\n \"Coverage config not found. Create `spec/coverage.config.{ts,js,json}` with your coverage settings.\",\n )\n }\n\n const raw = importCoverageModuleSync(resolved)\n if (!raw || typeof raw !== \"object\") {\n throw new Error(`Coverage config at ${resolved} must export an object.`)\n }\n\n return normalizeOptionsSync(raw, resolved)\n}\n\nasync function findCoverageFile(root: string, candidates: string[]): Promise<string | null> {\n for (const relative of candidates) {\n const candidate = path.resolve(root, relative)\n try {\n await fs.access(candidate)\n return candidate\n } catch {\n // continue\n }\n }\n return null\n}\n\nfunction findCoverageFileSync(root: string, candidates: string[]): string | null {\n for (const relative of candidates) {\n const candidate = path.resolve(root, relative)\n try {\n fsSync.accessSync(candidate)\n return candidate\n } catch {\n // continue\n }\n }\n return null\n}\n\nasync function importCoverageModule(filePath: string): Promise<unknown> {\n const ext = path.extname(filePath)\n\n if (ext === \".json\") {\n const raw = await fs.readFile(filePath, \"utf8\")\n return JSON.parse(raw)\n }\n\n if (ext === \".ts\") {\n const compiledUrl = await compileTsModule(filePath)\n return loadModule(compiledUrl)\n }\n\n const moduleUrl = pathToFileURL(filePath).href\n return loadModule(moduleUrl)\n}\n\nfunction importCoverageModuleSync(filePath: string): unknown {\n const ext = path.extname(filePath)\n\n if (ext === \".json\") {\n const raw = fsSync.readFileSync(filePath, \"utf8\")\n return JSON.parse(raw)\n }\n\n if (ext === \".cjs\") {\n return loadModuleSync(filePath)\n }\n\n const compiledPath = compileCjsModuleSync(filePath)\n return loadModuleSync(compiledPath)\n}\n\nasync function compileTsModule(filePath: string): Promise<string> {\n const stat = await fs.stat(filePath)\n const hash = crypto\n .createHash(\"sha1\")\n .update(filePath)\n .update(String(stat.mtimeMs))\n .digest(\"hex\")\n\n const outDir = path.join(os.tmpdir(), \"rpcbase-test\")\n await fs.mkdir(outDir, { recursive: true })\n const outfile = path.join(outDir, `coverage-${hash}.mjs`)\n\n await build({\n entryPoints: [filePath],\n outfile,\n platform: \"node\",\n format: \"esm\",\n bundle: false,\n sourcemap: \"inline\",\n logLevel: \"silent\",\n })\n\n return pathToFileURL(outfile).href\n}\n\nfunction compileCjsModuleSync(filePath: string): string {\n const stat = fsSync.statSync(filePath)\n const hash = crypto\n .createHash(\"sha1\")\n .update(filePath)\n .update(String(stat.mtimeMs))\n .digest(\"hex\")\n\n const outDir = path.join(os.tmpdir(), \"rpcbase-test\")\n fsSync.mkdirSync(outDir, { recursive: true })\n const outfile = path.join(outDir, `coverage-${hash}.cjs`)\n\n buildSync({\n entryPoints: [filePath],\n outfile,\n platform: \"node\",\n format: \"cjs\",\n bundle: false,\n sourcemap: \"inline\",\n logLevel: \"silent\",\n })\n\n return outfile\n}\n\nasync function loadModule(url: string): Promise<unknown> {\n const imported = await import(url)\n if (imported && typeof imported.default === \"object\") {\n return imported.default\n }\n return imported\n}\n\nfunction loadModuleSync(modulePath: string): unknown {\n const imported = require(modulePath)\n if (imported && typeof imported.default === \"object\") {\n return imported.default\n }\n return imported\n}\n\nconst DEFAULT_COLLECT_COVERAGE_EXTENSIONS = \"ts,tsx,js,jsx,mjs,cjs\"\nconst DEFAULT_COLLECT_COVERAGE_TEST_EXCLUDE = `!**/*.test.{${DEFAULT_COLLECT_COVERAGE_EXTENSIONS}}`\n\nasync function resolveCollectCoverageFrom(rawPatterns: unknown, rootDir: string): Promise<string[]> {\n const resolvedRootDir = path.resolve(String(rootDir ?? \"\"))\n\n const normalized = Array.isArray(rawPatterns)\n ? rawPatterns\n .map((pattern) => String(pattern ?? \"\").trim())\n .filter((pattern) => pattern.length > 0)\n : []\n\n const excludes = normalized.filter((pattern) => pattern.startsWith(\"!\"))\n const hasIncludes = normalized.some((pattern) => !pattern.startsWith(\"!\"))\n if (hasIncludes) {\n return withDefaultExcludes(normalized)\n }\n\n const defaults = await inferDefaultCollectCoverageFrom(resolvedRootDir)\n if (defaults.length === 0) {\n throw new Error(\n \"Coverage config: couldn't infer a default `collectCoverageFrom` (src/ directory missing). Provide `collectCoverageFrom` with at least one positive glob pattern.\",\n )\n }\n\n return withDefaultExcludes([...defaults, ...excludes])\n}\n\nfunction resolveCollectCoverageFromSync(rawPatterns: unknown, rootDir: string): string[] {\n const resolvedRootDir = path.resolve(String(rootDir ?? \"\"))\n\n const normalized = Array.isArray(rawPatterns)\n ? rawPatterns\n .map((pattern) => String(pattern ?? \"\").trim())\n .filter((pattern) => pattern.length > 0)\n : []\n\n const excludes = normalized.filter((pattern) => pattern.startsWith(\"!\"))\n const hasIncludes = normalized.some((pattern) => !pattern.startsWith(\"!\"))\n if (hasIncludes) {\n return withDefaultExcludes(normalized)\n }\n\n const defaults = inferDefaultCollectCoverageFromSync(resolvedRootDir)\n if (defaults.length === 0) {\n throw new Error(\n \"Coverage config: couldn't infer a default `collectCoverageFrom` (src/ directory missing). Provide `collectCoverageFrom` with at least one positive glob pattern.\",\n )\n }\n\n return withDefaultExcludes([...defaults, ...excludes])\n}\n\nasync function inferDefaultCollectCoverageFrom(rootDir: string): Promise<string[]> {\n const srcDir = path.join(rootDir, \"src\")\n if (await isDirectory(srcDir)) {\n return [`src/**/*.{${DEFAULT_COLLECT_COVERAGE_EXTENSIONS}}`]\n }\n\n return []\n}\n\nfunction inferDefaultCollectCoverageFromSync(rootDir: string): string[] {\n const srcDir = path.join(rootDir, \"src\")\n if (isDirectorySync(srcDir)) {\n return [`src/**/*.{${DEFAULT_COLLECT_COVERAGE_EXTENSIONS}}`]\n }\n\n return []\n}\n\nfunction withDefaultExcludes(patterns: string[]): string[] {\n if (!Array.isArray(patterns) || patterns.length === 0) {\n return patterns\n }\n\n const hasTestExclude = patterns.some((pattern) => {\n const raw = String(pattern ?? \"\")\n if (!raw.startsWith(\"!\")) {\n return false\n }\n return /\\.test(?:\\.|\\{|$)/.test(raw.slice(1))\n })\n if (hasTestExclude) {\n return patterns\n }\n\n return [...patterns, DEFAULT_COLLECT_COVERAGE_TEST_EXCLUDE]\n}\n\nasync function isDirectory(filePath: string): Promise<boolean> {\n try {\n const stat = await fs.stat(filePath)\n return stat.isDirectory()\n } catch {\n return false\n }\n}\n\nfunction isDirectorySync(filePath: string): boolean {\n try {\n const stat = fsSync.statSync(filePath)\n return stat.isDirectory()\n } catch {\n return false\n }\n}\n\nasync function normalizeOptions(\n rawOptions: any,\n filePath: string,\n): Promise<CoverageHarnessOptions> {\n const options = { ...rawOptions }\n const configDir = path.dirname(filePath)\n const rootDir = path.resolve(configDir, \"..\")\n\n const collectCoverageFrom = await resolveCollectCoverageFrom(options.collectCoverageFrom, rootDir)\n\n return {\n rootDir,\n collectCoverageFrom,\n coverageFileName: options.coverageFileName ?? \"v8-coverage.json\",\n includeAllFiles: options.includeAllFiles,\n thresholds: options.thresholds ?? {},\n }\n}\n\nfunction normalizeOptionsSync(\n rawOptions: any,\n filePath: string,\n): CoverageHarnessOptions {\n const options = { ...rawOptions }\n const configDir = path.dirname(filePath)\n const rootDir = path.resolve(configDir, \"..\")\n\n const collectCoverageFrom = resolveCollectCoverageFromSync(options.collectCoverageFrom, rootDir)\n\n return {\n rootDir,\n collectCoverageFrom,\n coverageFileName: options.coverageFileName ?? \"v8-coverage.json\",\n includeAllFiles: options.includeAllFiles,\n thresholds: options.thresholds ?? {},\n }\n}\n\nexport { DEFAULT_COVERAGE_CANDIDATES }\n"],"names":["require","fs","fsSync"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/coverage/config.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,sBAAsB,EAA8F,MAAM,SAAS,CAAA;AAyBjK,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,sBAAsB,GAAG,cAAc,CAuCpF"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/coverage/config.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,sBAAsB,EAA8F,MAAM,SAAS,CAAA;AAajK,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,sBAAsB,GAAG,cAAc,CAuCpF"}
@@ -7,15 +7,6 @@ const DEFAULT_THRESHOLDS = {
7
7
  };
8
8
  const THRESHOLD_KEYS = Object.keys(DEFAULT_THRESHOLDS);
9
9
  const THRESHOLD_KEY_SET = new Set(THRESHOLD_KEYS);
10
- function resolveDir(root, target, fallback) {
11
- if (!target) {
12
- return path.resolve(root, fallback);
13
- }
14
- if (path.isAbsolute(target)) {
15
- return target;
16
- }
17
- return path.resolve(root, target);
18
- }
19
10
  function createCoverageConfig(options) {
20
11
  const { rootDir } = options;
21
12
  if (!rootDir) {
@@ -27,8 +18,8 @@ function createCoverageConfig(options) {
27
18
  if (collectCoverageFrom.length === 0) {
28
19
  throw new Error("createCoverageConfig requires a collectCoverageFrom option");
29
20
  }
30
- const testResultsRoot = resolveDir(resolvedRootDir, options.testResultsDir, "test-results");
31
- const coverageReportDir = resolveDir(testResultsRoot, options.coverageReportSubdir, "coverage");
21
+ const testResultsRoot = path.join(resolvedRootDir, "build", "coverage");
22
+ const coverageReportDir = path.join(testResultsRoot, "report");
32
23
  const coverageFileName = options.coverageFileName ?? "v8-coverage.json";
33
24
  const disabledEnvVar = options.disabledEnvVar ?? "RB_DISABLE_COVERAGE";
34
25
  const coverageEnabled = process.env[disabledEnvVar] !== "1";
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sources":["../../src/coverage/config.ts"],"sourcesContent":["import path from \"node:path\"\n\nimport type { CoverageConfig, CoverageHarnessOptions, CoverageThresholdMap, CoverageThresholdOption, CoverageThresholdTarget, CoverageThresholds } from \"./types\"\n\n\nconst DEFAULT_THRESHOLDS = {\n branches: 60,\n functions: 75,\n lines: 75,\n statements: 75,\n}\n\nconst THRESHOLD_KEYS = Object.keys(DEFAULT_THRESHOLDS) as Array<keyof CoverageThresholds>\nconst THRESHOLD_KEY_SET = new Set<string>(THRESHOLD_KEYS as string[])\n\nfunction resolveDir(root: string, target: string | undefined, fallback: string): string {\n if (!target) {\n return path.resolve(root, fallback)\n }\n\n if (path.isAbsolute(target)) {\n return target\n }\n\n return path.resolve(root, target)\n}\n\nexport function createCoverageConfig(options: CoverageHarnessOptions): CoverageConfig {\n const { rootDir } = options as CoverageHarnessOptions\n if (!rootDir) {\n throw new Error(\"createCoverageConfig requires a rootDir\")\n }\n\n const resolvedRootDir = path.resolve(rootDir)\n const includeAllFiles = options.includeAllFiles !== false\n\n const collectCoverageFrom = Array.isArray(options.collectCoverageFrom)\n ? options.collectCoverageFrom\n .map((pattern) => String(pattern ?? \"\").trim())\n .filter((pattern) => pattern.length > 0)\n : []\n\n if (collectCoverageFrom.length === 0) {\n throw new Error(\"createCoverageConfig requires a collectCoverageFrom option\")\n }\n\n const testResultsRoot = resolveDir(resolvedRootDir, options.testResultsDir, \"test-results\")\n const coverageReportDir = resolveDir(testResultsRoot, options.coverageReportSubdir, \"coverage\")\n const coverageFileName = options.coverageFileName ?? \"v8-coverage.json\"\n const disabledEnvVar = options.disabledEnvVar ?? \"RB_DISABLE_COVERAGE\"\n const coverageEnabled = process.env[disabledEnvVar] !== \"1\"\n\n const { global: thresholds, targets: thresholdTargets } = normalizeThresholdOptions(options.thresholds)\n\n return {\n rootDir: resolvedRootDir,\n collectCoverageFrom,\n testResultsRoot,\n coverageReportDir,\n coverageFileName,\n thresholds,\n thresholdTargets,\n coverageEnabled,\n disabledEnvVar,\n includeAllFiles,\n }\n}\n\nfunction normalizeThresholdOptions(rawThresholds: CoverageThresholdOption | undefined): {\n global: CoverageThresholds\n targets: CoverageThresholdTarget[]\n} {\n const globalThresholds: CoverageThresholds = { ...DEFAULT_THRESHOLDS }\n const targets: CoverageThresholdTarget[] = []\n\n if (!isPlainObject(rawThresholds)) {\n return { global: globalThresholds, targets }\n }\n\n const thresholdMap = rawThresholds as CoverageThresholdMap\n\n for (const key of THRESHOLD_KEYS) {\n const value = thresholdMap[key]\n if (isThresholdValue(value)) {\n globalThresholds[key] = value\n }\n }\n\n if (Object.prototype.hasOwnProperty.call(thresholdMap, \"global\")) {\n if (!isPlainObject(thresholdMap.global)) {\n throw new Error(\"coverage thresholds: the `global` override must be an object of metric values\")\n }\n Object.assign(globalThresholds, pickThresholdOverrides(thresholdMap.global))\n }\n\n for (const [pattern, overrides] of Object.entries(thresholdMap)) {\n if (pattern === \"global\" || THRESHOLD_KEY_SET.has(pattern)) {\n continue\n }\n\n if (!isPlainObject(overrides)) {\n throw new Error(\n `coverage thresholds: override for \"${pattern}\" must be an object containing coverage metrics`,\n )\n }\n\n targets.push({\n id: pattern,\n pattern,\n thresholds: {\n ...globalThresholds,\n ...pickThresholdOverrides(overrides),\n },\n })\n }\n\n return { global: globalThresholds, targets }\n}\n\nfunction pickThresholdOverrides(source: unknown): Partial<CoverageThresholds> {\n const overrides: Partial<CoverageThresholds> = {}\n if (!isPlainObject(source)) {\n return overrides\n }\n\n for (const key of THRESHOLD_KEYS) {\n const value = (source as any)[key]\n if (isThresholdValue(value)) {\n overrides[key] = value\n }\n }\n\n return overrides\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === \"object\" && !Array.isArray(value)\n}\n\nfunction isThresholdValue(value: unknown): value is number {\n return typeof value === \"number\" && Number.isFinite(value)\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.js","sources":["../../src/coverage/config.ts"],"sourcesContent":["import path from \"node:path\"\n\nimport type { CoverageConfig, CoverageHarnessOptions, CoverageThresholdMap, CoverageThresholdOption, CoverageThresholdTarget, CoverageThresholds } from \"./types\"\n\n\nconst DEFAULT_THRESHOLDS = {\n branches: 60,\n functions: 75,\n lines: 75,\n statements: 75,\n}\n\nconst THRESHOLD_KEYS = Object.keys(DEFAULT_THRESHOLDS) as Array<keyof CoverageThresholds>\nconst THRESHOLD_KEY_SET = new Set<string>(THRESHOLD_KEYS as string[])\n\nexport function createCoverageConfig(options: CoverageHarnessOptions): CoverageConfig {\n const { rootDir } = options as CoverageHarnessOptions\n if (!rootDir) {\n throw new Error(\"createCoverageConfig requires a rootDir\")\n }\n\n const resolvedRootDir = path.resolve(rootDir)\n const includeAllFiles = options.includeAllFiles !== false\n\n const collectCoverageFrom = Array.isArray(options.collectCoverageFrom)\n ? options.collectCoverageFrom\n .map((pattern) => String(pattern ?? \"\").trim())\n .filter((pattern) => pattern.length > 0)\n : []\n\n if (collectCoverageFrom.length === 0) {\n throw new Error(\"createCoverageConfig requires a collectCoverageFrom option\")\n }\n\n const testResultsRoot = path.join(resolvedRootDir, \"build\", \"coverage\")\n const coverageReportDir = path.join(testResultsRoot, \"report\")\n const coverageFileName = options.coverageFileName ?? \"v8-coverage.json\"\n const disabledEnvVar = options.disabledEnvVar ?? \"RB_DISABLE_COVERAGE\"\n const coverageEnabled = process.env[disabledEnvVar] !== \"1\"\n\n const { global: thresholds, targets: thresholdTargets } = normalizeThresholdOptions(options.thresholds)\n\n return {\n rootDir: resolvedRootDir,\n collectCoverageFrom,\n testResultsRoot,\n coverageReportDir,\n coverageFileName,\n thresholds,\n thresholdTargets,\n coverageEnabled,\n disabledEnvVar,\n includeAllFiles,\n }\n}\n\nfunction normalizeThresholdOptions(rawThresholds: CoverageThresholdOption | undefined): {\n global: CoverageThresholds\n targets: CoverageThresholdTarget[]\n} {\n const globalThresholds: CoverageThresholds = { ...DEFAULT_THRESHOLDS }\n const targets: CoverageThresholdTarget[] = []\n\n if (!isPlainObject(rawThresholds)) {\n return { global: globalThresholds, targets }\n }\n\n const thresholdMap = rawThresholds as CoverageThresholdMap\n\n for (const key of THRESHOLD_KEYS) {\n const value = thresholdMap[key]\n if (isThresholdValue(value)) {\n globalThresholds[key] = value\n }\n }\n\n if (Object.prototype.hasOwnProperty.call(thresholdMap, \"global\")) {\n if (!isPlainObject(thresholdMap.global)) {\n throw new Error(\"coverage thresholds: the `global` override must be an object of metric values\")\n }\n Object.assign(globalThresholds, pickThresholdOverrides(thresholdMap.global))\n }\n\n for (const [pattern, overrides] of Object.entries(thresholdMap)) {\n if (pattern === \"global\" || THRESHOLD_KEY_SET.has(pattern)) {\n continue\n }\n\n if (!isPlainObject(overrides)) {\n throw new Error(\n `coverage thresholds: override for \"${pattern}\" must be an object containing coverage metrics`,\n )\n }\n\n targets.push({\n id: pattern,\n pattern,\n thresholds: {\n ...globalThresholds,\n ...pickThresholdOverrides(overrides),\n },\n })\n }\n\n return { global: globalThresholds, targets }\n}\n\nfunction pickThresholdOverrides(source: unknown): Partial<CoverageThresholds> {\n const overrides: Partial<CoverageThresholds> = {}\n if (!isPlainObject(source)) {\n return overrides\n }\n\n for (const key of THRESHOLD_KEYS) {\n const value = (source as any)[key]\n if (isThresholdValue(value)) {\n overrides[key] = value\n }\n }\n\n return overrides\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === \"object\" && !Array.isArray(value)\n}\n\nfunction isThresholdValue(value: unknown): value is number {\n return typeof value === \"number\" && Number.isFinite(value)\n}\n"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
1
  import { CoverageConfig } from './types';
2
- export declare function findCoverageFiles(config: CoverageConfig, root?: string): Promise<string[]>;
3
- export declare function removeCoverageFiles(config: CoverageConfig, root?: string): Promise<void>;
2
+ export declare function findCoverageFiles(config: CoverageConfig, root?: string | string[]): Promise<string[]>;
3
+ export declare function removeCoverageFiles(config: CoverageConfig, root?: string | string[]): Promise<void>;
4
4
  //# sourceMappingURL=files.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"files.d.ts","sourceRoot":"","sources":["../../src/coverage/files.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAG7C,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,cAAc,EAAE,IAAI,SAAyB,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CA4BhH;AAED,wBAAsB,mBAAmB,CAAC,MAAM,EAAE,cAAc,EAAE,IAAI,SAAyB,GAAG,OAAO,CAAC,IAAI,CAAC,CAoB9G"}
1
+ {"version":3,"file":"files.d.ts","sourceRoot":"","sources":["../../src/coverage/files.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAe7C,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,cAAc,EACtB,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GACvB,OAAO,CAAC,MAAM,EAAE,CAAC,CAgCnB;AAED,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,cAAc,EACtB,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GACvB,OAAO,CAAC,IAAI,CAAC,CAwBf"}
@@ -1,6 +1,17 @@
1
1
  import fs from "node:fs/promises";
2
2
  import path from "node:path";
3
- async function findCoverageFiles(config, root = config.testResultsRoot) {
3
+ function resolveCoverageRoots(config) {
4
+ const buildDir = path.join(config.rootDir, "build");
5
+ const roots = [
6
+ path.join(buildDir, "playwright", "coverage"),
7
+ path.join(buildDir, "vitest", "coverage"),
8
+ path.join(config.testResultsRoot, "playwright"),
9
+ path.join(config.testResultsRoot, "vitest")
10
+ ];
11
+ return Array.from(new Set(roots.map((root) => path.resolve(root))));
12
+ }
13
+ async function findCoverageFiles(config, root) {
14
+ const roots = root === void 0 ? resolveCoverageRoots(config) : Array.isArray(root) ? root : [root];
4
15
  const files = [];
5
16
  async function walk(current) {
6
17
  const entries = await fs.readdir(current, { withFileTypes: true });
@@ -15,18 +26,21 @@ async function findCoverageFiles(config, root = config.testResultsRoot) {
15
26
  })
16
27
  );
17
28
  }
18
- try {
19
- const stats = await fs.stat(root);
20
- if (!stats.isDirectory()) {
21
- return [];
29
+ for (const root2 of roots) {
30
+ try {
31
+ const stats = await fs.stat(root2);
32
+ if (!stats.isDirectory()) {
33
+ continue;
34
+ }
35
+ } catch {
36
+ continue;
22
37
  }
23
- } catch {
24
- return [];
38
+ await walk(root2);
25
39
  }
26
- await walk(root);
27
40
  return files.sort();
28
41
  }
29
- async function removeCoverageFiles(config, root = config.testResultsRoot) {
42
+ async function removeCoverageFiles(config, root) {
43
+ const roots = root === void 0 ? resolveCoverageRoots(config) : Array.isArray(root) ? root : [root];
30
44
  async function walk(current) {
31
45
  const entries = await fs.readdir(current, { withFileTypes: true });
32
46
  await Promise.all(
@@ -40,9 +54,11 @@ async function removeCoverageFiles(config, root = config.testResultsRoot) {
40
54
  })
41
55
  );
42
56
  }
43
- try {
44
- await walk(root);
45
- } catch {
57
+ for (const root2 of roots) {
58
+ try {
59
+ await walk(root2);
60
+ } catch {
61
+ }
46
62
  }
47
63
  }
48
64
  export {
@@ -1 +1 @@
1
- {"version":3,"file":"files.js","sources":["../../src/coverage/files.ts"],"sourcesContent":["import fs from \"node:fs/promises\"\nimport path from \"node:path\"\n\nimport type { CoverageConfig } from \"./types\"\n\n\nexport async function findCoverageFiles(config: CoverageConfig, root = config.testResultsRoot): Promise<string[]> {\n const files: string[] = []\n\n async function walk(current: string): Promise<void> {\n const entries = await fs.readdir(current, { withFileTypes: true })\n await Promise.all(\n entries.map(async (entry) => {\n const entryPath = path.join(current, entry.name)\n if (entry.isDirectory()) {\n await walk(entryPath)\n } else if (entry.isFile() && entry.name === config.coverageFileName) {\n files.push(entryPath)\n }\n }),\n )\n }\n\n try {\n const stats = await fs.stat(root)\n if (!stats.isDirectory()) {\n return []\n }\n } catch {\n return []\n }\n\n await walk(root)\n return files.sort()\n}\n\nexport async function removeCoverageFiles(config: CoverageConfig, root = config.testResultsRoot): Promise<void> {\n async function walk(current: string): Promise<void> {\n const entries = await fs.readdir(current, { withFileTypes: true })\n await Promise.all(\n entries.map(async (entry) => {\n const entryPath = path.join(current, entry.name)\n if (entry.isDirectory()) {\n await walk(entryPath)\n } else if (entry.isFile() && entry.name === config.coverageFileName) {\n await fs.rm(entryPath, { force: true })\n }\n }),\n )\n }\n\n try {\n await walk(root)\n } catch {\n // ignore cleanup errors\n }\n}\n"],"names":[],"mappings":";;AAMA,eAAsB,kBAAkB,QAAwB,OAAO,OAAO,iBAAoC;AAChH,QAAM,QAAkB,CAAA;AAExB,iBAAe,KAAK,SAAgC;AAClD,UAAM,UAAU,MAAM,GAAG,QAAQ,SAAS,EAAE,eAAe,MAAM;AACjE,UAAM,QAAQ;AAAA,MACZ,QAAQ,IAAI,OAAO,UAAU;AAC3B,cAAM,YAAY,KAAK,KAAK,SAAS,MAAM,IAAI;AAC/C,YAAI,MAAM,eAAe;AACvB,gBAAM,KAAK,SAAS;AAAA,QACtB,WAAW,MAAM,OAAA,KAAY,MAAM,SAAS,OAAO,kBAAkB;AACnE,gBAAM,KAAK,SAAS;AAAA,QACtB;AAAA,MACF,CAAC;AAAA,IAAA;AAAA,EAEL;AAEA,MAAI;AACF,UAAM,QAAQ,MAAM,GAAG,KAAK,IAAI;AAChC,QAAI,CAAC,MAAM,eAAe;AACxB,aAAO,CAAA;AAAA,IACT;AAAA,EACF,QAAQ;AACN,WAAO,CAAA;AAAA,EACT;AAEA,QAAM,KAAK,IAAI;AACf,SAAO,MAAM,KAAA;AACf;AAEA,eAAsB,oBAAoB,QAAwB,OAAO,OAAO,iBAAgC;AAC9G,iBAAe,KAAK,SAAgC;AAClD,UAAM,UAAU,MAAM,GAAG,QAAQ,SAAS,EAAE,eAAe,MAAM;AACjE,UAAM,QAAQ;AAAA,MACZ,QAAQ,IAAI,OAAO,UAAU;AAC3B,cAAM,YAAY,KAAK,KAAK,SAAS,MAAM,IAAI;AAC/C,YAAI,MAAM,eAAe;AACvB,gBAAM,KAAK,SAAS;AAAA,QACtB,WAAW,MAAM,OAAA,KAAY,MAAM,SAAS,OAAO,kBAAkB;AACnE,gBAAM,GAAG,GAAG,WAAW,EAAE,OAAO,MAAM;AAAA,QACxC;AAAA,MACF,CAAC;AAAA,IAAA;AAAA,EAEL;AAEA,MAAI;AACF,UAAM,KAAK,IAAI;AAAA,EACjB,QAAQ;AAAA,EAER;AACF;"}
1
+ {"version":3,"file":"files.js","sources":["../../src/coverage/files.ts"],"sourcesContent":["import fs from \"node:fs/promises\"\nimport path from \"node:path\"\n\nimport type { CoverageConfig } from \"./types\"\n\n\nfunction resolveCoverageRoots(config: CoverageConfig): string[] {\n const buildDir = path.join(config.rootDir, \"build\")\n const roots = [\n path.join(buildDir, \"playwright\", \"coverage\"),\n path.join(buildDir, \"vitest\", \"coverage\"),\n path.join(config.testResultsRoot, \"playwright\"),\n path.join(config.testResultsRoot, \"vitest\"),\n ]\n\n return Array.from(new Set(roots.map((root) => path.resolve(root))))\n}\n\nexport async function findCoverageFiles(\n config: CoverageConfig,\n root?: string | string[],\n): Promise<string[]> {\n const roots = root === undefined ? resolveCoverageRoots(config) : Array.isArray(root) ? root : [root]\n const files: string[] = []\n\n async function walk(current: string): Promise<void> {\n const entries = await fs.readdir(current, { withFileTypes: true })\n await Promise.all(\n entries.map(async (entry) => {\n const entryPath = path.join(current, entry.name)\n if (entry.isDirectory()) {\n await walk(entryPath)\n } else if (entry.isFile() && entry.name === config.coverageFileName) {\n files.push(entryPath)\n }\n }),\n )\n }\n\n for (const root of roots) {\n try {\n const stats = await fs.stat(root)\n if (!stats.isDirectory()) {\n continue\n }\n } catch {\n continue\n }\n\n await walk(root)\n }\n\n return files.sort()\n}\n\nexport async function removeCoverageFiles(\n config: CoverageConfig,\n root?: string | string[],\n): Promise<void> {\n const roots = root === undefined ? resolveCoverageRoots(config) : Array.isArray(root) ? root : [root]\n\n async function walk(current: string): Promise<void> {\n const entries = await fs.readdir(current, { withFileTypes: true })\n await Promise.all(\n entries.map(async (entry) => {\n const entryPath = path.join(current, entry.name)\n if (entry.isDirectory()) {\n await walk(entryPath)\n } else if (entry.isFile() && entry.name === config.coverageFileName) {\n await fs.rm(entryPath, { force: true })\n }\n }),\n )\n }\n\n for (const root of roots) {\n try {\n await walk(root)\n } catch {\n // ignore cleanup errors\n }\n }\n}\n"],"names":["root"],"mappings":";;AAMA,SAAS,qBAAqB,QAAkC;AAC9D,QAAM,WAAW,KAAK,KAAK,OAAO,SAAS,OAAO;AAClD,QAAM,QAAQ;AAAA,IACZ,KAAK,KAAK,UAAU,cAAc,UAAU;AAAA,IAC5C,KAAK,KAAK,UAAU,UAAU,UAAU;AAAA,IACxC,KAAK,KAAK,OAAO,iBAAiB,YAAY;AAAA,IAC9C,KAAK,KAAK,OAAO,iBAAiB,QAAQ;AAAA,EAAA;AAG5C,SAAO,MAAM,KAAK,IAAI,IAAI,MAAM,IAAI,CAAC,SAAS,KAAK,QAAQ,IAAI,CAAC,CAAC,CAAC;AACpE;AAEA,eAAsB,kBACpB,QACA,MACmB;AACnB,QAAM,QAAQ,SAAS,SAAY,qBAAqB,MAAM,IAAI,MAAM,QAAQ,IAAI,IAAI,OAAO,CAAC,IAAI;AACpG,QAAM,QAAkB,CAAA;AAExB,iBAAe,KAAK,SAAgC;AAClD,UAAM,UAAU,MAAM,GAAG,QAAQ,SAAS,EAAE,eAAe,MAAM;AACjE,UAAM,QAAQ;AAAA,MACZ,QAAQ,IAAI,OAAO,UAAU;AAC3B,cAAM,YAAY,KAAK,KAAK,SAAS,MAAM,IAAI;AAC/C,YAAI,MAAM,eAAe;AACvB,gBAAM,KAAK,SAAS;AAAA,QACtB,WAAW,MAAM,OAAA,KAAY,MAAM,SAAS,OAAO,kBAAkB;AACnE,gBAAM,KAAK,SAAS;AAAA,QACtB;AAAA,MACF,CAAC;AAAA,IAAA;AAAA,EAEL;AAEA,aAAWA,SAAQ,OAAO;AACxB,QAAI;AACF,YAAM,QAAQ,MAAM,GAAG,KAAKA,KAAI;AAChC,UAAI,CAAC,MAAM,eAAe;AACxB;AAAA,MACF;AAAA,IACF,QAAQ;AACN;AAAA,IACF;AAEA,UAAM,KAAKA,KAAI;AAAA,EACjB;AAEA,SAAO,MAAM,KAAA;AACf;AAEA,eAAsB,oBACpB,QACA,MACe;AACf,QAAM,QAAQ,SAAS,SAAY,qBAAqB,MAAM,IAAI,MAAM,QAAQ,IAAI,IAAI,OAAO,CAAC,IAAI;AAEpG,iBAAe,KAAK,SAAgC;AAClD,UAAM,UAAU,MAAM,GAAG,QAAQ,SAAS,EAAE,eAAe,MAAM;AACjE,UAAM,QAAQ;AAAA,MACZ,QAAQ,IAAI,OAAO,UAAU;AAC3B,cAAM,YAAY,KAAK,KAAK,SAAS,MAAM,IAAI;AAC/C,YAAI,MAAM,eAAe;AACvB,gBAAM,KAAK,SAAS;AAAA,QACtB,WAAW,MAAM,OAAA,KAAY,MAAM,SAAS,OAAO,kBAAkB;AACnE,gBAAM,GAAG,GAAG,WAAW,EAAE,OAAO,MAAM;AAAA,QACxC;AAAA,MACF,CAAC;AAAA,IAAA;AAAA,EAEL;AAEA,aAAWA,SAAQ,OAAO;AACxB,QAAI;AACF,YAAM,KAAKA,KAAI;AAAA,IACjB,QAAQ;AAAA,IAER;AAAA,EACF;AACF;"}
@@ -17,8 +17,6 @@ export type CoverageThresholdTarget = {
17
17
  export type CoverageHarnessOptions = {
18
18
  rootDir: string;
19
19
  collectCoverageFrom: string[];
20
- testResultsDir?: string;
21
- coverageReportSubdir?: string;
22
20
  coverageFileName?: string;
23
21
  includeAllFiles?: boolean;
24
22
  thresholds?: CoverageThresholdOption;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/coverage/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;IACb,UAAU,EAAE,MAAM,CAAA;CACnB,CAAA;AAED,MAAM,MAAM,oBAAoB,GAAG;IACjC,MAAM,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,CAAA;IACpC,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,GAAG,MAAM,GAAG,SAAS,CAAA;CACpE,CAAA;AAED,MAAM,MAAM,uBAAuB,GAAG,OAAO,CAAC,kBAAkB,CAAC,GAAG,oBAAoB,CAAA;AAExF,MAAM,MAAM,uBAAuB,GAAG;IACpC,EAAE,EAAE,MAAM,CAAA;IACV,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,kBAAkB,CAAA;CAC/B,CAAA;AAED,MAAM,MAAM,sBAAsB,GAAG;IACnC,OAAO,EAAE,MAAM,CAAA;IACf,mBAAmB,EAAE,MAAM,EAAE,CAAA;IAC7B,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,oBAAoB,CAAC,EAAE,MAAM,CAAA;IAC7B,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,UAAU,CAAC,EAAE,uBAAuB,CAAA;IACpC,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,OAAO,EAAE,MAAM,CAAA;IACf,mBAAmB,EAAE,MAAM,EAAE,CAAA;IAC7B,eAAe,EAAE,MAAM,CAAA;IACvB,iBAAiB,EAAE,MAAM,CAAA;IACzB,gBAAgB,EAAE,MAAM,CAAA;IACxB,eAAe,EAAE,OAAO,CAAA;IACxB,UAAU,EAAE,kBAAkB,CAAA;IAC9B,gBAAgB,EAAE,uBAAuB,EAAE,CAAA;IAC3C,eAAe,EAAE,OAAO,CAAA;IACxB,cAAc,EAAE,MAAM,CAAA;CACvB,CAAA;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,EAAE,cAAc,CAAA;IACtB,WAAW,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAChC,UAAU,CAAC,CAAC,SAAS;QAAE,MAAM,EAAE,CAAC,QAAQ,EAAE,GAAG,KAAK,OAAO,CAAA;KAAE,EAAE,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAA;IAC5E,aAAa,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA;CACpD,CAAA"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/coverage/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;IACb,UAAU,EAAE,MAAM,CAAA;CACnB,CAAA;AAED,MAAM,MAAM,oBAAoB,GAAG;IACjC,MAAM,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,CAAA;IACpC,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,GAAG,MAAM,GAAG,SAAS,CAAA;CACpE,CAAA;AAED,MAAM,MAAM,uBAAuB,GAAG,OAAO,CAAC,kBAAkB,CAAC,GAAG,oBAAoB,CAAA;AAExF,MAAM,MAAM,uBAAuB,GAAG;IACpC,EAAE,EAAE,MAAM,CAAA;IACV,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,kBAAkB,CAAA;CAC/B,CAAA;AAED,MAAM,MAAM,sBAAsB,GAAG;IACnC,OAAO,EAAE,MAAM,CAAA;IACf,mBAAmB,EAAE,MAAM,EAAE,CAAA;IAC7B,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,UAAU,CAAC,EAAE,uBAAuB,CAAA;IACpC,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,OAAO,EAAE,MAAM,CAAA;IACf,mBAAmB,EAAE,MAAM,EAAE,CAAA;IAC7B,eAAe,EAAE,MAAM,CAAA;IACvB,iBAAiB,EAAE,MAAM,CAAA;IACzB,gBAAgB,EAAE,MAAM,CAAA;IACxB,eAAe,EAAE,OAAO,CAAA;IACxB,UAAU,EAAE,kBAAkB,CAAA;IAC9B,gBAAgB,EAAE,uBAAuB,EAAE,CAAA;IAC3C,eAAe,EAAE,OAAO,CAAA;IACxB,cAAc,EAAE,MAAM,CAAA;CACvB,CAAA;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,EAAE,cAAc,CAAA;IACtB,WAAW,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAChC,UAAU,CAAC,CAAC,SAAS;QAAE,MAAM,EAAE,CAAC,QAAQ,EAAE,GAAG,KAAK,OAAO,CAAA;KAAE,EAAE,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAA;IAC5E,aAAa,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA;CACpD,CAAA"}
@@ -48,7 +48,7 @@ async function createCoverageTracker(page, config) {
48
48
  function resolveCoverageOutputFile(config, testInfo) {
49
49
  const projectName = sanitizePathSegment(testInfo.project?.name);
50
50
  const testId = sanitizePathSegment(testInfo.testId);
51
- const outputDir = path.join(config.testResultsRoot, "playwright", projectName, testId);
51
+ const outputDir = path.join(config.rootDir, "build", "playwright", "coverage", projectName, testId);
52
52
  return path.join(outputDir, config.coverageFileName);
53
53
  }
54
54
  async function collectCoveragePayload(session, scriptMeta, sourceCache, testInfo, config) {
@@ -1 +1 @@
1
- {"version":3,"file":"v8-tracker.js","sources":["../../src/coverage/v8-tracker.ts"],"sourcesContent":["import fs from \"node:fs/promises\"\nimport path from \"node:path\"\n\nimport type { Page, TestInfo } from \"@playwright/test\"\n\nimport { isInsideAnyRoot, resolveCollectCoverageRoots } from \"./collect\"\nimport type { CoverageConfig } from \"./types\"\n\n\nconst VITE_FS_PREFIX = \"/@fs/\"\n\nfunction sanitizePathSegment(input: unknown): string {\n const value = String(input ?? \"\").trim()\n return value.replace(/[^a-zA-Z0-9._-]+/g, \"_\") || \"unknown\"\n}\n\nfunction urlPathLooksLikeFile(pathname: unknown): boolean {\n const base = path.posix.basename(String(pathname ?? \"\"))\n return base.length > 0 && base.includes(\".\")\n}\n\nexport async function createCoverageTracker(\n page: Page,\n config: CoverageConfig,\n): Promise<{ stop: (testInfo: TestInfo) => Promise<void> }> {\n const session = await page.context().newCDPSession(page)\n const scriptMeta = new Map<string, { normalized: { absolutePath: string; relativePath: string } | null; url: string }>()\n const sourceCache = new Map<string, Promise<string>>()\n const scriptRoots = resolveCollectCoverageRoots(config.collectCoverageFrom, config.rootDir)\n\n await session.send(\"Debugger.enable\")\n session.on(\"Debugger.scriptParsed\", (event: any) => {\n if (!event.url) {\n return\n }\n\n const normalized = normalizeScriptUrl(event.url, config)\n const trackable = normalized\n && !isNodeModulesPath(normalized.absolutePath)\n && isInsideAnyRoot(normalized.absolutePath, scriptRoots)\n\n scriptMeta.set(event.scriptId, {\n normalized: trackable ? normalized : null,\n url: event.url,\n })\n })\n\n await session.send(\"Profiler.enable\")\n await session.send(\"Profiler.startPreciseCoverage\", { callCount: false, detailed: true })\n\n return {\n async stop(testInfo: TestInfo) {\n try {\n const payload = await collectCoveragePayload(session, scriptMeta, sourceCache, testInfo, config)\n\n if (payload.scripts.length === 0) {\n return\n }\n\n const outputFile = resolveCoverageOutputFile(config, testInfo)\n await fs.mkdir(path.dirname(outputFile), { recursive: true })\n await fs.writeFile(outputFile, JSON.stringify(payload, null, 2), \"utf8\")\n } finally {\n await shutdownSession(session)\n }\n },\n }\n}\n\nfunction resolveCoverageOutputFile(config: CoverageConfig, testInfo: TestInfo): string {\n const projectName = sanitizePathSegment(testInfo.project?.name)\n const testId = sanitizePathSegment(testInfo.testId)\n const outputDir = path.join(config.testResultsRoot, \"playwright\", projectName, testId)\n return path.join(outputDir, config.coverageFileName)\n}\n\nasync function collectCoveragePayload(\n session: any,\n scriptMeta: Map<string, { normalized: { absolutePath: string; relativePath: string } | null; url: string }>,\n sourceCache: Map<string, Promise<string>>,\n testInfo: TestInfo,\n config: CoverageConfig,\n): Promise<{ testId: string; scripts: any[] }> {\n const { result } = await session.send(\"Profiler.takePreciseCoverage\")\n await session.send(\"Profiler.stopPreciseCoverage\")\n\n const scripts = []\n\n for (const script of result) {\n const meta = scriptMeta.get(script.scriptId)\n if (!meta || !meta.normalized) {\n continue\n }\n\n const source = await resolveScriptSource(session, sourceCache, script.scriptId)\n scripts.push({\n absolutePath: meta.normalized.absolutePath,\n relativePath: meta.normalized.relativePath,\n source,\n functions: script.functions,\n url: meta.url,\n })\n }\n\n return {\n testId: testInfo.titlePath.join(\" › \"),\n scripts,\n }\n}\n\nasync function resolveScriptSource(session: any, cache: Map<string, Promise<string>>, scriptId: string): Promise<string> {\n const cached = cache.get(scriptId)\n if (cached) {\n return cached\n }\n\n const promise = fetchScriptSource(session, scriptId)\n cache.set(scriptId, promise)\n return promise\n}\n\nasync function fetchScriptSource(session: any, scriptId: string): Promise<string> {\n try {\n const sourceResponse = await session.send(\"Debugger.getScriptSource\", { scriptId })\n return sourceResponse?.scriptSource ?? \"\"\n } catch (error: any) {\n const message = String(error?.message ?? error)\n if (message.includes(\"Debugger agent is not enabled\")) {\n try {\n await session.send(\"Debugger.enable\")\n const sourceResponse = await session.send(\"Debugger.getScriptSource\", { scriptId })\n return sourceResponse?.scriptSource ?? \"\"\n } catch {\n return \"\"\n }\n }\n\n return \"\"\n }\n}\n\nasync function shutdownSession(session: any): Promise<void> {\n await Promise.allSettled([\n session.send(\"Profiler.stopPreciseCoverage\").catch(() => undefined),\n session.send(\"Profiler.disable\").catch(() => undefined),\n session.send(\"Debugger.disable\").catch(() => undefined),\n ])\n await session.detach().catch(() => undefined)\n}\n\nfunction normalizeScriptUrl(rawUrl: string, config: CoverageConfig): { absolutePath: string; relativePath: string } | null {\n if (!rawUrl || rawUrl.startsWith(\"node:\")) {\n return null\n }\n\n const cleaned = stripQuery(rawUrl)\n let pathname = cleaned\n\n try {\n const parsed = new URL(cleaned)\n pathname = parsed.pathname\n } catch {\n // keep as-is for relative paths\n }\n\n if (!pathname) {\n return null\n }\n\n let absolutePath\n\n const decoded = decodeURIComponent(pathname)\n if (decoded.startsWith(VITE_FS_PREFIX)) {\n const fsPath = decoded.slice(VITE_FS_PREFIX.length)\n const normalizedFsPath = fsPath.startsWith(\"/\") || /^[A-Za-z]:\\//.test(fsPath)\n ? fsPath\n : `/${fsPath}`\n absolutePath = path.normalize(normalizedFsPath)\n } else if (decoded.startsWith(\"/\")) {\n if (!urlPathLooksLikeFile(decoded)) {\n return null\n }\n absolutePath = path.resolve(process.cwd(), `.${decoded}`)\n } else {\n return null\n }\n\n return createNormalizedPath(absolutePath, config.rootDir)\n}\n\nfunction createNormalizedPath(absolutePath: string, rootDir: string): { absolutePath: string; relativePath: string } {\n const normalizedAbsolute = path.normalize(absolutePath)\n const relativePath = path.relative(rootDir, normalizedAbsolute)\n return {\n absolutePath: normalizedAbsolute,\n relativePath,\n }\n}\n\nfunction stripQuery(url: string): string {\n const queryIndex = url.indexOf(\"?\")\n const hashIndex = url.indexOf(\"#\")\n\n const endIndex = Math.min(\n queryIndex === -1 ? Number.POSITIVE_INFINITY : queryIndex,\n hashIndex === -1 ? Number.POSITIVE_INFINITY : hashIndex,\n )\n\n if (!Number.isFinite(endIndex)) {\n return url\n }\n\n return url.slice(0, endIndex)\n}\n\nfunction isNodeModulesPath(filePath: string): boolean {\n return path\n .normalize(String(filePath ?? \"\"))\n .split(path.sep)\n .includes(\"node_modules\")\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"v8-tracker.js","sources":["../../src/coverage/v8-tracker.ts"],"sourcesContent":["import fs from \"node:fs/promises\"\nimport path from \"node:path\"\n\nimport type { Page, TestInfo } from \"@playwright/test\"\n\nimport { isInsideAnyRoot, resolveCollectCoverageRoots } from \"./collect\"\nimport type { CoverageConfig } from \"./types\"\n\n\nconst VITE_FS_PREFIX = \"/@fs/\"\n\nfunction sanitizePathSegment(input: unknown): string {\n const value = String(input ?? \"\").trim()\n return value.replace(/[^a-zA-Z0-9._-]+/g, \"_\") || \"unknown\"\n}\n\nfunction urlPathLooksLikeFile(pathname: unknown): boolean {\n const base = path.posix.basename(String(pathname ?? \"\"))\n return base.length > 0 && base.includes(\".\")\n}\n\nexport async function createCoverageTracker(\n page: Page,\n config: CoverageConfig,\n): Promise<{ stop: (testInfo: TestInfo) => Promise<void> }> {\n const session = await page.context().newCDPSession(page)\n const scriptMeta = new Map<string, { normalized: { absolutePath: string; relativePath: string } | null; url: string }>()\n const sourceCache = new Map<string, Promise<string>>()\n const scriptRoots = resolveCollectCoverageRoots(config.collectCoverageFrom, config.rootDir)\n\n await session.send(\"Debugger.enable\")\n session.on(\"Debugger.scriptParsed\", (event: any) => {\n if (!event.url) {\n return\n }\n\n const normalized = normalizeScriptUrl(event.url, config)\n const trackable = normalized\n && !isNodeModulesPath(normalized.absolutePath)\n && isInsideAnyRoot(normalized.absolutePath, scriptRoots)\n\n scriptMeta.set(event.scriptId, {\n normalized: trackable ? normalized : null,\n url: event.url,\n })\n })\n\n await session.send(\"Profiler.enable\")\n await session.send(\"Profiler.startPreciseCoverage\", { callCount: false, detailed: true })\n\n return {\n async stop(testInfo: TestInfo) {\n try {\n const payload = await collectCoveragePayload(session, scriptMeta, sourceCache, testInfo, config)\n\n if (payload.scripts.length === 0) {\n return\n }\n\n const outputFile = resolveCoverageOutputFile(config, testInfo)\n await fs.mkdir(path.dirname(outputFile), { recursive: true })\n await fs.writeFile(outputFile, JSON.stringify(payload, null, 2), \"utf8\")\n } finally {\n await shutdownSession(session)\n }\n },\n }\n}\n\nfunction resolveCoverageOutputFile(config: CoverageConfig, testInfo: TestInfo): string {\n const projectName = sanitizePathSegment(testInfo.project?.name)\n const testId = sanitizePathSegment(testInfo.testId)\n const outputDir = path.join(config.rootDir, \"build\", \"playwright\", \"coverage\", projectName, testId)\n return path.join(outputDir, config.coverageFileName)\n}\n\nasync function collectCoveragePayload(\n session: any,\n scriptMeta: Map<string, { normalized: { absolutePath: string; relativePath: string } | null; url: string }>,\n sourceCache: Map<string, Promise<string>>,\n testInfo: TestInfo,\n config: CoverageConfig,\n): Promise<{ testId: string; scripts: any[] }> {\n const { result } = await session.send(\"Profiler.takePreciseCoverage\")\n await session.send(\"Profiler.stopPreciseCoverage\")\n\n const scripts = []\n\n for (const script of result) {\n const meta = scriptMeta.get(script.scriptId)\n if (!meta || !meta.normalized) {\n continue\n }\n\n const source = await resolveScriptSource(session, sourceCache, script.scriptId)\n scripts.push({\n absolutePath: meta.normalized.absolutePath,\n relativePath: meta.normalized.relativePath,\n source,\n functions: script.functions,\n url: meta.url,\n })\n }\n\n return {\n testId: testInfo.titlePath.join(\" › \"),\n scripts,\n }\n}\n\nasync function resolveScriptSource(session: any, cache: Map<string, Promise<string>>, scriptId: string): Promise<string> {\n const cached = cache.get(scriptId)\n if (cached) {\n return cached\n }\n\n const promise = fetchScriptSource(session, scriptId)\n cache.set(scriptId, promise)\n return promise\n}\n\nasync function fetchScriptSource(session: any, scriptId: string): Promise<string> {\n try {\n const sourceResponse = await session.send(\"Debugger.getScriptSource\", { scriptId })\n return sourceResponse?.scriptSource ?? \"\"\n } catch (error: any) {\n const message = String(error?.message ?? error)\n if (message.includes(\"Debugger agent is not enabled\")) {\n try {\n await session.send(\"Debugger.enable\")\n const sourceResponse = await session.send(\"Debugger.getScriptSource\", { scriptId })\n return sourceResponse?.scriptSource ?? \"\"\n } catch {\n return \"\"\n }\n }\n\n return \"\"\n }\n}\n\nasync function shutdownSession(session: any): Promise<void> {\n await Promise.allSettled([\n session.send(\"Profiler.stopPreciseCoverage\").catch(() => undefined),\n session.send(\"Profiler.disable\").catch(() => undefined),\n session.send(\"Debugger.disable\").catch(() => undefined),\n ])\n await session.detach().catch(() => undefined)\n}\n\nfunction normalizeScriptUrl(rawUrl: string, config: CoverageConfig): { absolutePath: string; relativePath: string } | null {\n if (!rawUrl || rawUrl.startsWith(\"node:\")) {\n return null\n }\n\n const cleaned = stripQuery(rawUrl)\n let pathname = cleaned\n\n try {\n const parsed = new URL(cleaned)\n pathname = parsed.pathname\n } catch {\n // keep as-is for relative paths\n }\n\n if (!pathname) {\n return null\n }\n\n let absolutePath\n\n const decoded = decodeURIComponent(pathname)\n if (decoded.startsWith(VITE_FS_PREFIX)) {\n const fsPath = decoded.slice(VITE_FS_PREFIX.length)\n const normalizedFsPath = fsPath.startsWith(\"/\") || /^[A-Za-z]:\\//.test(fsPath)\n ? fsPath\n : `/${fsPath}`\n absolutePath = path.normalize(normalizedFsPath)\n } else if (decoded.startsWith(\"/\")) {\n if (!urlPathLooksLikeFile(decoded)) {\n return null\n }\n absolutePath = path.resolve(process.cwd(), `.${decoded}`)\n } else {\n return null\n }\n\n return createNormalizedPath(absolutePath, config.rootDir)\n}\n\nfunction createNormalizedPath(absolutePath: string, rootDir: string): { absolutePath: string; relativePath: string } {\n const normalizedAbsolute = path.normalize(absolutePath)\n const relativePath = path.relative(rootDir, normalizedAbsolute)\n return {\n absolutePath: normalizedAbsolute,\n relativePath,\n }\n}\n\nfunction stripQuery(url: string): string {\n const queryIndex = url.indexOf(\"?\")\n const hashIndex = url.indexOf(\"#\")\n\n const endIndex = Math.min(\n queryIndex === -1 ? Number.POSITIVE_INFINITY : queryIndex,\n hashIndex === -1 ? Number.POSITIVE_INFINITY : hashIndex,\n )\n\n if (!Number.isFinite(endIndex)) {\n return url\n }\n\n return url.slice(0, endIndex)\n}\n\nfunction isNodeModulesPath(filePath: string): boolean {\n return path\n .normalize(String(filePath ?? \"\"))\n .split(path.sep)\n .includes(\"node_modules\")\n}\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rpcbase/test",
3
- "version": "0.319.0",
3
+ "version": "0.320.0",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist"