@rpcbase/test 0.404.0 → 0.406.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/dist/clearDatabase.js.map +1 -1
- package/dist/cli.js.map +1 -1
- package/dist/coverage/collect.js.map +1 -1
- package/dist/coverage/config-loader.js.map +1 -1
- package/dist/coverage/config.js.map +1 -1
- package/dist/coverage/console-text-report.js.map +1 -1
- package/dist/coverage/files.js.map +1 -1
- package/dist/coverage/fixtures.js.map +1 -1
- package/dist/coverage/report.js.map +1 -1
- package/dist/coverage/v8-tracker.js.map +1 -1
- package/dist/runners/playwright.js.map +1 -1
- package/dist/runners/process.js.map +1 -1
- package/dist/runners/vitest.js.map +1 -1
- package/dist/serverCoverage.js.map +1 -1
- package/dist/vitest.config.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clearDatabase.js","names":[],"sources":["../src/clearDatabase.ts"],"sourcesContent":["import mongoose from \"mongoose\"\n\n\nexport async function clearDatabase(dbName: string): Promise<void> {\n const { DB_PORT, APP_NAME } = process.env\n\n // directConnection=true skips replica-set discovery. The dev rs advertises\n // its member by the in-Docker hostname (e.g. \"mongodb:27018\"), unreachable\n // from the host, so without this the driver blocks for the full\n // serverSelectionTimeoutMS (~30s) before failing on every test DB cleanup.\n const connectionString = `mongodb://localhost:${DB_PORT}/${APP_NAME}-${dbName}?directConnection=true`\n\n // console.log(\"will clear DB:\", connectionString)\n\n const connection = await mongoose\n .createConnection(connectionString)\n .asPromise()\n\n // Drop the database\n await connection.dropDatabase()\n\n await connection.close()\n}\n"],"mappings":";;AAGA,eAAsB,cAAc,QAA+B;CACjE,MAAM,EAAE,SAAS,aAAa,QAAQ;CAMtC,MAAM,mBAAmB,uBAAuB,
|
|
1
|
+
{"version":3,"file":"clearDatabase.js","names":[],"sources":["../src/clearDatabase.ts"],"sourcesContent":["import mongoose from \"mongoose\"\n\n\nexport async function clearDatabase(dbName: string): Promise<void> {\n const { DB_PORT, APP_NAME } = process.env\n\n // directConnection=true skips replica-set discovery. The dev rs advertises\n // its member by the in-Docker hostname (e.g. \"mongodb:27018\"), unreachable\n // from the host, so without this the driver blocks for the full\n // serverSelectionTimeoutMS (~30s) before failing on every test DB cleanup.\n const connectionString = `mongodb://localhost:${DB_PORT}/${APP_NAME}-${dbName}?directConnection=true`\n\n // console.log(\"will clear DB:\", connectionString)\n\n const connection = await mongoose\n .createConnection(connectionString)\n .asPromise()\n\n // Drop the database\n await connection.dropDatabase()\n\n await connection.close()\n}\n"],"mappings":";;AAGA,eAAsB,cAAc,QAA+B;CACjE,MAAM,EAAE,SAAS,aAAa,QAAQ;CAMtC,MAAM,mBAAmB,uBAAuB,QAAQ,GAAG,SAAS,GAAG,OAAO;CAI9E,MAAM,aAAa,MAAM,SACtB,iBAAiB,gBAAgB,CAAC,CAClC,UAAU;CAGb,MAAM,WAAW,aAAa;CAE9B,MAAM,WAAW,MAAM;AACzB"}
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","names":[],"sources":["../src/cli.ts"],"sourcesContent":["import { 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\"\n\nimport fg from \"fast-glob\"\n\nimport { createCoverageConfig } from \"./coverage/config\"\nimport { createCollectCoverageMatcher } 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\"\nimport { runPlaywright } from \"./runners/playwright\"\nimport { resolveNodeCoverageDir, runVitest } from \"./runners/vitest\"\n\n\nconst require = createRequire(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\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\ntype CliArgs = {\n buildSpecsMap: boolean\n auto: boolean\n showMapping: boolean\n list: boolean\n passthroughArgs: string[]\n}\n\nconst RB_CLI_OPTIONS = [\"build-specs-map\", \"auto\", \"full\", \"show-mapping\", \"list\"] as const\n\nfunction isRbCliOption(arg: string): boolean {\n const normalized = arg.toLowerCase()\n return RB_CLI_OPTIONS.some((option) => normalized === `--${option}` || normalized.startsWith(`--${option}=`))\n}\n\nfunction parseBooleanCliArg(rawArgs: string[], option: string): boolean {\n const optionPrefix = `--${option}`\n const optionWithValuePrefix = `${optionPrefix}=`\n return rawArgs.some((arg) => {\n if (arg === optionPrefix) {\n return true\n }\n if (!arg.startsWith(optionWithValuePrefix)) {\n return false\n }\n const value = arg.slice(optionWithValuePrefix.length).toLowerCase()\n if (value === \"false\" || value === \"0\") {\n return false\n }\n return value.length > 0\n })\n}\n\nfunction parseCliArgs(rawArgs: string[]): CliArgs {\n const yargs = require(\"yargs/yargs\") as (args: string[]) => {\n help: (enabled: boolean) => any\n version: (enabled: boolean) => any\n strict: (enabled: boolean) => any\n exitProcess: (enabled: boolean) => any\n parserConfiguration: (options: Record<string, unknown>) => any\n option: (name: string, options: Record<string, unknown>) => any\n parseSync: () => Record<string, unknown>\n }\n\n const parsed = yargs(rawArgs)\n .help(false)\n .version(false)\n .strict(false)\n .exitProcess(false)\n .parserConfiguration({\n \"unknown-options-as-args\": true,\n \"populate--\": true,\n \"strip-dashed\": true,\n \"strip-aliased\": true,\n })\n .option(\"build-specs-map\", { type: \"boolean\", default: false })\n .option(\"auto\", { type: \"boolean\", default: false })\n .option(\"full\", { type: \"boolean\", default: false })\n .option(\"show-mapping\", { type: \"boolean\", default: false })\n .option(\"list\", { type: \"boolean\", default: false })\n .parseSync()\n\n const passthroughArgs = [\n ...(Array.isArray(parsed._) ? parsed._ : []),\n ...(Array.isArray(parsed[\"--\"]) ? parsed[\"--\"] : []),\n ].map((entry) => String(entry)).filter((arg) => !isRbCliOption(arg))\n\n return {\n buildSpecsMap: parseBooleanCliArg(rawArgs, \"build-specs-map\"),\n auto: parseBooleanCliArg(rawArgs, \"auto\") && !parseBooleanCliArg(rawArgs, \"full\"),\n showMapping: parseBooleanCliArg(rawArgs, \"show-mapping\"),\n list: parseBooleanCliArg(rawArgs, \"list\"),\n passthroughArgs,\n }\n}\n\nasync function runTests(): Promise<void> {\n const args = parseCliArgs(process.argv.slice(2))\n const buildSpecsMap = args.buildSpecsMap\n const auto = args.auto && !buildSpecsMap\n const showMapping = args.showMapping\n const list = args.list\n const filteredArgs = args.passthroughArgs\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 if (list) {\n if (auto) {\n await resolveAutoPlaywrightArgs({\n userArgs: filteredArgs,\n playwrightCoverage,\n vitestCoverage,\n showMapping,\n listOnly: true,\n })\n } else {\n await listPlaywrightSpecFiles(combinedCoverage?.config.rootDir ?? process.cwd())\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, filteredArgs, { 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 : filteredArgs\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 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{,.desktop,.mobile}.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 listOnly = false,\n}: {\n userArgs: string[]\n playwrightCoverage: CoverageState\n vitestCoverage: CoverageState\n showMapping?: boolean\n listOnly?: 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 if (listOnly) {\n console.log(\"[auto] No relevant git changes.\")\n console.log(\"[list] No matched spec files.\")\n return null\n }\n console.warn(\"[auto] No relevant git changes; running full Playwright suite.\")\n return userArgs\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 if (listOnly) {\n console.log(\"[list] No matched spec files.\")\n return null\n }\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 if (playwrightFiles.length === 0) {\n if (listOnly) {\n console.log(\"[list] No matched spec files.\")\n return null\n }\n console.log(\"[auto] No impacted specs.\")\n return null\n }\n\n const totalSpecFiles = (await findSpecSourceFiles(config.rootDir)).length\n\n if (listOnly) {\n console.log(`[auto] Selected ${playwrightFiles.length}/${totalSpecFiles} spec file(s):`)\n for (const playwrightFile of playwrightFiles) {\n console.log(` - ${playwrightFile}`)\n }\n return null\n }\n\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{,.desktop,.mobile}.ts.json\", \"spec/**/*.spec{,.desktop,.mobile}.tsx.json\"]\n const matches = await fg(patterns, { cwd: filesMapDir, absolute: true, onlyFiles: true }).catch(() => [])\n return matches.sort()\n}\n\nasync function listPlaywrightSpecFiles(projectRoot: string): Promise<void> {\n const specSourceFiles = await findSpecSourceFiles(projectRoot)\n if (specSourceFiles.length === 0) {\n console.log(\"[list] No spec files found.\")\n return\n }\n\n const playwrightFiles = specSourceFiles\n .map((specSourceFile) => path.relative(projectRoot, specSourceFile))\n .map((specProjectPath) => resolvePlaywrightSpecFile(specProjectPath))\n\n console.log(`[list] Selected ${playwrightFiles.length} spec file(s):`)\n for (const playwrightFile of playwrightFiles) {\n console.log(` - ${playwrightFile}`)\n }\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 /\\.spec(?:\\.(?:desktop|mobile))?\\.tsx?$/.test(absolutePath)\n}\n\nasync function findSpecSourceFiles(projectRoot: string): Promise<string[]> {\n const patterns = [\"spec/**/*.spec{,.desktop,.mobile}.ts\", \"spec/**/*.spec{,.desktop,.mobile}.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\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\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"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cli.js","names":[],"sources":["../src/cli.ts"],"sourcesContent":["import { 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\"\n\nimport fg from \"fast-glob\"\n\nimport { createCoverageConfig } from \"./coverage/config\"\nimport { createCollectCoverageMatcher } 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\"\nimport { runPlaywright } from \"./runners/playwright\"\nimport { resolveNodeCoverageDir, runVitest } from \"./runners/vitest\"\n\n\nconst require = createRequire(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\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\ntype CliArgs = {\n buildSpecsMap: boolean\n auto: boolean\n showMapping: boolean\n list: boolean\n passthroughArgs: string[]\n}\n\nconst RB_CLI_OPTIONS = [\"build-specs-map\", \"auto\", \"full\", \"show-mapping\", \"list\"] as const\n\nfunction isRbCliOption(arg: string): boolean {\n const normalized = arg.toLowerCase()\n return RB_CLI_OPTIONS.some((option) => normalized === `--${option}` || normalized.startsWith(`--${option}=`))\n}\n\nfunction parseBooleanCliArg(rawArgs: string[], option: string): boolean {\n const optionPrefix = `--${option}`\n const optionWithValuePrefix = `${optionPrefix}=`\n return rawArgs.some((arg) => {\n if (arg === optionPrefix) {\n return true\n }\n if (!arg.startsWith(optionWithValuePrefix)) {\n return false\n }\n const value = arg.slice(optionWithValuePrefix.length).toLowerCase()\n if (value === \"false\" || value === \"0\") {\n return false\n }\n return value.length > 0\n })\n}\n\nfunction parseCliArgs(rawArgs: string[]): CliArgs {\n const yargs = require(\"yargs/yargs\") as (args: string[]) => {\n help: (enabled: boolean) => any\n version: (enabled: boolean) => any\n strict: (enabled: boolean) => any\n exitProcess: (enabled: boolean) => any\n parserConfiguration: (options: Record<string, unknown>) => any\n option: (name: string, options: Record<string, unknown>) => any\n parseSync: () => Record<string, unknown>\n }\n\n const parsed = yargs(rawArgs)\n .help(false)\n .version(false)\n .strict(false)\n .exitProcess(false)\n .parserConfiguration({\n \"unknown-options-as-args\": true,\n \"populate--\": true,\n \"strip-dashed\": true,\n \"strip-aliased\": true,\n })\n .option(\"build-specs-map\", { type: \"boolean\", default: false })\n .option(\"auto\", { type: \"boolean\", default: false })\n .option(\"full\", { type: \"boolean\", default: false })\n .option(\"show-mapping\", { type: \"boolean\", default: false })\n .option(\"list\", { type: \"boolean\", default: false })\n .parseSync()\n\n const passthroughArgs = [\n ...(Array.isArray(parsed._) ? parsed._ : []),\n ...(Array.isArray(parsed[\"--\"]) ? parsed[\"--\"] : []),\n ].map((entry) => String(entry)).filter((arg) => !isRbCliOption(arg))\n\n return {\n buildSpecsMap: parseBooleanCliArg(rawArgs, \"build-specs-map\"),\n auto: parseBooleanCliArg(rawArgs, \"auto\") && !parseBooleanCliArg(rawArgs, \"full\"),\n showMapping: parseBooleanCliArg(rawArgs, \"show-mapping\"),\n list: parseBooleanCliArg(rawArgs, \"list\"),\n passthroughArgs,\n }\n}\n\nasync function runTests(): Promise<void> {\n const args = parseCliArgs(process.argv.slice(2))\n const buildSpecsMap = args.buildSpecsMap\n const auto = args.auto && !buildSpecsMap\n const showMapping = args.showMapping\n const list = args.list\n const filteredArgs = args.passthroughArgs\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 if (list) {\n if (auto) {\n await resolveAutoPlaywrightArgs({\n userArgs: filteredArgs,\n playwrightCoverage,\n vitestCoverage,\n showMapping,\n listOnly: true,\n })\n } else {\n await listPlaywrightSpecFiles(combinedCoverage?.config.rootDir ?? process.cwd())\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, filteredArgs, { 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 : filteredArgs\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 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{,.desktop,.mobile}.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 listOnly = false,\n}: {\n userArgs: string[]\n playwrightCoverage: CoverageState\n vitestCoverage: CoverageState\n showMapping?: boolean\n listOnly?: 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 if (listOnly) {\n console.log(\"[auto] No relevant git changes.\")\n console.log(\"[list] No matched spec files.\")\n return null\n }\n console.warn(\"[auto] No relevant git changes; running full Playwright suite.\")\n return userArgs\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 if (listOnly) {\n console.log(\"[list] No matched spec files.\")\n return null\n }\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 if (playwrightFiles.length === 0) {\n if (listOnly) {\n console.log(\"[list] No matched spec files.\")\n return null\n }\n console.log(\"[auto] No impacted specs.\")\n return null\n }\n\n const totalSpecFiles = (await findSpecSourceFiles(config.rootDir)).length\n\n if (listOnly) {\n console.log(`[auto] Selected ${playwrightFiles.length}/${totalSpecFiles} spec file(s):`)\n for (const playwrightFile of playwrightFiles) {\n console.log(` - ${playwrightFile}`)\n }\n return null\n }\n\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{,.desktop,.mobile}.ts.json\", \"spec/**/*.spec{,.desktop,.mobile}.tsx.json\"]\n const matches = await fg(patterns, { cwd: filesMapDir, absolute: true, onlyFiles: true }).catch(() => [])\n return matches.sort()\n}\n\nasync function listPlaywrightSpecFiles(projectRoot: string): Promise<void> {\n const specSourceFiles = await findSpecSourceFiles(projectRoot)\n if (specSourceFiles.length === 0) {\n console.log(\"[list] No spec files found.\")\n return\n }\n\n const playwrightFiles = specSourceFiles\n .map((specSourceFile) => path.relative(projectRoot, specSourceFile))\n .map((specProjectPath) => resolvePlaywrightSpecFile(specProjectPath))\n\n console.log(`[list] Selected ${playwrightFiles.length} spec file(s):`)\n for (const playwrightFile of playwrightFiles) {\n console.log(` - ${playwrightFile}`)\n }\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 /\\.spec(?:\\.(?:desktop|mobile))?\\.tsx?$/.test(absolutePath)\n}\n\nasync function findSpecSourceFiles(projectRoot: string): Promise<string[]> {\n const patterns = [\"spec/**/*.spec{,.desktop,.mobile}.ts\", \"spec/**/*.spec{,.desktop,.mobile}.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\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\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"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collect.js","names":[],"sources":["../../src/coverage/collect.ts"],"sourcesContent":["import path from \"node:path\"\n\nimport picomatch from \"picomatch\"\n\n\nexport function createCollectCoverageMatcher(patterns: unknown, rootDir: unknown): (absolutePath: string) => boolean {\n const normalizedRoot = path.resolve(String(rootDir ?? \"\"))\n\n const includeMatchers: Array<(candidate: string) => boolean> = []\n const excludeMatchers: Array<(candidate: string) => boolean> = []\n\n if (Array.isArray(patterns)) {\n for (const pattern of patterns) {\n const raw = String(pattern ?? \"\").trim()\n if (!raw) {\n continue\n }\n\n const isExclude = raw.startsWith(\"!\")\n const body = toPosix(isExclude ? raw.slice(1) : raw)\n if (!body) {\n continue\n }\n\n const matcher = picomatch(body, { dot: true })\n if (isExclude) {\n excludeMatchers.push(matcher)\n } else {\n includeMatchers.push(matcher)\n }\n }\n }\n\n if (includeMatchers.length === 0) {\n return () => false\n }\n\n return (absolutePath) => {\n const normalizedAbsolute = path.resolve(String(absolutePath ?? \"\"))\n if (!normalizedAbsolute) {\n return false\n }\n\n const relativePosix = toPosix(path.relative(normalizedRoot, normalizedAbsolute))\n const absolutePosix = toPosix(normalizedAbsolute)\n const candidates = new Set([absolutePosix, relativePosix])\n\n if (relativePosix) {\n candidates.add(`./${relativePosix}`)\n }\n\n const candidateList = Array.from(candidates)\n const included = includeMatchers.some((matcher) => candidateList.some((candidate) => matcher(candidate)))\n if (!included) {\n return false\n }\n\n return !excludeMatchers.some((matcher) => candidateList.some((candidate) => matcher(candidate)))\n }\n}\n\nexport function toPosix(input: unknown): string {\n return String(input ?? \"\").split(path.sep).join(\"/\")\n}\n\nexport function isInsideAnyRoot(absolutePath: string, roots: unknown): boolean {\n const normalizedAbsolute = path.resolve(String(absolutePath ?? \"\"))\n return (Array.isArray(roots) ? roots : []).some((root) => {\n const normalizedRoot = path.resolve(String(root ?? \"\"))\n const relative = path.relative(normalizedRoot, normalizedAbsolute)\n return relative === \"\" || (!relative.startsWith(\"..\") && !path.isAbsolute(relative))\n })\n}\n\nexport function resolveCollectCoverageRoots(patterns: unknown, rootDir: unknown): string[] {\n const resolvedRootDir = path.resolve(String(rootDir ?? \"\"))\n const roots = new Set([resolvedRootDir])\n\n if (!Array.isArray(patterns)) {\n return Array.from(roots)\n }\n\n for (const pattern of patterns) {\n const raw = String(pattern ?? \"\").trim()\n if (!raw) {\n continue\n }\n\n const cleaned = raw.startsWith(\"!\") ? raw.slice(1) : raw\n if (!cleaned) {\n continue\n }\n\n const prefix = staticGlobPrefix(cleaned)\n if (!prefix) {\n continue\n }\n\n roots.add(path.resolve(resolvedRootDir, prefix))\n }\n\n return Array.from(roots)\n}\n\nfunction staticGlobPrefix(pattern: unknown): string | null {\n const normalized = String(pattern ?? \"\").trim()\n if (!normalized) {\n return null\n }\n\n const firstGlobIndex = findFirstGlobIndex(normalized)\n const prefix = firstGlobIndex === -1 ? normalized : normalized.slice(0, firstGlobIndex)\n\n if (!prefix) {\n return null\n }\n\n if (prefix.endsWith(\"/\") || prefix.endsWith(path.sep)) {\n return prefix\n }\n\n const posix = prefix.split(path.sep).join(\"/\")\n return path.posix.dirname(posix)\n}\n\nfunction findFirstGlobIndex(value: string): number {\n for (let i = 0; i < value.length; i += 1) {\n const char = value[i]\n if (char === \"*\" || char === \"?\" || char === \"[\" || char === \"{\") {\n return i\n }\n }\n return -1\n}\n"],"mappings":";;;AAKA,SAAgB,6BAA6B,UAAmB,SAAqD;CACnH,MAAM,iBAAiB,KAAK,QAAQ,OAAO,WAAW,EAAE,CAAC;CAEzD,MAAM,kBAAyD,
|
|
1
|
+
{"version":3,"file":"collect.js","names":[],"sources":["../../src/coverage/collect.ts"],"sourcesContent":["import path from \"node:path\"\n\nimport picomatch from \"picomatch\"\n\n\nexport function createCollectCoverageMatcher(patterns: unknown, rootDir: unknown): (absolutePath: string) => boolean {\n const normalizedRoot = path.resolve(String(rootDir ?? \"\"))\n\n const includeMatchers: Array<(candidate: string) => boolean> = []\n const excludeMatchers: Array<(candidate: string) => boolean> = []\n\n if (Array.isArray(patterns)) {\n for (const pattern of patterns) {\n const raw = String(pattern ?? \"\").trim()\n if (!raw) {\n continue\n }\n\n const isExclude = raw.startsWith(\"!\")\n const body = toPosix(isExclude ? raw.slice(1) : raw)\n if (!body) {\n continue\n }\n\n const matcher = picomatch(body, { dot: true })\n if (isExclude) {\n excludeMatchers.push(matcher)\n } else {\n includeMatchers.push(matcher)\n }\n }\n }\n\n if (includeMatchers.length === 0) {\n return () => false\n }\n\n return (absolutePath) => {\n const normalizedAbsolute = path.resolve(String(absolutePath ?? \"\"))\n if (!normalizedAbsolute) {\n return false\n }\n\n const relativePosix = toPosix(path.relative(normalizedRoot, normalizedAbsolute))\n const absolutePosix = toPosix(normalizedAbsolute)\n const candidates = new Set([absolutePosix, relativePosix])\n\n if (relativePosix) {\n candidates.add(`./${relativePosix}`)\n }\n\n const candidateList = Array.from(candidates)\n const included = includeMatchers.some((matcher) => candidateList.some((candidate) => matcher(candidate)))\n if (!included) {\n return false\n }\n\n return !excludeMatchers.some((matcher) => candidateList.some((candidate) => matcher(candidate)))\n }\n}\n\nexport function toPosix(input: unknown): string {\n return String(input ?? \"\").split(path.sep).join(\"/\")\n}\n\nexport function isInsideAnyRoot(absolutePath: string, roots: unknown): boolean {\n const normalizedAbsolute = path.resolve(String(absolutePath ?? \"\"))\n return (Array.isArray(roots) ? roots : []).some((root) => {\n const normalizedRoot = path.resolve(String(root ?? \"\"))\n const relative = path.relative(normalizedRoot, normalizedAbsolute)\n return relative === \"\" || (!relative.startsWith(\"..\") && !path.isAbsolute(relative))\n })\n}\n\nexport function resolveCollectCoverageRoots(patterns: unknown, rootDir: unknown): string[] {\n const resolvedRootDir = path.resolve(String(rootDir ?? \"\"))\n const roots = new Set([resolvedRootDir])\n\n if (!Array.isArray(patterns)) {\n return Array.from(roots)\n }\n\n for (const pattern of patterns) {\n const raw = String(pattern ?? \"\").trim()\n if (!raw) {\n continue\n }\n\n const cleaned = raw.startsWith(\"!\") ? raw.slice(1) : raw\n if (!cleaned) {\n continue\n }\n\n const prefix = staticGlobPrefix(cleaned)\n if (!prefix) {\n continue\n }\n\n roots.add(path.resolve(resolvedRootDir, prefix))\n }\n\n return Array.from(roots)\n}\n\nfunction staticGlobPrefix(pattern: unknown): string | null {\n const normalized = String(pattern ?? \"\").trim()\n if (!normalized) {\n return null\n }\n\n const firstGlobIndex = findFirstGlobIndex(normalized)\n const prefix = firstGlobIndex === -1 ? normalized : normalized.slice(0, firstGlobIndex)\n\n if (!prefix) {\n return null\n }\n\n if (prefix.endsWith(\"/\") || prefix.endsWith(path.sep)) {\n return prefix\n }\n\n const posix = prefix.split(path.sep).join(\"/\")\n return path.posix.dirname(posix)\n}\n\nfunction findFirstGlobIndex(value: string): number {\n for (let i = 0; i < value.length; i += 1) {\n const char = value[i]\n if (char === \"*\" || char === \"?\" || char === \"[\" || char === \"{\") {\n return i\n }\n }\n return -1\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-loader.js","names":[],"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"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"config-loader.js","names":[],"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"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","names":[],"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"],"mappings":";;AAKA,IAAM,qBAAqB;CACzB,UAAU;CACV,WAAW;CACX,OAAO;CACP,YAAY;AACd;AAEA,IAAM,iBAAiB,OAAO,KAAK,kBAAkB;AACrD,IAAM,oBAAoB,IAAI,IAAY,cAA0B;AAEpE,SAAgB,qBAAqB,SAAiD;CACpF,MAAM,EAAE,YAAY;CACpB,IAAI,CAAC,SACH,MAAM,IAAI,MAAM,yCAAyC;CAG3D,MAAM,kBAAkB,KAAK,QAAQ,OAAO;CAC5C,MAAM,kBAAkB,QAAQ,oBAAoB;CAEpD,MAAM,sBAAsB,MAAM,QAAQ,QAAQ,mBAAmB,IACjE,QAAQ,oBACP,KAAK,YAAY,OAAO,WAAW,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAC9C,QAAQ,YAAY,QAAQ,SAAS,CAAC,IACvC,
|
|
1
|
+
{"version":3,"file":"config.js","names":[],"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"],"mappings":";;AAKA,IAAM,qBAAqB;CACzB,UAAU;CACV,WAAW;CACX,OAAO;CACP,YAAY;AACd;AAEA,IAAM,iBAAiB,OAAO,KAAK,kBAAkB;AACrD,IAAM,oBAAoB,IAAI,IAAY,cAA0B;AAEpE,SAAgB,qBAAqB,SAAiD;CACpF,MAAM,EAAE,YAAY;CACpB,IAAI,CAAC,SACH,MAAM,IAAI,MAAM,yCAAyC;CAG3D,MAAM,kBAAkB,KAAK,QAAQ,OAAO;CAC5C,MAAM,kBAAkB,QAAQ,oBAAoB;CAEpD,MAAM,sBAAsB,MAAM,QAAQ,QAAQ,mBAAmB,IACjE,QAAQ,oBACP,KAAK,YAAY,OAAO,WAAW,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAC9C,QAAQ,YAAY,QAAQ,SAAS,CAAC,IACvC,CAAC;CAEL,IAAI,oBAAoB,WAAW,GACjC,MAAM,IAAI,MAAM,4DAA4D;CAG9E,MAAM,kBAAkB,KAAK,KAAK,iBAAiB,SAAS,UAAU;CACtE,MAAM,oBAAoB,KAAK,KAAK,iBAAiB,QAAQ;CAC7D,MAAM,mBAAmB,QAAQ,oBAAoB;CACrD,MAAM,iBAAiB,QAAQ,kBAAkB;CACjD,MAAM,kBAAkB,QAAQ,IAAI,oBAAoB;CAExD,MAAM,EAAE,QAAQ,YAAY,SAAS,qBAAqB,0BAA0B,QAAQ,UAAU;CAEtG,OAAO;EACL,SAAS;EACT;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF;AACF;AAEA,SAAS,0BAA0B,eAGjC;CACA,MAAM,mBAAuC,EAAE,GAAG,mBAAmB;CACrE,MAAM,UAAqC,CAAC;CAE5C,IAAI,CAAC,cAAc,aAAa,GAC9B,OAAO;EAAE,QAAQ;EAAkB;CAAQ;CAG7C,MAAM,eAAe;CAErB,KAAK,MAAM,OAAO,gBAAgB;EAChC,MAAM,QAAQ,aAAa;EAC3B,IAAI,iBAAiB,KAAK,GACxB,iBAAiB,OAAO;CAE5B;CAEA,IAAI,OAAO,UAAU,eAAe,KAAK,cAAc,QAAQ,GAAG;EAChE,IAAI,CAAC,cAAc,aAAa,MAAM,GACpC,MAAM,IAAI,MAAM,+EAA+E;EAEjG,OAAO,OAAO,kBAAkB,uBAAuB,aAAa,MAAM,CAAC;CAC7E;CAEA,KAAK,MAAM,CAAC,SAAS,cAAc,OAAO,QAAQ,YAAY,GAAG;EAC/D,IAAI,YAAY,YAAY,kBAAkB,IAAI,OAAO,GACvD;EAGF,IAAI,CAAC,cAAc,SAAS,GAC1B,MAAM,IAAI,MACR,sCAAsC,QAAQ,gDAChD;EAGF,QAAQ,KAAK;GACX,IAAI;GACJ;GACA,YAAY;IACV,GAAG;IACH,GAAG,uBAAuB,SAAS;GACrC;EACF,CAAC;CACH;CAEA,OAAO;EAAE,QAAQ;EAAkB;CAAQ;AAC7C;AAEA,SAAS,uBAAuB,QAA8C;CAC5E,MAAM,YAAyC,CAAC;CAChD,IAAI,CAAC,cAAc,MAAM,GACvB,OAAO;CAGT,KAAK,MAAM,OAAO,gBAAgB;EAChC,MAAM,QAAS,OAAe;EAC9B,IAAI,iBAAiB,KAAK,GACxB,UAAU,OAAO;CAErB;CAEA,OAAO;AACT;AAEA,SAAS,cAAc,OAAkD;CACvE,OAAO,UAAU,QAAQ,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK;AAC5E;AAEA,SAAS,iBAAiB,OAAiC;CACzD,OAAO,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK;AAC3D"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"console-text-report.js","names":[],"sources":["../../src/coverage/console-text-report.ts"],"sourcesContent":["import path from \"node:path\"\n\n\nconst DEFAULT_CONSOLE_MAX_COLS = 80\nconst CONSOLE_SUMMARIZER = \"rbCwd\"\n\nexport function generateConsoleTextCoverageReport(\n reports: any,\n context: any,\n): { output: string; summarizer: string | undefined } {\n const debug = resolveConsoleReportDebugInfo()\n const summarizer = registerConsoleSummarizer(context)\n writeConsoleReportDebugLog({ ...debug, summarizer })\n\n const reportOutput = createConsoleTextReportOutput(reports, context, {\n maxCols: debug.maxCols + 20,\n summarizer,\n })\n\n return { output: stripUncoveredLineNumbersColumn(reportOutput), summarizer }\n}\n\nfunction resolveConsoleReportDebugInfo(): {\n isTTY: boolean\n stdoutColumns: number | undefined\n envColumns: string | undefined\n maxCols: number\n } {\n const isTTY = Boolean(process.stdout.isTTY)\n const stdoutColumns = process.stdout.columns\n const envColumns = process.env.COLUMNS\n const maxCols = resolveConsoleMaxCols(stdoutColumns, envColumns)\n\n return { isTTY, stdoutColumns, envColumns, maxCols }\n}\n\nfunction resolveConsoleMaxCols(stdoutColumns: number | undefined, envColumns: string | undefined): number {\n if (typeof stdoutColumns === \"number\" && Number.isFinite(stdoutColumns) && stdoutColumns > 0) {\n return stdoutColumns\n }\n\n const parsed = typeof envColumns === \"string\" ? Number.parseInt(envColumns, 10) : Number.NaN\n if (Number.isFinite(parsed) && parsed > 0) {\n return parsed\n }\n\n return DEFAULT_CONSOLE_MAX_COLS\n}\n\nfunction writeConsoleReportDebugLog({\n isTTY,\n stdoutColumns,\n envColumns,\n maxCols,\n summarizer,\n}: {\n isTTY: boolean\n stdoutColumns: number | undefined\n envColumns: string | undefined\n maxCols: number\n summarizer: string | undefined\n}): void {\n const message = [\n \"[coverage] debug\",\n `stdout.isTTY=${isTTY ? \"1\" : \"0\"}`,\n `stdout.columns=${stdoutColumns ?? \"undefined\"}`,\n `env.COLUMNS=${envColumns ?? \"undefined\"}`,\n `resolvedMaxCols=${maxCols}`,\n `summarizer=${summarizer ?? \"undefined\"}`,\n ].join(\" \")\n\n process.stderr.write(`${message}\\n`)\n}\n\nfunction createConsoleTextReportOutput(\n reports: any,\n context: any,\n options: { maxCols: number; summarizer?: string },\n): string {\n const fileWriter = context?.writer\n const fileWriterCtor = fileWriter?.constructor\n\n if (\n !fileWriterCtor\n || typeof fileWriterCtor.startCapture !== \"function\"\n || typeof fileWriterCtor.stopCapture !== \"function\"\n || typeof fileWriterCtor.getOutput !== \"function\"\n || typeof fileWriterCtor.resetOutput !== \"function\"\n ) {\n reports.create(\"text\", { maxCols: options.maxCols, summarizer: options.summarizer }).execute(context)\n return \"\"\n }\n\n fileWriterCtor.resetOutput()\n fileWriterCtor.startCapture()\n try {\n reports.create(\"text\", { maxCols: options.maxCols, summarizer: options.summarizer }).execute(context)\n } finally {\n fileWriterCtor.stopCapture()\n }\n const output = fileWriterCtor.getOutput()\n fileWriterCtor.resetOutput()\n return output\n}\n\nfunction stripUncoveredLineNumbersColumn(output: string): string {\n const lines = output.split(\"\\n\")\n const filtered = lines.map((line) => {\n const parts = line.split(\"|\")\n if (parts.length < 6) {\n return line.trimEnd()\n }\n return parts.slice(0, 5).join(\"|\").trimEnd()\n })\n return filtered.join(\"\\n\")\n}\n\nfunction registerConsoleSummarizer(context: any): string | undefined {\n const summarizerFactory = context?._summarizerFactory\n if (!summarizerFactory || typeof summarizerFactory !== \"object\") {\n return undefined\n }\n\n if (CONSOLE_SUMMARIZER in summarizerFactory) {\n return CONSOLE_SUMMARIZER\n }\n\n const pkgTree = context.getTree?.(\"pkg\")\n const pkgRoot = pkgTree?.getRoot?.()\n if (!pkgRoot) {\n return undefined\n }\n\n summarizerFactory[CONSOLE_SUMMARIZER] = createCollapsedCwdTree(pkgRoot, process.cwd())\n return CONSOLE_SUMMARIZER\n}\n\nfunction createCollapsedCwdTree(\n root: any,\n cwd: string,\n): { getRoot: () => any; visit: (visitor: any, state: any) => void } {\n const treeRoot = createCwdTreeFromCoverage(root, cwd)\n const clonedRoot = cloneReportNode(treeRoot, null)\n return {\n getRoot: () => clonedRoot,\n visit: (visitor: any, state: any) => {\n const fullVisitor = toFullVisitor(visitor)\n fullVisitor.onStart(clonedRoot, state)\n clonedRoot.visit(fullVisitor, state)\n fullVisitor.onEnd(clonedRoot, state)\n },\n }\n}\n\nfunction createCwdTreeFromCoverage(root: any, cwd: string): any {\n const proto = Object.getPrototypeOf(root)\n const pathCtor = root?.path?.constructor\n\n const fileCoverages: any[] = []\n collectFileCoverages(root, fileCoverages)\n\n const treeRoot = Object.create(proto)\n treeRoot.path = pathCtor ? new pathCtor([]) : root.path\n treeRoot.fileCoverage = null\n treeRoot.parent = null\n treeRoot.children = []\n\n const dirNodes = new Map<string, any>()\n dirNodes.set(\"\", treeRoot)\n\n for (const fileCoverage of fileCoverages) {\n const absolutePath = path.resolve(String(fileCoverage?.path ?? \"\"))\n if (!absolutePath) {\n continue\n }\n\n let relativePath = toPosix(path.relative(cwd, absolutePath))\n if (!relativePath) {\n relativePath = toPosix(absolutePath)\n }\n\n if (isInsideCwd(relativePath) && (relativePath === \"src\" || relativePath.startsWith(\"src/\"))) {\n relativePath = relativePath === \"src\" ? \"\" : relativePath.slice(\"src/\".length)\n }\n\n if (!relativePath) {\n relativePath = toPosix(path.basename(absolutePath))\n }\n\n const segments = relativePath.split(\"/\").filter(Boolean)\n if (segments.length === 0) {\n continue\n }\n\n let parent = treeRoot\n let prefix = \"\"\n\n for (let i = 0; i < segments.length - 1; i += 1) {\n prefix = prefix ? `${prefix}/${segments[i]}` : segments[i]\n const existing = dirNodes.get(prefix)\n if (existing) {\n parent = existing\n continue\n }\n\n const dirNode = Object.create(proto)\n dirNode.path = pathCtor ? new pathCtor(prefix.split(\"/\")) : root.path\n dirNode.fileCoverage = null\n dirNode.parent = parent\n dirNode.children = []\n parent.children.push(dirNode)\n dirNodes.set(prefix, dirNode)\n parent = dirNode\n }\n\n const fileNode = Object.create(proto)\n fileNode.path = pathCtor ? new pathCtor(segments) : root.path\n fileNode.fileCoverage = fileCoverage\n fileNode.parent = parent\n fileNode.children = []\n parent.children.push(fileNode)\n }\n\n sortReportTree(treeRoot)\n\n return treeRoot\n}\n\nfunction collectFileCoverages(node: any, out: any[]): void {\n if (!node || typeof node.isSummary !== \"function\") {\n return\n }\n\n if (!node.isSummary()) {\n const fileCoverage = typeof node.getFileCoverage === \"function\" ? node.getFileCoverage() : node.fileCoverage\n if (fileCoverage) {\n out.push(fileCoverage)\n }\n return\n }\n\n const children: any[] = typeof node.getChildren === \"function\" ? node.getChildren() : []\n for (const child of children) {\n collectFileCoverages(child, out)\n }\n}\n\nfunction sortReportTree(node: any): void {\n const children: any[] = Array.isArray(node?.children) ? node.children : []\n if (children.length === 0) {\n return\n }\n\n children.sort((a, b) => {\n const aKey = typeof a?.path?.toString === \"function\" ? a.path.toString() : \"\"\n const bKey = typeof b?.path?.toString === \"function\" ? b.path.toString() : \"\"\n return aKey < bKey ? -1 : aKey > bKey ? 1 : 0\n })\n\n for (const child of children) {\n sortReportTree(child)\n }\n}\n\nfunction isInsideCwd(relativePosix: string): boolean {\n if (!relativePosix) {\n return false\n }\n return !(relativePosix === \"..\" || relativePosix.startsWith(\"../\"))\n}\n\nfunction toPosix(input: string): string {\n return String(input ?? \"\").split(path.sep).join(\"/\")\n}\n\nfunction toFullVisitor(visitor: any): {\n onStart: (node: any, state: any) => void\n onEnd: (node: any, state: any) => void\n onSummary: (node: any, state: any) => void\n onSummaryEnd: (node: any, state: any) => void\n onDetail: (node: any, state: any) => void\n} {\n const call = (method: string) => (node: any, state: any) => {\n if (typeof visitor?.[method] === \"function\") {\n visitor[method](node, state)\n }\n }\n\n return {\n onStart: call(\"onStart\"),\n onEnd: call(\"onEnd\"),\n onSummary: call(\"onSummary\"),\n onSummaryEnd: call(\"onSummaryEnd\"),\n onDetail: call(\"onDetail\"),\n }\n}\n\nfunction cloneReportNode(node: any, parent: any): any {\n const clone = Object.create(Object.getPrototypeOf(node))\n clone.path = node.path\n clone.fileCoverage = node.fileCoverage\n clone.parent = parent\n\n const children: any[] = typeof node.getChildren === \"function\" ? node.getChildren() : []\n clone.children = children.flatMap((child) => cloneOrCollapseNode(child, clone))\n\n return clone\n}\n\nfunction cloneOrCollapseNode(node: any, parent: any): any[] {\n if (\n typeof node?.isSummary === \"function\"\n && node.isSummary()\n && typeof node.isRoot === \"function\"\n && !node.isRoot()\n && typeof node.getChildren === \"function\"\n ) {\n const children = node.getChildren()\n if (\n Array.isArray(children)\n && children.length === 1\n && typeof children[0]?.isSummary === \"function\"\n && !children[0].isSummary()\n ) {\n return [cloneReportNode(children[0], parent)]\n }\n }\n\n return [cloneReportNode(node, parent)]\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"console-text-report.js","names":[],"sources":["../../src/coverage/console-text-report.ts"],"sourcesContent":["import path from \"node:path\"\n\n\nconst DEFAULT_CONSOLE_MAX_COLS = 80\nconst CONSOLE_SUMMARIZER = \"rbCwd\"\n\nexport function generateConsoleTextCoverageReport(\n reports: any,\n context: any,\n): { output: string; summarizer: string | undefined } {\n const debug = resolveConsoleReportDebugInfo()\n const summarizer = registerConsoleSummarizer(context)\n writeConsoleReportDebugLog({ ...debug, summarizer })\n\n const reportOutput = createConsoleTextReportOutput(reports, context, {\n maxCols: debug.maxCols + 20,\n summarizer,\n })\n\n return { output: stripUncoveredLineNumbersColumn(reportOutput), summarizer }\n}\n\nfunction resolveConsoleReportDebugInfo(): {\n isTTY: boolean\n stdoutColumns: number | undefined\n envColumns: string | undefined\n maxCols: number\n } {\n const isTTY = Boolean(process.stdout.isTTY)\n const stdoutColumns = process.stdout.columns\n const envColumns = process.env.COLUMNS\n const maxCols = resolveConsoleMaxCols(stdoutColumns, envColumns)\n\n return { isTTY, stdoutColumns, envColumns, maxCols }\n}\n\nfunction resolveConsoleMaxCols(stdoutColumns: number | undefined, envColumns: string | undefined): number {\n if (typeof stdoutColumns === \"number\" && Number.isFinite(stdoutColumns) && stdoutColumns > 0) {\n return stdoutColumns\n }\n\n const parsed = typeof envColumns === \"string\" ? Number.parseInt(envColumns, 10) : Number.NaN\n if (Number.isFinite(parsed) && parsed > 0) {\n return parsed\n }\n\n return DEFAULT_CONSOLE_MAX_COLS\n}\n\nfunction writeConsoleReportDebugLog({\n isTTY,\n stdoutColumns,\n envColumns,\n maxCols,\n summarizer,\n}: {\n isTTY: boolean\n stdoutColumns: number | undefined\n envColumns: string | undefined\n maxCols: number\n summarizer: string | undefined\n}): void {\n const message = [\n \"[coverage] debug\",\n `stdout.isTTY=${isTTY ? \"1\" : \"0\"}`,\n `stdout.columns=${stdoutColumns ?? \"undefined\"}`,\n `env.COLUMNS=${envColumns ?? \"undefined\"}`,\n `resolvedMaxCols=${maxCols}`,\n `summarizer=${summarizer ?? \"undefined\"}`,\n ].join(\" \")\n\n process.stderr.write(`${message}\\n`)\n}\n\nfunction createConsoleTextReportOutput(\n reports: any,\n context: any,\n options: { maxCols: number; summarizer?: string },\n): string {\n const fileWriter = context?.writer\n const fileWriterCtor = fileWriter?.constructor\n\n if (\n !fileWriterCtor\n || typeof fileWriterCtor.startCapture !== \"function\"\n || typeof fileWriterCtor.stopCapture !== \"function\"\n || typeof fileWriterCtor.getOutput !== \"function\"\n || typeof fileWriterCtor.resetOutput !== \"function\"\n ) {\n reports.create(\"text\", { maxCols: options.maxCols, summarizer: options.summarizer }).execute(context)\n return \"\"\n }\n\n fileWriterCtor.resetOutput()\n fileWriterCtor.startCapture()\n try {\n reports.create(\"text\", { maxCols: options.maxCols, summarizer: options.summarizer }).execute(context)\n } finally {\n fileWriterCtor.stopCapture()\n }\n const output = fileWriterCtor.getOutput()\n fileWriterCtor.resetOutput()\n return output\n}\n\nfunction stripUncoveredLineNumbersColumn(output: string): string {\n const lines = output.split(\"\\n\")\n const filtered = lines.map((line) => {\n const parts = line.split(\"|\")\n if (parts.length < 6) {\n return line.trimEnd()\n }\n return parts.slice(0, 5).join(\"|\").trimEnd()\n })\n return filtered.join(\"\\n\")\n}\n\nfunction registerConsoleSummarizer(context: any): string | undefined {\n const summarizerFactory = context?._summarizerFactory\n if (!summarizerFactory || typeof summarizerFactory !== \"object\") {\n return undefined\n }\n\n if (CONSOLE_SUMMARIZER in summarizerFactory) {\n return CONSOLE_SUMMARIZER\n }\n\n const pkgTree = context.getTree?.(\"pkg\")\n const pkgRoot = pkgTree?.getRoot?.()\n if (!pkgRoot) {\n return undefined\n }\n\n summarizerFactory[CONSOLE_SUMMARIZER] = createCollapsedCwdTree(pkgRoot, process.cwd())\n return CONSOLE_SUMMARIZER\n}\n\nfunction createCollapsedCwdTree(\n root: any,\n cwd: string,\n): { getRoot: () => any; visit: (visitor: any, state: any) => void } {\n const treeRoot = createCwdTreeFromCoverage(root, cwd)\n const clonedRoot = cloneReportNode(treeRoot, null)\n return {\n getRoot: () => clonedRoot,\n visit: (visitor: any, state: any) => {\n const fullVisitor = toFullVisitor(visitor)\n fullVisitor.onStart(clonedRoot, state)\n clonedRoot.visit(fullVisitor, state)\n fullVisitor.onEnd(clonedRoot, state)\n },\n }\n}\n\nfunction createCwdTreeFromCoverage(root: any, cwd: string): any {\n const proto = Object.getPrototypeOf(root)\n const pathCtor = root?.path?.constructor\n\n const fileCoverages: any[] = []\n collectFileCoverages(root, fileCoverages)\n\n const treeRoot = Object.create(proto)\n treeRoot.path = pathCtor ? new pathCtor([]) : root.path\n treeRoot.fileCoverage = null\n treeRoot.parent = null\n treeRoot.children = []\n\n const dirNodes = new Map<string, any>()\n dirNodes.set(\"\", treeRoot)\n\n for (const fileCoverage of fileCoverages) {\n const absolutePath = path.resolve(String(fileCoverage?.path ?? \"\"))\n if (!absolutePath) {\n continue\n }\n\n let relativePath = toPosix(path.relative(cwd, absolutePath))\n if (!relativePath) {\n relativePath = toPosix(absolutePath)\n }\n\n if (isInsideCwd(relativePath) && (relativePath === \"src\" || relativePath.startsWith(\"src/\"))) {\n relativePath = relativePath === \"src\" ? \"\" : relativePath.slice(\"src/\".length)\n }\n\n if (!relativePath) {\n relativePath = toPosix(path.basename(absolutePath))\n }\n\n const segments = relativePath.split(\"/\").filter(Boolean)\n if (segments.length === 0) {\n continue\n }\n\n let parent = treeRoot\n let prefix = \"\"\n\n for (let i = 0; i < segments.length - 1; i += 1) {\n prefix = prefix ? `${prefix}/${segments[i]}` : segments[i]\n const existing = dirNodes.get(prefix)\n if (existing) {\n parent = existing\n continue\n }\n\n const dirNode = Object.create(proto)\n dirNode.path = pathCtor ? new pathCtor(prefix.split(\"/\")) : root.path\n dirNode.fileCoverage = null\n dirNode.parent = parent\n dirNode.children = []\n parent.children.push(dirNode)\n dirNodes.set(prefix, dirNode)\n parent = dirNode\n }\n\n const fileNode = Object.create(proto)\n fileNode.path = pathCtor ? new pathCtor(segments) : root.path\n fileNode.fileCoverage = fileCoverage\n fileNode.parent = parent\n fileNode.children = []\n parent.children.push(fileNode)\n }\n\n sortReportTree(treeRoot)\n\n return treeRoot\n}\n\nfunction collectFileCoverages(node: any, out: any[]): void {\n if (!node || typeof node.isSummary !== \"function\") {\n return\n }\n\n if (!node.isSummary()) {\n const fileCoverage = typeof node.getFileCoverage === \"function\" ? node.getFileCoverage() : node.fileCoverage\n if (fileCoverage) {\n out.push(fileCoverage)\n }\n return\n }\n\n const children: any[] = typeof node.getChildren === \"function\" ? node.getChildren() : []\n for (const child of children) {\n collectFileCoverages(child, out)\n }\n}\n\nfunction sortReportTree(node: any): void {\n const children: any[] = Array.isArray(node?.children) ? node.children : []\n if (children.length === 0) {\n return\n }\n\n children.sort((a, b) => {\n const aKey = typeof a?.path?.toString === \"function\" ? a.path.toString() : \"\"\n const bKey = typeof b?.path?.toString === \"function\" ? b.path.toString() : \"\"\n return aKey < bKey ? -1 : aKey > bKey ? 1 : 0\n })\n\n for (const child of children) {\n sortReportTree(child)\n }\n}\n\nfunction isInsideCwd(relativePosix: string): boolean {\n if (!relativePosix) {\n return false\n }\n return !(relativePosix === \"..\" || relativePosix.startsWith(\"../\"))\n}\n\nfunction toPosix(input: string): string {\n return String(input ?? \"\").split(path.sep).join(\"/\")\n}\n\nfunction toFullVisitor(visitor: any): {\n onStart: (node: any, state: any) => void\n onEnd: (node: any, state: any) => void\n onSummary: (node: any, state: any) => void\n onSummaryEnd: (node: any, state: any) => void\n onDetail: (node: any, state: any) => void\n} {\n const call = (method: string) => (node: any, state: any) => {\n if (typeof visitor?.[method] === \"function\") {\n visitor[method](node, state)\n }\n }\n\n return {\n onStart: call(\"onStart\"),\n onEnd: call(\"onEnd\"),\n onSummary: call(\"onSummary\"),\n onSummaryEnd: call(\"onSummaryEnd\"),\n onDetail: call(\"onDetail\"),\n }\n}\n\nfunction cloneReportNode(node: any, parent: any): any {\n const clone = Object.create(Object.getPrototypeOf(node))\n clone.path = node.path\n clone.fileCoverage = node.fileCoverage\n clone.parent = parent\n\n const children: any[] = typeof node.getChildren === \"function\" ? node.getChildren() : []\n clone.children = children.flatMap((child) => cloneOrCollapseNode(child, clone))\n\n return clone\n}\n\nfunction cloneOrCollapseNode(node: any, parent: any): any[] {\n if (\n typeof node?.isSummary === \"function\"\n && node.isSummary()\n && typeof node.isRoot === \"function\"\n && !node.isRoot()\n && typeof node.getChildren === \"function\"\n ) {\n const children = node.getChildren()\n if (\n Array.isArray(children)\n && children.length === 1\n && typeof children[0]?.isSummary === \"function\"\n && !children[0].isSummary()\n ) {\n return [cloneReportNode(children[0], parent)]\n }\n }\n\n return [cloneReportNode(node, parent)]\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"files.js","names":[],"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"],"mappings":";;;AAMA,SAAS,qBAAqB,QAAkC;CAC9D,MAAM,WAAW,KAAK,KAAK,OAAO,SAAS,OAAO;CAClD,MAAM,QAAQ;EACZ,KAAK,KAAK,UAAU,cAAc,UAAU;EAC5C,KAAK,KAAK,UAAU,UAAU,UAAU;EACxC,KAAK,KAAK,OAAO,iBAAiB,YAAY;EAC9C,KAAK,KAAK,OAAO,iBAAiB,QAAQ;
|
|
1
|
+
{"version":3,"file":"files.js","names":[],"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"],"mappings":";;;AAMA,SAAS,qBAAqB,QAAkC;CAC9D,MAAM,WAAW,KAAK,KAAK,OAAO,SAAS,OAAO;CAClD,MAAM,QAAQ;EACZ,KAAK,KAAK,UAAU,cAAc,UAAU;EAC5C,KAAK,KAAK,UAAU,UAAU,UAAU;EACxC,KAAK,KAAK,OAAO,iBAAiB,YAAY;EAC9C,KAAK,KAAK,OAAO,iBAAiB,QAAQ;CAC5C;CAEA,OAAO,MAAM,KAAK,IAAI,IAAI,MAAM,KAAK,SAAS,KAAK,QAAQ,IAAI,CAAC,CAAC,CAAC;AACpE;AAEA,eAAsB,kBACpB,QACA,MACmB;CACnB,MAAM,QAAQ,SAAS,KAAA,IAAY,qBAAqB,MAAM,IAAI,MAAM,QAAQ,IAAI,IAAI,OAAO,CAAC,IAAI;CACpG,MAAM,QAAkB,CAAC;CAEzB,eAAe,KAAK,SAAgC;EAClD,MAAM,UAAU,MAAM,GAAG,QAAQ,SAAS,EAAE,eAAe,KAAK,CAAC;EACjE,MAAM,QAAQ,IACZ,QAAQ,IAAI,OAAO,UAAU;GAC3B,MAAM,YAAY,KAAK,KAAK,SAAS,MAAM,IAAI;GAC/C,IAAI,MAAM,YAAY,GACpB,MAAM,KAAK,SAAS;QACf,IAAI,MAAM,OAAO,KAAK,MAAM,SAAS,OAAO,kBACjD,MAAM,KAAK,SAAS;EAExB,CAAC,CACH;CACF;CAEA,KAAK,MAAM,QAAQ,OAAO;EACxB,IAAI;GAEF,IAAI,EAAC,MADe,GAAG,KAAK,IAAI,EAAA,CACrB,YAAY,GACrB;EAEJ,QAAQ;GACN;EACF;EAEA,MAAM,KAAK,IAAI;CACjB;CAEA,OAAO,MAAM,KAAK;AACpB;AAEA,eAAsB,oBACpB,QACA,MACe;CACf,MAAM,QAAQ,SAAS,KAAA,IAAY,qBAAqB,MAAM,IAAI,MAAM,QAAQ,IAAI,IAAI,OAAO,CAAC,IAAI;CAEpG,eAAe,KAAK,SAAgC;EAClD,MAAM,UAAU,MAAM,GAAG,QAAQ,SAAS,EAAE,eAAe,KAAK,CAAC;EACjE,MAAM,QAAQ,IACZ,QAAQ,IAAI,OAAO,UAAU;GAC3B,MAAM,YAAY,KAAK,KAAK,SAAS,MAAM,IAAI;GAC/C,IAAI,MAAM,YAAY,GACpB,MAAM,KAAK,SAAS;QACf,IAAI,MAAM,OAAO,KAAK,MAAM,SAAS,OAAO,kBACjD,MAAM,GAAG,GAAG,WAAW,EAAE,OAAO,KAAK,CAAC;EAE1C,CAAC,CACH;CACF;CAEA,KAAK,MAAM,QAAQ,OACjB,IAAI;EACF,MAAM,KAAK,IAAI;CACjB,QAAQ,CAER;AAEJ"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fixtures.js","names":[],"sources":["../../src/coverage/fixtures.ts"],"sourcesContent":["import type { Page, TestInfo } from \"@playwright/test\"\n\nimport { createCoverageTracker } from \"./v8-tracker\"\nimport type { CoverageConfig } from \"./types\"\n\n\ntype CoverageTracker = {\n stop: (testInfo: TestInfo) => Promise<void>\n}\n\nfunction isChromiumPage(page: Page): boolean {\n return page.context().browser()?.browserType().name() === \"chromium\"\n}\n\nfunction shouldSilenceCoverageInitError(error: unknown): boolean {\n const message = error instanceof Error ? error.message : String(error)\n return message.includes(\"Script execution is prohibited\")\n || message.includes(\"CDP session is only available in Chromium\")\n}\n\nfunction noopTracker(): CoverageTracker {\n return {\n async stop() {\n // no-op\n },\n }\n}\n\nexport function createCoverageFixtures<T extends { extend: (fixtures: any) => unknown }>(\n baseTest: T,\n config: CoverageConfig,\n): T {\n return baseTest.extend({\n page: async (\n { page }: { page: Page },\n use: (page: Page) => Promise<void>,\n testInfo: TestInfo,\n ) => {\n let tracker: CoverageTracker = noopTracker()\n\n if (config.coverageEnabled && isChromiumPage(page)) {\n try {\n tracker = await createCoverageTracker(page, config)\n } catch (error) {\n if (shouldSilenceCoverageInitError(error)) {\n tracker = noopTracker()\n } else {\n console.warn(\"[coverage] failed to initialize V8 coverage:\", error)\n }\n }\n }\n\n try {\n // eslint-disable-next-line react-hooks/rules-of-hooks\n await use(page)\n } finally {\n try {\n await tracker.stop(testInfo)\n } catch (error) {\n console.warn(\"[coverage] failed to record V8 coverage:\", error)\n }\n }\n },\n }) as T\n}\n"],"mappings":";;AAUA,SAAS,eAAe,MAAqB;CAC3C,OAAO,KAAK,QAAQ,CAAC,CAAC,QAAQ,CAAC,EAAE,YAAY,CAAC,CAAC,KAAK,MAAM;AAC5D;AAEA,SAAS,+BAA+B,OAAyB;CAC/D,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;CACrE,OAAO,QAAQ,SAAS,gCAAgC,KACnD,QAAQ,SAAS,2CAA2C;AACnE;AAEA,SAAS,cAA+B;CACtC,OAAO,EACL,MAAM,OAAO,
|
|
1
|
+
{"version":3,"file":"fixtures.js","names":[],"sources":["../../src/coverage/fixtures.ts"],"sourcesContent":["import type { Page, TestInfo } from \"@playwright/test\"\n\nimport { createCoverageTracker } from \"./v8-tracker\"\nimport type { CoverageConfig } from \"./types\"\n\n\ntype CoverageTracker = {\n stop: (testInfo: TestInfo) => Promise<void>\n}\n\nfunction isChromiumPage(page: Page): boolean {\n return page.context().browser()?.browserType().name() === \"chromium\"\n}\n\nfunction shouldSilenceCoverageInitError(error: unknown): boolean {\n const message = error instanceof Error ? error.message : String(error)\n return message.includes(\"Script execution is prohibited\")\n || message.includes(\"CDP session is only available in Chromium\")\n}\n\nfunction noopTracker(): CoverageTracker {\n return {\n async stop() {\n // no-op\n },\n }\n}\n\nexport function createCoverageFixtures<T extends { extend: (fixtures: any) => unknown }>(\n baseTest: T,\n config: CoverageConfig,\n): T {\n return baseTest.extend({\n page: async (\n { page }: { page: Page },\n use: (page: Page) => Promise<void>,\n testInfo: TestInfo,\n ) => {\n let tracker: CoverageTracker = noopTracker()\n\n if (config.coverageEnabled && isChromiumPage(page)) {\n try {\n tracker = await createCoverageTracker(page, config)\n } catch (error) {\n if (shouldSilenceCoverageInitError(error)) {\n tracker = noopTracker()\n } else {\n console.warn(\"[coverage] failed to initialize V8 coverage:\", error)\n }\n }\n }\n\n try {\n // eslint-disable-next-line react-hooks/rules-of-hooks\n await use(page)\n } finally {\n try {\n await tracker.stop(testInfo)\n } catch (error) {\n console.warn(\"[coverage] failed to record V8 coverage:\", error)\n }\n }\n },\n }) as T\n}\n"],"mappings":";;AAUA,SAAS,eAAe,MAAqB;CAC3C,OAAO,KAAK,QAAQ,CAAC,CAAC,QAAQ,CAAC,EAAE,YAAY,CAAC,CAAC,KAAK,MAAM;AAC5D;AAEA,SAAS,+BAA+B,OAAyB;CAC/D,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;CACrE,OAAO,QAAQ,SAAS,gCAAgC,KACnD,QAAQ,SAAS,2CAA2C;AACnE;AAEA,SAAS,cAA+B;CACtC,OAAO,EACL,MAAM,OAAO,CAEb,EACF;AACF;AAEA,SAAgB,uBACd,UACA,QACG;CACH,OAAO,SAAS,OAAO,EACrB,MAAM,OACJ,EAAE,QACF,KACA,aACG;EACH,IAAI,UAA2B,YAAY;EAE3C,IAAI,OAAO,mBAAmB,eAAe,IAAI,GAC/C,IAAI;GACF,UAAU,MAAM,sBAAsB,MAAM,MAAM;EACpD,SAAS,OAAO;GACd,IAAI,+BAA+B,KAAK,GACtC,UAAU,YAAY;QAEtB,QAAQ,KAAK,gDAAgD,KAAK;EAEtE;EAGF,IAAI;GAEF,MAAM,IAAI,IAAI;EAChB,UAAU;GACR,IAAI;IACF,MAAM,QAAQ,KAAK,QAAQ;GAC7B,SAAS,OAAO;IACd,QAAQ,KAAK,4CAA4C,KAAK;GAChE;EACF;CACF,EACF,CAAC;AACH"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"report.js","names":[],"sources":["../../src/coverage/report.ts"],"sourcesContent":["import fs from \"node:fs/promises\"\nimport path from \"node:path\"\nimport { fileURLToPath } from \"node:url\"\n\nimport * as libCoverage from \"istanbul-lib-coverage\"\nimport * as libInstrument from \"istanbul-lib-instrument\"\nimport fg from \"fast-glob\"\nimport picomatch from \"picomatch\"\nimport v8ToIstanbul from \"v8-to-istanbul\"\n\nimport { createCollectCoverageMatcher, toPosix } from \"./collect\"\nimport { generateConsoleTextCoverageReport } from \"./console-text-report\"\nimport { findCoverageFiles } from \"./files\"\nimport type { CoverageConfig, CoverageThresholdTarget, CoverageThresholds } from \"./types\"\n\n\nconst TEXT_REPORT_FILENAME = \"coverage.txt\"\n\nexport class CoverageThresholdError extends Error {\n constructor(message: string) {\n super(message)\n this.name = \"CoverageThresholdError\"\n }\n}\n\nexport async function generateCoverageReport(config: CoverageConfig): Promise<void> {\n const coverageFiles = await findCoverageFiles(config)\n\n if (coverageFiles.length === 0) {\n console.warn(\"[coverage] no V8 coverage artifacts were generated\")\n return\n }\n\n const coverageLib = resolveCoverageLib()\n const coverageMap = coverageLib.createCoverageMap({})\n const matchesCollectCoverageFrom = createCollectCoverageMatcher(config.collectCoverageFrom, config.rootDir)\n\n for (const file of coverageFiles) {\n const payload = await readCoverageFile(file)\n if (!payload) {\n continue\n }\n\n for (const script of payload.scripts as any[]) {\n await mergeScriptCoverage(coverageMap, script, config, matchesCollectCoverageFrom)\n }\n }\n\n if (config.includeAllFiles) {\n await includeUntestedFiles(coverageMap, config, matchesCollectCoverageFrom)\n }\n\n if (coverageMap.files().length === 0) {\n console.warn(\"[coverage] no library files matched the coverage filters\")\n return\n }\n\n await fs.rm(config.coverageReportDir, { recursive: true, force: true })\n await fs.mkdir(config.coverageReportDir, { recursive: true })\n\n const { createContext, reports } = await loadIstanbulModules()\n const context = createContext({\n dir: config.coverageReportDir,\n coverageMap,\n defaultSummarizer: \"pkg\",\n })\n\n const { output: reportOutput, summarizer } = generateConsoleTextCoverageReport(reports, context)\n process.stdout.write(reportOutput)\n reports.create(\"text\", { file: TEXT_REPORT_FILENAME, summarizer }).execute(context)\n\n console.log(`[coverage] Full text report saved to ${path.join(config.coverageReportDir, TEXT_REPORT_FILENAME)}`)\n\n const summary = coverageMap.getCoverageSummary()\n enforceThresholds(summary, config.thresholds, \"global\")\n\n const targets: CoverageThresholdTarget[] = Array.isArray(config.thresholdTargets) ? config.thresholdTargets : []\n if (targets.length > 0) {\n const fileSummaries = buildFileSummaries(coverageMap, config.rootDir)\n for (const target of targets) {\n const matcher = createGlobMatcher(target.pattern)\n const matchResult = collectTargetSummary(fileSummaries, matcher, coverageLib)\n\n if (matchResult.matched === 0) {\n console.warn(\n `[coverage] threshold pattern \"${target.pattern}\" did not match any files — skipping`,\n )\n continue\n }\n\n enforceThresholds(matchResult.summary, target.thresholds, target.pattern)\n }\n }\n}\n\nexport async function collectCoveredFiles(config: CoverageConfig): Promise<string[]> {\n const coverageFiles = await findCoverageFiles(config)\n if (coverageFiles.length === 0) {\n return []\n }\n\n const coverageLib = resolveCoverageLib()\n const coverageMap = coverageLib.createCoverageMap({})\n const matchesCollectCoverageFrom = createCollectCoverageMatcher(config.collectCoverageFrom, config.rootDir)\n\n for (const file of coverageFiles) {\n const payload = await readCoverageFile(file)\n if (!payload) {\n continue\n }\n\n for (const script of payload.scripts as any[]) {\n await mergeScriptCoverage(coverageMap, script, config, matchesCollectCoverageFrom)\n }\n }\n\n return coverageMap.files().sort()\n}\n\nasync function loadIstanbulModules(): Promise<{ createContext: (opts: any) => any; reports: any }> {\n maybeForceColor()\n const [libReportMod, reportsMod]: any[] = await Promise.all([\n import(\"istanbul-lib-report\"),\n import(\"istanbul-reports\"),\n ])\n\n const createContext = typeof libReportMod.createContext === \"function\"\n ? libReportMod.createContext\n : libReportMod.default?.createContext\n\n if (typeof createContext !== \"function\") {\n throw new Error(\"istanbul-lib-report exports are unavailable\")\n }\n\n return {\n createContext,\n reports: reportsMod.default ?? reportsMod,\n }\n}\n\nfunction maybeForceColor(): void {\n if (process.stdout.isTTY) {\n return\n }\n\n if (process.env.FORCE_COLOR !== undefined) {\n return\n }\n\n if (process.env.NO_COLOR !== undefined || process.env.NODE_DISABLE_COLORS !== undefined) {\n return\n }\n\n if (process.env.CI !== undefined) {\n return\n }\n\n process.env.FORCE_COLOR = \"1\"\n}\n\nasync function mergeScriptCoverage(\n coverageMap: any,\n script: any,\n config: CoverageConfig,\n matchesCollectCoverageFrom: (absolutePath: string) => boolean,\n): Promise<void> {\n const scriptPath = script.absolutePath\n if (!scriptPath) {\n return\n }\n\n if (isNodeModulesPath(scriptPath)) {\n return\n }\n\n if (isViteVirtualModulePath(scriptPath)) {\n return\n }\n\n let source = script.source && script.source.length > 0\n ? script.source\n : \"\"\n\n if (!source) {\n try {\n source = await fs.readFile(scriptPath, \"utf8\")\n } catch (error: any) {\n const base = path.basename(scriptPath)\n if (error?.code === \"ENOENT\" && base && !base.includes(\".\")) {\n return\n }\n if (error?.code === \"ENOENT\" && !matchesCollectCoverageFrom(scriptPath)) {\n return\n }\n throw error\n }\n }\n\n const sourceMap = await loadSourceMapForScript(scriptPath, source)\n const converter = v8ToIstanbul(\n scriptPath,\n 0,\n sourceMap ? { source, sourceMap: { sourcemap: sourceMap } } : { source },\n )\n await converter.load()\n converter.applyCoverage(script.functions)\n\n const filtered = filterCoverageMap(converter.toIstanbul(), config, matchesCollectCoverageFrom)\n if (Object.keys(filtered).length > 0) {\n coverageMap.merge(filtered)\n }\n}\n\nasync function readCoverageFile(file: string): Promise<any | null> {\n try {\n const raw = await fs.readFile(file, \"utf8\")\n return JSON.parse(raw)\n } catch (error) {\n console.warn(`[coverage] failed to parse ${file}:`, error)\n return null\n }\n}\n\nfunction enforceThresholds(summary: any, thresholds: CoverageThresholds, label = \"global\"): void {\n const failures = []\n\n for (const metric of Object.keys(thresholds) as Array<keyof CoverageThresholds>) {\n const minimum = thresholds[metric]\n const actual = summary[metric]?.pct ?? 0\n if (actual < minimum) {\n failures.push({ metric, actual, minimum })\n }\n }\n\n if (failures.length === 0) {\n return\n }\n\n const details = failures\n .map(({ metric, actual, minimum }) => `${metric}: ${actual.toFixed(2)}% < ${minimum}%`)\n .join(\"; \")\n\n throw new CoverageThresholdError(`[coverage] thresholds not met (target: ${label}) — ${details}`)\n}\n\nfunction resolveCoverageLib(): any {\n const candidate: any = libCoverage as any\n if (typeof candidate.createCoverageMap === \"function\") {\n return candidate\n }\n\n if (candidate.default && typeof candidate.default.createCoverageMap === \"function\") {\n return candidate.default\n }\n\n throw new Error(\"istanbul-lib-coverage exports are unavailable\")\n}\n\nfunction resolveInstrumentLib(): any {\n const candidate: any = libInstrument as any\n if (typeof candidate.createInstrumenter === \"function\") {\n return candidate\n }\n\n if (candidate.default && typeof candidate.default.createInstrumenter === \"function\") {\n return candidate.default\n }\n\n throw new Error(\"istanbul-lib-instrument exports are unavailable\")\n}\n\nasync function includeUntestedFiles(\n coverageMap: any,\n config: CoverageConfig,\n matchesCollectCoverageFrom: (absolutePath: string) => boolean,\n): Promise<void> {\n const existing = new Set(\n coverageMap.files().map((filePath: unknown) => path.resolve(String(filePath ?? \"\"))),\n )\n\n const candidates = await findCollectCoverageFiles(config, matchesCollectCoverageFrom)\n if (candidates.length === 0) {\n return\n }\n\n const instrumentLib = resolveInstrumentLib()\n const instrumenter = instrumentLib.createInstrumenter({\n esModules: true,\n parserPlugins: [\n \"typescript\",\n \"jsx\",\n \"classProperties\",\n \"classPrivateProperties\",\n \"classPrivateMethods\",\n \"decorators-legacy\",\n \"importMeta\",\n \"topLevelAwait\",\n ],\n })\n\n for (const filePath of candidates) {\n const normalized = path.resolve(filePath)\n if (existing.has(normalized)) {\n continue\n }\n\n const source = await fs.readFile(normalized, \"utf8\").catch(() => null)\n if (source === null) {\n continue\n }\n\n try {\n instrumenter.instrumentSync(source, normalized)\n const fileCoverage = instrumenter.lastFileCoverage()\n if (!fileCoverage) {\n continue\n }\n coverageMap.addFileCoverage(fileCoverage)\n existing.add(normalized)\n } catch (error) {\n const relative = path.relative(config.rootDir, normalized)\n console.warn(\n `[coverage] failed to instrument ${relative && !relative.startsWith(\"..\") ? relative : normalized}:`,\n error,\n )\n }\n }\n}\n\nconst DEFAULT_COLLECT_COVERAGE_IGNORES = [\n \"**/.git/**\",\n \"**/.next/**\",\n \"**/.turbo/**\",\n \"**/.vite/**\",\n \"**/.vitest/**\",\n \"**/build/**\",\n \"**/coverage/**\",\n \"**/dist/**\",\n \"**/node_modules/**\",\n \"**/playwright-report/**\",\n \"**/spec/**\",\n \"**/test/**\",\n \"**/test-results/**\",\n \"**/tests/**\",\n \"**/__tests__/**\",\n \"**/*.d.ts\",\n \"**/*.map\",\n]\n\nasync function findCollectCoverageFiles(\n config: CoverageConfig,\n matchesCollectCoverageFrom: (absolutePath: string) => boolean,\n): Promise<string[]> {\n const patterns = Array.isArray(config.collectCoverageFrom)\n ? config.collectCoverageFrom\n : []\n\n if (patterns.length === 0) {\n return []\n }\n\n const rawFiles = await fg(patterns, {\n cwd: config.rootDir,\n absolute: true,\n dot: true,\n onlyFiles: true,\n unique: true,\n followSymbolicLinks: false,\n ignore: DEFAULT_COLLECT_COVERAGE_IGNORES,\n }).catch(() => [])\n\n const collected = new Set<string>()\n\n for (const file of rawFiles) {\n const normalized = path.resolve(String(file ?? \"\"))\n if (!normalized) {\n continue\n }\n\n if (normalized.endsWith(\".d.ts\") || normalized.endsWith(\".map\")) {\n continue\n }\n\n if (isNodeModulesPath(normalized)) {\n continue\n }\n\n if (isViteVirtualModulePath(normalized)) {\n continue\n }\n\n if (!matchesCollectCoverageFrom(normalized)) {\n continue\n }\n\n collected.add(normalized)\n }\n\n return Array.from(collected).sort()\n}\n\nfunction buildFileSummaries(\n coverageMap: any,\n rootDir: string,\n): Array<{ summary: any; candidates: string[] }> {\n const normalizedRoot = path.resolve(rootDir)\n return coverageMap.files().map((filePath: string) => {\n const normalizedAbsolute = path.resolve(filePath)\n const summary = coverageMap.fileCoverageFor(filePath).toSummary()\n const relativePath = path.relative(normalizedRoot, normalizedAbsolute)\n const candidates = new Set<string>()\n\n if (relativePath) {\n const relativePosix = toPosix(relativePath)\n candidates.add(relativePosix)\n candidates.add(`./${relativePosix}`)\n } else {\n candidates.add(toPosix(path.basename(normalizedAbsolute)))\n }\n\n return {\n summary,\n candidates: Array.from(candidates),\n }\n })\n}\n\nfunction collectTargetSummary(\n fileSummaries: Array<{ summary: any; candidates: string[] }>,\n matcher: (candidate: string) => boolean,\n coverageLib: any,\n): { summary: any; matched: number } {\n const summary = coverageLib.createCoverageSummary()\n let matched = 0\n\n for (const file of fileSummaries) {\n if (file.candidates.some((candidate) => matcher(candidate))) {\n summary.merge(file.summary)\n matched += 1\n }\n }\n\n return { summary, matched }\n}\n\nfunction createGlobMatcher(pattern: string): (candidate: string) => boolean {\n const normalized = toPosix(String(pattern ?? \"\")).trim()\n if (!normalized) {\n return () => false\n }\n if (isAbsoluteGlobPattern(normalized)) {\n throw new Error(`[coverage] threshold patterns must be relative (absolute paths are not supported): \"${pattern}\"`)\n }\n return picomatch(normalized, { dot: true })\n}\n\nfunction isAbsoluteGlobPattern(pattern: string): boolean {\n const normalized = String(pattern ?? \"\").trim()\n if (!normalized) {\n return false\n }\n\n if (normalized.startsWith(\"/\")) {\n return true\n }\n\n if (normalized.startsWith(\"file://\")) {\n return true\n }\n\n return /^[A-Za-z]:\\//.test(normalized)\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 extractSourceMappingUrl(source: string): string | null {\n const regex = /\\/\\/[#@]\\s*sourceMappingURL=([^\\s]+)/g\n\n let last = null\n let match = null\n\n while ((match = regex.exec(source)) !== null) {\n last = match[1]\n }\n\n return typeof last === \"string\" && last.length > 0 ? last : null\n}\n\nfunction resolveSourceMapPath(scriptPath: string, mappingUrl: string): string {\n const cleaned = stripQuery(mappingUrl)\n\n if (cleaned.startsWith(\"file://\")) {\n return fileURLToPath(cleaned)\n }\n\n if (path.isAbsolute(cleaned)) {\n return cleaned\n }\n\n return path.resolve(path.dirname(scriptPath), cleaned)\n}\n\nfunction filterCoverageMap(\n map: any,\n config: CoverageConfig,\n matchesCollectCoverageFrom: (absolutePath: string) => boolean,\n): Record<string, any> {\n if (!map || typeof map !== \"object\") {\n return {}\n }\n\n const filtered: Record<string, any> = {}\n\n for (const [filePath, fileCoverage] of Object.entries(map)) {\n const absolutePath = resolveCoveragePath(filePath, config.rootDir)\n if (!absolutePath) {\n continue\n }\n\n if (absolutePath.endsWith(\".d.ts\") || absolutePath.endsWith(\".map\")) {\n continue\n }\n\n if (isNodeModulesPath(absolutePath)) {\n continue\n }\n\n if (isViteVirtualModulePath(absolutePath)) {\n continue\n }\n\n if (!matchesCollectCoverageFrom(absolutePath)) {\n continue\n }\n\n if (fileCoverage && typeof fileCoverage === \"object\") {\n filtered[absolutePath] = { ...fileCoverage, path: absolutePath }\n } else {\n filtered[absolutePath] = fileCoverage\n }\n }\n\n return filtered\n}\n\nfunction resolveCoveragePath(filePath: string, rootDir: string): string | null {\n const raw = String(filePath ?? \"\").trim()\n if (!raw) {\n return null\n }\n\n const cleaned = stripQuery(raw)\n\n if (cleaned.startsWith(\"file://\")) {\n try {\n return path.normalize(fileURLToPath(cleaned))\n } catch {\n return null\n }\n }\n\n if (path.isAbsolute(cleaned)) {\n return path.normalize(cleaned)\n }\n\n if (cleaned.includes(\"://\")) {\n return null\n }\n\n return path.normalize(path.resolve(rootDir, cleaned))\n}\n\nfunction isNodeModulesPath(filePath: string): boolean {\n return path\n .normalize(String(filePath ?? \"\"))\n .split(path.sep)\n .includes(\"node_modules\")\n}\n\nfunction isViteVirtualModulePath(filePath: string): boolean {\n const normalized = path.normalize(String(filePath ?? \"\"))\n const baseName = path.basename(normalized)\n return baseName === \"__vite-browser-external\"\n || baseName.startsWith(\"__vite-browser-external:\")\n || baseName.startsWith(\"__vite-\")\n}\n\nfunction parseSourceMapPayload(raw: any): any | null {\n if (!raw || typeof raw !== \"object\") {\n return null\n }\n\n const sources = raw.sources\n if (!Array.isArray(sources) || sources.length === 0) {\n return null\n }\n\n return raw\n}\n\nfunction normalizeSourceMap(sourceMap: any, scriptPath: string): any {\n const root = typeof sourceMap.sourceRoot === \"string\"\n ? sourceMap.sourceRoot.replace(\"file://\", \"\")\n : \"\"\n\n const dir = path.dirname(scriptPath)\n const fixedSources = sourceMap.sources.map((source: unknown) => {\n const raw = String(source ?? \"\")\n const cleaned = stripQuery(raw)\n\n if (cleaned.startsWith(\"file://\")) {\n try {\n return path.normalize(fileURLToPath(cleaned))\n } catch {\n return cleaned\n }\n }\n\n const withoutWebpack = cleaned.replace(/^webpack:\\/\\//, \"\")\n const candidate = path.join(root, withoutWebpack)\n\n if (path.isAbsolute(candidate)) {\n return path.normalize(candidate)\n }\n\n const normalizedCandidate = candidate.split(\"/\").join(path.sep)\n\n if (dir.endsWith(`${path.sep}dist`) && !normalizedCandidate.startsWith(`..${path.sep}`)) {\n if (normalizedCandidate.startsWith(`src${path.sep}`) || normalizedCandidate.startsWith(`lib${path.sep}`)) {\n return path.normalize(path.resolve(dir, \"..\", normalizedCandidate))\n }\n }\n\n return path.normalize(path.resolve(dir, normalizedCandidate))\n })\n\n return {\n ...sourceMap,\n sources: fixedSources,\n }\n}\n\nasync function loadSourceMapForScript(scriptPath: string, source: string): Promise<any | null> {\n const mappingUrl = extractSourceMappingUrl(source)\n if (!mappingUrl) {\n return null\n }\n\n const cleaned = stripQuery(mappingUrl)\n\n if (cleaned.startsWith(\"data:\")) {\n const commaIndex = cleaned.indexOf(\",\")\n if (commaIndex === -1) {\n return null\n }\n\n const meta = cleaned.slice(0, commaIndex)\n const payload = cleaned.slice(commaIndex + 1)\n const raw = meta.includes(\";base64\")\n ? Buffer.from(payload, \"base64\").toString(\"utf8\")\n : decodeURIComponent(payload)\n\n try {\n const parsed = parseSourceMapPayload(JSON.parse(raw))\n return parsed ? normalizeSourceMap(parsed, scriptPath) : null\n } catch {\n return null\n }\n }\n\n try {\n const mapPath = resolveSourceMapPath(scriptPath, cleaned)\n const raw = await fs.readFile(mapPath, \"utf8\")\n const parsed = parseSourceMapPayload(JSON.parse(raw))\n return parsed ? normalizeSourceMap(parsed, scriptPath) : null\n } catch {\n return null\n }\n}\n"],"mappings":";;;;;;;;;;;;AAgBA,IAAM,uBAAuB;AAE7B,IAAa,yBAAb,cAA4C,MAAM;CAChD,YAAY,SAAiB;EAC3B,MAAM,OAAO;EACb,KAAK,OAAO;CACd;AACF;AAEA,eAAsB,uBAAuB,QAAuC;CAClF,MAAM,gBAAgB,MAAM,kBAAkB,MAAM;CAEpD,IAAI,cAAc,WAAW,GAAG;EAC9B,QAAQ,KAAK,oDAAoD;EACjE;CACF;CAEA,MAAM,cAAc,mBAAmB;CACvC,MAAM,cAAc,YAAY,kBAAkB,CAAC,CAAC;CACpD,MAAM,6BAA6B,6BAA6B,OAAO,qBAAqB,OAAO,OAAO;CAE1G,KAAK,MAAM,QAAQ,eAAe;EAChC,MAAM,UAAU,MAAM,iBAAiB,IAAI;EAC3C,IAAI,CAAC,SACH;EAGF,KAAK,MAAM,UAAU,QAAQ,SAC3B,MAAM,oBAAoB,aAAa,QAAQ,QAAQ,0BAA0B;CAErF;CAEA,IAAI,OAAO,iBACT,MAAM,qBAAqB,aAAa,QAAQ,0BAA0B;CAG5E,IAAI,YAAY,MAAM,CAAC,CAAC,WAAW,GAAG;EACpC,QAAQ,KAAK,0DAA0D;EACvE;CACF;CAEA,MAAM,GAAG,GAAG,OAAO,mBAAmB;EAAE,WAAW;EAAM,OAAO;CAAK,CAAC;CACtE,MAAM,GAAG,MAAM,OAAO,mBAAmB,EAAE,WAAW,KAAK,CAAC;CAE5D,MAAM,EAAE,eAAe,YAAY,MAAM,oBAAoB;CAC7D,MAAM,UAAU,cAAc;EAC5B,KAAK,OAAO;EACZ;EACA,mBAAmB;CACrB,CAAC;CAED,MAAM,EAAE,QAAQ,cAAc,eAAe,kCAAkC,SAAS,OAAO;CAC/F,QAAQ,OAAO,MAAM,YAAY;CACjC,QAAQ,OAAO,QAAQ;EAAE,MAAM;EAAsB;CAAW,CAAC,CAAC,CAAC,QAAQ,OAAO;CAElF,QAAQ,IAAI,wCAAwC,KAAK,KAAK,OAAO,mBAAmB,oBAAoB,GAAG;CAG/G,kBADgB,YAAY,mBACV,GAAS,OAAO,YAAY,QAAQ;CAEtD,MAAM,UAAqC,MAAM,QAAQ,OAAO,gBAAgB,IAAI,OAAO,mBAAmB,CAAA;CAC9G,IAAI,QAAQ,SAAS,GAAG;EACtB,MAAM,gBAAgB,mBAAmB,aAAa,OAAO,OAAO;EACpE,KAAK,MAAM,UAAU,SAAS;GAE5B,MAAM,cAAc,qBAAqB,eADzB,kBAAkB,OAAO,OACe,GAAS,WAAW;GAE5E,IAAI,YAAY,YAAY,GAAG;IAC7B,QAAQ,KACN,iCAAiC,OAAO,QAAO,qCACjD;IACA;GACF;GAEA,kBAAkB,YAAY,SAAS,OAAO,YAAY,OAAO,OAAO;EAC1E;CACF;AACF;AAEA,eAAsB,oBAAoB,QAA2C;CACnF,MAAM,gBAAgB,MAAM,kBAAkB,MAAM;CACpD,IAAI,cAAc,WAAW,GAC3B,OAAO,CAAA;CAIT,MAAM,cADc,mBACA,CAAA,CAAY,kBAAkB,CAAC,CAAC;CACpD,MAAM,6BAA6B,6BAA6B,OAAO,qBAAqB,OAAO,OAAO;CAE1G,KAAK,MAAM,QAAQ,eAAe;EAChC,MAAM,UAAU,MAAM,iBAAiB,IAAI;EAC3C,IAAI,CAAC,SACH;EAGF,KAAK,MAAM,UAAU,QAAQ,SAC3B,MAAM,oBAAoB,aAAa,QAAQ,QAAQ,0BAA0B;CAErF;CAEA,OAAO,YAAY,MAAM,CAAC,CAAC,KAAK;AAClC;AAEA,eAAe,sBAAoF;CACjG,gBAAgB;CAChB,MAAM,CAAC,cAAc,cAAqB,MAAM,QAAQ,IAAI,CAC1D,OAAO,wBACP,OAAO,mBAAmB,CAC3B;CAED,MAAM,gBAAgB,OAAO,aAAa,kBAAkB,aACxD,aAAa,gBACb,aAAa,SAAS;CAE1B,IAAI,OAAO,kBAAkB,YAC3B,MAAM,IAAI,MAAM,6CAA6C;CAG/D,OAAO;EACL;EACA,SAAS,WAAW,WAAW;CACjC;AACF;AAEA,SAAS,kBAAwB;CAC/B,IAAI,QAAQ,OAAO,OACjB;CAGF,IAAI,QAAQ,IAAI,gBAAgB,KAAA,GAC9B;CAGF,IAAI,QAAQ,IAAI,aAAa,KAAA,KAAa,QAAQ,IAAI,wBAAwB,KAAA,GAC5E;CAGF,IAAI,QAAQ,IAAI,OAAO,KAAA,GACrB;CAGF,QAAQ,IAAI,cAAc;AAC5B;AAEA,eAAe,oBACb,aACA,QACA,QACA,4BACe;CACf,MAAM,aAAa,OAAO;CAC1B,IAAI,CAAC,YACH;CAGF,IAAI,kBAAkB,UAAU,GAC9B;CAGF,IAAI,wBAAwB,UAAU,GACpC;CAGF,IAAI,SAAS,OAAO,UAAU,OAAO,OAAO,SAAS,IACjD,OAAO,SACP;CAEJ,IAAI,CAAC,QACH,IAAI;EACF,SAAS,MAAM,GAAG,SAAS,YAAY,MAAM;CAC/C,SAAS,OAAY;EACnB,MAAM,OAAO,KAAK,SAAS,UAAU;EACrC,IAAI,OAAO,SAAS,YAAY,QAAQ,CAAC,KAAK,SAAS,GAAG,GACxD;EAEF,IAAI,OAAO,SAAS,YAAY,CAAC,2BAA2B,UAAU,GACpE;EAEF,MAAM;CACR;CAGF,MAAM,YAAY,MAAM,uBAAuB,YAAY,MAAM;CACjE,MAAM,YAAY,aAChB,YACA,GACA,YAAY;EAAE;EAAQ,WAAW,EAAE,WAAW,UAAU;CAAE,IAAI,EAAE,OAAO,CACzE;CACA,MAAM,UAAU,KAAK;CACrB,UAAU,cAAc,OAAO,SAAS;CAExC,MAAM,WAAW,kBAAkB,UAAU,WAAW,GAAG,QAAQ,0BAA0B;CAC7F,IAAI,OAAO,KAAK,QAAQ,CAAC,CAAC,SAAS,GACjC,YAAY,MAAM,QAAQ;AAE9B;AAEA,eAAe,iBAAiB,MAAmC;CACjE,IAAI;EACF,MAAM,MAAM,MAAM,GAAG,SAAS,MAAM,MAAM;EAC1C,OAAO,KAAK,MAAM,GAAG;CACvB,SAAS,OAAO;EACd,QAAQ,KAAK,8BAA8B,KAAI,IAAK,KAAK;EACzD,OAAO;CACT;AACF;AAEA,SAAS,kBAAkB,SAAc,YAAgC,QAAQ,UAAgB;CAC/F,MAAM,WAAW,CAAA;CAEjB,KAAK,MAAM,UAAU,OAAO,KAAK,UAAU,GAAsC;EAC/E,MAAM,UAAU,WAAW;EAC3B,MAAM,SAAS,QAAQ,OAAO,EAAE,OAAO;EACvC,IAAI,SAAS,SACX,SAAS,KAAK;GAAE;GAAQ;GAAQ;EAAQ,CAAC;CAE7C;CAEA,IAAI,SAAS,WAAW,GACtB;CAOF,MAAM,IAAI,uBAAuB,0CAA0C,MAAK,MAJhE,SACb,KAAK,EAAE,QAAQ,QAAQ,cAAc,GAAG,OAAM,IAAK,OAAO,QAAQ,CAAC,EAAC,MAAO,QAAO,EAAG,CAAC,CACtF,KAAK,IAE+E,GAAS;AAClG;AAEA,SAAS,qBAA0B;CACjC,MAAM,YAAiB;CACvB,IAAI,OAAO,UAAU,sBAAsB,YACzC,OAAO;CAGT,IAAI,UAAU,WAAW,OAAO,UAAU,QAAQ,sBAAsB,YACtE,OAAO,UAAU;CAGnB,MAAM,IAAI,MAAM,+CAA+C;AACjE;AAEA,SAAS,uBAA4B;CACnC,MAAM,YAAiB;CACvB,IAAI,OAAO,UAAU,uBAAuB,YAC1C,OAAO;CAGT,IAAI,UAAU,WAAW,OAAO,UAAU,QAAQ,uBAAuB,YACvE,OAAO,UAAU;CAGnB,MAAM,IAAI,MAAM,iDAAiD;AACnE;AAEA,eAAe,qBACb,aACA,QACA,4BACe;CACf,MAAM,WAAW,IAAI,IACnB,YAAY,MAAM,CAAC,CAAC,KAAK,aAAsB,KAAK,QAAQ,OAAO,YAAY,EAAE,CAAC,CAAC,CACrF;CAEA,MAAM,aAAa,MAAM,yBAAyB,QAAQ,0BAA0B;CACpF,IAAI,WAAW,WAAW,GACxB;CAIF,MAAM,eADgB,qBACD,CAAA,CAAc,mBAAmB;EACpD,WAAW;EACX,eAAe;GACb;GACA;GACA;GACA;GACA;GACA;GACA;GACA;EAAe;CAEnB,CAAC;CAED,KAAK,MAAM,YAAY,YAAY;EACjC,MAAM,aAAa,KAAK,QAAQ,QAAQ;EACxC,IAAI,SAAS,IAAI,UAAU,GACzB;EAGF,MAAM,SAAS,MAAM,GAAG,SAAS,YAAY,MAAM,CAAC,CAAC,YAAY,IAAI;EACrE,IAAI,WAAW,MACb;EAGF,IAAI;GACF,aAAa,eAAe,QAAQ,UAAU;GAC9C,MAAM,eAAe,aAAa,iBAAiB;GACnD,IAAI,CAAC,cACH;GAEF,YAAY,gBAAgB,YAAY;GACxC,SAAS,IAAI,UAAU;EACzB,SAAS,OAAO;GACd,MAAM,WAAW,KAAK,SAAS,OAAO,SAAS,UAAU;GACzD,QAAQ,KACN,mCAAmC,YAAY,CAAC,SAAS,WAAW,IAAI,IAAI,WAAW,WAAU,IACjG,KACF;EACF;CACF;AACF;AAEA,IAAM,mCAAmC;CACvC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AAAU;AAGZ,eAAe,yBACb,QACA,4BACmB;CACnB,MAAM,WAAW,MAAM,QAAQ,OAAO,mBAAmB,IACrD,OAAO,sBACP,CAAA;CAEJ,IAAI,SAAS,WAAW,GACtB,OAAO,CAAA;CAGT,MAAM,WAAW,MAAM,GAAG,UAAU;EAClC,KAAK,OAAO;EACZ,UAAU;EACV,KAAK;EACL,WAAW;EACX,QAAQ;EACR,qBAAqB;EACrB,QAAQ;CACV,CAAC,CAAC,CAAC,YAAY,CAAA,CAAE;CAEjB,MAAM,4BAAY,IAAI,IAAY;CAElC,KAAK,MAAM,QAAQ,UAAU;EAC3B,MAAM,aAAa,KAAK,QAAQ,OAAO,QAAQ,EAAE,CAAC;EAClD,IAAI,CAAC,YACH;EAGF,IAAI,WAAW,SAAS,OAAO,KAAK,WAAW,SAAS,MAAM,GAC5D;EAGF,IAAI,kBAAkB,UAAU,GAC9B;EAGF,IAAI,wBAAwB,UAAU,GACpC;EAGF,IAAI,CAAC,2BAA2B,UAAU,GACxC;EAGF,UAAU,IAAI,UAAU;CAC1B;CAEA,OAAO,MAAM,KAAK,SAAS,CAAC,CAAC,KAAK;AACpC;AAEA,SAAS,mBACP,aACA,SAC+C;CAC/C,MAAM,iBAAiB,KAAK,QAAQ,OAAO;CAC3C,OAAO,YAAY,MAAM,CAAC,CAAC,KAAK,aAAqB;EACnD,MAAM,qBAAqB,KAAK,QAAQ,QAAQ;EAChD,MAAM,UAAU,YAAY,gBAAgB,QAAQ,CAAC,CAAC,UAAU;EAChE,MAAM,eAAe,KAAK,SAAS,gBAAgB,kBAAkB;EACrE,MAAM,6BAAa,IAAI,IAAY;EAEnC,IAAI,cAAc;GAChB,MAAM,gBAAgB,QAAQ,YAAY;GAC1C,WAAW,IAAI,aAAa;GAC5B,WAAW,IAAI,KAAK,eAAe;EACrC,OACE,WAAW,IAAI,QAAQ,KAAK,SAAS,kBAAkB,CAAC,CAAC;EAG3D,OAAO;GACL;GACA,YAAY,MAAM,KAAK,UAAU;EACnC;CACF,CAAC;AACH;AAEA,SAAS,qBACP,eACA,SACA,aACmC;CACnC,MAAM,UAAU,YAAY,sBAAsB;CAClD,IAAI,UAAU;CAEd,KAAK,MAAM,QAAQ,eACjB,IAAI,KAAK,WAAW,MAAM,cAAc,QAAQ,SAAS,CAAC,GAAG;EAC3D,QAAQ,MAAM,KAAK,OAAO;EAC1B,WAAW;CACb;CAGF,OAAO;EAAE;EAAS;CAAQ;AAC5B;AAEA,SAAS,kBAAkB,SAAiD;CAC1E,MAAM,aAAa,QAAQ,OAAO,WAAW,EAAE,CAAC,CAAC,CAAC,KAAK;CACvD,IAAI,CAAC,YACH,aAAa;CAEf,IAAI,sBAAsB,UAAU,GAClC,MAAM,IAAI,MAAM,uFAAuF,QAAO,EAAG;CAEnH,OAAO,UAAU,YAAY,EAAE,KAAK,KAAK,CAAC;AAC5C;AAEA,SAAS,sBAAsB,SAA0B;CACvD,MAAM,aAAa,OAAO,WAAW,EAAE,CAAC,CAAC,KAAK;CAC9C,IAAI,CAAC,YACH,OAAO;CAGT,IAAI,WAAW,WAAW,GAAG,GAC3B,OAAO;CAGT,IAAI,WAAW,WAAW,SAAS,GACjC,OAAO;CAGT,OAAO,eAAe,KAAK,UAAU;AACvC;AAEA,SAAS,WAAW,KAAqB;CACvC,MAAM,aAAa,IAAI,QAAQ,GAAG;CAClC,MAAM,YAAY,IAAI,QAAQ,GAAG;CAEjC,MAAM,WAAW,KAAK,IACpB,eAAe,KAAK,OAAO,oBAAoB,YAC/C,cAAc,KAAK,OAAO,oBAAoB,SAChD;CAEA,IAAI,CAAC,OAAO,SAAS,QAAQ,GAC3B,OAAO;CAGT,OAAO,IAAI,MAAM,GAAG,QAAQ;AAC9B;AAEA,SAAS,wBAAwB,QAA+B;CAC9D,MAAM,QAAQ;CAEd,IAAI,OAAO;CACX,IAAI,QAAQ;CAEZ,QAAQ,QAAQ,MAAM,KAAK,MAAM,OAAO,MACtC,OAAO,MAAM;CAGf,OAAO,OAAO,SAAS,YAAY,KAAK,SAAS,IAAI,OAAO;AAC9D;AAEA,SAAS,qBAAqB,YAAoB,YAA4B;CAC5E,MAAM,UAAU,WAAW,UAAU;CAErC,IAAI,QAAQ,WAAW,SAAS,GAC9B,OAAO,cAAc,OAAO;CAG9B,IAAI,KAAK,WAAW,OAAO,GACzB,OAAO;CAGT,OAAO,KAAK,QAAQ,KAAK,QAAQ,UAAU,GAAG,OAAO;AACvD;AAEA,SAAS,kBACP,KACA,QACA,4BACqB;CACrB,IAAI,CAAC,OAAO,OAAO,QAAQ,UACzB,OAAO,CAAC;CAGV,MAAM,WAAgC,CAAC;CAEvC,KAAK,MAAM,CAAC,UAAU,iBAAiB,OAAO,QAAQ,GAAG,GAAG;EAC1D,MAAM,eAAe,oBAAoB,UAAU,OAAO,OAAO;EACjE,IAAI,CAAC,cACH;EAGF,IAAI,aAAa,SAAS,OAAO,KAAK,aAAa,SAAS,MAAM,GAChE;EAGF,IAAI,kBAAkB,YAAY,GAChC;EAGF,IAAI,wBAAwB,YAAY,GACtC;EAGF,IAAI,CAAC,2BAA2B,YAAY,GAC1C;EAGF,IAAI,gBAAgB,OAAO,iBAAiB,UAC1C,SAAS,gBAAgB;GAAE,GAAG;GAAc,MAAM;EAAa;OAE/D,SAAS,gBAAgB;CAE7B;CAEA,OAAO;AACT;AAEA,SAAS,oBAAoB,UAAkB,SAAgC;CAC7E,MAAM,MAAM,OAAO,YAAY,EAAE,CAAC,CAAC,KAAK;CACxC,IAAI,CAAC,KACH,OAAO;CAGT,MAAM,UAAU,WAAW,GAAG;CAE9B,IAAI,QAAQ,WAAW,SAAS,GAC9B,IAAI;EACF,OAAO,KAAK,UAAU,cAAc,OAAO,CAAC;CAC9C,QAAQ;EACN,OAAO;CACT;CAGF,IAAI,KAAK,WAAW,OAAO,GACzB,OAAO,KAAK,UAAU,OAAO;CAG/B,IAAI,QAAQ,SAAS,KAAK,GACxB,OAAO;CAGT,OAAO,KAAK,UAAU,KAAK,QAAQ,SAAS,OAAO,CAAC;AACtD;AAEA,SAAS,kBAAkB,UAA2B;CACpD,OAAO,KACJ,UAAU,OAAO,YAAY,EAAE,CAAC,CAAC,CACjC,MAAM,KAAK,GAAG,CAAC,CACf,SAAS,cAAc;AAC5B;AAEA,SAAS,wBAAwB,UAA2B;CAC1D,MAAM,aAAa,KAAK,UAAU,OAAO,YAAY,EAAE,CAAC;CACxD,MAAM,WAAW,KAAK,SAAS,UAAU;CACzC,OAAO,aAAa,6BACf,SAAS,WAAW,0BAA0B,KAC9C,SAAS,WAAW,SAAS;AACpC;AAEA,SAAS,sBAAsB,KAAsB;CACnD,IAAI,CAAC,OAAO,OAAO,QAAQ,UACzB,OAAO;CAGT,MAAM,UAAU,IAAI;CACpB,IAAI,CAAC,MAAM,QAAQ,OAAO,KAAK,QAAQ,WAAW,GAChD,OAAO;CAGT,OAAO;AACT;AAEA,SAAS,mBAAmB,WAAgB,YAAyB;CACnE,MAAM,OAAO,OAAO,UAAU,eAAe,WACzC,UAAU,WAAW,QAAQ,WAAW,EAAE,IAC1C;CAEJ,MAAM,MAAM,KAAK,QAAQ,UAAU;CACnC,MAAM,eAAe,UAAU,QAAQ,KAAK,WAAoB;EAE9D,MAAM,UAAU,WADJ,OAAO,UAAU,EACF,CAAG;EAE9B,IAAI,QAAQ,WAAW,SAAS,GAC9B,IAAI;GACF,OAAO,KAAK,UAAU,cAAc,OAAO,CAAC;EAC9C,QAAQ;GACN,OAAO;EACT;EAGF,MAAM,iBAAiB,QAAQ,QAAQ,iBAAiB,EAAE;EAC1D,MAAM,YAAY,KAAK,KAAK,MAAM,cAAc;EAEhD,IAAI,KAAK,WAAW,SAAS,GAC3B,OAAO,KAAK,UAAU,SAAS;EAGjC,MAAM,sBAAsB,UAAU,MAAM,GAAG,CAAC,CAAC,KAAK,KAAK,GAAG;EAE9D,IAAI,IAAI,SAAS,GAAG,KAAK,IAAG,KAAM,KAAK,CAAC,oBAAoB,WAAW,KAAK,KAAK,KAAK,GAChF;OAAA,oBAAoB,WAAW,MAAM,KAAK,KAAK,KAAK,oBAAoB,WAAW,MAAM,KAAK,KAAK,GACrG,OAAO,KAAK,UAAU,KAAK,QAAQ,KAAK,MAAM,mBAAmB,CAAC;EAAA;EAItE,OAAO,KAAK,UAAU,KAAK,QAAQ,KAAK,mBAAmB,CAAC;CAC9D,CAAC;CAED,OAAO;EACL,GAAG;EACH,SAAS;CACX;AACF;AAEA,eAAe,uBAAuB,YAAoB,QAAqC;CAC7F,MAAM,aAAa,wBAAwB,MAAM;CACjD,IAAI,CAAC,YACH,OAAO;CAGT,MAAM,UAAU,WAAW,UAAU;CAErC,IAAI,QAAQ,WAAW,OAAO,GAAG;EAC/B,MAAM,aAAa,QAAQ,QAAQ,GAAG;EACtC,IAAI,eAAe,IACjB,OAAO;EAGT,MAAM,OAAO,QAAQ,MAAM,GAAG,UAAU;EACxC,MAAM,UAAU,QAAQ,MAAM,aAAa,CAAC;EAC5C,MAAM,MAAM,KAAK,SAAS,SAAS,IAC/B,OAAO,KAAK,SAAS,QAAQ,CAAC,CAAC,SAAS,MAAM,IAC9C,mBAAmB,OAAO;EAE9B,IAAI;GACF,MAAM,SAAS,sBAAsB,KAAK,MAAM,GAAG,CAAC;GACpD,OAAO,SAAS,mBAAmB,QAAQ,UAAU,IAAI;EAC3D,QAAQ;GACN,OAAO;EACT;CACF;CAEA,IAAI;EACF,MAAM,UAAU,qBAAqB,YAAY,OAAO;EACxD,MAAM,MAAM,MAAM,GAAG,SAAS,SAAS,MAAM;EAC7C,MAAM,SAAS,sBAAsB,KAAK,MAAM,GAAG,CAAC;EACpD,OAAO,SAAS,mBAAmB,QAAQ,UAAU,IAAI;CAC3D,QAAQ;EACN,OAAO;CACT;AACF"}
|
|
1
|
+
{"version":3,"file":"report.js","names":[],"sources":["../../src/coverage/report.ts"],"sourcesContent":["import fs from \"node:fs/promises\"\nimport path from \"node:path\"\nimport { fileURLToPath } from \"node:url\"\n\nimport * as libCoverage from \"istanbul-lib-coverage\"\nimport * as libInstrument from \"istanbul-lib-instrument\"\nimport fg from \"fast-glob\"\nimport picomatch from \"picomatch\"\nimport v8ToIstanbul from \"v8-to-istanbul\"\n\nimport { createCollectCoverageMatcher, toPosix } from \"./collect\"\nimport { generateConsoleTextCoverageReport } from \"./console-text-report\"\nimport { findCoverageFiles } from \"./files\"\nimport type { CoverageConfig, CoverageThresholdTarget, CoverageThresholds } from \"./types\"\n\n\nconst TEXT_REPORT_FILENAME = \"coverage.txt\"\n\nexport class CoverageThresholdError extends Error {\n constructor(message: string) {\n super(message)\n this.name = \"CoverageThresholdError\"\n }\n}\n\nexport async function generateCoverageReport(config: CoverageConfig): Promise<void> {\n const coverageFiles = await findCoverageFiles(config)\n\n if (coverageFiles.length === 0) {\n console.warn(\"[coverage] no V8 coverage artifacts were generated\")\n return\n }\n\n const coverageLib = resolveCoverageLib()\n const coverageMap = coverageLib.createCoverageMap({})\n const matchesCollectCoverageFrom = createCollectCoverageMatcher(config.collectCoverageFrom, config.rootDir)\n\n for (const file of coverageFiles) {\n const payload = await readCoverageFile(file)\n if (!payload) {\n continue\n }\n\n for (const script of payload.scripts as any[]) {\n await mergeScriptCoverage(coverageMap, script, config, matchesCollectCoverageFrom)\n }\n }\n\n if (config.includeAllFiles) {\n await includeUntestedFiles(coverageMap, config, matchesCollectCoverageFrom)\n }\n\n if (coverageMap.files().length === 0) {\n console.warn(\"[coverage] no library files matched the coverage filters\")\n return\n }\n\n await fs.rm(config.coverageReportDir, { recursive: true, force: true })\n await fs.mkdir(config.coverageReportDir, { recursive: true })\n\n const { createContext, reports } = await loadIstanbulModules()\n const context = createContext({\n dir: config.coverageReportDir,\n coverageMap,\n defaultSummarizer: \"pkg\",\n })\n\n const { output: reportOutput, summarizer } = generateConsoleTextCoverageReport(reports, context)\n process.stdout.write(reportOutput)\n reports.create(\"text\", { file: TEXT_REPORT_FILENAME, summarizer }).execute(context)\n\n console.log(`[coverage] Full text report saved to ${path.join(config.coverageReportDir, TEXT_REPORT_FILENAME)}`)\n\n const summary = coverageMap.getCoverageSummary()\n enforceThresholds(summary, config.thresholds, \"global\")\n\n const targets: CoverageThresholdTarget[] = Array.isArray(config.thresholdTargets) ? config.thresholdTargets : []\n if (targets.length > 0) {\n const fileSummaries = buildFileSummaries(coverageMap, config.rootDir)\n for (const target of targets) {\n const matcher = createGlobMatcher(target.pattern)\n const matchResult = collectTargetSummary(fileSummaries, matcher, coverageLib)\n\n if (matchResult.matched === 0) {\n console.warn(\n `[coverage] threshold pattern \"${target.pattern}\" did not match any files — skipping`,\n )\n continue\n }\n\n enforceThresholds(matchResult.summary, target.thresholds, target.pattern)\n }\n }\n}\n\nexport async function collectCoveredFiles(config: CoverageConfig): Promise<string[]> {\n const coverageFiles = await findCoverageFiles(config)\n if (coverageFiles.length === 0) {\n return []\n }\n\n const coverageLib = resolveCoverageLib()\n const coverageMap = coverageLib.createCoverageMap({})\n const matchesCollectCoverageFrom = createCollectCoverageMatcher(config.collectCoverageFrom, config.rootDir)\n\n for (const file of coverageFiles) {\n const payload = await readCoverageFile(file)\n if (!payload) {\n continue\n }\n\n for (const script of payload.scripts as any[]) {\n await mergeScriptCoverage(coverageMap, script, config, matchesCollectCoverageFrom)\n }\n }\n\n return coverageMap.files().sort()\n}\n\nasync function loadIstanbulModules(): Promise<{ createContext: (opts: any) => any; reports: any }> {\n maybeForceColor()\n const [libReportMod, reportsMod]: any[] = await Promise.all([\n import(\"istanbul-lib-report\"),\n import(\"istanbul-reports\"),\n ])\n\n const createContext = typeof libReportMod.createContext === \"function\"\n ? libReportMod.createContext\n : libReportMod.default?.createContext\n\n if (typeof createContext !== \"function\") {\n throw new Error(\"istanbul-lib-report exports are unavailable\")\n }\n\n return {\n createContext,\n reports: reportsMod.default ?? reportsMod,\n }\n}\n\nfunction maybeForceColor(): void {\n if (process.stdout.isTTY) {\n return\n }\n\n if (process.env.FORCE_COLOR !== undefined) {\n return\n }\n\n if (process.env.NO_COLOR !== undefined || process.env.NODE_DISABLE_COLORS !== undefined) {\n return\n }\n\n if (process.env.CI !== undefined) {\n return\n }\n\n process.env.FORCE_COLOR = \"1\"\n}\n\nasync function mergeScriptCoverage(\n coverageMap: any,\n script: any,\n config: CoverageConfig,\n matchesCollectCoverageFrom: (absolutePath: string) => boolean,\n): Promise<void> {\n const scriptPath = script.absolutePath\n if (!scriptPath) {\n return\n }\n\n if (isNodeModulesPath(scriptPath)) {\n return\n }\n\n if (isViteVirtualModulePath(scriptPath)) {\n return\n }\n\n let source = script.source && script.source.length > 0\n ? script.source\n : \"\"\n\n if (!source) {\n try {\n source = await fs.readFile(scriptPath, \"utf8\")\n } catch (error: any) {\n const base = path.basename(scriptPath)\n if (error?.code === \"ENOENT\" && base && !base.includes(\".\")) {\n return\n }\n if (error?.code === \"ENOENT\" && !matchesCollectCoverageFrom(scriptPath)) {\n return\n }\n throw error\n }\n }\n\n const sourceMap = await loadSourceMapForScript(scriptPath, source)\n const converter = v8ToIstanbul(\n scriptPath,\n 0,\n sourceMap ? { source, sourceMap: { sourcemap: sourceMap } } : { source },\n )\n await converter.load()\n converter.applyCoverage(script.functions)\n\n const filtered = filterCoverageMap(converter.toIstanbul(), config, matchesCollectCoverageFrom)\n if (Object.keys(filtered).length > 0) {\n coverageMap.merge(filtered)\n }\n}\n\nasync function readCoverageFile(file: string): Promise<any | null> {\n try {\n const raw = await fs.readFile(file, \"utf8\")\n return JSON.parse(raw)\n } catch (error) {\n console.warn(`[coverage] failed to parse ${file}:`, error)\n return null\n }\n}\n\nfunction enforceThresholds(summary: any, thresholds: CoverageThresholds, label = \"global\"): void {\n const failures = []\n\n for (const metric of Object.keys(thresholds) as Array<keyof CoverageThresholds>) {\n const minimum = thresholds[metric]\n const actual = summary[metric]?.pct ?? 0\n if (actual < minimum) {\n failures.push({ metric, actual, minimum })\n }\n }\n\n if (failures.length === 0) {\n return\n }\n\n const details = failures\n .map(({ metric, actual, minimum }) => `${metric}: ${actual.toFixed(2)}% < ${minimum}%`)\n .join(\"; \")\n\n throw new CoverageThresholdError(`[coverage] thresholds not met (target: ${label}) — ${details}`)\n}\n\nfunction resolveCoverageLib(): any {\n const candidate: any = libCoverage as any\n if (typeof candidate.createCoverageMap === \"function\") {\n return candidate\n }\n\n if (candidate.default && typeof candidate.default.createCoverageMap === \"function\") {\n return candidate.default\n }\n\n throw new Error(\"istanbul-lib-coverage exports are unavailable\")\n}\n\nfunction resolveInstrumentLib(): any {\n const candidate: any = libInstrument as any\n if (typeof candidate.createInstrumenter === \"function\") {\n return candidate\n }\n\n if (candidate.default && typeof candidate.default.createInstrumenter === \"function\") {\n return candidate.default\n }\n\n throw new Error(\"istanbul-lib-instrument exports are unavailable\")\n}\n\nasync function includeUntestedFiles(\n coverageMap: any,\n config: CoverageConfig,\n matchesCollectCoverageFrom: (absolutePath: string) => boolean,\n): Promise<void> {\n const existing = new Set(\n coverageMap.files().map((filePath: unknown) => path.resolve(String(filePath ?? \"\"))),\n )\n\n const candidates = await findCollectCoverageFiles(config, matchesCollectCoverageFrom)\n if (candidates.length === 0) {\n return\n }\n\n const instrumentLib = resolveInstrumentLib()\n const instrumenter = instrumentLib.createInstrumenter({\n esModules: true,\n parserPlugins: [\n \"typescript\",\n \"jsx\",\n \"classProperties\",\n \"classPrivateProperties\",\n \"classPrivateMethods\",\n \"decorators-legacy\",\n \"importMeta\",\n \"topLevelAwait\",\n ],\n })\n\n for (const filePath of candidates) {\n const normalized = path.resolve(filePath)\n if (existing.has(normalized)) {\n continue\n }\n\n const source = await fs.readFile(normalized, \"utf8\").catch(() => null)\n if (source === null) {\n continue\n }\n\n try {\n instrumenter.instrumentSync(source, normalized)\n const fileCoverage = instrumenter.lastFileCoverage()\n if (!fileCoverage) {\n continue\n }\n coverageMap.addFileCoverage(fileCoverage)\n existing.add(normalized)\n } catch (error) {\n const relative = path.relative(config.rootDir, normalized)\n console.warn(\n `[coverage] failed to instrument ${relative && !relative.startsWith(\"..\") ? relative : normalized}:`,\n error,\n )\n }\n }\n}\n\nconst DEFAULT_COLLECT_COVERAGE_IGNORES = [\n \"**/.git/**\",\n \"**/.next/**\",\n \"**/.turbo/**\",\n \"**/.vite/**\",\n \"**/.vitest/**\",\n \"**/build/**\",\n \"**/coverage/**\",\n \"**/dist/**\",\n \"**/node_modules/**\",\n \"**/playwright-report/**\",\n \"**/spec/**\",\n \"**/test/**\",\n \"**/test-results/**\",\n \"**/tests/**\",\n \"**/__tests__/**\",\n \"**/*.d.ts\",\n \"**/*.map\",\n]\n\nasync function findCollectCoverageFiles(\n config: CoverageConfig,\n matchesCollectCoverageFrom: (absolutePath: string) => boolean,\n): Promise<string[]> {\n const patterns = Array.isArray(config.collectCoverageFrom)\n ? config.collectCoverageFrom\n : []\n\n if (patterns.length === 0) {\n return []\n }\n\n const rawFiles = await fg(patterns, {\n cwd: config.rootDir,\n absolute: true,\n dot: true,\n onlyFiles: true,\n unique: true,\n followSymbolicLinks: false,\n ignore: DEFAULT_COLLECT_COVERAGE_IGNORES,\n }).catch(() => [])\n\n const collected = new Set<string>()\n\n for (const file of rawFiles) {\n const normalized = path.resolve(String(file ?? \"\"))\n if (!normalized) {\n continue\n }\n\n if (normalized.endsWith(\".d.ts\") || normalized.endsWith(\".map\")) {\n continue\n }\n\n if (isNodeModulesPath(normalized)) {\n continue\n }\n\n if (isViteVirtualModulePath(normalized)) {\n continue\n }\n\n if (!matchesCollectCoverageFrom(normalized)) {\n continue\n }\n\n collected.add(normalized)\n }\n\n return Array.from(collected).sort()\n}\n\nfunction buildFileSummaries(\n coverageMap: any,\n rootDir: string,\n): Array<{ summary: any; candidates: string[] }> {\n const normalizedRoot = path.resolve(rootDir)\n return coverageMap.files().map((filePath: string) => {\n const normalizedAbsolute = path.resolve(filePath)\n const summary = coverageMap.fileCoverageFor(filePath).toSummary()\n const relativePath = path.relative(normalizedRoot, normalizedAbsolute)\n const candidates = new Set<string>()\n\n if (relativePath) {\n const relativePosix = toPosix(relativePath)\n candidates.add(relativePosix)\n candidates.add(`./${relativePosix}`)\n } else {\n candidates.add(toPosix(path.basename(normalizedAbsolute)))\n }\n\n return {\n summary,\n candidates: Array.from(candidates),\n }\n })\n}\n\nfunction collectTargetSummary(\n fileSummaries: Array<{ summary: any; candidates: string[] }>,\n matcher: (candidate: string) => boolean,\n coverageLib: any,\n): { summary: any; matched: number } {\n const summary = coverageLib.createCoverageSummary()\n let matched = 0\n\n for (const file of fileSummaries) {\n if (file.candidates.some((candidate) => matcher(candidate))) {\n summary.merge(file.summary)\n matched += 1\n }\n }\n\n return { summary, matched }\n}\n\nfunction createGlobMatcher(pattern: string): (candidate: string) => boolean {\n const normalized = toPosix(String(pattern ?? \"\")).trim()\n if (!normalized) {\n return () => false\n }\n if (isAbsoluteGlobPattern(normalized)) {\n throw new Error(`[coverage] threshold patterns must be relative (absolute paths are not supported): \"${pattern}\"`)\n }\n return picomatch(normalized, { dot: true })\n}\n\nfunction isAbsoluteGlobPattern(pattern: string): boolean {\n const normalized = String(pattern ?? \"\").trim()\n if (!normalized) {\n return false\n }\n\n if (normalized.startsWith(\"/\")) {\n return true\n }\n\n if (normalized.startsWith(\"file://\")) {\n return true\n }\n\n return /^[A-Za-z]:\\//.test(normalized)\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 extractSourceMappingUrl(source: string): string | null {\n const regex = /\\/\\/[#@]\\s*sourceMappingURL=([^\\s]+)/g\n\n let last = null\n let match = null\n\n while ((match = regex.exec(source)) !== null) {\n last = match[1]\n }\n\n return typeof last === \"string\" && last.length > 0 ? last : null\n}\n\nfunction resolveSourceMapPath(scriptPath: string, mappingUrl: string): string {\n const cleaned = stripQuery(mappingUrl)\n\n if (cleaned.startsWith(\"file://\")) {\n return fileURLToPath(cleaned)\n }\n\n if (path.isAbsolute(cleaned)) {\n return cleaned\n }\n\n return path.resolve(path.dirname(scriptPath), cleaned)\n}\n\nfunction filterCoverageMap(\n map: any,\n config: CoverageConfig,\n matchesCollectCoverageFrom: (absolutePath: string) => boolean,\n): Record<string, any> {\n if (!map || typeof map !== \"object\") {\n return {}\n }\n\n const filtered: Record<string, any> = {}\n\n for (const [filePath, fileCoverage] of Object.entries(map)) {\n const absolutePath = resolveCoveragePath(filePath, config.rootDir)\n if (!absolutePath) {\n continue\n }\n\n if (absolutePath.endsWith(\".d.ts\") || absolutePath.endsWith(\".map\")) {\n continue\n }\n\n if (isNodeModulesPath(absolutePath)) {\n continue\n }\n\n if (isViteVirtualModulePath(absolutePath)) {\n continue\n }\n\n if (!matchesCollectCoverageFrom(absolutePath)) {\n continue\n }\n\n if (fileCoverage && typeof fileCoverage === \"object\") {\n filtered[absolutePath] = { ...fileCoverage, path: absolutePath }\n } else {\n filtered[absolutePath] = fileCoverage\n }\n }\n\n return filtered\n}\n\nfunction resolveCoveragePath(filePath: string, rootDir: string): string | null {\n const raw = String(filePath ?? \"\").trim()\n if (!raw) {\n return null\n }\n\n const cleaned = stripQuery(raw)\n\n if (cleaned.startsWith(\"file://\")) {\n try {\n return path.normalize(fileURLToPath(cleaned))\n } catch {\n return null\n }\n }\n\n if (path.isAbsolute(cleaned)) {\n return path.normalize(cleaned)\n }\n\n if (cleaned.includes(\"://\")) {\n return null\n }\n\n return path.normalize(path.resolve(rootDir, cleaned))\n}\n\nfunction isNodeModulesPath(filePath: string): boolean {\n return path\n .normalize(String(filePath ?? \"\"))\n .split(path.sep)\n .includes(\"node_modules\")\n}\n\nfunction isViteVirtualModulePath(filePath: string): boolean {\n const normalized = path.normalize(String(filePath ?? \"\"))\n const baseName = path.basename(normalized)\n return baseName === \"__vite-browser-external\"\n || baseName.startsWith(\"__vite-browser-external:\")\n || baseName.startsWith(\"__vite-\")\n}\n\nfunction parseSourceMapPayload(raw: any): any | null {\n if (!raw || typeof raw !== \"object\") {\n return null\n }\n\n const sources = raw.sources\n if (!Array.isArray(sources) || sources.length === 0) {\n return null\n }\n\n return raw\n}\n\nfunction normalizeSourceMap(sourceMap: any, scriptPath: string): any {\n const root = typeof sourceMap.sourceRoot === \"string\"\n ? sourceMap.sourceRoot.replace(\"file://\", \"\")\n : \"\"\n\n const dir = path.dirname(scriptPath)\n const fixedSources = sourceMap.sources.map((source: unknown) => {\n const raw = String(source ?? \"\")\n const cleaned = stripQuery(raw)\n\n if (cleaned.startsWith(\"file://\")) {\n try {\n return path.normalize(fileURLToPath(cleaned))\n } catch {\n return cleaned\n }\n }\n\n const withoutWebpack = cleaned.replace(/^webpack:\\/\\//, \"\")\n const candidate = path.join(root, withoutWebpack)\n\n if (path.isAbsolute(candidate)) {\n return path.normalize(candidate)\n }\n\n const normalizedCandidate = candidate.split(\"/\").join(path.sep)\n\n if (dir.endsWith(`${path.sep}dist`) && !normalizedCandidate.startsWith(`..${path.sep}`)) {\n if (normalizedCandidate.startsWith(`src${path.sep}`) || normalizedCandidate.startsWith(`lib${path.sep}`)) {\n return path.normalize(path.resolve(dir, \"..\", normalizedCandidate))\n }\n }\n\n return path.normalize(path.resolve(dir, normalizedCandidate))\n })\n\n return {\n ...sourceMap,\n sources: fixedSources,\n }\n}\n\nasync function loadSourceMapForScript(scriptPath: string, source: string): Promise<any | null> {\n const mappingUrl = extractSourceMappingUrl(source)\n if (!mappingUrl) {\n return null\n }\n\n const cleaned = stripQuery(mappingUrl)\n\n if (cleaned.startsWith(\"data:\")) {\n const commaIndex = cleaned.indexOf(\",\")\n if (commaIndex === -1) {\n return null\n }\n\n const meta = cleaned.slice(0, commaIndex)\n const payload = cleaned.slice(commaIndex + 1)\n const raw = meta.includes(\";base64\")\n ? Buffer.from(payload, \"base64\").toString(\"utf8\")\n : decodeURIComponent(payload)\n\n try {\n const parsed = parseSourceMapPayload(JSON.parse(raw))\n return parsed ? normalizeSourceMap(parsed, scriptPath) : null\n } catch {\n return null\n }\n }\n\n try {\n const mapPath = resolveSourceMapPath(scriptPath, cleaned)\n const raw = await fs.readFile(mapPath, \"utf8\")\n const parsed = parseSourceMapPayload(JSON.parse(raw))\n return parsed ? normalizeSourceMap(parsed, scriptPath) : null\n } catch {\n return null\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"v8-tracker.js","names":[],"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"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"v8-tracker.js","names":[],"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"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"playwright.js","names":[],"sources":["../../src/runners/playwright.ts"],"sourcesContent":["import 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 { spawnAndCaptureStdout, spawnWithLogs, withRegisterShim, type SpawnLauncher } from \"./process\"\n\n\nconst require = createRequire(import.meta.url)\nconst moduleDir = path.dirname(fileURLToPath(import.meta.url))\n\nconst COMBINED_COVERAGE_ENV_VAR = \"RB_TEST_COMBINED_COVERAGE\"\nconst PLAYWRIGHT_RESULTS_FILE = path.join(process.cwd(), \"build\", \"playwright\", \"results.json\")\n\ntype PlaywrightReportSummary = {\n failedFiles: string[]\n}\n\ntype PlaywrightRuntimeSettings = {\n retries: number | null\n workers: number | null\n}\n\nconst PLAYWRIGHT_OPTIONS_WITH_REQUIRED_VALUE = new Set([\n \"--browser\",\n \"--config\",\n \"-c\",\n \"--grep\",\n \"-g\",\n \"--grep-invert\",\n \"--global-timeout\",\n \"--max-failures\",\n \"--output\",\n \"--project\",\n \"--repeat-each\",\n \"--reporter\",\n \"--retries\",\n \"--shard\",\n \"--timeout\",\n \"--trace\",\n \"--tsconfig\",\n \"--workers\",\n \"-j\",\n])\n\nconst PLAYWRIGHT_OPTIONS_WITH_OPTIONAL_VALUE = new Set([\n \"--only-changed\",\n \"--update-snapshots\",\n \"-u\",\n])\n\nconst PLAYWRIGHT_OPTIONS_TO_REMOVE_FOR_WORKER_RETRY = new Set([\n \"--last-failed\",\n \"--only-changed\",\n \"--output\",\n \"--retries\",\n \"--pass-with-no-tests\",\n \"--reporter\",\n \"--workers\",\n \"-j\",\n])\n\nconst PLAYWRIGHT_OPTIONS_TO_REMOVE_FOR_INITIAL_FRESH_RUN = new Set([\n \"--retries\",\n])\n\nconst PLAYWRIGHT_RETRY_LOG_LABEL_MAX_LENGTH = 20\n\nexport async function runPlaywright(\n userArgs: string[],\n { disableCoverage = false }: { disableCoverage?: boolean } = {},\n): Promise<void> {\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 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 const runtimeSettings = await resolveFreshWorkerRetrySettings({\n launcher,\n configPath,\n hasCustomConfig,\n userArgs,\n env,\n })\n const configuredRetries = runtimeSettings.retries\n const retryConcurrency = Math.max(1, runtimeSettings.workers ?? 1)\n\n const resultsMtimeBeforeRun = getFileMtimeMs(PLAYWRIGHT_RESULTS_FILE)\n const initialRunArgs = buildPlaywrightInitialFreshWorkerArgs(userArgs)\n const initialPlaywrightArgs = [\"test\"]\n if (!hasCustomConfig) {\n initialPlaywrightArgs.push(\"--config\", configPath)\n }\n initialPlaywrightArgs.push(...initialRunArgs)\n\n try {\n await runPlaywrightOnce({\n launcher,\n args: initialPlaywrightArgs,\n env,\n })\n return\n } catch (error) {\n const summary = await readPlaywrightReportSummary(PLAYWRIGHT_RESULTS_FILE, resultsMtimeBeforeRun)\n if (!summary || configuredRetries <= 0 || summary.failedFiles.length === 0) {\n throw error\n }\n\n let lastError = error\n let failedFiles = summary.failedFiles\n const maxAttempts = configuredRetries\n\n for (let attempt = 1; attempt <= maxAttempts && failedFiles.length > 0; attempt += 1) {\n const activeRetryWorkers = Math.max(1, Math.min(retryConcurrency, failedFiles.length))\n console.warn(\n `[rb-test] Retrying ${failedFiles.length} failed Playwright file(s) with fresh workers (${attempt}/${maxAttempts}, up to ${activeRetryWorkers} in parallel)`,\n )\n const retryResults = await runPlaywrightRetryAttempt({\n launcher,\n userArgs,\n failedFiles,\n retryConcurrency: activeRetryWorkers,\n configPath,\n hasCustomConfig,\n env,\n attempt,\n })\n\n if (retryResults.lastError) {\n lastError = retryResults.lastError\n }\n failedFiles = retryResults.failedFiles\n }\n\n if (failedFiles.length === 0) {\n return\n }\n\n throw lastError\n }\n}\n\nfunction runPlaywrightOnce({\n launcher,\n args,\n env,\n outputMode = \"chunk\",\n bufferOutput = false,\n successMessage,\n failureMessage,\n stdoutLinePrefix,\n stderrLinePrefix,\n}: {\n launcher: SpawnLauncher\n args: string[]\n env: NodeJS.ProcessEnv\n outputMode?: \"chunk\" | \"line\"\n bufferOutput?: boolean\n successMessage?: string | null\n failureMessage?: string | null\n stdoutLinePrefix?: string\n stderrLinePrefix?: string\n}): Promise<void> {\n return spawnWithLogs({\n name: \"Playwright\",\n launcher,\n args,\n env,\n outputMode,\n bufferOutput,\n successMessage: successMessage === undefined ? \"Playwright suite passed!\" : successMessage ?? undefined,\n failureMessage: failureMessage === undefined ? \"Playwright failed\" : failureMessage ?? undefined,\n stdoutLinePrefix,\n stderrLinePrefix,\n })\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 for a usable playwright launcher.\n }\n }\n\n return null\n}\n\nfunction buildPlaywrightWorkerRetryArgs(userArgs: string[], failedFiles: string[], attempt: number): string[] {\n const optionArgs = extractPlaywrightOptionArgs(userArgs)\n const sanitizedOptions = removePlaywrightOptions(optionArgs, PLAYWRIGHT_OPTIONS_TO_REMOVE_FOR_WORKER_RETRY)\n return [\n ...sanitizedOptions,\n \"--retries=0\",\n \"--workers=1\",\n \"--reporter=list\",\n \"--output\",\n buildPlaywrightRetryOutputDir(attempt, failedFiles),\n ...failedFiles,\n ]\n}\n\nfunction buildPlaywrightInitialFreshWorkerArgs(userArgs: string[]): string[] {\n const optionArgs = extractPlaywrightOptionArgs(userArgs)\n const sanitizedOptions = removePlaywrightOptions(optionArgs, PLAYWRIGHT_OPTIONS_TO_REMOVE_FOR_INITIAL_FRESH_RUN)\n const positionalArgs = extractPlaywrightPositionalArgs(userArgs)\n return [...sanitizedOptions, \"--retries=0\", ...positionalArgs]\n}\n\nasync function resolveFreshWorkerRetrySettings({\n launcher,\n configPath,\n hasCustomConfig,\n userArgs,\n env,\n}: {\n launcher: SpawnLauncher\n configPath: string\n hasCustomConfig: boolean\n userArgs: string[]\n env: NodeJS.ProcessEnv\n}): Promise<{ retries: number; workers: number | null }> {\n const configuredSettings = await probeConfiguredPlaywrightSettings({\n launcher,\n configPath,\n hasCustomConfig,\n userArgs,\n env,\n })\n\n return {\n retries: configuredSettings.retries ?? 0,\n workers: configuredSettings.workers,\n }\n}\n\nasync function probeConfiguredPlaywrightSettings({\n launcher,\n configPath,\n hasCustomConfig,\n userArgs,\n env,\n}: {\n launcher: SpawnLauncher\n configPath: string\n hasCustomConfig: boolean\n userArgs: string[]\n env: NodeJS.ProcessEnv\n}): Promise<PlaywrightRuntimeSettings> {\n const probeArgs = [\"test\"]\n if (!hasCustomConfig) {\n probeArgs.push(\"--config\", configPath)\n }\n probeArgs.push(\"--list\", \"--reporter=json\", ...extractPlaywrightProjectArgs(userArgs))\n\n try {\n const stdout = await spawnAndCaptureStdout({\n name: \"Playwright retries probe\",\n launcher,\n args: probeArgs,\n env,\n })\n const json = parseJsonObjectFromText(stdout)\n if (!json) {\n return { retries: null, workers: null }\n }\n return {\n retries: resolvePlaywrightRetriesFromReport(json),\n workers: resolvePlaywrightWorkersFromReport(json),\n }\n } catch (_error) {\n return { retries: null, workers: null }\n }\n}\n\nfunction extractPlaywrightProjectArgs(userArgs: string[]): string[] {\n const output: string[] = []\n for (let i = 0; i < userArgs.length; i += 1) {\n const arg = userArgs[i]\n if (arg === \"--\") {\n break\n }\n if (arg === \"--project\") {\n const next = userArgs[i + 1]\n if (next != null) {\n output.push(arg, next)\n i += 1\n }\n continue\n }\n if (arg.startsWith(\"--project=\")) {\n output.push(arg)\n }\n }\n return output\n}\n\nfunction parseJsonObjectFromText(input: string): any | null {\n try {\n return JSON.parse(input)\n } catch {\n const start = input.indexOf(\"{\")\n const end = input.lastIndexOf(\"}\")\n if (start === -1 || end === -1 || end <= start) {\n return null\n }\n try {\n return JSON.parse(input.slice(start, end + 1))\n } catch {\n return null\n }\n }\n}\n\nfunction extractPlaywrightPositionalArgs(userArgs: string[]): string[] {\n const output: string[] = []\n\n for (let i = 0; i < userArgs.length; i += 1) {\n const arg = userArgs[i]\n\n if (arg === \"--\") {\n break\n }\n\n if (!arg.startsWith(\"-\")) {\n output.push(arg)\n continue\n }\n\n if (arg.includes(\"=\")) {\n continue\n }\n\n if (PLAYWRIGHT_OPTIONS_WITH_REQUIRED_VALUE.has(arg)) {\n const next = userArgs[i + 1]\n if (next !== undefined) {\n i += 1\n }\n continue\n }\n\n if (PLAYWRIGHT_OPTIONS_WITH_OPTIONAL_VALUE.has(arg)) {\n const next = userArgs[i + 1]\n if (next !== undefined && !next.startsWith(\"-\")) {\n i += 1\n }\n }\n }\n\n return output\n}\n\nfunction removePlaywrightOptions(optionArgs: string[], optionsToRemove: Set<string>): string[] {\n const output: string[] = []\n for (let i = 0; i < optionArgs.length; i += 1) {\n const arg = optionArgs[i]\n const normalized = arg.split(\"=\")[0]\n if (!arg.startsWith(\"-\") || !optionsToRemove.has(normalized)) {\n output.push(arg)\n continue\n }\n\n if (arg.includes(\"=\")) {\n continue\n }\n\n if (PLAYWRIGHT_OPTIONS_WITH_REQUIRED_VALUE.has(normalized)) {\n const next = optionArgs[i + 1]\n if (next !== undefined) {\n i += 1\n }\n continue\n }\n\n if (PLAYWRIGHT_OPTIONS_WITH_OPTIONAL_VALUE.has(normalized)) {\n const next = optionArgs[i + 1]\n if (next !== undefined && !next.startsWith(\"-\")) {\n i += 1\n }\n }\n }\n return output\n}\n\nfunction extractPlaywrightOptionArgs(userArgs: string[]): string[] {\n const output: string[] = []\n\n for (let i = 0; i < userArgs.length; i += 1) {\n const arg = userArgs[i]\n\n if (arg === \"--\") {\n break\n }\n\n if (!arg.startsWith(\"-\")) {\n continue\n }\n\n output.push(arg)\n\n if (arg.includes(\"=\")) {\n continue\n }\n\n if (PLAYWRIGHT_OPTIONS_WITH_REQUIRED_VALUE.has(arg)) {\n const next = userArgs[i + 1]\n if (next !== undefined) {\n output.push(next)\n i += 1\n }\n continue\n }\n\n if (PLAYWRIGHT_OPTIONS_WITH_OPTIONAL_VALUE.has(arg)) {\n const next = userArgs[i + 1]\n if (next !== undefined && !next.startsWith(\"-\")) {\n output.push(next)\n i += 1\n }\n }\n }\n\n return output\n}\n\nasync function readPlaywrightReportSummary(\n resultsFilePath: string,\n newerThanMtimeMs: number | null,\n): Promise<PlaywrightReportSummary | null> {\n const stats = await fsPromises.stat(resultsFilePath).catch(() => null)\n if (!stats) {\n return null\n }\n\n if (newerThanMtimeMs != null && stats.mtimeMs <= newerThanMtimeMs) {\n return null\n }\n\n const data = await readJson(resultsFilePath)\n if (!data || typeof data !== \"object\") {\n return null\n }\n\n return {\n failedFiles: resolveFailedPlaywrightFiles(data),\n }\n}\n\nfunction getFileMtimeMs(filePath: string): number | null {\n try {\n return fs.statSync(filePath).mtimeMs\n } catch {\n return null\n }\n}\n\nfunction resolvePlaywrightRetriesFromReport(data: any): number {\n const projects = Array.isArray(data?.config?.projects) ? data.config.projects : []\n const retriesFromProjects = projects\n .map((project: any) => Number(project?.retries))\n .filter((value: number) => Number.isFinite(value))\n .map((value: number) => Math.max(0, Math.floor(value)))\n\n if (retriesFromProjects.length > 0) {\n return Math.max(...retriesFromProjects)\n }\n\n const fallback = Number(data?.config?.retries)\n if (Number.isFinite(fallback)) {\n return Math.max(0, Math.floor(fallback))\n }\n\n return 0\n}\n\nfunction resolvePlaywrightWorkersFromReport(data: any): number | null {\n const configWorkers = Number(data?.config?.workers)\n if (Number.isFinite(configWorkers)) {\n return Math.max(1, Math.floor(configWorkers))\n }\n\n const projects = Array.isArray(data?.config?.projects) ? data.config.projects : []\n const workersFromProjects = projects\n .map((project: any) => Number(project?.metadata?.actualWorkers ?? project?.workers))\n .filter((value: number) => Number.isFinite(value))\n .map((value: number) => Math.max(1, Math.floor(value)))\n\n if (workersFromProjects.length > 0) {\n return Math.max(...workersFromProjects)\n }\n\n return null\n}\n\nfunction resolveFailedPlaywrightFiles(data: any): string[] {\n const suites = Array.isArray(data?.suites) ? data.suites : []\n const rootDir = typeof data?.config?.rootDir === \"string\" ? data.config.rootDir : null\n const failedFiles = new Set<string>()\n\n for (const suite of suites) {\n collectFailedPlaywrightFiles(suite, failedFiles, rootDir)\n }\n\n return Array.from(failedFiles).sort()\n}\n\nfunction collectFailedPlaywrightFiles(suite: any, output: Set<string>, rootDir: string | null): void {\n const specs = Array.isArray(suite?.specs) ? suite.specs : []\n\n for (const spec of specs) {\n if (isPlaywrightSpecSuccessful(spec)) {\n continue\n }\n const file = normalizePlaywrightReportFile(spec?.file ?? suite?.file, rootDir)\n if (file) {\n output.add(file)\n }\n }\n\n const innerSuites = Array.isArray(suite?.suites) ? suite.suites : []\n for (const innerSuite of innerSuites) {\n collectFailedPlaywrightFiles(innerSuite, output, rootDir)\n }\n}\n\nfunction isPlaywrightSpecSuccessful(spec: any): boolean {\n if (typeof spec?.ok === \"boolean\") {\n return spec.ok\n }\n\n const tests = Array.isArray(spec?.tests) ? spec.tests : []\n if (tests.length === 0) {\n return false\n }\n\n return tests.every((test: any) => {\n const testStatus = String(test?.status ?? \"\")\n if (testStatus === \"expected\" || testStatus === \"skipped\" || testStatus === \"flaky\") {\n return true\n }\n\n const results = Array.isArray(test?.results) ? test.results : []\n if (results.length === 0) {\n return false\n }\n return results.every((result: any) => result?.status === \"passed\" || result?.status === \"skipped\")\n })\n}\n\nfunction normalizePlaywrightReportFile(filePath: unknown, rootDir: string | null): string | null {\n const raw = String(filePath ?? \"\").trim()\n if (!raw) {\n return null\n }\n\n let absolutePath: string\n if (path.isAbsolute(raw)) {\n absolutePath = path.normalize(raw)\n } else {\n const cwdCandidate = path.resolve(process.cwd(), raw)\n const rootCandidate = rootDir ? path.resolve(rootDir, raw) : null\n if (rootCandidate && fs.existsSync(rootCandidate)) {\n absolutePath = rootCandidate\n } else if (fs.existsSync(cwdCandidate)) {\n absolutePath = cwdCandidate\n } else {\n absolutePath = rootCandidate ?? cwdCandidate\n }\n }\n\n const relative = path.relative(process.cwd(), absolutePath)\n if (relative === \"\" || (!relative.startsWith(\"..\") && !path.isAbsolute(relative))) {\n return toPosixPath(relative || raw)\n }\n\n return toPosixPath(raw)\n}\n\nfunction toPosixPath(input: unknown): string {\n return String(input ?? \"\").replaceAll(\"\\\\\", \"/\").split(path.sep).join(\"/\")\n}\n\nfunction buildPlaywrightRetryOutputDir(attempt: number, failedFiles: string[]): string {\n const slug = failedFiles\n .map((file) => toPosixPath(file).replace(/[^a-zA-Z0-9._/-]+/g, \"-\").replace(/\\//g, \"__\"))\n .join(\"--\")\n return toPosixPath(path.join(\"build\", \"playwright\", \"test-results\", \"rb-retries\", `attempt-${attempt}`, slug))\n}\n\nexport function createPlaywrightRetryEnv(baseEnv: NodeJS.ProcessEnv): NodeJS.ProcessEnv {\n return {\n ...baseEnv,\n PLAYWRIGHT_FORCE_TTY: \"false\",\n }\n}\n\nfunction truncatePlaywrightRetryLogLabel(label: string, maxLength = PLAYWRIGHT_RETRY_LOG_LABEL_MAX_LENGTH): string {\n if (label.length <= maxLength) {\n return label\n }\n\n if (maxLength <= 3) {\n return \".\".repeat(Math.max(0, maxLength))\n }\n\n const visibleChars = maxLength - 3\n const startLength = Math.ceil(visibleChars / 2)\n const endLength = Math.floor(visibleChars / 2)\n\n return `${label.slice(0, startLength)}...${label.slice(-endLength)}`\n}\n\nfunction getPlaywrightRetryLogName(failedFile: string): string {\n const normalizedFile = toPosixPath(failedFile)\n const relativeFile = normalizedFile.startsWith(\"build/spec/\")\n ? normalizedFile.slice(\"build/spec/\".length)\n : normalizedFile\n const strippedBaseName = relativeFile\n .replace(/\\.(spec|test)\\.[^.]+$/i, \"\")\n .replace(/\\.[^.]+$/i, \"\")\n .trim()\n\n return strippedBaseName || relativeFile || normalizedFile\n}\n\nfunction formatPlaywrightRetryBracketLabel({\n failedFile,\n suffix = \"\",\n}: {\n failedFile: string\n suffix?: string\n}): string {\n const label = truncatePlaywrightRetryLogLabel(\n getPlaywrightRetryLogName(failedFile),\n Math.max(1, PLAYWRIGHT_RETRY_LOG_LABEL_MAX_LENGTH - suffix.length),\n )\n return `[${label}${suffix}]`\n}\n\nexport function formatPlaywrightRetryLogLabel({\n failedFile,\n}: {\n failedFile: string\n}): string {\n return formatPlaywrightRetryBracketLabel({ failedFile })\n}\n\nexport function formatPlaywrightRetryLinePrefix({\n failedFile,\n stream,\n}: {\n failedFile: string\n stream: \"stdout\" | \"stderr\"\n}): string {\n return stream === \"stderr\"\n ? `${formatPlaywrightRetryBracketLabel({ failedFile, suffix: \" stderr\" })} `\n : `${formatPlaywrightRetryLogLabel({ failedFile })} `\n}\n\nasync function runPlaywrightRetryAttempt({\n launcher,\n userArgs,\n failedFiles,\n retryConcurrency,\n configPath,\n hasCustomConfig,\n env,\n attempt,\n}: {\n launcher: SpawnLauncher\n userArgs: string[]\n failedFiles: string[]\n retryConcurrency: number\n configPath: string\n hasCustomConfig: boolean\n env: NodeJS.ProcessEnv\n attempt: number\n}): Promise<{ failedFiles: string[]; lastError: unknown }> {\n const failedAgain = new Set<string>()\n let lastError: unknown = null\n let nextIndex = 0\n const retryEnv = createPlaywrightRetryEnv(env)\n\n async function runNext(): Promise<void> {\n while (nextIndex < failedFiles.length) {\n const fileIndex = nextIndex\n nextIndex += 1\n\n const failedFile = failedFiles[fileIndex]\n const retryLogLabel = formatPlaywrightRetryLogLabel({\n failedFile,\n })\n const retryArgs = buildPlaywrightWorkerRetryArgs(userArgs, [failedFile], attempt)\n const retryPlaywrightArgs = [\"test\"]\n if (!hasCustomConfig) {\n retryPlaywrightArgs.push(\"--config\", configPath)\n }\n retryPlaywrightArgs.push(...retryArgs)\n\n try {\n console.warn(`${retryLogLabel} Starting fresh-worker retry`)\n await runPlaywrightOnce({\n launcher,\n args: retryPlaywrightArgs,\n env: retryEnv,\n outputMode: \"line\",\n bufferOutput: true,\n successMessage: null,\n failureMessage: `${retryLogLabel} Playwright failed`,\n stdoutLinePrefix: formatPlaywrightRetryLinePrefix({\n failedFile,\n stream: \"stdout\",\n }),\n stderrLinePrefix: formatPlaywrightRetryLinePrefix({\n failedFile,\n stream: \"stderr\",\n }),\n })\n } catch (retryError) {\n lastError = retryError\n failedAgain.add(failedFile)\n }\n }\n }\n\n await Promise.all(\n Array.from(\n { length: Math.max(1, Math.min(retryConcurrency, failedFiles.length)) },\n () => runNext(),\n ),\n )\n\n return {\n failedFiles: failedFiles.filter((failedFile) => failedAgain.has(failedFile)),\n lastError,\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 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"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"playwright.js","names":[],"sources":["../../src/runners/playwright.ts"],"sourcesContent":["import 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 { spawnAndCaptureStdout, spawnWithLogs, withRegisterShim, type SpawnLauncher } from \"./process\"\n\n\nconst require = createRequire(import.meta.url)\nconst moduleDir = path.dirname(fileURLToPath(import.meta.url))\n\nconst COMBINED_COVERAGE_ENV_VAR = \"RB_TEST_COMBINED_COVERAGE\"\nconst PLAYWRIGHT_RESULTS_FILE = path.join(process.cwd(), \"build\", \"playwright\", \"results.json\")\n\ntype PlaywrightReportSummary = {\n failedFiles: string[]\n}\n\ntype PlaywrightRuntimeSettings = {\n retries: number | null\n workers: number | null\n}\n\nconst PLAYWRIGHT_OPTIONS_WITH_REQUIRED_VALUE = new Set([\n \"--browser\",\n \"--config\",\n \"-c\",\n \"--grep\",\n \"-g\",\n \"--grep-invert\",\n \"--global-timeout\",\n \"--max-failures\",\n \"--output\",\n \"--project\",\n \"--repeat-each\",\n \"--reporter\",\n \"--retries\",\n \"--shard\",\n \"--timeout\",\n \"--trace\",\n \"--tsconfig\",\n \"--workers\",\n \"-j\",\n])\n\nconst PLAYWRIGHT_OPTIONS_WITH_OPTIONAL_VALUE = new Set([\n \"--only-changed\",\n \"--update-snapshots\",\n \"-u\",\n])\n\nconst PLAYWRIGHT_OPTIONS_TO_REMOVE_FOR_WORKER_RETRY = new Set([\n \"--last-failed\",\n \"--only-changed\",\n \"--output\",\n \"--retries\",\n \"--pass-with-no-tests\",\n \"--reporter\",\n \"--workers\",\n \"-j\",\n])\n\nconst PLAYWRIGHT_OPTIONS_TO_REMOVE_FOR_INITIAL_FRESH_RUN = new Set([\n \"--retries\",\n])\n\nconst PLAYWRIGHT_RETRY_LOG_LABEL_MAX_LENGTH = 20\n\nexport async function runPlaywright(\n userArgs: string[],\n { disableCoverage = false }: { disableCoverage?: boolean } = {},\n): Promise<void> {\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 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 const runtimeSettings = await resolveFreshWorkerRetrySettings({\n launcher,\n configPath,\n hasCustomConfig,\n userArgs,\n env,\n })\n const configuredRetries = runtimeSettings.retries\n const retryConcurrency = Math.max(1, runtimeSettings.workers ?? 1)\n\n const resultsMtimeBeforeRun = getFileMtimeMs(PLAYWRIGHT_RESULTS_FILE)\n const initialRunArgs = buildPlaywrightInitialFreshWorkerArgs(userArgs)\n const initialPlaywrightArgs = [\"test\"]\n if (!hasCustomConfig) {\n initialPlaywrightArgs.push(\"--config\", configPath)\n }\n initialPlaywrightArgs.push(...initialRunArgs)\n\n try {\n await runPlaywrightOnce({\n launcher,\n args: initialPlaywrightArgs,\n env,\n })\n return\n } catch (error) {\n const summary = await readPlaywrightReportSummary(PLAYWRIGHT_RESULTS_FILE, resultsMtimeBeforeRun)\n if (!summary || configuredRetries <= 0 || summary.failedFiles.length === 0) {\n throw error\n }\n\n let lastError = error\n let failedFiles = summary.failedFiles\n const maxAttempts = configuredRetries\n\n for (let attempt = 1; attempt <= maxAttempts && failedFiles.length > 0; attempt += 1) {\n const activeRetryWorkers = Math.max(1, Math.min(retryConcurrency, failedFiles.length))\n console.warn(\n `[rb-test] Retrying ${failedFiles.length} failed Playwright file(s) with fresh workers (${attempt}/${maxAttempts}, up to ${activeRetryWorkers} in parallel)`,\n )\n const retryResults = await runPlaywrightRetryAttempt({\n launcher,\n userArgs,\n failedFiles,\n retryConcurrency: activeRetryWorkers,\n configPath,\n hasCustomConfig,\n env,\n attempt,\n })\n\n if (retryResults.lastError) {\n lastError = retryResults.lastError\n }\n failedFiles = retryResults.failedFiles\n }\n\n if (failedFiles.length === 0) {\n return\n }\n\n throw lastError\n }\n}\n\nfunction runPlaywrightOnce({\n launcher,\n args,\n env,\n outputMode = \"chunk\",\n bufferOutput = false,\n successMessage,\n failureMessage,\n stdoutLinePrefix,\n stderrLinePrefix,\n}: {\n launcher: SpawnLauncher\n args: string[]\n env: NodeJS.ProcessEnv\n outputMode?: \"chunk\" | \"line\"\n bufferOutput?: boolean\n successMessage?: string | null\n failureMessage?: string | null\n stdoutLinePrefix?: string\n stderrLinePrefix?: string\n}): Promise<void> {\n return spawnWithLogs({\n name: \"Playwright\",\n launcher,\n args,\n env,\n outputMode,\n bufferOutput,\n successMessage: successMessage === undefined ? \"Playwright suite passed!\" : successMessage ?? undefined,\n failureMessage: failureMessage === undefined ? \"Playwright failed\" : failureMessage ?? undefined,\n stdoutLinePrefix,\n stderrLinePrefix,\n })\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 for a usable playwright launcher.\n }\n }\n\n return null\n}\n\nfunction buildPlaywrightWorkerRetryArgs(userArgs: string[], failedFiles: string[], attempt: number): string[] {\n const optionArgs = extractPlaywrightOptionArgs(userArgs)\n const sanitizedOptions = removePlaywrightOptions(optionArgs, PLAYWRIGHT_OPTIONS_TO_REMOVE_FOR_WORKER_RETRY)\n return [\n ...sanitizedOptions,\n \"--retries=0\",\n \"--workers=1\",\n \"--reporter=list\",\n \"--output\",\n buildPlaywrightRetryOutputDir(attempt, failedFiles),\n ...failedFiles,\n ]\n}\n\nfunction buildPlaywrightInitialFreshWorkerArgs(userArgs: string[]): string[] {\n const optionArgs = extractPlaywrightOptionArgs(userArgs)\n const sanitizedOptions = removePlaywrightOptions(optionArgs, PLAYWRIGHT_OPTIONS_TO_REMOVE_FOR_INITIAL_FRESH_RUN)\n const positionalArgs = extractPlaywrightPositionalArgs(userArgs)\n return [...sanitizedOptions, \"--retries=0\", ...positionalArgs]\n}\n\nasync function resolveFreshWorkerRetrySettings({\n launcher,\n configPath,\n hasCustomConfig,\n userArgs,\n env,\n}: {\n launcher: SpawnLauncher\n configPath: string\n hasCustomConfig: boolean\n userArgs: string[]\n env: NodeJS.ProcessEnv\n}): Promise<{ retries: number; workers: number | null }> {\n const configuredSettings = await probeConfiguredPlaywrightSettings({\n launcher,\n configPath,\n hasCustomConfig,\n userArgs,\n env,\n })\n\n return {\n retries: configuredSettings.retries ?? 0,\n workers: configuredSettings.workers,\n }\n}\n\nasync function probeConfiguredPlaywrightSettings({\n launcher,\n configPath,\n hasCustomConfig,\n userArgs,\n env,\n}: {\n launcher: SpawnLauncher\n configPath: string\n hasCustomConfig: boolean\n userArgs: string[]\n env: NodeJS.ProcessEnv\n}): Promise<PlaywrightRuntimeSettings> {\n const probeArgs = [\"test\"]\n if (!hasCustomConfig) {\n probeArgs.push(\"--config\", configPath)\n }\n probeArgs.push(\"--list\", \"--reporter=json\", ...extractPlaywrightProjectArgs(userArgs))\n\n try {\n const stdout = await spawnAndCaptureStdout({\n name: \"Playwright retries probe\",\n launcher,\n args: probeArgs,\n env,\n })\n const json = parseJsonObjectFromText(stdout)\n if (!json) {\n return { retries: null, workers: null }\n }\n return {\n retries: resolvePlaywrightRetriesFromReport(json),\n workers: resolvePlaywrightWorkersFromReport(json),\n }\n } catch (_error) {\n return { retries: null, workers: null }\n }\n}\n\nfunction extractPlaywrightProjectArgs(userArgs: string[]): string[] {\n const output: string[] = []\n for (let i = 0; i < userArgs.length; i += 1) {\n const arg = userArgs[i]\n if (arg === \"--\") {\n break\n }\n if (arg === \"--project\") {\n const next = userArgs[i + 1]\n if (next != null) {\n output.push(arg, next)\n i += 1\n }\n continue\n }\n if (arg.startsWith(\"--project=\")) {\n output.push(arg)\n }\n }\n return output\n}\n\nfunction parseJsonObjectFromText(input: string): any | null {\n try {\n return JSON.parse(input)\n } catch {\n const start = input.indexOf(\"{\")\n const end = input.lastIndexOf(\"}\")\n if (start === -1 || end === -1 || end <= start) {\n return null\n }\n try {\n return JSON.parse(input.slice(start, end + 1))\n } catch {\n return null\n }\n }\n}\n\nfunction extractPlaywrightPositionalArgs(userArgs: string[]): string[] {\n const output: string[] = []\n\n for (let i = 0; i < userArgs.length; i += 1) {\n const arg = userArgs[i]\n\n if (arg === \"--\") {\n break\n }\n\n if (!arg.startsWith(\"-\")) {\n output.push(arg)\n continue\n }\n\n if (arg.includes(\"=\")) {\n continue\n }\n\n if (PLAYWRIGHT_OPTIONS_WITH_REQUIRED_VALUE.has(arg)) {\n const next = userArgs[i + 1]\n if (next !== undefined) {\n i += 1\n }\n continue\n }\n\n if (PLAYWRIGHT_OPTIONS_WITH_OPTIONAL_VALUE.has(arg)) {\n const next = userArgs[i + 1]\n if (next !== undefined && !next.startsWith(\"-\")) {\n i += 1\n }\n }\n }\n\n return output\n}\n\nfunction removePlaywrightOptions(optionArgs: string[], optionsToRemove: Set<string>): string[] {\n const output: string[] = []\n for (let i = 0; i < optionArgs.length; i += 1) {\n const arg = optionArgs[i]\n const normalized = arg.split(\"=\")[0]\n if (!arg.startsWith(\"-\") || !optionsToRemove.has(normalized)) {\n output.push(arg)\n continue\n }\n\n if (arg.includes(\"=\")) {\n continue\n }\n\n if (PLAYWRIGHT_OPTIONS_WITH_REQUIRED_VALUE.has(normalized)) {\n const next = optionArgs[i + 1]\n if (next !== undefined) {\n i += 1\n }\n continue\n }\n\n if (PLAYWRIGHT_OPTIONS_WITH_OPTIONAL_VALUE.has(normalized)) {\n const next = optionArgs[i + 1]\n if (next !== undefined && !next.startsWith(\"-\")) {\n i += 1\n }\n }\n }\n return output\n}\n\nfunction extractPlaywrightOptionArgs(userArgs: string[]): string[] {\n const output: string[] = []\n\n for (let i = 0; i < userArgs.length; i += 1) {\n const arg = userArgs[i]\n\n if (arg === \"--\") {\n break\n }\n\n if (!arg.startsWith(\"-\")) {\n continue\n }\n\n output.push(arg)\n\n if (arg.includes(\"=\")) {\n continue\n }\n\n if (PLAYWRIGHT_OPTIONS_WITH_REQUIRED_VALUE.has(arg)) {\n const next = userArgs[i + 1]\n if (next !== undefined) {\n output.push(next)\n i += 1\n }\n continue\n }\n\n if (PLAYWRIGHT_OPTIONS_WITH_OPTIONAL_VALUE.has(arg)) {\n const next = userArgs[i + 1]\n if (next !== undefined && !next.startsWith(\"-\")) {\n output.push(next)\n i += 1\n }\n }\n }\n\n return output\n}\n\nasync function readPlaywrightReportSummary(\n resultsFilePath: string,\n newerThanMtimeMs: number | null,\n): Promise<PlaywrightReportSummary | null> {\n const stats = await fsPromises.stat(resultsFilePath).catch(() => null)\n if (!stats) {\n return null\n }\n\n if (newerThanMtimeMs != null && stats.mtimeMs <= newerThanMtimeMs) {\n return null\n }\n\n const data = await readJson(resultsFilePath)\n if (!data || typeof data !== \"object\") {\n return null\n }\n\n return {\n failedFiles: resolveFailedPlaywrightFiles(data),\n }\n}\n\nfunction getFileMtimeMs(filePath: string): number | null {\n try {\n return fs.statSync(filePath).mtimeMs\n } catch {\n return null\n }\n}\n\nfunction resolvePlaywrightRetriesFromReport(data: any): number {\n const projects = Array.isArray(data?.config?.projects) ? data.config.projects : []\n const retriesFromProjects = projects\n .map((project: any) => Number(project?.retries))\n .filter((value: number) => Number.isFinite(value))\n .map((value: number) => Math.max(0, Math.floor(value)))\n\n if (retriesFromProjects.length > 0) {\n return Math.max(...retriesFromProjects)\n }\n\n const fallback = Number(data?.config?.retries)\n if (Number.isFinite(fallback)) {\n return Math.max(0, Math.floor(fallback))\n }\n\n return 0\n}\n\nfunction resolvePlaywrightWorkersFromReport(data: any): number | null {\n const configWorkers = Number(data?.config?.workers)\n if (Number.isFinite(configWorkers)) {\n return Math.max(1, Math.floor(configWorkers))\n }\n\n const projects = Array.isArray(data?.config?.projects) ? data.config.projects : []\n const workersFromProjects = projects\n .map((project: any) => Number(project?.metadata?.actualWorkers ?? project?.workers))\n .filter((value: number) => Number.isFinite(value))\n .map((value: number) => Math.max(1, Math.floor(value)))\n\n if (workersFromProjects.length > 0) {\n return Math.max(...workersFromProjects)\n }\n\n return null\n}\n\nfunction resolveFailedPlaywrightFiles(data: any): string[] {\n const suites = Array.isArray(data?.suites) ? data.suites : []\n const rootDir = typeof data?.config?.rootDir === \"string\" ? data.config.rootDir : null\n const failedFiles = new Set<string>()\n\n for (const suite of suites) {\n collectFailedPlaywrightFiles(suite, failedFiles, rootDir)\n }\n\n return Array.from(failedFiles).sort()\n}\n\nfunction collectFailedPlaywrightFiles(suite: any, output: Set<string>, rootDir: string | null): void {\n const specs = Array.isArray(suite?.specs) ? suite.specs : []\n\n for (const spec of specs) {\n if (isPlaywrightSpecSuccessful(spec)) {\n continue\n }\n const file = normalizePlaywrightReportFile(spec?.file ?? suite?.file, rootDir)\n if (file) {\n output.add(file)\n }\n }\n\n const innerSuites = Array.isArray(suite?.suites) ? suite.suites : []\n for (const innerSuite of innerSuites) {\n collectFailedPlaywrightFiles(innerSuite, output, rootDir)\n }\n}\n\nfunction isPlaywrightSpecSuccessful(spec: any): boolean {\n if (typeof spec?.ok === \"boolean\") {\n return spec.ok\n }\n\n const tests = Array.isArray(spec?.tests) ? spec.tests : []\n if (tests.length === 0) {\n return false\n }\n\n return tests.every((test: any) => {\n const testStatus = String(test?.status ?? \"\")\n if (testStatus === \"expected\" || testStatus === \"skipped\" || testStatus === \"flaky\") {\n return true\n }\n\n const results = Array.isArray(test?.results) ? test.results : []\n if (results.length === 0) {\n return false\n }\n return results.every((result: any) => result?.status === \"passed\" || result?.status === \"skipped\")\n })\n}\n\nfunction normalizePlaywrightReportFile(filePath: unknown, rootDir: string | null): string | null {\n const raw = String(filePath ?? \"\").trim()\n if (!raw) {\n return null\n }\n\n let absolutePath: string\n if (path.isAbsolute(raw)) {\n absolutePath = path.normalize(raw)\n } else {\n const cwdCandidate = path.resolve(process.cwd(), raw)\n const rootCandidate = rootDir ? path.resolve(rootDir, raw) : null\n if (rootCandidate && fs.existsSync(rootCandidate)) {\n absolutePath = rootCandidate\n } else if (fs.existsSync(cwdCandidate)) {\n absolutePath = cwdCandidate\n } else {\n absolutePath = rootCandidate ?? cwdCandidate\n }\n }\n\n const relative = path.relative(process.cwd(), absolutePath)\n if (relative === \"\" || (!relative.startsWith(\"..\") && !path.isAbsolute(relative))) {\n return toPosixPath(relative || raw)\n }\n\n return toPosixPath(raw)\n}\n\nfunction toPosixPath(input: unknown): string {\n return String(input ?? \"\").replaceAll(\"\\\\\", \"/\").split(path.sep).join(\"/\")\n}\n\nfunction buildPlaywrightRetryOutputDir(attempt: number, failedFiles: string[]): string {\n const slug = failedFiles\n .map((file) => toPosixPath(file).replace(/[^a-zA-Z0-9._/-]+/g, \"-\").replace(/\\//g, \"__\"))\n .join(\"--\")\n return toPosixPath(path.join(\"build\", \"playwright\", \"test-results\", \"rb-retries\", `attempt-${attempt}`, slug))\n}\n\nexport function createPlaywrightRetryEnv(baseEnv: NodeJS.ProcessEnv): NodeJS.ProcessEnv {\n return {\n ...baseEnv,\n PLAYWRIGHT_FORCE_TTY: \"false\",\n }\n}\n\nfunction truncatePlaywrightRetryLogLabel(label: string, maxLength = PLAYWRIGHT_RETRY_LOG_LABEL_MAX_LENGTH): string {\n if (label.length <= maxLength) {\n return label\n }\n\n if (maxLength <= 3) {\n return \".\".repeat(Math.max(0, maxLength))\n }\n\n const visibleChars = maxLength - 3\n const startLength = Math.ceil(visibleChars / 2)\n const endLength = Math.floor(visibleChars / 2)\n\n return `${label.slice(0, startLength)}...${label.slice(-endLength)}`\n}\n\nfunction getPlaywrightRetryLogName(failedFile: string): string {\n const normalizedFile = toPosixPath(failedFile)\n const relativeFile = normalizedFile.startsWith(\"build/spec/\")\n ? normalizedFile.slice(\"build/spec/\".length)\n : normalizedFile\n const strippedBaseName = relativeFile\n .replace(/\\.(spec|test)\\.[^.]+$/i, \"\")\n .replace(/\\.[^.]+$/i, \"\")\n .trim()\n\n return strippedBaseName || relativeFile || normalizedFile\n}\n\nfunction formatPlaywrightRetryBracketLabel({\n failedFile,\n suffix = \"\",\n}: {\n failedFile: string\n suffix?: string\n}): string {\n const label = truncatePlaywrightRetryLogLabel(\n getPlaywrightRetryLogName(failedFile),\n Math.max(1, PLAYWRIGHT_RETRY_LOG_LABEL_MAX_LENGTH - suffix.length),\n )\n return `[${label}${suffix}]`\n}\n\nexport function formatPlaywrightRetryLogLabel({\n failedFile,\n}: {\n failedFile: string\n}): string {\n return formatPlaywrightRetryBracketLabel({ failedFile })\n}\n\nexport function formatPlaywrightRetryLinePrefix({\n failedFile,\n stream,\n}: {\n failedFile: string\n stream: \"stdout\" | \"stderr\"\n}): string {\n return stream === \"stderr\"\n ? `${formatPlaywrightRetryBracketLabel({ failedFile, suffix: \" stderr\" })} `\n : `${formatPlaywrightRetryLogLabel({ failedFile })} `\n}\n\nasync function runPlaywrightRetryAttempt({\n launcher,\n userArgs,\n failedFiles,\n retryConcurrency,\n configPath,\n hasCustomConfig,\n env,\n attempt,\n}: {\n launcher: SpawnLauncher\n userArgs: string[]\n failedFiles: string[]\n retryConcurrency: number\n configPath: string\n hasCustomConfig: boolean\n env: NodeJS.ProcessEnv\n attempt: number\n}): Promise<{ failedFiles: string[]; lastError: unknown }> {\n const failedAgain = new Set<string>()\n let lastError: unknown = null\n let nextIndex = 0\n const retryEnv = createPlaywrightRetryEnv(env)\n\n async function runNext(): Promise<void> {\n while (nextIndex < failedFiles.length) {\n const fileIndex = nextIndex\n nextIndex += 1\n\n const failedFile = failedFiles[fileIndex]\n const retryLogLabel = formatPlaywrightRetryLogLabel({\n failedFile,\n })\n const retryArgs = buildPlaywrightWorkerRetryArgs(userArgs, [failedFile], attempt)\n const retryPlaywrightArgs = [\"test\"]\n if (!hasCustomConfig) {\n retryPlaywrightArgs.push(\"--config\", configPath)\n }\n retryPlaywrightArgs.push(...retryArgs)\n\n try {\n console.warn(`${retryLogLabel} Starting fresh-worker retry`)\n await runPlaywrightOnce({\n launcher,\n args: retryPlaywrightArgs,\n env: retryEnv,\n outputMode: \"line\",\n bufferOutput: true,\n successMessage: null,\n failureMessage: `${retryLogLabel} Playwright failed`,\n stdoutLinePrefix: formatPlaywrightRetryLinePrefix({\n failedFile,\n stream: \"stdout\",\n }),\n stderrLinePrefix: formatPlaywrightRetryLinePrefix({\n failedFile,\n stream: \"stderr\",\n }),\n })\n } catch (retryError) {\n lastError = retryError\n failedAgain.add(failedFile)\n }\n }\n }\n\n await Promise.all(\n Array.from(\n { length: Math.max(1, Math.min(retryConcurrency, failedFiles.length)) },\n () => runNext(),\n ),\n )\n\n return {\n failedFiles: failedFiles.filter((failedFile) => failedAgain.has(failedFile)),\n lastError,\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 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"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"process.js","names":[],"sources":["../../src/runners/process.ts"],"sourcesContent":["import { spawn } from \"node:child_process\"\nimport path from \"node:path\"\nimport { fileURLToPath } from \"node:url\"\n\n\nconst moduleDir = path.dirname(fileURLToPath(import.meta.url))\nconst isAider = process.env.IS_AIDER === \"yes\"\n\nexport type SpawnLauncher = {\n command: string\n args?: string[]\n}\n\ntype SpawnOutputMode = \"chunk\" | \"line\"\ntype BufferedOutputChunk = {\n stream: \"stdout\" | \"stderr\"\n text: string\n}\ntype OutputStream = Pick<NodeJS.WritableStream, \"write\">\n\nlet queuedOutputWrite: Promise<void> = Promise.resolve()\n\nexport function spawnWithLogs({\n name,\n launcher,\n args,\n env,\n successMessage,\n failureMessage,\n outputMode = \"chunk\",\n stdoutLinePrefix,\n stderrLinePrefix,\n bufferOutput = false,\n stdoutStream = process.stdout,\n stderrStream = process.stderr,\n}: {\n name: string\n launcher: SpawnLauncher\n args: string[]\n env: NodeJS.ProcessEnv\n successMessage?: string\n failureMessage?: string\n outputMode?: SpawnOutputMode\n stdoutLinePrefix?: string\n stderrLinePrefix?: string\n bufferOutput?: boolean\n stdoutStream?: OutputStream\n stderrStream?: OutputStream\n}): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n const stdoutBuffer: string[] = []\n const stderrBuffer: string[] = []\n const bufferedOutput: BufferedOutputChunk[] = []\n\n const child = spawn(\n launcher.command,\n [...(launcher.args || []), ...args],\n {\n shell: false,\n env,\n },\n )\n\n const stdoutForwarder = createOutputForwarder(stdoutStream, outputMode, stdoutLinePrefix)\n const stderrForwarder = createOutputForwarder(stderrStream, outputMode, stderrLinePrefix)\n\n child.stdout?.on(\"data\", (data) => {\n const text = data.toString()\n if (!isAider) {\n if (bufferOutput) {\n bufferedOutput.push({ stream: \"stdout\", text })\n } else {\n stdoutForwarder.write(text)\n }\n }\n stdoutBuffer.push(text)\n })\n\n child.stderr?.on(\"data\", (data) => {\n const text = data.toString()\n if (!isAider) {\n if (bufferOutput) {\n bufferedOutput.push({ stream: \"stderr\", text })\n } else {\n stderrForwarder.write(text)\n }\n }\n stderrBuffer.push(text)\n })\n\n child.on(\"close\", (code) => {\n if (!isAider) {\n if (bufferOutput) {\n flushBufferedOutput(bufferedOutput, stdoutForwarder, stderrForwarder)\n }\n stdoutForwarder.flush()\n stderrForwarder.flush()\n }\n\n const pendingWrites = queuedOutputWrite\n pendingWrites.then(() => {\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\n child.on(\"error\", (error) => {\n console.error(`Error spawning ${name}:`, error)\n reject(error)\n })\n })\n}\n\nexport function spawnAndCaptureStdout({\n name,\n launcher,\n args,\n env,\n}: {\n name: string\n launcher: SpawnLauncher\n args: string[]\n env: NodeJS.ProcessEnv\n}): Promise<string> {\n return new Promise<string>((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 stdoutBuffer.push(data.toString())\n })\n\n child.stderr?.on(\"data\", (data) => {\n stderrBuffer.push(data.toString())\n })\n\n child.on(\"close\", (code) => {\n if (code === 0) {\n resolve(stdoutBuffer.join(\"\"))\n } else {\n reject(new Error(`${name} failed with exit code: ${code}\\n${stderrBuffer.join(\"\")}`))\n }\n })\n\n child.on(\"error\", (error) => {\n reject(error)\n })\n })\n}\n\nexport function 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 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\nexport function prefixOutputLine(line: string, prefix?: string): string {\n if (!prefix || line.length === 0) {\n return line\n }\n\n if (line.endsWith(\"\\n\")) {\n return `${prefix}${line.slice(0, -1)}\\n`\n }\n\n return `${prefix}${line}`\n}\n\nfunction flushBufferedOutput(\n bufferedOutput: BufferedOutputChunk[],\n stdoutForwarder: ReturnType<typeof createOutputForwarder>,\n stderrForwarder: ReturnType<typeof createOutputForwarder>,\n): void {\n for (const chunk of bufferedOutput) {\n if (chunk.stream === \"stderr\") {\n stderrForwarder.write(chunk.text)\n } else {\n stdoutForwarder.write(chunk.text)\n }\n }\n}\n\nfunction createOutputForwarder(stream: OutputStream, outputMode: SpawnOutputMode, linePrefix?: string) {\n let pendingLine = \"\"\n\n return {\n write(data: Buffer | string) {\n const text = data.toString()\n if (outputMode === \"chunk\" && !linePrefix) {\n queueStreamWrite(stream, text)\n return\n }\n\n pendingLine += text\n while (true) {\n const newlineIndex = pendingLine.indexOf(\"\\n\")\n if (newlineIndex === -1) {\n break\n }\n const nextLine = pendingLine.slice(0, newlineIndex + 1)\n pendingLine = pendingLine.slice(newlineIndex + 1)\n queueStreamWrite(stream, prefixOutputLine(nextLine, linePrefix))\n }\n },\n flush() {\n if (pendingLine.length === 0) {\n return\n }\n queueStreamWrite(stream, prefixOutputLine(pendingLine, linePrefix))\n pendingLine = \"\"\n },\n }\n}\n\nfunction queueStreamWrite(stream: OutputStream, text: string): void {\n queuedOutputWrite = queuedOutputWrite\n .then(() => new Promise<void>((resolve) => {\n stream.write(text, () => resolve())\n }))\n .catch(() => undefined)\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"process.js","names":[],"sources":["../../src/runners/process.ts"],"sourcesContent":["import { spawn } from \"node:child_process\"\nimport path from \"node:path\"\nimport { fileURLToPath } from \"node:url\"\n\n\nconst moduleDir = path.dirname(fileURLToPath(import.meta.url))\nconst isAider = process.env.IS_AIDER === \"yes\"\n\nexport type SpawnLauncher = {\n command: string\n args?: string[]\n}\n\ntype SpawnOutputMode = \"chunk\" | \"line\"\ntype BufferedOutputChunk = {\n stream: \"stdout\" | \"stderr\"\n text: string\n}\ntype OutputStream = Pick<NodeJS.WritableStream, \"write\">\n\nlet queuedOutputWrite: Promise<void> = Promise.resolve()\n\nexport function spawnWithLogs({\n name,\n launcher,\n args,\n env,\n successMessage,\n failureMessage,\n outputMode = \"chunk\",\n stdoutLinePrefix,\n stderrLinePrefix,\n bufferOutput = false,\n stdoutStream = process.stdout,\n stderrStream = process.stderr,\n}: {\n name: string\n launcher: SpawnLauncher\n args: string[]\n env: NodeJS.ProcessEnv\n successMessage?: string\n failureMessage?: string\n outputMode?: SpawnOutputMode\n stdoutLinePrefix?: string\n stderrLinePrefix?: string\n bufferOutput?: boolean\n stdoutStream?: OutputStream\n stderrStream?: OutputStream\n}): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n const stdoutBuffer: string[] = []\n const stderrBuffer: string[] = []\n const bufferedOutput: BufferedOutputChunk[] = []\n\n const child = spawn(\n launcher.command,\n [...(launcher.args || []), ...args],\n {\n shell: false,\n env,\n },\n )\n\n const stdoutForwarder = createOutputForwarder(stdoutStream, outputMode, stdoutLinePrefix)\n const stderrForwarder = createOutputForwarder(stderrStream, outputMode, stderrLinePrefix)\n\n child.stdout?.on(\"data\", (data) => {\n const text = data.toString()\n if (!isAider) {\n if (bufferOutput) {\n bufferedOutput.push({ stream: \"stdout\", text })\n } else {\n stdoutForwarder.write(text)\n }\n }\n stdoutBuffer.push(text)\n })\n\n child.stderr?.on(\"data\", (data) => {\n const text = data.toString()\n if (!isAider) {\n if (bufferOutput) {\n bufferedOutput.push({ stream: \"stderr\", text })\n } else {\n stderrForwarder.write(text)\n }\n }\n stderrBuffer.push(text)\n })\n\n child.on(\"close\", (code) => {\n if (!isAider) {\n if (bufferOutput) {\n flushBufferedOutput(bufferedOutput, stdoutForwarder, stderrForwarder)\n }\n stdoutForwarder.flush()\n stderrForwarder.flush()\n }\n\n const pendingWrites = queuedOutputWrite\n pendingWrites.then(() => {\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\n child.on(\"error\", (error) => {\n console.error(`Error spawning ${name}:`, error)\n reject(error)\n })\n })\n}\n\nexport function spawnAndCaptureStdout({\n name,\n launcher,\n args,\n env,\n}: {\n name: string\n launcher: SpawnLauncher\n args: string[]\n env: NodeJS.ProcessEnv\n}): Promise<string> {\n return new Promise<string>((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 stdoutBuffer.push(data.toString())\n })\n\n child.stderr?.on(\"data\", (data) => {\n stderrBuffer.push(data.toString())\n })\n\n child.on(\"close\", (code) => {\n if (code === 0) {\n resolve(stdoutBuffer.join(\"\"))\n } else {\n reject(new Error(`${name} failed with exit code: ${code}\\n${stderrBuffer.join(\"\")}`))\n }\n })\n\n child.on(\"error\", (error) => {\n reject(error)\n })\n })\n}\n\nexport function 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 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\nexport function prefixOutputLine(line: string, prefix?: string): string {\n if (!prefix || line.length === 0) {\n return line\n }\n\n if (line.endsWith(\"\\n\")) {\n return `${prefix}${line.slice(0, -1)}\\n`\n }\n\n return `${prefix}${line}`\n}\n\nfunction flushBufferedOutput(\n bufferedOutput: BufferedOutputChunk[],\n stdoutForwarder: ReturnType<typeof createOutputForwarder>,\n stderrForwarder: ReturnType<typeof createOutputForwarder>,\n): void {\n for (const chunk of bufferedOutput) {\n if (chunk.stream === \"stderr\") {\n stderrForwarder.write(chunk.text)\n } else {\n stdoutForwarder.write(chunk.text)\n }\n }\n}\n\nfunction createOutputForwarder(stream: OutputStream, outputMode: SpawnOutputMode, linePrefix?: string) {\n let pendingLine = \"\"\n\n return {\n write(data: Buffer | string) {\n const text = data.toString()\n if (outputMode === \"chunk\" && !linePrefix) {\n queueStreamWrite(stream, text)\n return\n }\n\n pendingLine += text\n while (true) {\n const newlineIndex = pendingLine.indexOf(\"\\n\")\n if (newlineIndex === -1) {\n break\n }\n const nextLine = pendingLine.slice(0, newlineIndex + 1)\n pendingLine = pendingLine.slice(newlineIndex + 1)\n queueStreamWrite(stream, prefixOutputLine(nextLine, linePrefix))\n }\n },\n flush() {\n if (pendingLine.length === 0) {\n return\n }\n queueStreamWrite(stream, prefixOutputLine(pendingLine, linePrefix))\n pendingLine = \"\"\n },\n }\n}\n\nfunction queueStreamWrite(stream: OutputStream, text: string): void {\n queuedOutputWrite = queuedOutputWrite\n .then(() => new Promise<void>((resolve) => {\n stream.write(text, () => resolve())\n }))\n .catch(() => undefined)\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vitest.js","names":[],"sources":["../../src/runners/vitest.ts"],"sourcesContent":["import 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 { isInsideAnyRoot, resolveCollectCoverageRoots } from \"../coverage/collect\"\nimport type { CoverageConfig } from \"../coverage/types\"\nimport { spawnWithLogs, withRegisterShim, type SpawnLauncher } from \"./process\"\n\n\nconst require = createRequire(import.meta.url)\nconst moduleDir = path.dirname(fileURLToPath(import.meta.url))\n\ntype CoverageState = { config: CoverageConfig; enabled: boolean } | null\n\nexport async function runVitest(\n coverage: CoverageState,\n combinedConfig: CoverageConfig | null,\n userArgs: string[],\n { disableCoverage = false }: { disableCoverage?: boolean } = {},\n): Promise<void> {\n const vitestArgs = [\"run\", \"--passWithNoTests\"]\n const vitestConfig = resolveVitestConfig()\n\n const hasCustomConfig = userArgs.some((arg) => {\n if (arg === \"--config\" || arg === \"-c\") {\n return true\n }\n return arg.startsWith(\"--config=\")\n })\n\n if (vitestConfig && !hasCustomConfig) {\n vitestArgs.push(\"--config\", vitestConfig)\n }\n vitestArgs.push(...userArgs)\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 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\nexport function resolveNodeCoverageDir(config: CoverageConfig): string {\n return path.join(config.rootDir, \"build\", \"vitest\", \"test-results\", \"node-coverage\")\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 for a usable vitest launcher.\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 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 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 file URLs in raw coverage payloads.\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"],"mappings":";;;;;;;;AAWA,IAAM,UAAU,cAAc,YAAY,GAAG;AAC7C,IAAM,YAAY,KAAK,QAAQ,cAAc,YAAY,GAAG,CAAC;AAI7D,eAAsB,UACpB,UACA,gBACA,UACA,EAAE,kBAAkB,UAAyC,CAAC,GAC/C;CACf,MAAM,aAAa,CAAC,OAAO,mBAAmB;CAC9C,MAAM,eAAe,oBAAoB;CAEzC,MAAM,kBAAkB,SAAS,MAAM,QAAQ;EAC7C,IAAI,QAAQ,cAAc,QAAQ,MAChC,OAAO;EAET,OAAO,IAAI,WAAW,WAAW;CACnC,CAAC;CAED,IAAI,gBAAgB,CAAC,iBACnB,WAAW,KAAK,YAAY,YAAY;CAE1C,WAAW,KAAK,GAAG,QAAQ;CAE3B,MAAM,WAAW,sBAAsB;CACvC,MAAM,MAAM,iBAAiB,QAAQ,GAAG;CAExC,IAAI,iBACF,IAAI,sBAAsB;CAG5B,IAAI,UAAU,WAAW,CAAC,iBAAiB;EACzC,MAAM,kBAAkB,uBAAuB,kBAAkB,SAAS,MAAM;EAChF,MAAM,GAAW,MAAM,iBAAiB,EAAE,WAAW,KAAK,CAAC;EAC3D,IAAI,mBAAmB;CACzB;CAEA,MAAM,cAAc;EAClB,MAAM;EACN;EACA,MAAM;EACN;EACA,gBAAgB;EAChB,gBAAgB;CAClB,CAAC;CAED,IAAI,UAAU,WAAW,CAAC,iBACxB,MAAM,oBAAoB;EACxB,QAAQ,kBAAkB,SAAS;EACnC,iBAAiB,uBAAuB,kBAAkB,SAAS,MAAM;CAC3E,CAAC;AAEL;AAEA,SAAgB,uBAAuB,QAAgC;CACrE,OAAO,KAAK,KAAK,OAAO,SAAS,SAAS,UAAU,gBAAgB,eAAe;AACrF;AAEA,SAAS,wBAAuC;CAC9C,MAAM,cAAc,CAAC,QAAQ,IAAI,GAAG,SAAS;CAE7C,KAAK,MAAM,QAAQ,aACjB,IAAI;EACF,MAAM,UAAU,QAAQ,QAAQ,uBAAuB,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC;EACxE,MAAM,SAAS,KAAK,QAAQ,OAAO;EACnC,MAAM,UAAU,KAAK,MAAM,OAAG,aAAa,SAAS,MAAM,CAAC;EAC3D,MAAM,UAAU,OAAO,QAAQ,QAAQ,WAAW,QAAQ,MAAM,QAAQ,KAAK;EAC7E,IAAI,SACF,OAAO;GACL,SAAS,QAAQ;GACjB,MAAM,CAAC,KAAK,KAAK,QAAQ,OAAO,CAAC;EACnC;CAEJ,SAAS,QAAQ,CACf;CAIJ,MAAM,WAAW,KAAK,QAAQ,QAAQ,IAAI,GAAG,0BAA0B;CACvE,IAAI,OAAG,WAAW,QAAQ,GACxB,OAAO;EACL,SAAS;EACT,MAAM,CAAA;CACR;CAGF,OAAO;EACL,SAAS;EACT,MAAM,CAAA;CACR;AACF;AAEA,SAAS,sBAAqC;CAC5C,MAAM,aAAa,iBAAiB,QAAQ,IAAI,CAAC;CACjD,IAAI,YACF,OAAO;CAGT,MAAM,gBAAgB,KAAK,KAAK,WAAW,MAAM,kBAAkB;CACnE,OAAO,OAAG,WAAW,aAAa,IAAI,gBAAgB;AACxD;AAEA,SAAS,iBAAiB,SAAgC;CAOxD,KAAK,MAAM,QAAQ;EALjB;EACA;EACA;CAGiB,GAAY;EAC7B,MAAM,WAAW,KAAK,KAAK,SAAS,IAAI;EACxC,IAAI,OAAG,WAAW,QAAQ,GACxB,OAAO;CAEX;CAEA,OAAO;AACT;AAEA,eAAe,oBAAoB,UAA8E;CAC/G,MAAM,EAAE,QAAQ,oBAAoB;CAEpC,MAAM,UAAU,MAAM,GAAW,QAAQ,eAAe,CAAC,CAAC,YAAY,CAAA,CAAE;CACxE,MAAM,UAAU,CAAA;CAChB,MAAM,cAAc,4BAA4B,OAAO,qBAAqB,OAAO,OAAO;CAE1F,KAAK,MAAM,SAAS,SAAS;EAC3B,IAAI,CAAC,MAAM,SAAS,OAAO,GACzB;EAIF,MAAM,UAAU,MAAM,SADL,KAAK,KAAK,iBAAiB,KACb,CAAQ;EACvC,MAAM,UAAU,MAAM,QAAQ,SAAS,MAAM,IAAI,QAAQ,SAAS,CAAA;EAElE,KAAK,MAAM,UAAU,SAAS;GAC5B,MAAM,aAAa,uBAAuB,OAAO,KAAK,OAAO,OAAO;GACpE,IAAI,CAAC,YACH;GAGF,IAAI,kBAAkB,WAAW,YAAY,GAC3C;GAGF,IAAI,CAAC,gBAAgB,WAAW,cAAc,WAAW,GACvD;GAGF,MAAM,SAAS,MAAM,GAAW,SAAS,WAAW,cAAc,MAAM,CAAC,CAAC,YAAY,EAAE;GAExF,QAAQ,KAAK;IACX,cAAc,WAAW;IACzB,cAAc,WAAW;IACzB;IACA,WAAW,OAAO,aAAa,CAAA;IAC/B,KAAK,OAAO;GACd,CAAC;EACH;CACF;CAEA,IAAI,QAAQ,WAAW,GACrB;CAGF,MAAM,SAAS,KAAK,KAAK,OAAO,SAAS,SAAS,UAAU,UAAU;CACtE,MAAM,GAAW,MAAM,QAAQ,EAAE,WAAW,KAAK,CAAC;CAClD,MAAM,aAAa,KAAK,KAAK,QAAQ,OAAO,gBAAgB;CAC5D,MAAM,GAAW,UAAU,YAAY,KAAK,UAAU;EAAE,QAAQ;EAAU;CAAQ,GAAG,MAAM,CAAC,GAAG,MAAM;AACvG;AAEA,eAAe,SAAS,UAAuC;CAC7D,IAAI;EACF,MAAM,MAAM,MAAM,GAAW,SAAS,UAAU,MAAM;EACtD,OAAO,KAAK,MAAM,GAAG;CACvB,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAS,uBACP,QACA,SACuD;CACvD,IAAI,CAAC,UAAU,OAAO,WAAW,OAAO,GACtC,OAAO;CAGT,IAAI,eAAe;CAEnB,IAAI;EACF,IAAI,OAAO,WAAW,SAAS,GAC7B,eAAe,cAAc,MAAM;CAEvC,SAAS,MAAM,CACb;CAGF,IAAI,CAAC,gBAAgB,KAAK,WAAW,MAAM,GACzC,eAAe;CAGjB,IAAI,CAAC,cACH,OAAO;CAGT,MAAM,aAAa,KAAK,UAAU,YAAY;CAE9C,OAAO;EACL,cAAc;EACd,cAAc,KAAK,SAAS,SAAS,UAAU;CACjD;AACF;AAEA,SAAS,kBAAkB,UAA4B;CACrD,OAAO,KACJ,UAAU,OAAO,YAAY,EAAE,CAAC,CAAC,CACjC,MAAM,KAAK,GAAG,CAAC,CACf,SAAS,cAAc;AAC5B"}
|
|
1
|
+
{"version":3,"file":"vitest.js","names":[],"sources":["../../src/runners/vitest.ts"],"sourcesContent":["import 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 { isInsideAnyRoot, resolveCollectCoverageRoots } from \"../coverage/collect\"\nimport type { CoverageConfig } from \"../coverage/types\"\nimport { spawnWithLogs, withRegisterShim, type SpawnLauncher } from \"./process\"\n\n\nconst require = createRequire(import.meta.url)\nconst moduleDir = path.dirname(fileURLToPath(import.meta.url))\n\ntype CoverageState = { config: CoverageConfig; enabled: boolean } | null\n\nexport async function runVitest(\n coverage: CoverageState,\n combinedConfig: CoverageConfig | null,\n userArgs: string[],\n { disableCoverage = false }: { disableCoverage?: boolean } = {},\n): Promise<void> {\n const vitestArgs = [\"run\", \"--passWithNoTests\"]\n const vitestConfig = resolveVitestConfig()\n\n const hasCustomConfig = userArgs.some((arg) => {\n if (arg === \"--config\" || arg === \"-c\") {\n return true\n }\n return arg.startsWith(\"--config=\")\n })\n\n if (vitestConfig && !hasCustomConfig) {\n vitestArgs.push(\"--config\", vitestConfig)\n }\n vitestArgs.push(...userArgs)\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 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\nexport function resolveNodeCoverageDir(config: CoverageConfig): string {\n return path.join(config.rootDir, \"build\", \"vitest\", \"test-results\", \"node-coverage\")\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 for a usable vitest launcher.\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 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 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 file URLs in raw coverage payloads.\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"],"mappings":";;;;;;;;AAWA,IAAM,UAAU,cAAc,YAAY,GAAG;AAC7C,IAAM,YAAY,KAAK,QAAQ,cAAc,YAAY,GAAG,CAAC;AAI7D,eAAsB,UACpB,UACA,gBACA,UACA,EAAE,kBAAkB,UAAyC,CAAC,GAC/C;CACf,MAAM,aAAa,CAAC,OAAO,mBAAmB;CAC9C,MAAM,eAAe,oBAAoB;CAEzC,MAAM,kBAAkB,SAAS,MAAM,QAAQ;EAC7C,IAAI,QAAQ,cAAc,QAAQ,MAChC,OAAO;EAET,OAAO,IAAI,WAAW,WAAW;CACnC,CAAC;CAED,IAAI,gBAAgB,CAAC,iBACnB,WAAW,KAAK,YAAY,YAAY;CAE1C,WAAW,KAAK,GAAG,QAAQ;CAE3B,MAAM,WAAW,sBAAsB;CACvC,MAAM,MAAM,iBAAiB,QAAQ,GAAG;CAExC,IAAI,iBACF,IAAI,sBAAsB;CAG5B,IAAI,UAAU,WAAW,CAAC,iBAAiB;EACzC,MAAM,kBAAkB,uBAAuB,kBAAkB,SAAS,MAAM;EAChF,MAAM,GAAW,MAAM,iBAAiB,EAAE,WAAW,KAAK,CAAC;EAC3D,IAAI,mBAAmB;CACzB;CAEA,MAAM,cAAc;EAClB,MAAM;EACN;EACA,MAAM;EACN;EACA,gBAAgB;EAChB,gBAAgB;CAClB,CAAC;CAED,IAAI,UAAU,WAAW,CAAC,iBACxB,MAAM,oBAAoB;EACxB,QAAQ,kBAAkB,SAAS;EACnC,iBAAiB,uBAAuB,kBAAkB,SAAS,MAAM;CAC3E,CAAC;AAEL;AAEA,SAAgB,uBAAuB,QAAgC;CACrE,OAAO,KAAK,KAAK,OAAO,SAAS,SAAS,UAAU,gBAAgB,eAAe;AACrF;AAEA,SAAS,wBAAuC;CAC9C,MAAM,cAAc,CAAC,QAAQ,IAAI,GAAG,SAAS;CAE7C,KAAK,MAAM,QAAQ,aACjB,IAAI;EACF,MAAM,UAAU,QAAQ,QAAQ,uBAAuB,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC;EACxE,MAAM,SAAS,KAAK,QAAQ,OAAO;EACnC,MAAM,UAAU,KAAK,MAAM,OAAG,aAAa,SAAS,MAAM,CAAC;EAC3D,MAAM,UAAU,OAAO,QAAQ,QAAQ,WAAW,QAAQ,MAAM,QAAQ,KAAK;EAC7E,IAAI,SACF,OAAO;GACL,SAAS,QAAQ;GACjB,MAAM,CAAC,KAAK,KAAK,QAAQ,OAAO,CAAC;EACnC;CAEJ,SAAS,QAAQ,CAEjB;CAGF,MAAM,WAAW,KAAK,QAAQ,QAAQ,IAAI,GAAG,0BAA0B;CACvE,IAAI,OAAG,WAAW,QAAQ,GACxB,OAAO;EACL,SAAS;EACT,MAAM,CAAC;CACT;CAGF,OAAO;EACL,SAAS;EACT,MAAM,CAAC;CACT;AACF;AAEA,SAAS,sBAAqC;CAC5C,MAAM,aAAa,iBAAiB,QAAQ,IAAI,CAAC;CACjD,IAAI,YACF,OAAO;CAGT,MAAM,gBAAgB,KAAK,KAAK,WAAW,MAAM,kBAAkB;CACnE,OAAO,OAAG,WAAW,aAAa,IAAI,gBAAgB;AACxD;AAEA,SAAS,iBAAiB,SAAgC;CAOxD,KAAK,MAAM,QAAQ;EALjB;EACA;EACA;CAGiB,GAAY;EAC7B,MAAM,WAAW,KAAK,KAAK,SAAS,IAAI;EACxC,IAAI,OAAG,WAAW,QAAQ,GACxB,OAAO;CAEX;CAEA,OAAO;AACT;AAEA,eAAe,oBAAoB,UAA8E;CAC/G,MAAM,EAAE,QAAQ,oBAAoB;CAEpC,MAAM,UAAU,MAAM,GAAW,QAAQ,eAAe,CAAC,CAAC,YAAY,CAAC,CAAC;CACxE,MAAM,UAAU,CAAC;CACjB,MAAM,cAAc,4BAA4B,OAAO,qBAAqB,OAAO,OAAO;CAE1F,KAAK,MAAM,SAAS,SAAS;EAC3B,IAAI,CAAC,MAAM,SAAS,OAAO,GACzB;EAIF,MAAM,UAAU,MAAM,SADL,KAAK,KAAK,iBAAiB,KACb,CAAQ;EACvC,MAAM,UAAU,MAAM,QAAQ,SAAS,MAAM,IAAI,QAAQ,SAAS,CAAC;EAEnE,KAAK,MAAM,UAAU,SAAS;GAC5B,MAAM,aAAa,uBAAuB,OAAO,KAAK,OAAO,OAAO;GACpE,IAAI,CAAC,YACH;GAGF,IAAI,kBAAkB,WAAW,YAAY,GAC3C;GAGF,IAAI,CAAC,gBAAgB,WAAW,cAAc,WAAW,GACvD;GAGF,MAAM,SAAS,MAAM,GAAW,SAAS,WAAW,cAAc,MAAM,CAAC,CAAC,YAAY,EAAE;GAExF,QAAQ,KAAK;IACX,cAAc,WAAW;IACzB,cAAc,WAAW;IACzB;IACA,WAAW,OAAO,aAAa,CAAC;IAChC,KAAK,OAAO;GACd,CAAC;EACH;CACF;CAEA,IAAI,QAAQ,WAAW,GACrB;CAGF,MAAM,SAAS,KAAK,KAAK,OAAO,SAAS,SAAS,UAAU,UAAU;CACtE,MAAM,GAAW,MAAM,QAAQ,EAAE,WAAW,KAAK,CAAC;CAClD,MAAM,aAAa,KAAK,KAAK,QAAQ,OAAO,gBAAgB;CAC5D,MAAM,GAAW,UAAU,YAAY,KAAK,UAAU;EAAE,QAAQ;EAAU;CAAQ,GAAG,MAAM,CAAC,GAAG,MAAM;AACvG;AAEA,eAAe,SAAS,UAAuC;CAC7D,IAAI;EACF,MAAM,MAAM,MAAM,GAAW,SAAS,UAAU,MAAM;EACtD,OAAO,KAAK,MAAM,GAAG;CACvB,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAS,uBACP,QACA,SACuD;CACvD,IAAI,CAAC,UAAU,OAAO,WAAW,OAAO,GACtC,OAAO;CAGT,IAAI,eAAe;CAEnB,IAAI;EACF,IAAI,OAAO,WAAW,SAAS,GAC7B,eAAe,cAAc,MAAM;CAEvC,SAAS,MAAM,CAEf;CAEA,IAAI,CAAC,gBAAgB,KAAK,WAAW,MAAM,GACzC,eAAe;CAGjB,IAAI,CAAC,cACH,OAAO;CAGT,MAAM,aAAa,KAAK,UAAU,YAAY;CAE9C,OAAO;EACL,cAAc;EACd,cAAc,KAAK,SAAS,SAAS,UAAU;CACjD;AACF;AAEA,SAAS,kBAAkB,UAA4B;CACrD,OAAO,KACJ,UAAU,OAAO,YAAY,EAAE,CAAC,CAAC,CACjC,MAAM,KAAK,GAAG,CAAC,CACf,SAAS,cAAc;AAC5B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serverCoverage.js","names":[],"sources":["../src/serverCoverage.ts"],"sourcesContent":["import type { FullConfig } from \"@playwright/test\"\n\n\ntype SetupServerCoverageOptions = {\n baseURL?: string\n strict?: boolean\n}\n\nexport async function setupServerCoverage(\n config: FullConfig,\n options: SetupServerCoverageOptions = {},\n): Promise<() => Promise<void>> {\n if (process.env.RB_DISABLE_COVERAGE === \"1\") {\n return async () => {}\n }\n\n const strict = options.strict ?? true\n const baseURL = resolveBaseURL(config, options, strict)\n if (!baseURL) {\n return async () => {}\n }\n\n const startResponse = await fetch(`${baseURL}/api/dev/coverage/start`, { method: \"POST\" })\n if (!startResponse.ok) {\n const body = await startResponse.text().catch(() => \"\")\n if (!strict) {\n return async () => {}\n }\n throw new Error(`Failed to start server coverage: ${startResponse.status} ${body}`)\n }\n\n return async function stopCoverage(): Promise<void> {\n const stopResponse = await fetch(`${baseURL}/api/dev/coverage/stop`, { method: \"POST\" })\n if (!stopResponse.ok) {\n const body = await stopResponse.text().catch(() => \"\")\n throw new Error(`Failed to stop server coverage: ${stopResponse.status} ${body}`)\n }\n }\n}\n\nfunction resolveBaseURL(config: FullConfig, options: SetupServerCoverageOptions, strict: boolean): string | null {\n const raw = options.baseURL ?? (config.projects?.[0]?.use as any)?.baseURL\n ?? (process.env.PORT ? `http://localhost:${process.env.PORT}` : null)\n\n if (typeof raw !== \"string\" || !raw.trim()) {\n if (!strict) {\n return null\n }\n throw new Error(\"Cannot resolve Playwright baseURL (missing config.projects[0].use.baseURL and PORT)\")\n }\n\n return raw.replace(/\\/$/, \"\")\n}\n"],"mappings":";AAQA,eAAsB,oBACpB,QACA,UAAsC,CAAC,GACT;CAC9B,IAAI,QAAQ,IAAI,wBAAwB,KACtC,OAAO,YAAY,CAAC;CAGtB,MAAM,SAAS,QAAQ,UAAU;CACjC,MAAM,UAAU,eAAe,QAAQ,SAAS,MAAM;CACtD,IAAI,CAAC,SACH,OAAO,YAAY,CAAC;CAGtB,MAAM,gBAAgB,MAAM,MAAM,GAAG,
|
|
1
|
+
{"version":3,"file":"serverCoverage.js","names":[],"sources":["../src/serverCoverage.ts"],"sourcesContent":["import type { FullConfig } from \"@playwright/test\"\n\n\ntype SetupServerCoverageOptions = {\n baseURL?: string\n strict?: boolean\n}\n\nexport async function setupServerCoverage(\n config: FullConfig,\n options: SetupServerCoverageOptions = {},\n): Promise<() => Promise<void>> {\n if (process.env.RB_DISABLE_COVERAGE === \"1\") {\n return async () => {}\n }\n\n const strict = options.strict ?? true\n const baseURL = resolveBaseURL(config, options, strict)\n if (!baseURL) {\n return async () => {}\n }\n\n const startResponse = await fetch(`${baseURL}/api/dev/coverage/start`, { method: \"POST\" })\n if (!startResponse.ok) {\n const body = await startResponse.text().catch(() => \"\")\n if (!strict) {\n return async () => {}\n }\n throw new Error(`Failed to start server coverage: ${startResponse.status} ${body}`)\n }\n\n return async function stopCoverage(): Promise<void> {\n const stopResponse = await fetch(`${baseURL}/api/dev/coverage/stop`, { method: \"POST\" })\n if (!stopResponse.ok) {\n const body = await stopResponse.text().catch(() => \"\")\n throw new Error(`Failed to stop server coverage: ${stopResponse.status} ${body}`)\n }\n }\n}\n\nfunction resolveBaseURL(config: FullConfig, options: SetupServerCoverageOptions, strict: boolean): string | null {\n const raw = options.baseURL ?? (config.projects?.[0]?.use as any)?.baseURL\n ?? (process.env.PORT ? `http://localhost:${process.env.PORT}` : null)\n\n if (typeof raw !== \"string\" || !raw.trim()) {\n if (!strict) {\n return null\n }\n throw new Error(\"Cannot resolve Playwright baseURL (missing config.projects[0].use.baseURL and PORT)\")\n }\n\n return raw.replace(/\\/$/, \"\")\n}\n"],"mappings":";AAQA,eAAsB,oBACpB,QACA,UAAsC,CAAC,GACT;CAC9B,IAAI,QAAQ,IAAI,wBAAwB,KACtC,OAAO,YAAY,CAAC;CAGtB,MAAM,SAAS,QAAQ,UAAU;CACjC,MAAM,UAAU,eAAe,QAAQ,SAAS,MAAM;CACtD,IAAI,CAAC,SACH,OAAO,YAAY,CAAC;CAGtB,MAAM,gBAAgB,MAAM,MAAM,GAAG,QAAQ,0BAA0B,EAAE,QAAQ,OAAO,CAAC;CACzF,IAAI,CAAC,cAAc,IAAI;EACrB,MAAM,OAAO,MAAM,cAAc,KAAK,CAAC,CAAC,YAAY,EAAE;EACtD,IAAI,CAAC,QACH,OAAO,YAAY,CAAC;EAEtB,MAAM,IAAI,MAAM,oCAAoC,cAAc,OAAO,GAAG,MAAM;CACpF;CAEA,OAAO,eAAe,eAA8B;EAClD,MAAM,eAAe,MAAM,MAAM,GAAG,QAAQ,yBAAyB,EAAE,QAAQ,OAAO,CAAC;EACvF,IAAI,CAAC,aAAa,IAAI;GACpB,MAAM,OAAO,MAAM,aAAa,KAAK,CAAC,CAAC,YAAY,EAAE;GACrD,MAAM,IAAI,MAAM,mCAAmC,aAAa,OAAO,GAAG,MAAM;EAClF;CACF;AACF;AAEA,SAAS,eAAe,QAAoB,SAAqC,QAAgC;CAC/G,MAAM,MAAM,QAAQ,YAAY,OAAO,WAAW,EAAE,EAAE,IAAA,EAAa,YAC7D,QAAQ,IAAI,OAAO,oBAAoB,QAAQ,IAAI,SAAS;CAElE,IAAI,OAAO,QAAQ,YAAY,CAAC,IAAI,KAAK,GAAG;EAC1C,IAAI,CAAC,QACH,OAAO;EAET,MAAM,IAAI,MAAM,qFAAqF;CACvG;CAEA,OAAO,IAAI,QAAQ,OAAO,EAAE;AAC9B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vitest.config.js","names":[],"sources":["../src/vitest.config.ts"],"sourcesContent":["import path from \"node:path\"\nimport fs from \"node:fs\"\nimport { createRequire } from \"node:module\"\n\nimport { defineConfig } from \"vitest/config\"\n\n\nfunction escapeRegex(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\")\n}\n\ntype TsconfigPaths = Record<string, string[]>\ntype RawTsconfig = {\n extends?: string | string[]\n compilerOptions?: {\n baseUrl?: string\n paths?: unknown\n }\n}\n\nfunction findTsconfig(startDir: string): string | null {\n let current = path.resolve(startDir)\n\n while (true) {\n for (const name of [\"tsconfig.json\", \"tsconfig.base.json\"]) {\n const candidate = path.join(current, name)\n if (fs.existsSync(candidate)) {\n return candidate\n }\n }\n\n const parent = path.dirname(current)\n if (parent === current) {\n return null\n }\n current = parent\n }\n}\n\nfunction stripJsonComments(input: string): string {\n let output = \"\"\n let inString = false\n let escaped = false\n let inLineComment = false\n let inBlockComment = false\n\n for (let i = 0; i < input.length; i += 1) {\n const char = input[i]\n const next = input[i + 1]\n\n if (inLineComment) {\n if (char === \"\\n\" || char === \"\\r\") {\n inLineComment = false\n output += char\n }\n continue\n }\n\n if (inBlockComment) {\n if (char === \"*\" && next === \"/\") {\n inBlockComment = false\n i += 1\n continue\n }\n output += char === \"\\n\" || char === \"\\r\" ? char : \" \"\n continue\n }\n\n if (inString) {\n output += char\n if (escaped) {\n escaped = false\n } else if (char === \"\\\\\") {\n escaped = true\n } else if (char === \"\\\"\") {\n inString = false\n }\n continue\n }\n\n if (char === \"/\" && next === \"/\") {\n inLineComment = true\n i += 1\n continue\n }\n\n if (char === \"/\" && next === \"*\") {\n inBlockComment = true\n i += 1\n continue\n }\n\n if (char === \"\\\"\") {\n inString = true\n }\n output += char\n }\n\n return output\n}\n\nfunction stripTrailingCommas(input: string): string {\n let output = \"\"\n let inString = false\n let escaped = false\n\n for (let i = 0; i < input.length; i += 1) {\n const char = input[i]\n\n if (inString) {\n output += char\n if (escaped) {\n escaped = false\n } else if (char === \"\\\\\") {\n escaped = true\n } else if (char === \"\\\"\") {\n inString = false\n }\n continue\n }\n\n if (char === \"\\\"\") {\n inString = true\n output += char\n continue\n }\n\n if (char === \",\") {\n let nextIndex = i + 1\n while (/\\s/.test(input[nextIndex] ?? \"\")) {\n nextIndex += 1\n }\n const next = input[nextIndex]\n if (next === \"}\" || next === \"]\") {\n continue\n }\n }\n\n output += char\n }\n\n return output\n}\n\nfunction parseJsonc(filePath: string): RawTsconfig {\n const raw = fs.readFileSync(filePath, \"utf8\")\n return JSON.parse(stripTrailingCommas(stripJsonComments(raw))) as RawTsconfig\n}\n\nfunction resolveTsconfigPath(candidate: string): string | null {\n if (path.extname(candidate) === \".json\" && fs.existsSync(candidate) && fs.statSync(candidate).isFile()) {\n return candidate\n }\n\n if (path.extname(candidate) === \"\") {\n const jsonCandidate = `${candidate}.json`\n if (fs.existsSync(jsonCandidate) && fs.statSync(jsonCandidate).isFile()) {\n return jsonCandidate\n }\n }\n\n const directoryCandidate = path.join(candidate, \"tsconfig.json\")\n if (fs.existsSync(directoryCandidate) && fs.statSync(directoryCandidate).isFile()) {\n return directoryCandidate\n }\n\n return null\n}\n\nfunction resolveExtends(specifier: string, configDir: string): string {\n if (specifier.startsWith(\".\") || path.isAbsolute(specifier)) {\n const resolved = resolveTsconfigPath(path.resolve(configDir, specifier))\n if (resolved) {\n return resolved\n }\n } else {\n const localRequire = createRequire(path.join(configDir, \"tsconfig.json\"))\n try {\n const resolved = localRequire.resolve(specifier)\n if (path.extname(resolved) === \".json\") {\n return resolved\n }\n } catch (_err) {\n // Fall through to tsconfig-style package resolution.\n }\n\n try {\n return localRequire.resolve(`${specifier}/tsconfig.json`)\n } catch (_err) {\n const resolved = resolveTsconfigPath(path.resolve(configDir, specifier))\n if (resolved) {\n return resolved\n }\n }\n }\n\n throw new Error(`@rpcbase/test: unable to resolve tsconfig extends \"${specifier}\" from ${configDir}`)\n}\n\nfunction normalizePaths(paths: unknown): TsconfigPaths | undefined {\n if (!paths || typeof paths !== \"object\" || Array.isArray(paths)) {\n return undefined\n }\n\n const normalized: TsconfigPaths = {}\n for (const [key, value] of Object.entries(paths)) {\n if (Array.isArray(value) && value.every((entry) => typeof entry === \"string\")) {\n normalized[key] = value\n }\n }\n\n return Object.keys(normalized).length > 0 ? normalized : undefined\n}\n\nfunction loadTsconfigFile(configPath: string, seen = new Set<string>()): { path: string; baseUrl: string; paths?: TsconfigPaths } {\n const normalizedPath = path.resolve(configPath)\n if (seen.has(normalizedPath)) {\n throw new Error(`@rpcbase/test: circular tsconfig extends detected at ${normalizedPath}`)\n }\n seen.add(normalizedPath)\n\n const configDir = path.dirname(normalizedPath)\n const raw = parseJsonc(normalizedPath)\n const extendsEntries = Array.isArray(raw.extends)\n ? raw.extends\n : typeof raw.extends === \"string\"\n ? [raw.extends]\n : []\n\n let inherited: { baseUrl: string; paths?: TsconfigPaths } = {\n baseUrl: configDir,\n }\n\n for (const entry of extendsEntries) {\n inherited = loadTsconfigFile(resolveExtends(entry, configDir), seen)\n }\n\n const compilerOptions = raw.compilerOptions ?? {}\n const paths = normalizePaths(compilerOptions.paths)\n const loaded = {\n path: normalizedPath,\n baseUrl: typeof compilerOptions.baseUrl === \"string\"\n ? path.resolve(configDir, compilerOptions.baseUrl)\n : paths\n ? configDir\n : inherited.baseUrl,\n paths: paths ?? inherited.paths,\n }\n\n seen.delete(normalizedPath)\n return loaded\n}\n\nfunction loadTsconfig(): { path: string; baseUrl: string; paths?: TsconfigPaths } {\n const configPath = findTsconfig(process.cwd())\n if (!configPath) {\n throw new Error(\"@rpcbase/test: no tsconfig found for alias resolution\")\n }\n\n return loadTsconfigFile(configPath)\n}\n\ntype ViteAliasEntry = { find: string | RegExp; replacement: string }\n\nfunction pathsToAlias(tsconfig: { path: string; baseUrl: string; paths?: TsconfigPaths }): ViteAliasEntry[] {\n const paths = tsconfig?.paths\n if (!paths) return []\n\n const baseUrl = tsconfig.baseUrl || path.dirname(tsconfig.path)\n const alias: ViteAliasEntry[] = []\n\n for (const [key, targets] of Object.entries(paths)) {\n if (!Array.isArray(targets)) continue\n\n for (const target of targets) {\n if (/\\.d\\.[cm]?ts$/.test(target)) continue\n\n if (key.includes(\"*\") && target.includes(\"*\")) {\n const wildcardPattern = target.endsWith(\"*\") ? \"(.+)\" : \"([^/]+)\"\n const find = new RegExp(\n `^${escapeRegex(key).split(\"\\\\*\").join(wildcardPattern)}$`,\n )\n let groupIndex = 0\n const replacedTarget = target.replace(/\\*/g, () => `$${++groupIndex}`)\n const replacement = path.resolve(baseUrl, replacedTarget)\n const checkPath = replacement.replace(/\\$\\\\d+/g, \"\")\n if (\n checkPath.includes(`${path.sep}node_modules${path.sep}`) &&\n !fs.existsSync(checkPath)\n ) {\n continue\n }\n alias.push({ find, replacement })\n continue\n }\n\n const find = key.replace(/\\*$/, \"\")\n const cleanTarget = target.replace(/\\*$/, \"\")\n const replacement = path.resolve(baseUrl, cleanTarget)\n if (\n replacement.includes(`${path.sep}node_modules${path.sep}`) &&\n !fs.existsSync(replacement)\n ) {\n continue\n }\n alias.push({ find, replacement })\n }\n }\n\n return alias\n}\n\nconst tsconfig = loadTsconfig()\nconst alias = pathsToAlias(tsconfig)\n\nexport default defineConfig({\n test: {\n include: [\"{src,lib}/**/*.test.{js,ts,tsx}\"],\n },\n resolve: alias.length > 0 ? { alias } : undefined,\n})\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"vitest.config.js","names":[],"sources":["../src/vitest.config.ts"],"sourcesContent":["import path from \"node:path\"\nimport fs from \"node:fs\"\nimport { createRequire } from \"node:module\"\n\nimport { defineConfig } from \"vitest/config\"\n\n\nfunction escapeRegex(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\")\n}\n\ntype TsconfigPaths = Record<string, string[]>\ntype RawTsconfig = {\n extends?: string | string[]\n compilerOptions?: {\n baseUrl?: string\n paths?: unknown\n }\n}\n\nfunction findTsconfig(startDir: string): string | null {\n let current = path.resolve(startDir)\n\n while (true) {\n for (const name of [\"tsconfig.json\", \"tsconfig.base.json\"]) {\n const candidate = path.join(current, name)\n if (fs.existsSync(candidate)) {\n return candidate\n }\n }\n\n const parent = path.dirname(current)\n if (parent === current) {\n return null\n }\n current = parent\n }\n}\n\nfunction stripJsonComments(input: string): string {\n let output = \"\"\n let inString = false\n let escaped = false\n let inLineComment = false\n let inBlockComment = false\n\n for (let i = 0; i < input.length; i += 1) {\n const char = input[i]\n const next = input[i + 1]\n\n if (inLineComment) {\n if (char === \"\\n\" || char === \"\\r\") {\n inLineComment = false\n output += char\n }\n continue\n }\n\n if (inBlockComment) {\n if (char === \"*\" && next === \"/\") {\n inBlockComment = false\n i += 1\n continue\n }\n output += char === \"\\n\" || char === \"\\r\" ? char : \" \"\n continue\n }\n\n if (inString) {\n output += char\n if (escaped) {\n escaped = false\n } else if (char === \"\\\\\") {\n escaped = true\n } else if (char === \"\\\"\") {\n inString = false\n }\n continue\n }\n\n if (char === \"/\" && next === \"/\") {\n inLineComment = true\n i += 1\n continue\n }\n\n if (char === \"/\" && next === \"*\") {\n inBlockComment = true\n i += 1\n continue\n }\n\n if (char === \"\\\"\") {\n inString = true\n }\n output += char\n }\n\n return output\n}\n\nfunction stripTrailingCommas(input: string): string {\n let output = \"\"\n let inString = false\n let escaped = false\n\n for (let i = 0; i < input.length; i += 1) {\n const char = input[i]\n\n if (inString) {\n output += char\n if (escaped) {\n escaped = false\n } else if (char === \"\\\\\") {\n escaped = true\n } else if (char === \"\\\"\") {\n inString = false\n }\n continue\n }\n\n if (char === \"\\\"\") {\n inString = true\n output += char\n continue\n }\n\n if (char === \",\") {\n let nextIndex = i + 1\n while (/\\s/.test(input[nextIndex] ?? \"\")) {\n nextIndex += 1\n }\n const next = input[nextIndex]\n if (next === \"}\" || next === \"]\") {\n continue\n }\n }\n\n output += char\n }\n\n return output\n}\n\nfunction parseJsonc(filePath: string): RawTsconfig {\n const raw = fs.readFileSync(filePath, \"utf8\")\n return JSON.parse(stripTrailingCommas(stripJsonComments(raw))) as RawTsconfig\n}\n\nfunction resolveTsconfigPath(candidate: string): string | null {\n if (path.extname(candidate) === \".json\" && fs.existsSync(candidate) && fs.statSync(candidate).isFile()) {\n return candidate\n }\n\n if (path.extname(candidate) === \"\") {\n const jsonCandidate = `${candidate}.json`\n if (fs.existsSync(jsonCandidate) && fs.statSync(jsonCandidate).isFile()) {\n return jsonCandidate\n }\n }\n\n const directoryCandidate = path.join(candidate, \"tsconfig.json\")\n if (fs.existsSync(directoryCandidate) && fs.statSync(directoryCandidate).isFile()) {\n return directoryCandidate\n }\n\n return null\n}\n\nfunction resolveExtends(specifier: string, configDir: string): string {\n if (specifier.startsWith(\".\") || path.isAbsolute(specifier)) {\n const resolved = resolveTsconfigPath(path.resolve(configDir, specifier))\n if (resolved) {\n return resolved\n }\n } else {\n const localRequire = createRequire(path.join(configDir, \"tsconfig.json\"))\n try {\n const resolved = localRequire.resolve(specifier)\n if (path.extname(resolved) === \".json\") {\n return resolved\n }\n } catch (_err) {\n // Fall through to tsconfig-style package resolution.\n }\n\n try {\n return localRequire.resolve(`${specifier}/tsconfig.json`)\n } catch (_err) {\n const resolved = resolveTsconfigPath(path.resolve(configDir, specifier))\n if (resolved) {\n return resolved\n }\n }\n }\n\n throw new Error(`@rpcbase/test: unable to resolve tsconfig extends \"${specifier}\" from ${configDir}`)\n}\n\nfunction normalizePaths(paths: unknown): TsconfigPaths | undefined {\n if (!paths || typeof paths !== \"object\" || Array.isArray(paths)) {\n return undefined\n }\n\n const normalized: TsconfigPaths = {}\n for (const [key, value] of Object.entries(paths)) {\n if (Array.isArray(value) && value.every((entry) => typeof entry === \"string\")) {\n normalized[key] = value\n }\n }\n\n return Object.keys(normalized).length > 0 ? normalized : undefined\n}\n\nfunction loadTsconfigFile(configPath: string, seen = new Set<string>()): { path: string; baseUrl: string; paths?: TsconfigPaths } {\n const normalizedPath = path.resolve(configPath)\n if (seen.has(normalizedPath)) {\n throw new Error(`@rpcbase/test: circular tsconfig extends detected at ${normalizedPath}`)\n }\n seen.add(normalizedPath)\n\n const configDir = path.dirname(normalizedPath)\n const raw = parseJsonc(normalizedPath)\n const extendsEntries = Array.isArray(raw.extends)\n ? raw.extends\n : typeof raw.extends === \"string\"\n ? [raw.extends]\n : []\n\n let inherited: { baseUrl: string; paths?: TsconfigPaths } = {\n baseUrl: configDir,\n }\n\n for (const entry of extendsEntries) {\n inherited = loadTsconfigFile(resolveExtends(entry, configDir), seen)\n }\n\n const compilerOptions = raw.compilerOptions ?? {}\n const paths = normalizePaths(compilerOptions.paths)\n const loaded = {\n path: normalizedPath,\n baseUrl: typeof compilerOptions.baseUrl === \"string\"\n ? path.resolve(configDir, compilerOptions.baseUrl)\n : paths\n ? configDir\n : inherited.baseUrl,\n paths: paths ?? inherited.paths,\n }\n\n seen.delete(normalizedPath)\n return loaded\n}\n\nfunction loadTsconfig(): { path: string; baseUrl: string; paths?: TsconfigPaths } {\n const configPath = findTsconfig(process.cwd())\n if (!configPath) {\n throw new Error(\"@rpcbase/test: no tsconfig found for alias resolution\")\n }\n\n return loadTsconfigFile(configPath)\n}\n\ntype ViteAliasEntry = { find: string | RegExp; replacement: string }\n\nfunction pathsToAlias(tsconfig: { path: string; baseUrl: string; paths?: TsconfigPaths }): ViteAliasEntry[] {\n const paths = tsconfig?.paths\n if (!paths) return []\n\n const baseUrl = tsconfig.baseUrl || path.dirname(tsconfig.path)\n const alias: ViteAliasEntry[] = []\n\n for (const [key, targets] of Object.entries(paths)) {\n if (!Array.isArray(targets)) continue\n\n for (const target of targets) {\n if (/\\.d\\.[cm]?ts$/.test(target)) continue\n\n if (key.includes(\"*\") && target.includes(\"*\")) {\n const wildcardPattern = target.endsWith(\"*\") ? \"(.+)\" : \"([^/]+)\"\n const find = new RegExp(\n `^${escapeRegex(key).split(\"\\\\*\").join(wildcardPattern)}$`,\n )\n let groupIndex = 0\n const replacedTarget = target.replace(/\\*/g, () => `$${++groupIndex}`)\n const replacement = path.resolve(baseUrl, replacedTarget)\n const checkPath = replacement.replace(/\\$\\\\d+/g, \"\")\n if (\n checkPath.includes(`${path.sep}node_modules${path.sep}`) &&\n !fs.existsSync(checkPath)\n ) {\n continue\n }\n alias.push({ find, replacement })\n continue\n }\n\n const find = key.replace(/\\*$/, \"\")\n const cleanTarget = target.replace(/\\*$/, \"\")\n const replacement = path.resolve(baseUrl, cleanTarget)\n if (\n replacement.includes(`${path.sep}node_modules${path.sep}`) &&\n !fs.existsSync(replacement)\n ) {\n continue\n }\n alias.push({ find, replacement })\n }\n }\n\n return alias\n}\n\nconst tsconfig = loadTsconfig()\nconst alias = pathsToAlias(tsconfig)\n\nexport default defineConfig({\n test: {\n include: [\"{src,lib}/**/*.test.{js,ts,tsx}\"],\n },\n resolve: alias.length > 0 ? { alias } : undefined,\n})\n"],"mappings":";;;;;AAOA,SAAS,YAAY,KAAqB;CACxC,OAAO,IAAI,QAAQ,uBAAuB,MAAM;AAClD;AAWA,SAAS,aAAa,UAAiC;CACrD,IAAI,UAAU,KAAK,QAAQ,QAAQ;CAEnC,OAAO,MAAM;EACX,KAAK,MAAM,QAAQ,CAAC,iBAAiB,oBAAoB,GAAG;GAC1D,MAAM,YAAY,KAAK,KAAK,SAAS,IAAI;GACzC,IAAI,OAAG,WAAW,SAAS,GACzB,OAAO;EAEX;EAEA,MAAM,SAAS,KAAK,QAAQ,OAAO;EACnC,IAAI,WAAW,SACb,OAAO;EAET,UAAU;CACZ;AACF;AAEA,SAAS,kBAAkB,OAAuB;CAChD,IAAI,SAAS;CACb,IAAI,WAAW;CACf,IAAI,UAAU;CACd,IAAI,gBAAgB;CACpB,IAAI,iBAAiB;CAErB,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK,GAAG;EACxC,MAAM,OAAO,MAAM;EACnB,MAAM,OAAO,MAAM,IAAI;EAEvB,IAAI,eAAe;GACjB,IAAI,SAAS,QAAQ,SAAS,MAAM;IAClC,gBAAgB;IAChB,UAAU;GACZ;GACA;EACF;EAEA,IAAI,gBAAgB;GAClB,IAAI,SAAS,OAAO,SAAS,KAAK;IAChC,iBAAiB;IACjB,KAAK;IACL;GACF;GACA,UAAU,SAAS,QAAQ,SAAS,OAAO,OAAO;GAClD;EACF;EAEA,IAAI,UAAU;GACZ,UAAU;GACV,IAAI,SACF,UAAU;QACL,IAAI,SAAS,MAClB,UAAU;QACL,IAAI,SAAS,MAClB,WAAW;GAEb;EACF;EAEA,IAAI,SAAS,OAAO,SAAS,KAAK;GAChC,gBAAgB;GAChB,KAAK;GACL;EACF;EAEA,IAAI,SAAS,OAAO,SAAS,KAAK;GAChC,iBAAiB;GACjB,KAAK;GACL;EACF;EAEA,IAAI,SAAS,MACX,WAAW;EAEb,UAAU;CACZ;CAEA,OAAO;AACT;AAEA,SAAS,oBAAoB,OAAuB;CAClD,IAAI,SAAS;CACb,IAAI,WAAW;CACf,IAAI,UAAU;CAEd,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK,GAAG;EACxC,MAAM,OAAO,MAAM;EAEnB,IAAI,UAAU;GACZ,UAAU;GACV,IAAI,SACF,UAAU;QACL,IAAI,SAAS,MAClB,UAAU;QACL,IAAI,SAAS,MAClB,WAAW;GAEb;EACF;EAEA,IAAI,SAAS,MAAM;GACjB,WAAW;GACX,UAAU;GACV;EACF;EAEA,IAAI,SAAS,KAAK;GAChB,IAAI,YAAY,IAAI;GACpB,OAAO,KAAK,KAAK,MAAM,cAAc,EAAE,GACrC,aAAa;GAEf,MAAM,OAAO,MAAM;GACnB,IAAI,SAAS,OAAO,SAAS,KAC3B;EAEJ;EAEA,UAAU;CACZ;CAEA,OAAO;AACT;AAEA,SAAS,WAAW,UAA+B;CACjD,MAAM,MAAM,OAAG,aAAa,UAAU,MAAM;CAC5C,OAAO,KAAK,MAAM,oBAAoB,kBAAkB,GAAG,CAAC,CAAC;AAC/D;AAEA,SAAS,oBAAoB,WAAkC;CAC7D,IAAI,KAAK,QAAQ,SAAS,MAAM,WAAW,OAAG,WAAW,SAAS,KAAK,OAAG,SAAS,SAAS,CAAC,CAAC,OAAO,GACnG,OAAO;CAGT,IAAI,KAAK,QAAQ,SAAS,MAAM,IAAI;EAClC,MAAM,gBAAgB,GAAG,UAAU;EACnC,IAAI,OAAG,WAAW,aAAa,KAAK,OAAG,SAAS,aAAa,CAAC,CAAC,OAAO,GACpE,OAAO;CAEX;CAEA,MAAM,qBAAqB,KAAK,KAAK,WAAW,eAAe;CAC/D,IAAI,OAAG,WAAW,kBAAkB,KAAK,OAAG,SAAS,kBAAkB,CAAC,CAAC,OAAO,GAC9E,OAAO;CAGT,OAAO;AACT;AAEA,SAAS,eAAe,WAAmB,WAA2B;CACpE,IAAI,UAAU,WAAW,GAAG,KAAK,KAAK,WAAW,SAAS,GAAG;EAC3D,MAAM,WAAW,oBAAoB,KAAK,QAAQ,WAAW,SAAS,CAAC;EACvE,IAAI,UACF,OAAO;CAEX,OAAO;EACL,MAAM,eAAe,cAAc,KAAK,KAAK,WAAW,eAAe,CAAC;EACxE,IAAI;GACF,MAAM,WAAW,aAAa,QAAQ,SAAS;GAC/C,IAAI,KAAK,QAAQ,QAAQ,MAAM,SAC7B,OAAO;EAEX,SAAS,MAAM,CAEf;EAEA,IAAI;GACF,OAAO,aAAa,QAAQ,GAAG,UAAU,eAAe;EAC1D,SAAS,MAAM;GACb,MAAM,WAAW,oBAAoB,KAAK,QAAQ,WAAW,SAAS,CAAC;GACvE,IAAI,UACF,OAAO;EAEX;CACF;CAEA,MAAM,IAAI,MAAM,sDAAsD,UAAU,SAAS,WAAW;AACtG;AAEA,SAAS,eAAe,OAA2C;CACjE,IAAI,CAAC,SAAS,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,GAC5D;CAGF,MAAM,aAA4B,CAAC;CACnC,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,KAAK,GAC7C,IAAI,MAAM,QAAQ,KAAK,KAAK,MAAM,OAAO,UAAU,OAAO,UAAU,QAAQ,GAC1E,WAAW,OAAO;CAItB,OAAO,OAAO,KAAK,UAAU,CAAC,CAAC,SAAS,IAAI,aAAa,KAAA;AAC3D;AAEA,SAAS,iBAAiB,YAAoB,uBAAO,IAAI,IAAY,GAA6D;CAChI,MAAM,iBAAiB,KAAK,QAAQ,UAAU;CAC9C,IAAI,KAAK,IAAI,cAAc,GACzB,MAAM,IAAI,MAAM,wDAAwD,gBAAgB;CAE1F,KAAK,IAAI,cAAc;CAEvB,MAAM,YAAY,KAAK,QAAQ,cAAc;CAC7C,MAAM,MAAM,WAAW,cAAc;CACrC,MAAM,iBAAiB,MAAM,QAAQ,IAAI,OAAO,IAC5C,IAAI,UACJ,OAAO,IAAI,YAAY,WACrB,CAAC,IAAI,OAAO,IACZ,CAAC;CAEP,IAAI,YAAwD,EAC1D,SAAS,UACX;CAEA,KAAK,MAAM,SAAS,gBAClB,YAAY,iBAAiB,eAAe,OAAO,SAAS,GAAG,IAAI;CAGrE,MAAM,kBAAkB,IAAI,mBAAmB,CAAC;CAChD,MAAM,QAAQ,eAAe,gBAAgB,KAAK;CAClD,MAAM,SAAS;EACb,MAAM;EACN,SAAS,OAAO,gBAAgB,YAAY,WACxC,KAAK,QAAQ,WAAW,gBAAgB,OAAO,IAC/C,QACE,YACA,UAAU;EAChB,OAAO,SAAS,UAAU;CAC5B;CAEA,KAAK,OAAO,cAAc;CAC1B,OAAO;AACT;AAEA,SAAS,eAAyE;CAChF,MAAM,aAAa,aAAa,QAAQ,IAAI,CAAC;CAC7C,IAAI,CAAC,YACH,MAAM,IAAI,MAAM,uDAAuD;CAGzE,OAAO,iBAAiB,UAAU;AACpC;AAIA,SAAS,aAAa,UAAsF;CAC1G,MAAM,QAAQ,UAAU;CACxB,IAAI,CAAC,OAAO,OAAO,CAAC;CAEpB,MAAM,UAAU,SAAS,WAAW,KAAK,QAAQ,SAAS,IAAI;CAC9D,MAAM,QAA0B,CAAC;CAEjC,KAAK,MAAM,CAAC,KAAK,YAAY,OAAO,QAAQ,KAAK,GAAG;EAClD,IAAI,CAAC,MAAM,QAAQ,OAAO,GAAG;EAE7B,KAAK,MAAM,UAAU,SAAS;GAC5B,IAAI,gBAAgB,KAAK,MAAM,GAAG;GAElC,IAAI,IAAI,SAAS,GAAG,KAAK,OAAO,SAAS,GAAG,GAAG;IAC7C,MAAM,kBAAkB,OAAO,SAAS,GAAG,IAAI,SAAS;IACxD,MAAM,OAAO,IAAI,OACf,IAAI,YAAY,GAAG,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,KAAK,eAAe,EAAE,EAC1D;IACA,IAAI,aAAa;IACjB,MAAM,iBAAiB,OAAO,QAAQ,aAAa,IAAI,EAAE,YAAY;IACrE,MAAM,cAAc,KAAK,QAAQ,SAAS,cAAc;IACxD,MAAM,YAAY,YAAY,QAAQ,WAAW,EAAE;IACnD,IACE,UAAU,SAAS,GAAG,KAAK,IAAI,cAAc,KAAK,KAAK,KACvD,CAAC,OAAG,WAAW,SAAS,GAExB;IAEF,MAAM,KAAK;KAAE;KAAM;IAAY,CAAC;IAChC;GACF;GAEA,MAAM,OAAO,IAAI,QAAQ,OAAO,EAAE;GAClC,MAAM,cAAc,OAAO,QAAQ,OAAO,EAAE;GAC5C,MAAM,cAAc,KAAK,QAAQ,SAAS,WAAW;GACrD,IACE,YAAY,SAAS,GAAG,KAAK,IAAI,cAAc,KAAK,KAAK,KACzD,CAAC,OAAG,WAAW,WAAW,GAE1B;GAEF,MAAM,KAAK;IAAE;IAAM;GAAY,CAAC;EAClC;CACF;CAEA,OAAO;AACT;AAGA,IAAM,QAAQ,aADG,aACU,CAAQ;AAEnC,IAAA,wBAAe,aAAa;CAC1B,MAAM,EACJ,SAAS,CAAC,iCAAiC,EAC7C;CACA,SAAS,MAAM,SAAS,IAAI,EAAE,MAAM,IAAI,KAAA;AAC1C,CAAC"}
|