deploy-branch / deploy (push) Successful in 2m18s
deploy-branch / teardown (push) Skipped
tests / Unitarias + componente + build (pull_request) Successful in 2m23s
tests / Integración (Nominatim real, opt-in) (pull_request) Skipped
tests / Unitarias + componente + build (push) Successful in 2m30s
tests / Integración (Nominatim real, opt-in) (push) Skipped
- Nuevo PasoDatosLocal con nombre, provincia y dirección (ahora editable) en la misma pantalla, con aviso cuando vienen de la inferencia - El wizard pasa de 6 a 5 pasos: Ubicación → Datos del local → Categoría → Tipo específico → Resumen - Eliminados PasoNombre y PasoProvincia (absorbidos) - Spec principal actualizada al nuevo orden de pantallas
87 lines
4.2 KiB
React
87 lines
4.2 KiB
React
// @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 <Componente form={form} setForm={setForm} />;
|
|
}
|
|
render(<Wrapper />);
|
|
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(<PasoSubcategoria form={{ categoria: "", subcategoria: "" }} setForm={() => {}} />);
|
|
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(<PasoSubcategoria form={{ categoria: "Restauración", subcategoria: "" }} setForm={() => {}} />);
|
|
expect(select.disabled).toBe(false);
|
|
const opciones = [...select.options].map((o) => o.value);
|
|
expect(opciones).toEqual(["", ...CATEGORIAS["Restauración"].subcategorias]);
|
|
});
|
|
});
|