mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-13 06:03:39 -06:00
chore: speed up CLI test fixtures (#118547)
* test(cli): remove redundant setup waits * test(cli): keep MCP runtime exports isolated --------- Co-authored-by: Peter Steinberger <steipete@mac-studio-sf2.local>
This commit is contained in:
committed by
GitHub
parent
938980d51b
commit
6ce00caaf2
@@ -3,11 +3,31 @@ import fs from "node:fs";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import JSON5 from "json5";
|
||||
import { beforeAll, describe, expect, it } from "vitest";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { clearConfigCache, clearRuntimeConfigSnapshot } from "../config/config.js";
|
||||
import { captureEnv, deleteTestEnvValue, setTestEnvValue } from "../test-utils/env.js";
|
||||
import { runConfigSet } from "./config-cli.js";
|
||||
|
||||
// Config mutation owns these assertions; plugin discovery suites own registry breadth.
|
||||
// Keep the two real schemas this suite exercises, but build their metadata only once.
|
||||
vi.mock("../plugins/plugin-metadata-snapshot.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../plugins/plugin-metadata-snapshot.js")>();
|
||||
let snapshot: ReturnType<typeof actual.loadPluginMetadataSnapshot> | undefined;
|
||||
return {
|
||||
...actual,
|
||||
resolvePluginMetadataSnapshot: (
|
||||
params: Parameters<typeof actual.resolvePluginMetadataSnapshot>[0],
|
||||
) => {
|
||||
snapshot ??= actual.loadPluginMetadataSnapshot({
|
||||
...params,
|
||||
pluginIds: ["discord", "openclaw-mem0"],
|
||||
pluginIdScope: undefined,
|
||||
});
|
||||
return snapshot;
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
function createTestRuntime() {
|
||||
const logs: string[] = [];
|
||||
const errors: string[] = [];
|
||||
@@ -113,30 +133,6 @@ async function withExecDryRunConfigHarness(
|
||||
}
|
||||
|
||||
describe("config cli integration", () => {
|
||||
beforeAll(async () => {
|
||||
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-config-cli-warmup-"));
|
||||
const configPath = path.join(tempDir, "openclaw.json");
|
||||
const envSnapshot = captureEnv(["OPENCLAW_CONFIG_PATH", "OPENCLAW_TEST_FAST"]);
|
||||
try {
|
||||
fs.writeFileSync(configPath, `${JSON.stringify({ gateway: { port: 18789 } }, null, 2)}\n`);
|
||||
setTestEnvValue("OPENCLAW_TEST_FAST", "1");
|
||||
setTestEnvValue("OPENCLAW_CONFIG_PATH", configPath);
|
||||
clearConfigCache();
|
||||
clearRuntimeConfigSnapshot();
|
||||
await runConfigSet({
|
||||
path: "gateway.port",
|
||||
value: "18790",
|
||||
cliOptions: {},
|
||||
runtime: createTestRuntime().runtime,
|
||||
});
|
||||
} finally {
|
||||
envSnapshot.restore();
|
||||
clearConfigCache();
|
||||
clearRuntimeConfigSnapshot();
|
||||
fs.rmSync(tempDir, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
it("accepts plugin hook conversation-access policy via config set", async () => {
|
||||
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-config-cli-plugin-hooks-"));
|
||||
const configPath = path.join(tempDir, "openclaw.json");
|
||||
|
||||
+59
-34
@@ -9,6 +9,9 @@ import { withTempHome } from "../config/home-env.test-harness.js";
|
||||
import { createDeferred } from "../shared/deferred.js";
|
||||
import { registerMcpCli } from "./mcp-cli.js";
|
||||
|
||||
type CreateSessionMcpRuntime =
|
||||
typeof import("../agents/agent-bundle-mcp-runtime.js").createSessionMcpRuntime;
|
||||
|
||||
const mocks = vi.hoisted(() => {
|
||||
const runtime = {
|
||||
log: vi.fn(),
|
||||
@@ -26,6 +29,7 @@ const mocks = vi.hoisted(() => {
|
||||
clearMcpOAuthCredentials: vi.fn(),
|
||||
readMcpOAuthCredentialsStatus: vi.fn(),
|
||||
runMcpOAuthLogin: vi.fn(),
|
||||
createSessionMcpRuntimeOverride: undefined as CreateSessionMcpRuntime | undefined,
|
||||
};
|
||||
});
|
||||
|
||||
@@ -51,6 +55,15 @@ vi.mock("../agents/mcp-oauth.js", () => ({
|
||||
runMcpOAuthLogin: mocks.runMcpOAuthLogin,
|
||||
}));
|
||||
|
||||
vi.mock("../agents/agent-bundle-mcp-runtime.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../agents/agent-bundle-mcp-runtime.js")>();
|
||||
return {
|
||||
...actual,
|
||||
createSessionMcpRuntime: (params: Parameters<CreateSessionMcpRuntime>[0]) =>
|
||||
mocks.createSessionMcpRuntimeOverride?.(params) ?? actual.createSessionMcpRuntime(params),
|
||||
};
|
||||
});
|
||||
|
||||
const tempDirs: string[] = [];
|
||||
|
||||
async function createWorkspace(): Promise<string> {
|
||||
@@ -145,6 +158,7 @@ describe("mcp cli", () => {
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
mocks.createSessionMcpRuntimeOverride = undefined;
|
||||
readMcpOAuthCredentialsStatus.mockResolvedValue({
|
||||
hasTokens: false,
|
||||
requiresAuthorization: false,
|
||||
@@ -336,42 +350,53 @@ describe("mcp cli", () => {
|
||||
},
|
||||
);
|
||||
|
||||
it(
|
||||
"bounds initialize with a five-second probe timeout when no flag is supplied",
|
||||
{ timeout: 8_000 },
|
||||
async () => {
|
||||
await withTempHome("openclaw-cli-mcp-home-", async (home) => {
|
||||
const workspaceDir = await createWorkspace();
|
||||
const serverPath = path.join(workspaceDir, "probe-server.mjs");
|
||||
const configPath = path.join(home, ".openclaw", "openclaw.json");
|
||||
await writeProbeMcpServer(serverPath);
|
||||
vi.spyOn(process, "cwd").mockReturnValue(workspaceDir);
|
||||
it("passes a five-second default initialize timeout to the probe runtime", async () => {
|
||||
await withTempHome("openclaw-cli-mcp-home-", async (home) => {
|
||||
const workspaceDir = await createWorkspace();
|
||||
const configPath = path.join(home, ".openclaw", "openclaw.json");
|
||||
vi.spyOn(process, "cwd").mockReturnValue(workspaceDir);
|
||||
let probeTimeoutMs: unknown;
|
||||
mocks.createSessionMcpRuntimeOverride = (params) => {
|
||||
probeTimeoutMs = params.cfg?.mcp?.servers?.["hung-default"]?.connectionTimeoutMs;
|
||||
return {
|
||||
sessionId: params.sessionId,
|
||||
workspaceDir: params.workspaceDir,
|
||||
configFingerprint: "cli-probe-test",
|
||||
createdAt: 0,
|
||||
lastUsedAt: 0,
|
||||
getCatalog: async () => ({
|
||||
version: 1,
|
||||
generatedAt: Date.now(),
|
||||
servers: {},
|
||||
tools: [],
|
||||
diagnostics: [
|
||||
{
|
||||
serverName: "hung-default",
|
||||
safeServerName: "hung-default",
|
||||
launchSummary: process.execPath,
|
||||
message:
|
||||
'MCP server "hung-default" timed out: did not complete initialize within 5s',
|
||||
},
|
||||
],
|
||||
}),
|
||||
peekCatalog: () => null,
|
||||
markUsed: () => {},
|
||||
callTool: async () => ({ content: [] }),
|
||||
dispose: async () => {},
|
||||
};
|
||||
};
|
||||
|
||||
const startedAt = performance.now();
|
||||
await expect(
|
||||
runMcpCommand([
|
||||
"mcp",
|
||||
"add",
|
||||
"hung-default",
|
||||
"--command",
|
||||
process.execPath,
|
||||
"--arg",
|
||||
serverPath,
|
||||
"--env",
|
||||
"MCP_MODE=hang-start",
|
||||
]),
|
||||
).rejects.toThrow("__exit__:1");
|
||||
const elapsedMs = performance.now() - startedAt;
|
||||
await expect(
|
||||
runMcpCommand(["mcp", "add", "hung-default", "--command", process.execPath]),
|
||||
).rejects.toThrow("__exit__:1");
|
||||
|
||||
expect(elapsedMs).toBeGreaterThanOrEqual(4_500);
|
||||
expect(elapsedMs).toBeLessThan(6_500);
|
||||
expect(lastErrorLine()).toContain(
|
||||
'MCP server "hung-default" timed out: did not complete initialize within 5s',
|
||||
);
|
||||
await expect(fs.readFile(configPath, "utf8")).rejects.toMatchObject({ code: "ENOENT" });
|
||||
});
|
||||
},
|
||||
);
|
||||
expect(probeTimeoutMs).toBe(5_000);
|
||||
expect(lastErrorLine()).toContain(
|
||||
'MCP server "hung-default" timed out: did not complete initialize within 5s',
|
||||
);
|
||||
await expect(fs.readFile(configPath, "utf8")).rejects.toMatchObject({ code: "ENOENT" });
|
||||
});
|
||||
});
|
||||
|
||||
it("labels listed MCP servers as OpenClaw-managed", async () => {
|
||||
await withTempHome("openclaw-cli-mcp-home-", async () => {
|
||||
|
||||
Reference in New Issue
Block a user