Files
portifolio-evandrodevbr/lib/whatsapp.test.ts
T
Evandro Fonseca Junior 9e2d65a926 fix(home): oferta leva ao formulário, ofertas logo depois da vitrine
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.
2026-10-14 19:14:47 -03:00

148 lines
4.7 KiB
TypeScript

import {
AI_REVIEW_SUBJECT,
buildWhatsAppUrl,
CASES_SUBJECT,
HOME_SUBJECT,
headerOpensWhatsApp,
isServiceOrCasePath,
RESUME_SUBJECT,
SERVICES_SUBJECT,
similarProjectSubject,
type WhatsAppContexts,
whatsAppSubjectForPath,
} from "./whatsapp";
const contexts: WhatsAppContexts = {
services: { "criacao-de-sites": "Sites profissionais" },
cases: { "sev-modaintima": "SEV Moda Íntima" },
};
describe("whatsAppSubjectForPath", () => {
it("cites the service on /servicos/<slug>", () => {
expect(whatsAppSubjectForPath("/servicos/criacao-de-sites", contexts)).toBe(
"Sites profissionais",
);
});
it("cites the case on /cases/<slug>, with the phrase every page uses for a similar project", () => {
expect(whatsAppSubjectForPath("/cases/sev-modaintima", contexts)).toBe(
"um projeto parecido com o case SEV Moda Íntima",
);
expect(similarProjectSubject("Lavação 047")).toBe(
"um projeto parecido com o case Lavação 047",
);
});
it("speaks of the page itself on the home and the index pages, the same as the body buttons of /cases and /servicos", () => {
expect(whatsAppSubjectForPath("/", contexts)).toBe(HOME_SUBJECT);
expect(whatsAppSubjectForPath("/cases", contexts)).toBe(CASES_SUBJECT);
expect(CASES_SUBJECT).toBe("um projeto parecido com os cases do portfólio");
expect(whatsAppSubjectForPath("/servicos", contexts)).toBe(
SERVICES_SUBJECT,
);
expect(SERVICES_SUBJECT).toBe("Sites, sistemas e aplicativos");
expect(whatsAppSubjectForPath("/curriculo", contexts)).toBe(RESUME_SUBJECT);
// sem contextos, a página-índice continua falando de si
expect(whatsAppSubjectForPath("/cases/")).toBe(CASES_SUBJECT);
expect(whatsAppSubjectForPath("/curriculo/")).toBe(RESUME_SUBJECT);
});
it("cites the AI review on /ia", () => {
expect(whatsAppSubjectForPath("/ia", contexts)).toBe(AI_REVIEW_SUBJECT);
expect(whatsAppSubjectForPath("/ia/", undefined)).toBe(AI_REVIEW_SUBJECT);
});
it("ignores a trailing slash", () => {
expect(
whatsAppSubjectForPath("/servicos/criacao-de-sites/", contexts),
).toBe("Sites profissionais");
});
it.each([
"/privacidade",
"/notebook-smoke",
"/servicos/inexistente",
"/cases/inexistente",
"/servicos/criacao-de-sites/extra",
// nomes que existem em todo objeto não podem virar assunto
"/servicos/constructor",
"/cases/__proto__",
"/cases/toString",
])("falls back to a generic message on %s", (pathname) => {
expect(whatsAppSubjectForPath(pathname, contexts)).toBeUndefined();
});
it("treats an empty or blank name as missing, so the message never reads 'sobre .'", () => {
const blank: WhatsAppContexts = {
services: { vazio: "", espacos: " " },
cases: { vazio: "", espacos: " " },
};
for (const pathname of [
"/servicos/vazio",
"/servicos/espacos",
"/cases/vazio",
"/cases/espacos",
]) {
expect(whatsAppSubjectForPath(pathname, blank)).toBeUndefined();
}
});
it("is generic without contexts, without a pathname or outside the router", () => {
expect(
whatsAppSubjectForPath("/servicos/criacao-de-sites"),
).toBeUndefined();
expect(whatsAppSubjectForPath(null, contexts)).toBeUndefined();
expect(whatsAppSubjectForPath(undefined, contexts)).toBeUndefined();
});
});
describe("isServiceOrCasePath", () => {
it.each([
["/servicos/criacao-de-sites", true],
["/servicos/qualquer-coisa/", true],
["/cases/sev-modaintima", true],
["/", false],
["/servicos", false],
["/cases", false],
["/ia", false],
["/servicos/a/b", false],
[null, false],
[undefined, false],
])("%s -> %s", (pathname, expected) => {
expect(isServiceOrCasePath(pathname)).toBe(expected);
});
});
describe("headerOpensWhatsApp", () => {
it.each([
["/servicos/criacao-de-sites", true],
["/servicos/inexistente", true],
["/cases/sev-modaintima", true],
["/ia", true],
["/ia/", true],
["/cases", true],
["/servicos", true],
["/curriculo", true],
["/curriculo/", true],
// a home já tem o formulário na própria página; as demais rotas não têm assunto
["/", false],
["/privacidade", false],
["/cases/a/b", false],
["/ia/extra", false],
[null, false],
[undefined, false],
])("%s -> %s", (pathname, expected) => {
expect(headerOpensWhatsApp(pathname)).toBe(expected);
});
});
describe("buildWhatsAppUrl", () => {
it("encodes the message in the text parameter of a wa.me link", () => {
const url = new URL(buildWhatsAppUrl("Olá & tudo? #1"));
expect(url.origin).toBe("https://wa.me");
expect(url.pathname).toMatch(/^\/\d{12,13}$/);
expect(url.searchParams.get("text")).toBe("Olá & tudo? #1");
});
});