import { afterEach, describe, expect, it, vi } from "vitest"; import ProveedorNominatim from "../../src/utils/ubicacion/proveedorNominatim.js"; afterEach(() => vi.unstubAllGlobals()); describe("ProveedorNominatim", () => { const p = new ProveedorNominatim(); describe("detecta (fallback de texto)", () => { it("acepta direcciones y nombres con letras", () => { expect(p.detecta("Calle Mayor 5, Alcalá de Henares, Madrid")).toBe(true); expect(p.detecta("Bar El Olivo Sevilla")).toBe(true); }); it("rechaza URLs (las gestiona otro proveedor)", () => { expect(p.detecta("https://ejemplo.com/calle")).toBe(false); expect(p.detecta("www.ejemplo.com")).toBe(false); expect(p.detecta("https://maps.app.goo.gl/abc")).toBe(false); }); it("rechaza textos demasiado cortos o sin letras", () => { expect(p.detecta("ab")).toBe(false); expect(p.detecta("")).toBe(false); expect(p.detecta("12345")).toBe(false); }); }); describe("desdeResultado (normalización de provincia)", () => { it("normaliza provincia canónica insensible a acentos", () => { const r = p.desdeResultado({ lat: "40.4", lon: "-3.7", display_name: "X, Madrid, España", address: { state: "Comunidad de Madrid" }, namedetails: { name: "X" }, }); expect(r.provincia).toBe("Madrid"); }); it("alias cooficiales: Bizkaia → Vizcaya, A Coruña → La Coruña", () => { const r = p.desdeResultado({ lat: "1", lon: "2", display_name: "d", address: { province: "Bizkaia" }, namedetails: {} }); expect(r.provincia).toBe("Vizcaya"); const r2 = p.desdeResultado({ lat: "1", lon: "2", display_name: "d", address: { city: "A Coruña" }, namedetails: {} }); expect(r2.provincia).toBe("La Coruña"); }); it("provincia fuera del listado → \"\" (selección manual)", () => { const r = p.desdeResultado({ lat: "1", lon: "2", display_name: "d", address: { state: "Île-de-France" }, namedetails: {} }); expect(r.provincia).toBe(""); }); it("resultado extensible: lat/lng/proveedor/nombre/direccion", () => { const r = p.desdeResultado({ lat: "41.5", lon: "2.1", display_name: "X, Girona, España", address: { province: "Girona" }, namedetails: { name: "X" }, }); expect(r).toEqual({ proveedor: "nominatim", lat: 41.5, lng: 2.1, nombre: "X", provincia: "Gerona", direccion: "X, Girona, España" }); }); }); describe("extrae (búsqueda por texto)", () => { it("devuelve el primer resultado normalizado", async () => { const fetchMock = vi.fn(() => ({ ok: true, json: async () => [{ lat: "40.4828632", lon: "-3.3652613", display_name: "5, Calle Mayor, Alcalá de Henares, España", address: { city: "Alcalá de Henares", state: "Comunidad de Madrid" }, namedetails: { name: "Casa de la Panadería" }, }], })); vi.stubGlobal("fetch", fetchMock); const r = await p.extrae("Calle Mayor 5, Alcalá de Henares"); expect(r.proveedor).toBe("nominatim"); expect(r.lat).toBeCloseTo(40.4828632, 6); expect(r.provincia).toBe("Madrid"); expect(r.nombre).toBe("Casa de la Panadería"); // la búsqueda acota a España const [url] = fetchMock.mock.calls[0]; expect(decodeURIComponent(String(url).replace(/\+/g, " "))).toContain("Calle Mayor 5, Alcalá de Henares, España"); }); it("sin resultados → null", async () => { vi.stubGlobal("fetch", vi.fn(() => ({ ok: true, json: async () => [] }))); expect(await p.extrae("calle inventada zzzz")).toBeNull(); }); it("fallo de red → null (degradación controlada)", async () => { vi.stubGlobal("fetch", vi.fn(() => Promise.reject(new Error("sin red")))); expect(await p.extrae("Calle Mayor 5, Madrid")).toBeNull(); }); }); });