Home mais curta (hero, vitrine de clientes, sobre, serviços, IA resumida, depoimentos e contato), faixa de clientes e telas reais no hero, sem números do GitHub. Barra de cookies fina, WhatsApp fixo no celular, formulário com e-mail opcional e alternativa por e-mail, página /ia, eventos de e-mail, redes e currículo e conversão do Ads opcional por variável. Rodapé em 3 colunas. Remove componentes órfãos (LighthouseMetrics, Skills, Experience, contagem do GitHub).
172 lines
5.6 KiB
TypeScript
172 lines
5.6 KiB
TypeScript
import { fireEvent, render, screen } from "@testing-library/react";
|
|
import userEvent from "@testing-library/user-event";
|
|
import WhatsAppLink from "./WhatsAppLink";
|
|
|
|
const CONSENT_KEY = "evandro.analytics-consent.v1";
|
|
const DISABLE_KEY = "ga-disable-G-QTT9QT0T3S";
|
|
|
|
beforeEach(() => {
|
|
jest.replaceProperty(process.env, "NODE_ENV", "production");
|
|
localStorage.clear();
|
|
window.gtag = jest.fn();
|
|
delete window[DISABLE_KEY];
|
|
window.history.replaceState(
|
|
{},
|
|
"",
|
|
"/[email protected]#private",
|
|
);
|
|
});
|
|
|
|
afterEach(() => {
|
|
jest.restoreAllMocks();
|
|
delete window.gtag;
|
|
delete window[DISABLE_KEY];
|
|
localStorage.clear();
|
|
window.history.replaceState({}, "", "/");
|
|
});
|
|
|
|
function renderLink() {
|
|
render(
|
|
<WhatsAppLink service="Sistemas web" placement="service_hub_hero">
|
|
Conversar no WhatsApp
|
|
</WhatsAppLink>,
|
|
);
|
|
return screen.getByRole("link", { name: "Conversar no WhatsApp" });
|
|
}
|
|
|
|
it("talks about the service when one is given", () => {
|
|
const url = new URL(renderLink().getAttribute("href") || "");
|
|
expect(url.searchParams.get("text")).toBe(
|
|
"Olá, Evandro! Quero conversar sobre Sistemas web. Contato iniciado pelo site evandro.dev.br.",
|
|
);
|
|
});
|
|
|
|
it("talks about 'um projeto' when no service is given", () => {
|
|
render(<WhatsAppLink placement="contact_direct">Conversar</WhatsAppLink>);
|
|
|
|
const url = new URL(
|
|
screen.getByRole("link", { name: "Conversar" }).getAttribute("href") || "",
|
|
);
|
|
const text = url.searchParams.get("text");
|
|
expect(text).toBe(
|
|
"Olá, Evandro! Quero conversar sobre um projeto. Contato iniciado pelo site evandro.dev.br.",
|
|
);
|
|
expect(text).not.toContain("Contato.");
|
|
});
|
|
|
|
it.each([null, "denied", "{malformed", '"granted"'])(
|
|
"keeps a native destination without collecting or replaying when consent is %s",
|
|
async (consent) => {
|
|
if (consent !== null) localStorage.setItem(CONSENT_KEY, consent);
|
|
const link = renderLink();
|
|
const url = new URL(link.getAttribute("href") || "");
|
|
expect(url.origin).toBe("https://wa.me");
|
|
expect(url.pathname).toMatch(/^\/\d+$/);
|
|
expect(url.searchParams.get("text")).toContain("Sistemas web");
|
|
expect(link).toHaveAttribute("target", "_blank");
|
|
expect(link).toHaveAttribute("rel", "noopener noreferrer");
|
|
expect(fireEvent.click(link, { button: 0 })).toBe(true);
|
|
expect(window.gtag).not.toHaveBeenCalled();
|
|
|
|
localStorage.setItem(CONSENT_KEY, "granted");
|
|
await Promise.resolve();
|
|
expect(window.gtag).not.toHaveBeenCalled();
|
|
fireEvent.click(link, { button: 0 });
|
|
expect(window.gtag).toHaveBeenCalledTimes(1);
|
|
},
|
|
);
|
|
|
|
it("emits one GA4 handoff per primary, middle or keyboard activation without personal URL data", async () => {
|
|
const user = userEvent.setup();
|
|
localStorage.setItem(CONSENT_KEY, "granted");
|
|
const link = renderLink();
|
|
await user.click(link);
|
|
expect(window.gtag).toHaveBeenCalledTimes(1);
|
|
expect(window.gtag).toHaveBeenLastCalledWith("event", "whatsapp_open", {
|
|
send_to: "G-QTT9QT0T3S",
|
|
service: "Sistemas web",
|
|
placement: "service_hub_hero",
|
|
page_path: "/servicos",
|
|
page_location: "https://evandro.dev.br/servicos",
|
|
page_referrer: "",
|
|
});
|
|
|
|
expect(
|
|
fireEvent(
|
|
link,
|
|
new MouseEvent("auxclick", {
|
|
button: 1,
|
|
bubbles: true,
|
|
cancelable: true,
|
|
}),
|
|
),
|
|
).toBe(true);
|
|
expect(window.gtag).toHaveBeenCalledTimes(2);
|
|
fireEvent(link, new MouseEvent("auxclick", { button: 2, bubbles: true }));
|
|
expect(window.gtag).toHaveBeenCalledTimes(2);
|
|
link.focus();
|
|
await user.keyboard("{Enter}");
|
|
expect(window.gtag).toHaveBeenCalledTimes(3);
|
|
});
|
|
|
|
it("stops collecting immediately after revocation and honors the GA disabled flag", () => {
|
|
localStorage.setItem(CONSENT_KEY, "granted");
|
|
const link = renderLink();
|
|
fireEvent.click(link, { button: 0 });
|
|
expect(window.gtag).toHaveBeenCalledTimes(1);
|
|
|
|
localStorage.setItem(CONSENT_KEY, "denied");
|
|
expect(fireEvent.click(link, { button: 0 })).toBe(true);
|
|
expect(window.gtag).toHaveBeenCalledTimes(1);
|
|
|
|
localStorage.setItem(CONSENT_KEY, "granted");
|
|
window[DISABLE_KEY] = true;
|
|
expect(fireEvent.click(link, { button: 0 })).toBe(true);
|
|
expect(window.gtag).toHaveBeenCalledTimes(1);
|
|
});
|
|
|
|
it("keeps navigation available when storage, analytics or its loader is blocked", () => {
|
|
localStorage.setItem(CONSENT_KEY, "granted");
|
|
const link = renderLink();
|
|
const storage = jest
|
|
.spyOn(Storage.prototype, "getItem")
|
|
.mockImplementation(() => {
|
|
throw new Error("storage blocked");
|
|
});
|
|
expect(fireEvent.click(link, { button: 0 })).toBe(true);
|
|
expect(window.gtag).not.toHaveBeenCalled();
|
|
storage.mockRestore();
|
|
|
|
delete window.gtag;
|
|
expect(fireEvent.click(link, { button: 0 })).toBe(true);
|
|
window.gtag = jest.fn(() => {
|
|
throw new Error("analytics blocked");
|
|
});
|
|
expect(fireEvent.click(link, { button: 0 })).toBe(true);
|
|
});
|
|
|
|
it("does not collect outside production", () => {
|
|
jest.replaceProperty(process.env, "NODE_ENV", "development");
|
|
localStorage.setItem(CONSENT_KEY, "granted");
|
|
expect(fireEvent.click(renderLink(), { button: 0 })).toBe(true);
|
|
expect(window.gtag).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it("uses a route template rather than collecting arbitrary dynamic path segments", () => {
|
|
localStorage.setItem(CONSENT_KEY, "granted");
|
|
window.history.replaceState(
|
|
{},
|
|
"",
|
|
"/servicos/ana%40example.com?message=private",
|
|
);
|
|
fireEvent.click(renderLink(), { button: 0 });
|
|
expect(window.gtag).toHaveBeenCalledWith("event", "whatsapp_open", {
|
|
send_to: "G-QTT9QT0T3S",
|
|
service: "Sistemas web",
|
|
placement: "service_hub_hero",
|
|
page_path: "/servicos/[slug]",
|
|
page_location: "https://evandro.dev.br/servicos/[slug]",
|
|
page_referrer: "",
|
|
});
|
|
});
|