import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' import { cleanup, fireEvent, render, screen } from '@testing-library/react' import AltaClientePage from './AltaClientePage' import type { LeadResumen } from '../services/api' type FetchFn = (input: RequestInfo | URL, init?: RequestInit) => Promise const LEAD: LeadResumen = { id: 'lead-9', nombre: 'María Fernanda López', telefono: '4771234567', email: 'maria@correo.com', estado: 'NUEVO', origen: 'Web', fuente: 'lead', } const respuestaOk = (data: unknown) => new Response(JSON.stringify(data), { status: 200, headers: { 'Content-Type': 'application/json' } }) let fetchMock: ReturnType> beforeEach(() => { fetchMock = vi.fn().mockImplementation((input) => { const url = String(input) if (url.includes('/borradores')) { // Un borrador para que la pantalla inicial sea el picker return Promise.resolve( respuestaOk([{ id: 'b-1', nombre: 'Borrador previo', paso: 0, updatedAt: '2026-08-20T10:00:00Z' }]), ) } if (url.includes('/leads/buscar')) return Promise.resolve(respuestaOk([LEAD])) return Promise.reject(new Error(`fetch inesperado: ${url}`)) }) vi.stubGlobal('fetch', fetchMock) }) afterEach(() => { cleanup() vi.unstubAllGlobals() }) describe('AltaClientePage — pantalla de entrada', () => { it('muestra las dos opciones de alta', async () => { render() expect(await screen.findByRole('button', { name: /Alta Afluencia/ })).toBeTruthy() expect(screen.getByRole('button', { name: /Alta de Cliente/ })).toBeTruthy() }) it('"Alta de Cliente" navega al picker (borradores + búsqueda de lead)', async () => { render() fireEvent.click(await screen.findByRole('button', { name: /Alta de Cliente/ })) expect(await screen.findByLabelText(/Buscar lead/)).toBeTruthy() expect(screen.getByText('Borrador previo')).toBeTruthy() }) it('"Alta Afluencia" muestra el formulario y "Volver" regresa a la entrada', async () => { render() fireEvent.click(await screen.findByRole('button', { name: /Alta Afluencia/ })) expect(await screen.findByLabelText(/^Nombre/)).toBeTruthy() fireEvent.click(screen.getByRole('button', { name: 'Volver' })) expect(await screen.findByRole('button', { name: /Alta de Cliente/ })).toBeTruthy() }) }) describe('AltaClientePage — alta desde lead capturado', () => { it('al elegir un lead el wizard arranca con datosGenerales prellenados', async () => { render() // Entrada → Alta de Cliente → picker con la sección de búsqueda fireEvent.click(await screen.findByRole('button', { name: /Alta de Cliente/ })) const busqueda = await screen.findByLabelText(/Buscar lead/) fireEvent.change(busqueda, { target: { value: 'maria' } }) fireEvent.click(await screen.findByText('María Fernanda López')) // Wizard paso 1 con los campos del lead ya capturados const nombre = (await screen.findByLabelText(/Nombre completo/)) as HTMLInputElement expect(nombre.value).toBe('MARÍA FERNANDA LÓPEZ') expect((screen.getByLabelText(/Correo electrónico|Email/i) as HTMLInputElement).value).toBe('maria@correo.com') expect((screen.getByLabelText(/Celular/i) as HTMLInputElement).value).toBe('4771234567') }) }) describe('AltaClientePage — alta desde cotización (?cotizacion=)', () => { it('se salta la entrada y va directo al wizard prellenado', async () => { window.history.pushState({}, '', '/?cotizacion=cot-1') fetchMock.mockImplementation((input) => { const url = String(input) if (url.includes('/cotizaciones/cot-1')) { return Promise.resolve( respuestaOk({ clienteNombre: 'Cliente Prueba', clienteEmail: 'cliente@correo.com', clienteTelefono: '6645550000', desarrollo: 'SENDA', unidadCodigo: 'U-101', precioFinal: 1500000, enganche: 150000, }), ) } return Promise.reject(new Error(`fetch inesperado: ${url}`)) }) try { render() // Wizard directo, sin pasar por la entrada const nombre = (await screen.findByLabelText(/Nombre completo/)) as HTMLInputElement expect(nombre.value).toBe('CLIENTE PRUEBA') expect(screen.queryByRole('button', { name: /Alta Afluencia/ })).toBeNull() } finally { window.history.pushState({}, '', '/') } }) })