Fix E2E tests for WordPress 6.5 (#44593)

* Add sharding to Blocks e2e tests

* Changelog

* Push a change to Blocks README to trigger tests

* Fix syntax

* Fixed again

* Try again

* Trying to get the shard number

* Shard names

* fix E2E test

* use wordpress 6.5 as test env

* update util

* fix Mini Cart Block E2E test

* add editor dependency

* fix E2E tests

* fix E2E tests

* fix E2E tests

* restore global setup file

* fix E2E tests

* fix global setup

* try now

* try now

* fix E2E test

* fix E2E test

* fix mini cart E2E test

* add changelog

* complete all the jobs

* update playwright

* fix E2E tests

* fix E2E test

* try now

* fix E2E test

* not show welcome guide for the post editor

* update configuration

* fix guest storage state

* fix E2E tests

* check now

* fix E2E tests

* fix command

* improve selector

* use WordPress 6.5 beta 2

* use WordPress 6.5 beta 3

* fix canvas use

* wait for button

* fix E2E test

* fix E2E test

* fix product button

* fix product collection tests

* fix wp build link

* use beforeEach

* fix E2E tests

* use WordPress RC2

* Add changefile(s) from automation for the following project(s): woocommerce-blocks, woocommerce

* trigger CI

* fix E2E tests

* fix E2E tests

* fix E2E test

* fix E2E tests

* add timeout

* Fix flaky locator assertions
...by replacing them with dedicaed auto-waiting ones.

* Apply correct use of waitForRequest/Response and remove where unnecessary

* Remove obsolete waitUntils

* Fix accidentally isolated test

* Replace saveTemplate with core's saveSiteEditorEntities

* Fix findProductRow util

* Restore necessary request waiters

* Use activateTheme util instead of cli call

* Remove unused import

* Fix request destructured call
Request properties cannot be destructured (todo: create upstream issue)

* Revert some waitForRequest changes
These need to be investigated for heavy bleeding from side-effects

* Fix failing cart checkout test

* Set navigation timeout to 10s
We need this so that API like page.goto or page.waitForURL doesn't take 100 seconds (global timeout) to throw.

* Do not close the page in the page fixture override
The page will be closed anyway, and by closing it explicitly in the teardown phase of the fixture we create a flaky race condition where the page might be closed before the action/navigation timeout is reached, resulting in "page closed!" error instead of, e.g. "locator.fill timed out".

* Revert product collection tests due to conflicts

* Try fixing E2E test

* Remove some random change

* Revert to programmatic blur 🤷

* Fix additional checkout fields test

* Add a waitForRequest safety check in case it's debounced

* Fix price filter test

* Fix flaky visitTemplateEditor util

* Remove obsolete code from global setup

* Revert "Fix flaky visitTemplateEditor util"

This reverts commit 227336f265.

* update to WordPress RC3

* Add waitForCustomerDataUpdate function

* Don't wait for requests and use data store instead

* Try with new wait condition

* Re-add wait condition

* Wait for customer update in guest checkout test

* Add changelog

* fix lint error

* fix some E2E tests

* disable welcome guide

* remove beforeAll

* add timeout

* add another timeout

* increase timeout

* Add call to waitForSiteEditorFinishLoading when editing the theme template

* remove timeout

* remove not necessary comment

* clean changelog

* Add changefile(s) from automation for the following project(s): woocommerce-blocks, woocommerce

* remove changelog

---------

Co-authored-by: Jon Lane <jon.lane@automattic.com>
Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: Bart Kalisz <bartlomiej.kalisz@gmail.com>
Co-authored-by: Karol Manijak <20098064+kmanijak@users.noreply.github.com>
Co-authored-by: Thomas Roberts <thomas.roberts@automattic.com>
Co-authored-by: Albert Juhé Lluveras <contact@albertjuhe.com>
This commit is contained in:
Luigi Teschio 2024-03-27 10:54:44 +01:00 committed by GitHub
parent ca7e3b99ed
commit 66b5481590
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
45 changed files with 516 additions and 634 deletions

View File

@ -1,5 +1,5 @@
{
"core": null,
"core": "https://wordpress.org/wordpress-6.5-RC3.zip",
"plugins": [
"https://github.com/WP-API/Basic-Auth/archive/master.zip",
"https://downloads.wordpress.org/plugin/wordpress-importer.0.8.zip",

View File

@ -186,7 +186,7 @@
"@wordpress/dom": "3.27.0",
"@wordpress/dom-ready": "3.27.0",
"@wordpress/e2e-test-utils": "10.12.0",
"@wordpress/e2e-test-utils-playwright": "wp-6.4",
"@wordpress/e2e-test-utils-playwright": "wp-6.5",
"@wordpress/e2e-tests": "^4.9.2",
"@wordpress/element": "5.22.0",
"@wordpress/env": "8.2.0",

View File

@ -1,19 +1,9 @@
/**
* External dependencies
*/
import {
BLOCK_THEME_WITH_TEMPLATES_NAME,
BLOCK_THEME_WITH_TEMPLATES_SLUG,
cli,
} from '@woocommerce/e2e-utils';
import { test as setup, expect } from '@woocommerce/e2e-playwright-utils';
import { BLOCK_THEME_WITH_TEMPLATES_SLUG } from '@woocommerce/e2e-utils';
import { test as setup } from '@woocommerce/e2e-playwright-utils';
setup( 'Sets up the block theme with templates', async ( { admin } ) => {
await cli(
`npm run wp-env run tests-cli -- wp theme activate ${ BLOCK_THEME_WITH_TEMPLATES_SLUG }`
);
await admin.page.goto( '/wp-admin/themes.php' );
await expect(
admin.page.getByText( `Active: ${ BLOCK_THEME_WITH_TEMPLATES_NAME }` )
).toBeVisible();
setup( 'Sets up the block theme with templates', async ( { requestUtils } ) => {
await requestUtils.activateTheme( BLOCK_THEME_WITH_TEMPLATES_SLUG );
} );

View File

@ -41,6 +41,45 @@ const prepareAttributes = async () => {
.getByRole( 'button' )
.click();
await page.goto( BASE_URL + '/wp-admin/post-new.php' );
await page.waitForFunction( () => {
return window.wp.data !== undefined;
} );
// Disable the welcome guide for the site editor.
await page.evaluate( () => {
return Promise.all( [
window.wp.data
.dispatch( 'core/preferences' )
.set( 'core/edit-site', 'welcomeGuide', false ),
window.wp.data
.dispatch( 'core/preferences' )
.set( 'core/edit-site', 'welcomeGuideStyles', false ),
window.wp.data
.dispatch( 'core/preferences' )
.set( 'core/edit-site', 'welcomeGuidePage', false ),
window.wp.data
.dispatch( 'core/preferences' )
.set( 'core/edit-site', 'welcomeGuideTemplate', false ),
window.wp.data
.dispatch( 'core/preferences' )
.set( 'core/edit-post', 'welcomeGuide', false ),
window.wp.data
.dispatch( 'core/preferences' )
.set( 'core/edit-post', 'welcomeGuideStyles', false ),
window.wp.data
.dispatch( 'core/preferences' )
.set( 'core/edit-post', 'welcomeGuidePage', false ),
window.wp.data
.dispatch( 'core/preferences' )
.set( 'core/edit-post', 'welcomeGuideTemplate', false ),
] );
} );
await page.context().storageState( { path: adminFile } );
await context.close();
await browser.close();

View File

@ -143,8 +143,8 @@ const test = base.extend<
};
}
>( {
admin: async ( { page, pageUtils }, use ) => {
await use( new Admin( { page, pageUtils } ) );
admin: async ( { page, pageUtils, editor }, use ) => {
await use( new Admin( { page, pageUtils, editor } ) );
},
editor: async ( { page }, use ) => {
await use( new Editor( { page } ) );
@ -158,8 +158,6 @@ const test = base.extend<
await page.evaluate( () => {
window.localStorage.clear();
} );
await page.close();
},
pageUtils: async ( { page }, use ) => {
await use( new PageUtils( { page } ) );

View File

@ -43,6 +43,7 @@ const config: ExtendedPlaywrightTestConfig = {
viewport: { width: 1280, height: 720 },
storageState: STORAGE_STATE_PATH,
actionTimeout: 10_000,
navigationTimeout: 10_000,
},
projects: [
{

View File

@ -9,7 +9,7 @@ import { test, expect } from '@woocommerce/e2e-playwright-utils';
test.describe( 'A basic set of tests to ensure WP, wp-admin and my-account load', async () => {
test( 'Load the home page', async ( { page } ) => {
await page.goto( '/', { waitUntil: 'commit' } );
await page.goto( '/' );
const title = page
.locator( 'header' )
.locator( '.wp-block-site-title' );
@ -18,7 +18,7 @@ test.describe( 'A basic set of tests to ensure WP, wp-admin and my-account load'
test.describe( 'Sign in as admin', () => {
test( 'Load wp-admin', async ( { page } ) => {
await page.goto( '/wp-admin', { waitUntil: 'commit' } );
await page.goto( '/wp-admin' );
const title = page.locator( 'div.wrap > h1' );
await expect( title ).toHaveText( 'Dashboard' );
} );
@ -29,7 +29,7 @@ test.describe( 'A basic set of tests to ensure WP, wp-admin and my-account load'
storageState: process.env.CUSTOMERSTATE,
} );
test( 'Load customer my account page', async ( { page } ) => {
await page.goto( '/my-account', { waitUntil: 'commit' } );
await page.goto( '/my-account' );
const title = page.locator( 'h1.wp-block-post-title' );
await expect( title ).toHaveText( 'My Account' );
} );

View File

@ -98,15 +98,19 @@ test.describe( 'Cart performance', () => {
while ( i-- ) {
const start = performance.now();
await page.click(
'button.wc-block-components-quantity-selector__button--plus'
);
const response = await page.waitForResponse(
const responsePromise = page.waitForResponse(
( responseFromWait ) =>
responseFromWait.url().includes( '/wc/store/v1/batch' ) &&
responseFromWait.status() === 207
);
await expect( response.ok() ).toBeTruthy();
await page.click(
'button.wc-block-components-quantity-selector__button--plus'
);
const response = await responsePromise;
expect( response.ok() ).toBeTruthy();
const end = performance.now();
timesForResponse.push( end - start );
@ -136,17 +140,20 @@ test.describe( 'Cart performance', () => {
const start = performance.now();
await page.fill( '[aria-label="Enter code"]', 'test_coupon' );
await page.click(
'button.wc-block-components-totals-coupon__button'
);
const response = await page.waitForResponse(
const responsePromise = page.waitForResponse(
( responseFromWait ) =>
responseFromWait.url().includes( '/wc/store/v1/batch' ) &&
responseFromWait.status() === 207
);
await expect( response.ok() ).toBeTruthy();
await page.click(
'button.wc-block-components-totals-coupon__button'
);
const response = await responsePromise;
expect( response.ok() ).toBeTruthy();
const end = performance.now();
timesForResponse.push( end - start );

View File

@ -98,6 +98,10 @@ test.describe( 'Shopper → Coupon', () => {
await page.getByLabel( 'Enter code' ).fill( 'single-use-coupon' );
await page.getByRole( 'button', { name: 'Apply' } ).click();
await expect(
page.getByLabel( 'Remove coupon "single-use-coupon"' )
).toBeVisible();
await checkoutPageObject.fillInCheckoutWithTestData();
await checkoutPageObject.placeOrder();

View File

@ -96,11 +96,12 @@ test.describe( 'Shopper → Notice Templates', () => {
} );
test( 'custom block notice templates are visible by template overwrite', async ( {
requestUtils,
frontendUtils,
page,
} ) => {
await cli(
`npm run wp-env run tests-cli -- wp theme activate ${ BLOCK_CHILD_THEME_WITH_BLOCK_NOTICES_TEMPLATE_SLUG }`
await requestUtils.activateTheme(
BLOCK_CHILD_THEME_WITH_BLOCK_NOTICES_TEMPLATE_SLUG
);
await frontendUtils.goToCartShortcode();
@ -142,17 +143,16 @@ test.describe( 'Shopper → Notice Templates', () => {
page.locator( '.wc-block-components-notice-banner.is-success svg' )
).toBeVisible();
await cli(
`npm run wp-env run tests-cli -- wp theme activate ${ BLOCK_THEME_SLUG }`
);
await requestUtils.activateTheme( BLOCK_THEME_SLUG );
} );
test( 'classic notice templates are visible by template overwrite', async ( {
requestUtils,
frontendUtils,
page,
} ) => {
await cli(
`npm run wp-env run tests-cli -- wp theme activate ${ BLOCK_CHILD_THEME_WITH_CLASSIC_NOTICES_TEMPLATE_SLUG }`
await requestUtils.activateTheme(
BLOCK_CHILD_THEME_WITH_CLASSIC_NOTICES_TEMPLATE_SLUG
);
await frontendUtils.goToCartShortcode();
@ -198,17 +198,16 @@ test.describe( 'Shopper → Notice Templates', () => {
page.locator( '.woocommerce-notices-wrapper .woocommerce-info' )
).toBeVisible();
await cli(
`npm run wp-env run tests-cli -- wp theme activate ${ BLOCK_THEME_SLUG }`
);
await requestUtils.activateTheme( BLOCK_THEME_SLUG );
} );
test( 'default classic notice templates cannot be triggered by filter', async ( {
requestUtils,
frontendUtils,
page,
} ) => {
await cli(
`npm run wp-env run tests-cli -- wp theme activate ${ BLOCK_CHILD_THEME_WITH_BLOCK_NOTICES_FILTER_SLUG }`
await requestUtils.activateTheme(
BLOCK_CHILD_THEME_WITH_BLOCK_NOTICES_FILTER_SLUG
);
await frontendUtils.goToCartShortcode();
@ -254,8 +253,6 @@ test.describe( 'Shopper → Notice Templates', () => {
page.locator( '.wc-block-components-notice-banner.is-success svg' )
).toBeVisible();
await cli(
`npm run wp-env run tests-cli -- wp theme activate ${ BLOCK_THEME_SLUG }`
);
await requestUtils.activateTheme( BLOCK_THEME_SLUG );
} );
} );

View File

@ -93,11 +93,12 @@ test.describe( 'Shopper → Notice Templates', () => {
} );
test( 'custom classic notice templates are visible by template overwrite', async ( {
requestUtils,
frontendUtils,
page,
} ) => {
await cli(
`npm run wp-env run tests-cli -- wp theme activate ${ CLASSIC_CHILD_THEME_WITH_CLASSIC_NOTICES_TEMPLATE_SLUG }`
await requestUtils.activateTheme(
CLASSIC_CHILD_THEME_WITH_CLASSIC_NOTICES_TEMPLATE_SLUG
);
await frontendUtils.goToCartShortcode();
@ -143,17 +144,16 @@ test.describe( 'Shopper → Notice Templates', () => {
page.locator( '.woocommerce-notices-wrapper .woocommerce-info' )
).toBeVisible();
await cli(
`npm run wp-env run tests-cli -- wp theme activate ${ CLASSIC_THEME_SLUG }`
);
await requestUtils.activateTheme( CLASSIC_THEME_SLUG );
} );
test( 'custom block notice templates are visible by template overwrite', async ( {
requestUtils,
frontendUtils,
page,
} ) => {
await cli(
`npm run wp-env run tests-cli -- wp theme activate ${ CLASSIC_CHILD_THEME_WITH_BLOCK_NOTICES_TEMPLATE_SLUG }`
await requestUtils.activateTheme(
CLASSIC_CHILD_THEME_WITH_BLOCK_NOTICES_TEMPLATE_SLUG
);
await frontendUtils.goToCartShortcode();
@ -195,17 +195,16 @@ test.describe( 'Shopper → Notice Templates', () => {
page.locator( '.wc-block-components-notice-banner.is-success svg' )
).toBeVisible();
await cli(
`npm run wp-env run tests-cli -- wp theme activate ${ CLASSIC_THEME_SLUG }`
);
await requestUtils.activateTheme( CLASSIC_THEME_SLUG );
} );
test( 'default block notice templates are visible by filter', async ( {
requestUtils,
frontendUtils,
page,
} ) => {
await cli(
`npm run wp-env run tests-cli -- wp theme activate ${ CLASSIC_CHILD_THEME_WITH_BLOCK_NOTICES_FILTER_SLUG }`
await requestUtils.activateTheme(
CLASSIC_CHILD_THEME_WITH_BLOCK_NOTICES_FILTER_SLUG
);
await frontendUtils.goToCartShortcode();
@ -245,8 +244,6 @@ test.describe( 'Shopper → Notice Templates', () => {
page.locator( '.wc-block-components-notice-banner.is-success svg' )
).toBeVisible();
await cli(
`npm run wp-env run tests-cli -- wp theme activate ${ CLASSIC_THEME_SLUG }`
);
await requestUtils.activateTheme( CLASSIC_THEME_SLUG );
} );
} );

View File

@ -11,21 +11,8 @@ export class CartPage {
}
async findProductRow( productName: string ) {
await this.page.waitForSelector( '.wc-block-cart-items__row' );
const productRows = this.page.locator( '.wc-block-cart-items__row' );
const rowCount = await productRows.count();
for ( let i = 0; i < rowCount; i++ ) {
const productRow = productRows.nth( i );
const nameElement = productRow.locator(
'.wc-block-components-product-name'
);
const nameText = await nameElement.innerText();
if ( nameText === productName ) {
return productRow;
}
}
return productRows;
return this.page.locator( '.wc-block-cart-items__row', {
hasText: new RegExp( productName ),
} );
}
}

View File

@ -361,8 +361,11 @@ test.describe( 'Shopper → Additional Checkout Fields', () => {
name: 'Additional order information',
} )
.getByLabel( 'How did you hear about us?' )
.fill( '' );
.click();
await checkoutPageObject.page
.getByRole( 'group', {
name: 'Additional order information',
} )
.locator(
'ul.components-form-token-field__suggestions-list > li'
)

View File

@ -258,7 +258,7 @@ test.describe( 'Shipping and Billing Addresses', () => {
const blockSelectorInEditor = blockData.selectors.editor.block as string;
test.beforeEach(
async ( { editor, frontendUtils, admin, editorUtils } ) => {
async ( { editor, frontendUtils, admin, editorUtils, page } ) => {
await admin.visitSiteEditor( {
postId: 'woocommerce/woocommerce//page-checkout',
postType: 'wp_template',
@ -270,7 +270,7 @@ test.describe( 'Shipping and Billing Addresses', () => {
' [data-type="woocommerce/checkout-shipping-address-block"]'
);
const checkbox = editor.page.getByRole( 'checkbox', {
const checkbox = page.getByRole( 'checkbox', {
name: 'Company',
exact: true,
} );
@ -286,31 +286,33 @@ test.describe( 'Shipping and Billing Addresses', () => {
}
);
test.afterEach( async ( { frontendUtils, admin, editorUtils, editor } ) => {
await frontendUtils.emptyCart();
await admin.visitSiteEditor( {
postId: 'woocommerce/woocommerce//page-checkout',
postType: 'wp_template',
} );
await editorUtils.enterEditMode();
await editor.openDocumentSettingsSidebar();
await editor.selectBlocks(
blockSelectorInEditor +
' [data-type="woocommerce/checkout-shipping-address-block"]'
);
const checkbox = editor.page.getByRole( 'checkbox', {
name: 'Company',
exact: true,
} );
await checkbox.uncheck();
await expect( checkbox ).not.toBeChecked();
await expect(
editor.canvas.locator(
'.wc-block-checkout__shipping-fields .wc-block-components-address-form__company'
)
).toBeHidden();
await editorUtils.saveSiteEditorEntities();
} );
test.afterEach(
async ( { frontendUtils, admin, editorUtils, editor, page } ) => {
await frontendUtils.emptyCart();
await admin.visitSiteEditor( {
postId: 'woocommerce/woocommerce//page-checkout',
postType: 'wp_template',
} );
await editorUtils.enterEditMode();
await editor.openDocumentSettingsSidebar();
await editor.selectBlocks(
blockSelectorInEditor +
' [data-type="woocommerce/checkout-shipping-address-block"]'
);
const checkbox = page.getByRole( 'checkbox', {
name: 'Company',
exact: true,
} );
await checkbox.uncheck();
await expect( checkbox ).not.toBeChecked();
await expect(
editor.canvas.locator(
'.wc-block-checkout__shipping-fields .wc-block-components-address-form__company'
)
).toBeHidden();
await editorUtils.saveSiteEditorEntities();
}
);
test( 'User can add postcodes for different countries', async ( {
frontendUtils,

View File

@ -160,6 +160,7 @@ export class CheckoutPage {
*/
async waitForCheckoutToFinishUpdating() {
await this.page.evaluate( 'document.activeElement.blur()' );
await this.page.waitForFunction( () => {
return (
! window.wp.data
@ -182,6 +183,18 @@ export class CheckoutPage {
* when testing for errors on the checkout page.
*/
async placeOrder( waitForRedirect = true ) {
await this.page
.waitForRequest(
( request ) => {
return request.url().includes( 'batch' );
},
{ timeout: 3000 }
)
.catch( () => {
// Do nothing. This is just in case there's a debounced request
// still to be made, e.g. from checking "Can a truck fit down
// your road?" field.
} );
await this.waitForCheckoutToFinishUpdating();
await this.page.getByText( 'Place Order', { exact: true } ).click();
if ( waitForRedirect ) {
@ -353,9 +366,6 @@ export class CheckoutPage {
const field = billingForm.getByLabel( label, { exact: true } );
await field.fill( value );
}
// Blur active field to trigger customer address update.
await this.page.keyboard.press( 'Escape' );
}
async fillShippingDetails(

View File

@ -46,7 +46,6 @@ test.describe( 'Shopper → Order Confirmation (logged in user)', () => {
postType: 'wp_template',
} );
await editorUtils.enterEditMode();
await editorUtils.closeWelcomeGuideModal();
await editorUtils.transformIntoBlocks();
} );

View File

@ -46,20 +46,10 @@ test.describe( 'Product Filter: Active Filters Block', async () => {
} ) => {
await page.goto( `${ defaultBlockPost.link }?rating_filter=1,2,5` );
const hasTitle =
( await page.locator( 'text=Rating:' ).count() ) === 1;
expect( hasTitle ).toBe( true );
for ( const text of [
'Rated 1 out of 5',
'Rated 2 out of 5',
'Rated 5 out of 5',
] ) {
const hasFilter =
( await page.locator( `text=${ text }` ).count() ) === 1;
expect( hasFilter ).toBe( true );
}
await expect( page.getByText( 'Rating:' ) ).toBeVisible();
await expect( page.getByText( 'Rated 1 out of 5' ) ).toBeVisible();
await expect( page.getByText( 'Rated 2 out of 5' ) ).toBeVisible();
await expect( page.getByText( 'Rated 5 out of 5' ) ).toBeVisible();
} );
test( 'With stock filters applied it shows the correct active filters', async ( {
@ -70,16 +60,9 @@ test.describe( 'Product Filter: Active Filters Block', async () => {
`${ defaultBlockPost.link }?filter_stock_status=instock,onbackorder`
);
const hasTitle =
( await page.locator( 'text=Stock Status:' ).count() ) === 1;
expect( hasTitle ).toBe( true );
for ( const text of [ 'In stock', 'On backorder' ] ) {
const hasFilter =
( await page.locator( `text=${ text }` ).count() ) === 1;
expect( hasFilter ).toBe( true );
}
await expect( page.getByText( 'Stock Status:' ) ).toBeVisible();
await expect( page.getByText( 'In stock' ) ).toBeVisible();
await expect( page.getByText( 'On backorder' ) ).toBeVisible();
} );
test( 'With attribute filters applied it shows the correct active filters', async ( {
@ -90,16 +73,9 @@ test.describe( 'Product Filter: Active Filters Block', async () => {
`${ defaultBlockPost.link }?filter_color=blue,gray&query_type_color=or`
);
const hasTitle =
( await page.locator( 'text=Color:' ).count() ) === 1;
expect( hasTitle ).toBe( true );
for ( const text of [ 'Blue', 'Gray' ] ) {
const hasFilter =
( await page.locator( `text=${ text }` ).count() ) === 1;
expect( hasFilter ).toBe( true );
}
await expect( page.getByText( 'Color:' ) ).toBeVisible();
await expect( page.getByText( 'Blue' ) ).toBeVisible();
await expect( page.getByText( 'Gray' ) ).toBeVisible();
} );
test( 'With price filters applied it shows the correct active filters', async ( {
@ -110,15 +86,10 @@ test.describe( 'Product Filter: Active Filters Block', async () => {
`${ defaultBlockPost.link }?min_price=17&max_price=71`
);
const hasTitle =
( await page.locator( 'text=Price:' ).count() ) === 1;
expect( hasTitle ).toBe( true );
const hasFilter =
( await page.locator( `text=Between $17 and $71` ).count() ) ===
1;
expect( hasFilter ).toBe( true );
await expect( page.getByText( 'Price:' ) ).toBeVisible();
await expect(
page.getByText( 'Between $17 and $71' )
).toBeVisible();
} );
} );
} );

View File

@ -37,30 +37,30 @@ test.describe( 'Filter blocks registration', async () => {
} );
test( 'Variations can be inserted through the inserter.', async ( {
editor,
page,
editorUtils,
} ) => {
for ( const block of filterBlocks ) {
await editorUtils.insertBlockUsingGlobalInserter( block.title );
await expect(
editor.canvas.getByLabel( `Block: ${ block.title }` )
page.getByLabel( `Block: ${ block.title }` )
).toBeVisible();
}
} );
test( 'Each filter block comes with a default title', async ( {
editor,
editorUtils,
page,
} ) => {
for ( const block of filterBlocks ) {
await editorUtils.insertBlockUsingGlobalInserter( block.title );
await expect(
editor.canvas
page
.getByLabel( `Block: Product Filter` )
.getByLabel( 'Block: Heading' )
.and( editor.canvas.getByText( block.heading ) )
.and( page.getByText( block.heading ) )
).toBeVisible();
}
} );

View File

@ -31,8 +31,7 @@ test.describe( 'Product Filter: Rating Filter Block', async () => {
await page.goto( defaultBlockPost.link );
const ratingStars = page.getByLabel( /^Rated \d out of 5/ );
const count = await ratingStars.count();
expect( count ).toBe( 2 );
await expect( ratingStars ).toHaveCount( 2 );
// See bin/scripts/parallel/reviews.sh for reviews data.
await expect( ratingStars.nth( 0 ) ).toHaveAttribute(
@ -63,9 +62,7 @@ test.describe( 'Product Filter: Rating Filter Block', async () => {
);
const products = page.locator( '.wc-block-product' );
const productCount = await products.count();
expect( productCount ).toBe( 1 );
await expect( products ).toHaveCount( 1 );
} );
} );
} );

View File

@ -53,6 +53,7 @@ test.describe( 'Merchant → Mini Cart', () => {
await editorUtils.page
.getByLabel( 'Search for blocks and patterns' )
.fill( blockData.slug );
const miniCartButton = editorUtils.page.getByRole( 'option', {
name: blockData.name,
exact: true,

View File

@ -116,16 +116,9 @@ test.describe( `${ blockData.name }`, () => {
await pageObject.toggleFullScreenOnClickSetting( false );
await Promise.all( [
editor.saveSiteEditorEntities(),
editor.page.waitForResponse( ( response ) =>
response.url().includes( 'wp-json/wp/v2/templates/' )
),
] );
await editor.saveSiteEditorEntities();
await page.goto( blockData.productPage, {
waitUntil: 'commit',
} );
await page.goto( blockData.productPage );
const block = await frontendUtils.getBlockByName( blockData.name );
@ -145,16 +138,9 @@ test.describe( `${ blockData.name }`, () => {
await pageObject.toggleFullScreenOnClickSetting( false );
await Promise.all( [
editor.saveSiteEditorEntities(),
page.waitForResponse( ( response ) =>
response.url().includes( 'wp-json/wp/v2/templates/' )
),
] );
await editor.saveSiteEditorEntities();
await page.goto( blockData.productPageNotOnSale, {
waitUntil: 'commit',
} );
await page.goto( blockData.productPageNotOnSale );
const block = await frontendUtils.getBlockByName( blockData.name );
@ -191,16 +177,9 @@ test.describe( `${ blockData.name }`, () => {
editorBoundingClientRect.productSaleBadge.x - blockData.margin
).toEqual( editorBoundingClientRect.productSaleBadgeContainer.x );
await Promise.all( [
editor.saveSiteEditorEntities(),
page.waitForResponse( ( response ) =>
response.url().includes( 'wp-json/wp/v2/templates/' )
),
] );
await editor.saveSiteEditorEntities();
await page.goto( blockData.productPage, {
waitUntil: 'commit',
} );
await page.goto( blockData.productPage );
const clientBoundingClientRect = await getBoundingClientRect( {
frontendUtils,
@ -245,16 +224,9 @@ test.describe( `${ blockData.name }`, () => {
editorBoundingClientRect.productSaleBadgeContainer.right
);
await Promise.all( [
editor.saveSiteEditorEntities(),
page.waitForResponse( ( response ) =>
response.url().includes( 'wp-json/wp/v2/templates/' )
),
] );
await editor.saveSiteEditorEntities();
await page.goto( blockData.productPage, {
waitUntil: 'commit',
} );
await page.goto( blockData.productPage );
const clientBoundingClientRect = await getBoundingClientRect( {
frontendUtils,
@ -295,16 +267,9 @@ test.describe( `${ blockData.name }`, () => {
editorBoundingClientRect.productSaleBadgeContainer.right
);
await Promise.all( [
editor.saveSiteEditorEntities(),
page.waitForResponse( ( response ) =>
response.url().includes( 'wp-json/wp/v2/templates/' )
),
] );
await editor.saveSiteEditorEntities();
await page.goto( blockData.productPage, {
waitUntil: 'commit',
} );
await page.goto( blockData.productPage );
const clientBoundingClientRect = await getBoundingClientRect( {
frontendUtils,

View File

@ -34,8 +34,11 @@ const templates = [
];
const userText = 'Hello World in the page';
test.describe( 'Page Content Wrapper', async () => {
templates.forEach( async ( template ) => {
templates.forEach( async ( template ) => {
test.describe( 'Page Content Wrapper', async () => {
test.beforeAll( async ( { requestUtils } ) => {
await requestUtils.deleteAllTemplates( 'wp_template' );
} );
test( `the content of the ${ template.title } page is correctly rendered in the ${ template.title } template`, async ( {
admin,
page,
@ -43,8 +46,7 @@ test.describe( 'Page Content Wrapper', async () => {
frontendUtils,
} ) => {
await admin.visitAdminPage( 'edit.php?post_type=page' );
page.getByLabel( `${ template.title }” (Edit)` ).click();
await editorUtils.closeWelcomeGuideModal();
await page.getByLabel( `${ template.title }” (Edit)` ).click();
// Prevent trying to insert the paragraph block before the editor is ready.
await page.locator( template.blockClassName ).waitFor();
@ -53,6 +55,7 @@ test.describe( 'Page Content Wrapper', async () => {
name: 'core/paragraph',
attributes: { content: userText },
} );
await editorUtils.updatePost();
// Verify edits are in the template when viewed from the frontend.
@ -61,8 +64,7 @@ test.describe( 'Page Content Wrapper', async () => {
// Clean up the paragraph block added before.
await admin.visitAdminPage( 'edit.php?post_type=page' );
page.getByLabel( `${ template.title }” (Edit)` ).click();
await editorUtils.closeWelcomeGuideModal();
await page.getByLabel( `${ template.title }” (Edit)` ).click();
// Prevent trying to insert the paragraph block before the editor is ready.
await page.locator( template.blockClassName ).waitFor();

View File

@ -16,8 +16,8 @@ const blockData: BlockData< {
frontend: {},
editor: {},
},
urlSearchParamWhenFilterIsApplied: '?max_price=10',
endpointAPI: 'max_price=1000',
urlSearchParamWhenFilterIsApplied: '?max_price=5',
endpointAPI: 'max_price=500',
placeholderUrl: `${ BASE_URL }/wp-content/plugins/woocommerce/assets/images/placeholder.png`,
};
@ -35,7 +35,33 @@ test.describe( `${ blockData.name } Block - with All products Block`, () => {
await editor.publishPost();
const url = new URL( page.url() );
const postId = url.searchParams.get( 'post' );
await page.goto( `/?p=${ postId }` );
await page
.waitForResponse(
async ( response ) => {
if (
response.url().includes( 'products/collection-data' )
) {
const payload = await response.json();
// Price range seems to be the last thing to be loaded.
const containsPriceRange = !! payload.price_range;
return containsPriceRange;
}
return false;
},
{ timeout: 3000 }
)
.catch( () => {
// Do nothing. This is only to ensure the products are loaded.
// There are multiple requests until the products are fully
// loaded. We need to ensure the page is ready to be interacted
// with, hence the extra check. Ideally, this should be signaled
// by the UI (e.g., by a loading spinner), but we don't have
// that yet.
} );
} );
test( 'should show all products', async ( { frontendUtils } ) => {
@ -50,9 +76,9 @@ test.describe( `${ blockData.name } Block - with All products Block`, () => {
blockData.placeholderUrl
);
const products = await allProductsBlock.getByRole( 'listitem' ).all();
const products = allProductsBlock.getByRole( 'listitem' );
expect( products ).toHaveLength( 9 );
await expect( products ).toHaveCount( 9 );
} );
test( 'should show only products that match the filter', async ( {
@ -79,9 +105,10 @@ test.describe( `${ blockData.name } Block - with All products Block`, () => {
const maxPriceInput = page.getByRole( 'textbox', {
name: 'Filter products by maximum price',
} );
// await page.pause();
await maxPriceInput.dblclick();
await maxPriceInput.fill( '$10' );
await maxPriceInput.fill( '$5' );
await maxPriceInput.press( 'Tab' );
const allProductsBlock = await frontendUtils.getBlockByName(
@ -89,7 +116,6 @@ test.describe( `${ blockData.name } Block - with All products Block`, () => {
);
const img = allProductsBlock.locator( 'img' ).first();
await expect( img ).not.toHaveAttribute(
'src',
blockData.placeholderUrl
@ -116,7 +142,7 @@ test.describe( `${ blockData.name } Block - with PHP classic template`, () => {
postType: 'wp_template',
} );
await editor.canvas.click( 'body' );
await editor.canvas.locator( 'body' ).click();
await editor.insertBlock( {
name: 'woocommerce/filter-wrapper',
@ -126,7 +152,7 @@ test.describe( `${ blockData.name } Block - with PHP classic template`, () => {
},
} );
await editor.saveSiteEditorEntities();
await page.goto( `/shop`, { waitUntil: 'commit' } );
await page.goto( `/shop` );
} );
test.afterEach( async ( { templateApiUtils } ) => {
@ -140,14 +166,11 @@ test.describe( `${ blockData.name } Block - with PHP classic template`, () => {
'woocommerce/legacy-template'
);
legacyTemplate.waitFor();
const products = await legacyTemplate
const products = legacyTemplate
.getByRole( 'list' )
.locator( '.product' )
.all();
.locator( '.product' );
expect( products ).toHaveLength( 16 );
await expect( products ).toHaveCount( 16 );
} );
// eslint-disable-next-line playwright/no-skipped-test
@ -160,7 +183,7 @@ test.describe( `${ blockData.name } Block - with PHP classic template`, () => {
} );
await frontendUtils.selectTextInput( maxPriceInput );
await maxPriceInput.fill( '$10' );
await maxPriceInput.fill( '$5' );
await maxPriceInput.press( 'Tab' );
await page.waitForURL( ( url ) =>
url
@ -172,12 +195,11 @@ test.describe( `${ blockData.name } Block - with PHP classic template`, () => {
'woocommerce/legacy-template'
);
const products = await legacyTemplate
const products = legacyTemplate
.getByRole( 'list' )
.locator( '.product' )
.all();
.locator( '.product' );
expect( products ).toHaveLength( 1 );
await expect( products ).toHaveCount( 1 );
} );
test.afterAll( async () => {

View File

@ -13,6 +13,9 @@ import {
import { blockData, handleAddToCartAjaxSetting } from './utils';
test.describe( `${ blockData.name } Block`, () => {
test.beforeAll( async ( { requestUtils } ) => {
await requestUtils.deleteAllTemplates( 'wp_template' );
} );
test.beforeEach( async ( { frontendUtils, storeApiUtils } ) => {
await storeApiUtils.cleanCart();
await frontendUtils.goToShop();
@ -60,6 +63,7 @@ test.describe( `${ blockData.name } Block`, () => {
state: 'detached',
} );
await block.click();
await expect( block.locator( 'loading' ) ).toBeHidden();
await expect( block.getByRole( 'button' ) ).toHaveText( '1 in cart' );
await expect( block.getByRole( 'link' ) ).toHaveText( 'View cart' );

View File

@ -218,7 +218,7 @@ class ProductCollectionPage {
postType: 'wp_template',
} );
await this.editorUtils.waitForSiteEditorFinishLoading();
await this.editor.canvas.click( 'body' );
await this.page.click( 'body' );
await this.insertProductCollection();
await this.chooseCollectionInTemplate( collection );
await this.refreshLocators( 'editor' );

View File

@ -128,16 +128,9 @@ test.describe( `${ blockData.name }`, () => {
} ) => {
await addBlock( admin, editor, editorUtils );
await Promise.all( [
editor.saveSiteEditorEntities(),
page.waitForResponse( ( response ) =>
response.url().includes( 'wp-json/wp/v2/templates/' )
),
] );
await editor.saveSiteEditorEntities();
await page.goto( blockData.productPage, {
waitUntil: 'commit',
} );
await page.goto( blockData.productPage );
const block = await pageObject.getNextPreviousButtonsBlock( {
page: 'frontend',
@ -177,9 +170,7 @@ test.describe( `${ blockData.name }`, () => {
await editor.saveSiteEditorEntities();
await page.goto( blockData.productPage, {
waitUntil: 'commit',
} );
await page.goto( blockData.productPage );
const leftArrow = await page
.locator( blockData.selectors.editor.leftArrow.off )
@ -245,16 +236,9 @@ test.describe( `${ blockData.name }`, () => {
editorBoundingClientRect.gallery.right
);
await Promise.all( [
editor.saveSiteEditorEntities(),
page.waitForResponse( ( response ) =>
response.url().includes( 'wp-json/wp/v2/templates/' )
),
] );
await editor.saveSiteEditorEntities();
await page.goto( blockData.productPage, {
waitUntil: 'commit',
} );
await page.goto( blockData.productPage );
const frontendBoundingClientRect = await getBoundingClientRect( {
pageObject,
@ -326,16 +310,9 @@ test.describe( `${ blockData.name }`, () => {
editorBoundingClientRect.gallery.right
);
await Promise.all( [
editor.saveSiteEditorEntities(),
page.waitForResponse( ( response ) =>
response.url().includes( 'wp-json/wp/v2/templates/' )
),
] );
await editor.saveSiteEditorEntities();
await page.goto( blockData.productPage, {
waitUntil: 'commit',
} );
await page.goto( blockData.productPage );
const frontendBoundingClientRect = await getBoundingClientRect( {
pageObject,
@ -393,16 +370,9 @@ test.describe( `${ blockData.name }`, () => {
await expect( block ).toHaveCSS( 'align-items', 'flex-start' );
await Promise.all( [
editor.saveSiteEditorEntities(),
page.waitForResponse( ( response ) =>
response.url().includes( 'wp-json/wp/v2/templates/' )
),
] );
await editor.saveSiteEditorEntities();
await page.goto( blockData.productPage, {
waitUntil: 'commit',
} );
await page.goto( blockData.productPage );
const frontendBlock = await pageObject.getNextPreviousButtonsBlock(
{
@ -454,16 +424,9 @@ test.describe( `${ blockData.name }`, () => {
await expect( block ).toHaveCSS( 'align-items', 'center' );
await Promise.all( [
editor.saveSiteEditorEntities(),
page.waitForResponse( ( response ) =>
response.url().includes( 'wp-json/wp/v2/templates/' )
),
] );
await editor.saveSiteEditorEntities();
await page.goto( blockData.productPage, {
waitUntil: 'commit',
} );
await page.goto( blockData.productPage );
const frontendBlock = await pageObject.getNextPreviousButtonsBlock(
{
@ -510,16 +473,9 @@ test.describe( `${ blockData.name }`, () => {
await expect( block ).toHaveCSS( 'align-items', 'flex-end' );
await Promise.all( [
editor.saveSiteEditorEntities(),
page.waitForResponse( ( response ) =>
response.url().includes( 'wp-json/wp/v2/templates/' )
),
] );
await editor.saveSiteEditorEntities();
await page.goto( blockData.productPage, {
waitUntil: 'commit',
} );
await page.goto( blockData.productPage );
const frontendBlock = await pageObject.getNextPreviousButtonsBlock(
{

View File

@ -49,7 +49,7 @@ test.describe( `${ blockData.name }`, () => {
test( 'Renders Product Gallery Large Image block on the editor and frontend side', async ( {
page,
editorUtils,
editor,
pageObject,
} ) => {
await pageObject.addProductGalleryBlock( { cleanContent: true } );
@ -60,11 +60,9 @@ test.describe( `${ blockData.name }`, () => {
await expect( block ).toBeVisible();
await editorUtils.saveTemplate();
await editor.saveSiteEditorEntities();
await page.goto( blockData.productPage, {
waitUntil: 'commit',
} );
await page.goto( blockData.productPage );
const blockFrontend = await pageObject.getMainImageBlock( {
page: 'frontend',
@ -83,16 +81,14 @@ test.describe( `${ blockData.name }`, () => {
} );
test( 'should work on frontend when is enabled', async ( {
pageObject,
editorUtils,
editor,
page,
} ) => {
await pageObject.addProductGalleryBlock( { cleanContent: true } );
await pageObject.toggleZoomWhileHoveringSetting( true );
await editorUtils.saveTemplate();
await editor.saveSiteEditorEntities();
await page.goto( blockData.productPage, {
waitUntil: 'commit',
} );
await page.goto( blockData.productPage );
const blockFrontend = await pageObject.getMainImageBlock( {
page: 'frontend',
@ -115,21 +111,18 @@ test.describe( `${ blockData.name }`, () => {
test( 'should not work on frontend when is disabled', async ( {
pageObject,
editorUtils,
editor,
page,
} ) => {
await pageObject.addProductGalleryBlock( { cleanContent: true } );
await pageObject.toggleZoomWhileHoveringSetting( false );
const buttonElement =
await pageObject.getZoomWhileHoveringSetting();
const buttonElement = pageObject.getZoomWhileHoveringSetting();
await expect( buttonElement ).not.toBeChecked();
await editorUtils.saveTemplate();
await editor.saveSiteEditorEntities();
await page.goto( blockData.productPage, {
waitUntil: 'commit',
} );
await page.goto( blockData.productPage );
const blockFrontend = await pageObject.getMainImageBlock( {
page: 'frontend',
@ -152,7 +145,7 @@ test.describe( `${ blockData.name }`, () => {
test( 'Renders correct image when selecting a product variation in the Add to Cart With Options block', async ( {
page,
editorUtils,
editor,
pageObject,
} ) => {
await pageObject.addProductGalleryBlock( { cleanContent: false } );
@ -164,11 +157,9 @@ test.describe( `${ blockData.name }`, () => {
await expect( block ).toBeVisible();
await editorUtils.saveTemplate();
await editor.saveSiteEditorEntities();
await page.goto( blockData.productPage, {
waitUntil: 'commit',
} );
await page.goto( blockData.productPage );
const largeImageBlockOnFrontend = await pageObject.getMainImageBlock( {
page: 'frontend',

View File

@ -44,9 +44,12 @@ const test = base.extend< { pageObject: ProductGalleryPage } >( {
} );
test.describe( `${ blockData.name }`, () => {
test.beforeEach( async ( { requestUtils, admin, editorUtils, editor } ) => {
test.beforeAll( async ( { requestUtils } ) => {
await requestUtils.deleteAllTemplates( 'wp_template' );
await requestUtils.deleteAllTemplates( 'wp_template_part' );
} );
test.beforeEach( async ( { admin, editorUtils, editor } ) => {
await admin.visitSiteEditor( {
postId: `woocommerce/woocommerce//${ blockData.slug }`,
postType: 'wp_template',
@ -62,7 +65,7 @@ test.describe( `${ blockData.name }`, () => {
test( 'Renders Product Gallery Pager block on the editor and frontend side', async ( {
page,
editorUtils,
editor,
pageObject,
} ) => {
await pageObject.addProductGalleryBlock( { cleanContent: true } );
@ -73,11 +76,9 @@ test.describe( `${ blockData.name }`, () => {
await expect( block ).toBeVisible();
await editorUtils.saveTemplate();
await editor.saveSiteEditorEntities();
await page.goto( blockData.productPage, {
waitUntil: 'commit',
} );
await page.goto( blockData.productPage );
const blockFrontend = await pageObject.getMainImageBlock( {
page: 'frontend',
@ -111,15 +112,13 @@ test.describe( `${ blockData.name }`, () => {
await editor.saveSiteEditorEntities();
await page.goto( blockData.productPage, {
waitUntil: 'commit',
} );
await page.goto( blockData.productPage );
const pagerBlock = await page
.locator( blockData.selectors.frontend.pagerBlock )
.isVisible();
const pagerBlock = page.locator(
blockData.selectors.frontend.pagerBlock
);
expect( pagerBlock ).toBe( false );
await expect( pagerBlock ).toBeHidden();
} );
test( 'display pages as dot icons when display mode is set to "Dots"', async ( {
@ -146,24 +145,20 @@ test.describe( `${ blockData.name }`, () => {
await editor.saveSiteEditorEntities();
await page.goto( blockData.productPage, {
waitUntil: 'domcontentloaded',
} );
await page.goto( blockData.productPage );
const pagerBlock = await page
const pagerBlock = page
.locator( blockData.selectors.frontend.pagerBlock )
.nth( 0 )
.isVisible();
.first();
expect( pagerBlock ).toBe( true );
await expect( pagerBlock ).toBeVisible();
const dotIconsAmount = await page
const dotIconsAmount = page
.locator( blockData.selectors.frontend.pagerListContainer )
.nth( 0 )
.locator( 'svg' )
.count();
.first()
.locator( 'svg' );
expect( dotIconsAmount ).toEqual( 3 );
await expect( dotIconsAmount ).toHaveCount( 3 );
} );
test( 'display pages as numbers when display mode is set to "Digits"', async ( {
@ -190,27 +185,21 @@ test.describe( `${ blockData.name }`, () => {
await editor.saveSiteEditorEntities();
await page.goto( blockData.productPage, {
waitUntil: 'domcontentloaded',
} );
await page.goto( blockData.productPage );
const pagerBlock = await page
const pagerBlock = page
.locator( blockData.selectors.frontend.pagerBlock )
.nth( 0 )
.isVisible();
.first();
expect( pagerBlock ).toBe( true );
await expect( pagerBlock ).toBeVisible();
const pages = await page
const pages = page
.locator( blockData.selectors.frontend.pagerListContainer )
.nth( 0 )
.locator( blockData.selectors.frontend.pagerListItem )
.all();
.first()
.locator( blockData.selectors.frontend.pagerListItem );
expect( pages.length ).toEqual( 3 );
await expect( pages[ 0 ] ).toHaveText( '1' );
await expect( pages[ 1 ] ).toHaveText( '2' );
await expect( pages[ 2 ] ).toHaveText( '3' );
await expect( pages ).toHaveCount( 3 );
await expect( pages ).toHaveText( [ '1', '2', '3' ] );
} );
} );
} );

View File

@ -100,16 +100,9 @@ test.describe( `${ blockData.name }`, () => {
expect( isThumbnailsBlockEarlier ).toBe( true );
await Promise.all( [
editor.saveSiteEditorEntities(),
page.waitForResponse( ( response ) =>
response.url().includes( 'wp-json/wp/v2/templates/' )
),
] );
await editor.saveSiteEditorEntities();
await page.goto( blockData.productPage, {
waitUntil: 'commit',
} );
await page.goto( blockData.productPage );
const groupBlockFrontend = (
await frontendUtils.getBlockByClassWithParent(
@ -158,9 +151,7 @@ test.describe( `${ blockData.name }`, () => {
await editor.saveSiteEditorEntities();
await page.goto( blockData.productPage, {
waitUntil: 'commit',
} );
await page.goto( blockData.productPage );
} );
// We can test the left position of thumbnails by cross-checking:
@ -226,16 +217,9 @@ test.describe( `${ blockData.name }`, () => {
expect( isThumbnailsBlockEarlier ).toBe( true );
await Promise.all( [
editor.saveSiteEditorEntities(),
page.waitForResponse( ( response ) =>
response.url().includes( 'wp-json/wp/v2/templates/' )
),
] );
await editor.saveSiteEditorEntities();
await page.goto( blockData.productPage, {
waitUntil: 'commit',
} );
await page.goto( blockData.productPage );
const groupBlockFrontend = (
await frontendUtils.getBlockByClassWithParent(
@ -323,16 +307,8 @@ test.describe( `${ blockData.name }`, () => {
expect( isThumbnailsBlockEarlier ).toBe( false );
await Promise.all( [
editor.saveSiteEditorEntities(),
page.waitForResponse( ( response ) =>
response.url().includes( 'wp-json/wp/v2/templates/' )
),
] );
await page.goto( blockData.productPage, {
waitUntil: 'commit',
} );
await editor.saveSiteEditorEntities();
await page.goto( blockData.productPage );
const groupBlockFrontend = (
await frontendUtils.getBlockByClassWithParent(
@ -422,16 +398,8 @@ test.describe( `${ blockData.name }`, () => {
expect( isThumbnailsBlockEarlier ).toBe( false );
await Promise.all( [
editor.saveSiteEditorEntities(),
page.waitForResponse( ( response ) =>
response.url().includes( 'wp-json/wp/v2/templates/' )
),
] );
await page.goto( blockData.productPage, {
waitUntil: 'commit',
} );
await editor.saveSiteEditorEntities();
await page.goto( blockData.productPage );
const groupBlockFrontend = (
await frontendUtils.getBlockByClassWithParent(
@ -480,11 +448,11 @@ test.describe( `${ blockData.name }`, () => {
'4.2'
);
let numberOfThumbnailsOnScreen = await thumbnailsBlock
.locator( '.wc-block-product-gallery-thumbnails__thumbnail' )
.all();
let numberOfThumbnailsOnScreen = thumbnailsBlock.locator(
'.wc-block-product-gallery-thumbnails__thumbnail'
);
expect( numberOfThumbnailsOnScreen ).toHaveLength( 4 );
await expect( numberOfThumbnailsOnScreen ).toHaveCount( 4 );
await changeNumberOfThumbnailsInputValue(
page,
@ -492,11 +460,11 @@ test.describe( `${ blockData.name }`, () => {
'4.7'
);
numberOfThumbnailsOnScreen = await thumbnailsBlock
.locator( '.wc-block-product-gallery-thumbnails__thumbnail' )
.all();
numberOfThumbnailsOnScreen = thumbnailsBlock.locator(
'.wc-block-product-gallery-thumbnails__thumbnail'
);
expect( numberOfThumbnailsOnScreen ).toHaveLength( 5 );
await expect( numberOfThumbnailsOnScreen ).toHaveCount( 5 );
} );
} );
} );

View File

@ -2,7 +2,7 @@
* External dependencies
*/
import { test as base, expect } from '@woocommerce/e2e-playwright-utils';
import { Locator, Page } from '@playwright/test';
import { Locator } from '@playwright/test';
/**
* Internal dependencies
@ -67,14 +67,6 @@ export const getIsDialogOpen = async (
return productGalleryBlockParsedContext.isDialogOpen;
};
const waitForJavascriptFrontendFileIsLoaded = async ( page: Page ) => {
await page.waitForResponse(
( response ) =>
response.url().includes( 'product-gallery-frontend' ) &&
response.status() === 200
);
};
const getThumbnailImageIdByNth = async (
nth: number,
thumbnailsLocator: Locator
@ -109,16 +101,14 @@ test.describe( `${ blockData.name }`, () => {
test.describe( 'with thumbnails', () => {
test( 'should have as first thumbnail, the same image that it is visible in the Large Image block', async ( {
page,
editorUtils,
editor,
pageObject,
} ) => {
await pageObject.addProductGalleryBlock( { cleanContent: true } );
await editorUtils.saveTemplate();
await editor.saveSiteEditorEntities();
await page.goto( blockData.productPage, {
waitUntil: 'commit',
} );
await page.goto( blockData.productPage );
const visibleLargeImageId = await getVisibleLargeImageId(
await pageObject.getMainImageBlock( {
@ -138,19 +128,14 @@ test.describe( `${ blockData.name }`, () => {
test( 'should change the image when the user click on a thumbnail image', async ( {
page,
editorUtils,
editor,
pageObject,
} ) => {
await pageObject.addProductGalleryBlock( { cleanContent: true } );
await editorUtils.saveTemplate();
await editor.saveSiteEditorEntities();
await Promise.all( [
page.goto( blockData.productPage, {
waitUntil: 'load',
} ),
waitForJavascriptFrontendFileIsLoaded( page ),
] );
await page.goto( blockData.productPage );
const visibleLargeImageId = await getVisibleLargeImageId(
await pageObject.getMainImageBlock( {
@ -189,19 +174,14 @@ test.describe( `${ blockData.name }`, () => {
test.describe( 'with previous and next buttons', () => {
test( 'should change the image when the user click on the previous or next button', async ( {
page,
editorUtils,
editor,
pageObject,
} ) => {
await pageObject.addProductGalleryBlock( { cleanContent: true } );
await editorUtils.saveTemplate();
await editor.saveSiteEditorEntities();
await Promise.all( [
page.goto( blockData.productPage, {
waitUntil: 'load',
} ),
waitForJavascriptFrontendFileIsLoaded( page ),
] );
await page.goto( blockData.productPage );
const initialVisibleLargeImageId = await getVisibleLargeImageId(
await pageObject.getMainImageBlock( {
@ -255,19 +235,14 @@ test.describe( `${ blockData.name }`, () => {
test.describe( 'with pager', () => {
test( 'should change the image when the user click on a pager item', async ( {
page,
editorUtils,
editor,
pageObject,
} ) => {
await pageObject.addProductGalleryBlock( { cleanContent: true } );
await editorUtils.saveTemplate();
await editor.saveSiteEditorEntities();
await Promise.all( [
page.goto( blockData.productPage, {
waitUntil: 'load',
} ),
waitForJavascriptFrontendFileIsLoaded( page ),
] );
await page.goto( blockData.productPage );
const initialVisibleLargeImageId = await getVisibleLargeImageId(
await pageObject.getMainImageBlock( {
@ -330,19 +305,14 @@ test.describe( `${ blockData.name }`, () => {
test.describe( 'within pop-up', () => {
test( 'should display the same selected image when the pop-up is opened', async ( {
page,
editorUtils,
editor,
pageObject,
} ) => {
await pageObject.addProductGalleryBlock( { cleanContent: false } );
await editorUtils.saveTemplate();
await editor.saveSiteEditorEntities();
await Promise.all( [
page.goto( blockData.productPage, {
waitUntil: 'load',
} ),
waitForJavascriptFrontendFileIsLoaded( page ),
] );
await page.goto( blockData.productPage );
const initialVisibleLargeImageId = await getVisibleLargeImageId(
await pageObject.getMainImageBlock( {
@ -396,19 +366,14 @@ test.describe( `${ blockData.name }`, () => {
test( 'should reset to the first thumbnail when the pop-up is closed', async ( {
page,
editorUtils,
editor,
pageObject,
} ) => {
await pageObject.addProductGalleryBlock( { cleanContent: true } );
await editorUtils.saveTemplate();
await editor.saveSiteEditorEntities();
await Promise.all( [
page.goto( blockData.productPage, {
waitUntil: 'load',
} ),
waitForJavascriptFrontendFileIsLoaded( page ),
] );
await page.goto( blockData.productPage );
const largeImageBlock = await pageObject.getMainImageBlock( {
page: 'frontend',
@ -510,17 +475,12 @@ test.describe( `${ blockData.name }`, () => {
test( 'should open dialog on the frontend', async ( {
pageObject,
page,
editorUtils,
editor,
} ) => {
await pageObject.addProductGalleryBlock( { cleanContent: true } );
await editorUtils.saveTemplate();
await editor.saveSiteEditorEntities();
await Promise.all( [
page.goto( blockData.productPage, {
waitUntil: 'domcontentloaded',
} ),
waitForJavascriptFrontendFileIsLoaded( page ),
] );
await page.goto( blockData.productPage );
const mainImageBlock = await pageObject.getMainImageBlock( {
page: 'frontend',
@ -537,19 +497,13 @@ test.describe( `${ blockData.name }`, () => {
pageObject,
page,
editor,
editorUtils,
} ) => {
await pageObject.addProductGalleryBlock( { cleanContent: true } );
await editor.openDocumentSettingsSidebar();
await pageObject.toggleFullScreenOnClickSetting( false );
await editorUtils.saveTemplate();
await editor.saveSiteEditorEntities();
await Promise.all( [
page.goto( blockData.productPage, {
waitUntil: 'domcontentloaded',
} ),
waitForJavascriptFrontendFileIsLoaded( page ),
] );
await page.goto( blockData.productPage );
await expect( page.locator( 'dialog' ) ).toBeHidden();
@ -601,7 +555,7 @@ test.describe( `${ blockData.name }`, () => {
page,
editorUtils,
} ) => {
await admin.createNewPost( { legacyCanvas: true } );
await admin.createNewPost();
await editorUtils.openGlobalBlockInserter();
const productGalleryBlockOption = page
.getByRole( 'listbox', { name: 'WooCommerce' } )
@ -613,30 +567,22 @@ test.describe( `${ blockData.name }`, () => {
test( 'should show (square) cropped main product images when crop option is enabled', async ( {
page,
editorUtils,
editor,
pageObject,
} ) => {
await pageObject.addProductGalleryBlock( { cleanContent: true } );
const block = await pageObject.getMainImageBlock( {
page: 'editor',
} );
await expect( block ).toBeVisible();
await page
.locator( blockData.selectors.editor.settings.cropImagesOption )
.click();
await editorUtils.saveTemplate();
await editor.saveSiteEditorEntities();
await expect(
page.locator( blockData.selectors.editor.settings.cropImagesOption )
).toBeChecked();
await page.goto( blockData.productPage, {
waitUntil: 'commit',
} );
await page.goto( blockData.productPage );
const image = await page
.locator(
@ -645,8 +591,8 @@ test.describe( `${ blockData.name }`, () => {
.first()
.boundingBox();
const height = image?.height;
const width = image?.width;
const height = image?.height as number;
const width = image?.width as number;
// Allow 1 pixel of difference.
expect(

View File

@ -67,7 +67,7 @@ test.describe( `${ blockData.name } Block `, () => {
postType: 'wp_template',
} );
await editor.canvas.click( 'body' );
await editor.canvas.locator( 'body' ).click();
const block = await editorUtils.getBlockByName( blockData.name );
await editor.selectBlocks( block );
@ -95,7 +95,7 @@ test.describe( `${ blockData.name } Block `, () => {
postType: 'wp_template',
} );
await editor.canvas.click( 'body' );
await editor.canvas.locator( 'body' ).click();
const block = await editorUtils.getBlockByName( blockData.name );
await editor.selectBlocks( block );
@ -138,7 +138,7 @@ for ( const {
postType: 'wp_template',
} );
await editor.canvas.click( 'body' );
await editor.canvas.locator( 'body' ).click();
const block = await editorUtils.getBlockByName( blockData.name );
// eslint-disable-next-line playwright/no-conditional-in-test
const clientId = ( await block.getAttribute( 'data-block' ) ) ?? '';
@ -152,16 +152,9 @@ for ( const {
parentClientId
);
await Promise.all( [
editor.saveSiteEditorEntities(),
page.waitForResponse( ( response ) =>
response.url().includes( 'wp-json/wp/v2/templates/' )
),
] );
await editor.saveSiteEditorEntities();
await page.goto( frontendPage, {
waitUntil: 'load',
} );
await page.goto( frontendPage );
const classicProducts = await getProductsNameFromClassicTemplate(
page

View File

@ -20,11 +20,13 @@ const blockData: BlockData = {
test.describe( `${ blockData.name } Block`, () => {
test( "can't be added in the Post Editor", async ( { admin, editor } ) => {
await admin.createNewPost( { legacyCanvas: true } );
await admin.createNewPost();
editor.insertBlock( { name: blockData.slug } ).catch( ( e ) => {
try {
await editor.insertBlock( { name: blockData.slug } );
} catch ( e ) {
expect( e.message ).toContain( 'is not registered' );
} );
}
} );
test( "can't be added in the Post Editor - Product Catalog Template", async ( {
@ -38,11 +40,11 @@ test.describe( `${ blockData.name } Block`, () => {
} );
await editorUtils.enterEditMode();
await editor.insertBlock( { name: blockData.slug } );
editor.insertBlock( { name: blockData.slug } ).catch( ( e ) => {
try {
await editor.insertBlock( { name: blockData.slug } );
} catch ( e ) {
expect( e.message ).toContain( 'is not registered' );
} );
}
} );
test( 'can be added in the Post Editor - Single Product Template', async ( {

View File

@ -18,7 +18,6 @@ test.describe( 'Test the cart template', async () => {
postType: templateType,
} );
await editorUtils.enterEditMode();
await editorUtils.closeWelcomeGuideModal();
await expect(
page
.frameLocator( 'iframe[title="Editor canvas"i]' )
@ -38,7 +37,6 @@ test.describe( 'Test the cart template', async () => {
.getByRole( 'button', { name: 'Cart', exact: true } )
.click();
await editorUtils.enterEditMode();
await editorUtils.closeWelcomeGuideModal();
await expect(
editor.canvas.locator( 'h1:has-text("Cart")' ).first()
@ -54,7 +52,7 @@ test.describe( 'Test the cart template', async () => {
} );
test( 'Admin bar edit site link opens site editor', async ( { admin } ) => {
await admin.page.goto( permalink, { waitUntil: 'load' } );
await admin.page.goto( permalink );
await admin.page.locator( '#wp-admin-bar-site-editor a' ).click();
await expect(
admin.page
@ -81,13 +79,12 @@ test.describe( 'Test editing the cart template', async () => {
postType: templateType,
} );
await editorUtils.enterEditMode();
await editorUtils.closeWelcomeGuideModal();
await editor.setContent(
'<!-- wp:woocommerce/classic-shortcode {"shortcode":"cart"} /-->'
);
await editor.canvas.waitForSelector(
'.wp-block-woocommerce-classic-shortcode'
);
await editor.canvas
.locator( '.wp-block-woocommerce-classic-shortcode' )
.waitFor();
await editor.canvas
.getByRole( 'button', { name: 'Transform into blocks' } )
.click();

View File

@ -18,7 +18,6 @@ test.describe( 'Test the checkout template', async () => {
postType: templateType,
} );
await editorUtils.enterEditMode();
await editorUtils.closeWelcomeGuideModal();
await expect(
page
.frameLocator( 'iframe[title="Editor canvas"i]' )
@ -42,7 +41,6 @@ test.describe( 'Test the checkout template', async () => {
.getByRole( 'button', { name: 'Checkout', exact: true } )
.click();
await editorUtils.enterEditMode();
await editorUtils.closeWelcomeGuideModal();
await expect(
editor.canvas.locator( 'h1:has-text("Checkout")' ).first()
@ -63,7 +61,7 @@ test.describe( 'Test the checkout template', async () => {
} ) => {
await frontendUtils.goToShop();
await frontendUtils.addToCart();
await admin.page.goto( permalink, { waitUntil: 'load' } );
await admin.page.goto( permalink );
await admin.page.locator( '#wp-admin-bar-site-editor a' ).click();
await expect(
admin.page
@ -90,13 +88,12 @@ test.describe( 'Test editing the checkout template', async () => {
postType: templateType,
} );
await editorUtils.enterEditMode();
await editorUtils.closeWelcomeGuideModal();
await editor.setContent(
'<!-- wp:woocommerce/classic-shortcode {"shortcode":"checkout"} /-->'
);
await editor.canvas.waitForSelector(
'.wp-block-woocommerce-classic-shortcode'
);
await editor.canvas
.locator( '.wp-block-woocommerce-classic-shortcode' )
.waitFor();
await editor.canvas
.getByRole( 'button', { name: 'Transform into blocks' } )
.click();

View File

@ -14,7 +14,6 @@ test.describe( 'Test the order confirmation template', async () => {
postType: 'wp_template',
} );
await editorUtils.enterEditMode();
await editorUtils.closeWelcomeGuideModal();
await editorUtils.transformIntoBlocks();
await expect(
page

View File

@ -10,6 +10,7 @@ test.describe( 'Single Product template', async () => {
test( 'loads the Single Product template for a specific product', async ( {
admin,
editor,
editorUtils,
page,
} ) => {
@ -37,15 +38,14 @@ test.describe( 'Single Product template', async () => {
await page
.getByRole( 'option', { name: testData.productName } )
.click();
await editorUtils.closeWelcomeGuideModal();
await page.getByLabel( 'Fallback content' ).click();
// Edit the template.
await editorUtils.editor.insertBlock( {
await editor.insertBlock( {
name: 'core/paragraph',
attributes: { content: userText },
} );
await editorUtils.saveTemplate();
await editor.saveSiteEditorEntities();
// Verify edits are visible.
await page.goto( testData.permalink );

View File

@ -25,6 +25,7 @@ test.describe( 'Single Product Template', async () => {
test( 'loads the theme template for a specific product using the product slug and it can be customized', async ( {
admin,
editor,
editorUtils,
page,
} ) => {
@ -33,11 +34,11 @@ test.describe( 'Single Product Template', async () => {
testData.templateName,
testData.templateType
);
await editorUtils.editor.insertBlock( {
await editor.insertBlock( {
name: 'core/paragraph',
attributes: { content: userText },
} );
await editorUtils.saveTemplate();
await editor.saveSiteEditorEntities();
await page.goto( testData.permalink );
// Verify edits are visible in the frontend.

View File

@ -5,7 +5,6 @@ import { test, expect } from '@woocommerce/e2e-playwright-utils';
import {
BLOCK_THEME_SLUG,
BLOCK_THEME_WITH_TEMPLATES_SLUG,
cli,
} from '@woocommerce/e2e-utils';
/**
@ -13,10 +12,11 @@ import {
*/
import { CUSTOMIZABLE_WC_TEMPLATES } from './constants';
CUSTOMIZABLE_WC_TEMPLATES.forEach( ( testData ) => {
if ( ! testData.canBeOverriddenByThemes ) {
return;
}
const testToRun = CUSTOMIZABLE_WC_TEMPLATES.filter(
( data ) => data.canBeOverriddenByThemes
);
for ( const testData of testToRun ) {
const userText = `Hello World in the ${ testData.templateName } template`;
const woocommerceTemplateUserText = `Hello World in the WooCommerce ${ testData.templateName } template`;
@ -26,25 +26,25 @@ CUSTOMIZABLE_WC_TEMPLATES.forEach( ( testData ) => {
} );
test( `user-modified ${ testData.templateName } template based on the theme template has priority over the user-modified template based on the default WooCommerce template`, async ( {
admin,
frontendUtils,
editorUtils,
page,
admin,
editor,
requestUtils,
editorUtils,
frontendUtils,
} ) => {
// Edit the WooCommerce default template
await editorUtils.visitTemplateEditor(
testData.templateName,
testData.templateType
);
await editorUtils.editor.insertBlock( {
await editor.insertBlock( {
name: 'core/paragraph',
attributes: { content: woocommerceTemplateUserText },
} );
await editorUtils.saveTemplate();
await editor.saveSiteEditorEntities();
await cli(
`npm run wp-env run tests-cli -- wp theme activate ${ BLOCK_THEME_WITH_TEMPLATES_SLUG }`
);
await requestUtils.activateTheme( BLOCK_THEME_WITH_TEMPLATES_SLUG );
// Edit the theme template. The theme template is not
// directly available from the UI, because the customized
@ -54,12 +54,12 @@ CUSTOMIZABLE_WC_TEMPLATES.forEach( ( testData ) => {
postType: testData.templateType,
} );
await editorUtils.enterEditMode();
await editorUtils.closeWelcomeGuideModal();
await editorUtils.waitForSiteEditorFinishLoading();
await editorUtils.editor.insertBlock( {
name: 'core/paragraph',
attributes: { content: userText },
} );
await editorUtils.saveTemplate();
await editor.saveSiteEditorEntities();
// Verify the template is the one modified by the user based on the theme.
await testData.visitPage( { frontendUtils, page } );
@ -80,6 +80,7 @@ CUSTOMIZABLE_WC_TEMPLATES.forEach( ( testData ) => {
await editorUtils.revertTemplateCustomizations(
testData.templateName
);
await testData.visitPage( { frontendUtils, page } );
await expect(
@ -87,9 +88,7 @@ CUSTOMIZABLE_WC_TEMPLATES.forEach( ( testData ) => {
).toBeVisible();
await expect( page.getByText( userText ) ).toHaveCount( 0 );
await cli(
`npm run wp-env run tests-cli -- wp theme activate ${ BLOCK_THEME_SLUG }`
);
await requestUtils.activateTheme( BLOCK_THEME_SLUG );
} );
} );
} );
}

View File

@ -22,6 +22,7 @@ CUSTOMIZABLE_WC_TEMPLATES.forEach( ( testData ) => {
test( 'can be modified and reverted', async ( {
admin,
frontendUtils,
editor,
editorUtils,
page,
} ) => {
@ -30,11 +31,11 @@ CUSTOMIZABLE_WC_TEMPLATES.forEach( ( testData ) => {
testData.templateName,
testData.templateType
);
await editorUtils.editor.insertBlock( {
await editor.insertBlock( {
name: 'core/paragraph',
attributes: { content: userText },
} );
await editorUtils.saveTemplate();
await editor.saveSiteEditorEntities();
// Verify template name didn't change.
// See: https://github.com/woocommerce/woocommerce/issues/42221
await expect(
@ -62,6 +63,7 @@ CUSTOMIZABLE_WC_TEMPLATES.forEach( ( testData ) => {
test( `defaults to the ${ testData.fallbackTemplate.templateName } template`, async ( {
admin,
frontendUtils,
editor,
editorUtils,
page,
} ) => {
@ -70,13 +72,13 @@ CUSTOMIZABLE_WC_TEMPLATES.forEach( ( testData ) => {
testData.fallbackTemplate?.templateName || '',
testData.templateType
);
await editorUtils.editor.insertBlock( {
await editor.insertBlock( {
name: 'core/paragraph',
attributes: {
content: fallbackTemplateUserText,
},
} );
await editorUtils.saveTemplate();
await editor.saveSiteEditorEntities();
await testData.visitPage( { frontendUtils, page } );
await expect(
page.getByText( fallbackTemplateUserText ).first()

View File

@ -24,6 +24,7 @@ CUSTOMIZABLE_WC_TEMPLATES.forEach( ( testData ) => {
test( "theme template has priority over WooCommerce's and can be modified", async ( {
admin,
editor,
editorUtils,
frontendUtils,
page,
@ -33,11 +34,11 @@ CUSTOMIZABLE_WC_TEMPLATES.forEach( ( testData ) => {
testData.templateName,
testData.templateType
);
await editorUtils.editor.insertBlock( {
await editor.insertBlock( {
name: 'core/paragraph',
attributes: { content: userText },
} );
await editorUtils.saveTemplate();
await editor.saveSiteEditorEntities();
// Verify template name didn't change.
// See: https://github.com/woocommerce/woocommerce/issues/42221
await expect(
@ -74,6 +75,7 @@ CUSTOMIZABLE_WC_TEMPLATES.forEach( ( testData ) => {
test( `theme template has priority over user-modified ${ testData.fallbackTemplate.templateName } template`, async ( {
admin,
frontendUtils,
editor,
editorUtils,
page,
} ) => {
@ -82,13 +84,13 @@ CUSTOMIZABLE_WC_TEMPLATES.forEach( ( testData ) => {
testData.fallbackTemplate?.templateName || '',
testData.templateType
);
await editorUtils.editor.insertBlock( {
await editor.insertBlock( {
name: 'core/paragraph',
attributes: {
content: fallbackTemplateUserText,
},
} );
await editorUtils.saveTemplate();
await editor.saveSiteEditorEntities();
await testData.visitPage( { frontendUtils, page } );
await expect(
page.getByText( fallbackTemplateUserText )

View File

@ -42,7 +42,7 @@ export class TemplateApiUtils {
{
data: {
id: slug,
content: content.raw,
content: content?.raw,
source: 'theme',
},
headers: {

View File

@ -37,8 +37,22 @@ export class EditorUtils {
return true;
}
/**
* Checks if the editor is inside an iframe.
*/
private async isEditorInsideIframe() {
try {
return ( await this.editor.canvas.locator( '*' ).count() ) > 0;
} catch ( e ) {
return false;
}
}
async getBlockByName( name: string ) {
return this.editor.canvas.locator( `[data-type="${ name }"]` );
if ( await this.isEditorInsideIframe() ) {
return this.editor.canvas.locator( `[data-type="${ name }"]` );
}
return this.page.locator( `[data-type="${ name }"]` );
}
async getBlockByTypeWithParent( name: string, parentName: string ) {
@ -160,17 +174,9 @@ export class EditorUtils {
* Toggles the global inserter.
*/
async toggleGlobalBlockInserter() {
// "Add block" selector is required to make sure performance comparison
// doesn't fail on older branches where we still had "Add block" as label.
await this.page.click(
'.edit-post-header [aria-label="Add block"],' +
'.edit-site-header [aria-label="Add block"],' +
'.edit-post-header [aria-label="Toggle block inserter"],' +
'.edit-site-header [aria-label="Toggle block inserter"],' +
'.edit-widgets-header [aria-label="Add block"],' +
'.edit-widgets-header [aria-label="Toggle block inserter"],' +
'.edit-site-header-edit-mode__inserter-toggle'
);
await this.page
.getByRole( 'button', { name: 'Toggle block inserter' } )
.click();
}
/**
@ -179,20 +185,11 @@ export class EditorUtils {
* @return {Promise<boolean>} Whether the inserter is open or not.
*/
async isGlobalInserterOpen() {
return await this.page.evaluate( () => {
// "Add block" selector is required to make sure performance comparison
// doesn't fail on older branches where we still had "Add block" as
// label.
return !! document.querySelector(
'.edit-post-header [aria-label="Add block"].is-pressed,' +
'.edit-site-header-edit-mode [aria-label="Add block"].is-pressed,' +
'.edit-post-header [aria-label="Toggle block inserter"].is-pressed,' +
'.edit-site-header [aria-label="Toggle block inserter"].is-pressed,' +
'.edit-widgets-header [aria-label="Toggle block inserter"].is-pressed,' +
'.edit-widgets-header [aria-label="Add block"].is-pressed,' +
'.edit-site-header-edit-mode__inserter-toggle.is-pressed'
);
const button = this.page.getByRole( 'button', {
name: 'Toggle block inserter',
} );
return ( await button.getAttribute( 'aria-pressed' ) ) === 'true';
}
/**
@ -211,7 +208,11 @@ export class EditorUtils {
name: 'Edit',
exact: true,
} )
.click();
.dispatchEvent( 'click' );
await this.page.locator( '.edit-site-layout__sidebar' ).waitFor( {
state: 'hidden',
} );
}
async isBlockEarlierThan< T >(
@ -295,17 +296,6 @@ export class EditorUtils {
await this.page.getByText( option ).click();
}
async saveTemplate() {
await Promise.all( [
this.editor.saveSiteEditorEntities(),
this.editor.page.waitForResponse(
( response ) =>
response.url().includes( 'wp-json/wp/v2/templates/' ) ||
response.url().includes( 'wp-json/wp/v2/template-parts/' )
),
] );
}
async closeWelcomeGuideModal() {
const isModalOpen = await this.page
.getByRole( 'dialog', { name: 'Welcome to the site editor' } )
@ -417,17 +407,12 @@ export class EditorUtils {
async revertTemplateCreation( templateName: string ) {
const templateRow = this.page.getByRole( 'row' ).filter( {
has: this.page.getByRole( 'heading', {
has: this.page.getByRole( 'link', {
name: templateName,
exact: true,
} ),
} );
templateRow.getByRole( 'button', { name: 'Actions' } ).click();
await this.page
.getByRole( 'menuitem', {
name: 'Delete',
} )
.click();
await templateRow.getByRole( 'button', { name: 'Delete' } ).click();
await this.page
.getByRole( 'button', {
name: 'Delete',
@ -441,25 +426,30 @@ export class EditorUtils {
async revertTemplateCustomizations( templateName: string ) {
const templateRow = this.page.getByRole( 'row' ).filter( {
has: this.page.getByRole( 'heading', {
has: this.page.getByRole( 'link', {
name: templateName,
exact: true,
} ),
} );
templateRow.getByRole( 'button', { name: 'Actions' } ).click();
await this.page
.getByRole( 'menuitem', {
name: 'Clear customizations',
} )
.click();
await this.page
.getByRole( 'button', { name: 'Dismiss this notice' } )
const resetButton = templateRow.getByRole( 'button', {
name: 'Reset',
} );
const waitForReset = this.page
.getByLabel( 'Dismiss this notice' )
.getByText( `"${ templateName }" reverted.` )
.waitFor();
const waitForSavedLabel = this.page
.getByRole( 'button', { name: 'Saved' } )
.waitFor();
await resetButton.click();
await waitForSavedLabel;
await waitForReset;
}
async updatePost() {
await this.page.click( 'role=button[name="Update"i]' );
await this.page.getByRole( 'button', { name: 'Update' } ).click();
await this.page
.getByRole( 'button', { name: 'Dismiss this notice' } )

View File

@ -0,0 +1,4 @@
Significance: patch
Type: dev
Comment: Fix E2E tests on WordPress 6.5

View File

@ -4211,8 +4211,8 @@ importers:
specifier: 10.12.0
version: 10.12.0(jest@29.7.0)(puppeteer-core@21.6.0)
'@wordpress/e2e-test-utils-playwright':
specifier: wp-6.4
version: 0.10.13(@playwright/test@1.40.1)(typescript@5.3.2)
specifier: wp-6.5
version: 0.19.2(@playwright/test@1.40.1)(typescript@5.3.2)
'@wordpress/e2e-tests':
specifier: ^4.9.2
version: 4.9.2(@swc/core@1.3.100)(esbuild@0.18.20)(eslint-import-resolver-typescript@3.2.4)(eslint-import-resolver-webpack@0.13.2)(jest@29.7.0)(puppeteer-core@21.6.0)(puppeteer@17.1.3)(react-dom@17.0.2)(react@17.0.2)(typescript@5.3.2)
@ -20858,6 +20858,15 @@ packages:
'@wordpress/i18n': 4.47.0
'@wordpress/url': 3.48.0
/@wordpress/api-fetch@6.51.0:
resolution: {integrity: sha512-9jPBMk/TEBR9DFQxCcHvCq7YQJzbFMyDH56vKeYNN0q+hvlJ2Ju2CWVFfsQ4mCSCGBJAblcBxZ7F2D3H4JQJ/A==}
engines: {node: '>=12'}
dependencies:
'@babel/runtime': 7.23.6
'@wordpress/i18n': 4.54.0
'@wordpress/url': 3.55.0
dev: true
/@wordpress/autop@3.16.0:
resolution: {integrity: sha512-cepLM41mF1h7f2JIU12XhLLfep1R0DNkI0gM2GoVzp0DlM0qSnJVuU93R75wTnR0OTija0cVVPUovt+gBWIR2Q==}
engines: {node: '>=12'}
@ -22595,29 +22604,6 @@ packages:
lodash: 4.17.21
dev: false
/@wordpress/e2e-test-utils-playwright@0.10.13(@playwright/test@1.40.1)(typescript@5.3.2):
resolution: {integrity: sha512-5zqIsG6Nn6N0DBlK9GyvYKxUrK7dEBHFInRnIqqfimWAQmz07iBCJU34njs9lQi+/GzKfXS+2XgBI7dDQnbfwQ==}
engines: {node: '>=12'}
peerDependencies:
'@playwright/test': '>=1'
dependencies:
'@playwright/test': 1.40.1
'@wordpress/api-fetch': 6.44.0
'@wordpress/keycodes': 3.47.0
'@wordpress/url': 3.48.0
change-case: 4.1.2
form-data: 4.0.0
get-port: 5.1.1
lighthouse: 10.4.0(typescript@5.3.2)
mime: 3.0.0
transitivePeerDependencies:
- bufferutil
- encoding
- supports-color
- typescript
- utf-8-validate
dev: true
/@wordpress/e2e-test-utils-playwright@0.10.13(@playwright/test@1.40.1)(typescript@5.3.3):
resolution: {integrity: sha512-5zqIsG6Nn6N0DBlK9GyvYKxUrK7dEBHFInRnIqqfimWAQmz07iBCJU34njs9lQi+/GzKfXS+2XgBI7dDQnbfwQ==}
engines: {node: '>=12'}
@ -22641,6 +22627,30 @@ packages:
- utf-8-validate
dev: true
/@wordpress/e2e-test-utils-playwright@0.19.2(@playwright/test@1.40.1)(typescript@5.3.2):
resolution: {integrity: sha512-pB/WsJwtbKLrKEhdr8HEmjThP6XGuFJmEHfxSm76l/S5Hc0dzhFHAYojk3iu0VEZMUlgppUNYfXTab8JTCkwBA==}
engines: {node: '>=12'}
peerDependencies:
'@playwright/test': '>=1'
dependencies:
'@playwright/test': 1.40.1
'@wordpress/api-fetch': 6.51.0
'@wordpress/keycodes': 3.54.0
'@wordpress/url': 3.55.0
change-case: 4.1.2
form-data: 4.0.0
get-port: 5.1.1
lighthouse: 10.4.0(typescript@5.3.2)
mime: 3.0.0
web-vitals: 3.5.2
transitivePeerDependencies:
- bufferutil
- encoding
- supports-color
- typescript
- utf-8-validate
dev: true
/@wordpress/e2e-test-utils@10.12.0(jest@29.7.0)(puppeteer-core@21.6.0):
resolution: {integrity: sha512-S81RDBgm91mgA9VfyqsJ5nlu7E75Jn9/g2aXe81qhp//yKXEAfDjMvHZMi+STTiisMWTbTehrKMzydZTf0ptzg==}
engines: {node: '>=14'}
@ -22705,7 +22715,7 @@ packages:
jest: '>=24'
puppeteer: '>=1.19.0'
dependencies:
'@babel/runtime': 7.23.6
'@babel/runtime': 7.23.5
'@wordpress/keycodes': 2.19.3
'@wordpress/url': 2.22.2(react-native@0.73.0)
jest: 29.7.0(@types/node@16.18.68)
@ -23390,6 +23400,13 @@ packages:
dependencies:
'@babel/runtime': 7.23.6
/@wordpress/hooks@3.54.0:
resolution: {integrity: sha512-ciLUJCH/xIxtwZI5ADts0RT6te6Lye1Qx/7saBC6qQ8CDdaO6+bvVm8Up4dWG60CZ8UQe/+9QSss2xIkOxgY3w==}
engines: {node: '>=12'}
dependencies:
'@babel/runtime': 7.23.6
dev: true
/@wordpress/hooks@3.6.1:
resolution: {integrity: sha512-4sIngmH64M1jzcprfkffo1GHsQbd/QNbTweq6cSPIJNorKfE63Inf59NQ6r0pq6+Nz+cuq64eMz5v4eyngjZ/A==}
engines: {node: '>=12'}
@ -23452,6 +23469,19 @@ packages:
sprintf-js: 1.1.3
tannin: 1.2.0
/@wordpress/i18n@4.54.0:
resolution: {integrity: sha512-gSKBopBN9rY9GhNy3CXLK3n4D5viuBTObvcu3blu4SFqkHl+Ws1Gx0tHbpypfV80ESrOyMXHJIAqWgBD8d4Hew==}
engines: {node: '>=12'}
hasBin: true
dependencies:
'@babel/runtime': 7.23.6
'@wordpress/hooks': 3.54.0
gettext-parser: 1.4.0
memize: 2.1.0
sprintf-js: 1.1.3
tannin: 1.2.0
dev: true
/@wordpress/i18n@4.6.1:
resolution: {integrity: sha512-hdi+hyEzIqZhEFSmiwApTCfsu5qRpFDSKzpPf5uJbCeCGcY/BVB2m8kh7E0M5Ltva9Hct/4AKR34bR6bm9INFA==}
engines: {node: '>=12'}
@ -23861,6 +23891,14 @@ packages:
'@wordpress/i18n': 4.47.0
change-case: 4.1.2
/@wordpress/keycodes@3.54.0:
resolution: {integrity: sha512-perPl0Hoq9Kp2hNSe5t7U68is2EljRA6sE6wQ50pqrgTJ1IMk9x8fLa/osRtC7B9AXmGlxKcbIn5i9rlsopN6Q==}
engines: {node: '>=12'}
dependencies:
'@babel/runtime': 7.23.6
'@wordpress/i18n': 4.54.0
dev: true
/@wordpress/keycodes@3.6.1:
resolution: {integrity: sha512-bqKk3zaJ2tN0hYBhrrgajKnsFMnahQT3FxR5fvqA6e1jVeRAntve3ILUUNTW3lKjmZpKXUaYs7fVrCbRNa4q3A==}
engines: {node: '>=12'}
@ -25010,6 +25048,14 @@ packages:
'@babel/runtime': 7.23.6
remove-accents: 0.5.0
/@wordpress/url@3.55.0:
resolution: {integrity: sha512-xAN/VxImq+KG8PDV7i3HtmPR6Y4LFb7lc0CvBxlHkwv2/PF+vu+1IZYMzj2kCiOvDYrue82n/5rE+Em0+l31aA==}
engines: {node: '>=12'}
dependencies:
'@babel/runtime': 7.23.6
remove-accents: 0.5.0
dev: true
/@wordpress/url@3.7.1:
resolution: {integrity: sha512-wX/Uck/If+/b8nLhB3UazLMlG7s6jjHv7isG/+/QCaJ01cf/VXXg8x6bRWnoB84ObhwBbBiM4rDTperge7+elg==}
engines: {node: '>=12'}
@ -51237,6 +51283,10 @@ packages:
resolution: {integrity: sha512-wYxSGajtmoP4WxfejAPIr4l0fVh+jeMXZb08wNc0tMg6xsfZXj3cECqIK0G7ZAqUq0PP8WlMDtaOGVBTAWztNw==}
dev: true
/web-vitals@3.5.2:
resolution: {integrity: sha512-c0rhqNcHXRkY/ogGDJQxZ9Im9D19hDihbzSQJrsioex+KnFgmMzBiy57Z1EjkhX/+OjyBpclDCzz2ITtjokFmg==}
dev: true
/webidl-conversions@3.0.1:
resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}