test: add focused seams for faster isolated tests

This commit is contained in:
Peter Steinberger
2026-05-06 00:52:21 +01:00
parent 46c99cff0b
commit e428a2dfe2
9 changed files with 95 additions and 54 deletions

View File

@@ -12,11 +12,16 @@ const PROVIDER_RUNTIME_CANDIDATES = [
] as const;
let providerRuntimeModule: ProviderRuntimeModule | undefined;
let providerRuntimeLoadAttempted = false;
function loadProviderRuntime(): ProviderRuntimeModule | null {
if (providerRuntimeModule) {
return providerRuntimeModule;
}
if (providerRuntimeLoadAttempted) {
return null;
}
providerRuntimeLoadAttempted = true;
for (const candidate of PROVIDER_RUNTIME_CANDIDATES) {
try {
providerRuntimeModule = require(candidate) as ProviderRuntimeModule;

View File

@@ -14,7 +14,7 @@ process.env.FORCE_COLOR = "0";
mockSessionsConfig();
import { sessionsCommand } from "./sessions.js";
import { sessionsCommand, __testing } from "./sessions.js";
describe("sessionsCommand", () => {
beforeEach(() => {
@@ -226,31 +226,8 @@ describe("sessionsCommand", () => {
expect(payload.sessions?.map((row) => row.key)).toEqual(["recent"]);
});
it("limits JSON output to the newest 100 sessions by default", async () => {
const entries: Record<string, { sessionId: string; updatedAt: number; model: string }> = {};
for (let i = 0; i < 105; i += 1) {
entries[`session-${String(i).padStart(3, "0")}`] = {
sessionId: `session-${i}`,
updatedAt: Date.now() - i * 60_000,
model: "pi:opus",
};
}
const store = writeStore(entries, "sessions-default-limit");
const payload = await runSessionsJson<{
count?: number;
totalCount?: number;
limitApplied?: number | null;
hasMore?: boolean;
sessions?: Array<{ key: string }>;
}>(sessionsCommand, store);
expect(payload.count).toBe(100);
expect(payload.totalCount).toBe(105);
expect(payload.limitApplied).toBe(100);
expect(payload.hasMore).toBe(true);
expect(payload.sessions?.at(0)?.key).toBe("session-000");
expect(payload.sessions?.some((row) => row.key === "session-104")).toBe(false);
it("uses a default JSON output limit of 100 sessions", () => {
expect(__testing.parseSessionsLimit(undefined)).toBe(100);
});
it("honors explicit JSON output limits", async () => {

View File

@@ -415,3 +415,7 @@ export async function sessionsCommand(
runtime.log(line.trimEnd());
}
}
export const __testing = {
parseSessionsLimit,
} as const;

View File

@@ -20,6 +20,7 @@ import {
getResolvedLoggerSettings,
isFileLogLevelEnabled,
resetLogger,
setLoggerConfigLoaderForTests,
setLoggerOverride,
toPinoLikeLogger,
} from "./logging/logger.js";
@@ -50,6 +51,7 @@ export {
getResolvedLoggerSettings,
isFileLogLevelEnabled,
resetLogger,
setLoggerConfigLoaderForTests,
setLoggerOverride,
toPinoLikeLogger,
createSubsystemLogger,

View File

@@ -1,15 +1,5 @@
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
const { readLoggingConfigMock, shouldSkipMutatingLoggingConfigReadMock } = vi.hoisted(() => ({
readLoggingConfigMock: vi.fn<() => unknown>(() => undefined),
shouldSkipMutatingLoggingConfigReadMock: vi.fn(() => false),
}));
vi.mock("./config.js", () => ({
readLoggingConfig: readLoggingConfigMock,
shouldSkipMutatingLoggingConfigRead: shouldSkipMutatingLoggingConfigReadMock,
}));
let originalTestFileLog: string | undefined;
let originalOpenClawLogLevel: string | undefined;
let logging: typeof import("../logging.js");
@@ -23,10 +13,6 @@ beforeEach(() => {
originalOpenClawLogLevel = process.env.OPENCLAW_LOG_LEVEL;
delete process.env.OPENCLAW_TEST_FILE_LOG;
delete process.env.OPENCLAW_LOG_LEVEL;
readLoggingConfigMock.mockReset();
readLoggingConfigMock.mockReturnValue(undefined);
shouldSkipMutatingLoggingConfigReadMock.mockReset();
shouldSkipMutatingLoggingConfigReadMock.mockReturnValue(false);
logging.resetLogger();
logging.setLoggerOverride(null);
});
@@ -44,23 +30,28 @@ afterEach(() => {
}
logging.resetLogger();
logging.setLoggerOverride(null);
logging.setLoggerConfigLoaderForTests();
vi.restoreAllMocks();
});
describe("getResolvedLoggerSettings", () => {
it("uses a silent fast path in default Vitest mode without config reads", () => {
const readLoggingConfig = vi.fn(() => undefined);
logging.setLoggerConfigLoaderForTests(readLoggingConfig);
const settings = logging.getResolvedLoggerSettings();
expect(settings.level).toBe("silent");
expect(readLoggingConfigMock).not.toHaveBeenCalled();
expect(readLoggingConfig).not.toHaveBeenCalled();
});
it("reads logging config when test file logging is explicitly enabled", () => {
process.env.OPENCLAW_TEST_FILE_LOG = "1";
readLoggingConfigMock.mockReturnValue({
logging.setLoggerConfigLoaderForTests(() => ({
level: "debug",
file: "/tmp/openclaw-configured.log",
maxFileBytes: 2048,
});
}));
const settings = logging.getResolvedLoggerSettings();
@@ -71,9 +62,9 @@ describe("getResolvedLoggerSettings", () => {
});
});
it("uses defaults when config schema skips logging config reads", () => {
it("uses defaults when no logging config is available", () => {
process.env.OPENCLAW_TEST_FILE_LOG = "1";
shouldSkipMutatingLoggingConfigReadMock.mockReturnValue(true);
logging.setLoggerConfigLoaderForTests(() => undefined);
const settings = logging.getResolvedLoggerSettings();

View File

@@ -70,6 +70,7 @@ type ResolvedSettings = {
};
export type LoggerResolvedSettings = ResolvedSettings;
type TsLogRecord = Record<string, unknown>;
type LoggerConfigLoader = () => OpenClawConfig["logging"] | undefined;
type DiagnosticLogCode = {
line?: number;
@@ -78,6 +79,15 @@ type DiagnosticLogCode = {
const MAX_DIAGNOSTIC_LOG_BINDINGS_JSON_CHARS = 8 * 1024;
const MAX_DIAGNOSTIC_LOG_MESSAGE_CHARS = 4 * 1024;
const loadLoggerConfigDefault: LoggerConfigLoader = () => readLoggingConfig();
let loadLoggerConfig: LoggerConfigLoader = loadLoggerConfigDefault;
export function setLoggerConfigLoaderForTests(loader?: LoggerConfigLoader): void {
loadLoggerConfig = loader ?? loadLoggerConfigDefault;
loggingState.cachedLogger = null;
loggingState.cachedSettings = null;
}
const MAX_DIAGNOSTIC_LOG_ATTRIBUTE_COUNT = 32;
const MAX_DIAGNOSTIC_LOG_ATTRIBUTE_VALUE_CHARS = 2 * 1024;
const MAX_DIAGNOSTIC_LOG_NAME_CHARS = 120;
@@ -473,7 +483,7 @@ function resolveSettings(): ResolvedSettings {
}
const cfg: OpenClawConfig["logging"] | undefined =
(loggingState.overrideSettings as LoggerSettings | null) ?? readLoggingConfig();
(loggingState.overrideSettings as LoggerSettings | null) ?? loadLoggerConfig();
const defaultLevel =
process.env.VITEST === "true" && process.env.OPENCLAW_TEST_FILE_LOG !== "1" ? "silent" : "info";
const fromConfig = normalizeLogLevel(cfg?.level, defaultLevel);
@@ -670,6 +680,7 @@ export function resetLogger() {
loggingState.cachedSettings = null;
loggingState.cachedConsoleSettings = null;
loggingState.overrideSettings = null;
loadLoggerConfig = loadLoggerConfigDefault;
}
export const __test__ = {

View File

@@ -87,7 +87,11 @@ export {
} from "../agents/pi-embedded-subscribe.tools.js";
export { normalizeUsage } from "../agents/usage.js";
export { resolveOpenClawAgentDir } from "./agent-dir-compat.js";
export { resolveAgentDir, resolveSessionAgentIds } from "../agents/agent-scope.js";
export {
resolveAgentDir,
resolveDefaultAgentDir,
resolveSessionAgentIds,
} from "../agents/agent-scope.js";
export { resolveModelAuthMode } from "../agents/model-auth.js";
export { supportsModelTools } from "../agents/model-tool-support.js";
export { resolveAttemptSpawnWorkspaceDir } from "../agents/pi-embedded-runner/run/attempt.thread-helpers.js";