Skip to content

E2E Tests

E2E Tests #15

Workflow file for this run

name: E2E Tests
on:
workflow_dispatch:
schedule:
# Run E2E tests weekly on Sunday at 2:00 AM UTC
- cron: '0 2 * * 0'
permissions:
contents: read
jobs:
e2e:
name: Playwright E2E Tests
runs-on: ubuntu-latest
timeout-minutes: 30
services:
db:
image: mariadb:11.4
env:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: typo3
MYSQL_CHARSET: utf8mb4
MYSQL_COLLATION: utf8mb4_unicode_ci
ports:
- 3306:3306
options: >-
--health-cmd="healthcheck.sh --connect --innodb_initialized"
--health-interval=10s
--health-timeout=5s
--health-retries=5
steps:
- name: Harden Runner
uses: step-security/harden-runner@5ef0c079ce82195b2a36a210272d6b661572d83e # v2.14.2
with:
egress-policy: audit
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup PHP
uses: shivammathur/setup-php@44454db4f0199b8b9685a5d763dc37cbf79108e1 # v2.36.0
with:
php-version: '8.5'
extensions: mysqli, pdo_mysql, gd, intl, curl, zip
coverage: none
- name: Get Composer cache directory
id: composer-cache
run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
- name: Cache Composer dependencies
uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}
restore-keys: ${{ runner.os }}-composer-
- name: Install Composer dependencies
run: composer install --prefer-dist --no-progress
- name: Setup TYPO3
run: |
# Wait for database to be ready (extra safety beyond GitHub Services health check)
for i in {1..30}; do
if mysqladmin ping -h127.0.0.1 -uroot -proot --silent 2>/dev/null; then
echo "Database is ready."
break
fi
echo "Waiting for database to be ready... (attempt $i/30)"
sleep 2
done
# Use TYPO3 setup command to create full schema + admin user
.Build/bin/typo3 setup \
--driver=mysqli \
--host=127.0.0.1 \
--port=3306 \
--dbname=typo3 \
--username=root \
--password=root \
--admin-username=admin \
--admin-user-password='Joh316!!' \
--admin-email=admin@example.com \
--project-name='nr_llm E2E Tests' \
--server-type=other \
--no-interaction \
--force
# Activate the extension (creates extension-specific tables/modules)
.Build/bin/typo3 extension:setup --no-interaction
# Configure trustedHostsPattern for PHP built-in server
mkdir -p config/system
printf '<?php\n$GLOBALS["TYPO3_CONF_VARS"]["SYS"]["trustedHostsPattern"] = ".*";\n$GLOBALS["TYPO3_CONF_VARS"]["SYS"]["displayErrors"] = 1;\n$GLOBALS["TYPO3_CONF_VARS"]["SYS"]["devIPmask"] = "*";\n$GLOBALS["TYPO3_CONF_VARS"]["BE"]["debug"] = true;\n' > config/system/additional.php
# Flush caches
.Build/bin/typo3 cache:flush
- name: Setup Node.js
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
with:
node-version: '22'
cache: 'npm'
- name: Install npm dependencies
run: npm ci
- name: Install Playwright browsers
run: npx playwright install --with-deps chromium
- name: Start PHP server
run: |
# Create router script for PHP built-in server (replaces .htaccess rewriting)
cat > /tmp/typo3-router.php << 'ROUTER'
<?php
$uri = urldecode(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH));
$docRoot = $_SERVER['DOCUMENT_ROOT'];
$path = $docRoot . $uri;
// Serve existing files directly (JS, CSS, images, etc.)
if ($uri !== '/' && file_exists($path) && is_file($path)) {
return false;
}
// All other requests go through the TYPO3 entry point
$_SERVER['SCRIPT_NAME'] = '/index.php';
require $docRoot . '/index.php';
ROUTER
php -S 0.0.0.0:8080 -t .Build/Web /tmp/typo3-router.php > /tmp/php-server.log 2>&1 &
echo $! > /tmp/php-server.pid
# Wait for server to become ready (up to 30 seconds)
for i in $(seq 1 30); do
if curl -sf http://localhost:8080/typo3/login > /dev/null 2>&1; then
echo "PHP server is up (checked after ${i}s)."
break
fi
sleep 1
done
# Verify server is running after retries
if ! curl -sf http://localhost:8080/typo3/login > /dev/null 2>&1; then
echo "PHP server failed to start within timeout. Server log:"
cat /tmp/php-server.log
echo "---"
echo "Trying to get response body:"
curl -v http://localhost:8080/typo3/login 2>&1 | head -50
exit 1
fi
- name: Run Playwright tests
env:
TYPO3_BASE_URL: http://localhost:8080
run: npm run test:e2e
- name: Upload test results
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
if: always()
with:
name: playwright-report
path: |
Tests/E2E/Playwright/reports/
Tests/E2E/Playwright/test-results/
retention-days: 7
- name: Upload PHP server logs
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
if: failure()
with:
name: php-server-logs
path: /tmp/php-server.log
retention-days: 3
- name: Stop PHP server
if: always()
run: |
if [ -f /tmp/php-server.pid ]; then
kill $(cat /tmp/php-server.pid) 2>/dev/null || true
fi