import { beforeAll, describe, expect, it } from "vitest"; import request from "supertest"; // BD en memoria: aislada, offline y determinista. Debe configurarse ANTES de // importar la app (server/db.js resuelve la ruta en la carga del módulo). process.env.LOCALESP_DB = ":memory:"; let app; beforeAll(async () => { ({ default: app } = await import("../../server/index.js")); }); // Payload equivalente al que envía la pasarela tras este cambio: sin // descripcion y sin puntuacion (el backend aplica sus defaults). const PROPUESTA_PASARELA = { nombre: "Bar El Olivo", provincia: "Madrid", categoria: "Restauración", subcategoria: "Tapas y raciones", direccion: "Calle Mayor 5, Alcalá de Henares", enlaceGoogleMaps: "", lat: 40.4828, lng: -3.3652, }; describe("Integración API local (Express + SQLite en memoria)", () => { it("GET /api/locales arranca limpio", async () => { const r = await request(app).get("/api/locales"); expect(r.status).toBe(200); expect(r.body).toEqual([]); }); it("POST /api/propuestas acepta una propuesta de la pasarela sin descripcion ni puntuacion (defaults)", async () => { const r = await request(app).post("/api/propuestas").send(PROPUESTA_PASARELA); expect(r.status).toBe(201); expect(r.body.nombre).toBe("Bar El Olivo"); expect(r.body.puntuacion).toBe(0); // default del backend expect(r.body.estado).toBe("pendiente"); expect(r.body.id).toBeTruthy(); // y aparece en pendientes (vista admin) const pend = await request(app).get("/api/pendientes"); expect(pend.body.map((p) => p.nombre)).toContain("Bar El Olivo"); }); it("POST /api/check-duplicado detecta mismo nombre normalizado en la misma provincia", async () => { const r = await request(app) .post("/api/check-duplicado") .send({ nombre: "bar el olivo", provincia: "Madrid", lat: 41.0, lng: -4.0 }); // lejos: cuenta la provincia expect(r.body.duplicado).toBe(true); expect(r.body.coincidencias[0]).toMatchObject({ nombre: "Bar El Olivo", provincia: "Madrid", estado: "pendiente", // aún no publicado }); }); it("POST /api/check-duplicado detecta por cercanía aunque cambie la provincia", async () => { const r = await request(app) .post("/api/check-duplicado") .send({ nombre: "BAR EL OLIVO", provincia: "Barcelona", lat: 40.48281, lng: -3.36521 }); // ~1-2 m expect(r.body.duplicado).toBe(true); }); it("POST /api/check-duplicado no marca nombres distintos ni mismos nombres lejos y en otra provincia", async () => { const distinto = await request(app) .post("/api/check-duplicado") .send({ nombre: "Cafetería Luna", provincia: "Madrid", lat: 40.48, lng: -3.36 }); expect(distinto.body.duplicado).toBe(false); const lejosOtraProvincia = await request(app) .post("/api/check-duplicado") .send({ nombre: "Bar El Olivo", provincia: "Sevilla", lat: 37.38, lng: -5.98 }); expect(lejosOtraProvincia.body.duplicado).toBe(false); }); it("flujo admin completo: aprobar publica el local con los datos de la propuesta", async () => { const propuesta = (await request(app).get("/api/pendientes")).body[0]; const aprobado = await request(app).post(`/api/aprobar/${propuesta.id}`); expect(aprobado.body.ok).toBe(true); const locales = (await request(app).get("/api/locales")).body; const publicado = locales.find((l) => l.nombre === "Bar El Olivo"); expect(publicado).toMatchObject({ provincia: "Madrid", categoria: "Restauración", subcategoria: "Tapas y raciones", direccion: "Calle Mayor 5, Alcalá de Henares", puntuacion: 0, // default aplicado en cascada }); }); });