/
uzer_007
/
Rixea
Обзор
Документация
Войти
/
uzer_007
/
Rixea
Код
Запросы
0
Задачи
Вики
Пакеты
5
Релизы
2
CI/CD
Аналитика
Безопасность
master
tools/test-e2e.sh
387 строк
12 KB
uzer_007
feat: первая версия Rixea
02 авг 2026, 22:16
02 авг 2026, 22:16
d4f7504
Код
Авторство
О чём код?
#!/bin/bash set -euo pipefail CONTAINER_RUNTIME="${CONTAINER_RUNTIME:-docker}" CONTAINER_NAME="rixea-e2e-runner-$$" EXECUTABLE="${EXECUTABLE:-rixea}" free_port() { node -e "const s=require('net').createServer();s.listen(0,'127.0.0.1',()=>{process.stdout.write(String(s.address().port));s.close()})" } detect_playwright_mode() { if [ "${PLAYWRIGHT_MODE:-auto}" = "local" ] || [ "${PLAYWRIGHT_MODE:-auto}" = "container" ]; then return fi PLAYWRIGHT_MODE="local" if [ "$(uname -s)" = "Linux" ]; then # playwright only supports ubuntu/debian officially if ! grep -qE '^ID(_LIKE)?=.*(ubuntu|debian)' /etc/os-release 2>/dev/null; then PLAYWRIGHT_MODE="container" fi fi } wait_for_container() { local max_wait=30 local elapsed=0 echo "Waiting for container to start..." while ! (echo > "/dev/tcp/127.0.0.1/$PLAYWRIGHT_SERVER_PORT") 2>/dev/null; do if [ "$("$CONTAINER_RUNTIME" inspect -f '{{.State.Running}}' "$CONTAINER_NAME" 2>/dev/null)" != "true" ]; then echo "Error: container exited before becoming ready." >&2 "$CONTAINER_RUNTIME" logs "$CONTAINER_NAME" >&2 || true return 1 fi if [ "$elapsed" -ge "$max_wait" ]; then echo "Error: container did not become ready after ${max_wait}s." >&2 "$CONTAINER_RUNTIME" logs "$CONTAINER_NAME" >&2 || true return 1 fi sleep 1 elapsed=$((elapsed + 1)) done echo "Container is ready." } wait_for_process_ready() { local process_id=$1 local ready_file=$2 local log_file=$3 local process_name=$4 for _ in $(seq 1 100); do if [ -s "$ready_file" ]; then return fi if ! kill -0 "$process_id" 2>/dev/null; then echo "error: тестовый ${process_name} неожиданно завершился." >&2 cat "$log_file" >&2 || true return 1 fi sleep 0.1 done echo "error: тестовый ${process_name} не успел запуститься." >&2 return 1 } CMD="${1:-run}" if [ "$CMD" = "install" ] || [ "$CMD" = "run" ]; then [ $# -gt 0 ] && shift else CMD="run" fi detect_playwright_mode if [ "$PLAYWRIGHT_MODE" = "container" ]; then if ! command -v "$CONTAINER_RUNTIME" >/dev/null 2>&1; then echo "error: PLAYWRIGHT_MODE=container but '$CONTAINER_RUNTIME' is not installed." >&2 echo "Install docker/podman or set CONTAINER_RUNTIME to an available runtime." >&2 exit 1 fi PLAYWRIGHT_VERSION=$(sed -n 's/.*"@playwright\/test"[[:space:]]*:[[:space:]]*"[^[:digit:]]*\([^"]*\)".*/\1/p' package.json) if ! [[ "$PLAYWRIGHT_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.]+)?$ ]]; then echo "error: invalid @playwright/test version in package.json: '${PLAYWRIGHT_VERSION}'" >&2 exit 1 fi PLAYWRIGHT_IMAGE="mcr.microsoft.com/playwright:v${PLAYWRIGHT_VERSION}-noble" NODE_MODULES_DIR=$(node -p 'require("node:fs").realpathSync("node_modules")') PLAYWRIGHT_CLI=$(node -p 'require("node:fs").realpathSync("node_modules/@playwright/test/cli.js")') case "$PLAYWRIGHT_CLI" in "$NODE_MODULES_DIR"/*) PLAYWRIGHT_CLI_PATH=${PLAYWRIGHT_CLI#"$NODE_MODULES_DIR/"} ;; *) echo "error: CLI Playwright находится вне node_modules." >&2 exit 1 ;; esac fi if [ "$CMD" = "install" ]; then if [ "$PLAYWRIGHT_MODE" = "local" ]; then # on GitHub Actions VMs, playwright's system deps are pre-installed if [ -z "${GITHUB_ACTIONS:-}" ]; then # shellcheck disable=SC2086 # flag string pnpm exec playwright install --with-deps chromium firefox ${PLAYWRIGHT_FLAGS:-} else # shellcheck disable=SC2086 # flag string pnpm exec playwright install chromium firefox ${PLAYWRIGHT_FLAGS:-} fi else echo "Running playwright in container as host distro is not supported by playwright directly" if ! "$CONTAINER_RUNTIME" image inspect "$PLAYWRIGHT_IMAGE" >/dev/null 2>&1; then "$CONTAINER_RUNTIME" pull "$PLAYWRIGHT_IMAGE" fi fi exit 0 fi # Create isolated work directory WORK_DIR=$(mktemp -d) # Find a random free port FREE_PORT=$(free_port) RIXEA_TEST_E2E_DOMAIN="e2e.rixea.local" RIXEA_TEST_E2E_USER="e2e-admin" RIXEA_TEST_E2E_PASSWORD="password" RIXEA_TEST_E2E_EMAIL="$RIXEA_TEST_E2E_USER@$RIXEA_TEST_E2E_DOMAIN" RIXEA_TEST_OIDC_PROVIDER_NAME="Тестовый OpenID Connect" RIXEA_TEST_OIDC_USERNAME="e2e-oidc-user" RIXEA_TEST_OIDC_EMAIL="$RIXEA_TEST_OIDC_USERNAME@$RIXEA_TEST_E2E_DOMAIN" OIDC_CLIENT_ID="rixea-e2e" OIDC_CLIENT_SECRET="rixea-e2e-secret" RIXEA_TEST_OPENID_USERNAME="e2e-openid-identifier-with-a-very-long-unbroken-suffix-0123456789abcdefghijklmnopqrstuvwxyz" cleanup() { if [ "$PLAYWRIGHT_MODE" = "container" ]; then "$CONTAINER_RUNTIME" rm -f "$CONTAINER_NAME" >/dev/null 2>&1 || true fi if [ -n "${OIDC_PID:-}" ]; then kill "$OIDC_PID" 2>/dev/null || true wait "$OIDC_PID" 2>/dev/null || true fi if [ -n "${OPENID_PID:-}" ]; then kill "$OPENID_PID" 2>/dev/null || true wait "$OPENID_PID" 2>/dev/null || true fi if [ -n "${SMTP_PID:-}" ]; then kill "$SMTP_PID" 2>/dev/null || true wait "$SMTP_PID" 2>/dev/null || true fi if [ -n "${SERVER_PID:-}" ]; then kill "$SERVER_PID" 2>/dev/null || true wait "$SERVER_PID" 2>/dev/null || true fi if [ -n "${REINDEXER_DATABASE:-}" ]; then curl -sS -X DELETE "${RIXEA_TEST_REINDEXER_HTTP_BASE:-http://127.0.0.1:9088}/api/v1/db/${REINDEXER_DATABASE}" >/dev/null 2>&1 || true fi if [ -n "${RIXEA_TEST_E2E_KEEP_WORK_DIR:-}" ]; then echo "Диагностический каталог сохранён: $WORK_DIR" else rm -rf "$WORK_DIR" fi } trap cleanup EXIT if [ "$PLAYWRIGHT_MODE" = "container" ]; then PLAYWRIGHT_SERVER_PORT=$(free_port) # The project package exactly matches the image and avoids a network install # inside every short-lived container. "$CONTAINER_RUNTIME" run \ --network=host \ --name "$CONTAINER_NAME" \ --detach \ --init \ --user pwuser \ --volume "$(pwd):/work:ro" \ --volume "$NODE_MODULES_DIR:/work/node_modules:ro" \ --workdir /work \ "$PLAYWRIGHT_IMAGE" \ node "node_modules/$PLAYWRIGHT_CLI_PATH" run-server \ --port "$PLAYWRIGHT_SERVER_PORT" \ --host 0.0.0.0 if ! wait_for_container; then exit 1 fi fi # Изолированный SMTP-приёмник проверяет реальную отправку без внешних служб. SMTP_PORT=$(free_port) while [ "$SMTP_PORT" = "$FREE_PORT" ]; do SMTP_PORT=$(free_port) done SMTP_INBOX="$WORK_DIR/smtp-inbox" SMTP_READY="$WORK_DIR/smtp.ready" mkdir -p "$SMTP_INBOX" node tools/test-smtp-server.mjs \ --host 127.0.0.1 \ --port "$SMTP_PORT" \ --inbox "$SMTP_INBOX" \ --ready "$SMTP_READY" \ >"$WORK_DIR/smtp.log" 2>&1 & SMTP_PID=$! wait_for_process_ready "$SMTP_PID" "$SMTP_READY" "$WORK_DIR/smtp.log" "SMTP-сервер" # Loopback OIDC-провайдер проверяет полный Authorization Code flow. OIDC_PORT=$(free_port) while [ "$OIDC_PORT" = "$FREE_PORT" ] || [ "$OIDC_PORT" = "$SMTP_PORT" ]; do OIDC_PORT=$(free_port) done OIDC_READY="$WORK_DIR/oidc.ready" node tools/test-oidc-server.mjs \ --host 127.0.0.1 \ --port "$OIDC_PORT" \ --app-port "$FREE_PORT" \ --client-id "$OIDC_CLIENT_ID" \ --client-secret "$OIDC_CLIENT_SECRET" \ --username "$RIXEA_TEST_OIDC_USERNAME" \ --email "$RIXEA_TEST_OIDC_EMAIL" \ --ready "$OIDC_READY" \ >"$WORK_DIR/oidc.log" 2>&1 & OIDC_PID=$! wait_for_process_ready "$OIDC_PID" "$OIDC_READY" "$WORK_DIR/oidc.log" "OIDC-провайдер" # Локальный OpenID 2.0-провайдер проверяет discovery, подпись утверждения и привязку. OPENID_PORT=$(free_port) while [ "$OPENID_PORT" = "$FREE_PORT" ] || [ "$OPENID_PORT" = "$SMTP_PORT" ] || [ "$OPENID_PORT" = "$OIDC_PORT" ]; do OPENID_PORT=$(free_port) done OPENID_READY="$WORK_DIR/openid.ready" node tools/test-openid-server.mjs \ --host 127.0.0.1 \ --port "$OPENID_PORT" \ --app-port "$FREE_PORT" \ --username "$RIXEA_TEST_OPENID_USERNAME" \ --ready "$OPENID_READY" \ >"$WORK_DIR/openid.log" 2>&1 & OPENID_PID=$! wait_for_process_ready "$OPENID_PID" "$OPENID_READY" "$WORK_DIR/openid.log" "OpenID-провайдер" # Write config file for isolated instance mkdir -p "$WORK_DIR/custom/conf" REINDEXER_HOST=${RIXEA_TEST_REINDEXER_HOST:-127.0.0.1:6534} REINDEXER_DATABASE=${RIXEA_TEST_REINDEXER_DATABASE:-rixea_e2e_${FREE_PORT}_$$} cat > "$WORK_DIR/custom/conf/app.ini" <<EOF [database] DB_TYPE = reindexer HOST = $REINDEXER_HOST NAME = $REINDEXER_DATABASE USER = ${RIXEA_TEST_REINDEXER_USER:-} PASSWD = ${RIXEA_TEST_REINDEXER_PASSWORD:-} SSL_MODE = ${RIXEA_TEST_REINDEXER_SSL_MODE:-disable} REINDEXER_CREATE_DATABASE = true [server] HTTP_PORT = $FREE_PORT ROOT_URL = http://localhost:$FREE_PORT STATIC_ROOT_PATH = $(pwd) LFS_START_SERVER = true SSH_AUTHORIZED_PRINCIPALS_ALLOW = username,email SSH_CREATE_AUTHORIZED_KEYS_FILE = false SSH_CREATE_AUTHORIZED_PRINCIPALS_FILE = false [security] INSTALL_LOCK = true CRYPTO_PROFILE = standard SECRET_KEY = rixea-e2e-secret-key ALLOWED_HOST_LIST = loopback [service] ENABLE_CAPTCHA = false ENABLE_NOTIFY_MAIL = true [openid] ENABLE_OPENID_SIGNIN = true ENABLE_OPENID_SIGNUP = false [mailer] ENABLED = true PROTOCOL = smtp SMTP_ADDR = 127.0.0.1 SMTP_PORT = $SMTP_PORT FROM = Rixea <no-reply@e2e.rixea.local> [oauth2_client] ENABLE_AUTO_REGISTRATION = true OPENID_CONNECT_SCOPES = openid profile email USERNAME = nickname ACCOUNT_LINKING = disabled [i18n] LANGS = ru-RU,en-US NAMES = Русский,English [ui.notification] EVENT_SOURCE_UPDATE_TIME = 500ms [log] MODE = console LEVEL = ${RIXEA_TEST_E2E_LOG_LEVEL:-Warn} [markup.test-external] ENABLED = true FILE_EXTENSIONS = .external RENDER_COMMAND = cat IS_INPUT_FILE = false RENDER_CONTENT_MODE = iframe EOF export RIXEA_WORK_DIR="$WORK_DIR" export RIXEA_TEST_E2E=true # Создаём источник до запуска web, чтобы сервер зарегистрировал его при старте. "./$EXECUTABLE" admin auth add-oauth \ --name "$RIXEA_TEST_OIDC_PROVIDER_NAME" \ --provider openidConnect \ --key "$OIDC_CLIENT_ID" \ --secret "$OIDC_CLIENT_SECRET" \ --auto-discover-url "http://127.0.0.1:$OIDC_PORT/.well-known/openid-configuration" # Start Rixea server echo "Starting Rixea server on port $FREE_PORT (workdir: $WORK_DIR)..." if [ -n "${RIXEA_TEST_E2E_DEBUG:-}" ]; then "./$EXECUTABLE" web & else "./$EXECUTABLE" web > "$WORK_DIR/server.log" 2>&1 & fi SERVER_PID=$! # Wait for server to be reachable E2E_URL="http://localhost:$FREE_PORT" HEALTH_URL="$E2E_URL/api/healthz" MAX_WAIT=${RIXEA_TEST_E2E_MAX_WAIT:-120} ELAPSED=0 while ! curl -sf --max-time 5 "$HEALTH_URL" > /dev/null 2>&1; do if ! kill -0 "$SERVER_PID" 2>/dev/null; then echo "error: Rixea server process exited unexpectedly. Server log:" >&2 cat "$WORK_DIR/server.log" 2>/dev/null >&2 || true exit 1 fi if [ "$ELAPSED" -ge "$MAX_WAIT" ]; then echo "error: Rixea server not reachable after ${MAX_WAIT}s. Server log:" >&2 cat "$WORK_DIR/server.log" 2>/dev/null >&2 || true exit 1 fi sleep 2 ELAPSED=$((ELAPSED + 2)) done echo "Rixea server is ready at $E2E_URL" # Create admin test user "./$EXECUTABLE" admin user create \ --username "$RIXEA_TEST_E2E_USER" \ --password "$RIXEA_TEST_E2E_PASSWORD" \ --email "$RIXEA_TEST_E2E_EMAIL" \ --must-change-password=false \ --admin # timeout multiplier to make the tests pass on slow CI runners while using # factor 1 on a fast local machine like a MacBook Pro M1+ if [ -z "${RIXEA_TEST_E2E_TIMEOUT_FACTOR:-}" ]; then if [ -n "${CI:-}" ]; then RIXEA_TEST_E2E_TIMEOUT_FACTOR=4 else RIXEA_TEST_E2E_TIMEOUT_FACTOR=1 fi fi export RIXEA_TEST_E2E_URL="$E2E_URL" export RIXEA_TEST_E2E_DOMAIN export RIXEA_TEST_E2E_USER export RIXEA_TEST_E2E_PASSWORD export RIXEA_TEST_E2E_EMAIL export RIXEA_TEST_E2E_TIMEOUT_FACTOR export RIXEA_TEST_SMTP_INBOX="$SMTP_INBOX" export RIXEA_TEST_OIDC_URL="http://localhost:$OIDC_PORT" export RIXEA_TEST_OIDC_PROVIDER_NAME export RIXEA_TEST_OIDC_USERNAME export RIXEA_TEST_OIDC_EMAIL export RIXEA_TEST_OPENID_URL="http://localhost:$OPENID_PORT" export RIXEA_TEST_OPENID_ID="$RIXEA_TEST_OPENID_URL/identity/$RIXEA_TEST_OPENID_USERNAME" if [ "$PLAYWRIGHT_MODE" = "container" ]; then export PW_TEST_CONNECT_WS_ENDPOINT="ws://127.0.0.1:${PLAYWRIGHT_SERVER_PORT}/" fi pnpm exec playwright test "$@"