Files
boss/tests/device-heartbeat-event-noise.test.ts

117 lines
3.8 KiB
TypeScript

import test from "node:test";
import assert from "node:assert/strict";
import os from "node:os";
import path from "node:path";
import { mkdtemp, rm } from "node:fs/promises";
let runtimeRoot = "";
let readState: (typeof import("../src/lib/boss-data"))["readState"];
let upsertDeviceHeartbeat: (typeof import("../src/lib/boss-data"))["upsertDeviceHeartbeat"];
let subscribeBossEvents: (typeof import("../src/lib/boss-events"))["subscribeBossEvents"];
async function setup() {
if (runtimeRoot) return;
runtimeRoot = await mkdtemp(path.join(os.tmpdir(), "boss-device-heartbeat-noise-"));
process.env.BOSS_RUNTIME_ROOT = runtimeRoot;
process.env.BOSS_STATE_FILE = path.join(runtimeRoot, "boss-state.json");
const [data, events] = await Promise.all([
import("../src/lib/boss-data.ts"),
import("../src/lib/boss-events.ts"),
]);
readState = data.readState;
upsertDeviceHeartbeat = data.upsertDeviceHeartbeat;
subscribeBossEvents = events.subscribeBossEvents;
}
test.after(async () => {
if (runtimeRoot) {
await rm(runtimeRoot, { recursive: true, force: true });
}
});
function buildHeartbeatPayload(deviceId: string, projectCandidates: Array<{
folderName: string;
threadId: string;
threadDisplayName: string;
codexFolderRef: string;
codexThreadRef: string;
lastActiveAt: string;
}>) {
return {
deviceId,
token: `${deviceId}-token`,
name: "Mac Studio",
avatar: "M",
account: "krisolo",
status: "online" as const,
quota5h: 68,
quota7d: 81,
projects: [],
endpoint: "mac://kris.local",
projectCandidates,
};
}
const bossThreadCandidate = {
folderName: "boss",
threadId: "thread-boss-main",
threadDisplayName: "Boss开发主线程",
codexFolderRef: "/Users/kris/code/boss",
codexThreadRef: "thread-boss-main",
lastActiveAt: "2026-04-10T10:00:00.000Z",
};
test("unchanged device heartbeats do not publish conversation refresh events", async () => {
await setup();
const heartbeat = buildHeartbeatPayload("noise-device-a", [bossThreadCandidate]);
await upsertDeviceHeartbeat(heartbeat);
await upsertDeviceHeartbeat(heartbeat);
const primedState = await readState();
const primedDraft = primedState.deviceImportDrafts.find((draft) => draft.deviceId === "noise-device-a");
assert.equal(primedDraft?.status, "applied");
const events: Array<{ event: string; payload: { note?: string; deviceId?: string } }> = [];
const unsubscribe = subscribeBossEvents((event, payload) => {
events.push({ event, payload });
});
await upsertDeviceHeartbeat(heartbeat);
unsubscribe();
assert.deepEqual(events.map((event) => event.event), ["devices.updated"]);
});
test("device heartbeats publish one conversation refresh when import candidates change", async () => {
await setup();
const nextThreadCandidate = {
folderName: "boss",
threadId: "thread-boss-review",
threadDisplayName: "Boss回归线程",
codexFolderRef: "/Users/kris/code/boss",
codexThreadRef: "thread-boss-review",
lastActiveAt: "2026-04-10T10:01:00.000Z",
};
await upsertDeviceHeartbeat(buildHeartbeatPayload("noise-device-b", [bossThreadCandidate]));
await upsertDeviceHeartbeat(buildHeartbeatPayload("noise-device-b", [bossThreadCandidate]));
const events: Array<{ event: string; payload: { note?: string; deviceId?: string } }> = [];
const unsubscribe = subscribeBossEvents((event, payload) => {
events.push({ event, payload });
});
await upsertDeviceHeartbeat(buildHeartbeatPayload("noise-device-b", [bossThreadCandidate, nextThreadCandidate]));
unsubscribe();
assert.deepEqual(
events.map((event) => [event.event, event.payload.deviceId, event.payload.note]),
[
["devices.updated", "noise-device-b", undefined],
["conversation.updated", "noise-device-b", "device_import.updated"],
],
);
});