cameras/src/app/camera-summary.test.ts
Michael Mainguy 0ec434ca26 Add read-only camera settings page and dashboard stream summary
Read-only settings and stream URLs (vrek gol-2nxgqjn), shaped by a
read-only probe of the real cameras (findings fnd-*) and decisions
dec-s205dvs and dec-gtw493s.

- src/lib/camera-settings.ts: reads streams, image, time/NTP and
  network over ONVIF behind a CameraSettingsSource interface, so an
  ISAPI source can be added later. Sections are read independently
  and fail on their own with fixed text. RTSP URLs have credentials
  stripped and use the registry host. camera.ts exports its cached
  connect() and the profile helpers it shares with it (iss-7eaywtf).
- /cameras/[id]: server-rendered page with an access check, 404 for
  unknown ids or non-private hosts, and a streamed Suspense section.
  Shows streams (with copyable RTSP URLs and an ONVIF-login note),
  image, time/NTP with a drift warning, and network, plus Refresh
  and back. Copy falls back to execCommand over plain LAN HTTP,
  where the clipboard API is unavailable (iss-s935a4n).
- Dashboard card: the name links to the camera page; a main-stream
  summary line ("Main 4096×1860 · H.264 · 20 fps"); a manufacturer
  of "ONVIF" is hidden (iss-pv2bvzj).

522 tests, 99.9% line coverage. Checked by the user in a browser
against both cameras. Refreshes the vrek export (the icon principle
now covers the page's new icons).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-19 13:00:37 -05:00

92 lines
2.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { describe, expect, it } from "vitest";
import type { CameraProfile } from "@/lib/camera";
import { codecLabel, deviceLine, displayBrand, mainStream, streamSummary } from "./camera-summary";
const main: CameraProfile = { token: "p1", name: "mainStream", encoding: "H264", width: 4096, height: 1860, fps: 20 };
const sub: CameraProfile = { token: "p2", name: "subStream", encoding: "H264", width: 1200, height: 536, fps: 20 };
describe("mainStream", () => {
it("picks the highest resolution regardless of order", () => {
expect(mainStream([sub, main])).toBe(main);
expect(mainStream([main, sub])).toBe(main);
});
it("keeps the first on a tie, and treats missing sizes as 0", () => {
const twin = { ...main, token: "p3" };
expect(mainStream([main, twin])).toBe(main);
const bare = { token: "b" };
expect(mainStream([bare, sub])).toBe(sub);
expect(mainStream([bare])).toBe(bare);
});
it("is undefined with no profiles", () => {
expect(mainStream([])).toBeUndefined();
});
});
describe("streamSummary", () => {
it("describes the main stream of the probed cameras", () => {
expect(streamSummary([main, sub])).toBe("Main 4096×1860 · H.264 · 20 fps");
});
it("omits missing parts", () => {
expect(streamSummary([{ token: "x", encoding: "H265" }])).toBe("Main · H.265");
expect(streamSummary([{ token: "x", width: 640, height: 480 }])).toBe("Main 640×480");
expect(streamSummary([{ token: "x" }])).toBe("Main");
});
it("is null with no profiles", () => {
expect(streamSummary([])).toBeNull();
});
});
describe("codecLabel", () => {
it.each([
["H264", "H.264"],
["h265", "H.265"],
["JPEG", "JPEG"],
["MPEG4", "MPEG4"],
])("%s → %s", (encoding, label) => {
expect(codecLabel(encoding)).toBe(label);
});
});
describe("displayBrand", () => {
it.each([
["ONVIF", undefined],
["onvif ", undefined],
["", undefined],
[" ", undefined],
[undefined, undefined],
["Hikvision", "Hikvision"],
[" Annke ", "Annke"],
])("%j → %j", (manufacturer, brand) => {
expect(displayBrand(manufacturer)).toBe(brand);
});
});
describe("deviceLine", () => {
it("hides the ONVIF placeholder brand", () => {
expect(deviceLine({ manufacturer: "ONVIF", model: "I91ET", firmwareVersion: "V5.8.10" })).toBe(
"I91ET · fw V5.8.10",
);
});
it("keeps a real brand", () => {
expect(deviceLine({ manufacturer: "Hikvision", model: "DS-2CD", firmwareVersion: "V5.7" })).toBe(
"Hikvision DS-2CD · fw V5.7",
);
});
it("omits missing parts", () => {
expect(deviceLine({ model: "I91ET" })).toBe("I91ET");
expect(deviceLine({ firmwareVersion: "V1" })).toBe("fw V1");
expect(deviceLine({ manufacturer: "Annke" })).toBe("Annke");
});
it("is null when nothing is known", () => {
expect(deviceLine({})).toBeNull();
expect(deviceLine({ manufacturer: "ONVIF" })).toBeNull();
});
});