feat(servicos): topo, entregáveis e cases por serviço, assunto próprio no WhatsApp e títulos curtos
This commit is contained in:
1 parent
cf360041bd
commit
2fd8b063d9
33 files changed
+1578
-300
No files matched your search
@@ -0,0 +1,140 @@
|
||||
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"]);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user