Skip to content

GH#2673: test: cover trash selector fixture #2338

GH#2673: test: cover trash selector fixture

GH#2673: test: cover trash selector fixture #2338

Workflow file for this run

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