test: stabilize gateway canvas and session cleanup

This commit is contained in:
Peter Steinberger
2026-04-05 13:07:28 +09:00
parent 5e0e50b12e
commit 749ed86fe3
2 changed files with 30 additions and 5 deletions

View File

@@ -1,3 +1,4 @@
import type { Socket } from "node:net";
import { describe, expect, test } from "vitest";
import { WebSocket, WebSocketServer } from "ws";
import { A2UI_PATH, CANVAS_HOST_PATH, CANVAS_WS_PATH } from "../canvas-host/a2ui.js";
@@ -12,7 +13,6 @@ import { withTempConfig } from "./test-temp-config.js";
const WS_REJECT_TIMEOUT_MS = 2_000;
const WS_CONNECT_TIMEOUT_MS = 2_000;
async function listen(
server: ReturnType<typeof createGatewayHttpServer>,
host = "127.0.0.1",
@@ -21,6 +21,13 @@ async function listen(
port: number;
close: () => Promise<void>;
}> {
const sockets = new Set<Socket>();
server.on("connection", (socket) => {
sockets.add(socket);
socket.once("close", () => {
sockets.delete(socket);
});
});
await new Promise<void>((resolve) => server.listen(0, host, resolve));
const addr = server.address();
const port = typeof addr === "object" && addr ? addr.port : 0;
@@ -28,6 +35,9 @@ async function listen(
host,
port,
close: async () => {
for (const socket of sockets) {
socket.destroy();
}
await new Promise<void>((resolve, reject) =>
server.close((err) => (err ? reject(err) : resolve())),
);
@@ -169,10 +179,16 @@ async function withCanvasGatewayHarness(params: {
try {
await params.run({ listener, clients });
} finally {
for (const ws of canvasWss.clients) {
ws.terminate();
}
for (const ws of wss.clients) {
ws.terminate();
}
await new Promise<void>((resolve) => canvasWss.close(() => resolve()));
await new Promise<void>((resolve) => wss.close(() => resolve()));
await listener.close();
params.rateLimiter?.dispose();
canvasWss.close();
wss.close();
}
}

View File

@@ -3,7 +3,6 @@ import os from "node:os";
import path from "node:path";
import { afterAll, beforeAll, beforeEach, describe, expect, test, vi } from "vitest";
import { WebSocket } from "ws";
import { DEFAULT_PROVIDER } from "../agents/defaults.js";
import { clearConfigCache, clearRuntimeConfigSnapshot } from "../config/config.js";
import { loadConfig } from "../config/config.js";
import { withSessionStoreLockForTest } from "../config/sessions/store.js";
@@ -183,6 +182,16 @@ vi.mock("../acp/control-plane/manager.js", () => ({
}),
}));
vi.mock("../../extensions/browser/runtime-api.js", async () => {
const actual = await vi.importActual<typeof import("../../extensions/browser/runtime-api.js")>(
"../../extensions/browser/runtime-api.js",
);
return {
...actual,
closeTrackedBrowserTabsForSessions: browserSessionTabMocks.closeTrackedBrowserTabsForSessions,
};
});
vi.mock("../plugin-sdk/browser-maintenance.js", () => ({
closeTrackedBrowserTabsForSessions: browserSessionTabMocks.closeTrackedBrowserTabsForSessions,
movePathToTrash: vi.fn(async () => {}),
@@ -971,7 +980,7 @@ describe("gateway server sessions", () => {
expect(list1.ok).toBe(true);
expect(list1.payload?.path).toBe(storePath);
expect(list1.payload?.sessions.some((s) => s.key === "global")).toBe(false);
expect(list1.payload?.defaults?.modelProvider).toBe(DEFAULT_PROVIDER);
expect(list1.payload?.defaults?.modelProvider).toBe("anthropic");
const main = list1.payload?.sessions.find((s) => s.key === "agent:main:main");
expect(main?.totalTokens).toBeUndefined();
expect(main?.totalTokensFresh).toBe(false);