feat(servicos): ofertas no topo de /servicos, capa por assunto e diagramas

/servicos abre com as 3 ofertas e depois outros serviços; H1 de criação de sites e de engenharia com o nome da oferta; capa de cada serviço pelo assunto (SEV fora do próprio case cai de ~11 para 2 imagens); diagrama de fluxo em SVG nos serviços sem case; cases com o que o cliente passou a poder fazer e contato logo depois de Como ficou; FAQ num componente só; lastmod por rota; ProfessionalService com areaServed.
This commit is contained in:
Evandro Fonseca Junior committed 2026-10-14 19:14:46 -03:00
1 parent e63f3c2ebd
commit fc44a69fb3
41 files changed
+2486 -550

No files matched your search

+14 -5
View File
@@ -8,10 +8,12 @@ import ServicePage, { generateMetadata } from "./page";
* Cobrem só o que o arquivo principal não exercita: slug desconhecido e perguntas frequentes ausentes ou vazias.
*/
// usePathname: o HoverPrefetchLink (trilha, cartões) lê o caminho para saber se está na home
jest.mock("next/navigation", () => ({
notFound: jest.fn(() => {
throw new Error("NEXT_NOT_FOUND");
}),
usePathname: () => "/servicos",
}));
beforeEach(() => {
@@ -33,20 +35,27 @@ describe("ServicePage: caminhos que o teste principal não cobre", () => {
expect(notFound).toHaveBeenCalledTimes(1);
});
it("path: service with a FAQ (main path) -> shows every question", async () => {
it("path: service with a FAQ (main path) -> shows every question as a closed accordion item, the same pattern as the home", async () => {
const service = getServicePage("criacao-de-sites");
if (!service?.faq?.length) throw new Error("Missing service FAQ");
await renderService(service.slug);
const { container } = await renderService(service.slug);
expect(
screen.getByRole("heading", { level: 2, name: FAQ_HEADING }),
).toBeVisible();
const summaries = Array.from(
container.querySelectorAll("#faq summary"),
).map((summary) => summary.textContent?.replace("+", "").trim());
expect(summaries).toEqual(service.faq.map(({ question }) => question));
for (const item of service.faq) {
expect(
screen.getByRole("heading", { level: 3, name: item.question }),
).toBeVisible();
const details = screen.getByText(item.question).closest("details");
expect(details).not.toBeNull();
expect(details?.open).toBe(false);
expect(details).toHaveTextContent(item.answer);
}
// um formato só: nenhum cartão de pergunta e resposta
expect(container.querySelector("#faq article")).toBeNull();
});
it("path: service without the faq field -> no FAQ section, the rest of the page stays", async () => {