import { act, fireEvent, render, screen } from "@testing-library/react"; import { MOBILE_QUERY } from "@/lib/device"; import { getFeaturedProjects } from "@/lib/portfolio-data"; import { ProjectReel } from "./ProjectReel"; import { ShowcaseProvider, useShowcaseOpen } from "./ShowcaseProvider"; import { PINNED_QUERY } from "./useShowcaseMedia"; /* * A vitrine fixa e a janela ampliada (código e CSS) chegam sob demanda: o módulo só é carregado quando alguém precisa * dele. Aqui os módulos pesados são trocados por dublês que contam quantas vezes foram carregados, e o React.lazy é o * de verdade (os outros testes de showcase o trocam por componentes síncronos). A fábrica de cada dublê roda uma vez * por arquivo, na primeira importação: os testes seguem esta ordem (celular, janela ampliada, desktop) e a contagem * acumula de um para o outro. */ const mockLoads = { pinned: 0, lightbox: 0 }; jest.mock("./PinnedReel", () => { mockLoads.pinned += 1; return { __esModule: true, default: ({ items }: { items: unknown[] }) => (
{items.length} projetos fixos
), }; }); jest.mock("./ProjectLightbox", () => { mockLoads.lightbox += 1; return { ProjectLightbox: ({ index }: { index: number }) => (
aberto:{index}
), }; }); jest.mock("@/app/hooks/useReducedMotion", () => ({ useReducedMotion: () => false, })); const projects = getFeaturedProjects(null); const originalMatchMedia = window.matchMedia; function mockViewport({ phone }: { phone: boolean }) { window.matchMedia = jest.fn().mockImplementation((query: string) => ({ matches: (query === MOBILE_QUERY && phone) || (query === PINNED_QUERY && !phone), media: query, addEventListener() {}, removeEventListener() {}, })); } afterEach(() => { window.matchMedia = originalMatchMedia; }); function Opener() { const open = useShowcaseOpen(); return ( ); } describe("carregamento sob demanda", () => { it("1. on a phone nothing heavy is loaded: the list is all there is, and the window waits for a click", async () => { mockViewport({ phone: true }); render( , ); await act(async () => { await Promise.resolve(); }); expect(mockLoads).toEqual({ pinned: 0, lightbox: 0 }); expect(screen.queryByTestId("pinned-reel")).toBeNull(); expect( screen.getByRole("region", { name: "Projetos de clientes" }), ).toBeInTheDocument(); }); it("2. the enlarged window is loaded when a project is enlarged, and only then", async () => { mockViewport({ phone: true }); render( , ); expect(mockLoads.lightbox).toBe(0); fireEvent.click(screen.getByRole("button", { name: "ampliar" })); expect( await screen.findByRole("dialog", { name: "ampliado" }), ).toBeInTheDocument(); expect(mockLoads.lightbox).toBe(1); expect(mockLoads.pinned).toBe(0); }); it("3. the pinned reel is loaded where it fits, holding the place with a block of the same height until it arrives", async () => { mockViewport({ phone: false }); const { container } = render( , ); // enquanto o pacote chega: o bloco reservado (com a conta da altura), não uma página que encolhe const hold = container.querySelector(".ds-reel-placeholder"); expect(hold).not.toBeNull(); expect(hold).toHaveAttribute("aria-hidden", "true"); expect((hold as HTMLElement).style.getPropertyValue("--reel-sum")).not.toBe( "", ); expect(screen.queryByTestId("pinned-reel")).toBeNull(); expect(await screen.findByTestId("pinned-reel")).toBeInTheDocument(); expect(mockLoads.pinned).toBe(1); expect(container.querySelector(".ds-reel-placeholder")).toBeNull(); }); });