feat(home): prova no topo, contato sem atrito e conversão medida
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).
This commit is contained in:
1 parent
6e1022b58c
commit
8d07b8c6bb
60 files changed
+4392
-2124
No files matched your search
@@ -103,3 +103,114 @@ it("opens the project draft with analytics unavailable and consent denied", asyn
|
||||
expect(destination.origin).toBe("https://wa.me");
|
||||
expect(destination.searchParams.get("text")).toContain("Organizar pedidos");
|
||||
});
|
||||
|
||||
it("lets the visitor skip the e-mail and leaves that line out of the message", async () => {
|
||||
const user = userEvent.setup();
|
||||
render(<Contact />);
|
||||
|
||||
expect(screen.getByRole("textbox", { name: /e-mail/i })).not.toBeRequired();
|
||||
await user.type(screen.getByRole("textbox", { name: /nome/i }), "Ana");
|
||||
await user.type(
|
||||
screen.getByRole("textbox", { name: /contexto/i }),
|
||||
"Organizar pedidos",
|
||||
);
|
||||
await user.click(screen.getByRole("button", { name: /whatsapp/i }));
|
||||
|
||||
expect(window.open).toHaveBeenCalledTimes(1);
|
||||
const url = new URL(String(jest.mocked(window.open).mock.calls[0][0]));
|
||||
const message = url.searchParams.get("text") ?? "";
|
||||
expect(message).toContain("Nome: Ana");
|
||||
expect(message).toContain("Tipo de projeto: Site para empresa");
|
||||
expect(message).not.toContain("E-mail:");
|
||||
});
|
||||
|
||||
it("offers 'Site para empresa' as the first and default project type", () => {
|
||||
render(<Contact />);
|
||||
|
||||
const subject = screen.getByRole("combobox", { name: /tipo de projeto/i });
|
||||
const options = Array.from(subject.querySelectorAll("option")).map(
|
||||
(option) => option.value,
|
||||
);
|
||||
expect(options[0]).toBe("Site para empresa");
|
||||
expect(subject).toHaveValue("Site para empresa");
|
||||
});
|
||||
|
||||
it("explains each invalid field in Portuguese and marks it for assistive technology", async () => {
|
||||
const user = userEvent.setup();
|
||||
render(<Contact />);
|
||||
|
||||
await user.type(
|
||||
screen.getByRole("textbox", { name: /e-mail/i }),
|
||||
"email-invalido",
|
||||
);
|
||||
await user.click(screen.getByRole("button", { name: /whatsapp/i }));
|
||||
|
||||
const name = screen.getByRole("textbox", { name: /nome/i });
|
||||
const email = screen.getByRole("textbox", { name: /e-mail/i });
|
||||
const message = screen.getByRole("textbox", { name: /contexto/i });
|
||||
for (const field of [name, email, message]) {
|
||||
expect(field).toHaveAttribute("aria-invalid", "true");
|
||||
}
|
||||
expect(name).toHaveAccessibleDescription(
|
||||
"Informe seu nome para eu saber com quem falo.",
|
||||
);
|
||||
expect(email).toHaveAccessibleDescription(
|
||||
"Confira o e-mail: ele precisa ter o formato [email protected].",
|
||||
);
|
||||
expect(message).toHaveAccessibleDescription(
|
||||
/Conte em poucas palavras o que você precisa resolver\./,
|
||||
);
|
||||
expect(name).toHaveFocus();
|
||||
expect(window.open).not.toHaveBeenCalled();
|
||||
|
||||
await user.type(name, "Ana");
|
||||
expect(name).not.toHaveAttribute("aria-invalid");
|
||||
expect(
|
||||
screen.queryByText("Informe seu nome para eu saber com quem falo."),
|
||||
).toBeNull();
|
||||
});
|
||||
|
||||
it("offers the same text by e-mail, below the WhatsApp button", async () => {
|
||||
const user = userEvent.setup();
|
||||
render(<Contact />);
|
||||
|
||||
await user.type(screen.getByRole("textbox", { name: /nome/i }), "Ana");
|
||||
await user.type(
|
||||
screen.getByRole("textbox", { name: /contexto/i }),
|
||||
"Organizar pedidos & estoque",
|
||||
);
|
||||
const submit = screen.getByRole("button", { name: /whatsapp/i });
|
||||
const mail = screen.getByRole("link", {
|
||||
name: "Prefere e-mail? Enviar por e-mail",
|
||||
});
|
||||
expect(
|
||||
submit.compareDocumentPosition(mail) & Node.DOCUMENT_POSITION_FOLLOWING,
|
||||
).toBeTruthy();
|
||||
|
||||
const href = mail.getAttribute("href") ?? "";
|
||||
expect(href.startsWith("mailto:[email protected]?")).toBe(true);
|
||||
const url = new URL(href);
|
||||
expect(url.searchParams.get("subject")).toBe("Projeto pelo site");
|
||||
const body = url.searchParams.get("body") ?? "";
|
||||
expect(body).toContain("Nome: Ana");
|
||||
expect(body).toContain("Organizar pedidos & estoque");
|
||||
expect(body).toContain("Tipo de projeto: Site para empresa");
|
||||
|
||||
await user.click(mail);
|
||||
expect(window.gtag).toHaveBeenCalledWith(
|
||||
"event",
|
||||
"email_click",
|
||||
expect.objectContaining({ placement: "contact_form" }),
|
||||
);
|
||||
});
|
||||
|
||||
it("does not call the direct WhatsApp row 'Contato'", () => {
|
||||
render(<Contact />);
|
||||
|
||||
const direct = screen.getByRole("link", { name: /Prefere conversar direto/ });
|
||||
const text = new URL(direct.getAttribute("href") ?? "").searchParams.get(
|
||||
"text",
|
||||
);
|
||||
expect(text).toContain("Quero conversar sobre um projeto.");
|
||||
expect(text).not.toMatch(/sobre Contato/);
|
||||
});
|
||||
Reference in new issue
Block a user