141 lines
5.0 KiB
TypeScript
141 lines
5.0 KiB
TypeScript
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>): 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"]);
|
|
});
|
|
});
|