E2E Tests #15
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 |