import { act, fireEvent, render, screen } from "@testing-library/react";
import { beforeEach } from "vitest";
import { useSessionStore } from "../store/sessionStore";
import { CentralStatus } from "./CentralStatus";
beforeEach(() => useSessionStore.getState().resetSession());
function setScrollGeometry(
element: HTMLElement,
values: { scrollHeight: number; clientHeight: number; scrollTop: number },
) {
Object.defineProperties(element, {
scrollHeight: { configurable: true, value: values.scrollHeight },
clientHeight: { configurable: true, value: values.clientHeight },
scrollTop: { configurable: true, writable: true, value: values.scrollTop },
});
}
test("renders only the chronological assistant transcript log while working", () => {
useSessionStore.setState({
lastUserEntry: { kind: "input", text: "how many patients?" },
stepMessages: [{ level: "warning", text: "Searching the schema…" }],
transcript: [
{ role: "assistant", text: "First line\n\nSecond line" },
{ role: "assistant", text: "Third line" },
],
});
render();
const log = screen.getByRole("log", { name: "Live model activity" });
expect(log).toHaveTextContent("First line");
expect(log).toHaveTextContent("Second line");
expect(log).toHaveTextContent("Third line");
expect(log).toHaveClass("max-h-28", "overflow-y-auto");
expect(screen.queryByText("how many patients?")).not.toBeInTheDocument();
expect(screen.queryByText("Searching the schema…")).not.toBeInTheDocument();
expect(screen.queryByRole("status")).not.toBeInTheDocument();
expect(screen.queryByText(/\d+s/)).not.toBeInTheDocument();
});
test("wraps live log lines instead of truncating them", () => {
useSessionStore.setState({
transcript: [{ role: "assistant", text: "a_very_long_model_activity_line" }],
});
render();
expect(screen.getByText("a_very_long_model_activity_line")).toHaveClass(
"whitespace-pre-wrap",
"break-words",
);
expect(screen.getByText("a_very_long_model_activity_line")).not.toHaveClass("truncate");
});
test.each([
{ working: false, transcript: [{ role: "assistant" as const, text: "hidden" }] },
{ working: true, transcript: [] },
{ working: true, transcript: [{ role: "assistant" as const, text: " \n " }] },
])("renders nothing without active non-blank transcript content", ({ working, transcript }) => {
useSessionStore.setState({ transcript });
const { container } = render();
expect(container).toBeEmptyDOMElement();
});
test("bottom-follows appended transcript text only while near the bottom", () => {
useSessionStore.setState({ transcript: [{ role: "assistant", text: "First" }] });
render();
const log = screen.getByRole("log", { name: "Live model activity" });
setScrollGeometry(log, { scrollHeight: 400, clientHeight: 100, scrollTop: 300 });
act(() => useSessionStore.getState().applyEvent({ type: "text_delta", text: " second" }));
expect(log.scrollTop).toBe(400);
});
test("preserves manual live-log scroll position away from the bottom", () => {
useSessionStore.setState({ transcript: [{ role: "assistant", text: "First" }] });
render();
const log = screen.getByRole("log", { name: "Live model activity" });
setScrollGeometry(log, { scrollHeight: 400, clientHeight: 100, scrollTop: 100 });
fireEvent.scroll(log);
act(() => useSessionStore.getState().applyEvent({ type: "text_delta", text: " second" }));
expect(log.scrollTop).toBe(100);
});