Enhance Jenkinsfile for frontend testing and update Playwright configuration

- Added a new 'E2E (docker compose + Playwright)' stage in the Jenkinsfile to run end-to-end tests using Docker Compose and Playwright.
- Updated the 'Test frontend' stage to utilize the Playwright test image and improved error handling for missing files.
- Modified Playwright configuration to use an environment variable for the base URL, enhancing flexibility in CI environments.
- Expanded TypeScript configuration to include additional test and configuration files for better type checking.
This commit is contained in:
2026-04-24 11:18:57 -05:00
parent 46c98dbc38
commit b8f46d09ae
5 changed files with 116 additions and 16 deletions

64
Jenkinsfile vendored
View File

@@ -13,6 +13,8 @@ pipeline {
environment {
REGISTRY = 'dev.aduanasoft.com'
IMAGE_NAMESPACE = 'anexo76'
// Debe coincidir con @playwright/test del frontend (ver frontend/pnpm-lock)
PLAYWRIGHT_TEST_IMAGE = 'mcr.microsoft.com/playwright:v1.56.1-noble'
}
stages {
@@ -131,15 +133,17 @@ pipeline {
}
}
// Test frontend: OBLIGATORIO usar el repo clonado (WORKSPACE), no la imagen del frontend en Harbor.
// Svelte se compila en el Dockerfile: la imagen de producción solo trae build/ + deps de runtime; no hay fuentes
// para vitest, ni paraglide desde inlang, ni pnpm devDependencies. Imagen usada aquí: solo node:22-bookworm.
// Mismo criterio que Test backend: docker cp (no -v) si Jenkins vive en Docker. Vitest: sin @vitest/browser en CI.
stage('Test frontend') {
// Código = WORKSPACE (docker cp), no la imagen Harbor. Imagen base: mcr.microsoft.com/playwright (Chromium p/ Vitest y E2E).
stage('Test frontend (Vitest + Svelte browser)') {
steps {
sh '''
set -euxo pipefail
echo "== Test frontend (vitest) =="
echo "== Test frontend: vitest (Node + @vitest/browser) con $PLAYWRIGHT_TEST_IMAGE =="
if [ ! -f "$WORKSPACE/frontend/package.json" ]; then
echo "ERROR: $WORKSPACE/frontend/package.json no existe"
ls -la "$WORKSPACE" 2>&1 | head -40
exit 1
fi
FE_CONTAINER="anexo76-test-fe-${BUILD_NUMBER}"
cleanup() {
@@ -148,7 +152,7 @@ pipeline {
trap cleanup EXIT
docker rm -f "$FE_CONTAINER" >/dev/null 2>&1 || true
docker run -d --name "$FE_CONTAINER" node:22-bookworm sleep infinity
docker run -d --name "$FE_CONTAINER" "$PLAYWRIGHT_TEST_IMAGE" sleep infinity
docker exec "$FE_CONTAINER" mkdir -p /workspace
docker cp "$WORKSPACE/." "$FE_CONTAINER:/workspace"
@@ -156,6 +160,7 @@ pipeline {
-e CI=true \
-e NODE_ENV=test \
-e "JENKINS_URL=${JENKINS_URL}" \
-e JENKINS_VITEST_FULL=1 \
-w /workspace/frontend \
"$FE_CONTAINER" \
bash -lc '
@@ -172,6 +177,51 @@ pipeline {
}
}
stage('E2E (docker compose + Playwright)') {
options {
timeout(time: 90, unit: 'MINUTES')
}
steps {
sh '''
set -euxo pipefail
echo "== E2E: levanta docker-compose.yml (host) y pnpm test:e2e =="
if [ ! -f "$WORKSPACE/frontend/package.json" ] || [ ! -f "$WORKSPACE/docker-compose.yml" ]; then
echo "ERROR: faltan archivos de repo (frontend o compose)"
exit 1
fi
export E2E_COMPOSE_PROJECT="anexo76-e2e-${BUILD_NUMBER}"
export COMPOSE_PROJECT_NAME="${E2E_COMPOSE_PROJECT}"
cd "$WORKSPACE"
compose_down() {
export COMPOSE_PROJECT_NAME="${E2E_COMPOSE_PROJECT}"
docker compose -f "$WORKSPACE/docker-compose.yml" down --remove-orphans 2>/dev/null || true
}
trap compose_down EXIT
compose_down
# Stack completo (API, Keycloak, Vite) — puede tardar varios minutos la 1.ª vez
docker compose -f "$WORKSPACE/docker-compose.yml" up -d --build
bash "$WORKSPACE/scripts/wait-for-jenkins-stack.sh"
# --network host: en Linux el contenedor de tests ve localhost:5173/8000 publicados por compose
docker run --rm --network host \
-e CI=true \
-e "JENKINS_URL=${JENKINS_URL}" \
-e PLAYWRIGHT_TEST_BASE_URL=http://127.0.0.1:5173 \
-v "$WORKSPACE:/workspace" \
-w /workspace/frontend \
"$PLAYWRIGHT_TEST_IMAGE" \
bash -lc '
set -euxo pipefail
test -f package.json
corepack enable
pnpm install --frozen-lockfile
pnpm run i18n:compile
pnpm run test:e2e
'
'''
}
}
stage('Generate version') {
steps {
script {

View File

@@ -1,6 +1,6 @@
import { defineConfig } from '@playwright/test';
import { fileURLToPath } from 'url';
import path from 'path';
import { fileURLToPath } from 'node:url';
import path from 'node:path';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
@@ -13,7 +13,7 @@ export default defineConfig({
forbidOnly: inCI,
timeout: 60000,
use: {
baseURL: 'http://localhost:5173',
baseURL: process.env.PLAYWRIGHT_TEST_BASE_URL || 'http://localhost:5173',
// Sin display en agentes de integración: obligatorio headless
headless: inCI ? true : false
},

View File

@@ -11,7 +11,25 @@
"strict": true,
"moduleResolution": "bundler",
"allowArbitraryExtensions": true
}
},
"include": [
"playwright.config.ts",
"e2e/**/*.ts",
"e2e/**/*.js",
"vitest-setup-client.ts",
"eslint.config.js",
"./.svelte-kit/ambient.d.ts",
"./.svelte-kit/non-ambient.d.ts",
"./.svelte-kit/types/**/$types.d.ts",
"./src/**/*.js",
"./src/**/*.ts",
"./src/**/*.svelte",
"./tests/**/*.js",
"./tests/**/*.ts",
"./tests/**/*.svelte",
"./vite.config.js",
"./vite.config.ts"
]
// Path aliases are handled by https://svelte.dev/docs/kit/configuration#alias
// except $lib which is handled by https://svelte.dev/docs/kit/configuration#files
//

View File

@@ -3,11 +3,12 @@ import tailwindcss from '@tailwindcss/vite';
import { defineConfig } from 'vitest/config';
import { sveltekit } from '@sveltejs/kit/vite';
/* Jenkins / CI: sin navegador ni pnpm exec playwright install (Vitest 3+ intenta aun levantar el project "client" si queda en la config). */
const vitestNoBrowser =
process.env.CI === 'true' ||
Boolean(process.env.JENKINS_URL) ||
process.env.VITEST_NO_BROWSER === '1';
/* En CI, por defecto solo Node (evita Chromium). Con JENKINS_VITEST_FULL=1 o VITEST_FULL=1, también @vitest/browser. */
const inCi = process.env.CI === 'true' || Boolean(process.env.JENKINS_URL);
const vitestFull =
process.env.VITEST_FULL === '1' || process.env.JENKINS_VITEST_FULL === '1';
const skipBrowser = process.env.VITEST_NO_BROWSER === '1';
const vitestNoBrowser = (inCi && !vitestFull) || skipBrowser;
const vitestServerProject = {
extends: './vite.config.ts',

View File

@@ -0,0 +1,31 @@
#!/usr/bin/env bash
# Espera API y Vite levantados en el host (tras docker compose), para E2E en CI.
set -euo pipefail
BACKEND_MAX_SEC="${BACKEND_MAX_SEC:-600}"
FRONTEND_MAX_SEC="${FRONTEND_MAX_SEC:-300}"
i=0
while true; do
if curl -fsS "http://localhost:8000/api/health" >/dev/null 2>&1; then
echo "== stack: backend listo =="
break
fi
i=$((i + 2))
if [ "$i" -ge "$BACKEND_MAX_SEC" ]; then
echo "ERROR: timeout esperando http://localhost:8000/api/health (${BACKEND_MAX_SEC}s)"
exit 1
fi
sleep 2
done
i=0
while true; do
if curl -fsS "http://localhost:5173/" >/dev/null 2>&1; then
echo "== stack: frontend listo =="
exit 0
fi
i=$((i + 2))
if [ "$i" -ge "$FRONTEND_MAX_SEC" ]; then
echo "ERROR: timeout esperando http://localhost:5173/ (${FRONTEND_MAX_SEC}s)"
exit 1
fi
sleep 2
done