test: refs #6695 run e2e in parallel in local
gitea/salix-front/pipeline/pr-dev There was a failure building this commit
Details
gitea/salix-front/pipeline/pr-dev There was a failure building this commit
Details
This commit is contained in:
parent
6d2268e433
commit
7704c764e8
|
@ -20,7 +20,7 @@ export default defineConfig({
|
||||||
downloadsFolder: 'test/cypress/downloads',
|
downloadsFolder: 'test/cypress/downloads',
|
||||||
video: false,
|
video: false,
|
||||||
specPattern: 'test/cypress/integration/**/*.spec.js',
|
specPattern: 'test/cypress/integration/**/*.spec.js',
|
||||||
// specPattern: 'test/cypress/integration/route/routeList.spec.js',
|
// specPattern: 'test/cypress/integration/client/clientList.spec.js',
|
||||||
experimentalRunAllSpecs: true,
|
experimentalRunAllSpecs: true,
|
||||||
watchForFileChanges: true,
|
watchForFileChanges: true,
|
||||||
reporter: 'cypress-mochawesome-reporter',
|
reporter: 'cypress-mochawesome-reporter',
|
||||||
|
@ -39,8 +39,8 @@ export default defineConfig({
|
||||||
},
|
},
|
||||||
setupNodeEvents: async (on, config) => {
|
setupNodeEvents: async (on, config) => {
|
||||||
on('file:preprocessor', vitePreprocessor());
|
on('file:preprocessor', vitePreprocessor());
|
||||||
const plugin = await import('cypress-mochawesome-reporter/plugin');
|
// const plugin = await import('cypress-mochawesome-reporter/plugin');
|
||||||
plugin.default(on);
|
// plugin.default(on);
|
||||||
return config;
|
return config;
|
||||||
},
|
},
|
||||||
viewportWidth: 1280,
|
viewportWidth: 1280,
|
||||||
|
|
|
@ -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
|
||||||
|
#
|
|
@ -21,14 +21,21 @@ services:
|
||||||
# ports:
|
# ports:
|
||||||
# - '9000:9000'
|
# - '9000:9000'
|
||||||
e2e:
|
e2e:
|
||||||
image: alexmorenovn/vndev:latest
|
image: cypress-setup:latest
|
||||||
# command: pnpm exec cypress run --browser chromium
|
command: sh -c "while [ ! -d node_modules/cypress ]; do sleep 1; done && pnpm exec cypress run --browser chromium"
|
||||||
command: sh -c "pnpm exec cypress install && pnpm exec cypress run --headed"
|
|
||||||
environment:
|
environment:
|
||||||
- TZ=Europe/Madrid
|
- TZ=Europe/Madrid
|
||||||
volumes:
|
volumes:
|
||||||
- .:/app
|
- .:/app
|
||||||
working_dir: /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:
|
vn-database:
|
||||||
image: alexmorenovn/vn_db:latest
|
image: alexmorenovn/vn_db:latest
|
||||||
# ports:
|
# ports:
|
||||||
|
|
|
@ -3,3 +3,4 @@ screenshots/*
|
||||||
storage/*
|
storage/*
|
||||||
reports/*
|
reports/*
|
||||||
downloads/*
|
downloads/*
|
||||||
|
docker/logs/*
|
||||||
|
|
|
@ -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
|
|
@ -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
|
||||||
|
}
|
|
@ -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
|
|
@ -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
|
||||||
|
}
|
|
@ -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
|
|
@ -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
|
||||||
|
}
|
|
@ -8,7 +8,11 @@ describe('ClaimNotes', () => {
|
||||||
|
|
||||||
it('should add a new note', () => {
|
it('should add a new note', () => {
|
||||||
const message = 'This is a new message.';
|
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(saveBtn).click();
|
||||||
cy.get(firstNote).should('have.text', message);
|
cy.get(firstNote).should('have.text', message);
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue