import { afterEach, describe, expect, it, rs } from "@rstest/core"; import { cleanup, render } from "@testing-library/react"; import type { PropsWithChildren } from "react"; import { ProjectThreadsSection } from "@/components/workspace/projects/project-threads-section"; import { I18nProvider } from "@/core/i18n/context"; import type { ProjectThreadsQueryResult } from "@/core/projects"; import type { ProjectThread } from "@/core/projects/types"; // Keep the row links inert under happy-dom; only the href wiring matters. rs.mock("next/link", () => { const MockLink = ({ href, children, }: { href: string; children: React.ReactNode; }) => {children}; return { default: MockLink }; }); function makeThread(id: string, title: string): ProjectThread { return { thread_id: id, display_name: title, metadata: {}, created_at: "2026-01-01T00:00:00Z", updated_at: "2026-01-02T00:00:00Z", }; } function makeQuery(threads: ProjectThread[]): ProjectThreadsQueryResult { return { data: { pages: [threads], pageParams: [0] }, isError: false, isLoading: false, hasNextPage: false, isFetchingNextPage: false, fetchNextPage: rs.fn(), } as unknown as ProjectThreadsQueryResult; } function Wrapper({ children }: PropsWithChildren) { return {children}; } afterEach(() => { cleanup(); }); describe("ProjectThreadsSection", () => { it("renders a divider on every row except the final one", () => { const { container } = render( , ); const links = container.querySelectorAll("a"); expect(links).toHaveLength(3); expect(links[0]?.href).toContain("/workspace/chats/t-1"); const rowDivs = [...links].map((link) => link.firstElementChild); expect(rowDivs[0]?.classList.contains("border-b")).toBe(true); expect(rowDivs[1]?.classList.contains("border-b")).toBe(true); // Only the final data row drops the divider — the check must hold even // when virtualization mounts just a window of rows. expect(rowDivs[2]?.classList.contains("border-b")).toBe(false); }); it("shows the untitled fallback and the load-more button for a partial page", () => { const { container } = render( , ); expect(container.textContent).toContain("Untitled"); expect( container.querySelector('[data-testid="project-threads-load-more"]'), ).not.toBeNull(); }); });