fix(test): extend e2e vitest watchdog

This commit is contained in:
Vincent Koc
2026-05-31 11:32:59 +02:00
parent 425a4ab2f2
commit a753e6bc86
2 changed files with 77 additions and 2 deletions

View File

@@ -19,11 +19,16 @@ const ANSI_CSI_SUFFIX_RE = /^[0-?]*[ -/]*[@-~]/u;
const SUPPRESSED_VITEST_STDERR_PATTERNS = ["[PLUGIN_TIMINGS]"];
export const DEFAULT_VITEST_NO_OUTPUT_TIMEOUT_MS = 120_000;
export const DEFAULT_VITEST_NO_OUTPUT_HEARTBEAT_MS = 60_000;
export const DEFAULT_LONG_RUNNING_VITEST_NO_OUTPUT_TIMEOUT_MS = 300_000;
const VITEST_NO_OUTPUT_TIMEOUT_ENV_KEY = "OPENCLAW_VITEST_NO_OUTPUT_TIMEOUT_MS";
const VITEST_NO_OUTPUT_HEARTBEAT_ENV_KEY = "OPENCLAW_VITEST_NO_OUTPUT_HEARTBEAT_MS";
const UI_VITEST_CONFIG = "test/vitest/vitest.ui.config.ts";
const UNIT_UI_VITEST_CONFIG = "test/vitest/vitest.unit-ui.config.ts";
const TOOLING_VITEST_CONFIG = "test/vitest/vitest.tooling.config.ts";
const LONG_RUNNING_VITEST_CONFIGS = new Set([
"test/vitest/vitest.e2e.config.ts",
"test/vitest/vitest.ui-e2e.config.ts",
]);
const TOOLING_EXCLUDED_TESTS = new Set([
...boundaryTestFiles,
"test/scripts/openclaw-e2e-instance.test.ts",
@@ -230,15 +235,16 @@ export function resolveRunVitestSpawnEnv(env = process.env, argv = []) {
if (explicitMode !== "run" && !isTruthyEnvValue(env.CI)) {
return env;
}
const defaultTimeoutMs = resolveDefaultVitestNoOutputTimeoutMs(argv);
const hasTimeout = Object.hasOwn(env, VITEST_NO_OUTPUT_TIMEOUT_ENV_KEY);
const timeoutMs = hasTimeout
? parsePositiveInt(env[VITEST_NO_OUTPUT_TIMEOUT_ENV_KEY])
: DEFAULT_VITEST_NO_OUTPUT_TIMEOUT_MS;
: defaultTimeoutMs;
const hasHeartbeat = Object.hasOwn(env, VITEST_NO_OUTPUT_HEARTBEAT_ENV_KEY);
return {
...env,
...(!hasTimeout
? { [VITEST_NO_OUTPUT_TIMEOUT_ENV_KEY]: String(DEFAULT_VITEST_NO_OUTPUT_TIMEOUT_MS) }
? { [VITEST_NO_OUTPUT_TIMEOUT_ENV_KEY]: String(defaultTimeoutMs) }
: {}),
...(!hasHeartbeat && timeoutMs !== null && DEFAULT_VITEST_NO_OUTPUT_HEARTBEAT_MS < timeoutMs
? { [VITEST_NO_OUTPUT_HEARTBEAT_ENV_KEY]: String(DEFAULT_VITEST_NO_OUTPUT_HEARTBEAT_MS) }
@@ -246,6 +252,40 @@ export function resolveRunVitestSpawnEnv(env = process.env, argv = []) {
};
}
export function resolveDefaultVitestNoOutputTimeoutMs(argv = []) {
const config = resolveVitestConfigArg(argv);
if (config !== null && isLongRunningVitestConfig(config)) {
return DEFAULT_LONG_RUNNING_VITEST_NO_OUTPUT_TIMEOUT_MS;
}
return DEFAULT_VITEST_NO_OUTPUT_TIMEOUT_MS;
}
function resolveVitestConfigArg(argv) {
for (let index = 0; index < argv.length; index += 1) {
const arg = argv[index];
if (arg === "--") {
return null;
}
if (arg === "--config" || arg === "-c") {
return argv[index + 1] ?? null;
}
if (arg.startsWith("--config=")) {
return arg.slice("--config=".length);
}
}
return null;
}
function isLongRunningVitestConfig(config) {
const normalized = path.normalize(config).replaceAll(path.sep, "/").replace(/^\.\//u, "");
for (const candidate of LONG_RUNNING_VITEST_CONFIGS) {
if (normalized === candidate || normalized.endsWith(`/${candidate}`)) {
return true;
}
}
return false;
}
export function resolveVitestSpawnParams(env = process.env, platform = process.platform) {
return {
env: resolveVitestSpawnEnv(env),

View File

@@ -1,7 +1,9 @@
import { EventEmitter } from "node:events";
import { describe, expect, it, vi } from "vitest";
import {
DEFAULT_LONG_RUNNING_VITEST_NO_OUTPUT_TIMEOUT_MS,
installVitestNoOutputWatchdog,
resolveDefaultVitestNoOutputTimeoutMs,
resolveDirectNodeVitestArgs,
resolveExplicitTestFileNoPassArgs,
resolveImplicitVitestArgs,
@@ -343,6 +345,39 @@ describe("scripts/run-vitest", () => {
});
});
it("uses a longer default stall watchdog for broad e2e configs", () => {
const timeout = String(DEFAULT_LONG_RUNNING_VITEST_NO_OUTPUT_TIMEOUT_MS);
expect(
resolveRunVitestSpawnEnv({ PATH: "/usr/bin" }, [
"run",
"--config",
"test/vitest/vitest.e2e.config.ts",
]),
).toEqual({
PATH: "/usr/bin",
OPENCLAW_VITEST_NO_OUTPUT_HEARTBEAT_MS: "60000",
OPENCLAW_VITEST_NO_OUTPUT_TIMEOUT_MS: timeout,
});
expect(
resolveRunVitestSpawnEnv({ PATH: "/usr/bin" }, [
"run",
"--config=./test/vitest/vitest.ui-e2e.config.ts",
]),
).toEqual({
PATH: "/usr/bin",
OPENCLAW_VITEST_NO_OUTPUT_HEARTBEAT_MS: "60000",
OPENCLAW_VITEST_NO_OUTPUT_TIMEOUT_MS: timeout,
});
expect(
resolveDefaultVitestNoOutputTimeoutMs([
"run",
"-c",
"/repo/test/vitest/vitest.e2e.config.ts",
]),
).toBe(DEFAULT_LONG_RUNNING_VITEST_NO_OUTPUT_TIMEOUT_MS);
});
it("does not default implicit interactive runs to the stall watchdog", () => {
expect(resolveRunVitestSpawnEnv({ PATH: "/usr/bin" }, ["src/foo.test.ts"])).toEqual({
PATH: "/usr/bin",