fix(ci): compatibilidad con el runner self-hosted (npm 10 / Node 20)
- vitest 4 traía vite 8 anidado con esbuild 0.28: el lockfile quedaba incompleto para npm ci y el npm 10.8.2 del runner fallaba con "Missing @esbuild/* from lock file" / EBADPLATFORM. vitest 3 usa el vite 5 del proyecto como peer: sin árbol anidado, esbuild solo 0.21.5 - jsdom 30 exige Node >=22.22 (el runner tiene 20.20): bajado a jsdom 26 - tests.yml sobre el runner real (self-hosted, Node del sistema) en vez de ubuntu-latest, que no existe como label - aserciones de max()/calc() tolerantes a la serialización de jsdom 26
This commit is contained in:
@@ -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
|
||||||
|
|
||||||
|
|||||||
Generated
+686
-1273
File diff suppressed because it is too large
Load Diff
+2
-2
@@ -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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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");
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user