import { render, screen, within } from "@testing-library/react"; import { getCaseMedia } from "@/app/cases/_components/case-media"; import { getShowcaseAssets } from "@/lib/project-showcase"; import { caseStudies, isClientCase } from "@/lib/site-content"; import { ServiceRelatedCases } from "./ServiceRelatedCases"; /** * Testes de caminhos-base de ServiceRelatedCases, direto no componente: * sem case nem experiência, só a experiência, case sem frase de relação, case de laboratório, * case sem captura e case sem site no ar. A existência dos arquivos em disco é simulada em getCaseMedia. */ jest.mock("@/app/cases/_components/case-media", () => ({ getCaseMedia: jest.fn(), })); const mockedGetCaseMedia = jest.mocked(getCaseMedia); function getCase(id: string) { const caseStudy = caseStudies.find((item) => item.id === id); if (!caseStudy) throw new Error(`Missing case ${id}`); return caseStudy; } function withDesktopCapture() { mockedGetCaseMedia.mockImplementation((id, device) => device === "desktop" ? getShowcaseAssets(id, device) : undefined, ); } const sev = getCase("sev-modaintima"); // cliente, com site no ar const asServicos = getCase("as-servicos"); // cliente, sem site público const twins = getCase("twins-lab"); // laboratório, sem site público /** Título com algum case de cliente; sem cliente (só experiência ou projeto próprio), é "Como eu trabalho nisso". */ const TITLE = "Onde já apliquei isso"; const TITLE_WITHOUT_CLIENT = "Como eu trabalho nisso"; const NOTE = "Texto de experiência de teste."; beforeEach(() => { mockedGetCaseMedia.mockReturnValue(undefined); }); afterEach(() => { mockedGetCaseMedia.mockReset(); }); describe("ServiceRelatedCases", () => { it("path: no case and no experience note -> renders nothing", () => { const { container } = render( , ); expect(container).toBeEmptyDOMElement(); }); it("path: no case but an experience note -> keeps the block with the note and no case card", () => { const { container } = render( , ); expect( screen.getByRole("heading", { level: 2, name: TITLE_WITHOUT_CLIENT }), ).toBeVisible(); expect(screen.queryByRole("heading", { name: TITLE })).toBeNull(); expect(screen.getByText(NOTE)).toBeVisible(); expect(container.querySelectorAll("article")).toHaveLength(0); expect(screen.queryByRole("link", { name: /^Ver case/ })).toBeNull(); }); it("path: cases and no experience note (main path) -> one card per case, no 'Na prática' paragraph", () => { withDesktopCapture(); const { container } = render( , ); expect( screen.getByRole("heading", { level: 2, name: TITLE }), ).toBeVisible(); expect(screen.queryByText("Na prática:")).toBeNull(); const card = container.querySelector("article"); if (!card) throw new Error("Missing case card"); expect(within(card).getByText(sev.headline)).toBeVisible(); // case de cliente: o kicker é só o nome const kicker = card.querySelector(".ds-kicker"); expect(kicker).toHaveTextContent(new RegExp(`^${sev.title}$`)); expect(within(card).queryByText(/Projeto próprio/)).toBeNull(); expect(within(card).getByText("Frase de relação do SEV.")).toBeVisible(); expect( within(card).getByRole("link", { name: `Ver case ${sev.title}` }), ).toHaveAttribute("href", `/cases/${sev.id}`); expect( within(card).getByRole("link", { name: `Abrir o site ${sev.title}` }), ).toHaveAttribute("href", sev.demoUrl); }); it("path: cases and an experience note -> the note comes first, in text only, with no link", () => { render( , ); const note = screen.getByText(NOTE, { exact: false }); expect(screen.getByText("Na prática:")).toBeVisible(); expect(note.closest("a")).toBeNull(); expect(note.querySelector("a")).toBeNull(); expect( note.compareDocumentPosition( screen.getByRole("link", { name: `Ver case ${sev.title}` }), ) & Node.DOCUMENT_POSITION_FOLLOWING, ).toBeTruthy(); }); it("path: case with a desktop capture -> cover link with the poster, hidden from assistive tech", () => { withDesktopCapture(); const { container } = render( , ); const coverLink = container.querySelector( `article a[aria-hidden="true"][href="/cases/${sev.id}"]`, ); expect(coverLink).not.toBeNull(); expect(coverLink).toHaveAttribute("tabindex", "-1"); expect(coverLink?.querySelector(".ds-bframe img")).toHaveAttribute( "alt", `Captura de tela do site ${sev.title}`, ); }); it("path: case without a desktop capture -> no cover link, text and buttons stay", () => { const { container } = render( , ); expect(container.querySelector("a[aria-hidden='true']")).toBeNull(); expect(container.querySelector(".ds-bframe")).toBeNull(); expect(container.querySelector("img")).toBeNull(); expect( screen.getByRole("link", { name: `Ver case ${sev.title}` }), ).toBeVisible(); }); it("path: laboratory case -> kicker marks it as 'Projeto próprio'", () => { expect(isClientCase(twins)).toBe(false); render( , ); expect(screen.getByText(`${twins.title} · Projeto próprio`)).toBeVisible(); // só projeto próprio, sem cliente: o título não promete trabalho aplicado para alguém expect( screen.getByRole("heading", { level: 2, name: TITLE_WITHOUT_CLIENT }), ).toBeVisible(); }); it("path: case whose cover already opens the page -> it gets no card at all (the cover caption cites it), the others keep theirs", () => { withDesktopCapture(); const lavacao = getCase("lavacao-047"); const { container } = render( , ); expect(container.querySelectorAll("article")).toHaveLength(1); expect( container.querySelector(`a[href="/cases/${lavacao.id}"]`), ).toBeNull(); expect(container.textContent).not.toContain(lavacao.title); expect( container.querySelector(`a[aria-hidden="true"][href="/cases/${sev.id}"]`), ).not.toBeNull(); expect( screen.getByRole("link", { name: `Ver case ${sev.title}` }), ).toBeVisible(); }); it("path: the cover case is the only one -> no cases to list and no experience note -> renders nothing", () => { const { container } = render( , ); expect(container).toBeEmptyDOMElement(); }); it("path: no relevance sentence for the case -> falls back to the case summary", () => { render(); const card = screen.getByRole("heading", { level: 3 }).closest("article"); expect(card).not.toBeNull(); expect(within(card as HTMLElement).getByText(sev.summary)).toBeVisible(); }); it("path: case without a public site -> no 'Abrir o site' link", () => { expect(asServicos.demoUrl).toBeNull(); render( , ); expect( screen.getByRole("link", { name: `Ver case ${asServicos.title}` }), ).toBeVisible(); expect(screen.queryByRole("link", { name: /^Abrir o site/ })).toBeNull(); }); });