feat(propuesta): pasarela paso a paso con autodetección de ubicación y FAB
deploy-branch / deploy (push) Failing after 6s
deploy-branch / teardown (push) Skipped

- 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:
2026-08-16 01:35:02 +02:00
parent d48b74cbd4
commit 003b1e209f
53 changed files with 4896 additions and 253 deletions
+40
View File
@@ -0,0 +1,40 @@
import { describe, expect, it } from "vitest";
import ProveedorGoogleMaps from "../../src/utils/ubicacion/proveedorGoogleMaps.js";
describe("ProveedorGoogleMaps", () => {
const p = new ProveedorGoogleMaps();
it("detecta URLs de Google Maps (dominios y subdominios)", () => {
expect(p.detecta("https://maps.google.com/@41.38,2.17")).toBe(true);
expect(p.detecta("https://www.google.es/maps?q=41.38,2.17")).toBe(true);
expect(p.detecta("https://maps.app.goo.gl/abc")).toBe(true);
expect(p.detecta("https://waze.com/ul?ll=41.38,2.17")).toBe(false);
expect(p.detecta("41.38, 2.17")).toBe(false);
});
it("extrae del formato @lat,lng", async () => {
expect(await p.extrae("https://www.google.com/maps/@41.3851,2.1734,15z"))
.toEqual({ proveedor: "google-maps", lat: 41.3851, lng: 2.1734 });
});
it("extrae del formato !3d…!4d… cuando no hay @", async () => {
expect(await p.extrae("https://www.google.com/maps/place/Bar/data=!4m2!3m1!1s0x0:0x0?hl=es"))
.toBeNull(); // sin coordenadas en absoluto
expect(await p.extrae("https://www.google.com/maps/place/Bar/data=!3d41.3851!4d2.1734"))
.toEqual({ proveedor: "google-maps", lat: 41.3851, lng: 2.1734 });
});
it("extrae del formato ?q=lat,lng", async () => {
expect(await p.extrae("https://www.google.com/maps?q=41.3851,-2.1734"))
.toEqual({ proveedor: "google-maps", lat: 41.3851, lng: -2.1734 });
});
it("prioriza @ sobre !3d!4d (comportamiento migrado de parsearEnlaceGoogleMaps)", async () => {
const r = await p.extrae("https://www.google.com/maps/place/X/@40.4168,-3.7038,17z/data=!3d40.4178!4d-3.7028");
expect(r).toEqual({ proveedor: "google-maps", lat: 40.4168, lng: -3.7038 });
});
it("enlace acortado: detecta pero no puede extraer → null", async () => {
expect(await p.extrae("https://maps.app.goo.gl/AbCdEf123")).toBeNull();
});
});