import { createServer } from "node:net"; import { once } from "node:events"; import { afterEach, describe, expect, it } from "vitest"; import { startHub } from "../../src/hub.js"; import { TEST_DATABASE_URL } from "./helpers.js"; const ENV_KEYS = [ "DATABASE_URL", "ANTHROPIC_AUTH_TOKEN", "ANTHROPIC_API_KEY", "FEISHU_APP_ID", "FEISHU_APP_SECRET", "FEISHU_BOT_OPEN_ID", "HUB_PROJECT_WORKSPACE_ROOT", "HUB_SESSION_SECRET", "HUB_PUBLIC_BASE_URL", "HUB_FEISHU_LISTENER_ENABLED", "HOST", "PORT", ] as const; describe("Hub startup", () => { const previousEnv = new Map(ENV_KEYS.map((key) => [key, process.env[key]])); afterEach(() => { for (const [key, value] of previousEnv) { if (value === undefined) delete process.env[key]; else process.env[key] = value; } }); it("rejects startup before the Feishu listener when the HTTP bind fails", async () => { const blocker = createServer(); blocker.listen(0, "127.0.0.1"); await once(blocker, "listening"); const address = blocker.address(); if (address === null || typeof address === "string") throw new Error("expected an INET test listener"); Object.assign(process.env, { DATABASE_URL: TEST_DATABASE_URL, ANTHROPIC_AUTH_TOKEN: "test-provider-token", ANTHROPIC_API_KEY: "", FEISHU_APP_ID: "test-app", FEISHU_APP_SECRET: "test-secret", FEISHU_BOT_OPEN_ID: "ou_test_bot", HUB_PROJECT_WORKSPACE_ROOT: "/tmp/cph-hub-server-start-test", HUB_SESSION_SECRET: "integration-session-secret-with-32-bytes", HUB_PUBLIC_BASE_URL: "https://hub.example.test", HUB_FEISHU_LISTENER_ENABLED: "false", HOST: "127.0.0.1", PORT: String(address.port), }); try { await expect(startHub()).rejects.toMatchObject({ code: "EADDRINUSE" }); } finally { blocker.close(); await once(blocker, "close"); } }); });