O botão das ofertas rola até o contato com o tipo marcado e não quebra mais as âncoras; ofertas com o que você recebe e primeiro passo, logo depois da vitrine; bloco de IA fora da home; cartão largo da SEV no hero do celular; separador da faixa de clientes só entre itens; favicon de 13 para 1,8 KB; pré-carregamento só no hover e nunca de /#... fora da home; X do menu e cabeçalho opaco; WhatsApp com "o case"; /ia com 3 passos e modelo de relatório ilustrativo; Sobre alinhado ao currículo; CSP Report-Only com os domínios do Ads.
54 lines
2.2 KiB
TypeScript
54 lines
2.2 KiB
TypeScript
import { render } from "@testing-library/react";
|
|
import { SEO_IDS } from "@/lib/seo";
|
|
import CinematicHome from "./CinematicHome";
|
|
|
|
/**
|
|
* Dados estruturados da home: um único script `application/ld+json` com o negócio (ProfessionalService). O WebSite e
|
|
* a Person já saem do layout (app/layout.tsx), e repeti-los aqui duplicaria os dados.
|
|
*/
|
|
|
|
jest.mock("../Hero", () => ({ __esModule: true, default: () => null }));
|
|
jest.mock("../Projects", () => ({ __esModule: true, default: () => null }));
|
|
jest.mock("../About", () => ({ __esModule: true, default: () => null }));
|
|
jest.mock("../WorkModalities", () => ({ WorkModalities: () => null }));
|
|
jest.mock("../HomeFaq", () => ({ __esModule: true, default: () => null }));
|
|
jest.mock("../Testimonials", () => ({ __esModule: true, default: () => null }));
|
|
jest.mock("../Contact", () => ({ __esModule: true, default: () => null }));
|
|
jest.mock("./CinematicMain", () => ({
|
|
__esModule: true,
|
|
default: ({ children }: { children: React.ReactNode }) => (
|
|
<main>{children}</main>
|
|
),
|
|
}));
|
|
|
|
function structuredData() {
|
|
const { container } = render(<CinematicHome projects={[]} />);
|
|
return Array.from(
|
|
container.querySelectorAll('script[type="application/ld+json"]'),
|
|
).map((script) => JSON.parse(script.textContent ?? ""));
|
|
}
|
|
|
|
describe("CinematicHome: dados estruturados", () => {
|
|
it("emits exactly one ld+json script, before the scenes", () => {
|
|
const { container } = render(<CinematicHome projects={[]} />);
|
|
|
|
const scripts = container.querySelectorAll(
|
|
'script[type="application/ld+json"]',
|
|
);
|
|
expect(scripts).toHaveLength(1);
|
|
expect(container.firstElementChild).toBe(scripts[0]);
|
|
});
|
|
|
|
it("describes only the business as a ProfessionalService, without repeating what the layout emits", () => {
|
|
const [data] = structuredData();
|
|
|
|
expect(data["@context"]).toBe("https://schema.org");
|
|
expect(data["@graph"]).toHaveLength(1);
|
|
const [business] = data["@graph"];
|
|
expect(business["@type"]).toBe("ProfessionalService");
|
|
expect(business["@id"]).toBe(SEO_IDS.professionalService);
|
|
expect(business.founder).toEqual({ "@id": SEO_IDS.person });
|
|
expect(JSON.stringify(data)).not.toMatch(/"@type":"(WebSite|Person)"/);
|
|
});
|
|
});
|