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