import { describe, it, expect } from "vitest"; import { Metrics, mergeExposition } from "../src/metrics.js"; /** * TASK-0135 — the /metrics merge contract (local registry authoritative, * OTel-only families appended, no duplicate families). */ const LOCAL = [ "# HELP uptime_seconds Process uptime in seconds.", "# TYPE uptime_seconds gauge", "uptime_seconds 42", "# HELP ws_connections Live WebSocket connections, by room type.", "# TYPE ws_connections gauge", 'ws_connections{room="page"} 3', "# HELP ws_messages_total Frames received, by frame type.", "# TYPE ws_messages_total counter", 'ws_messages_total{frame="update"} 10', ].join("\n") + "\n"; const OTEL = [ "# HELP target_info Target metadata.", "# TYPE target_info gauge", 'target_info{service_name="factory-realtime"} 1', "# HELP ws_active_connections Live WebSocket connections, total.", "# TYPE ws_active_connections gauge", "ws_active_connections 5", "# HELP ws_messages_total Frames received (OTel, no labels).", "# TYPE ws_messages_total counter", "ws_messages_total 7", ].join("\n") + "\n"; describe("mergeExposition", () => { it("returns the local text unchanged when OTel text is empty (disabled)", () => { expect(mergeExposition(LOCAL, "")).toBe(LOCAL); }); it("appends OTel-only families (target_info, ws_active_connections)", () => { const out = mergeExposition(LOCAL, OTEL); expect(out).toContain('target_info{service_name="factory-realtime"} 1'); expect(out).toContain("ws_active_connections 5"); expect(out).toContain("# TYPE target_info gauge"); }); it("keeps the LOCAL form on a family collision and drops the OTel one", () => { const out = mergeExposition(LOCAL, OTEL); // The local, labeled form survives… expect(out).toContain('ws_messages_total{frame="update"} 10'); // …and the OTel unlabeled duplicate does NOT (no second family def, no bare sample). expect(out).not.toContain("# HELP ws_messages_total Frames received (OTel, no labels)."); expect(out).not.toMatch(/^ws_messages_total \d+/m); // Exactly one `# TYPE ws_messages_total` line in the result. expect(out.match(/# TYPE ws_messages_total /g)).toHaveLength(1); }); it("preserves the local ordering first, OTel additions last", () => { const out = mergeExposition(LOCAL, OTEL); expect(out.indexOf("uptime_seconds 42")).toBeLessThan(out.indexOf("target_info")); }); it("round-trips the local registry's own render() output", () => { const reg = new Metrics(() => 1000); reg.inc("ws_messages_total", { frame: "ping" }); const local = reg.render(); const out = mergeExposition(local, OTEL); expect(out).toContain('ws_messages_total{frame="ping"} 1'); expect(out.match(/# TYPE ws_messages_total /g)).toHaveLength(1); }); });