179 lines
6.1 KiB
TypeScript
179 lines
6.1 KiB
TypeScript
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();
|
|
}
|
|
});
|
|
});
|