import { describe, expect, it } from "@suaveplan/testing/runner"; import { TrysteroServer } from "../src/server/server.js"; import { makeFakeBrokerFactory } from "./setup/fake-trystero-server.js"; async function fetchJson( url: string ): Promise<{ readonly status: number; readonly body: unknown }> { const res = await fetch(url); const body = await res.json(); return { status: res.status, body }; } function baseUrl(address: string, port: number): string { const host = address === "::" || address === "0.0.0.0" ? "127.0.0.1" : address; return `http://${host}:${port}`; } describe("integration: real HTTP boot + health probes (mqtt)", () => { it("health/ready/live respond with 200 while running", { timeout: 10_000, }, async () => { const { factory } = makeFakeBrokerFactory("mqtt"); const server = new TrysteroServer({ mode: "mqtt", port: 0, host: "127.0.0.1", mqttBrokerFactory: factory, }); const { address, port, mode, relayUrl } = await server.start(); expect(mode).toBe("mqtt"); expect(relayUrl.endsWith("/mqtt")).toBe(true); const base = baseUrl(address, port); try { const health = await fetchJson(`${base}/health`); expect(health.status).toBe(200); expect((health.body as { status: string }).status).toBe("ok"); expect((health.body as { mode: string }).mode).toBe("mqtt"); const ready = await fetchJson(`${base}/ready`); expect(ready.status).toBe(200); const live = await fetchJson(`${base}/live`); expect(live.status).toBe(200); // Non-health route falls through to the relay marker. const fall = await fetch(`${base}/mqtt`); expect(fall.status).toBe(200); const txt = await fall.text(); expect(txt).toContain("mqtt"); } finally { await server.stop(); } }); it("two clients connect via fake broker; daemon tracks both", { timeout: 10_000, }, async () => { const { factory, instances } = makeFakeBrokerFactory("mqtt"); const server = new TrysteroServer({ mode: "mqtt", port: 0, host: "127.0.0.1", mqttBrokerFactory: factory, }); await server.start(); try { const broker = instances[0]; if (!broker) throw new Error("expected broker"); broker.connect("client-1"); broker.connect("client-2"); broker.frame("client-1"); broker.frame("client-2"); expect(server.activeConnections).toBe(2); const ids = server .peers() .map((p) => p.id) .sort(); expect(ids).toEqual(["client-1", "client-2"]); } finally { await server.stop(); } }); it("malformed frame from a misbehaving client is dropped", { timeout: 10_000, }, async () => { const { factory, instances } = makeFakeBrokerFactory("mqtt"); const server = new TrysteroServer({ mode: "mqtt", port: 0, host: "127.0.0.1", mqttBrokerFactory: factory, }); await server.start(); try { const broker = instances[0]; if (!broker) throw new Error("expected broker"); broker.connect("client-1"); broker.malformed("client-1"); // Still tracked, no extra peers. expect(server.activeConnections).toBe(1); expect(server.peers()).toHaveLength(1); } finally { await server.stop(); } }); it("graceful stop closes the HTTP listener", { timeout: 10_000, }, async () => { const { factory } = makeFakeBrokerFactory("mqtt"); const server = new TrysteroServer({ mode: "mqtt", port: 0, host: "127.0.0.1", mqttBrokerFactory: factory, }); const { address, port } = await server.start(); const base = baseUrl(address, port); await server.stop(); await expect(fetch(`${base}/health`)).rejects.toBeDefined(); }); }); describe("integration: real HTTP boot + health probes (nostr)", () => { it("health/ready/live respond with 200 while running", { timeout: 10_000, }, async () => { const { factory } = makeFakeBrokerFactory("nostr"); const server = new TrysteroServer({ mode: "nostr", port: 0, host: "127.0.0.1", nostrRelayFactory: factory, nostr: { relayName: "edge-it" }, }); const { address, port, mode, relayUrl } = await server.start(); expect(mode).toBe("nostr"); expect(relayUrl.endsWith("/nostr")).toBe(true); const base = baseUrl(address, port); try { const health = await fetchJson(`${base}/health`); expect(health.status).toBe(200); expect((health.body as { mode: string }).mode).toBe("nostr"); const fall = await fetch(`${base}/nostr`); expect(fall.status).toBe(200); const txt = await fall.text(); expect(txt).toContain("nostr"); } finally { await server.stop(); } }); it("two clients relay a frame between modes (nostr)", { timeout: 10_000, }, async () => { const { factory, instances } = makeFakeBrokerFactory("nostr"); const server = new TrysteroServer({ mode: "nostr", port: 0, host: "127.0.0.1", nostrRelayFactory: factory, }); await server.start(); try { const broker = instances[0]; if (!broker) throw new Error("expected broker"); broker.connect("client-1"); broker.connect("client-2"); broker.frame("client-1"); expect(server.activeConnections).toBe(2); } finally { await server.stop(); } }); });