mirror of
https://github.com/moltbot/moltbot.git
synced 2026-04-23 14:45:46 +00:00
refactor: route direct extension test targets
This commit is contained in:
@@ -1,5 +1,77 @@
|
||||
export function parseTestProjectsArgs(args) {
|
||||
import fs from "node:fs";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { isChannelSurfaceTestFile } from "../vitest.channel-paths.mjs";
|
||||
|
||||
const DEFAULT_VITEST_CONFIG = "vitest.config.ts";
|
||||
const CHANNEL_VITEST_CONFIG = "vitest.channels.config.ts";
|
||||
const EXTENSIONS_VITEST_CONFIG = "vitest.extensions.config.ts";
|
||||
const INCLUDE_FILE_ENV_KEY = "OPENCLAW_VITEST_INCLUDE_FILE";
|
||||
|
||||
function normalizePathPattern(value) {
|
||||
return value.replaceAll("\\", "/");
|
||||
}
|
||||
|
||||
function isExistingPathTarget(arg, cwd) {
|
||||
return fs.existsSync(path.resolve(cwd, arg));
|
||||
}
|
||||
|
||||
function isGlobTarget(arg) {
|
||||
return /[*?[\]{}]/u.test(arg);
|
||||
}
|
||||
|
||||
function isFileLikeTarget(arg) {
|
||||
return /\.(?:test|spec)\.[cm]?[jt]sx?$/u.test(arg);
|
||||
}
|
||||
|
||||
function isPathLikeTargetArg(arg, cwd) {
|
||||
if (!arg || arg === "--" || arg.startsWith("-")) {
|
||||
return false;
|
||||
}
|
||||
return isExistingPathTarget(arg, cwd) || isGlobTarget(arg) || isFileLikeTarget(arg);
|
||||
}
|
||||
|
||||
function toRepoRelativeTarget(arg, cwd) {
|
||||
if (isGlobTarget(arg)) {
|
||||
return normalizePathPattern(arg.replace(/^\.\//u, ""));
|
||||
}
|
||||
const absolute = path.resolve(cwd, arg);
|
||||
return normalizePathPattern(path.relative(cwd, absolute));
|
||||
}
|
||||
|
||||
function toScopedIncludePattern(arg, cwd) {
|
||||
const relative = toRepoRelativeTarget(arg, cwd);
|
||||
if (isGlobTarget(relative) || isFileLikeTarget(relative)) {
|
||||
return relative;
|
||||
}
|
||||
return `${relative.replace(/\/+$/u, "")}/**/*.test.ts`;
|
||||
}
|
||||
|
||||
function classifyTarget(arg, cwd) {
|
||||
const relative = toRepoRelativeTarget(arg, cwd);
|
||||
if (relative.startsWith("extensions/")) {
|
||||
return isChannelSurfaceTestFile(relative) ? "channel" : "extension";
|
||||
}
|
||||
if (isChannelSurfaceTestFile(relative)) {
|
||||
return "channel";
|
||||
}
|
||||
return "default";
|
||||
}
|
||||
|
||||
function createVitestArgs(params) {
|
||||
return [
|
||||
"exec",
|
||||
"vitest",
|
||||
...(params.watchMode ? [] : ["run"]),
|
||||
"--config",
|
||||
params.config,
|
||||
...params.forwardedArgs,
|
||||
];
|
||||
}
|
||||
|
||||
export function parseTestProjectsArgs(args, cwd = process.cwd()) {
|
||||
const forwardedArgs = [];
|
||||
const targetArgs = [];
|
||||
let watchMode = false;
|
||||
|
||||
for (const arg of args) {
|
||||
@@ -10,20 +82,109 @@ export function parseTestProjectsArgs(args) {
|
||||
watchMode = true;
|
||||
continue;
|
||||
}
|
||||
if (isPathLikeTargetArg(arg, cwd)) {
|
||||
targetArgs.push(arg);
|
||||
}
|
||||
forwardedArgs.push(arg);
|
||||
}
|
||||
|
||||
return { forwardedArgs, watchMode };
|
||||
return { forwardedArgs, targetArgs, watchMode };
|
||||
}
|
||||
|
||||
export function buildVitestArgs(args) {
|
||||
const { forwardedArgs, watchMode } = parseTestProjectsArgs(args);
|
||||
return [
|
||||
"exec",
|
||||
"vitest",
|
||||
...(watchMode ? [] : ["run"]),
|
||||
"--config",
|
||||
"vitest.config.ts",
|
||||
...forwardedArgs,
|
||||
];
|
||||
export function buildVitestRunPlans(args, cwd = process.cwd()) {
|
||||
const { forwardedArgs, targetArgs, watchMode } = parseTestProjectsArgs(args, cwd);
|
||||
if (targetArgs.length === 0) {
|
||||
return [
|
||||
{
|
||||
config: DEFAULT_VITEST_CONFIG,
|
||||
forwardedArgs,
|
||||
includePatterns: null,
|
||||
watchMode,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
const groupedTargets = new Map();
|
||||
for (const targetArg of targetArgs) {
|
||||
const kind = classifyTarget(targetArg, cwd);
|
||||
const current = groupedTargets.get(kind) ?? [];
|
||||
current.push(targetArg);
|
||||
groupedTargets.set(kind, current);
|
||||
}
|
||||
|
||||
if (watchMode && groupedTargets.size > 1) {
|
||||
throw new Error(
|
||||
"watch mode with mixed test suites is not supported; target one suite at a time or use a dedicated suite command",
|
||||
);
|
||||
}
|
||||
|
||||
const nonTargetArgs = forwardedArgs.filter((arg) => !targetArgs.includes(arg));
|
||||
const orderedKinds = ["default", "channel", "extension"];
|
||||
const plans = [];
|
||||
for (const kind of orderedKinds) {
|
||||
const grouped = groupedTargets.get(kind);
|
||||
if (!grouped || grouped.length === 0) {
|
||||
continue;
|
||||
}
|
||||
const config =
|
||||
kind === "channel"
|
||||
? CHANNEL_VITEST_CONFIG
|
||||
: kind === "extension"
|
||||
? EXTENSIONS_VITEST_CONFIG
|
||||
: DEFAULT_VITEST_CONFIG;
|
||||
const includePatterns =
|
||||
kind === "default"
|
||||
? null
|
||||
: grouped.map((targetArg) => toScopedIncludePattern(targetArg, cwd));
|
||||
const scopedTargetArgs = kind === "default" ? grouped : [];
|
||||
plans.push({
|
||||
config,
|
||||
forwardedArgs: [...nonTargetArgs, ...scopedTargetArgs],
|
||||
includePatterns,
|
||||
watchMode,
|
||||
});
|
||||
}
|
||||
return plans;
|
||||
}
|
||||
|
||||
export function createVitestRunSpecs(args, params = {}) {
|
||||
const cwd = params.cwd ?? process.cwd();
|
||||
const plans = buildVitestRunPlans(args, cwd);
|
||||
return plans.map((plan, index) => {
|
||||
const includeFilePath = plan.includePatterns
|
||||
? path.join(
|
||||
params.tempDir ?? os.tmpdir(),
|
||||
`openclaw-vitest-include-${process.pid}-${Date.now()}-${index}.json`,
|
||||
)
|
||||
: null;
|
||||
return {
|
||||
config: plan.config,
|
||||
env: includeFilePath
|
||||
? {
|
||||
...(params.baseEnv ?? process.env),
|
||||
[INCLUDE_FILE_ENV_KEY]: includeFilePath,
|
||||
}
|
||||
: (params.baseEnv ?? process.env),
|
||||
includeFilePath,
|
||||
includePatterns: plan.includePatterns,
|
||||
pnpmArgs: createVitestArgs(plan),
|
||||
watchMode: plan.watchMode,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
export function writeVitestIncludeFile(filePath, includePatterns) {
|
||||
fs.writeFileSync(filePath, `${JSON.stringify(includePatterns, null, 2)}\n`);
|
||||
}
|
||||
|
||||
export function buildVitestArgs(args, cwd = process.cwd()) {
|
||||
const [plan] = buildVitestRunPlans(args, cwd);
|
||||
if (!plan) {
|
||||
return createVitestArgs({
|
||||
config: DEFAULT_VITEST_CONFIG,
|
||||
forwardedArgs: [],
|
||||
watchMode: false,
|
||||
});
|
||||
}
|
||||
return createVitestArgs(plan);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user