/** @vitest-environment jsdom */ import { describe, it, expect, vi, afterEach } from 'vitest'; import { render, screen, cleanup, fireEvent, waitFor } from '@testing-library/react'; import { LeadGateView } from './LeadGateView'; import { en } from '../i18n/en'; afterEach(cleanup); function renderGate(onSubmit = vi.fn().mockResolvedValue(true), onSkip = vi.fn()) { render(); return { onSubmit, onSkip, email: screen.getByLabelText(en.lead.emailLabel) as HTMLInputElement, consent: screen.getByRole('checkbox') as HTMLInputElement, submit: screen.getByRole('button', { name: en.lead.submit }) as HTMLButtonElement, }; } describe('what the visitor is told', () => { it('states the purpose before asking for anything', () => { renderGate(); expect(screen.getByText(en.lead.purpose)).toBeDefined(); }); // Consent that arrives pre-ticked is not consent. it('leaves the consent box unticked', () => { const { consent } = renderGate(); expect(consent.checked).toBe(false); }); }); describe('what it takes to submit', () => { it('refuses until both the address and the consent are there', () => { const { email, consent, submit } = renderGate(); expect(submit.disabled).toBe(true); fireEvent.change(email, { target: { value: 'buyer@store.co' } }); expect(submit.disabled).toBe(true); fireEvent.click(consent); expect(submit.disabled).toBe(false); }); it('refuses a malformed address even with the consent ticked', () => { const { email, consent, submit } = renderGate(); fireEvent.change(email, { target: { value: 'buyer@store' } }); fireEvent.click(consent); expect(submit.disabled).toBe(true); }); it('hands the trimmed address to the parent', async () => { const { email, consent, submit, onSubmit } = renderGate(); fireEvent.change(email, { target: { value: ' buyer@store.co ' } }); fireEvent.click(consent); fireEvent.click(submit); await waitFor(() => expect(onSubmit).toHaveBeenCalledWith('buyer@store.co')); }); }); describe('when saving fails', () => { it('says so and lets the visitor try again', async () => { const onSubmit = vi.fn().mockResolvedValue(false); const { email, consent, submit } = renderGate(onSubmit); fireEvent.change(email, { target: { value: 'buyer@store.co' } }); fireEvent.click(consent); fireEvent.click(submit); await waitFor(() => expect(screen.getByRole('alert').textContent).toBe(en.lead.error)); expect((screen.getByRole('button', { name: en.lead.submit }) as HTMLButtonElement).disabled).toBe( false ); }); }); describe('the way out', () => { it('is a plain button that needs no email at all', () => { const { onSkip } = renderGate(); fireEvent.click(screen.getByRole('button', { name: en.lead.skip })); expect(onSkip).toHaveBeenCalledTimes(1); }); });