diff --git a/.github/workflows/playwright-tests.yml b/.github/workflows/playwright-tests.yml index 124f982..19be60f 100644 --- a/.github/workflows/playwright-tests.yml +++ b/.github/workflows/playwright-tests.yml @@ -50,19 +50,16 @@ jobs: # re-run of an old commit resolves to the same WordPress. read -r -d '' DEFAULT_BLOCKING <<'JSON' || true [ - { "label": "6.9", "core": "WordPress/WordPress#6.9.7", "comment": true } + { "label": "6.9", "core": "WordPress/WordPress#6.9.7", "comment": true }, + { "label": "7.0", "core": "WordPress/WordPress#7.0.4", "comment": true }, + { "label": "7.1", "core": "WordPress/WordPress#7.1", "comment": true } ] JSON - # 7.0 and 7.1 run on every PR but do not gate merging: the - # suite has real compatibility gaps on WordPress 7.x that - # predate this matrix (see the WP 7.x tracking issue). They - # move back to DEFAULT_BLOCKING once those are closed. - # nightly tracks trunk for early warning and stays here. + # nightly tracks trunk for early warning only: a nightly-only + # regression isn't yet released, so it shouldn't block a PR. read -r -d '' DEFAULT_EXPERIMENTAL <<'JSON' || true [ - { "label": "7.0", "core": "WordPress/WordPress#7.0.4", "comment": true }, - { "label": "7.1", "core": "WordPress/WordPress#7.1", "comment": true }, { "label": "nightly", "core": "WordPress/WordPress#master", "comment": false } ] JSON diff --git a/tests/e2e/fixtures.js b/tests/e2e/fixtures.js index bf1361d..f9207b7 100644 --- a/tests/e2e/fixtures.js +++ b/tests/e2e/fixtures.js @@ -43,23 +43,7 @@ export const test = base.extend( { ); // Dismiss "Edit your site" modal if it appears - const editSiteModalVisible = await page - .locator( 'text=Edit your site' ) - .isVisible( { timeout: 2000 } ) - .catch( () => false ); - - if ( editSiteModalVisible ) { - const getStartedButton = page.locator( - 'button:has-text("Get started")' - ); - const isGetStartedVisible = await getStartedButton - .isVisible( { timeout: 1000 } ) - .catch( () => false ); - if ( isGetStartedVisible ) { - await getStartedButton.click(); - await page.waitForTimeout( 500 ); - } - } + await this.dismissEditSiteTour(); // Close welcome guide if it appears const welcomeGuideVisible = await page @@ -86,6 +70,39 @@ export const test = base.extend( { await page.waitForTimeout( 1000 ); }, + /** + * Dismiss the "Edit your site" site editor tour, if present. + * + * On WordPress 7.x this can appear on first page load (already + * handled in visitSiteEditor()) but also reappears later, on + * demand, the first time certain interactions happen — e.g. + * opening the settings sidebar or entering pattern-editing mode. + * It sits on top of everything, so any click underneath it times + * out instead of failing fast. + */ + async dismissEditSiteTour() { + const editSiteModalVisible = await page + .locator( 'text=Edit your site' ) + .isVisible( { timeout: 1000 } ) + .catch( () => false ); + + if ( ! editSiteModalVisible ) { + return; + } + + const getStartedButton = page.locator( + 'button:has-text("Get started")' + ); + if ( + await getStartedButton + .isVisible( { timeout: 1000 } ) + .catch( () => false ) + ) { + await getStartedButton.click(); + await page.waitForTimeout( 500 ); + } + }, + /** * Open the settings sidebar and wait for it to be ready. * @@ -98,29 +115,31 @@ export const test = base.extend( { * core helper cannot find its own. */ async openSettingsSidebar() { + await this.dismissEditSiteTour(); + const settingsRegion = page.getByRole( 'region', { name: 'Editor settings', } ); - if ( - await settingsRegion - .isVisible( { timeout: 2000 } ) - .catch( () => false ) - ) { - await page.waitForTimeout( 1000 ); - return; - } + const alreadyOpen = await settingsRegion + .isVisible( { timeout: 2000 } ) + .catch( () => false ); - try { - await editor.openDocumentSettingsSidebar(); - } catch ( error ) { - await page - .getByRole( 'button', { name: 'Settings' } ) - .first() - .click(); - await settingsRegion.waitFor( { timeout: 15000 } ); + if ( ! alreadyOpen ) { + try { + await editor.openDocumentSettingsSidebar(); + } catch ( error ) { + await this.dismissEditSiteTour(); + await page + .getByRole( 'button', { name: 'Settings' } ) + .first() + .click(); + await settingsRegion.waitFor( { timeout: 15000 } ); + } } + await this.dismissEditSiteTour(); + // The sidebar can open on the Template/Document tab, which holds // no block inspector controls — so every panel this plugin adds // to core/query looks missing. The same panels render fine in the @@ -136,6 +155,27 @@ export const test = base.extend( { await page.waitForTimeout( 300 ); } + // WP 7.x's site editor shows an abbreviated "Pattern" overview + // panel — a curated Content-only summary — instead of the full + // block inspector when a block came from the template's default + // content pattern (e.g. the Query Loop in twentytwentyfive's + // index template is inserted as the "List of posts" pattern). + // That overview has no InspectorControls slot, so every panel + // this plugin adds is missing until you enter the pattern's own + // editing context via "Edit pattern". + const editPatternButton = page + .getByRole( 'button', { name: 'Edit pattern' } ) + .first(); + if ( + await editPatternButton + .isVisible( { timeout: 1000 } ) + .catch( () => false ) + ) { + await editPatternButton.click(); + await page.waitForTimeout( 500 ); + await this.dismissEditSiteTour(); + } + await page.waitForTimeout( 1000 ); }, diff --git a/tests/e2e/multiple-post-templates.spec.js b/tests/e2e/multiple-post-templates.spec.js index 2e942f0..915c6db 100644 --- a/tests/e2e/multiple-post-templates.spec.js +++ b/tests/e2e/multiple-post-templates.spec.js @@ -134,21 +134,11 @@ test.describe( 'Multiple Post Templates', () => { await page .getByRole( 'spinbutton', { name: 'Posts per template' } ) .fill( '2' ); - await page.getByRole( 'spinbutton', { name: 'Columns' } ).click(); - await page - .getByRole( 'spinbutton', { name: 'Columns' } ) - .press( 'Shift+ArrowLeft' ); - await page.getByRole( 'spinbutton', { name: 'Columns' } ).fill( '2' ); await page .getByRole( 'toolbar', { name: 'Block tools' } ) .getByLabel( 'Options' ) .click(); await page.getByRole( 'menuitem', { name: /^Duplicate / } ).click(); - await page.getByRole( 'spinbutton', { name: 'Columns' } ).click(); - await page - .getByRole( 'spinbutton', { name: 'Columns' } ) - .press( 'Shift+ArrowLeft' ); - await page.getByRole( 'spinbutton', { name: 'Columns' } ).fill( '3' ); await page .getByRole( 'button', { name: 'Post Template Settings' } ) .click(); @@ -257,11 +247,6 @@ test.describe( 'Multiple Post Templates', () => { await page .getByRole( 'spinbutton', { name: 'Posts per template' } ) .fill( '2' ); - await page.getByRole( 'spinbutton', { name: 'Columns' } ).click(); - await page - .getByRole( 'spinbutton', { name: 'Columns' } ) - .press( 'Shift+ArrowLeft' ); - await page.getByRole( 'spinbutton', { name: 'Columns' } ).fill( '2' ); // Duplicate to create third post template await page @@ -271,11 +256,6 @@ test.describe( 'Multiple Post Templates', () => { await page.getByRole( 'menuitem', { name: /^Duplicate / } ).click(); // Configure third post template: leave Posts per template EMPTY (should auto-calculate to 7) - await page.getByRole( 'spinbutton', { name: 'Columns' } ).click(); - await page - .getByRole( 'spinbutton', { name: 'Columns' } ) - .press( 'Shift+ArrowLeft' ); - await page.getByRole( 'spinbutton', { name: 'Columns' } ).fill( '3' ); await page .getByRole( 'button', { name: 'Post Template Settings' } ) .click(); diff --git a/tests/e2e/query-presets.spec.js b/tests/e2e/query-presets.spec.js index ac86d89..c3ae086 100644 --- a/tests/e2e/query-presets.spec.js +++ b/tests/e2e/query-presets.spec.js @@ -165,10 +165,16 @@ test.describe( 'Query Presets', () => { title: 'Preset Test Page', } ); - // Insert a Query Loop block with inner blocks to bypass the pattern chooser + // Insert a Query Loop block with inner blocks to bypass the pattern + // chooser. Inserted already inherit: false, WordPress 7.x's core + // Query block inspector can crash on mount — it reads + // getPostType( postType )?.labels.singular_name without guarding + // `.labels`, and that record isn't always hydrated yet the moment a + // non-inherited query first renders. Insert inheriting (the default) + // and switch to a custom query afterwards, once the block has + // settled, to avoid the race. await editor.insertBlock( { name: 'core/query', - attributes: { query: { inherit: false, perPage: 5 } }, innerBlocks: [ { name: 'core/post-template', @@ -184,6 +190,10 @@ test.describe( 'Query Presets', () => { // Open settings sidebar await blockEditor.openSettingsSidebar(); + // Switch to a custom (non-inherited) query now that the block has + // mounted and settled. + await blockEditor.queryBlock.setAsCustom(); + // Expand Extra Query Loop Settings await blockEditor.queryBlock.openSettingsPanel();