t531: fix set_demo_behavior fatal TypeError on PHP 8 when null passed via deprecated compat layer #1636
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: | |
| push: | |
| branches: | |
| - main | |
| pull_request: | |
| branches: | |
| - "**" | |
| jobs: | |
| cypress: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 45 # Increased for setup wizard + Stripe test clock advancement | |
| strategy: | |
| matrix: | |
| php: ["8.1", "8.2"] # Reduced PHP versions for faster CI | |
| browser: ["chrome"] # Start with Chrome only for reliability | |
| services: | |
| mailpit: | |
| image: axllent/mailpit:latest | |
| ports: | |
| - 1025:1025 | |
| - 8025:8025 | |
| options: >- | |
| --health-cmd="wget --spider -q http://localhost:8025 || exit 1" | |
| --health-interval=2s | |
| --health-timeout=2s | |
| --health-retries=10 | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 | |
| with: | |
| node-version: 18 | |
| - name: Cache NPM dependencies | |
| uses: actions/cache@6f8efc29b200d32929f49075959781ed54ec270c # v3 | |
| with: | |
| path: ~/.npm | |
| key: ${{ runner.os }}-npm-cache | |
| - name: Install NPM dependencies | |
| run: npm ci | |
| - name: Cache Composer dependencies | |
| uses: actions/cache@6f8efc29b200d32929f49075959781ed54ec270c # v3 | |
| with: | |
| path: vendor | |
| key: ${{ runner.os }}-composer-cache | |
| - name: Install Composer dependencies | |
| run: composer install | |
| - name: Set PHP version and filter missing plugins for wp-env | |
| run: | | |
| node -e " | |
| const fs = require('fs'); | |
| const path = require('path'); | |
| const config = JSON.parse(fs.readFileSync('.wp-env.json', 'utf8')); | |
| const override = { config: { phpVersion: '${{ matrix.php }}' }, env: {} }; | |
| for (const [envName, envConfig] of Object.entries(config.env || {})) { | |
| if (envConfig.plugins) { | |
| const existing = envConfig.plugins.filter(p => { | |
| const resolved = path.resolve(p); | |
| return fs.existsSync(resolved); | |
| }); | |
| override.env[envName] = { plugins: existing }; | |
| } | |
| } | |
| fs.writeFileSync('.wp-env.override.json', JSON.stringify(override, null, 2)); | |
| console.log('Override:', JSON.stringify(override, null, 2)); | |
| " | |
| - name: Start WordPress Test Environment | |
| run: npm run env:start:test | |
| - name: Wait for WordPress to be ready | |
| run: | | |
| for i in {1..60}; do | |
| if curl -s http://localhost:8889 | grep -q "WordPress"; then | |
| echo "WordPress is ready"; | |
| break; | |
| fi | |
| echo "Waiting for WordPress... ($i/60)"; | |
| sleep 5; | |
| done | |
| echo "Final check:" | |
| curl -s http://localhost:8889 || echo "WordPress not responding" | |
| - name: Network-activate plugin in tests environment | |
| run: | | |
| echo "=== Network-activating Ultimate Multisite plugin ===" | |
| PLUGIN_SLUG=$(basename "$PWD") | |
| echo "Plugin slug: $PLUGIN_SLUG" | |
| # Network-activate so wu_save_setting() and other functions | |
| # are fully bootstrapped for all wp eval / eval-file calls. | |
| npx wp-env run tests-cli wp plugin activate "$PLUGIN_SLUG" --network || \ | |
| npx wp-env run tests-cli wp plugin activate ultimate-multisite --network || \ | |
| echo "⚠️ Could not network-activate by directory name, listing plugins..." | |
| echo "Plugin list after activation attempt:" | |
| npx wp-env run tests-cli wp plugin list --status=active --format=table | |
| echo "Verifying wu_save_setting() is available:" | |
| npx wp-env run tests-cli wp eval "var_dump(function_exists('wu_save_setting'));" || true | |
| - name: Comprehensive WordPress Debug | |
| run: | | |
| echo "=== WordPress Environment Debug ===" | |
| echo "1. Basic URL Tests:" | |
| curl -I http://localhost:8889 || echo "❌ WordPress not responding" | |
| curl -I http://localhost:8889/wp-admin/ || echo "❌ WP Admin not responding" | |
| curl -I http://localhost:8889/wp-admin/network/ || echo "❌ Network admin not responding" | |
| echo -e "\n2. WordPress Content Test:" | |
| curl -s http://localhost:8889 | head -20 | grep -E "(WordPress|wp-)" || echo "❌ No WordPress indicators found" | |
| echo -e "\n3. Plugin Status Check:" | |
| curl -s "http://localhost:8889/wp-admin/network/plugins.php" | grep -i "multisite-ultimate" || echo "❌ Plugin not found in network admin" | |
| echo -e "\n4. Database Connection Test:" | |
| curl -s "http://localhost:8889/wp-admin/network/" | grep -E "(Database|MySQL|connection)" || echo "✅ No database errors visible" | |
| echo -e "\n5. Multisite Status:" | |
| curl -s http://localhost:8889 | grep -i "multisite\|network" || echo "ℹ️ No multisite indicators in homepage" | |
| echo -e "\n6. Error Log Check:" | |
| docker logs $(docker ps -q --filter "name=tests-wordpress") 2>&1 | tail -20 || echo "ℹ️ Could not get container logs" | |
| echo -e "\n7. File System Check:" | |
| ls -la $(pwd) || echo "❌ Could not list current directory" | |
| ls -la $(pwd)/multisite-ultimate.php 2>/dev/null && echo "✅ Main plugin file exists" || echo "❌ Main plugin file not found" | |
| - name: Pre-Test Environment Verification | |
| run: | | |
| echo "=== Pre-Test Verification ===" | |
| echo "1. Cypress Config Check:" | |
| ls -la cypress.config.test.js && echo "✅ Config file exists" || echo "❌ Config file missing" | |
| echo "2. Test Files Check:" | |
| ls -la tests/e2e/cypress/integration/ && echo "✅ Test directory exists" || echo "❌ Test directory missing" | |
| find tests/e2e/cypress/integration/ -name "*.spec.js" | wc -l | xargs echo "Test files found:" | |
| echo "3. Support Files Check:" | |
| ls -la tests/e2e/cypress/support/commands/ && echo "✅ Commands directory exists" || echo "❌ Commands missing" | |
| echo "4. Cypress Environment Variables:" | |
| echo "Base URL: http://localhost:8889" | |
| cat cypress.env.json 2>/dev/null || echo "❌ cypress.env.json not found" | |
| - name: Run Setup Test (Must Run First) | |
| id: setup-test | |
| run: | | |
| echo "=== Starting Setup Test ===" | |
| npx cypress run \ | |
| --config-file cypress.config.test.js \ | |
| --spec "tests/e2e/cypress/integration/000-setup.spec.js" \ | |
| --browser ${{ matrix.browser }} | |
| - name: Dump container logs on setup failure | |
| if: failure() && steps.setup-test.outcome == 'failure' | |
| run: | | |
| echo "=== Container logs (last 100 lines) ===" | |
| docker logs $(docker ps -q --filter "name=tests-wordpress") 2>&1 | tail -100 || echo "Could not get container logs" | |
| echo "=== PHP error log ===" | |
| npx wp-env run tests-cli cat /var/www/html/wp-content/debug.log 2>&1 | tail -100 || echo "No debug.log found" | |
| - name: Run Checkout Tests (After Setup) | |
| id: checkout-tests | |
| run: | | |
| set +e | |
| echo "=== Starting Checkout Tests ===" | |
| CHECKOUT_TESTS=( | |
| "tests/e2e/cypress/integration/010-manual-checkout-flow.spec.js" | |
| "tests/e2e/cypress/integration/020-free-trial-flow.spec.js" | |
| ) | |
| TOTAL_FAILURES=0 | |
| for TEST_SPEC in "${CHECKOUT_TESTS[@]}"; do | |
| echo "Running: $TEST_SPEC" | |
| npx cypress run \ | |
| --config-file cypress.config.test.js \ | |
| --spec "$TEST_SPEC" \ | |
| --browser ${{ matrix.browser }} | |
| CYPRESS_EXIT_CODE=$? | |
| if [ $CYPRESS_EXIT_CODE -eq 0 ]; then | |
| echo "✅ $TEST_SPEC passed" | |
| else | |
| echo "❌ $TEST_SPEC failed with exit code $CYPRESS_EXIT_CODE" | |
| TOTAL_FAILURES=$((TOTAL_FAILURES + 1)) | |
| fi | |
| done | |
| if [ $TOTAL_FAILURES -gt 0 ]; then | |
| echo "❌ $TOTAL_FAILURES checkout test(s) failed" | |
| exit 1 | |
| fi | |
| echo "✅ All checkout tests passed!" | |
| - name: Run SSO Redirect Loop Tests (After Setup) | |
| id: sso-tests | |
| run: | | |
| echo "=== Starting SSO Redirect Loop Tests ===" | |
| npx cypress run \ | |
| --config-file cypress.config.test.js \ | |
| --spec "tests/e2e/cypress/integration/065-sso-redirect-loop.spec.js" \ | |
| --browser ${{ matrix.browser }} | |
| - name: Run Stripe Tests (After Setup) | |
| id: stripe-tests | |
| env: | |
| STRIPE_TEST_PK_KEY: ${{ secrets.STRIPE_TEST_PK_KEY }} | |
| STRIPE_TEST_SK_KEY: ${{ secrets.STRIPE_TEST_SK_KEY }} | |
| run: | | |
| if [ -z "$STRIPE_TEST_SK_KEY" ]; then | |
| echo "⏭️ Skipping Stripe tests: STRIPE_TEST_SK_KEY secret not configured" | |
| exit 0 | |
| fi | |
| set +e | |
| echo "=== Starting Stripe Tests ===" | |
| STRIPE_TESTS=( | |
| "tests/e2e/cypress/integration/030-stripe-checkout-flow.spec.js" | |
| "tests/e2e/cypress/integration/040-stripe-renewal-flow.spec.js" | |
| ) | |
| TOTAL_FAILURES=0 | |
| for TEST_SPEC in "${STRIPE_TESTS[@]}"; do | |
| echo "Running: $TEST_SPEC" | |
| npx cypress run \ | |
| --config-file cypress.config.test.js \ | |
| --spec "$TEST_SPEC" \ | |
| --browser ${{ matrix.browser }} | |
| CYPRESS_EXIT_CODE=$? | |
| if [ $CYPRESS_EXIT_CODE -eq 0 ]; then | |
| echo "✅ $TEST_SPEC passed" | |
| else | |
| echo "❌ $TEST_SPEC failed with exit code $CYPRESS_EXIT_CODE" | |
| TOTAL_FAILURES=$((TOTAL_FAILURES + 1)) | |
| fi | |
| done | |
| if [ $TOTAL_FAILURES -gt 0 ]; then | |
| echo "❌ $TOTAL_FAILURES Stripe test(s) failed" | |
| exit 1 | |
| fi | |
| echo "✅ All Stripe tests passed!" | |
| - name: Fix permissions for Cypress output | |
| if: always() | |
| run: sudo chown -R $USER:$USER tests/e2e/cypress | |
| - name: Upload Cypress screenshots | |
| if: always() | |
| continue-on-error: true | |
| uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7 | |
| with: | |
| name: cypress-screenshots-${{ matrix.php }}-${{ matrix.browser }} | |
| path: tests/e2e/cypress/screenshots | |
| - name: Upload Cypress videos | |
| if: always() | |
| continue-on-error: true | |
| uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7 | |
| with: | |
| name: cypress-videos-${{ matrix.php }}-${{ matrix.browser }} | |
| path: tests/e2e/cypress/videos | |
| - name: Stop WordPress Environment | |
| if: always() | |
| run: npm run env:stop |