| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475 |
- import assert from "node:assert/strict";
- import test from "node:test";
- import { MonitorStore } from "../src/store.js";
- import { normalizeThread } from "../src/domain.js";
- import { rawThread } from "./fake-app-server.js";
- function summary(id: string, status = "notLoaded") {
- return normalizeThread(rawThread(id, { status: { type: status } }));
- }
- test("snapshot replacement is atomic and advances revision only for changed inventory", () => {
- const store = new MonitorStore();
- store.replaceSnapshot([summary("a")], new Set(["a"]));
- const firstRevision = store.revision;
- assert.deepEqual(store.snapshot().threads.map((thread) => thread.id), ["a"]);
- store.replaceSnapshot([summary("b")], new Set(["b"]));
- assert.deepEqual(store.snapshot().threads.map((thread) => thread.id), ["b"]);
- assert.equal(store.revision, firstRevision + 1);
- store.replaceSnapshot([summary("b")], new Set(["b"]));
- assert.equal(store.revision, firstRevision + 1);
- });
- test("status events update known and newly observed threads", () => {
- const store = new MonitorStore();
- store.replaceSnapshot([summary("known")], new Set());
- store.updateStatus("known", { type: "active", activeFlags: ["waitingOnApproval"] });
- store.updateStatus("new", { type: "idle", activeFlags: [] });
- const byId = new Map(store.snapshot().threads.map((thread) => [thread.id, thread]));
- assert.equal(byId.get("known")?.status, "active");
- assert.deepEqual(byId.get("known")?.activeFlags, ["waitingOnApproval"]);
- assert.equal(byId.get("new")?.status, "idle");
- });
- test("change ring stays bounded and reports lost history", () => {
- const store = new MonitorStore({ changeRingSize: 2 });
- store.setConnection("connecting");
- store.setConnection("disconnected", "one");
- store.setConnection("connecting");
- const result = store.changesSince(0, 10);
- assert.equal(result.changes.length, 2);
- assert.equal(result.truncated, true);
- });
- test("connection loss retains cached snapshot and marks it stale", () => {
- const store = new MonitorStore();
- store.replaceSnapshot([summary("a")], new Set());
- store.setConnection("disconnected", "socket closed");
- const snapshot = store.snapshot();
- assert.equal(snapshot.freshness, "stale");
- assert.equal(snapshot.threads.length, 1);
- assert.equal(snapshot.connectionError, "socket closed");
- });
- test("waiting observes changes and normal timeouts", async () => {
- const store = new MonitorStore();
- const wait = store.waitForChange(store.revision, 100);
- store.setConnection("connecting");
- const changed = await wait;
- assert.equal(changed.timedOut, false);
- assert.equal(changed.changes[0]?.kind, "connection");
- const timedOut = await store.waitForChange(store.revision, 5);
- assert.equal(timedOut.timedOut, true);
- });
- test("concurrent waiters are all released and shutdown cancels remaining waits", async () => {
- const store = new MonitorStore();
- const first = store.waitForChange(0, 100);
- const second = store.waitForChange(0, 100);
- store.setConnection("connecting");
- assert.deepEqual((await Promise.all([first, second])).map((result) => result.revision), [1, 1]);
- const pending = store.waitForChange(store.revision, 10_000);
- store.shutdown();
- assert.equal((await pending).cancelled, true);
- });
|