Files
clawdbot/src/infra/bonjour-discovery.test.ts
2026-01-09 08:13:04 +01:00

135 lines
4.0 KiB
TypeScript

import { describe, expect, it, vi } from "vitest";
import type { runCommandWithTimeout } from "../process/exec.js";
import { WIDE_AREA_DISCOVERY_DOMAIN } from "./widearea-dns.js";
import { discoverGatewayBeacons } from "./bonjour-discovery.js";
describe("bonjour-discovery", () => {
it("discovers beacons on darwin across local + wide-area domains", async () => {
const calls: Array<{ argv: string[]; timeoutMs: number }> = [];
const run = vi.fn(async (argv: string[], options: { timeoutMs: number }) => {
calls.push({ argv, timeoutMs: options.timeoutMs });
const domain = argv[3] ?? "";
if (argv[0] === "dns-sd" && argv[1] === "-B") {
if (domain === "local.") {
return {
stdout: [
"Add 2 3 local. _clawdbot-bridge._tcp. Studio Bridge",
"Add 2 3 local. _clawdbot-bridge._tcp. Laptop Bridge",
"",
].join("\n"),
stderr: "",
code: 0,
signal: null,
killed: false,
};
}
if (domain === WIDE_AREA_DISCOVERY_DOMAIN) {
return {
stdout: [
`Add 2 3 ${WIDE_AREA_DISCOVERY_DOMAIN} _clawdbot-bridge._tcp. Tailnet Bridge`,
"",
].join("\n"),
stderr: "",
code: 0,
signal: null,
killed: false,
};
}
}
if (argv[0] === "dns-sd" && argv[1] === "-L") {
const instance = argv[2] ?? "";
const host =
instance === "Studio Bridge"
? "studio.local"
: instance === "Laptop Bridge"
? "laptop.local"
: "tailnet.local";
const tailnetDns =
instance === "Tailnet Bridge" ? "studio.tailnet.ts.net" : "";
const txtParts = [
"txtvers=1",
`displayName=${instance.replace(" Bridge", "")}`,
`lanHost=${host}`,
"gatewayPort=18789",
"bridgePort=18790",
"sshPort=22",
tailnetDns ? `tailnetDns=${tailnetDns}` : null,
].filter((v): v is string => Boolean(v));
return {
stdout: [
`${instance}._clawdbot-bridge._tcp. can be reached at ${host}:18790`,
txtParts.join(" "),
"",
].join("\n"),
stderr: "",
code: 0,
signal: null,
killed: false,
};
}
throw new Error(`unexpected argv: ${argv.join(" ")}`);
});
const beacons = await discoverGatewayBeacons({
platform: "darwin",
timeoutMs: 1234,
run: run as unknown as typeof runCommandWithTimeout,
});
expect(beacons).toHaveLength(3);
expect(beacons.map((b) => b.domain)).toEqual(
expect.arrayContaining(["local.", WIDE_AREA_DISCOVERY_DOMAIN]),
);
const browseCalls = calls.filter(
(c) => c.argv[0] === "dns-sd" && c.argv[1] === "-B",
);
expect(browseCalls.map((c) => c.argv[3])).toEqual(
expect.arrayContaining(["local.", WIDE_AREA_DISCOVERY_DOMAIN]),
);
expect(browseCalls.every((c) => c.timeoutMs === 1234)).toBe(true);
});
it("normalizes domains and respects domains override", async () => {
const calls: string[][] = [];
const run = vi.fn(async (argv: string[]) => {
calls.push(argv);
return {
stdout: "",
stderr: "",
code: 0,
signal: null,
killed: false,
};
});
await discoverGatewayBeacons({
platform: "darwin",
timeoutMs: 1,
domains: ["local", "clawdbot.internal"],
run: run as unknown as typeof runCommandWithTimeout,
});
expect(calls.filter((c) => c[1] === "-B").map((c) => c[3])).toEqual(
expect.arrayContaining(["local.", "clawdbot.internal."]),
);
calls.length = 0;
await discoverGatewayBeacons({
platform: "darwin",
timeoutMs: 1,
domains: ["local."],
run: run as unknown as typeof runCommandWithTimeout,
});
expect(calls.filter((c) => c[1] === "-B")).toHaveLength(1);
expect(calls.filter((c) => c[1] === "-B")[0]?.[3]).toBe("local.");
});
});