feat: infraestructura base para E2E tests con Playwright
Proyecto Node.js independiente en e2e/ con Playwright + Chromium headless. Incluye setup-element.sh para descargar y servir Element Web localmente (puerto 8090 por defecto, 8080 ocupado por Docker). Scripts de instalacion y placeholder para ejecucion de tests. Cierra issue 0022a. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
+8
-1
@@ -11,4 +11,11 @@ logs/
|
||||
|
||||
/agentctl
|
||||
/dashboard
|
||||
/verify
|
||||
/verify
|
||||
|
||||
# E2E tests
|
||||
e2e/node_modules/
|
||||
e2e/test-results/
|
||||
e2e/.auth/
|
||||
e2e/.env
|
||||
e2e/element-web/
|
||||
Executable
+42
@@ -0,0 +1,42 @@
|
||||
#!/usr/bin/env bash
|
||||
# install.sh — instalar dependencias para E2E tests
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
E2E_DIR="$REPO_ROOT/e2e"
|
||||
|
||||
echo "=== Instalacion de E2E tests ==="
|
||||
|
||||
# 1. Verificar Node.js
|
||||
if ! command -v node &>/dev/null; then
|
||||
echo "ERROR: Node.js no encontrado."
|
||||
echo "Instalar Node.js v18+ con:"
|
||||
echo " curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -"
|
||||
echo " sudo apt-get install -y nodejs"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
NODE_VERSION=$(node -v | sed 's/v//' | cut -d. -f1)
|
||||
if [ "$NODE_VERSION" -lt 18 ]; then
|
||||
echo "ERROR: Se requiere Node.js v18+, encontrado v$(node -v)"
|
||||
exit 1
|
||||
fi
|
||||
echo "Node.js $(node -v) OK"
|
||||
|
||||
# 2. Instalar dependencias del proyecto
|
||||
echo "Instalando dependencias npm..."
|
||||
cd "$E2E_DIR"
|
||||
npm ci
|
||||
|
||||
# 3. Instalar Chromium para Playwright
|
||||
echo "Instalando Chromium para Playwright..."
|
||||
npx playwright install chromium
|
||||
|
||||
# 4. Instalar dependencias del sistema para Playwright
|
||||
echo "Instalando dependencias del sistema (requiere sudo)..."
|
||||
sudo npx playwright install-deps chromium
|
||||
|
||||
echo ""
|
||||
echo "=== Instalacion completa ==="
|
||||
echo "Siguiente paso: copiar e2e/.env.example a e2e/.env y configurar credenciales"
|
||||
Executable
+26
@@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env bash
|
||||
# run.sh — ejecutar E2E tests con Playwright
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
E2E_DIR="$REPO_ROOT/e2e"
|
||||
|
||||
# Verificar dependencias instaladas
|
||||
if [ ! -d "$E2E_DIR/node_modules" ]; then
|
||||
echo "ERROR: node_modules no encontrado. Ejecutar primero:"
|
||||
echo " ./dev-scripts/e2e/install.sh"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verificar .env
|
||||
if [ ! -f "$E2E_DIR/.env" ]; then
|
||||
echo "ERROR: e2e/.env no encontrado. Crear desde el template:"
|
||||
echo " cp e2e/.env.example e2e/.env"
|
||||
echo " # editar e2e/.env con credenciales"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Los tests E2E se agregan en el issue 0022c."
|
||||
echo "Cuando esten listos, ejecutar:"
|
||||
echo " cd $E2E_DIR && npx playwright test"
|
||||
@@ -27,6 +27,6 @@ afectados y notas de implementacion.
|
||||
| 20 | Aislar claude -p del repo | [0020-claude-code-sandbox.md](completed/0020-claude-code-sandbox.md) | completado |
|
||||
| 21 | Threads default config | (completado via branch) | completado |
|
||||
| 22 | Tests E2E con Playwright | [0022-e2e-tests-playwright.md](0022-e2e-tests-playwright.md) | pendiente |
|
||||
| 22a | E2E: Infraestructura base | [0022a-e2e-infra.md](0022a-e2e-infra.md) | pendiente |
|
||||
| 22a | E2E: Infraestructura base | [0022a-e2e-infra.md](completed/0022a-e2e-infra.md) | completado |
|
||||
| 22b | E2E: Auth fixtures y helpers | [0022b-e2e-auth-helpers.md](0022b-e2e-auth-helpers.md) | pendiente |
|
||||
| 22c | E2E: Tests de agentes + docs | [0022c-e2e-agent-tests.md](0022c-e2e-agent-tests.md) | pendiente |
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
ELEMENT_URL=http://localhost:8090
|
||||
MATRIX_HOMESERVER=https://matrix-af2f3d.organic-machine.com
|
||||
MATRIX_USER=@test-user:matrix-af2f3d.organic-machine.com
|
||||
MATRIX_PASSWORD=
|
||||
MATRIX_RECOVERY_KEY=
|
||||
Generated
+92
@@ -0,0 +1,92 @@
|
||||
{
|
||||
"name": "agents-e2e",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "agents-e2e",
|
||||
"version": "1.0.0",
|
||||
"devDependencies": {
|
||||
"@playwright/test": "^1.50.0",
|
||||
"dotenv": "^16.4.7"
|
||||
}
|
||||
},
|
||||
"node_modules/@playwright/test": {
|
||||
"version": "1.58.2",
|
||||
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.58.2.tgz",
|
||||
"integrity": "sha512-akea+6bHYBBfA9uQqSYmlJXn61cTa+jbO87xVLCWbTqbWadRVmhxlXATaOjOgcBaWU4ePo0wB41KMFv3o35IXA==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"playwright": "1.58.2"
|
||||
},
|
||||
"bin": {
|
||||
"playwright": "cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/dotenv": {
|
||||
"version": "16.6.1",
|
||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz",
|
||||
"integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://dotenvx.com"
|
||||
}
|
||||
},
|
||||
"node_modules/fsevents": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
|
||||
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/playwright": {
|
||||
"version": "1.58.2",
|
||||
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.58.2.tgz",
|
||||
"integrity": "sha512-vA30H8Nvkq/cPBnNw4Q8TWz1EJyqgpuinBcHET0YVJVFldr8JDNiU9LaWAE1KqSkRYazuaBhTpB5ZzShOezQ6A==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"playwright-core": "1.58.2"
|
||||
},
|
||||
"bin": {
|
||||
"playwright": "cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"fsevents": "2.3.2"
|
||||
}
|
||||
},
|
||||
"node_modules/playwright-core": {
|
||||
"version": "1.58.2",
|
||||
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.58.2.tgz",
|
||||
"integrity": "sha512-yZkEtftgwS8CsfYo7nm0KE8jsvm6i/PTgVtB8DL726wNf6H2IMsDuxCpJj59KDaxCtSnrWan2AeDqM7JBaultg==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"bin": {
|
||||
"playwright-core": "cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "agents-e2e",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"description": "E2E tests for agents_and_robots via Playwright + Element Web",
|
||||
"scripts": {
|
||||
"test": "npx playwright test",
|
||||
"test:headed": "npx playwright test --headed",
|
||||
"test:debug": "npx playwright test --debug"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@playwright/test": "^1.50.0",
|
||||
"dotenv": "^16.4.7"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
import { defineConfig, devices } from "@playwright/test";
|
||||
import * as dotenv from "dotenv";
|
||||
import * as path from "path";
|
||||
|
||||
dotenv.config({ path: path.resolve(__dirname, ".env") });
|
||||
|
||||
export default defineConfig({
|
||||
testDir: "./tests",
|
||||
fullyParallel: false,
|
||||
forbidOnly: !!process.env.CI,
|
||||
retries: process.env.CI ? 1 : 0,
|
||||
workers: 1,
|
||||
reporter: "list",
|
||||
|
||||
// LLMs son lentos — timeouts generosos
|
||||
timeout: 60_000,
|
||||
expect: { timeout: 30_000 },
|
||||
|
||||
use: {
|
||||
baseURL: process.env.ELEMENT_URL || "http://localhost:8080",
|
||||
headless: true,
|
||||
screenshot: "only-on-failure",
|
||||
trace: "on-first-retry",
|
||||
actionTimeout: 30_000,
|
||||
},
|
||||
|
||||
globalSetup: "./global-setup.ts",
|
||||
|
||||
projects: [
|
||||
{
|
||||
name: "chromium",
|
||||
use: { ...devices["Desktop Chrome"] },
|
||||
},
|
||||
],
|
||||
});
|
||||
Executable
+116
@@ -0,0 +1,116 @@
|
||||
#!/usr/bin/env bash
|
||||
# setup-element.sh — descargar y servir Element Web localmente
|
||||
set -euo pipefail
|
||||
|
||||
ELEMENT_VERSION="v1.11.92"
|
||||
ELEMENT_DIR="$(cd "$(dirname "$0")/.." && pwd)/element-web"
|
||||
PORT="${ELEMENT_PORT:-8090}"
|
||||
PIDFILE="$ELEMENT_DIR/.server.pid"
|
||||
HOMESERVER="${MATRIX_HOMESERVER:-https://matrix-af2f3d.organic-machine.com}"
|
||||
SERVER_NAME="${MATRIX_SERVER_NAME:-matrix-af2f3d.organic-machine.com}"
|
||||
|
||||
usage() {
|
||||
echo "Uso: $0 {start|stop|status}"
|
||||
echo ""
|
||||
echo " start Descargar Element Web (si falta) y servir en puerto $PORT"
|
||||
echo " stop Detener el servidor local"
|
||||
echo " status Verificar si el servidor esta corriendo"
|
||||
exit 1
|
||||
}
|
||||
|
||||
download_element() {
|
||||
if [ -d "$ELEMENT_DIR" ] && [ -f "$ELEMENT_DIR/index.html" ]; then
|
||||
echo "Element Web ya descargado en $ELEMENT_DIR"
|
||||
return 0
|
||||
fi
|
||||
|
||||
local tarball="element-${ELEMENT_VERSION}.tar.gz"
|
||||
local url="https://github.com/element-hq/element-web/releases/download/${ELEMENT_VERSION}/element-${ELEMENT_VERSION}.tar.gz"
|
||||
|
||||
echo "Descargando Element Web ${ELEMENT_VERSION}..."
|
||||
mkdir -p "$ELEMENT_DIR"
|
||||
curl -fSL "$url" -o "/tmp/$tarball"
|
||||
tar xzf "/tmp/$tarball" --strip-components=1 -C "$ELEMENT_DIR"
|
||||
rm -f "/tmp/$tarball"
|
||||
|
||||
echo "Generando config.json para homeserver $HOMESERVER..."
|
||||
cat > "$ELEMENT_DIR/config.json" <<CONF
|
||||
{
|
||||
"default_server_config": {
|
||||
"m.homeserver": {
|
||||
"base_url": "$HOMESERVER",
|
||||
"server_name": "$SERVER_NAME"
|
||||
}
|
||||
},
|
||||
"brand": "Element",
|
||||
"disable_guests": true,
|
||||
"disable_3pid_login": true
|
||||
}
|
||||
CONF
|
||||
|
||||
echo "Element Web ${ELEMENT_VERSION} listo en $ELEMENT_DIR"
|
||||
}
|
||||
|
||||
start_server() {
|
||||
if [ -f "$PIDFILE" ] && kill -0 "$(cat "$PIDFILE")" 2>/dev/null; then
|
||||
echo "Element Web ya corriendo (PID $(cat "$PIDFILE")) en http://localhost:$PORT"
|
||||
return 0
|
||||
fi
|
||||
|
||||
download_element
|
||||
|
||||
echo "Iniciando servidor en http://localhost:$PORT ..."
|
||||
if command -v python3 &>/dev/null; then
|
||||
(cd "$ELEMENT_DIR" && python3 -m http.server "$PORT" --bind 0.0.0.0) &>/dev/null &
|
||||
elif command -v npx &>/dev/null; then
|
||||
npx --yes serve -s "$ELEMENT_DIR" -l "$PORT" &>/dev/null &
|
||||
else
|
||||
echo "Error: necesitas python3 o npx (Node.js) para servir archivos"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo $! > "$PIDFILE"
|
||||
|
||||
# Esperar a que el servidor arranque
|
||||
for i in 1 2 3 4 5; do
|
||||
if curl -sf "http://localhost:$PORT/" >/dev/null 2>&1; then
|
||||
echo "Element Web serving en http://localhost:$PORT (PID $!)"
|
||||
return 0
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
echo "WARN: servidor iniciado (PID $!) pero no responde aun en http://localhost:$PORT"
|
||||
}
|
||||
|
||||
stop_server() {
|
||||
if [ ! -f "$PIDFILE" ]; then
|
||||
echo "No hay servidor corriendo (no se encontro pidfile)"
|
||||
return 0
|
||||
fi
|
||||
|
||||
local pid
|
||||
pid=$(cat "$PIDFILE")
|
||||
if kill -0 "$pid" 2>/dev/null; then
|
||||
kill "$pid"
|
||||
echo "Servidor detenido (PID $pid)"
|
||||
else
|
||||
echo "Proceso $pid ya no existe"
|
||||
fi
|
||||
rm -f "$PIDFILE"
|
||||
}
|
||||
|
||||
server_status() {
|
||||
if [ -f "$PIDFILE" ] && kill -0 "$(cat "$PIDFILE")" 2>/dev/null; then
|
||||
echo "Element Web corriendo (PID $(cat "$PIDFILE")) en http://localhost:$PORT"
|
||||
else
|
||||
echo "Element Web no esta corriendo"
|
||||
[ -f "$PIDFILE" ] && rm -f "$PIDFILE"
|
||||
fi
|
||||
}
|
||||
|
||||
case "${1:-}" in
|
||||
start) start_server ;;
|
||||
stop) stop_server ;;
|
||||
status) server_status ;;
|
||||
*) usage ;;
|
||||
esac
|
||||
Reference in New Issue
Block a user