59 lines
3.6 KiB
TypeScript
59 lines
3.6 KiB
TypeScript
import { act, createElement } from "react";
|
|
import { createRoot } from "react-dom/client";
|
|
import { SWRConfig } from "swr";
|
|
import { expect, it, vi } from "vitest";
|
|
import type { AgentApiClient, AgentTopic } from "@/features/agent";
|
|
import { useAgentTopics } from "./use-agent-topics";
|
|
import { WorkbenchSessionProvider } from "./workbench-session-provider";
|
|
|
|
it("reuses theme reads and keeps a late project result out of the personal theme list", async () => {
|
|
const topic = (id: string): AgentTopic => ({ id, name: id, createdAt: "2026-10-22T01:00:00Z", updatedAt: "2026-10-22T01:00:00Z" });
|
|
let finish!: (topics: AgentTopic[]) => void;
|
|
const projectRead = vi.fn(() => new Promise<AgentTopic[]>((resolve) => { finish = resolve; }));
|
|
const personalRead = vi.fn(async () => [topic("personal-theme")]);
|
|
const clients = { project: { listTopics: projectRead }, personal: { listTopics: personalRead } } as unknown as Record<"project" | "personal", AgentApiClient>;
|
|
const root = createRoot(document.createElement("div"));
|
|
const cache = new Map();
|
|
let topics!: ReturnType<typeof useAgentTopics>;
|
|
function Probe({ scope }: { scope: "project" | "personal" }) { topics = useAgentTopics(clients[scope], scope); return null; }
|
|
const render = (scope: "project" | "personal") => root.render(createElement(WorkbenchSessionProvider, null,
|
|
createElement(SWRConfig, { value: { provider: () => cache, dedupingInterval: 0 } }, createElement(Probe, { scope }))));
|
|
try {
|
|
await act(async () => render("project"));
|
|
let pending!: Promise<void>;
|
|
await act(async () => { pending = topics.ensure(); });
|
|
await act(async () => render("personal"));
|
|
await act(async () => { finish([topic("project-theme")]); await pending; });
|
|
expect(topics.topics.map((entry) => entry.id)).toEqual(["personal-theme"]);
|
|
for (let i = 0; i < 10; i++) await act(async () => { await topics.ensure(); });
|
|
expect(projectRead).toHaveBeenCalledTimes(1);
|
|
expect(personalRead).toHaveBeenCalledTimes(1);
|
|
} finally { await act(async () => root.unmount()); }
|
|
});
|
|
|
|
it("keeps a newly created topic selectable when the open menu's older read finishes later", async () => {
|
|
const topic = (id: string): AgentTopic => ({ id, name: id, createdAt: "2026-10-22T01:00:00Z", updatedAt: "2026-10-22T01:00:00Z" });
|
|
let finish!: (topics: AgentTopic[]) => void;
|
|
const client = {
|
|
listTopics: vi.fn(() => new Promise<AgentTopic[]>((resolve) => { finish = resolve; })),
|
|
createTopic: vi.fn(async () => topic("new-topic")),
|
|
} as unknown as AgentApiClient;
|
|
let topics!: ReturnType<typeof useAgentTopics>;
|
|
function Probe() { topics = useAgentTopics(client, "project:slow-read"); return null; }
|
|
const root = createRoot(document.createElement("div"));
|
|
const cache = new Map();
|
|
try {
|
|
await act(async () => root.render(createElement(WorkbenchSessionProvider, null,
|
|
createElement(SWRConfig, { value: { provider: () => cache, dedupingInterval: 0 } }, createElement(Probe)))));
|
|
let reading!: Promise<void>;
|
|
let creating!: Promise<AgentTopic>;
|
|
await act(async () => { reading = topics.ensure(); });
|
|
await act(async () => { creating = topics.create("new-topic"); });
|
|
await act(async () => { finish([topic("existing-topic")]); await reading; await creating; });
|
|
expect(topics.topics.map((entry) => entry.id)).toEqual(["existing-topic", "new-topic"]);
|
|
await act(async () => { await topics.ensure(); });
|
|
expect(topics.topics.map((entry) => entry.id)).toEqual(["existing-topic", "new-topic"]);
|
|
expect(client.listTopics).toHaveBeenCalledTimes(1);
|
|
} finally { await act(async () => root.unmount()); }
|
|
});
|