Files
next-tjwater-frontend/src/features/agent/session-state/use-answer-view-state.test.tsx
T
jiang c0e4231b83
Generic Container CI/CD / test-build-publish (push) Successful in 1m52s
Frontend CI/CD / build-test-publish-and-deploy (push) Successful in 1m52s
feat: expand intelligent investigation workspace
2026-10-30 17:30:19 +08:00

33 lines
2.4 KiB
TypeScript

import { act } from "react";
import { createRoot } from "react-dom/client";
import { expect, it, vi } from "vitest";
import type { Spec } from "@json-render/core";
import type { AnswerViewStateRecord, AnswerViewStateWrite } from "../api/answer-view-state";
import { AnswerViewStateScope } from "./answer-view-state-scope";
import { useAnswerViewState } from "./use-answer-view-state";
it("keeps rerenders debounced, flushes a switched session and retains drafts across component remounts", async () => {
vi.useFakeTimers();
const root = createRoot(document.createElement("div"));
const spec: Spec = { root: "form", elements: { form: { type: "FollowUpForm", children: [], props: { fields: [{ name: "note", kind: "text" }] } } } };
const remote = (session: string): AnswerViewStateRecord => ({ version: "answer-view-state@1", message_id: "message", block_id: "block", revision: 0,
schema_digest: "digest", updated_at: null, nodes: { form: { type: "FollowUpForm", values: { note: session } } }, block: { evidenceFilter: "all" } });
const client = { getAnswerViewState: vi.fn(async (session: string) => remote(session)),
putAnswerViewState: vi.fn(async (session: string, state: AnswerViewStateWrite) => ({ ...remote(session), revision: state.expected_revision + 1, nodes: state.nodes })) };
const scope = new AnswerViewStateScope("actor:project", client);
let current!: ReturnType<typeof useAnswerViewState>;
function Probe({ session }: { session: string }) { current = useAnswerViewState(scope, session, "message", "block", spec); return null; }
try {
await act(async () => root.render(<Probe session="first" />));
await act(async () => current.update({ ...current.state, nodes: { form: { type: "FollowUpForm", values: { note: "draft" } } } }, ["/nodes/form/values/note"]));
await act(async () => root.render(<Probe session="first" />));
expect(client.putAnswerViewState).not.toHaveBeenCalled();
await act(async () => root.render(<Probe session="second" />));
expect(client.putAnswerViewState.mock.calls[0][0]).toBe("first");
expect(current.state.nodes.form).toMatchObject({ values: { note: "second" } });
await act(async () => root.render(<Probe session="first" />));
expect(current.state.nodes.form).toMatchObject({ values: { note: "draft" } });
expect(client.getAnswerViewState).toHaveBeenCalledTimes(2);
} finally { await act(async () => root.unmount()); scope.dispose(); vi.useRealTimers(); }
});