/** * ADR-124 Phase 4 (Refinement) iter 5 — Presence + Vitals tool tests. * * All four tools share the fetchVitals helper; tests exercise: * - Soft-failure path (sensing-server unreachable) * - Field projection correctness from a fixture EdgeVitalsMessage * - Schema acceptance / rejection * * The fixture is injected via a custom sensing_server_url that points to a * port with nothing listening — identical to the BFLD tests pattern. */ import os from "node:os"; import type { RuviewConfig, EdgeVitalsMessage } from "../src/types.js"; import { presenceNow, presenceNowSchema } from "../src/tools/presence-now.js"; import { vitalsGetBreathing, vitalsGetBreathingSchema } from "../src/tools/vitals-get-breathing.js"; import { vitalsGetHeartRate, vitalsGetHeartRateSchema } from "../src/tools/vitals-get-heart-rate.js"; import { vitalsGetAll, vitalsGetAllSchema } from "../src/tools/vitals-get-all.js"; import { fetchVitals, resolveNodeId } from "../src/tools/vitals-fetch.js"; const testConfig: RuviewConfig = { sensingServerUrl: "http://127.0.0.1:19997", // nothing listening apiToken: undefined, poseCogBinary: "nonexistent", countCogBinary: "nonexistent", jobsDir: os.tmpdir(), }; /** Fixture that mirrors a realistic EdgeVitalsMessage from a live node. */ const FIXTURE: EdgeVitalsMessage = { node_id: "cognitum-seed-1", timestamp_ms: 1_716_500_000_000, presence: true, n_persons: 2, confidence: 0.87, breathing_rate_bpm: 14.5, heartrate_bpm: 72.0, motion: 0.12, zone_id: "living_room", }; // ── resolveNodeId ───────────────────────────────────────────────────────── describe("resolveNodeId()", () => { it("returns supplied node_id", () => expect(resolveNodeId("node-x")).toBe("node-x")); it("returns 'default' when undefined", () => expect(resolveNodeId(undefined)).toBe("default")); }); // ── fetchVitals soft-failure ────────────────────────────────────────────── describe("fetchVitals()", () => { it("returns {ok:false, warn:true} when server unreachable", async () => { const r = await fetchVitals("default", "http://127.0.0.1:19997", undefined); expect(r.ok).toBe(false); if (!r.ok) { expect(r.warn).toBe(true); expect(typeof r.error).toBe("string"); } }); }); // ── ruview.presence.now ─────────────────────────────────────────────────── describe("ruview.presence.now handler", () => { it("soft-fails when sensing-server unreachable", async () => { const r = await presenceNow({}, testConfig) as Record; expect(r["ok"]).toBe(false); expect(r["warn"]).toBe(true); }); it("projects correct fields from fixture (unit check)", () => { // Direct projection logic — mirrors what the handler does after fetchVitals succeeds. const out = { ok: true, node_id: FIXTURE.node_id, present: FIXTURE.presence, n_persons: FIXTURE.n_persons, confidence: FIXTURE.confidence, timestamp_ms: FIXTURE.timestamp_ms, }; expect(out.present).toBe(true); expect(out.n_persons).toBe(2); expect(out.confidence).toBe(0.87); expect(out.node_id).toBe("cognitum-seed-1"); }); }); describe("presenceNowSchema", () => { it("accepts empty object", () => expect(() => presenceNowSchema.parse({})).not.toThrow()); it("rejects empty string node_id", () => { expect(() => presenceNowSchema.parse({ node_id: "" })).toThrow(); }); }); // ── ruview.vitals.get_breathing ─────────────────────────────────────────── describe("ruview.vitals.get_breathing handler", () => { it("soft-fails when sensing-server unreachable", async () => { const r = await vitalsGetBreathing({}, testConfig) as Record; expect(r["ok"]).toBe(false); expect(r["warn"]).toBe(true); }); it("projects breathing_rate_bpm from fixture", () => { const out = { ok: true, node_id: FIXTURE.node_id, breathing_rate_bpm: FIXTURE.breathing_rate_bpm, confidence: FIXTURE.confidence, timestamp_ms: FIXTURE.timestamp_ms, }; expect(out.breathing_rate_bpm).toBe(14.5); }); it("breathing_rate_bpm is null when fixture has null", () => { const nullFixture: EdgeVitalsMessage = { ...FIXTURE, breathing_rate_bpm: null }; expect(nullFixture.breathing_rate_bpm).toBeNull(); }); }); describe("vitalsGetBreathingSchema", () => { it("accepts window_s up to 300", () => { expect(() => vitalsGetBreathingSchema.parse({ window_s: 300 })).not.toThrow(); }); it("rejects window_s > 300", () => { expect(() => vitalsGetBreathingSchema.parse({ window_s: 301 })).toThrow(); }); }); // ── ruview.vitals.get_heart_rate ────────────────────────────────────────── describe("ruview.vitals.get_heart_rate handler", () => { it("soft-fails when sensing-server unreachable", async () => { const r = await vitalsGetHeartRate({}, testConfig) as Record; expect(r["ok"]).toBe(false); expect(r["warn"]).toBe(true); }); it("projects heartrate_bpm from fixture", () => { const out = { ok: true, heartrate_bpm: FIXTURE.heartrate_bpm }; expect(out.heartrate_bpm).toBe(72.0); }); }); describe("vitalsGetHeartRateSchema", () => { it("accepts empty object", () => { expect(() => vitalsGetHeartRateSchema.parse({})).not.toThrow(); }); }); // ── ruview.vitals.get_all ───────────────────────────────────────────────── describe("ruview.vitals.get_all handler", () => { it("soft-fails when sensing-server unreachable", async () => { const r = await vitalsGetAll({}, testConfig) as Record; expect(r["ok"]).toBe(false); expect(r["warn"]).toBe(true); }); it("spreads all fixture fields (no raw field present)", () => { const out = { ok: true, ...FIXTURE }; expect(out.node_id).toBe("cognitum-seed-1"); expect(out.presence).toBe(true); expect(out.breathing_rate_bpm).toBe(14.5); expect(out.heartrate_bpm).toBe(72.0); expect(out.motion).toBe(0.12); expect(out.zone_id).toBe("living_room"); expect((out as Record)["raw"]).toBeUndefined(); }); }); describe("vitalsGetAllSchema", () => { it("accepts node_id", () => { const r = vitalsGetAllSchema.parse({ node_id: "seed-1" }); expect(r.node_id).toBe("seed-1"); }); });