mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-15 12:28:10 +02:00
95 lines
3.0 KiB
TypeScript
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([]);
|
|
});
|
|
});
|