Prototipo YB01 #1

Open
edgar.friendly wants to merge 16 commits from prototipo-yb01 into master
6 changed files with 717 additions and 1294 deletions
Showing only changes of commit 0c5651a6c0 - Show all commits
+4 -12
View File
@@ -11,15 +11,12 @@ on:
jobs: jobs:
test: test:
name: Unitarias + componente + build name: Unitarias + componente + build
runs-on: ubuntu-latest # El runner disponible es self-hosted (AlmaLinux, Node 20 del sistema);
# las deps soportan Node >=18/20 (jsdom@26), así que no hace falta setup-node.
runs-on: self-hosted
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- name: Instalar dependencias - name: Instalar dependencias
run: npm ci run: npm ci
@@ -31,17 +28,12 @@ jobs:
integracion: integracion:
name: Integración (Nominatim real, opt-in) name: Integración (Nominatim real, opt-in)
runs-on: ubuntu-latest runs-on: self-hosted
if: github.event_name == 'workflow_dispatch' if: github.event_name == 'workflow_dispatch'
continue-on-error: true # depende de un servicio externo: informativa continue-on-error: true # depende de un servicio externo: informativa
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- name: Instalar dependencias - name: Instalar dependencias
run: npm ci run: npm ci
+686 -1273
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -24,9 +24,9 @@
"@testing-library/react": "^16.3.2", "@testing-library/react": "^16.3.2",
"@vitejs/plugin-react": "^4.2.1", "@vitejs/plugin-react": "^4.2.1",
"concurrently": "^8.0.0", "concurrently": "^8.0.0",
"jsdom": "^30.0.1", "jsdom": "^26.1.0",
"supertest": "^7.2.2", "supertest": "^7.2.2",
"vite": "^5.2.0", "vite": "^5.2.0",
"vitest": "^4.1.10" "vitest": "^3.2.7"
} }
} }
+11 -3
View File
@@ -24,7 +24,15 @@ const matchMediaMock = (esMovil) => (_query) => ({
// En pantallas anchas la tarjeta acompaña a la columna de 720px (mismo borde // En pantallas anchas la tarjeta acompaña a la columna de 720px (mismo borde
// que el contenido); en estrechas queda a 16px del borde de la ventana. // que el contenido); en estrechas queda a 16px del borde de la ventana.
const PATRON_ALINEADO_CUERPO = /left:\s*max\(16px,\s*[^;]*100vw[^;]*720px[^;]*16px[^;]*\)/; // (la serialización exacta de max()/calc() varía entre versiones de jsdom,
// así que se comprueba por contenido y no por sintaxis exacta)
function assertAlineadoAlCuerpo(styleAttr) {
const left = (styleAttr.match(/left:\s*([^;]+)/) || [])[1];
expect(left, "debe usar left con max()").toMatch(/max\(/);
expect(left).toContain("100vw");
expect(left).toContain("720px");
expect(left).toContain("16px");
}
function contenedorFijo() { function contenedorFijo() {
const fijos = [...document.querySelectorAll("div")].filter((d) => d.style.position === "fixed"); const fijos = [...document.querySelectorAll("div")].filter((d) => d.style.position === "fixed");
@@ -53,7 +61,7 @@ describe("BannerMovil (PC y móvil): abajo a la izquierda, alineado al cuerpo",
const contenedor = contenedorFijo(); const contenedor = contenedorFijo();
expect(contenedor.style.bottom).toBe("0px"); expect(contenedor.style.bottom).toBe("0px");
expect(contenedor.getAttribute("style")).toMatch(PATRON_ALINEADO_CUERPO); assertAlineadoAlCuerpo(contenedor.getAttribute("style"));
expect(contenedor.style.right).toBe(""); // nunca a la derecha, ahí vive el FAB expect(contenedor.style.right).toBe(""); // nunca a la derecha, ahí vive el FAB
// en PC la tarjeta es más grande // en PC la tarjeta es más grande
const tarjeta = screen.getByRole("button", { name: "Cerrar aviso de instalación" }).parentElement; const tarjeta = screen.getByRole("button", { name: "Cerrar aviso de instalación" }).parentElement;
@@ -65,7 +73,7 @@ describe("BannerMovil (PC y móvil): abajo a la izquierda, alineado al cuerpo",
render(<BannerMovil />); render(<BannerMovil />);
const contenedor = contenedorFijo(); const contenedor = contenedorFijo();
// misma fórmula: con vw < 720px el navegador la evalúa a 16px // misma fórmula: con vw < 720px el navegador la evalúa a 16px
expect(contenedor.getAttribute("style")).toMatch(PATRON_ALINEADO_CUERPO); assertAlineadoAlCuerpo(contenedor.getAttribute("style"));
expect(contenedor.style.bottom).toBe("0px"); expect(contenedor.style.bottom).toBe("0px");
expect(contenedor.style.right).toBe(""); expect(contenedor.style.right).toBe("");
const tarjeta = screen.getByRole("button", { name: "Cerrar aviso de instalación" }).parentElement; const tarjeta = screen.getByRole("button", { name: "Cerrar aviso de instalación" }).parentElement;
+7 -2
View File
@@ -59,8 +59,13 @@ describe("BotonFlotante", () => {
const contenedor = boton.closest("div").parentElement; // button → relativo → fijo const contenedor = boton.closest("div").parentElement; // button → relativo → fijo
expect(contenedor.style.position).toBe("fixed"); expect(contenedor.style.position).toBe("fixed");
expect(contenedor.style.bottom).toBe("0px"); expect(contenedor.style.bottom).toBe("0px");
// en pantallas anchas acompaña a la columna de 720px; mínimo 16px // en pantallas anchas acompaña a la columna de 720px; mínimo 16px.
expect(contenedor.getAttribute("style")).toMatch(/right:\s*max\(16px,\s*[^;]*100vw[^;]*720px[^;]*16px[^;]*\)/); // (la serialización exacta de max()/calc() varía entre versiones de jsdom)
const right = (contenedor.getAttribute("style").match(/right:\s*([^;]+)/) || [])[1];
expect(right).toMatch(/max\(/);
expect(right).toContain("100vw");
expect(right).toContain("720px");
expect(right).toContain("16px");
// en PC el FAB mide 64px (en móvil 54) // en PC el FAB mide 64px (en móvil 54)
expect(boton.style.width).toBe("64px"); expect(boton.style.width).toBe("64px");
expect(boton.style.height).toBe("64px"); expect(boton.style.height).toBe("64px");
+7 -2
View File
@@ -30,8 +30,13 @@ describe("BotonProponerArriba (solo PC)", () => {
expect(boton.style.position).toBe("fixed"); expect(boton.style.position).toBe("fixed");
expect(boton.style.top).toBe("20px"); expect(boton.style.top).toBe("20px");
// alineado al borde derecho de la columna de 720px; mínimo 16px // alineado al borde derecho de la columna de 720px; mínimo 16px.
expect(boton.getAttribute("style")).toMatch(/right:\s*max\(16px,\s*[^;]*100vw[^;]*720px[^;]*16px[^;]*\)/); // (la serialización exacta de max()/calc() varía entre versiones de jsdom)
const right = (boton.getAttribute("style").match(/right:\s*([^;]+)/) || [])[1];
expect(right).toMatch(/max\(/);
expect(right).toContain("100vw");
expect(right).toContain("720px");
expect(right).toContain("16px");
fireEvent.click(boton); fireEvent.click(boton);
expect(onClick).toHaveBeenCalledTimes(1); expect(onClick).toHaveBeenCalledTimes(1);