// @vitest-environment jsdom import { afterEach, describe, expect, it } from "vitest"; import { useState } from "react"; import { cleanup, fireEvent, render, screen } from "@testing-library/react"; import PasoDatosLocal from "../../src/components/PasoDatosLocal.jsx"; import PasoCategoria from "../../src/components/PasoCategoria.jsx"; import PasoSubcategoria from "../../src/components/PasoSubcategoria.jsx"; import { PROVINCIAS } from "../../src/constants/provincias.js"; import { CATEGORIAS, NOMBRES_CATEGORIAS } from "../../src/constants/categorias.js"; afterEach(cleanup); // Harness con useState real: los pasos escriben a través de setForm y el // estado resultante se lee desde fuera (más fiel que espiar el updater). function renderPaso(Componente, inicial) { const estado = { form: inicial }; function Wrapper() { const [form, setForm] = useState(inicial); estado.form = form; return ; } render(); return estado; } describe("PasoDatosLocal (datos inferidos en una pantalla)", () => { it("muestra los tres campos pre-rellenados con lo inferido, en la misma pantalla", () => { renderPaso(PasoDatosLocal, { nombre: "Puerta del Sol", provincia: "Madrid", direccion: "Puerta del Sol, 28013 Madrid" }); expect(screen.getByLabelText(/nombre del local/i).value).toBe("Puerta del Sol"); expect(screen.getByLabelText(/provincia/i).value).toBe("Madrid"); expect(screen.getByLabelText(/^dirección/i).value).toBe("Puerta del Sol, 28013 Madrid"); // aviso de que vienen de la inferencia expect(screen.getByText(/Rellenados automáticamente desde la ubicación/i)).toBeTruthy(); }); it("todos editables: nombre (input), provincia (select PROVINCIAS), dirección (input)", () => { const estado = renderPaso(PasoDatosLocal, { nombre: "Bar X", provincia: "Barcelona", direccion: "Calle 1" }); fireEvent.change(screen.getByLabelText(/nombre del local/i), { target: { value: "Bar La Plaza" } }); expect(estado.form.nombre).toBe("Bar La Plaza"); const select = screen.getByLabelText(/provincia/i); const opciones = [...select.options].map((o) => o.value); expect(opciones).toEqual(["", ...PROVINCIAS]); fireEvent.change(select, { target: { value: "Gerona" } }); expect(estado.form.provincia).toBe("Gerona"); fireEvent.change(screen.getByLabelText(/^dirección/i), { target: { value: "Calle Nueva 2" } }); expect(estado.form.direccion).toBe("Calle Nueva 2"); }); it("vacíos y sin aviso de inferencia cuando la inferencia falló", () => { renderPaso(PasoDatosLocal, { nombre: "", provincia: "", direccion: "" }); expect(screen.getByLabelText(/nombre del local/i).value).toBe(""); expect(screen.getByLabelText(/provincia/i).value).toBe(""); expect(screen.getByLabelText(/^dirección/i).value).toBe(""); expect(screen.queryByText(/Rellenados automáticamente/i)).toBeNull(); }); }); describe("PasoCategoria", () => { it("ofrece todas las categorías y al elegir limpia la subcategoría", () => { const estado = renderPaso(PasoCategoria, { categoria: "Pequeño comercio", subcategoria: "Farmacia" }); const select = screen.getByLabelText(/categoría/i); const opciones = [...select.options].map((o) => o.value); expect(opciones).toEqual(["", ...NOMBRES_CATEGORIAS]); fireEvent.change(select, { target: { value: "Restauración" } }); expect(estado.form.categoria).toBe("Restauración"); expect(estado.form.subcategoria).toBe(""); }); }); describe("PasoSubcategoria", () => { it("deshabilitado sin categoría y opcional con ella", () => { const { rerender } = render( {}} />); const select = screen.getByLabelText(/tipo específico/i); expect(select.disabled).toBe(true); expect([...select.options][0].textContent).toMatch(/sin tipo específico/i); // se puede continuar rerender( {}} />); expect(select.disabled).toBe(false); const opciones = [...select.options].map((o) => o.value); expect(opciones).toEqual(["", ...CATEGORIAS["Restauración"].subcategorias]); }); });