





























@@ -1,14 +1,18 @@
1+import fs from "node:fs";
2+import path from "node:path";
13import { defineConfig } from "vitest/config";
24import { loadPatternListFromEnv, narrowIncludePatternsForCli } from "./vitest.pattern-file.ts";
35import { resolveVitestIsolation } from "./vitest.scoped-config.ts";
46import {
57nonIsolatedRunnerPath,
8+repoRoot,
69resolveRepoRootPath,
710sharedVitestConfig,
811} from "./vitest.shared.config.ts";
912import { getUnitFastTestFiles } from "./vitest.unit-fast-paths.mjs";
1013import {
1114isBundledPluginDependentUnitTestFile,
15+isUnitConfigTestFile,
1216unitTestAdditionalExcludePatterns,
1317unitTestIncludePatterns,
1418} from "./vitest.unit-paths.mjs";
@@ -28,6 +32,58 @@ export function loadExtraExcludePatternsFromEnv(
2832return loadPatternListFromEnv("OPENCLAW_VITEST_EXTRA_EXCLUDE_FILE", env) ?? [];
2933}
303435+const defaultUnitCoverageRoots = ["src", "packages", "test"] as const;
36+37+function toRepoPath(filePath: string): string {
38+return path.relative(repoRoot, filePath).split(path.sep).join("/");
39+}
40+41+function collectTestFiles(dir: string): string[] {
42+if (!fs.existsSync(dir)) {
43+return [];
44+}
45+const files: string[] = [];
46+for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
47+if (entry.name === "node_modules" || entry.name === "dist" || entry.name === "coverage") {
48+continue;
49+}
50+const entryPath = path.join(dir, entry.name);
51+if (entry.isDirectory()) {
52+files.push(...collectTestFiles(entryPath));
53+} else if (entry.isFile() && entry.name.endsWith(".test.ts")) {
54+files.push(toRepoPath(entryPath));
55+}
56+}
57+return files;
58+}
59+60+function resolveSiblingSourceFile(testFile: string): string | null {
61+if (!testFile.endsWith(".test.ts")) {
62+return null;
63+}
64+const sourceFile = testFile.replace(/\.test\.ts$/u, ".ts");
65+return fs.existsSync(resolveRepoRootPath(sourceFile)) ? sourceFile : null;
66+}
67+68+export function resolveDefaultUnitCoverageIncludePatterns(
69+unitFastTestFiles = getUnitFastTestFiles(),
70+): string[] {
71+const fastTestFiles = new Set(unitFastTestFiles);
72+const sourceFiles = new Set<string>();
73+for (const root of defaultUnitCoverageRoots) {
74+for (const testFile of collectTestFiles(resolveRepoRootPath(root))) {
75+if (!isUnitConfigTestFile(testFile) || fastTestFiles.has(testFile)) {
76+continue;
77+}
78+const sourceFile = resolveSiblingSourceFile(testFile);
79+if (sourceFile !== null) {
80+sourceFiles.add(sourceFile);
81+}
82+}
83+}
84+return [...sourceFiles].toSorted((left, right) => left.localeCompare(right));
85+}
86+3187export function createUnitVitestConfigWithOptions(
3288env: Record<string, string | undefined> = process.env,
3389options: {
@@ -40,8 +96,15 @@ export function createUnitVitestConfigWithOptions(
4096) {
4197const isolate = resolveVitestIsolation(env);
4298const unitFastTestFiles = getUnitFastTestFiles();
99+const envIncludePatterns = loadIncludePatternsFromEnv(env);
43100const defaultIncludePatterns = options.includePatterns ?? unitTestIncludePatterns;
44101const cliIncludePatterns = narrowIncludePatternsForCli(defaultIncludePatterns, options.argv);
102+const coverageIncludePatterns =
103+options.includePatterns === undefined &&
104+envIncludePatterns === null &&
105+cliIncludePatterns === null
106+ ? resolveDefaultUnitCoverageIncludePatterns(unitFastTestFiles)
107+ : null;
45108const protectedIncludeFiles = new Set(
46109defaultIncludePatterns.filter((pattern) => isBundledPluginDependentUnitTestFile(pattern)),
47110);
@@ -66,7 +129,7 @@ export function createUnitVitestConfigWithOptions(
66129),
67130),
68131],
69-include: loadIncludePatternsFromEnv(env) ?? cliIncludePatterns ?? defaultIncludePatterns,
132+include: envIncludePatterns ?? cliIncludePatterns ?? defaultIncludePatterns,
70133exclude: [
71134 ...new Set([
72135 ...exclude,
@@ -78,6 +141,9 @@ export function createUnitVitestConfigWithOptions(
78141],
79142coverage: {
80143 ...sharedTest.coverage,
144+ ...(coverageIncludePatterns !== null && coverageIncludePatterns.length > 0
145+ ? { include: coverageIncludePatterns }
146+ : {}),
81147exclude: [
82148 ...new Set([
83149 ...(sharedTest.coverage?.exclude ?? []),
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。