import { getCaseMedia } from "@/app/cases/_components/case-media"; import { getShowcaseAssets } from "@/lib/project-showcase"; import { getServicePage, type ServicePageContent } from "@/lib/site-content"; import { resolveServiceHero, splitServiceCases } from "./service-page"; /** * Caminhos-base de resolveServiceHero (CC 6) e splitServiceCases (CC 3) que service-page.test.ts não separa, todos com um * serviço montado à mão, porque nenhum serviço real reúne essas combinações: * - capa e esquema ao mesmo tempo: a capa vale e o esquema some; sem captura da capa, o esquema entra no lugar; * - os cases do bloco menor não contam para o botão "Ver projetos parecidos" (ele leva a "Onde já apliquei isso"); * - todos os cases no bloco menor: nenhum cartão, e o bloco leva todos, na ordem de `relatedCaseIds`. * A existência das capturas em disco é simulada em getCaseMedia. */ jest.mock("@/app/cases/_components/case-media", () => ({ getCaseMedia: jest.fn(), })); const mockedGetCaseMedia = jest.mocked(getCaseMedia); function service(overrides: Partial): ServicePageContent { const base = getServicePage("consultoria-nextjs"); if (!base) throw new Error("Missing service consultoria-nextjs"); return { ...base, heroCase: undefined, diagram: undefined, alsoCases: undefined, ...overrides, }; } /** Só as capturas listadas existem no disco. */ function capturesOnDisk(captures: readonly (readonly [string, string])[]) { mockedGetCaseMedia.mockImplementation((id, device) => captures.some( ([knownId, knownDevice]) => knownId === id && knownDevice === device, ) ? getShowcaseAssets(id, device) : undefined, ); } afterEach(() => { mockedGetCaseMedia.mockReset(); }); describe("resolveServiceHero: combinações que os serviços reais não têm", () => { it("path: a cover with its capture AND a diagram -> the cover wins and the diagram is dropped", () => { capturesOnDisk([["lavacao-047", "desktop"]]); const hero = resolveServiceHero( service({ relatedCaseIds: ["lavacao-047"], heroCase: { id: "lavacao-047", device: "desktop" }, diagram: "iot", }), ); expect(hero.heroCase?.id).toBe("lavacao-047"); expect(hero.diagram).toBeUndefined(); expect(hero.hasHeroSide).toBe(true); }); it("path: a cover WITHOUT its capture and a diagram -> the diagram takes the side column", () => { capturesOnDisk([]); const hero = resolveServiceHero( service({ relatedCaseIds: ["lavacao-047"], heroCase: { id: "lavacao-047", device: "desktop" }, diagram: "iot", }), ); expect(hero.heroCase).toBeUndefined(); expect(hero.diagram).toBe("iot"); expect(hero.hasHeroSide).toBe(true); // a capa não valeu, então o case não está citado em legenda nenhuma: ele ganha o cartão expect(hero.hasCaseCards).toBe(true); }); it("path: the only card left after the smaller block is the cover -> no 'Ver projetos parecidos' target, even with related cases in the block", () => { capturesOnDisk([["lavacao-047", "desktop"]]); const hero = resolveServiceHero( service({ relatedCaseIds: ["lavacao-047", "sc-plus", "as-servicos"], heroCase: { id: "lavacao-047", device: "desktop" }, alsoCases: { title: "Também", caseIds: ["sc-plus", "as-servicos"] }, }), ); expect(hero.heroCase?.id).toBe("lavacao-047"); expect(hero.hasCaseCards).toBe(false); }); it("path: a cover in the smaller block as well -> it is not a card, and the cover stays", () => { capturesOnDisk([["lavacao-047", "desktop"]]); const hero = resolveServiceHero( service({ relatedCaseIds: ["lavacao-047"], heroCase: { id: "lavacao-047", device: "desktop" }, alsoCases: { title: "Também", caseIds: ["lavacao-047"] }, }), ); expect(hero.heroCase?.id).toBe("lavacao-047"); expect(hero.hasCaseCards).toBe(false); }); }); describe("splitServiceCases: o bloco leva todos os cases", () => { it("path: every related case in the smaller block -> no card at all, and the block keeps the order of relatedCaseIds", () => { const { cards, also } = splitServiceCases( service({ relatedCaseIds: ["sc-plus", "as-servicos"], // fora de ordem de propósito: quem manda é a ordem de `relatedCaseIds` alsoCases: { title: "Também", caseIds: ["as-servicos", "sc-plus"] }, }), ); expect(cards).toEqual([]); expect(also?.title).toBe("Também"); expect(also?.cases.map(({ id }) => id)).toEqual(["sc-plus", "as-servicos"]); }); it("path: a smaller block with an empty list of ids -> null, and every related case stays a card", () => { const { cards, also } = splitServiceCases( service({ relatedCaseIds: ["sc-plus", "lavacao-047"], alsoCases: { title: "Também", caseIds: [] }, }), ); expect(also).toBeNull(); expect(cards.map(({ id }) => id)).toEqual(["sc-plus", "lavacao-047"]); }); });