hermes-office/tests/unit/standupStore.test.ts

113 lines
3.3 KiB
TypeScript

import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import { afterEach, describe, expect, it } from "vitest";
import { loadActiveStandupMeeting } from "@/lib/office/standup/store";
import type { StandupMeetingStore } from "@/lib/office/standup/types";
const makeTempDir = (name: string) => fs.mkdtempSync(path.join(os.tmpdir(), `${name}-`));
const writeStandupStore = (stateDir: string, store: StandupMeetingStore) => {
const storeDir = path.join(stateDir, "claw3d");
fs.mkdirSync(storeDir, { recursive: true });
fs.writeFileSync(
path.join(storeDir, "standup-store.json"),
JSON.stringify(store, null, 2),
"utf8"
);
};
describe("standup store", () => {
const priorStateDir = process.env.OPENCLAW_STATE_DIR;
let tempDir: string | null = null;
afterEach(() => {
process.env.OPENCLAW_STATE_DIR = priorStateDir;
if (tempDir) {
fs.rmSync(tempDir, { recursive: true, force: true });
tempDir = null;
}
});
it("drops stale active gathering meetings on load", () => {
tempDir = makeTempDir("standup-store-stale");
process.env.OPENCLAW_STATE_DIR = tempDir;
const staleIso = new Date(Date.now() - 60 * 60 * 1000).toISOString();
writeStandupStore(tempDir, {
activeMeeting: {
id: "meeting-stale",
trigger: "manual",
phase: "gathering",
scheduledFor: null,
startedAt: staleIso,
updatedAt: staleIso,
completedAt: null,
currentSpeakerAgentId: null,
speakerStartedAt: null,
speakerDurationMs: 8000,
participantOrder: ["main"],
arrivedAgentIds: ["main"],
cards: [],
},
lastMeeting: null,
});
expect(loadActiveStandupMeeting()).toBeNull();
});
it("keeps fresh active gatherings on load", () => {
tempDir = makeTempDir("standup-store-fresh");
process.env.OPENCLAW_STATE_DIR = tempDir;
const freshIso = new Date().toISOString();
writeStandupStore(tempDir, {
activeMeeting: {
id: "meeting-fresh",
trigger: "manual",
phase: "gathering",
scheduledFor: null,
startedAt: freshIso,
updatedAt: freshIso,
completedAt: null,
currentSpeakerAgentId: null,
speakerStartedAt: null,
speakerDurationMs: 8000,
participantOrder: ["main"],
arrivedAgentIds: [],
cards: [],
},
lastMeeting: null,
});
expect(loadActiveStandupMeeting()?.id).toBe("meeting-fresh");
});
it("drops stale gathering meetings even if arrivals refreshed updatedAt", () => {
tempDir = makeTempDir("standup-store-gathering-updated");
process.env.OPENCLAW_STATE_DIR = tempDir;
const staleStartedIso = new Date(Date.now() - 10 * 60 * 1000).toISOString();
const freshUpdatedIso = new Date().toISOString();
writeStandupStore(tempDir, {
activeMeeting: {
id: "meeting-gathering-stale",
trigger: "manual",
phase: "gathering",
scheduledFor: null,
startedAt: staleStartedIso,
updatedAt: freshUpdatedIso,
completedAt: null,
currentSpeakerAgentId: null,
speakerStartedAt: null,
speakerDurationMs: 8000,
participantOrder: ["main"],
arrivedAgentIds: ["main"],
cards: [],
},
lastMeeting: null,
});
expect(loadActiveStandupMeeting()).toBeNull();
});
});