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();
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();
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();
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();
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();
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();
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();
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();
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();
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();
});
});