81 lines
3.5 KiB
TypeScript
81 lines
3.5 KiB
TypeScript
import { render, screen } from "@testing-library/react";
|
|
import userEvent from "@testing-library/user-event";
|
|
import { beforeEach, vi } from "vitest";
|
|
import { useSessionStore } from "../store/sessionStore";
|
|
import { ModelActivityPanel } from "./ModelActivityPanel";
|
|
|
|
beforeEach(() => useSessionStore.getState().resetSession());
|
|
|
|
test("renders the streamed model activity", () => {
|
|
useSessionStore.getState().applyEvent({ type: "activity_delta", text: "Promoting table dim_patient." });
|
|
render(<ModelActivityPanel onClose={vi.fn()} />);
|
|
expect(screen.getByText(/Promoting table dim_patient/)).toBeInTheDocument();
|
|
});
|
|
|
|
test("does not treat final assistant text as model reasoning", () => {
|
|
useSessionStore.getState().applyEvent({ type: "text_delta", text: "Final answer" });
|
|
render(<ModelActivityPanel onClose={vi.fn()} />);
|
|
|
|
expect(screen.queryByText("Final answer")).not.toBeInTheDocument();
|
|
expect(screen.getByText("No activity yet.")).toBeInTheDocument();
|
|
});
|
|
|
|
test("renders markdown emphasis instead of literal asterisks", () => {
|
|
useSessionStore.getState().applyEvent({ type: "activity_delta", text: "Chiarimento su **fibrillazione atriale**." });
|
|
render(<ModelActivityPanel onClose={vi.fn()} />);
|
|
expect(screen.getByText("fibrillazione atriale").tagName).toBe("STRONG");
|
|
});
|
|
|
|
test("close button calls onClose", async () => {
|
|
const onClose = vi.fn();
|
|
render(<ModelActivityPanel onClose={onClose} />);
|
|
await userEvent.click(screen.getByRole("button", { name: /close/i }));
|
|
expect(onClose).toHaveBeenCalled();
|
|
});
|
|
|
|
const EIGHT = ["para-01", "para-02", "para-03", "para-04", "para-05", "para-06", "para-07", "para-08"].join("\n\n");
|
|
|
|
test("collapsed shows only the last 5 paragraphs of the model-stream tail", () => {
|
|
useSessionStore.getState().applyEvent({ type: "activity_delta", text: EIGHT });
|
|
render(<ModelActivityPanel onClose={vi.fn()} />);
|
|
expect(screen.getByText("para-08")).toBeInTheDocument();
|
|
expect(screen.getByText("para-04")).toBeInTheDocument();
|
|
expect(screen.queryByText("para-03")).not.toBeInTheDocument();
|
|
expect(screen.queryByText("para-01")).not.toBeInTheDocument();
|
|
});
|
|
|
|
test("expanding reveals the full stream", async () => {
|
|
useSessionStore.getState().applyEvent({ type: "activity_delta", text: EIGHT });
|
|
render(<ModelActivityPanel onClose={vi.fn()} />);
|
|
await userEvent.click(screen.getByRole("button", { name: /show more/i }));
|
|
expect(screen.getByText("para-01")).toBeInTheDocument();
|
|
});
|
|
|
|
test("paragraphs stay separated as distinct blocks", () => {
|
|
useSessionStore
|
|
.getState()
|
|
.applyEvent({ type: "activity_delta", text: "Primo paragrafo.\n\nSecondo paragrafo." });
|
|
render(<ModelActivityPanel onClose={vi.fn()} />);
|
|
const first = screen.getByText("Primo paragrafo.");
|
|
const second = screen.getByText("Secondo paragrafo.");
|
|
expect(first.tagName).toBe("P");
|
|
expect(second.tagName).toBe("P");
|
|
expect(first).not.toBe(second);
|
|
});
|
|
|
|
|
|
test("separates activity updates concatenated after sentence punctuation", () => {
|
|
useSessionStore.getState().applyEvent({
|
|
type: "activity_delta",
|
|
text: "Ambiguità principale risolta.Finestra temporale risolta.Terza ambiguità risolta.",
|
|
});
|
|
render(<ModelActivityPanel onClose={vi.fn()} />);
|
|
|
|
const first = screen.getByText("Ambiguità principale risolta.");
|
|
const second = screen.getByText("Finestra temporale risolta.");
|
|
const third = screen.getByText("Terza ambiguità risolta.");
|
|
expect(first.tagName).toBe("P");
|
|
expect(second.tagName).toBe("P");
|
|
expect(third.tagName).toBe("P");
|
|
});
|