Merge pull request 'feature/testing' (#314) from feature/testing into development
Reviewed-on: ADUANASOFT/anexo76#314
This commit is contained in:
81
Jenkinsfile
vendored
81
Jenkinsfile
vendored
@@ -13,6 +13,8 @@ pipeline {
|
|||||||
environment {
|
environment {
|
||||||
REGISTRY = 'dev.aduanasoft.com'
|
REGISTRY = 'dev.aduanasoft.com'
|
||||||
IMAGE_NAMESPACE = 'anexo76'
|
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 {
|
stages {
|
||||||
@@ -131,23 +133,39 @@ pipeline {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Frontend: i18n (paraglide no versionado) + vitest solo proyecto "server" (Node).
|
// Código = WORKSPACE (docker cp), no la imagen Harbor. Imagen base: mcr.microsoft.com/playwright (Chromium p/ Vitest y E2E).
|
||||||
* "client" usa @vitest/browser+Playwright: requeriría playwright install (chromium) en el contenedor.
|
stage('Test frontend (Vitest + Svelte browser)') {
|
||||||
* pnpm run check svelte-check se omite mientras haya deuda de tipos en el árbol; pnpm run lint alinear cuando pase. */
|
|
||||||
stage('Test frontend') {
|
|
||||||
steps {
|
steps {
|
||||||
sh '''
|
sh '''
|
||||||
set -euxo pipefail
|
set -euxo pipefail
|
||||||
echo "== Test frontend (vitest —project server) =="
|
echo "== Test frontend: vitest (Node + @vitest/browser) con $PLAYWRIGHT_TEST_IMAGE =="
|
||||||
docker run --rm \
|
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() {
|
||||||
|
docker rm -f "$FE_CONTAINER" >/dev/null 2>&1 || true
|
||||||
|
}
|
||||||
|
trap cleanup EXIT
|
||||||
|
|
||||||
|
docker rm -f "$FE_CONTAINER" >/dev/null 2>&1 || true
|
||||||
|
docker run -d --name "$FE_CONTAINER" "$PLAYWRIGHT_TEST_IMAGE" sleep infinity
|
||||||
|
docker exec "$FE_CONTAINER" mkdir -p /workspace
|
||||||
|
docker cp "$WORKSPACE/." "$FE_CONTAINER:/workspace"
|
||||||
|
|
||||||
|
docker exec \
|
||||||
-e CI=true \
|
-e CI=true \
|
||||||
-e NODE_ENV=test \
|
-e NODE_ENV=test \
|
||||||
-e JENKINS_URL=${JENKINS_URL} \
|
-e "JENKINS_URL=${JENKINS_URL}" \
|
||||||
-v "$WORKSPACE:/workspace" \
|
-e JENKINS_VITEST_FULL=1 \
|
||||||
-w /workspace/frontend \
|
-w /workspace/frontend \
|
||||||
node:22-bookworm \
|
"$FE_CONTAINER" \
|
||||||
bash -lc '
|
bash -lc '
|
||||||
set -euxo pipefail
|
set -euxo pipefail
|
||||||
|
test -f package.json
|
||||||
node --version
|
node --version
|
||||||
corepack enable
|
corepack enable
|
||||||
pnpm --version
|
pnpm --version
|
||||||
@@ -159,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') {
|
stage('Generate version') {
|
||||||
steps {
|
steps {
|
||||||
script {
|
script {
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ services:
|
|||||||
ports:
|
ports:
|
||||||
- "5432:5432"
|
- "5432:5432"
|
||||||
volumes:
|
volumes:
|
||||||
- postgres_app_data:/var/lib/postgresql/data
|
- postgres_app_data:/var/lib/postgresql
|
||||||
- ./scripts/postgres-app-entrypoint.sh:/docker-entrypoint-initdb.d/init-app.sh:ro
|
- ./scripts/postgres-app-entrypoint.sh:/docker-entrypoint-initdb.d/init-app.sh:ro
|
||||||
networks:
|
networks:
|
||||||
- backend-net
|
- backend-net
|
||||||
@@ -47,7 +47,7 @@ services:
|
|||||||
ports:
|
ports:
|
||||||
- "5433:5432"
|
- "5433:5432"
|
||||||
volumes:
|
volumes:
|
||||||
- postgres_keycloak_data:/var/lib/postgresql/data
|
- postgres_keycloak_data:/var/lib/postgresql
|
||||||
- ./scripts/postgres-keycloak-entrypoint.sh:/docker-entrypoint-initdb.d/init-keycloak.sh:ro
|
- ./scripts/postgres-keycloak-entrypoint.sh:/docker-entrypoint-initdb.d/init-keycloak.sh:ro
|
||||||
networks:
|
networks:
|
||||||
- auth-net
|
- auth-net
|
||||||
@@ -418,16 +418,7 @@ volumes:
|
|||||||
networks:
|
networks:
|
||||||
backend-net:
|
backend-net:
|
||||||
driver: bridge
|
driver: bridge
|
||||||
ipam:
|
|
||||||
config:
|
|
||||||
- subnet: 172.20.0.0/16
|
|
||||||
auth-net:
|
auth-net:
|
||||||
driver: bridge
|
driver: bridge
|
||||||
ipam:
|
|
||||||
config:
|
|
||||||
- subnet: 172.21.0.0/16
|
|
||||||
frontend-net:
|
frontend-net:
|
||||||
driver: bridge
|
driver: bridge
|
||||||
ipam:
|
|
||||||
config:
|
|
||||||
- subnet: 172.22.0.0/16
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { defineConfig } from '@playwright/test';
|
import { defineConfig } from '@playwright/test';
|
||||||
import { fileURLToPath } from 'url';
|
import { fileURLToPath } from 'node:url';
|
||||||
import path from 'path';
|
import path from 'node:path';
|
||||||
|
|
||||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||||
|
|
||||||
@@ -13,7 +13,7 @@ export default defineConfig({
|
|||||||
forbidOnly: inCI,
|
forbidOnly: inCI,
|
||||||
timeout: 60000,
|
timeout: 60000,
|
||||||
use: {
|
use: {
|
||||||
baseURL: 'http://localhost:5173',
|
baseURL: process.env.PLAYWRIGHT_TEST_BASE_URL || 'http://localhost:5173',
|
||||||
// Sin display en agentes de integración: obligatorio headless
|
// Sin display en agentes de integración: obligatorio headless
|
||||||
headless: inCI ? true : false
|
headless: inCI ? true : false
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -11,7 +11,25 @@
|
|||||||
"strict": true,
|
"strict": true,
|
||||||
"moduleResolution": "bundler",
|
"moduleResolution": "bundler",
|
||||||
"allowArbitraryExtensions": true
|
"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
|
// 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
|
// except $lib which is handled by https://svelte.dev/docs/kit/configuration#files
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -3,11 +3,12 @@ import tailwindcss from '@tailwindcss/vite';
|
|||||||
import { defineConfig } from 'vitest/config';
|
import { defineConfig } from 'vitest/config';
|
||||||
import { sveltekit } from '@sveltejs/kit/vite';
|
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). */
|
/* En CI, por defecto solo Node (evita Chromium). Con JENKINS_VITEST_FULL=1 o VITEST_FULL=1, también @vitest/browser. */
|
||||||
const vitestNoBrowser =
|
const inCi = process.env.CI === 'true' || Boolean(process.env.JENKINS_URL);
|
||||||
process.env.CI === 'true' ||
|
const vitestFull =
|
||||||
Boolean(process.env.JENKINS_URL) ||
|
process.env.VITEST_FULL === '1' || process.env.JENKINS_VITEST_FULL === '1';
|
||||||
process.env.VITEST_NO_BROWSER === '1';
|
const skipBrowser = process.env.VITEST_NO_BROWSER === '1';
|
||||||
|
const vitestNoBrowser = (inCi && !vitestFull) || skipBrowser;
|
||||||
|
|
||||||
const vitestServerProject = {
|
const vitestServerProject = {
|
||||||
extends: './vite.config.ts',
|
extends: './vite.config.ts',
|
||||||
|
|||||||
31
scripts/wait-for-jenkins-stack.sh
Executable file
31
scripts/wait-for-jenkins-stack.sh
Executable 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
|
||||||
Reference in New Issue
Block a user