import { render, screen, within } from "@testing-library/react"; import { buttonLabels, clientCasesForListing, labCases, } from "@/lib/site-content"; import { getCaseMedia } from "./_components/case-media"; import CasesPage from "./page"; /** * Teste de caminhos-base da lista de cases de cliente em CasesPage: * o caminho "case de cliente sem captura gravada" (a página principal só vê cases com captura). */ jest.mock("./_components/case-media", () => { const actual = jest.requireActual("./_components/case-media"); return { ...actual, getCaseMedia: jest.fn(actual.getCaseMedia) }; }); const actualGetCaseMedia = jest.requireActual< typeof import("./_components/case-media") >("./_components/case-media").getCaseMedia; const mockedGetCaseMedia = jest.mocked(getCaseMedia); afterEach(() => { mockedGetCaseMedia.mockImplementation(actualGetCaseMedia); }); function clientCard(container: HTMLElement, id: string) { const card = container .querySelector(`a[href="/cases/${id}"]`) ?.closest("article"); if (!card) throw new Error(`Missing client card ${id}`); return card; } describe("CasesPage: cases de cliente", () => { it("path: client case without a desktop capture -> card keeps text and links but no cover", () => { const [withoutCapture, withCapture] = clientCasesForListing; mockedGetCaseMedia.mockImplementation((id, device) => id === withoutCapture.id ? undefined : actualGetCaseMedia(id, device), ); const { container } = render(); const bare = clientCard(container, withoutCapture.id); expect(bare.querySelector(".ds-bframe")).toBeNull(); expect(bare.querySelector("img")).toBeNull(); expect(bare.querySelector("a[aria-hidden='true']")).toBeNull(); expect(within(bare).getByText(withoutCapture.headline)).toBeVisible(); expect( within(bare).getByRole("link", { name: `${buttonLabels.case} ${withoutCapture.title}`, }), ).toHaveAttribute("href", `/cases/${withoutCapture.id}`); // os outros cases de cliente continuam com a capa const covered = clientCard(container, withCapture.id); expect(covered.querySelector(".ds-bframe img")).toHaveAttribute( "alt", `Captura de tela do site ${withCapture.title}`, ); }); it("path: every case -> one 'Ver case' button, named after its project, and no 'Ver o case' or 'Ler case'", () => { render(); const buttons = screen.getAllByRole("link", { name: /^Ver case / }); expect(buttons).toHaveLength( clientCasesForListing.length + labCases.length, ); for (const link of buttons) { expect(link.textContent?.startsWith(buttonLabels.case)).toBe(true); } expect( screen.queryByRole("link", { name: /Ver o case|Ler case|Ver o projeto/ }), ).toBeNull(); }); it("path: an odd number of client cases -> the last card takes the whole row on wide screens, so the grid ends with no empty cell", () => { const { container } = render(); const wide = clientCasesForListing.map((caseStudy) => clientCard(container, caseStudy.id).className.includes( "min-[1025px]:col-span-2", ), ); const odd = clientCasesForListing.length % 2 === 1; expect(wide).toEqual( clientCasesForListing.map( (_, index) => odd && index === clientCasesForListing.length - 1, ), ); }); it("path: contact -> 'Chamar no WhatsApp', and the list of clients follows the showcase: the SEV first, then Lavação 047, SC Plus, AS Serviços and Julia Beauty", () => { const { container } = render(); expect( screen.getByRole("link", { name: buttonLabels.whatsapp }), ).toHaveAttribute("href", expect.stringContaining("https://wa.me/")); const clientTitles = Array.from( container.querySelectorAll("#cases-clientes ~ div article .ds-kicker"), ).map((kicker) => kicker.textContent); expect(clientTitles).toEqual( clientCasesForListing.map(({ title }) => title), ); expect(clientTitles).toEqual([ "SEV Moda Íntima", "Lavação 047", "SC Plus Aquicultura", "AS Serviços", "Julia Beauty", ]); // um botão de contato só na página: o do fecho expect( screen.getAllByRole("link", { name: buttonLabels.whatsapp }), ).toHaveLength(1); }); }); describe("CasesPage: topo sem mosaico", () => { it("path: captures found -> no poster mosaic (the cards below already carry the covers), only the block piece beside the text, a lower strip, no 'Veja o que já' twice", () => { const { container } = render(); const hero = container.querySelector("section"); const images = hero?.querySelectorAll("img") ?? []; expect(images).toHaveLength(1); expect(images[0].getAttribute("src")).toContain("estado-tela.webp"); // decorativa e só de 1024 px em diante expect(images[0].closest('[aria-hidden="true"]')).toHaveClass( "hidden", "lg:block", ); expect(hero?.className).toContain("md:!pb-sp-12"); // o título e o subtítulo não repetem a mesma frase const heading = within(hero as HTMLElement).getByRole("heading", { level: 1, }); expect(heading).toHaveTextContent("Veja o que já fiz para empresas."); expect(hero?.textContent?.match(/Veja o que já/g)).toHaveLength(1); expect(hero?.textContent).not.toMatch(/\bdireto\b/); }); it("path: no capture for the other clients -> still no mosaic, and the first card cover takes the priority", () => { mockedGetCaseMedia.mockImplementation((id, device) => id === clientCasesForListing[0].id ? actualGetCaseMedia(id, device) : undefined, ); const { container } = render(); const hero = container.querySelector("section"); expect(hero?.querySelectorAll("img")).toHaveLength(1); const firstCover = clientCard( container, clientCasesForListing[0].id, ).querySelector(".ds-bframe img"); expect(firstCover).toHaveAttribute("loading", "eager"); expect(firstCover).toHaveAttribute("fetchpriority", "high"); }); }); describe("CasesPage: prioridade da capa do primeiro cartão", () => { it("path: no mosaic -> the first card cover is the page's biggest image, so it loads at once with high priority; the others stay lazy", () => { const { container } = render(); const [first, ...others] = clientCasesForListing; const firstCover = clientCard(container, first.id).querySelector( ".ds-bframe img", ); expect(firstCover).toHaveAttribute("loading", "eager"); expect(firstCover).toHaveAttribute("fetchpriority", "high"); for (const { id } of others) { const cover = clientCard(container, id).querySelector(".ds-bframe img"); expect(cover).toHaveAttribute("loading", "lazy"); expect(cover).not.toHaveAttribute("fetchpriority"); } }); });