ci: stabilize vitest runs
This commit is contained in:
@@ -52,7 +52,7 @@ describe("Agent-specific sandbox config", () => {
|
|||||||
|
|
||||||
it(
|
it(
|
||||||
"should use global sandbox config when no agent-specific config exists",
|
"should use global sandbox config when no agent-specific config exists",
|
||||||
{ timeout: 15_000 },
|
{ timeout: 60_000 },
|
||||||
async () => {
|
async () => {
|
||||||
const { resolveSandboxContext } = await import("./sandbox.js");
|
const { resolveSandboxContext } = await import("./sandbox.js");
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
|
|
||||||
describe("sandbox config merges", () => {
|
describe("sandbox config merges", () => {
|
||||||
it("resolves sandbox scope deterministically", { timeout: 15_000 }, async () => {
|
it("resolves sandbox scope deterministically", { timeout: 60_000 }, async () => {
|
||||||
const { resolveSandboxScope } = await import("./sandbox.js");
|
const { resolveSandboxScope } = await import("./sandbox.js");
|
||||||
|
|
||||||
expect(resolveSandboxScope({})).toBe("agent");
|
expect(resolveSandboxScope({})).toBe("agent");
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ afterEach(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe("trigger handling", () => {
|
describe("trigger handling", () => {
|
||||||
it("stages inbound media into the sandbox workspace", { timeout: 15_000 }, async () => {
|
it("stages inbound media into the sandbox workspace", { timeout: 60_000 }, async () => {
|
||||||
await withTempHome(async (home) => {
|
await withTempHome(async (home) => {
|
||||||
const inboundDir = join(home, ".clawdbot", "media", "inbound");
|
const inboundDir = join(home, ".clawdbot", "media", "inbound");
|
||||||
await fs.mkdir(inboundDir, { recursive: true });
|
await fs.mkdir(inboundDir, { recursive: true });
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ vi.mock("../runtime.js", () => ({
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
describe("cron cli", () => {
|
describe("cron cli", () => {
|
||||||
it("trims model and thinking on cron add", { timeout: 30_000 }, async () => {
|
it("trims model and thinking on cron add", { timeout: 60_000 }, async () => {
|
||||||
callGatewayFromCli.mockClear();
|
callGatewayFromCli.mockClear();
|
||||||
|
|
||||||
const { registerCronCli } = await import("./cron-cli.js");
|
const { registerCronCli } = await import("./cron-cli.js");
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ vi.mock("../commands/models.js", async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe("models cli", () => {
|
describe("models cli", () => {
|
||||||
it("registers github-copilot login command", { timeout: 15_000 }, async () => {
|
it("registers github-copilot login command", { timeout: 60_000 }, async () => {
|
||||||
const { Command } = await import("commander");
|
const { Command } = await import("commander");
|
||||||
const { registerModelsCli } = await import("./models-cli.js");
|
const { registerModelsCli } = await import("./models-cli.js");
|
||||||
|
|
||||||
|
|||||||
@@ -322,7 +322,7 @@ vi.mock("./doctor-state-migrations.js", () => ({
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
describe("doctor command", () => {
|
describe("doctor command", () => {
|
||||||
it("migrates routing.allowFrom to channels.whatsapp.allowFrom", { timeout: 30_000 }, async () => {
|
it("migrates routing.allowFrom to channels.whatsapp.allowFrom", { timeout: 60_000 }, async () => {
|
||||||
readConfigFileSnapshot.mockResolvedValue({
|
readConfigFileSnapshot.mockResolvedValue({
|
||||||
path: "/tmp/clawdbot.json",
|
path: "/tmp/clawdbot.json",
|
||||||
exists: true,
|
exists: true,
|
||||||
@@ -366,7 +366,7 @@ describe("doctor command", () => {
|
|||||||
expect(written.routing).toBeUndefined();
|
expect(written.routing).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("migrates legacy gateway services", { timeout: 30_000 }, async () => {
|
it("migrates legacy gateway services", { timeout: 60_000 }, async () => {
|
||||||
readConfigFileSnapshot.mockResolvedValue({
|
readConfigFileSnapshot.mockResolvedValue({
|
||||||
path: "/tmp/clawdbot.json",
|
path: "/tmp/clawdbot.json",
|
||||||
exists: true,
|
exists: true,
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ beforeEach(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe("discord native commands", () => {
|
describe("discord native commands", () => {
|
||||||
it("streams tool results for native slash commands", { timeout: 30_000 }, async () => {
|
it("streams tool results for native slash commands", { timeout: 60_000 }, async () => {
|
||||||
const { ChannelType } = await import("@buape/carbon");
|
const { ChannelType } = await import("@buape/carbon");
|
||||||
const { createDiscordNativeCommand } = await import("./monitor.js");
|
const { createDiscordNativeCommand } = await import("./monitor.js");
|
||||||
|
|
||||||
|
|||||||
@@ -333,7 +333,7 @@ describe("gateway server agent", () => {
|
|||||||
await server.close();
|
await server.close();
|
||||||
});
|
});
|
||||||
|
|
||||||
test("agent dedupe survives reconnect", { timeout: 15000 }, async () => {
|
test("agent dedupe survives reconnect", { timeout: 60_000 }, async () => {
|
||||||
const port = await getFreePort();
|
const port = await getFreePort();
|
||||||
const server = await startGatewayServer(port);
|
const server = await startGatewayServer(port);
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ async function waitForWsClose(ws: WebSocket, timeoutMs: number): Promise<boolean
|
|||||||
}
|
}
|
||||||
|
|
||||||
describe("gateway server auth/connect", () => {
|
describe("gateway server auth/connect", () => {
|
||||||
test("closes silent handshakes after timeout", { timeout: 30_000 }, async () => {
|
test("closes silent handshakes after timeout", { timeout: 60_000 }, async () => {
|
||||||
vi.useRealTimers();
|
vi.useRealTimers();
|
||||||
const { server, ws } = await startServerWithClient();
|
const { server, ws } = await startServerWithClient();
|
||||||
const closed = await waitForWsClose(ws, HANDSHAKE_TIMEOUT_MS + 2_000);
|
const closed = await waitForWsClose(ws, HANDSHAKE_TIMEOUT_MS + 2_000);
|
||||||
@@ -129,7 +129,7 @@ describe("gateway server auth/connect", () => {
|
|||||||
|
|
||||||
test(
|
test(
|
||||||
"invalid connect params surface in response and close reason",
|
"invalid connect params surface in response and close reason",
|
||||||
{ timeout: 15000 },
|
{ timeout: 60_000 },
|
||||||
async () => {
|
async () => {
|
||||||
const { server, ws } = await startServerWithClient();
|
const { server, ws } = await startServerWithClient();
|
||||||
const closeInfoPromise = new Promise<{ code: number; reason: string }>((resolve) => {
|
const closeInfoPromise = new Promise<{ code: number; reason: string }>((resolve) => {
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ async function waitFor(condition: () => boolean, timeoutMs = 1500) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
describe("gateway server chat", () => {
|
describe("gateway server chat", () => {
|
||||||
test("chat.history caps payload bytes", { timeout: 15_000 }, async () => {
|
test("chat.history caps payload bytes", { timeout: 60_000 }, async () => {
|
||||||
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-gw-"));
|
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-gw-"));
|
||||||
testState.sessionStorePath = path.join(dir, "sessions.json");
|
testState.sessionStorePath = path.join(dir, "sessions.json");
|
||||||
await writeSessionStore({
|
await writeSessionStore({
|
||||||
@@ -105,7 +105,7 @@ describe("gateway server chat", () => {
|
|||||||
await server.close();
|
await server.close();
|
||||||
});
|
});
|
||||||
|
|
||||||
test("chat.abort cancels an in-flight chat.send", { timeout: 15000 }, async () => {
|
test("chat.abort cancels an in-flight chat.send", { timeout: 60_000 }, async () => {
|
||||||
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-gw-"));
|
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-gw-"));
|
||||||
testState.sessionStorePath = path.join(dir, "sessions.json");
|
testState.sessionStorePath = path.join(dir, "sessions.json");
|
||||||
await writeSessionStore({
|
await writeSessionStore({
|
||||||
@@ -263,7 +263,7 @@ describe("gateway server chat", () => {
|
|||||||
await server.close();
|
await server.close();
|
||||||
});
|
});
|
||||||
|
|
||||||
test("chat.send treats /stop as an out-of-band abort", { timeout: 15000 }, async () => {
|
test("chat.send treats /stop as an out-of-band abort", { timeout: 60_000 }, async () => {
|
||||||
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-gw-"));
|
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-gw-"));
|
||||||
testState.sessionStorePath = path.join(dir, "sessions.json");
|
testState.sessionStorePath = path.join(dir, "sessions.json");
|
||||||
await writeSessionStore({
|
await writeSessionStore({
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import {
|
|||||||
installGatewayTestHooks();
|
installGatewayTestHooks();
|
||||||
|
|
||||||
describe("gateway server health/presence", () => {
|
describe("gateway server health/presence", () => {
|
||||||
test("connect + health + presence + status succeed", { timeout: 20_000 }, async () => {
|
test("connect + health + presence + status succeed", { timeout: 60_000 }, async () => {
|
||||||
const { server, ws } = await startServerWithClient();
|
const { server, ws } = await startServerWithClient();
|
||||||
await connectOk(ws);
|
await connectOk(ws);
|
||||||
|
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ describe("gateway server misc", () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test("send dedupes by idempotencyKey", { timeout: 20_000 }, async () => {
|
test("send dedupes by idempotencyKey", { timeout: 60_000 }, async () => {
|
||||||
const { server, ws } = await startServerWithClient();
|
const { server, ws } = await startServerWithClient();
|
||||||
await connectOk(ws);
|
await connectOk(ws);
|
||||||
|
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ describe("gateway server models + voicewake", () => {
|
|||||||
|
|
||||||
test(
|
test(
|
||||||
"voicewake.get returns defaults and voicewake.set broadcasts",
|
"voicewake.get returns defaults and voicewake.set broadcasts",
|
||||||
{ timeout: 30_000 },
|
{ timeout: 60_000 },
|
||||||
async () => {
|
async () => {
|
||||||
const homeDir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-home-"));
|
const homeDir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-home-"));
|
||||||
const restoreHome = setTempHome(homeDir);
|
const restoreHome = setTempHome(homeDir);
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ describe("sessions_send gateway loopback", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe("sessions_send label lookup", () => {
|
describe("sessions_send label lookup", () => {
|
||||||
it("finds session by label and sends message", { timeout: 15_000 }, async () => {
|
it("finds session by label and sends message", { timeout: 60_000 }, async () => {
|
||||||
const port = await getFreePort();
|
const port = await getFreePort();
|
||||||
const prevPort = process.env.CLAWDBOT_GATEWAY_PORT;
|
const prevPort = process.env.CLAWDBOT_GATEWAY_PORT;
|
||||||
process.env.CLAWDBOT_GATEWAY_PORT = String(port);
|
process.env.CLAWDBOT_GATEWAY_PORT = String(port);
|
||||||
@@ -170,7 +170,7 @@ describe("sessions_send label lookup", () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it("returns error when label not found", { timeout: 15_000 }, async () => {
|
it("returns error when label not found", { timeout: 60_000 }, async () => {
|
||||||
const port = await getFreePort();
|
const port = await getFreePort();
|
||||||
const prevPort = process.env.CLAWDBOT_GATEWAY_PORT;
|
const prevPort = process.env.CLAWDBOT_GATEWAY_PORT;
|
||||||
process.env.CLAWDBOT_GATEWAY_PORT = String(port);
|
process.env.CLAWDBOT_GATEWAY_PORT = String(port);
|
||||||
@@ -199,7 +199,7 @@ describe("sessions_send label lookup", () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it("returns error when neither sessionKey nor label provided", { timeout: 15_000 }, async () => {
|
it("returns error when neither sessionKey nor label provided", { timeout: 60_000 }, async () => {
|
||||||
const port = await getFreePort();
|
const port = await getFreePort();
|
||||||
const prevPort = process.env.CLAWDBOT_GATEWAY_PORT;
|
const prevPort = process.env.CLAWDBOT_GATEWAY_PORT;
|
||||||
process.env.CLAWDBOT_GATEWAY_PORT = String(port);
|
process.env.CLAWDBOT_GATEWAY_PORT = String(port);
|
||||||
|
|||||||
@@ -228,7 +228,7 @@ describe("web auto-reply", () => {
|
|||||||
await run;
|
await run;
|
||||||
}, 15_000);
|
}, 15_000);
|
||||||
|
|
||||||
it("stops after hitting max reconnect attempts", { timeout: 20000 }, async () => {
|
it("stops after hitting max reconnect attempts", { timeout: 60_000 }, async () => {
|
||||||
const closeResolvers: Array<() => void> = [];
|
const closeResolvers: Array<() => void> = [];
|
||||||
const sleep = vi.fn(async () => {});
|
const sleep = vi.fn(async () => {});
|
||||||
const listenerFactory = vi.fn(async () => {
|
const listenerFactory = vi.fn(async () => {
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ describe("web logout", () => {
|
|||||||
vi.restoreAllMocks();
|
vi.restoreAllMocks();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("deletes cached credentials when present", { timeout: 15_000 }, async () => {
|
it("deletes cached credentials when present", { timeout: 60_000 }, async () => {
|
||||||
await withTempHome(async (home) => {
|
await withTempHome(async (home) => {
|
||||||
vi.resetModules();
|
vi.resetModules();
|
||||||
const { logoutWeb, WA_WEB_AUTH_DIR } = await import("./session.js");
|
const { logoutWeb, WA_WEB_AUTH_DIR } = await import("./session.js");
|
||||||
@@ -37,7 +37,7 @@ describe("web logout", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("no-ops when nothing to delete", { timeout: 15_000 }, async () => {
|
it("no-ops when nothing to delete", { timeout: 60_000 }, async () => {
|
||||||
await withTempHome(async () => {
|
await withTempHome(async () => {
|
||||||
vi.resetModules();
|
vi.resetModules();
|
||||||
const { logoutWeb } = await import("./session.js");
|
const { logoutWeb } = await import("./session.js");
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { fileURLToPath } from "node:url";
|
|||||||
import { defineConfig } from "vitest/config";
|
import { defineConfig } from "vitest/config";
|
||||||
|
|
||||||
const repoRoot = path.dirname(fileURLToPath(import.meta.url));
|
const repoRoot = path.dirname(fileURLToPath(import.meta.url));
|
||||||
|
const isCI = process.env.CI === "true" || process.env.GITHUB_ACTIONS === "true";
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
resolve: {
|
resolve: {
|
||||||
@@ -11,8 +12,10 @@ export default defineConfig({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
test: {
|
test: {
|
||||||
testTimeout: 30_000,
|
testTimeout: 60_000,
|
||||||
hookTimeout: 60_000,
|
hookTimeout: 120_000,
|
||||||
|
pool: "forks",
|
||||||
|
maxWorkers: isCI ? 3 : 4,
|
||||||
include: [
|
include: [
|
||||||
"src/**/*.test.ts",
|
"src/**/*.test.ts",
|
||||||
"extensions/**/*.test.ts",
|
"extensions/**/*.test.ts",
|
||||||
|
|||||||
Reference in New Issue
Block a user