diff --git a/.github/workflows/end-to-end-tests.yml b/.github/workflows/end-to-end-tests.yml new file mode 100644 index 00000000..64cf4b12 --- /dev/null +++ b/.github/workflows/end-to-end-tests.yml @@ -0,0 +1,35 @@ +name: End-to-end Tests + +on: + push: + branches: + - main + pull_request: + +jobs: + test: + name: End-to-end Tests + runs-on: ubuntu-latest + timeout-minutes: 20 + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Set UID and GID for PHP in WordPress images + run: | + echo "PHP_FPM_UID=$(id -u)" >> $GITHUB_ENV + echo "PHP_FPM_GID=$(id -g)" >> $GITHUB_ENV + + - name: Install Playwright browsers + run: npx playwright install --with-deps + + - name: Run end-to-end tests + run: composer run test-e2e + + - name: Stop Docker containers + if: always() + run: composer run wp-test-clean diff --git a/.github/workflows/wp-tests-end-to-end.yml b/.github/workflows/wp-tests-end-to-end.yml new file mode 100644 index 00000000..2b32a5a0 --- /dev/null +++ b/.github/workflows/wp-tests-end-to-end.yml @@ -0,0 +1,35 @@ +name: WordPress End-to-end Tests + +on: + push: + branches: + - main + pull_request: + +jobs: + test: + name: WordPress End-to-end Tests + runs-on: ubuntu-latest + timeout-minutes: 20 + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Set UID and GID for PHP in WordPress images + run: | + echo "PHP_FPM_UID=$(id -u)" >> $GITHUB_ENV + echo "PHP_FPM_GID=$(id -g)" >> $GITHUB_ENV + + - name: Install Playwright browsers + run: npx playwright install --with-deps + + - name: Run WordPress end-to-end tests + run: composer run wp-test-e2e + + - name: Stop Docker containers + if: always() + run: composer run wp-test-clean diff --git a/.github/workflows/wp-tests-phpunit-run.js b/.github/workflows/wp-tests-phpunit-run.js index ff4d873c..03ce2697 100644 --- a/.github/workflows/wp-tests-phpunit-run.js +++ b/.github/workflows/wp-tests-phpunit-run.js @@ -1,5 +1,5 @@ /* - * Wrap the "composer run wp-tests-phpunit" command to process tests + * Wrap the "composer run wp-tests-php" command to process tests * that are expected to error and fail at the moment. * * This makes sure that the CI job passes, while explicitly tracking @@ -108,7 +108,7 @@ console.log( 'Expected failures:', expectedFailures ); try { try { execSync( - `composer run wp-test-phpunit -- --log-junit=phpunit-results.xml --verbose`, + `composer run wp-test-php -- --log-junit=phpunit-results.xml --verbose`, { stdio: 'inherit' } ); console.log( '\n⚠️ All tests passed, checking if expected errors/failures occurred...' ); diff --git a/.github/workflows/wp-tests-phpunit.yml b/.github/workflows/wp-tests-phpunit.yml index 0bf5c511..d2746fdc 100644 --- a/.github/workflows/wp-tests-phpunit.yml +++ b/.github/workflows/wp-tests-phpunit.yml @@ -1,4 +1,4 @@ -name: WordPress Tests +name: WordPress PHPUnit Tests on: push: @@ -24,12 +24,6 @@ jobs: echo "PHP_FPM_UID=$(id -u)" >> $GITHUB_ENV echo "PHP_FPM_GID=$(id -g)" >> $GITHUB_ENV - - name: Setup WordPress test environment - run: composer run wp-setup - - - name: Start WordPress test environment - run: composer run wp-test-start - - name: Run WordPress PHPUnit tests run: node .github/workflows/wp-tests-phpunit-run.js diff --git a/composer.json b/composer.json index 1d27a626..4ac7fc76 100644 --- a/composer.json +++ b/composer.json @@ -39,6 +39,13 @@ "test": [ "phpunit" ], + "test-e2e": [ + "@wp-test-ensure-env @no_additional_args", + "rm -f tests/e2e/package.json tests/e2e/node_modules @no_additional_args", + "ln -s ../../wordpress/package.json tests/e2e/package.json @no_additional_args", + "ln -s ../../wordpress/node_modules tests/e2e/node_modules @no_additional_args", + "npm --prefix tests/e2e run test:e2e -- --config . @additional_args" + ], "wp-setup": [ "./wp-setup.sh" ], @@ -47,13 +54,27 @@ ], "wp-test-start": [ "npm --prefix wordpress run env:start", - "npm --prefix wordpress run env:install" + "npm --prefix wordpress run env:install", + "npm --prefix wordpress run env:cli -- plugin install gutenberg", + "npm --prefix wordpress run env:cli -- plugin install query-monitor" + ], + "wp-test-ensure-env": [ + "if [ ! -f wordpress/src/wp-load.php ]; then composer run wp-setup; fi", + "@putenv COMPOSE_IGNORE_ORPHANS=true", + "cd wordpress && if [ -z \"$(node tools/local-env/scripts/docker.js ps -q)\" ]; then cd ..; composer run wp-test-start; fi" + ], + "wp-test-php": [ + "@wp-test-ensure-env @no_additional_args", + "rm -rf wordpress/src/wp-content/database/.ht.sqlite @no_additional_args", + "npm --prefix wordpress run test:php -- @additional_args" ], - "wp-test-phpunit": [ - "rm -rf wordpress/src/wp-content/database && npm --prefix wordpress run test:php --" + "wp-test-e2e": [ + "@wp-test-ensure-env @no_additional_args", + "npm --prefix wordpress run test:e2e -- @additional_args" ], "wp-test-clean": [ - "npm --prefix wordpress run env:clean" + "npm --prefix wordpress run env:clean", + "rm -rf wordpress/src/wp-content/database/.ht.sqlite" ] } } diff --git a/tests/e2e/.gitignore b/tests/e2e/.gitignore new file mode 100644 index 00000000..a5dd015f --- /dev/null +++ b/tests/e2e/.gitignore @@ -0,0 +1,3 @@ +/artifacts +/node_modules +/package.json diff --git a/tests/e2e/playwright.config.js b/tests/e2e/playwright.config.js new file mode 100644 index 00000000..531b6a1d --- /dev/null +++ b/tests/e2e/playwright.config.js @@ -0,0 +1,27 @@ +/** + * External dependencies + */ +import path from 'node:path'; +import { defineConfig } from '@playwright/test'; + +/** + * WordPress dependencies + */ +const baseConfig = require( '@wordpress/scripts/config/playwright.config' ); + +process.env.WP_ARTIFACTS_PATH ??= path.join( process.cwd(), 'artifacts' ); +process.env.STORAGE_STATE_PATH ??= path.join( + process.env.WP_ARTIFACTS_PATH, + 'storage-states/admin.json' +); + +const config = defineConfig( { + ...baseConfig, + globalSetup: require.resolve( '../../wordpress/tests/e2e/config/global-setup.js' ), + webServer: { + ...baseConfig.webServer, + command: 'npm run env:start', + }, +} ); + +export default config; diff --git a/tests/e2e/specs/query-monitor-plugin.test.js b/tests/e2e/specs/query-monitor-plugin.test.js new file mode 100644 index 00000000..64b13213 --- /dev/null +++ b/tests/e2e/specs/query-monitor-plugin.test.js @@ -0,0 +1,47 @@ +/** + * WordPress dependencies + */ +import { test, expect } from '@wordpress/e2e-test-utils-playwright'; + +test.describe( 'Query Monitor plugin', () => { + async function deactivateQueryMonitor( requestUtils ) { + await requestUtils.deactivatePlugin( 'query-monitor' ); + const plugin = await requestUtils.rest( { + path: 'wp/v2/plugins/query-monitor/query-monitor', + } ); + expect( plugin.status ).toBe( 'inactive' ); + } + + test.beforeEach( async ( { requestUtils }) => { + await deactivateQueryMonitor( requestUtils ); + } ); + + test.afterEach( async ( { requestUtils }) => { + await deactivateQueryMonitor( requestUtils ); + } ); + + test( 'should activate', async ( { admin, page } ) => { + // Activate the Query Monitor plugin on the plugins page. + await admin.visitAdminPage( '/plugins.php' ); + await page.getByLabel( 'Activate Query Monitor', { exact: true } ).click(); + await page.getByText( 'Plugin activated.', { exact: true } ).waitFor(); + + // Click on the Query Monitor menu item in the WordPress admin bar. + await page.locator('a[role="menuitem"][href="#qm-overview"][aria-expanded="false"]').click(); + + // Wait for the Query Monitor panel to open. + await page.locator( '#query-monitor-main' ).waitFor(); + await page.getByRole( 'heading', { name: 'Query Monitor', exact: true } ).waitFor(); + + // Click on the Database Queries tab. + await page.getByRole( 'tab', { name: 'Database Queries' } ).click(); + + // Verify the first logged query. + const sqlCell = page.locator( '.qm-row-sql' ).first(); + await expect( sqlCell ).toContainText( 'SELECT option_name, option_value' ); + + // Check that the query is logged with SQLite information. + await sqlCell.getByLabel( 'Toggle SQLite queries' ).click(); + expect( page.locator('.qm-sqlite-query', { hasText: 'SELECT `option_name` , `option_value` FROM `wp_options`' }).first() ).toBeVisible(); + } ); +} ); diff --git a/wp-setup.sh b/wp-setup.sh index b3e00de7..44b8c016 100755 --- a/wp-setup.sh +++ b/wp-setup.sh @@ -65,3 +65,4 @@ sed -i.bak "s#class WpdbExposedMethodsForTesting extends wpdb {#class WpdbExpose # 6. Install dependencies. echo "Installing dependencies..." npm --prefix "$WP_DIR" install +npm --prefix "$WP_DIR" run build:dev