GH#2673: test: cover trash selector fixture #2338
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: | |
| pull_request: | |
| branches: [main] | |
| paths-ignore: | |
| - '**.md' | |
| - 'docs/**' | |
| - '.github/ISSUE_TEMPLATE/**' | |
| - 'TODO.md' | |
| - 'todo/**' | |
| - 'LICENSE' | |
| - '.editorconfig' | |
| - '.agents/**' | |
| workflow_dispatch: | |
| concurrency: | |
| group: e2e-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| e2e: | |
| name: Playwright E2E (WP ${{ matrix.wp }} shard ${{ matrix.shard }}) | |
| runs-on: ubuntu-latest | |
| # Each shard runs ~1/3 of the 13 spec files. 90 min accounts for setup | |
| # overhead (~20 min: pnpm install, composer, wp-env start) + worst-case test | |
| # runtime (2 retries at 90 s/test × 3 attempts / 2 workers). The 60-min | |
| # limit was exceeded after the per-test timeout increased from 60 s to | |
| # 90 s in playwright.config.js — setup + test time could exceed 60 min. | |
| timeout-minutes: 90 | |
| # This required WordPress 7.0 environment provides the browser Abilities | |
| # API that client-abilities.spec.js must exercise. Do not allow failures to | |
| # pass as advisory coverage. | |
| continue-on-error: false | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| # Pin the required browser-ability coverage to WordPress 7.0-RC2. The | |
| # final 7.0 and moving trunk builds do not reliably load | |
| # @wordpress/core-abilities on admin pages. | |
| wp: ['7.0-RC2'] | |
| # 3 shards split 13 spec files into ~4-5 files each. With the 90-min | |
| # job timeout, each shard has ample headroom even with 2 retries. | |
| shard: [1, 2, 3] | |
| include: | |
| - wp: '7.0-RC2' | |
| wp_env_port: '8890' | |
| wp_env_override: '{"core":"WordPress/WordPress#7.0"}' | |
| # 1 worker: shard 1 still showed login and SPA-render timeouts | |
| # with 2 workers on GitHub-hosted runners under WordPress 7.0 load. | |
| playwright_workers: '1' | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| - name: Setup pnpm and Node.js | |
| uses: pnpm/setup@c9883cc79df532ad1a7b81bf9ab944ceb090d65c # v2.0.0 | |
| with: | |
| runtime: node@24 | |
| cache: true | |
| install: false | |
| - name: Setup PHP | |
| uses: shivammathur/setup-php@v2 | |
| with: | |
| php-version: '8.2' | |
| extensions: mbstring, intl, zip | |
| tools: composer:v2 | |
| 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@v5 | |
| with: | |
| path: ${{ steps.composer-cache.outputs.dir }} | |
| key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} | |
| restore-keys: ${{ runner.os }}-composer- | |
| - name: Install Composer dependencies | |
| run: composer install --prefer-dist --no-progress | |
| - name: Install Node dependencies | |
| run: pnpm install --frozen-lockfile | |
| - name: Patch @wordpress/env phpunit constraint | |
| # @wordpress/env's CLI.Dockerfile installs phpunit globally. Composer | |
| # 2.6+ defaults audit.block-insecure to true, which blocks ALL phpunit | |
| # versions (v5–v11) due to security advisories PKSA-5jz8-6tcw-pbk4 and | |
| # PKSA-z3gr-8qht-p93v. COMPOSER_NO_AUDIT=1 only skips post-install | |
| # audit reporting — it does NOT disable block-insecure resolution blocking. | |
| # Fix: prepend 'composer config --global audit.block-insecure false &&' | |
| # to disable the resolver-level block before running the install. | |
| # v10.x uses init-config.js; v11.x renamed it to docker-config.js. | |
| # Remove once @wordpress/env ships a fix upstream. | |
| run: | | |
| node -e " | |
| const fs = require('fs'); | |
| const path = require('path'); | |
| const base = 'node_modules/@wordpress/env/lib/runtime/docker/'; | |
| const candidates = ['init-config.js', 'docker-config.js']; | |
| const before = 'RUN composer global require --dev phpunit/phpunit:\"^5.7.21 || ^6.0 || ^7.0 || ^8.0 || ^9.0 || ^10.0\"'; | |
| const after = 'RUN composer config --global audit.block-insecure false && composer global require --dev phpunit/phpunit:\"^5.7.21 || ^6.0 || ^7.0 || ^8.0 || ^9.0 || ^10.0\"'; | |
| let patched = false; | |
| for (const name of candidates) { | |
| const f = path.resolve(base + name); | |
| if (!fs.existsSync(f)) continue; | |
| let c = fs.readFileSync(f, 'utf8'); | |
| if (!c.includes(before)) { console.log(name + ': already patched or pattern changed, skipping'); continue; } | |
| fs.writeFileSync(f, c.replace(before, after)); | |
| console.log('Patched ' + f); | |
| patched = true; | |
| } | |
| if (!patched) console.log('No files needed patching'); | |
| " | |
| # Playwright launches the preinstalled Chrome channel below. Avoid | |
| # `playwright install-deps`, which runs apt and can stall on a runner | |
| # mirror before the E2E suite starts. | |
| - name: Verify system Chrome availability | |
| run: google-chrome --version | |
| - name: Build plugin assets | |
| run: pnpm run build | |
| - name: Override wp-env core version | |
| if: matrix.wp_env_override != '' | |
| env: | |
| WP_ENV_OVERRIDE: ${{ matrix.wp_env_override }} | |
| run: | | |
| node -e " | |
| const fs = require('fs'); | |
| const base = JSON.parse(fs.readFileSync('.wp-env.json', 'utf8')); | |
| const override = JSON.parse(process.env.WP_ENV_OVERRIDE); | |
| Object.assign(base, override); | |
| fs.writeFileSync('.wp-env.override.json', JSON.stringify(base, null, 2)); | |
| " | |
| - name: Start wp-env | |
| run: pnpm run wp-env:start | |
| timeout-minutes: 10 | |
| env: | |
| WP_ENV_HOME: /tmp/wp-env | |
| - name: Wait for wp-env to be ready | |
| run: | | |
| ready=0 | |
| for i in $(seq 1 30); do | |
| if curl -s -o /dev/null -w "%{http_code}" http://localhost:${{ matrix.wp_env_port }}/wp-login.php | grep -q "200"; then | |
| echo "wp-env is ready on port ${{ matrix.wp_env_port }}" | |
| ready=1 | |
| break | |
| fi | |
| echo "Waiting for wp-env... attempt $i" | |
| sleep 5 | |
| done | |
| if [ "$ready" -ne 1 ]; then | |
| echo "wp-env did not become ready in time on port ${{ matrix.wp_env_port }}" >&2 | |
| exit 1 | |
| fi | |
| - name: Install required WordPress 7.0-RC2 browser Abilities API build | |
| # wp-env bootstraps from the stable source tree, then WP-CLI installs | |
| # the RC2 build where @wordpress/core-abilities is loaded in wp-admin. | |
| # `--` keeps wp-env from consuming WP-CLI's `--version` option. | |
| run: | | |
| pnpm exec wp-env run cli -- wp core update --version=7.0-RC2 --force | |
| pnpm exec wp-env run cli -- wp core update-db | |
| pnpm exec wp-env run cli -- wp core version | grep -x '7.0-RC2' | |
| env: | |
| WP_ENV_HOME: /tmp/wp-env | |
| - name: Verify plugin health | |
| run: | | |
| echo "=== Plugin status ===" | |
| pnpm exec wp-env run cli wp plugin list --format=table | |
| echo "" | |
| echo "=== Verify plugin is active ===" | |
| pnpm exec wp-env run cli wp plugin is-active superdav-ai-agent && echo "Plugin is active" || echo "ERROR: Plugin is NOT active" | |
| echo "" | |
| echo "=== Check admin page loads (HTTP status) ===" | |
| # Log in and fetch the admin page to verify the SPA renders. | |
| # First get a login cookie, then check the plugin page. | |
| LOGIN_COOKIE=$(curl -s -c - -d "log=admin&pwd=password&wp-submit=Log+In" \ | |
| "http://localhost:${{ matrix.wp_env_port }}/wp-login.php" | grep wordpress_logged_in | awk '{print $NF}') | |
| STATUS=$(curl -s -o /dev/null -w "%{http_code}" -b "wordpress_logged_in_=$(echo $LOGIN_COOKIE)" \ | |
| "http://localhost:${{ matrix.wp_env_port }}/wp-admin/admin.php?page=sd-ai-agent") | |
| echo "Admin page HTTP status: $STATUS" | |
| echo "" | |
| echo "=== PHP error log (last 30 lines) ===" | |
| pnpm exec wp-env run cli cat /var/www/html/wp-content/debug.log 2>/dev/null | tail -30 || echo "(no error log)" | |
| env: | |
| WP_ENV_HOME: /tmp/wp-env | |
| - name: Configure plugin for E2E tests | |
| run: | | |
| # Mark onboarding complete so the main chat UI renders instead of | |
| # the bootstrap discovery session (Setup Assistant agent). | |
| pnpm exec wp-env run cli wp option update sd_ai_agent_settings \ | |
| '{"onboarding_complete":true}' --format=json | |
| # Register the deterministic SDK provider from tests/mu-plugins so | |
| # /providers returns one authenticated provider without installing a | |
| # real ai-provider-for-* plugin. E2E specs mock /stream, so no real | |
| # provider API calls are made. | |
| pnpm exec wp-env run cli wp option update sd_ai_agent_e2e_register_provider 1 | |
| # Create a real post so the site is no longer detected as a fresh install | |
| # even after the transient expires (belt-and-suspenders). | |
| pnpm exec wp-env run cli wp post create --post_title='E2E Test Post' \ | |
| --post_status=publish --post_type=post | |
| # Create the second admin user required by shared-conversations.spec.js. | |
| # Done here (not in test.beforeAll) so WP_ENV_HOME is available and | |
| # wp-env can locate its docker-compose.yml. | |
| pnpm exec wp-env run cli wp user create admin2 admin2@example.com \ | |
| --role=administrator --user_pass=password2 --send-email=false || true | |
| env: | |
| WP_ENV_HOME: /tmp/wp-env | |
| - name: Run Playwright E2E tests (shard ${{ matrix.shard }}/3) | |
| run: pnpm exec playwright test --shard=${{ matrix.shard }}/3 | |
| env: | |
| WP_BASE_URL: http://localhost:${{ matrix.wp_env_port }} | |
| WP_ADMIN_USER: admin | |
| WP_ADMIN_PASSWORD: password | |
| CI: true | |
| PLAYWRIGHT_USE_SYSTEM_CHROME: '1' | |
| PLAYWRIGHT_WORKERS: ${{ matrix.playwright_workers }} | |
| - name: Upload Playwright report | |
| uses: actions/upload-artifact@v7 | |
| if: always() | |
| with: | |
| # Artifact name includes shard index to avoid name collisions between | |
| # shards of the same WP version. | |
| name: playwright-report-wp${{ matrix.wp }}-shard${{ matrix.shard }} | |
| path: playwright-report/ | |
| retention-days: 3 | |
| - name: Upload test results | |
| uses: actions/upload-artifact@v7 | |
| if: failure() | |
| with: | |
| name: test-results-wp${{ matrix.wp }}-shard${{ matrix.shard }} | |
| path: test-results/ | |
| retention-days: 3 | |
| - name: Dump PHP error log on failure | |
| if: failure() | |
| run: | | |
| echo "=== PHP debug.log ===" | |
| pnpm exec wp-env run cli cat /var/www/html/wp-content/debug.log 2>/dev/null | tail -100 || echo "(no error log)" | |
| env: | |
| WP_ENV_HOME: /tmp/wp-env | |
| - name: Stop wp-env | |
| if: always() | |
| run: pnpm run wp-env:stop | |
| env: | |
| WP_ENV_HOME: /tmp/wp-env |