Três ofertas (site que traz pedidos pelo WhatsApp, sistema para tirar a operação da planilha, revisão de sistema existente) com miniatura e formulário com o tipo escolhido; botão principal do hero abre o WhatsApp; moldura da SEV no hero do celular; menu fecha ao navegar, Esc, foco preso incluindo a barra de cookies e espaço para ela; CinematicHome como componente de servidor com ilha cliente; /ia com H1 de oferta e cartão do que você recebe; botão flutuante em aside com transform; AVIF antes de WebP; copy sem repetir contato direto.
150 lines
4.5 KiB
TypeScript
150 lines
4.5 KiB
TypeScript
import { act, render, screen, within } from "@testing-library/react";
|
|
import userEvent from "@testing-library/user-event";
|
|
import Contact from "./Contact";
|
|
import { CONTACT_KIND_EVENT } from "./contact-subject";
|
|
|
|
/**
|
|
* O tipo de projeto do formulário vindo da oferta escolhida na home: pelo evento que o botão da oferta dispara
|
|
* (na própria home) ou pelo `?tipo=` do endereço (ao chegar de outra página), mais a opção de revisão de sistema.
|
|
*/
|
|
|
|
const subjectSelect = () =>
|
|
screen.getByRole("combobox", {
|
|
name: /tipo de projeto/i,
|
|
}) as HTMLSelectElement;
|
|
|
|
const choose = (kind: unknown) =>
|
|
act(() => {
|
|
window.dispatchEvent(new CustomEvent(CONTACT_KIND_EVENT, { detail: kind }));
|
|
});
|
|
|
|
afterEach(() => {
|
|
window.history.replaceState(null, "", "/");
|
|
});
|
|
|
|
describe("Contact: opções do tipo de projeto", () => {
|
|
it("lists 'Revisão ou diagnóstico de sistema' and keeps 'Ainda preciso definir' first and selected", () => {
|
|
render(<Contact />);
|
|
|
|
const options = within(subjectSelect()).getAllByRole("option");
|
|
expect(options.map((option) => option.textContent)).toEqual([
|
|
"Ainda preciso definir",
|
|
"Site para empresa",
|
|
"Sistemas web sob medida",
|
|
"Aplicativos",
|
|
"Integrações e automações",
|
|
"Evolução de um sistema existente",
|
|
"Revisão ou diagnóstico de sistema",
|
|
]);
|
|
expect(subjectSelect()).toHaveValue("Ainda preciso definir");
|
|
});
|
|
|
|
it("puts the review type in the message that goes to WhatsApp and e-mail", async () => {
|
|
const user = userEvent.setup({ delay: null });
|
|
render(<Contact />);
|
|
|
|
await user.selectOptions(
|
|
subjectSelect(),
|
|
"Revisão ou diagnóstico de sistema",
|
|
);
|
|
|
|
const mail = screen.getByRole("link", { name: /e-mail/i });
|
|
const body = new URL(mail.getAttribute("href") ?? "").searchParams.get(
|
|
"body",
|
|
);
|
|
expect(body).toContain(
|
|
"Tipo de projeto: Revisão ou diagnóstico de sistema",
|
|
);
|
|
});
|
|
});
|
|
|
|
describe("Contact: tipo escolhido pela oferta", () => {
|
|
it.each([
|
|
["site", "Site para empresa"],
|
|
["sistema", "Sistemas web sob medida"],
|
|
["revisao", "Revisão ou diagnóstico de sistema"],
|
|
])("the offer event with %s selects %s", (kind, option) => {
|
|
render(<Contact />);
|
|
|
|
choose(kind);
|
|
|
|
expect(subjectSelect()).toHaveValue(option);
|
|
});
|
|
|
|
it("a later offer replaces the earlier choice, and a person's own pick is replaced by the offer too", async () => {
|
|
const user = userEvent.setup({ delay: null });
|
|
render(<Contact />);
|
|
|
|
choose("site");
|
|
await user.selectOptions(subjectSelect(), "Aplicativos");
|
|
expect(subjectSelect()).toHaveValue("Aplicativos");
|
|
choose("revisao");
|
|
|
|
expect(subjectSelect()).toHaveValue("Revisão ou diagnóstico de sistema");
|
|
});
|
|
|
|
it.each([
|
|
"desconhecido",
|
|
"constructor",
|
|
"__proto__",
|
|
"",
|
|
undefined,
|
|
null,
|
|
42,
|
|
])("an unknown type %p changes nothing", (kind) => {
|
|
render(<Contact />);
|
|
choose("sistema");
|
|
|
|
choose(kind);
|
|
|
|
expect(subjectSelect()).toHaveValue("Sistemas web sob medida");
|
|
});
|
|
|
|
it("reads ?tipo= from the address when the form mounts (arrival from another page)", () => {
|
|
window.history.replaceState(null, "", "/?tipo=revisao#contact");
|
|
|
|
render(<Contact />);
|
|
|
|
expect(subjectSelect()).toHaveValue("Revisão ou diagnóstico de sistema");
|
|
});
|
|
|
|
it("ignores an unknown ?tipo= in the address and keeps the default", () => {
|
|
window.history.replaceState(null, "", "/?tipo=outra-coisa");
|
|
|
|
render(<Contact />);
|
|
|
|
expect(subjectSelect()).toHaveValue("Ainda preciso definir");
|
|
});
|
|
|
|
it("stops listening when it unmounts", () => {
|
|
const add = jest.spyOn(window, "addEventListener");
|
|
const remove = jest.spyOn(window, "removeEventListener");
|
|
const { unmount } = render(<Contact />);
|
|
const registered = add.mock.calls.find(
|
|
([type]) => type === CONTACT_KIND_EVENT,
|
|
);
|
|
expect(registered).toBeDefined();
|
|
|
|
unmount();
|
|
|
|
expect(remove).toHaveBeenCalledWith(CONTACT_KIND_EVENT, registered?.[1]);
|
|
add.mockRestore();
|
|
remove.mockRestore();
|
|
});
|
|
});
|
|
|
|
describe("Contact: texto da seção", () => {
|
|
it("keeps 'conversar direto' only on the WhatsApp line, with no other 'fala direto' phrasing", () => {
|
|
const { container } = render(<Contact />);
|
|
|
|
expect(screen.getByText("Prefere conversar direto?")).toBeInTheDocument();
|
|
expect(container.textContent).not.toMatch(/fala direto|fale direto/i);
|
|
expect(
|
|
screen.getByRole("heading", {
|
|
level: 3,
|
|
name: "Como a conversa começa.",
|
|
}),
|
|
).toBeInTheDocument();
|
|
});
|
|
});
|