import { describe, expect, test } from "bun:test"; import { Value } from "@sinclair/typebox/value"; import { EdgeClientMessageSchema } from "@continuum/ts-types"; import { NO_CAMERA_MESSAGE, NO_GATEWAY_STREAM_MESSAGE, resolveStream } from "../src/stream"; const hello = { type: "hello", gateway_id: "gw-1", farm_id: "f1", token: "t" }; describe("hello stream_base_url", () => { test("is accepted when present", () => { const msg = { ...hello, stream_base_url: "http://gateway.local:1984" }; expect(Value.Check(EdgeClientMessageSchema, msg)).toBe(true); }); test("is accepted when absent, the normal case", () => { expect(Value.Check(EdgeClientMessageSchema, hello)).toBe(true); }); test("tolerates an explicit null from a serde producer", () => { expect(Value.Check(EdgeClientMessageSchema, { ...hello, stream_base_url: null })).toBe(true); }); }); describe("telemetry camera_stream", () => { const telemetry = (extra: object) => ({ type: "telemetry", printers: [{ printer_id: "p1", name: "X1", ...extra }], }); // The persistence step itself is `snapshot.camera_stream ?? null` inside // persistTelemetry, which needs a database; what is checked here is that // the value survives the validator that guards that path. test("survives validation with its value intact", () => { const msg = telemetry({ camera_stream: "p1" }); expect(Value.Check(EdgeClientMessageSchema, msg)).toBe(true); expect((msg.printers[0] as { camera_stream?: string }).camera_stream).toBe("p1"); }); test("is optional", () => { expect(Value.Check(EdgeClientMessageSchema, telemetry({}))).toBe(true); }); }); describe("resolveStream", () => { test("returns the endpoint's success shape", () => { expect(resolveStream("p1", "http://gateway.local:1984")).toEqual({ ok: true, stream: { streamUrl: "http://gateway.local:1984", cameraId: "p1" }, }); }); test("the two failures are distinguishable", () => { const noCamera = resolveStream(null, "http://gateway.local:1984"); const noBase = resolveStream("p1", undefined); if (noCamera.ok || noBase.ok) throw new Error("expected both to fail"); expect(noCamera.reason).toBe("no_camera"); expect(noBase.reason).toBe("no_stream_base"); expect(noCamera.message).toBe(NO_CAMERA_MESSAGE); expect(noBase.message).toBe(NO_GATEWAY_STREAM_MESSAGE); expect(noCamera.message).not.toBe(noBase.message); }); test("a printer with no camera is blamed first, even if the gateway is also absent", () => { const both = resolveStream(undefined, undefined); expect(!both.ok && both.reason).toBe("no_camera"); }); });