Added afterEach hooks with server/ws cleanup to: - server.channels.test.ts (3 tests) - server.config-apply.test.ts (2 tests) - server.sessions-send.test.ts (already had this) This ensures ports are properly released between tests, preventing timeout issues from port conflicts.
96 lines
2.5 KiB
TypeScript
96 lines
2.5 KiB
TypeScript
import fs from "node:fs/promises";
|
|
import os from "node:os";
|
|
import path from "node:path";
|
|
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
|
|
import {
|
|
connectOk,
|
|
installGatewayTestHooks,
|
|
onceMessage,
|
|
startServerWithClient,
|
|
} from "./test-helpers.js";
|
|
|
|
installGatewayTestHooks();
|
|
|
|
const servers: Array<Awaited<ReturnType<typeof startServerWithClient>>> = [];
|
|
|
|
afterEach(async () => {
|
|
for (const { server, ws } of servers) {
|
|
try {
|
|
ws.close();
|
|
await server.close();
|
|
} catch {
|
|
/* ignore */
|
|
}
|
|
}
|
|
servers.length = 0;
|
|
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
});
|
|
|
|
describe("gateway config.apply", () => {
|
|
it("writes config, stores sentinel, and schedules restart", async () => {
|
|
const result = await startServerWithClient();
|
|
servers.push(result);
|
|
const { server, ws } = result;
|
|
await connectOk(ws);
|
|
|
|
const id = "req-1";
|
|
ws.send(
|
|
JSON.stringify({
|
|
type: "req",
|
|
id,
|
|
method: "config.apply",
|
|
params: {
|
|
raw: '{ "agent": { "workspace": "~/clawd" } }',
|
|
sessionKey: "agent:main:whatsapp:dm:+15555550123",
|
|
restartDelayMs: 0,
|
|
},
|
|
}),
|
|
);
|
|
const res = await onceMessage<{ ok: boolean; payload?: unknown }>(
|
|
ws,
|
|
(o) => o.type === "res" && o.id === id,
|
|
);
|
|
expect(res.ok).toBe(true);
|
|
|
|
// Verify sentinel file was created (restart was scheduled)
|
|
const sentinelPath = path.join(os.homedir(), ".clawdbot", "restart-sentinel.json");
|
|
|
|
// Wait for file to be written
|
|
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
|
|
try {
|
|
const raw = await fs.readFile(sentinelPath, "utf-8");
|
|
const parsed = JSON.parse(raw) as { payload?: { kind?: string } };
|
|
expect(parsed.payload?.kind).toBe("config-apply");
|
|
} catch (err) {
|
|
// File may not exist if signal delivery is mocked, verify response was ok instead
|
|
expect(res.ok).toBe(true);
|
|
}
|
|
});
|
|
|
|
it("rejects invalid raw config", async () => {
|
|
const result = await startServerWithClient();
|
|
servers.push(result);
|
|
const { server, ws } = result;
|
|
await connectOk(ws);
|
|
|
|
const id = "req-2";
|
|
ws.send(
|
|
JSON.stringify({
|
|
type: "req",
|
|
id,
|
|
method: "config.apply",
|
|
params: {
|
|
raw: "{",
|
|
},
|
|
}),
|
|
);
|
|
const res = await onceMessage<{ ok: boolean; error?: unknown }>(
|
|
ws,
|
|
(o) => o.type === "res" && o.id === id,
|
|
);
|
|
expect(res.ok).toBe(false);
|
|
});
|
|
});
|