From 1e1e7dd65d824674f602eabc78685fa0e1413cff Mon Sep 17 00:00:00 2001 From: Bart Kalisz Date: Tue, 14 May 2024 10:23:17 +0200 Subject: [PATCH] Blocks E2E: Align ESLint and TS configs with Gutenberg (#47228) --- plugins/woocommerce-blocks/.eslintrc.js | 4 +- .../woocommerce-blocks/tests/e2e/.eslintrc.js | 51 +++--- .../tests/e2e/global-setup.ts | 4 +- .../tests/e2e/playwright.config.ts | 1 + .../no-raw-playwright-test-import.js | 0 .../add-to-cart-form.block_theme.spec.ts | 40 +++-- .../cart-block.shopper.block_theme.spec.ts | 6 +- ...checkout-block.shopper.block_theme.spec.ts | 164 +++++++++--------- .../order-confirmation.block_theme.spec.ts | 2 +- .../rating-filter.block_theme.spec.ts | 2 +- .../local-pickup.merchant.block_theme.spec.ts | 5 +- ...ni-cart-block.merchant.block_theme.spec.ts | 3 +- ...ingle-product-template.block_theme.spec.ts | 12 +- .../page-content-wrapper.block_theme.spec.ts | 4 +- .../product-collection.block_theme.spec.ts | 2 +- .../product-collection.page.ts | 6 +- ...ge-image-next-previous.block_theme.spec.ts | 2 +- ...ct-gallery-large-image.block_theme.spec.ts | 10 +- ...uct-gallery-thumbnails.block_theme.spec.ts | 54 +++--- .../product-gallery-thumbnails/utils.ts | 26 --- .../product-gallery.block_theme.spec.ts | 27 +-- .../related-products.block_theme.spec.ts | 26 +-- ...oduct-template-compatibility-layer.spec.ts | 2 +- .../stock-filter.block_theme.spec.ts | 9 +- .../tests/e2e/tsconfig.json | 9 + .../e2e/utils/editor/editor-utils.page.ts | 2 +- .../e2e/utils/frontend/frontend-utils.page.ts | 2 +- .../tests/e2e/utils/navigation/navigation.ts | 2 +- ...228-align-e2e-eslint-config-with-gutenberg | 4 + 29 files changed, 250 insertions(+), 231 deletions(-) rename plugins/woocommerce-blocks/tests/e2e/{wc-blocks-eslint-rules => rules}/no-raw-playwright-test-import.js (100%) delete mode 100644 plugins/woocommerce-blocks/tests/e2e/tests/product-gallery/inner-blocks/product-gallery-thumbnails/utils.ts create mode 100644 plugins/woocommerce/changelog/47228-align-e2e-eslint-config-with-gutenberg diff --git a/plugins/woocommerce-blocks/.eslintrc.js b/plugins/woocommerce-blocks/.eslintrc.js index e308412e717..d3090e395a0 100644 --- a/plugins/woocommerce-blocks/.eslintrc.js +++ b/plugins/woocommerce-blocks/.eslintrc.js @@ -167,8 +167,10 @@ module.exports = { '@wordpress/keycodes', '@wordpress/url', '@woocommerce/blocks-test-utils', - '@woocommerce/e2e-utils', '@woocommerce/e2e-mocks', + '@woocommerce/e2e-types', + '@woocommerce/e2e-utils', + '@woocommerce/e2e-playwright-utils', 'babel-jest', 'dotenv', 'jest-environment-puppeteer', diff --git a/plugins/woocommerce-blocks/tests/e2e/.eslintrc.js b/plugins/woocommerce-blocks/tests/e2e/.eslintrc.js index 118f61e8707..8f4d4f21187 100644 --- a/plugins/woocommerce-blocks/tests/e2e/.eslintrc.js +++ b/plugins/woocommerce-blocks/tests/e2e/.eslintrc.js @@ -1,29 +1,40 @@ const rulesDirPlugin = require( 'eslint-plugin-rulesdir' ); -rulesDirPlugin.RULES_DIR = `${ __dirname }/wc-blocks-eslint-rules`; +rulesDirPlugin.RULES_DIR = `${ __dirname }/rules`; const config = { - extends: [ '../../.eslintrc.js', 'plugin:playwright/recommended' ], + extends: [ + 'plugin:playwright/recommended', + 'plugin:@typescript-eslint/base', + ], plugins: [ 'rulesdir' ], + parserOptions: { + tsconfigRootDir: __dirname, + project: './tsconfig.json', + }, rules: { - 'playwright/expect-expect': 'error', - 'playwright/max-nested-describe': 'error', - 'playwright/missing-playwright-await': 'error', - 'playwright/no-conditional-in-test': 'error', - 'playwright/no-element-handle': 'error', - 'playwright/no-eval': 'error', - 'playwright/no-focused-test': 'error', - 'playwright/no-force-option': 'error', - 'playwright/no-nested-step': 'error', - 'playwright/no-networkidle': 'error', - 'playwright/no-page-pause': 'error', - 'playwright/no-skipped-test': 'error', - 'playwright/no-useless-await': 'error', - 'playwright/no-useless-not': 'error', - 'playwright/no-wait-for-timeout': 'error', - 'playwright/prefer-web-first-assertions': 'error', - 'playwright/valid-expect': 'error', + '@wordpress/no-global-active-element': 'off', + '@wordpress/no-global-get-selection': 'off', + 'no-restricted-syntax': [ + 'error', + { + selector: 'CallExpression[callee.property.name="$"]', + message: '`$` is discouraged, please use `locator` instead', + }, + { + selector: 'CallExpression[callee.property.name="$$"]', + message: '`$$` is discouraged, please use `locator` instead', + }, + { + selector: + 'CallExpression[callee.object.name="page"][callee.property.name="waitForTimeout"]', + message: 'Prefer page.locator instead.', + }, + ], + 'playwright/no-conditional-in-test': 'off', + '@typescript-eslint/await-thenable': 'error', + '@typescript-eslint/no-floating-promises': 'error', + '@typescript-eslint/no-misused-promises': 'error', 'rulesdir/no-raw-playwright-test-import': 'error', - 'playwright/no-hooks': [ 'error', { allow: [ 'beforeEach' ] } ], }, }; diff --git a/plugins/woocommerce-blocks/tests/e2e/global-setup.ts b/plugins/woocommerce-blocks/tests/e2e/global-setup.ts index 72958cf5b95..67583de5d22 100644 --- a/plugins/woocommerce-blocks/tests/e2e/global-setup.ts +++ b/plugins/woocommerce-blocks/tests/e2e/global-setup.ts @@ -30,8 +30,8 @@ const prepareAttributes = async () => { // Intercept the dialog event. This is needed because when the regenerate // button is clicked, a dialog is shown. - page.on( 'dialog', async ( dialog ) => { - await dialog.accept(); + page.on( 'dialog', ( dialog ) => { + void dialog.accept(); } ); await page.goto( '/wp-admin/admin.php?page=wc-status&tab=tools' ); diff --git a/plugins/woocommerce-blocks/tests/e2e/playwright.config.ts b/plugins/woocommerce-blocks/tests/e2e/playwright.config.ts index 66275559cfb..936c15b06da 100644 --- a/plugins/woocommerce-blocks/tests/e2e/playwright.config.ts +++ b/plugins/woocommerce-blocks/tests/e2e/playwright.config.ts @@ -19,6 +19,7 @@ const config: PlaywrightTestConfig = { // We're running our tests in serial, so we only need one worker. workers: 1, fullyParallel: false, + forbidOnly: !! CI, // Don't report slow test "files", as we're running our tests in serial. reportSlowTests: null, reporter: process.env.CI ? [ [ 'github' ], [ 'list' ] ] : 'list', diff --git a/plugins/woocommerce-blocks/tests/e2e/wc-blocks-eslint-rules/no-raw-playwright-test-import.js b/plugins/woocommerce-blocks/tests/e2e/rules/no-raw-playwright-test-import.js similarity index 100% rename from plugins/woocommerce-blocks/tests/e2e/wc-blocks-eslint-rules/no-raw-playwright-test-import.js rename to plugins/woocommerce-blocks/tests/e2e/rules/no-raw-playwright-test-import.js diff --git a/plugins/woocommerce-blocks/tests/e2e/tests/add-to-cart-form/add-to-cart-form.block_theme.spec.ts b/plugins/woocommerce-blocks/tests/e2e/tests/add-to-cart-form/add-to-cart-form.block_theme.spec.ts index 1e9be0b59c8..e7111e42cd1 100644 --- a/plugins/woocommerce-blocks/tests/e2e/tests/add-to-cart-form/add-to-cart-form.block_theme.spec.ts +++ b/plugins/woocommerce-blocks/tests/e2e/tests/add-to-cart-form/add-to-cart-form.block_theme.spec.ts @@ -36,7 +36,7 @@ test.describe( `${ blockData.name } Block`, () => { editorUtils, } ) => { // Add to Cart with Options in the Post Editor is only available as inner block of the Single Product Block. - await admin.createNewPost( { legacyCanvas: true } ); + await admin.createNewPost(); await editor.insertBlock( { name: 'woocommerce/single-product' } ); await configureSingleProductBlock( editorUtils ); @@ -57,13 +57,24 @@ test.describe( `${ blockData.name } Block`, () => { admin, editor, editorUtils, + requestUtils, } ) => { - // Add to Cart with Options in the Site Editor is only available as inner block of the Single Product Block except for the Single Product Template - await admin.visitSiteEditor( { - postId: `woocommerce/woocommerce//archive-product`, - postType: 'wp_template', + // Add to Cart with Options in the Site Editor is only available as + // inner block of the Single Product Block except for the Single Product + // Template + const template = await requestUtils.createTemplate( 'wp_template', { + slug: 'product-catalog', + title: 'Custom Product Catalog', + content: 'placeholder', } ); - await editorUtils.enterEditMode(); + + await admin.visitSiteEditor( { + postId: template.id, + postType: 'wp_template', + canvas: 'edit', + } ); + + await expect( editor.canvas.getByText( 'placeholder' ) ).toBeVisible(); await editor.insertBlock( { name: 'woocommerce/single-product' } ); @@ -85,14 +96,21 @@ test.describe( `${ blockData.name } Block`, () => { admin, editor, editorUtils, + requestUtils, } ) => { - await admin.visitSiteEditor( { - postId: `woocommerce/woocommerce//single-product`, - postType: 'wp_template', + const template = await requestUtils.createTemplate( 'wp_template', { + slug: 'single-product', + title: 'Custom Single Product', + content: 'placeholder', } ); - await editorUtils.enterEditMode(); - await editor.setContent( '' ); + await admin.visitSiteEditor( { + postId: template.id, + postType: 'wp_template', + canvas: 'edit', + } ); + + await expect( editor.canvas.getByText( 'placeholder' ) ).toBeVisible(); await editor.insertBlock( { name: blockData.slug } ); diff --git a/plugins/woocommerce-blocks/tests/e2e/tests/cart/cart-block.shopper.block_theme.spec.ts b/plugins/woocommerce-blocks/tests/e2e/tests/cart/cart-block.shopper.block_theme.spec.ts index 5b6e9edd273..adc238f107e 100644 --- a/plugins/woocommerce-blocks/tests/e2e/tests/cart/cart-block.shopper.block_theme.spec.ts +++ b/plugins/woocommerce-blocks/tests/e2e/tests/cart/cart-block.shopper.block_theme.spec.ts @@ -251,9 +251,9 @@ test.describe( 'Shopper → Cart block', () => { await frontendUtils.goToShop(); await frontendUtils.addToCart( SIMPLE_PHYSICAL_PRODUCT_NAME ); await frontendUtils.goToCart(); - await page.waitForSelector( - '.wp-block-woocommerce-cart-cross-sells-block' - ); + await page + .locator( '.wp-block-woocommerce-cart-cross-sells-block' ) + .waitFor(); // Cap is the cross sells product that will be added to the cart await page .getByRole( 'button', { name: 'Add to cart: “Cap”' } ) diff --git a/plugins/woocommerce-blocks/tests/e2e/tests/checkout/checkout-block.shopper.block_theme.spec.ts b/plugins/woocommerce-blocks/tests/e2e/tests/checkout/checkout-block.shopper.block_theme.spec.ts index 92f962217a8..b10253362d4 100644 --- a/plugins/woocommerce-blocks/tests/e2e/tests/checkout/checkout-block.shopper.block_theme.spec.ts +++ b/plugins/woocommerce-blocks/tests/e2e/tests/checkout/checkout-block.shopper.block_theme.spec.ts @@ -249,12 +249,14 @@ test.describe( 'Shopper → Shipping and Billing Addresses', () => { postType: 'wp_template', } ); await editorUtils.enterEditMode(); - await editor.openDocumentSettingsSidebar(); + await editor.selectBlocks( blockSelectorInEditor + ' [data-type="woocommerce/checkout-shipping-address-block"]' ); + await editor.openDocumentSettingsSidebar(); + const checkbox = page.getByRole( 'checkbox', { name: 'Company', exact: true, @@ -299,7 +301,7 @@ test.describe( 'Shopper → Shipping (customer user)', () => { await frontendUtils.goToShop(); await frontendUtils.addToCart( 'Beanie' ); await frontendUtils.goToCheckout(); - await expect( + expect( await checkoutPageObject.selectAndVerifyShippingOption( FREE_SHIPPING_NAME, FREE_SHIPPING_PRICE @@ -314,7 +316,7 @@ test.describe( 'Shopper → Shipping (customer user)', () => { await frontendUtils.goToShop(); await frontendUtils.addToCart( 'Beanie' ); await frontendUtils.goToCheckout(); - await expect( + expect( await checkoutPageObject.selectAndVerifyShippingOption( FLAT_RATE_SHIPPING_NAME, FLAT_RATE_SHIPPING_PRICE @@ -333,7 +335,7 @@ test.describe( 'Shopper → Shipping (customer user)', () => { name: 'Billing address', } ); - await expect( shippingForm.getByLabel( 'Phone' ).inputValue ).toEqual( + expect( shippingForm.getByLabel( 'Phone' ).inputValue ).toEqual( billingForm.getByLabel( 'Phone' ).inputValue ); @@ -371,7 +373,7 @@ test.describe( 'Shopper → Place Guest Order', () => { await frontendUtils.goToShop(); await frontendUtils.addToCart( SIMPLE_PHYSICAL_PRODUCT_NAME ); await frontendUtils.goToCheckout(); - await expect( + expect( await checkoutPageObject.selectAndVerifyShippingOption( FREE_SHIPPING_NAME, FREE_SHIPPING_PRICE @@ -527,29 +529,6 @@ test.describe( 'Billing Address Form', () => { await editorUtils.saveSiteEditorEntities(); } ); - const shippingTestData = { - firstname: 'John', - lastname: 'Doe', - addressfirstline: '123 Easy Street', - addresssecondline: 'Testville', - country: 'United States (US)', - city: 'New York', - state: 'New York', - postcode: '90210', - phone: '01234567890', - }; - const billingTestData = { - first_name: '', - last_name: '', - address_1: '', - address_2: '', - country: 'United States (US)', - city: '', - state: 'New York', - postcode: '', - phone: '', - }; - test.describe( 'Guest user', () => { test.use( { storageState: guestFile } ); @@ -562,66 +541,81 @@ test.describe( 'Billing Address Form', () => { await frontendUtils.addToCart( SIMPLE_PHYSICAL_PRODUCT_NAME ); await frontendUtils.goToCheckout(); - await checkoutPageObject.fillShippingDetails( shippingTestData ); + await checkoutPageObject.fillShippingDetails( { + firstname: 'John', + lastname: 'Doe', + addressfirstline: '123 Easy Street', + addresssecondline: 'Testville', + country: 'United States (US)', + city: 'New York', + state: 'New York', + postcode: '90210', + phone: '01234567890', + } ); + + const shippingForm = page.getByRole( 'group', { + name: 'Shipping address', + } ); + await page.getByLabel( 'Use same address for billing' ).uncheck(); - // Check shipping fields are filled. - for ( const [ key, value ] of Object.entries( shippingTestData ) ) { - // eslint-disable-next-line playwright/no-conditional-in-test - switch ( key ) { - case 'firstname': - await expect( - page.locator( '#shipping-first_name' ) - ).toHaveValue( value ); - break; - case 'lastname': - await expect( - page.locator( '#shipping-last_name' ) - ).toHaveValue( value ); - break; - case 'country': - await expect( - page.locator( '#shipping-country input' ) - ).toHaveValue( value ); - break; - case 'addressfirstline': - await expect( - page.locator( '#shipping-address_1' ) - ).toHaveValue( value ); - break; - case 'addresssecondline': - await expect( - page.locator( '#shipping-address_2' ) - ).toHaveValue( value ); - break; - case 'state': - await expect( - page.locator( '#shipping-state input' ) - ).toHaveValue( value ); - break; - default: - await expect( - page.locator( `#shipping-${ key }` ) - ).toHaveValue( value ); - } - } + await expect( shippingForm.getByLabel( 'First name' ) ).toHaveValue( + 'John' + ); + await expect( shippingForm.getByLabel( 'Last name' ) ).toHaveValue( + 'Doe' + ); + await expect( + shippingForm.getByLabel( 'Address', { exact: true } ) + ).toHaveValue( '123 Easy Street' ); + await expect( + shippingForm.getByLabel( 'Apartment, suite, etc. (' ) + ).toHaveValue( 'Testville' ); + await expect( + shippingForm.getByLabel( 'United States (US), Country/' ) + ).toHaveValue( 'United States (US)' ); + await expect( shippingForm.getByLabel( 'City' ) ).toHaveValue( + 'New York' + ); + await expect( + shippingForm.getByLabel( 'New York, State' ) + ).toHaveValue( 'New York' ); + await expect( shippingForm.getByLabel( 'ZIP Code' ) ).toHaveValue( + '90210' + ); + await expect( + shippingForm.getByLabel( 'Phone (optional)' ) + ).toHaveValue( '01234567890' ); - // Check billing fields are empty. - for ( const [ key, value ] of Object.entries( billingTestData ) ) { - // eslint-disable-next-line playwright/no-conditional-in-test - switch ( key ) { - case 'country': - await expect( - page.locator( '#billing-country input' ) - ).toHaveValue( value ); - break; - case 'state': - await expect( - page.locator( '#billing-state input' ) - ).toHaveValue( value ); - break; - } - } + const billingForm = page.getByRole( 'group', { + name: 'Billing address', + } ); + + await expect( billingForm.getByLabel( 'First name' ) ).toHaveValue( + '' + ); + await expect( billingForm.getByLabel( 'Last name' ) ).toHaveValue( + '' + ); + await expect( + billingForm.getByLabel( 'Address', { exact: true } ) + ).toHaveValue( '' ); + await expect( + billingForm.getByLabel( 'Apartment, suite, etc. (' ) + ).toHaveValue( '' ); + await expect( + billingForm.getByLabel( 'United States (US), Country/' ) + ).toHaveValue( 'United States (US)' ); + await expect( billingForm.getByLabel( 'City' ) ).toHaveValue( '' ); + await expect( + billingForm.getByLabel( 'New York, State' ) + ).toHaveValue( 'New York' ); + await expect( billingForm.getByLabel( 'ZIP Code' ) ).toHaveValue( + '' + ); + await expect( + billingForm.getByLabel( 'Phone (optional)' ) + ).toHaveValue( '' ); } ); } ); } ); diff --git a/plugins/woocommerce-blocks/tests/e2e/tests/checkout/order-confirmation.block_theme.spec.ts b/plugins/woocommerce-blocks/tests/e2e/tests/checkout/order-confirmation.block_theme.spec.ts index 439eb0c958f..aed32c285ba 100644 --- a/plugins/woocommerce-blocks/tests/e2e/tests/checkout/order-confirmation.block_theme.spec.ts +++ b/plugins/woocommerce-blocks/tests/e2e/tests/checkout/order-confirmation.block_theme.spec.ts @@ -243,7 +243,7 @@ test.describe( 'Shopper → Order Confirmation → Downloadable Products', () => // Update last order status to completed. await admin.visitAdminPage( 'edit.php', 'post_type=shop_order' ); - await admin.page.waitForSelector( '.wp-list-table' ); + await admin.page.locator( '.wp-list-table' ).waitFor(); await admin.page.click( '.wp-list-table tbody tr:first-child a.order-view' ); diff --git a/plugins/woocommerce-blocks/tests/e2e/tests/filter-blocks/rating-filter.block_theme.spec.ts b/plugins/woocommerce-blocks/tests/e2e/tests/filter-blocks/rating-filter.block_theme.spec.ts index 2add3e71884..4da314b73e9 100644 --- a/plugins/woocommerce-blocks/tests/e2e/tests/filter-blocks/rating-filter.block_theme.spec.ts +++ b/plugins/woocommerce-blocks/tests/e2e/tests/filter-blocks/rating-filter.block_theme.spec.ts @@ -111,7 +111,7 @@ test.describe( 'Product Filter: Rating Filter Block', () => { /Checkbox: Rated \d out of 5/ ); - ratingCheckboxes.nth( 0 ).check(); + await ratingCheckboxes.nth( 0 ).check(); // wait for navigation await page.waitForURL( diff --git a/plugins/woocommerce-blocks/tests/e2e/tests/local-pickup/local-pickup.merchant.block_theme.spec.ts b/plugins/woocommerce-blocks/tests/e2e/tests/local-pickup/local-pickup.merchant.block_theme.spec.ts index 26602c9bc52..285dbd131ba 100644 --- a/plugins/woocommerce-blocks/tests/e2e/tests/local-pickup/local-pickup.merchant.block_theme.spec.ts +++ b/plugins/woocommerce-blocks/tests/e2e/tests/local-pickup/local-pickup.merchant.block_theme.spec.ts @@ -198,9 +198,8 @@ test.describe( 'Merchant → Local Pickup Settings', () => { postType: 'wp_template', } ); await editorUtils.enterEditMode(); - - const block = await editorUtils.getBlockByName( - 'woocommerce/checkout-shipping-method-block' + const block = editor.canvas.locator( + '[data-type="woocommerce/checkout-shipping-method-block"]' ); await editor.selectBlocks( block ); diff --git a/plugins/woocommerce-blocks/tests/e2e/tests/mini-cart/mini-cart-block.merchant.block_theme.spec.ts b/plugins/woocommerce-blocks/tests/e2e/tests/mini-cart/mini-cart-block.merchant.block_theme.spec.ts index b17d0665e3d..c1e56dd99dc 100644 --- a/plugins/woocommerce-blocks/tests/e2e/tests/mini-cart/mini-cart-block.merchant.block_theme.spec.ts +++ b/plugins/woocommerce-blocks/tests/e2e/tests/mini-cart/mini-cart-block.merchant.block_theme.spec.ts @@ -34,9 +34,8 @@ test.describe( 'Merchant → Mini Cart', () => { await editor.insertBlock( { name: blockData.slug } ); await expect( - await editorUtils.getBlockByName( blockData.slug ) + editor.canvas.getByLabel( 'Block: Mini-Cart' ) ).toBeVisible(); - await editor.saveSiteEditorEntities(); } ); test( 'can only be inserted once', async ( { editorUtils, admin } ) => { diff --git a/plugins/woocommerce-blocks/tests/e2e/tests/on-sale-badge/on-sale-badge-single-product-template.block_theme.spec.ts b/plugins/woocommerce-blocks/tests/e2e/tests/on-sale-badge/on-sale-badge-single-product-template.block_theme.spec.ts index 423143ce6de..5a494ac3b42 100644 --- a/plugins/woocommerce-blocks/tests/e2e/tests/on-sale-badge/on-sale-badge-single-product-template.block_theme.spec.ts +++ b/plugins/woocommerce-blocks/tests/e2e/tests/on-sale-badge/on-sale-badge-single-product-template.block_theme.spec.ts @@ -164,7 +164,7 @@ test.describe( `${ blockData.name }`, () => { isFrontend: false, } ); - await expect( + expect( editorBoundingClientRect.productSaleBadge.x - blockData.margin ).toEqual( editorBoundingClientRect.productSaleBadgeContainer.x ); @@ -178,7 +178,7 @@ test.describe( `${ blockData.name }`, () => { isFrontend: true, } ); - await expect( + expect( clientBoundingClientRect.productSaleBadge.x - blockData.margin ).toEqual( clientBoundingClientRect.productSaleBadgeContainer.x ); } ); @@ -209,7 +209,7 @@ test.describe( `${ blockData.name }`, () => { isFrontend: false, } ); - await expect( + expect( editorBoundingClientRect.productSaleBadge.right ).toBeLessThan( editorBoundingClientRect.productSaleBadgeContainer.right @@ -225,7 +225,7 @@ test.describe( `${ blockData.name }`, () => { isFrontend: true, } ); - await expect( + expect( clientBoundingClientRect.productSaleBadge.right ).toBeLessThan( clientBoundingClientRect.productSaleBadgeContainer.right @@ -251,7 +251,7 @@ test.describe( `${ blockData.name }`, () => { isFrontend: false, } ); - await expect( + expect( editorBoundingClientRect.productSaleBadge.right + blockData.margin ).toEqual( @@ -268,7 +268,7 @@ test.describe( `${ blockData.name }`, () => { isFrontend: true, } ); - await expect( + expect( clientBoundingClientRect.productSaleBadge.right + blockData.margin ).toEqual( diff --git a/plugins/woocommerce-blocks/tests/e2e/tests/page-content-wrapper/page-content-wrapper.block_theme.spec.ts b/plugins/woocommerce-blocks/tests/e2e/tests/page-content-wrapper/page-content-wrapper.block_theme.spec.ts index 45c1dd439ad..9c8923231ab 100644 --- a/plugins/woocommerce-blocks/tests/e2e/tests/page-content-wrapper/page-content-wrapper.block_theme.spec.ts +++ b/plugins/woocommerce-blocks/tests/e2e/tests/page-content-wrapper/page-content-wrapper.block_theme.spec.ts @@ -36,7 +36,7 @@ const templates = [ ]; const userText = 'Hello World in the page'; -templates.forEach( async ( template ) => { +for ( const template of templates ) { test.describe( 'Page Content Wrapper', () => { test( `the content of the ${ template.title } page is correctly rendered in the ${ template.title } template`, async ( { page, @@ -70,4 +70,4 @@ templates.forEach( async ( template ) => { await expect( page.getByText( userText ).first() ).toBeVisible(); } ); } ); -} ); +} diff --git a/plugins/woocommerce-blocks/tests/e2e/tests/product-collection/product-collection.block_theme.spec.ts b/plugins/woocommerce-blocks/tests/e2e/tests/product-collection/product-collection.block_theme.spec.ts index 945e4b8e9c1..d641b44a849 100644 --- a/plugins/woocommerce-blocks/tests/e2e/tests/product-collection/product-collection.block_theme.spec.ts +++ b/plugins/woocommerce-blocks/tests/e2e/tests/product-collection/product-collection.block_theme.spec.ts @@ -492,7 +492,7 @@ test.describe( 'Product Collection', () => { ).toBeVisible(); // "On sale control" should retain its state when inherit query from template is enabled again - pageObject.setShowOnlyProductsOnSale( { + await pageObject.setShowOnlyProductsOnSale( { onSale: true, isLocatorsRefreshNeeded: false, } ); diff --git a/plugins/woocommerce-blocks/tests/e2e/tests/product-collection/product-collection.page.ts b/plugins/woocommerce-blocks/tests/e2e/tests/product-collection/product-collection.page.ts index 2b7a9859f95..01961765711 100644 --- a/plugins/woocommerce-blocks/tests/e2e/tests/product-collection/product-collection.page.ts +++ b/plugins/woocommerce-blocks/tests/e2e/tests/product-collection/product-collection.page.ts @@ -130,7 +130,7 @@ class ProductCollectionPage { } async createNewPostAndInsertBlock( collection?: Collections ) { - await this.admin.createNewPost( { legacyCanvas: true } ); + await this.admin.createNewPost(); await this.insertProductCollection(); await this.chooseCollectionInPost( collection ); await this.refreshLocators( 'editor' ); @@ -289,7 +289,7 @@ class ProductCollectionPage { name: 'Order by', } ); await orderByComboBox.selectOption( orderBy ); - await this.page.waitForSelector( SELECTORS.product ); + await this.page.locator( SELECTORS.product ).first().waitFor(); await this.refreshLocators( 'editor' ); } @@ -554,7 +554,7 @@ class ProductCollectionPage { } async insertProductCollectionInSingleProductBlock() { - this.insertSingleProductBlock(); + await this.insertSingleProductBlock(); const siblingBlock = await this.editorUtils.getBlockByName( 'woocommerce/product-price' diff --git a/plugins/woocommerce-blocks/tests/e2e/tests/product-gallery/inner-blocks/product-gallery-large-image-next-previous/product-gallery-large-image-next-previous.block_theme.spec.ts b/plugins/woocommerce-blocks/tests/e2e/tests/product-gallery/inner-blocks/product-gallery-large-image-next-previous/product-gallery-large-image-next-previous.block_theme.spec.ts index d84cf6002ca..4e7f45b9880 100644 --- a/plugins/woocommerce-blocks/tests/e2e/tests/product-gallery/inner-blocks/product-gallery-large-image-next-previous/product-gallery-large-image-next-previous.block_theme.spec.ts +++ b/plugins/woocommerce-blocks/tests/e2e/tests/product-gallery/inner-blocks/product-gallery-large-image-next-previous/product-gallery-large-image-next-previous.block_theme.spec.ts @@ -402,7 +402,7 @@ test.describe( `${ blockData.name }`, () => { parentClientId ); await ( - await await pageObject.getNextPreviousButtonsBlock( { + await pageObject.getNextPreviousButtonsBlock( { page: 'editor', } ) ).click(); diff --git a/plugins/woocommerce-blocks/tests/e2e/tests/product-gallery/inner-blocks/product-gallery-large-image/product-gallery-large-image.block_theme.spec.ts b/plugins/woocommerce-blocks/tests/e2e/tests/product-gallery/inner-blocks/product-gallery-large-image/product-gallery-large-image.block_theme.spec.ts index 78917b2a894..711de8dbe04 100644 --- a/plugins/woocommerce-blocks/tests/e2e/tests/product-gallery/inner-blocks/product-gallery-large-image/product-gallery-large-image.block_theme.spec.ts +++ b/plugins/woocommerce-blocks/tests/e2e/tests/product-gallery/inner-blocks/product-gallery-large-image/product-gallery-large-image.block_theme.spec.ts @@ -68,7 +68,7 @@ test.describe( `${ blockData.name }`, () => { test( 'should be enabled by default', async ( { pageObject } ) => { await pageObject.addProductGalleryBlock( { cleanContent: true } ); const zoomWhileHoveringSetting = - await pageObject.getZoomWhileHoveringSetting(); + pageObject.getZoomWhileHoveringSetting(); await expect( zoomWhileHoveringSetting ).toBeChecked(); } ); @@ -91,7 +91,7 @@ test.describe( `${ blockData.name }`, () => { const imgElement = blockFrontend.locator( 'img' ).first(); const style = await imgElement.evaluate( ( el ) => el.style ); - await expect( style.transform ).toBe( 'scale(1)' ); + expect( style.transform ).toBe( 'scale(1)' ); await imgElement.hover(); @@ -99,7 +99,7 @@ test.describe( `${ blockData.name }`, () => { ( el ) => el.style ); - await expect( styleOnHover.transform ).toBe( 'scale(1.3)' ); + expect( styleOnHover.transform ).toBe( 'scale(1.3)' ); } ); test( 'should not work on frontend when is disabled', async ( { @@ -124,7 +124,7 @@ test.describe( `${ blockData.name }`, () => { const imgElement = blockFrontend.locator( 'img' ).first(); const style = await imgElement.evaluate( ( el ) => el.style ); - await expect( style.transform ).toBe( '' ); + expect( style.transform ).toBe( '' ); await imgElement.hover(); @@ -132,7 +132,7 @@ test.describe( `${ blockData.name }`, () => { ( el ) => el.style ); - await expect( styleOnHover.transform ).toBe( '' ); + expect( styleOnHover.transform ).toBe( '' ); } ); } ); diff --git a/plugins/woocommerce-blocks/tests/e2e/tests/product-gallery/inner-blocks/product-gallery-thumbnails/product-gallery-thumbnails.block_theme.spec.ts b/plugins/woocommerce-blocks/tests/e2e/tests/product-gallery/inner-blocks/product-gallery-thumbnails/product-gallery-thumbnails.block_theme.spec.ts index 399964fca5a..b2afbbd07d8 100644 --- a/plugins/woocommerce-blocks/tests/e2e/tests/product-gallery/inner-blocks/product-gallery-thumbnails/product-gallery-thumbnails.block_theme.spec.ts +++ b/plugins/woocommerce-blocks/tests/e2e/tests/product-gallery/inner-blocks/product-gallery-thumbnails/product-gallery-thumbnails.block_theme.spec.ts @@ -7,7 +7,6 @@ import { Locator, Page } from '@playwright/test'; /** * Internal dependencies */ -import { addBlock } from './utils'; import { ProductGalleryPage } from '../../product-gallery.page'; const blockData = { @@ -48,12 +47,17 @@ const test = base.extend< { pageObject: ProductGalleryPage } >( { }, } ); test.describe( `${ blockData.name }`, () => { - test.beforeEach( async ( { admin, editorUtils } ) => { + test.beforeEach( async ( { admin, editor } ) => { await admin.visitSiteEditor( { postId: `woocommerce/woocommerce//${ blockData.slug }`, postType: 'wp_template', + canvas: 'edit', } ); - await editorUtils.enterEditMode(); + + await editor.canvas + .locator( '[data-testid="product-image"]' ) + .first() + .waitFor(); } ); test( 'Renders Product Gallery Thumbnails block on the editor and frontend side', async ( { @@ -126,30 +130,26 @@ test.describe( `${ blockData.name }`, () => { } ); test.describe( `${ blockData.name } Settings`, () => { - test( 'Hide correctly the thumbnails', async ( { - page, - editor, - editorUtils, - admin, - } ) => { - await addBlock( admin, editor, editorUtils ); - await ( - await editorUtils.getBlockByName( blockData.name ) - ).click(); + test( 'Hide correctly the thumbnails', async ( { page, editor } ) => { + await editor.insertBlock( { + name: 'woocommerce/product-gallery', + } ); + + await editor.canvas + .locator( `[data-type="${ blockData.name }"]` ) + .click(); + await editor.openDocumentSettingsSidebar(); + await page .locator( blockData.selectors.editor.noThumbnailsOption ) .click(); - const element = page.locator( - blockData.selectors.editor.thumbnails - ); - - await expect( element ).toBeHidden(); + await expect( + page.locator( blockData.selectors.editor.thumbnails ) + ).toBeHidden(); await editor.saveSiteEditorEntities(); - - await page.goto( blockData.productPage ); } ); // We can test the left position of thumbnails by cross-checking: @@ -413,17 +413,17 @@ test.describe( `${ blockData.name }`, () => { test( 'Ensure entered Number of Thumbnails rounds to integer', async ( { page, editor, - pageObject, } ) => { await editor.insertBlock( { name: 'woocommerce/product-gallery', } ); - const thumbnailsBlock = await pageObject.getThumbnailsBlock( { - page: 'editor', - } ); + await editor.selectBlocks( + '[data-type="woocommerce/product-gallery"]' + ); await editor.openDocumentSettingsSidebar(); + const numberOfThumbnailInput = page.getByRole( 'spinbutton', { name: 'Number of Thumbnails', } ); @@ -434,7 +434,7 @@ test.describe( `${ blockData.name }`, () => { '4.2' ); - let numberOfThumbnailsOnScreen = thumbnailsBlock.locator( + const numberOfThumbnailsOnScreen = editor.canvas.locator( '.wc-block-product-gallery-thumbnails__thumbnail' ); @@ -446,10 +446,6 @@ test.describe( `${ blockData.name }`, () => { '4.7' ); - numberOfThumbnailsOnScreen = thumbnailsBlock.locator( - '.wc-block-product-gallery-thumbnails__thumbnail' - ); - await expect( numberOfThumbnailsOnScreen ).toHaveCount( 5 ); } ); } ); diff --git a/plugins/woocommerce-blocks/tests/e2e/tests/product-gallery/inner-blocks/product-gallery-thumbnails/utils.ts b/plugins/woocommerce-blocks/tests/e2e/tests/product-gallery/inner-blocks/product-gallery-thumbnails/utils.ts deleted file mode 100644 index b36ae591a46..00000000000 --- a/plugins/woocommerce-blocks/tests/e2e/tests/product-gallery/inner-blocks/product-gallery-thumbnails/utils.ts +++ /dev/null @@ -1,26 +0,0 @@ -/** - * External dependencies - */ -import { EditorUtils } from '@woocommerce/e2e-utils'; -import { Admin, Editor } from '@wordpress/e2e-test-utils-playwright'; - -// Define a utility function to add the "woocommerce/product-gallery" block to the editor -export const addBlock = async ( - admin: Admin, - editor: Editor, - editorUtils: EditorUtils -) => { - // Visit the site editor for the specific product page - await admin.visitSiteEditor( { - postId: `woocommerce/woocommerce//single-product`, - postType: 'wp_template', - } ); - - // Enter the edit mode - await editorUtils.enterEditMode(); - - // Insert the "woocommerce/product-gallery" block - await editor.insertBlock( { - name: 'woocommerce/product-gallery', - } ); -}; diff --git a/plugins/woocommerce-blocks/tests/e2e/tests/product-gallery/product-gallery.block_theme.spec.ts b/plugins/woocommerce-blocks/tests/e2e/tests/product-gallery/product-gallery.block_theme.spec.ts index 2ff960b88d2..92f1c3cafdf 100644 --- a/plugins/woocommerce-blocks/tests/e2e/tests/product-gallery/product-gallery.block_theme.spec.ts +++ b/plugins/woocommerce-blocks/tests/e2e/tests/product-gallery/product-gallery.block_theme.spec.ts @@ -83,12 +83,20 @@ const getThumbnailImageIdByNth = async ( }; test.describe( `${ blockData.name }`, () => { - test.beforeEach( async ( { admin, editorUtils } ) => { - await admin.visitSiteEditor( { - postId: `woocommerce/woocommerce//${ blockData.slug }`, - postType: 'wp_template', + test.beforeEach( async ( { admin, editor, requestUtils } ) => { + const template = await requestUtils.createTemplate( 'wp_template', { + slug: blockData.slug, + title: 'Custom Single Product', + content: 'placeholder', } ); - await editorUtils.enterEditMode(); + + await admin.visitSiteEditor( { + postId: template.id, + postType: 'wp_template', + canvas: 'edit', + } ); + + await expect( editor.canvas.getByText( 'placeholder' ) ).toBeVisible(); } ); test.describe( 'with thumbnails', () => { @@ -342,7 +350,7 @@ test.describe( `${ blockData.name }`, () => { const largeImageBlock = await pageObject.getMainImageBlock( { page: 'frontend', } ); - largeImageBlock.click(); + await largeImageBlock.click(); const productGalleryPopUpContent = page.locator( '.wc-block-product-gallery-dialog__body' @@ -401,7 +409,7 @@ test.describe( `${ blockData.name }`, () => { secondImageThumbnailId ); - largeImageBlock.click(); + await largeImageBlock.click(); const productGalleryPopUpContent = page.locator( '.wc-block-product-gallery-dialog__body' @@ -434,7 +442,7 @@ test.describe( `${ blockData.name }`, () => { const closePopUpButton = productGalleryPopUpHeader.locator( '.wc-block-product-gallery-dialog__close' ); - closePopUpButton.click(); + await closePopUpButton.click(); await page.waitForFunction( () => { const isPopUpOpen = document @@ -459,8 +467,7 @@ test.describe( `${ blockData.name }`, () => { } ) => { await pageObject.addProductGalleryBlock( { cleanContent: true } ); await editor.openDocumentSettingsSidebar(); - const fullScreenOption = - await pageObject.getFullScreenOnClickSetting(); + const fullScreenOption = pageObject.getFullScreenOnClickSetting(); await expect( fullScreenOption ).toBeChecked(); } ); diff --git a/plugins/woocommerce-blocks/tests/e2e/tests/related-products/related-products.block_theme.spec.ts b/plugins/woocommerce-blocks/tests/e2e/tests/related-products/related-products.block_theme.spec.ts index c3223ee8191..c481639cc13 100644 --- a/plugins/woocommerce-blocks/tests/e2e/tests/related-products/related-products.block_theme.spec.ts +++ b/plugins/woocommerce-blocks/tests/e2e/tests/related-products/related-products.block_theme.spec.ts @@ -4,10 +4,6 @@ import { BlockData } from '@woocommerce/e2e-types'; import { test, expect } from '@woocommerce/e2e-playwright-utils'; -/** - * Internal dependencies - */ - const blockData: BlockData = { name: 'Related Products', slug: 'woocommerce/related-products', @@ -22,11 +18,11 @@ test.describe( `${ blockData.name } Block`, () => { test( "can't be added in the Post Editor", async ( { admin, editor } ) => { await admin.createNewPost(); - try { - await editor.insertBlock( { name: blockData.slug } ); - } catch ( e ) { - expect( e.message ).toContain( 'is not registered' ); - } + await expect( + editor.insertBlock( { name: blockData.slug } ) + ).rejects.toThrow( + new RegExp( `Block type '${ blockData.slug }' is not registered.` ) + ); } ); test( "can't be added in the Post Editor - Product Catalog Template", async ( { @@ -40,11 +36,17 @@ test.describe( `${ blockData.name } Block`, () => { } ); await editorUtils.enterEditMode(); + await editor.setContent( '' ); + try { await editor.insertBlock( { name: blockData.slug } ); - } catch ( e ) { - expect( e.message ).toContain( 'is not registered' ); + } catch ( _error ) { + // noop } + + await expect( + await editorUtils.getBlockByName( blockData.slug ) + ).toBeHidden(); } ); test( 'can be added in the Post Editor - Single Product Template', async ( { @@ -57,9 +59,7 @@ test.describe( `${ blockData.name } Block`, () => { postType: 'wp_template', } ); await editorUtils.enterEditMode(); - await editor.setContent( '' ); - await editor.insertBlock( { name: blockData.slug } ); await expect( diff --git a/plugins/woocommerce-blocks/tests/e2e/tests/single-product-template/single-product-template-compatibility-layer.spec.ts b/plugins/woocommerce-blocks/tests/e2e/tests/single-product-template/single-product-template-compatibility-layer.spec.ts index e6c1ac75209..d7ab1345def 100644 --- a/plugins/woocommerce-blocks/tests/e2e/tests/single-product-template/single-product-template-compatibility-layer.spec.ts +++ b/plugins/woocommerce-blocks/tests/e2e/tests/single-product-template/single-product-template-compatibility-layer.spec.ts @@ -91,7 +91,7 @@ test.describe( 'Compatibility Layer with Product Collection block', () => { } ); // eslint-disable-next-line playwright/valid-describe-callback - test.describe( 'Product Archive with Product Collection block', async () => { + test.describe( 'Product Archive with Product Collection block', () => { for ( const scenario of singleOccurranceScenarios ) { test( `${ scenario.title } is attached to the page`, async ( { page, diff --git a/plugins/woocommerce-blocks/tests/e2e/tests/stock-filter/stock-filter.block_theme.spec.ts b/plugins/woocommerce-blocks/tests/e2e/tests/stock-filter/stock-filter.block_theme.spec.ts index d772263f978..5067c8e71d2 100644 --- a/plugins/woocommerce-blocks/tests/e2e/tests/stock-filter/stock-filter.block_theme.spec.ts +++ b/plugins/woocommerce-blocks/tests/e2e/tests/stock-filter/stock-filter.block_theme.spec.ts @@ -122,7 +122,7 @@ test.describe( `${ blockData.name } Block`, () => { } ); test.describe( `${ blockData.name } Block - with PHP classic template`, () => { - test.beforeEach( async ( { admin, page, editor, editorUtils } ) => { + test.beforeEach( async ( { admin, page, editor } ) => { await cli( 'npm run wp-env run tests-cli -- wp option update wc_blocks_use_blockified_product_grid_block_as_template false' ); @@ -130,9 +130,14 @@ test.describe( `${ blockData.name } Block - with PHP classic template`, () => { await admin.visitSiteEditor( { postId: 'woocommerce/woocommerce//archive-product', postType: 'wp_template', + canvas: 'edit', } ); - await editorUtils.enterEditMode(); + await editor.canvas + .locator( + '.wp-block-woocommerce-classic-template__placeholder-image' + ) + .waitFor(); await editor.insertBlock( { name: 'woocommerce/filter-wrapper', diff --git a/plugins/woocommerce-blocks/tests/e2e/tsconfig.json b/plugins/woocommerce-blocks/tests/e2e/tsconfig.json index f52a4d12b49..0e5dc606f74 100644 --- a/plugins/woocommerce-blocks/tests/e2e/tsconfig.json +++ b/plugins/woocommerce-blocks/tests/e2e/tsconfig.json @@ -1,3 +1,12 @@ { + "$schema": "https://json.schemastore.org/tsconfig.json", "extends": "../../tsconfig.base.json", + "compilerOptions": { + "noEmit": true, + "emitDeclarationOnly": false, + "allowJs": true, + "checkJs": false + }, + "include": [ "**/*", "./.eslintrc.js" ], + "exclude": [] } diff --git a/plugins/woocommerce-blocks/tests/e2e/utils/editor/editor-utils.page.ts b/plugins/woocommerce-blocks/tests/e2e/utils/editor/editor-utils.page.ts index b989740b8cb..a7b4dba2165 100644 --- a/plugins/woocommerce-blocks/tests/e2e/utils/editor/editor-utils.page.ts +++ b/plugins/woocommerce-blocks/tests/e2e/utils/editor/editor-utils.page.ts @@ -211,7 +211,7 @@ export class EditorUtils { async openGlobalBlockInserter() { if ( ! ( await this.isGlobalInserterOpen() ) ) { await this.toggleGlobalBlockInserter(); - await this.page.waitForSelector( '.block-editor-inserter__menu' ); + await this.page.locator( '.block-editor-inserter__menu' ).waitFor(); } } diff --git a/plugins/woocommerce-blocks/tests/e2e/utils/frontend/frontend-utils.page.ts b/plugins/woocommerce-blocks/tests/e2e/utils/frontend/frontend-utils.page.ts index 0e3d3f3d107..1c016147863 100644 --- a/plugins/woocommerce-blocks/tests/e2e/utils/frontend/frontend-utils.page.ts +++ b/plugins/woocommerce-blocks/tests/e2e/utils/frontend/frontend-utils.page.ts @@ -53,7 +53,7 @@ export class FrontendUtils { waitUntil: 'domcontentloaded', } ); - await this.page.waitForSelector( '#email' ); + await this.page.locator( '#email' ).waitFor(); } async goToCart() { diff --git a/plugins/woocommerce-blocks/tests/e2e/utils/navigation/navigation.ts b/plugins/woocommerce-blocks/tests/e2e/utils/navigation/navigation.ts index 819511a1482..3b25813c082 100644 --- a/plugins/woocommerce-blocks/tests/e2e/utils/navigation/navigation.ts +++ b/plugins/woocommerce-blocks/tests/e2e/utils/navigation/navigation.ts @@ -35,6 +35,6 @@ export const editBlockPage = async ( .getByRole( 'link', { name: `“${ name } block” (Edit)` } ) .click(); - await page.waitForSelector( blockSelector ); + await page.locator( blockSelector as string ).waitFor(); await closeModalIfExists( page ); }; diff --git a/plugins/woocommerce/changelog/47228-align-e2e-eslint-config-with-gutenberg b/plugins/woocommerce/changelog/47228-align-e2e-eslint-config-with-gutenberg new file mode 100644 index 00000000000..43b71479b19 --- /dev/null +++ b/plugins/woocommerce/changelog/47228-align-e2e-eslint-config-with-gutenberg @@ -0,0 +1,4 @@ +Significance: patch +Type: dev + +Blocks E2E: Align ESlint and TS configs with Gutenberg & fix flaky tests.