Files
PaperClipAI/ui/src/lib/recent-tasks.test.ts
T

95 lines
3.0 KiB
TypeScript

// @vitest-environment jsdom
import { beforeEach, describe, expect, it, vi } from "vitest";
import {
RECENT_TASKS_LIMIT,
RECENT_TASKS_UPDATED_EVENT,
getRecentTasksStorageKey,
pruneRecentTasks,
readRecentTasks,
recordRecentTask,
updateRecentTaskSnapshots,
} from "./recent-tasks";
const issue = (id: string, companyId = "company-1") => ({
id,
companyId,
title: `Task ${id}`,
identifier: `PAP-${id}`,
status: "todo" as const,
updatedAt: new Date(0),
});
describe("recent task persistence", () => {
beforeEach(() => window.localStorage.clear());
it("is account and company scoped", () => {
expect(getRecentTasksStorageKey("company-1", "user-1")).not.toBe(
getRecentTasksStorageKey("company-1", "user-2"),
);
expect(getRecentTasksStorageKey("company-1", "user-1")).not.toBe(
getRecentTasksStorageKey("company-2", "user-1"),
);
});
it("deduplicates, only promotes newer activity, and stays bounded", () => {
for (let index = 0; index < RECENT_TASKS_LIMIT + 2; index += 1) {
recordRecentTask(issue(String(index)), "user-1", index);
}
recordRecentTask(issue("4"), "user-1", 4);
let entries = readRecentTasks(getRecentTasksStorageKey("company-1", "user-1"), "company-1");
expect(entries[0]?.id).toBe("6");
recordRecentTask(issue("4"), "user-1", 99);
entries = readRecentTasks(getRecentTasksStorageKey("company-1", "user-1"), "company-1");
expect(entries).toHaveLength(RECENT_TASKS_LIMIT);
expect(entries[0]?.id).toBe("4");
expect(entries.filter((entry) => entry.id === "4")).toHaveLength(1);
});
it("publishes same-tab updates", () => {
const listener = vi.fn();
window.addEventListener(RECENT_TASKS_UPDATED_EVENT, listener);
recordRecentTask(issue("1"), "user-1");
expect(listener).toHaveBeenCalledOnce();
listener.mockClear();
recordRecentTask(issue("1"), "user-1");
expect(listener).not.toHaveBeenCalled();
window.removeEventListener(RECENT_TASKS_UPDATED_EVENT, listener);
});
it("prunes unavailable tasks and refreshes stored snapshots", () => {
recordRecentTask(issue("1"), "user-1", 1);
recordRecentTask(issue("2"), "user-1", 2);
const storageKey = getRecentTasksStorageKey("company-1", "user-1");
updateRecentTaskSnapshots(storageKey, "company-1", [{
...issue("2"),
title: "Updated task",
status: "in_progress",
updatedAt: new Date(3),
}]);
pruneRecentTasks(storageKey, "company-1", new Set(["1"]));
expect(readRecentTasks(storageKey, "company-1")).toEqual([
expect.objectContaining({
id: "2",
title: "Updated task",
status: "in_progress",
recordedAt: 3,
}),
]);
});
it("ignores malformed and cross-company entries", () => {
const storageKey = getRecentTasksStorageKey("company-1", "user-1");
window.localStorage.setItem(storageKey, JSON.stringify([
issue("other", "company-2"),
{ nonsense: true },
]));
expect(readRecentTasks(storageKey, "company-1")).toEqual([]);
});
});