feat(cases): cases de clientes, serviços ligados à prova e SEO por página

Cases da SEV Moda Íntima e da Lavação 047; case no formato cliente, problema, entrega, mídia e contato, com detalhes técnicos recolhidos; sem GitHub, ressalvas e fontes de commit. /cases separa clientes e Laboratório. Serviços mostram o case de cliente certo e o bloco de investimento e prazo só aparece preenchido. Metadata social própria por página, not-found com noindex, sitemap com /ia.
This commit is contained in:
Evandro Fonseca Junior committed 2026-10-14 03:31:57 -03:00
1 parent 3756905a1b
commit 6e1022b58c
44 files changed
+2691 -1424

No files matched your search

+49 -6
View File
@@ -1,11 +1,13 @@
import sitemap from "../app/sitemap";
import {
buildBreadcrumbList,
buildPageSocialMetadata,
buildPersonJsonLd,
buildProfilePageJsonLd,
buildServiceJsonLd,
buildWebSiteJsonLd,
SEO_IDS,
twitterHandle,
} from "./seo";
import { caseStudies, servicePages, siteName, siteUrl } from "./site-content";
@@ -61,10 +63,7 @@ it("keeps the root graph limited to verified website and person fields", () => {
image: `${siteUrl}/edev.jpg`,
jobTitle: "Engenheiro da Computação e Desenvolvedor de Software",
homeLocation: { "@type": "Place", name: "Garuva, Santa Catarina, Brasil" },
sameAs: [
"https://github.com/evandrodevbr",
"https://www.linkedin.com/in/evandro-fonseca-junior-0969aa1b0/",
],
sameAs: ["https://www.linkedin.com/in/evandrodevbr/"],
});
expect(JSON.stringify([website, person])).not.toMatch(
@@ -121,16 +120,60 @@ it("keeps profile data timeless and sitemap output deterministic", () => {
`${siteUrl}/privacidade`,
`${siteUrl}/servicos`,
`${siteUrl}/cases`,
`${siteUrl}/ia`,
...servicePages.map(({ slug }) => `${siteUrl}/servicos/${slug}`),
...caseStudies.map(({ id }) => `${siteUrl}/cases/${id}`),
];
const first = sitemap();
const second = sitemap();
expect(first).toEqual(expectedUrls.map((url) => ({ url })));
expect(first.map(({ url }) => url)).toEqual(expectedUrls);
expect(second).toEqual(first);
expect(first).toHaveLength(17);
expect(first).toHaveLength(20);
expect(
first.filter(({ url }) => url === `${siteUrl}/privacidade`),
).toHaveLength(1);
});
it("lists the client cases and the AI page, each with a fixed modification date", () => {
const entries = sitemap();
const urls = entries.map(({ url }) => url);
expect(urls).toContain(`${siteUrl}/cases/sev-modaintima`);
expect(urls).toContain(`${siteUrl}/cases/lavacao-047`);
expect(urls).toContain(`${siteUrl}/ia`);
for (const entry of entries) {
expect(entry.lastModified).toBeInstanceOf(Date);
expect(Number.isNaN(new Date(entry.lastModified ?? "").getTime())).toBe(
false,
);
}
});
it("gives every page a complete social card, so it never inherits the home one", () => {
const url = `${siteUrl}/cases`;
expect(
buildPageSocialMetadata({
url,
title: "Título",
description: "Descrição",
type: "website",
}),
).toEqual({
alternates: { canonical: url },
openGraph: {
locale: "pt_BR",
title: "Título",
description: "Descrição",
url,
siteName,
type: "website",
},
twitter: {
card: "summary_large_image",
title: "Título",
description: "Descrição",
creator: twitterHandle,
},
});
});