149 lines
5.1 KiB
TypeScript
149 lines
5.1 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";
|
|
|
|
/**
|
|
* resolveServiceHero (CC 6): capa com captura | sem captura do aparelho pedido; esquema | sem esquema; o aparelho padrão
|
|
* (computador) | o do serviço (celular); algum case com cartão | só o da capa | nenhum.
|
|
* splitServiceCases (CC 3): serviço com bloco menor | sem ele; ids do bloco que o serviço relaciona | que não relaciona.
|
|
* 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(slug: string): ServicePageContent {
|
|
const found = getServicePage(slug);
|
|
if (!found) throw new Error(`Missing service ${slug}`);
|
|
return found;
|
|
}
|
|
|
|
/** 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", () => {
|
|
it("path: cover with its capture on disk -> the case is the cover, no diagram, two columns", () => {
|
|
capturesOnDisk([["lavacao-047", "desktop"]]);
|
|
|
|
const hero = resolveServiceHero(service("criacao-de-sites"));
|
|
|
|
expect(hero.heroCase?.id).toBe("lavacao-047");
|
|
expect(hero.heroDevice).toBe("desktop");
|
|
expect(hero.diagram).toBeUndefined();
|
|
expect(hero.hasHeroSide).toBe(true);
|
|
// a SEV, que não é a capa, ganha cartão
|
|
expect(hero.hasCaseCards).toBe(true);
|
|
});
|
|
|
|
it("path: a service that asks for the phone -> the capture is checked for the phone", () => {
|
|
capturesOnDisk([["sev-modaintima", "mobile"]]);
|
|
|
|
const hero = resolveServiceHero(service("engenharia-de-software"));
|
|
|
|
expect(hero.heroDevice).toBe("mobile");
|
|
expect(hero.heroCase?.id).toBe("sev-modaintima");
|
|
expect(mockedGetCaseMedia).toHaveBeenCalledWith("sev-modaintima", "mobile");
|
|
});
|
|
|
|
it("path: cover without a capture and no diagram -> no side column, and the case that would be the cover gets its card back", () => {
|
|
capturesOnDisk([]);
|
|
|
|
const hero = resolveServiceHero(service("criacao-de-sites"));
|
|
|
|
expect(hero.heroCase).toBeUndefined();
|
|
expect(hero.diagram).toBeUndefined();
|
|
expect(hero.hasHeroSide).toBe(false);
|
|
expect(hero.hasCaseCards).toBe(true);
|
|
});
|
|
|
|
it("path: service with a diagram -> the diagram fills the side column, desktop by default", () => {
|
|
capturesOnDisk([]);
|
|
|
|
const hero = resolveServiceHero(service("tauri-rust"));
|
|
|
|
expect(hero.heroCase).toBeUndefined();
|
|
expect(hero.heroDevice).toBe("desktop");
|
|
expect(hero.diagram).toBe("desktop");
|
|
expect(hero.hasHeroSide).toBe(true);
|
|
expect(hero.hasCaseCards).toBe(true);
|
|
});
|
|
|
|
it("path: the only related case is the cover -> no card, so no 'Ver projetos parecidos' target", () => {
|
|
capturesOnDisk([["sc-plus", "desktop"]]);
|
|
const onlyCover: ServicePageContent = {
|
|
...service("consultoria-nextjs"),
|
|
relatedCaseIds: ["sc-plus"],
|
|
};
|
|
|
|
const hero = resolveServiceHero(onlyCover);
|
|
|
|
expect(hero.heroCase?.id).toBe("sc-plus");
|
|
expect(hero.hasCaseCards).toBe(false);
|
|
});
|
|
|
|
it("path: no related case at all -> no cards", () => {
|
|
capturesOnDisk([]);
|
|
|
|
expect(resolveServiceHero(service("arquitetura-de-software"))).toEqual({
|
|
heroCase: undefined,
|
|
heroDevice: "desktop",
|
|
diagram: "arquitetura",
|
|
hasHeroSide: true,
|
|
hasCaseCards: false,
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("splitServiceCases", () => {
|
|
it("path: service with a smaller block -> the sites institucionais leave the cards and go to the block", () => {
|
|
const { cards, also } = splitServiceCases(service("criacao-de-sites"));
|
|
|
|
expect(cards.map(({ id }) => id)).toEqual([
|
|
"lavacao-047",
|
|
"sev-modaintima",
|
|
]);
|
|
expect(also?.title).toBe("Também faço sites institucionais");
|
|
expect(also?.cases.map(({ id }) => id)).toEqual(["sc-plus", "as-servicos"]);
|
|
});
|
|
|
|
it("path: service without a smaller block -> every related case is a card and `also` is null", () => {
|
|
const { cards, also } = splitServiceCases(
|
|
service("engenharia-de-software"),
|
|
);
|
|
|
|
expect(cards.map(({ id }) => id)).toEqual([
|
|
"sev-modaintima",
|
|
"lavacao-047",
|
|
]);
|
|
expect(also).toBeNull();
|
|
});
|
|
|
|
it("path: block ids that the service does not relate -> ignored, and with none left the block is null", () => {
|
|
const stray: ServicePageContent = {
|
|
...service("consultoria-nextjs"),
|
|
alsoCases: { title: "Também", caseIds: ["as-servicos", "nao-existe"] },
|
|
};
|
|
|
|
const { cards, also } = splitServiceCases(stray);
|
|
|
|
expect(cards.map(({ id }) => id)).toEqual(["sc-plus", "lavacao-047"]);
|
|
expect(also).toBeNull();
|
|
});
|
|
});
|