import { afterEach, expect, test, vi } from "vitest"; import { screen, within } from "@testing-library/react"; import { Route, Routes } from "react-router-dom"; import { renderApp } from "../test/render"; import { VocabulariesPage } from "./vocabularies-page"; import { VocabularyTerms } from "./vocabulary-terms"; import { SelectVocabularyPrompt } from "./select-vocabulary-prompt"; function setViewport(wide: boolean) { Object.defineProperty(window, "matchMedia", { value: (query: string): MediaQueryList => ({ matches: wide && query === "(min-width: 1024px)", media: query, onchange: null, addEventListener: () => {}, removeEventListener: () => {}, addListener: () => {}, removeListener: () => {}, dispatchEvent: () => false, }) as MediaQueryList, writable: true, }); } afterEach(() => vi.restoreAllMocks()); function tree() { return ( }> } /> } /> ); } test("narrow: a selected vocabulary's detail renders in a portaled drawer", async () => { setViewport(false); renderApp(tree(), { route: "/vocabularies/v-material" }); const body = within(document.body); expect( await body.findByRole("button", { name: /close detail/i }, { timeout: 5000 }), ).toBeInTheDocument(); }); test("wide: a selected vocabulary renders inline, with no detail drawer", async () => { setViewport(true); renderApp(tree(), { route: "/vocabularies/v-material" }); // VocabularyTerms renders its "Terms" caption inline in the right pane. await screen.findByText(/terms/i); expect(screen.queryByRole("button", { name: /close detail/i })).toBeNull(); });