feat(propuesta): pasarela paso a paso con autodetección de ubicación y FAB
- Campo universal de ubicación (Google Maps/Waze/OSM/coordenadas/dirección) sobre proveedores extensibles (src/utils/ubicacion) con resolver e inferencia inversa Nominatim (nombre/provincia pre-rellenados, alias cooficiales) - FAB flotante abajo a la derecha que abre la pasarela en un modal accesible (Escape, foco contenido, responsive); sin descripción ni puntuación; avisos de duplicado y filtro de palabras dentro del modal - Aviso PWA reposicionado: tarjeta abajo a la izquierda en móvil, botón compacto arriba a la izquierda en PC (no tapa el FAB) - Suite de pruebas: 88 unitarias/componente (vitest + RTL, offline) y 10 de integración (supertest + SQLite :memory: y Nominatim real opt-in) - CI: workflow de Gitea Actions con npm test + build en push/PR e integración manual
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import ProveedorWaze from "../../src/utils/ubicacion/proveedorWaze.js";
|
||||
|
||||
const respuestaNominatim = (resultados) => ({
|
||||
ok: true,
|
||||
json: async () => resultados,
|
||||
});
|
||||
|
||||
afterEach(() => vi.unstubAllGlobals());
|
||||
|
||||
describe("ProveedorWaze", () => {
|
||||
const p = new ProveedorWaze();
|
||||
|
||||
it("detecta URLs de Waze", () => {
|
||||
expect(p.detecta("https://waze.com/ul?ll=41.38,2.17&navigate=yes")).toBe(true);
|
||||
expect(p.detecta("https://www.waze.com/live-map/")).toBe(true);
|
||||
expect(p.detecta("waze.to/abc")).toBe(true);
|
||||
expect(p.detecta("https://google.com/maps")).toBe(false);
|
||||
});
|
||||
|
||||
it("extrae de ll=lat,lng", async () => {
|
||||
expect(await p.extrae("https://waze.com/ul?ll=41.3851,2.1734&navigate=yes"))
|
||||
.toEqual({ proveedor: "waze", lat: 41.3851, lng: 2.1734 });
|
||||
// sin esquema https://
|
||||
expect(await p.extrae("waze.com/ul?ll=43.263,-2.935"))
|
||||
.toEqual({ proveedor: "waze", lat: 43.263, lng: -2.935 });
|
||||
});
|
||||
|
||||
it("ll malformado → null sin consultar Nominatim", async () => {
|
||||
const fetchMock = vi.fn();
|
||||
vi.stubGlobal("fetch", fetchMock);
|
||||
expect(await p.extrae("https://waze.com/ul?ll=abc,def")).toBeNull();
|
||||
expect(fetchMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("q=texto delega en la búsqueda de Nominatim marcando proveedor waze", async () => {
|
||||
const fetchMock = vi.fn(() => respuestaNominatim([{
|
||||
lat: "40.4828632", lon: "-3.3652613",
|
||||
display_name: "5, Calle Mayor, Alcalá de Henares, Comunidad de Madrid, 28801, España",
|
||||
address: { city: "Alcalá de Henares", state: "Comunidad de Madrid" },
|
||||
namedetails: { name: "" },
|
||||
}]));
|
||||
vi.stubGlobal("fetch", fetchMock);
|
||||
const r = await p.extrae("https://waze.com/ul?q=Calle%20Mayor%205%2C%20Alcal%C3%A1%20de%20Henares");
|
||||
expect(r).toEqual({
|
||||
proveedor: "waze",
|
||||
lat: 40.4828632,
|
||||
lng: -3.3652613,
|
||||
nombre: "",
|
||||
provincia: "Madrid",
|
||||
direccion: "5, Calle Mayor, Alcalá de Henares, Comunidad de Madrid, 28801, España",
|
||||
});
|
||||
// la petición lleva countrycodes=es y las cabeceras de Nominatim
|
||||
const [url, init] = fetchMock.mock.calls[0];
|
||||
expect(String(url)).toContain("countrycodes=es");
|
||||
expect(init.headers["User-Agent"]).toBe("LocalesEspanoles/1.0");
|
||||
});
|
||||
|
||||
it("q=texto sin resultados en Nominatim → null", async () => {
|
||||
vi.stubGlobal("fetch", vi.fn(() => respuestaNominatim([])));
|
||||
expect(await p.extrae("https://waze.com/ul?q=calle%20inexistente%20zzzz")).toBeNull();
|
||||
});
|
||||
|
||||
it("URL de Waze sin ll ni q → null", async () => {
|
||||
expect(await p.extrae("https://waze.com/live-map/")).toBeNull();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user