// @vitest-environment jsdom // // The conversation list as a keyboard list (E11 S5): `j`/`k` walk the conversations and Enter opens // the one the row's name button opens — not the pop-out button beside it. The live query, the key // state and the thread are stubbed: the list itself is what is under test. import { afterEach, describe, expect, it, vi } from "vitest"; import { act, cleanup, render, screen } from "@testing-library/react"; vi.mock("react-i18next", async (importOriginal) => { const actual = await importOriginal(); return { ...actual, useTranslation: () => ({ i18n: { language: "en" }, t: (key: string) => key }), }; }); const conversation = (id: number, name: string) => ({ partner: { id, name, avatar_url: null }, last_message: { kind: "system", body: `hello from ${name}`, created_at: "2026-09-13T00:00:00Z" }, unread: 0, }); const items = [conversation(0, "Siftlode"), conversation(7, "Anna"), conversation(9, "Bence")]; vi.mock("../lib/useLiveQuery", () => ({ useLiveQuery: () => ({ data: { items }, isError: false, isLoading: false, refetch: () => {} }), })); vi.mock("../lib/messaging", () => ({ SYSTEM_ID: 0, POLL_MS: 20000, partnerPub: async () => "", useKeyState: () => "ready", })); const openChat = vi.fn(); vi.mock("../lib/chatDock", () => ({ openChat: (...a: unknown[]) => openChat(...a) })); vi.mock("./ChatThread", () => ({ default: ({ partnerId }: { partnerId: number }) =>
{partnerId}
, })); import Messages from "./Messages"; afterEach(() => { cleanup(); history.replaceState(null, ""); }); function press(key: string) { act(() => { (document.activeElement ?? document.body).dispatchEvent( new KeyboardEvent("keydown", { key, bubbles: true, cancelable: true }), ); }); } describe("Messages · the conversation list is a keyboard list", () => { it("walks the conversations with j/k and opens the focused one on Enter", () => { render(); const focusedRow = () => document.activeElement?.getAttribute("data-nav-index"); press("j"); press("j"); press("j"); expect(focusedRow()).toBe("2"); expect(document.activeElement?.textContent).toContain("Bence"); press("k"); expect(focusedRow()).toBe("1"); expect(document.activeElement?.textContent).toContain("Anna"); press("Enter"); expect(screen.getByTestId("thread").textContent).toBe("7"); expect(openChat).not.toHaveBeenCalled(); }); });