test: refs #6695 run e2e in parallel in local
gitea/salix-front/pipeline/pr-dev There was a failure building this commit Details

This commit is contained in:
Alex Moreno 2025-02-14 13:34:16 +01:00
parent 6d2268e433
commit 7704c764e8
11 changed files with 342 additions and 7 deletions

View File

@ -20,7 +20,7 @@ export default defineConfig({
downloadsFolder: 'test/cypress/downloads',
video: false,
specPattern: 'test/cypress/integration/**/*.spec.js',
// specPattern: 'test/cypress/integration/route/routeList.spec.js',
// specPattern: 'test/cypress/integration/client/clientList.spec.js',
experimentalRunAllSpecs: true,
watchForFileChanges: true,
reporter: 'cypress-mochawesome-reporter',
@ -39,8 +39,8 @@ export default defineConfig({
},
setupNodeEvents: async (on, config) => {
on('file:preprocessor', vitePreprocessor());
const plugin = await import('cypress-mochawesome-reporter/plugin');
plugin.default(on);
// const plugin = await import('cypress-mochawesome-reporter/plugin');
// plugin.default(on);
return config;
},
viewportWidth: 1280,

View File

@ -0,0 +1,99 @@
version: '3.7'
services:
back:
image: registry.verdnatura.es/salix-back:25.08.0-build1314
# image: back_try
volumes:
- ./test/cypress/storage:/salix/storage
- ./test/cypress/back/datasources.json:/salix/loopback/server/datasources.json
depends_on:
- vn-database
# ports:
# - '3000:3000'
front:
image: alexmorenovn/vndev:latest
command: quasar dev
volumes:
- .:/app:delegated
working_dir: /app
environment:
- TZ=Europe/Madrid
# ports:
# - '9000:9000'
e2e:
image: cypress-setup:latest
command: sh -c "while [ ! -d node_modules/cypress ]; do sleep 1; done && pnpm exec cypress run --browser chromium --spec ${CYPRESS_SPEC:?}"
environment:
- TZ=Europe/Madrid
volumes:
- .:/app
working_dir: /app
cypress-setup:
image: cypress-setup:latest
build:
context: .
dockerfile: ./test/cypress/Dockerfile
command: sh -c "pnpm install --frozen-lockfile && pnpm exec cypress install"
volumes:
- .:/app:delegated
vn-database:
image: alexmorenovn/vn_db:latest
# ports:
# - '3306:3306'
# e2e:
# command: npx cypress run --browser chromium
# build:
# context: .
# dockerfile: ./Dockerfile.e2e
# volumes:
# - .:/app
# working_dir: /app
# front:
# # command: pnpx quasar dev
# # command: npx quasar serve --history --proxy ./proxy.mjs --hostname 127.0.0.1 --port 9000
# build:
# context: .
# dockerfile: ./Dockerfile.e2e
# network_mode: host
# e2e:
# command: pnpx cypress run --browser chromium
# build:
# context: .
# dockerfile: ./Dockerfile.e2e
# network_mode: host
# volumes:
# - ./node_modules:/app/node_modules
# db:
# image: db
# command: npx myt run -t --ci -d -n front_default
# build:
# context: .
# dockerfile: test/cypress/db/Dockerfile
# network_mode: host
# privileged: true
# volumes:
# - /var/run/docker.sock:/var/run/docker.sock
# back:
# image: back
# build:
# context: ./salix
# dockerfile: salix/back/Dockerfile
# # depends_on:
# # - db
# ports:
# - 3000:3000
# - 5000:5000
# volumes:
# - ./test/cypress/storage:/salix/storage
# e2e-2:
# image: registry.verdnatura.es/salix-frontend:${VERSION:?}
# command: npx cypress run --config-file test/cypress/configs/cypress.config.2.js
# build:
# context: .
# dockerfile: ./Dockerfile.e2e
#

View File

@ -21,14 +21,21 @@ services:
# ports:
# - '9000:9000'
e2e:
image: alexmorenovn/vndev:latest
# command: pnpm exec cypress run --browser chromium
command: sh -c "pnpm exec cypress install && pnpm exec cypress run --headed"
image: cypress-setup:latest
command: sh -c "while [ ! -d node_modules/cypress ]; do sleep 1; done && pnpm exec cypress run --browser chromium"
environment:
- TZ=Europe/Madrid
volumes:
- .:/app
working_dir: /app
cypress-setup:
image: cypress-setup:latest
build:
context: .
dockerfile: ./test/cypress/Dockerfile
command: sh -c "pnpm install --frozen-lockfile && pnpm exec cypress install"
volumes:
- .:/app
vn-database:
image: alexmorenovn/vn_db:latest
# ports:

View File

@ -3,3 +3,4 @@ screenshots/*
storage/*
reports/*
downloads/*
docker/logs/*

12
test/cypress/Dockerfile Normal file
View File

@ -0,0 +1,12 @@
FROM alexmorenovn/vndev:latest
WORKDIR /app
# Copiar los archivos de package.json y pnpm-lock.yaml para evitar reinstalar dependencias innecesariamente
COPY package.json pnpm-lock.yaml ./
# Instalar solo Cypress sin instalar todas las dependencias del proyecto
RUN pnpm install --frozen-lockfile && pnpm exec cypress install
# Definir el directorio de trabajo por defecto
WORKDIR /app

View File

@ -0,0 +1,24 @@
#!/bin/bash
cleanup() {
echo "⏹ Deteniendo ejecución..."
# Detener todos los procesos en paralelo
kill "${pids[@]}" 2>/dev/null
# Buscar y eliminar contenedores que comiencen con NETWORK
containers=$(docker ps -aq --filter "name=^${NETWORK}")
if [[ -n "$containers" ]]; then
# echo "🧹 Eliminando contenedores: $containers"
docker rm -fv $containers >/dev/null 2>&1 || true
echo "✅ → ⏹🧹 Detenido y eliminado contenedores correctamente"
fi
# Buscar y eliminar redes que comiencen con NETWORK
networks=$(docker network ls --format '{{.Name}}' | grep "^${NETWORK}" || true)
if [[ -n "$networks" ]]; then
# echo "🧹 Eliminando redes: $networks"
docker network rm $networks >/dev/null 2>&1 || true
echo "✅ → 🧹 Redes eliminadas correctamente"
fi
}

View File

@ -0,0 +1,26 @@
#!/bin/bash
# Cargar módulos
source "$(dirname "$0")/cleanup.sh"
source "$(dirname "$0")/setup.sh"
source "$(dirname "$0")/run_group.sh"
source "$(dirname "$0")/summary.sh"
# Manejo de señales para limpiar si se interrumpe el script
trap cleanup SIGINT
# Ejecutar grupos en paralelo y almacenar PIDs
for i in "${!groups[@]}"; do
run_group "${groups[$i]}" "$((i+1))" & # Ejecutar en segundo plano
pids+=($!) # Guardar el PID del proceso
done
# Esperar a que terminen todos los procesos en segundo plano
wait "${pids[@]}"
# Generar el resumen final
generate_summary
# Limpiar contenedores al finalizar
cleanup
exit 0

View File

@ -0,0 +1,102 @@
#!/bin/bash
# Función para esperar a que un servicio devuelva un JSON con `{ "status": true }` en la red de Docker
wait_for_api_ready() {
local service_name="$1"
local container_name="$2"
local port="$3"
local path="$4"
local network="$5"
local max_retries=30 # Máximo de intentos (30 segundos)
local retries=0
local url="http://$container_name:$port$path"
# echo "⏳ Esperando a que $service_name devuelva exactamente 'true' en $url..."
while [[ $retries -lt $max_retries ]]; do
response=$(docker run --rm --network="$network" curlimages/curl -s "$url" || echo "error")
# echo "🔍 Respuesta recibida de $service_name: '$response'"
if [[ "$response" == "true" ]]; then
# echo "✅ Conectado al servicio $service_name → $url!"
return 0
fi
sleep 1
((retries++))
done
echo "❌ ERROR: $service_name no respondió con 'true' en $url después de $max_retries intentos."
exit 1
}
run_group() {
local group="$1"
local parallelIndex="$2"
local groupIndex=1
echo "=== Ejecutando grupo paralelo ${parallelIndex} ==="
docker-compose -p lilium-e2e -f docker-compose.e2e.local.yml build cypress-setup >/dev/null 2>&1
for testFolder in $group; do
folderName=$(basename "$testFolder" | tr -cd 'a-zA-Z0-9_-')
uniqueName="${NETWORK}_${folderName}_${parallelIndex}_${groupIndex}"
echo "🔹 $folderName (Grupo: $parallelIndex, Índice: $groupIndex)"
export CYPRESS_SPEC="test/cypress/integration/${folderName}/**/*.spec.js"
# Iniciar servicios del backend y frontend
docker-compose -p "$uniqueName" -f docker-compose.e2e.local.yml up -d back >/dev/null 2>&1
docker-compose -p "$uniqueName" -f docker-compose.e2e.local.yml up -d front >/dev/null 2>&1
# 🔹 Esperar a que la API en /api/Applications/status devuelva { "status": true }
wait_for_api_ready "Aplicación" "front" 9000 "/api/Applications/status" "${uniqueName}_default"
# 🚀 Ejecutar pruebas en modo detach
docker-compose -p "$uniqueName" -f docker-compose.e2e.local.yml up -d e2e >/dev/null 2>&1
# 🔹 Esperar hasta que el contenedor de Cypress finalice
container_id=""
max_retries=10
retries=0
while [[ -z "$container_id" && $retries -lt $max_retries ]]; do
sleep 2
container_id=$(docker-compose -p "$uniqueName" -f docker-compose.e2e.local.yml ps -q e2e)
((retries++))
done
if [[ -z "$container_id" ]]; then
echo "⚠️ No se pudo obtener el contenedor para ${folderName} después de $max_retries intentos"
failedTests+=("$folderName")
continue
fi
# echo "📦 Contenedor $container_id encontrado. Esperando a que finalice..."
# 🔹 Esperar activamente a que el contenedor finalice
while true; do
container_status=$(docker inspect -f '{{.State.Running}}' "$container_id" 2>/dev/null || echo "false")
if [[ "$container_status" == "false" ]]; then
break
fi
sleep 2
done
# Verificar el código de salida
exit_code=$(docker inspect -f '{{.State.ExitCode}}' "$container_id" 2>/dev/null || echo "1")
if [[ "$exit_code" -ne 0 ]]; then
echo "⚠️ Error en la ejecución de ${folderName} (Exit Code: $exit_code)"
buildResult="UNSTABLE"
docker logs "$container_id" > "test/cypress/docker/logs/${folderName}.log" 2>/dev/null || true
failedTests+=("$folderName")
fi
# Limpiar contenedores
docker-compose -p "$uniqueName" -f docker-compose.e2e.local.yml down >/dev/null 2>&1 || true
((groupIndex++))
done
}

View File

@ -0,0 +1,45 @@
#!/bin/bash
# Configuración: Número de grupos en paralelo (por defecto 4, pero puede sobreescribirse con el primer argumento)
numParallelGroups=${1:-4}
NETWORK="lilium-e2e"
pids=() # Para almacenar los procesos en paralelo
failedTests=() # Para almacenar las carpetas que fallaron
# Limpiar la carpeta de logs antes de cada ejecución
LOG_DIR="test/cypress/docker/logs"
if [[ -d "$LOG_DIR" ]]; then
echo "🧹 Borrando logs anteriores en $LOG_DIR..."
rm -rf "$LOG_DIR"
fi
mkdir -p "$LOG_DIR"
# Verificar si se pasó una carpeta específica como segundo parámetro
if [[ -n "$2" ]]; then
if [[ -d "test/cypress/integration/$2" ]]; then
folders=()
for ((i = 0; i < numParallelGroups; i++)); do
folders+=("test/cypress/integration/$2/")
done
echo "🔍 Ejecutando '$2' en $numParallelGroups instancias paralelas."
else
echo "❌ La carpeta especificada '$2' no existe."
exit 1
fi
else
# Obtener todas las carpetas de pruebas si no se especificó una
folders=($(ls -d test/cypress/integration/*/ 2>/dev/null))
if [[ ${#folders[@]} -eq 0 ]]; then
echo "No se encontraron carpetas de pruebas."
exit 0
fi
fi
# Calcular el tamaño de cada grupo
groupSize=$(( (${#folders[@]} + numParallelGroups - 1) / numParallelGroups )) # Redondeo hacia arriba
# Dividir las carpetas en grupos
groups=()
for ((i = 0; i < ${#folders[@]}; i += groupSize)); do
groups+=("$(printf "%s " "${folders[@]:i:groupSize}")")
done

View File

@ -0,0 +1,15 @@
#!/bin/bash
generate_summary() {
# Verificar si hay archivos en el directorio de logs (indicando fallos)
if [[ -d "$LOG_DIR" && "$(ls -A "$LOG_DIR")" ]]; then
echo "❌ Se encontraron fallos en los siguientes tests:"
for log_file in "$LOG_DIR"/*.log; do
test_name=$(basename "$log_file" .log)
echo " - $test_name (log en $log_file)"
done
exit 1 # Devolver código de error para que Jenkins lo detecte
else
echo "✅ Todas las pruebas han pasado correctamente."
fi
}

View File

@ -8,7 +8,11 @@ describe('ClaimNotes', () => {
it('should add a new note', () => {
const message = 'This is a new message.';
cy.get('.q-textarea').type(message);
cy.get('.q-textarea')
.should('be.visible')
.should('not.be.disabled')
.type(message);
cy.get(saveBtn).click();
cy.get(firstNote).should('have.text', message);
});