From 0d65648ed77b65afde8dd9713d2d7c8dbb296693 Mon Sep 17 00:00:00 2001 From: Ivan Stojadinov Date: Tue, 3 Sep 2024 23:53:23 +0200 Subject: [PATCH] [e2e] Skipping 11 tests for the Pressable website (#51123) * Skipping 11 tests for the Pressable website * Add changefile(s) from automation for the following project(s): woocommerce --------- Co-authored-by: github-actions Co-authored-by: Jonathan Lane --- ...123-e2e-external-envs-disble-failing-tests | 4 + .../assembler/color-picker.spec.js | 218 +++---- .../assembler/full-composability.spec.js | 23 +- .../assembler/homepage.spec.js | 70 +- .../assembler/logo-picker/logo-picker.spec.js | 44 +- .../tests/customize-store/intro.spec.js | 31 +- .../customize-store/transitional.spec.js | 21 +- .../tests/merchant/create-cart-block.spec.js | 2 +- .../merchant/create-checkout-block.spec.js | 176 ++--- ...create-simple-product-block-editor.spec.js | 601 +++++++++--------- ...d-product-tab-product-block-editor.spec.js | 217 ++++--- 11 files changed, 726 insertions(+), 681 deletions(-) create mode 100644 plugins/woocommerce/changelog/51123-e2e-external-envs-disble-failing-tests diff --git a/plugins/woocommerce/changelog/51123-e2e-external-envs-disble-failing-tests b/plugins/woocommerce/changelog/51123-e2e-external-envs-disble-failing-tests new file mode 100644 index 00000000000..1f8bb767263 --- /dev/null +++ b/plugins/woocommerce/changelog/51123-e2e-external-envs-disble-failing-tests @@ -0,0 +1,4 @@ +Significance: patch +Type: update + +E2E tests - skipping 11 tests for the Pressable website \ No newline at end of file diff --git a/plugins/woocommerce/tests/e2e-pw/tests/customize-store/assembler/color-picker.spec.js b/plugins/woocommerce/tests/e2e-pw/tests/customize-store/assembler/color-picker.spec.js index f28ae181628..e612598cf6b 100644 --- a/plugins/woocommerce/tests/e2e-pw/tests/customize-store/assembler/color-picker.spec.js +++ b/plugins/woocommerce/tests/e2e-pw/tests/customize-store/assembler/color-picker.spec.js @@ -512,121 +512,123 @@ test.describe( 'Assembler -> Color Pickers', { tag: '@gutenberg' }, () => { } ); - test( 'Create "your own" pickers should be visible', async ( { - assemblerPageObject, - baseURL, - }, testInfo ) => { - testInfo.snapshotSuffix = ''; - const wordPressVersion = await getInstalledWordPressVersion(); + test( + 'Create "your own" pickers should be visible', + { tag: '@skip-on-default-pressable' }, + async ( { assemblerPageObject, baseURL }, testInfo ) => { + testInfo.snapshotSuffix = ''; + const wordPressVersion = await getInstalledWordPressVersion(); - const assembler = await assemblerPageObject.getAssembler(); - const colorPicker = assembler.getByText( 'Create your own' ); + const assembler = await assemblerPageObject.getAssembler(); + const colorPicker = assembler.getByText( 'Create your own' ); - await colorPicker.click(); + await colorPicker.click(); - // Check if Gutenberg is installed - const apiContext = await request.newContext( { - baseURL, - extraHTTPHeaders: { - Authorization: `Basic ${ encodeCredentials( - admin.username, - admin.password - ) }`, - cookie: '', - }, - } ); - const listPluginsResponse = await apiContext.get( - `/wp-json/wp/v2/plugins`, - { - failOnStatusCode: true, - } - ); - const pluginsList = await listPluginsResponse.json(); - const gutenbergPlugin = pluginsList.find( - ( { textdomain } ) => textdomain === 'gutenberg' - ); - - const mapTypeFeatures = { - background: [ 'solid', 'gradient' ], - text: [], - heading: [ 'text', 'background', 'gradient' ], - button: [ 'text', 'background', 'gradient' ], - link: [ 'default', 'hover' ], - captions: [], - }; - const mapTypeFeaturesGutenberg = { - background: [ 'color', 'gradient' ], - text: [], - heading: [ 'text', 'background', 'gradient' ], - button: [ 'text', 'background', 'gradient' ], - link: [ 'default', 'hover' ], - captions: [], - }; - - const customColorSelector = - '.components-color-palette__custom-color-button'; - const gradientColorSelector = - '.components-custom-gradient-picker__gradient-bar-background'; - - const mapFeatureSelectors = { - solid: customColorSelector, - text: customColorSelector, - background: customColorSelector, - default: customColorSelector, - hover: customColorSelector, - gradient: gradientColorSelector, - }; - const mapFeatureSelectorsGutenberg = { - color: customColorSelector, - text: customColorSelector, - background: customColorSelector, - default: customColorSelector, - hover: customColorSelector, - gradient: gradientColorSelector, - }; - - for ( const type of Object.keys( mapTypeFeatures ) ) { - await assembler - .locator( - '.woocommerce-customize-store__color-panel-container' - ) - .getByText( type ) - .click(); - - // eslint-disable-next-line playwright/no-conditional-in-test - if ( gutenbergPlugin || wordPressVersion >= 6.6 ) { - for ( const feature of mapTypeFeaturesGutenberg[ type ] ) { - const container = assembler.locator( - '.block-editor-panel-color-gradient-settings__dropdown-content' - ); - await container - .getByRole( 'tab', { - name: feature, - } ) - .click(); - - const selector = mapFeatureSelectorsGutenberg[ feature ]; - const featureSelector = container.locator( selector ); - - await expect( featureSelector ).toBeVisible(); + // Check if Gutenberg is installed + const apiContext = await request.newContext( { + baseURL, + extraHTTPHeaders: { + Authorization: `Basic ${ encodeCredentials( + admin.username, + admin.password + ) }`, + cookie: '', + }, + } ); + const listPluginsResponse = await apiContext.get( + `/wp-json/wp/v2/plugins`, + { + failOnStatusCode: true, } - } else { - for ( const feature of mapTypeFeatures[ type ] ) { - const container = assembler.locator( - '.block-editor-panel-color-gradient-settings__dropdown-content' - ); - await container - .getByRole( 'tab', { - name: feature, - } ) - .click(); + ); + const pluginsList = await listPluginsResponse.json(); + const gutenbergPlugin = pluginsList.find( + ( { textdomain } ) => textdomain === 'gutenberg' + ); - const selector = mapFeatureSelectors[ feature ]; - const featureSelector = container.locator( selector ); + const mapTypeFeatures = { + background: [ 'solid', 'gradient' ], + text: [], + heading: [ 'text', 'background', 'gradient' ], + button: [ 'text', 'background', 'gradient' ], + link: [ 'default', 'hover' ], + captions: [], + }; + const mapTypeFeaturesGutenberg = { + background: [ 'color', 'gradient' ], + text: [], + heading: [ 'text', 'background', 'gradient' ], + button: [ 'text', 'background', 'gradient' ], + link: [ 'default', 'hover' ], + captions: [], + }; - await expect( featureSelector ).toBeVisible(); + const customColorSelector = + '.components-color-palette__custom-color-button'; + const gradientColorSelector = + '.components-custom-gradient-picker__gradient-bar-background'; + + const mapFeatureSelectors = { + solid: customColorSelector, + text: customColorSelector, + background: customColorSelector, + default: customColorSelector, + hover: customColorSelector, + gradient: gradientColorSelector, + }; + const mapFeatureSelectorsGutenberg = { + color: customColorSelector, + text: customColorSelector, + background: customColorSelector, + default: customColorSelector, + hover: customColorSelector, + gradient: gradientColorSelector, + }; + + for ( const type of Object.keys( mapTypeFeatures ) ) { + await assembler + .locator( + '.woocommerce-customize-store__color-panel-container' + ) + .getByText( type ) + .click(); + + // eslint-disable-next-line playwright/no-conditional-in-test + if ( gutenbergPlugin || wordPressVersion >= 6.6 ) { + for ( const feature of mapTypeFeaturesGutenberg[ type ] ) { + const container = assembler.locator( + '.block-editor-panel-color-gradient-settings__dropdown-content' + ); + await container + .getByRole( 'tab', { + name: feature, + } ) + .click(); + + const selector = + mapFeatureSelectorsGutenberg[ feature ]; + const featureSelector = container.locator( selector ); + + await expect( featureSelector ).toBeVisible(); + } + } else { + for ( const feature of mapTypeFeatures[ type ] ) { + const container = assembler.locator( + '.block-editor-panel-color-gradient-settings__dropdown-content' + ); + await container + .getByRole( 'tab', { + name: feature, + } ) + .click(); + + const selector = mapFeatureSelectors[ feature ]; + const featureSelector = container.locator( selector ); + + await expect( featureSelector ).toBeVisible(); + } } } } - } ); + ); } ); diff --git a/plugins/woocommerce/tests/e2e-pw/tests/customize-store/assembler/full-composability.spec.js b/plugins/woocommerce/tests/e2e-pw/tests/customize-store/assembler/full-composability.spec.js index 4d8f95f4869..f4b8729c74f 100644 --- a/plugins/woocommerce/tests/e2e-pw/tests/customize-store/assembler/full-composability.spec.js +++ b/plugins/woocommerce/tests/e2e-pw/tests/customize-store/assembler/full-composability.spec.js @@ -96,19 +96,20 @@ test.describe( 'Assembler -> Full composability', { tag: '@gutenberg' }, () => { } } ); - test( 'The list of categories should be displayed', async ( { - pageObject, - baseURL, - } ) => { - await prepareAssembler( pageObject, baseURL ); - const assembler = await pageObject.getAssembler(); + test( + 'The list of categories should be displayed', + { tag: '@skip-on-default-pressable' }, + async ( { pageObject, baseURL } ) => { + await prepareAssembler( pageObject, baseURL ); + const assembler = await pageObject.getAssembler(); - const categories = assembler.locator( - '.woocommerce-customize-store__sidebar-homepage-content .components-item-group' - ); + const categories = assembler.locator( + '.woocommerce-customize-store__sidebar-homepage-content .components-item-group' + ); - await expect( categories ).toHaveCount( 6 ); - } ); + await expect( categories ).toHaveCount( 6 ); + } + ); test( 'Clicking on "Design your homepage" should open the Intro sidebar by default', async ( { pageObject, diff --git a/plugins/woocommerce/tests/e2e-pw/tests/customize-store/assembler/homepage.spec.js b/plugins/woocommerce/tests/e2e-pw/tests/customize-store/assembler/homepage.spec.js index 8be49d4945a..f6d83d1758b 100644 --- a/plugins/woocommerce/tests/e2e-pw/tests/customize-store/assembler/homepage.spec.js +++ b/plugins/woocommerce/tests/e2e-pw/tests/customize-store/assembler/homepage.spec.js @@ -70,20 +70,21 @@ test.describe( 'Assembler -> Homepage', { tag: '@gutenberg' }, () => { } } ); - test( 'Available homepage should be displayed', async ( { - pageObject, - baseURL, - } ) => { - await prepareAssembler( pageObject, baseURL ); + test( + 'Available homepage should be displayed', + { tag: '@skip-on-default-pressable' }, + async ( { pageObject, baseURL } ) => { + await prepareAssembler( pageObject, baseURL ); - const assembler = await pageObject.getAssembler(); + const assembler = await pageObject.getAssembler(); - const homepages = assembler.locator( - '.block-editor-block-patterns-list__list-item' - ); + const homepages = assembler.locator( + '.block-editor-block-patterns-list__list-item' + ); - await expect( homepages ).toHaveCount( 3 ); - } ); + await expect( homepages ).toHaveCount( 3 ); + } + ); test( 'The selected homepage should be focused when is clicked', async ( { pageObject, @@ -247,31 +248,36 @@ test.describe( 'Homepage tracking banner', () => { } } ); - test( 'Should show the "Want more patterns?" banner with the PTK API unavailable message', async ( { - baseURL, - pageObject, - page, - } ) => { - await setOption( request, baseURL, 'woocommerce_allow_tracking', 'no' ); + test( + 'Should show the "Want more patterns?" banner with the PTK API unavailable message', + { tag: '@skip-on-default-pressable' }, + async ( { baseURL, pageObject, page } ) => { + await setOption( + request, + baseURL, + 'woocommerce_allow_tracking', + 'no' + ); - await page.route( '**/wp-json/wc-admin/patterns*', ( route ) => { - route.fulfill( { - status: 500, + await page.route( '**/wp-json/wc-admin/patterns*', ( route ) => { + route.fulfill( { + status: 500, + } ); } ); - } ); - await prepareAssembler( pageObject, baseURL ); + await prepareAssembler( pageObject, baseURL ); - const assembler = await pageObject.getAssembler(); - await expect( - assembler.getByText( 'Want more patterns?' ) - ).toBeVisible(); - await expect( - assembler.getByText( - "Unfortunately, we're experiencing some technical issues — please come back later to access more patterns." - ) - ).toBeVisible(); - } ); + const assembler = await pageObject.getAssembler(); + await expect( + assembler.getByText( 'Want more patterns?' ) + ).toBeVisible(); + await expect( + assembler.getByText( + "Unfortunately, we're experiencing some technical issues — please come back later to access more patterns." + ) + ).toBeVisible(); + } + ); test( 'Should show the "Want more patterns?" banner with the Opt-in message when tracking is not allowed', async ( { pageObject, diff --git a/plugins/woocommerce/tests/e2e-pw/tests/customize-store/assembler/logo-picker/logo-picker.spec.js b/plugins/woocommerce/tests/e2e-pw/tests/customize-store/assembler/logo-picker/logo-picker.spec.js index 7428e9dcc83..d1615de2394 100644 --- a/plugins/woocommerce/tests/e2e-pw/tests/customize-store/assembler/logo-picker/logo-picker.spec.js +++ b/plugins/woocommerce/tests/e2e-pw/tests/customize-store/assembler/logo-picker/logo-picker.spec.js @@ -219,29 +219,29 @@ test.describe( 'Assembler -> Logo Picker', { tag: '@gutenberg' }, () => { await expect( emptyLogoLocator ).toBeHidden(); } ); - test( 'Enabling the "use as site icon" option should set the image as the site icon', async ( { - page, - assemblerPageObject, - logoPickerPageObject, - } ) => { - const assembler = await assemblerPageObject.getAssembler(); - const emptyLogoPicker = - logoPickerPageObject.getEmptyLogoPickerLocator( assembler ); - await emptyLogoPicker.click(); - await logoPickerPageObject.pickImage( assembler ); - await assembler.getByText( 'Use as site icon' ).click(); - await logoPickerPageObject.saveLogoSettings( assembler ); + test( + 'Enabling the "use as site icon" option should set the image as the site icon', + { tag: '@skip-on-default-pressable' }, + async ( { page, assemblerPageObject, logoPickerPageObject } ) => { + const assembler = await assemblerPageObject.getAssembler(); + const emptyLogoPicker = + logoPickerPageObject.getEmptyLogoPickerLocator( assembler ); + await emptyLogoPicker.click(); + await logoPickerPageObject.pickImage( assembler ); + await assembler.getByText( 'Use as site icon' ).click(); + await logoPickerPageObject.saveLogoSettings( assembler ); - // alternative way to verify new site icon on the site - // verifying site icon shown in the new tab is impossible in headless mode - const date = new Date(); - const month = ( date.getMonth() + 1 ).toString().padStart( 2, '0' ); - await expect( - page.goto( - `/wp-content/uploads/${ date.getFullYear() }/${ month }/image-03-100x100.png` - ) - ).toBeTruthy(); - } ); + // alternative way to verify new site icon on the site + // verifying site icon shown in the new tab is impossible in headless mode + const date = new Date(); + const month = ( date.getMonth() + 1 ).toString().padStart( 2, '0' ); + await expect( + page.goto( + `/wp-content/uploads/${ date.getFullYear() }/${ month }/image-03-100x100.png` + ) + ).toBeTruthy(); + } + ); test( 'The selected image should be visible on the frontend', async ( { page, diff --git a/plugins/woocommerce/tests/e2e-pw/tests/customize-store/intro.spec.js b/plugins/woocommerce/tests/e2e-pw/tests/customize-store/intro.spec.js index ffe3f97b831..22d7c7d449d 100644 --- a/plugins/woocommerce/tests/e2e-pw/tests/customize-store/intro.spec.js +++ b/plugins/woocommerce/tests/e2e-pw/tests/customize-store/intro.spec.js @@ -58,21 +58,24 @@ test.describe( ); } ); - test( 'it shows the "offline banner" when the network is offline', async ( { - page, - context, - } ) => { - await page.goto( CUSTOMIZE_STORE_URL ); - await expect( - page.locator( 'text=Design your own' ) - ).toBeVisible(); - await context.setOffline( true ); + test( + 'it shows the "offline banner" when the network is offline', + { tag: '@skip-on-default-pressable' }, + async ( { page, context } ) => { + await page.goto( CUSTOMIZE_STORE_URL ); + await expect( + page.locator( 'text=Design your own' ) + ).toBeVisible(); + await context.setOffline( true ); - await expect( page.locator( '.offline-banner' ) ).toBeVisible(); - await expect( - page.locator( 'text=Looking to design your store using AI?' ) - ).toBeVisible(); - } ); + await expect( page.locator( '.offline-banner' ) ).toBeVisible(); + await expect( + page.locator( + 'text=Looking to design your store using AI?' + ) + ).toBeVisible(); + } + ); test( 'it shows the "no AI" banner on Core when the task is not completed', async ( { page, diff --git a/plugins/woocommerce/tests/e2e-pw/tests/customize-store/transitional.spec.js b/plugins/woocommerce/tests/e2e-pw/tests/customize-store/transitional.spec.js index b156bec00aa..58f4165f233 100644 --- a/plugins/woocommerce/tests/e2e-pw/tests/customize-store/transitional.spec.js +++ b/plugins/woocommerce/tests/e2e-pw/tests/customize-store/transitional.spec.js @@ -60,17 +60,20 @@ test.describe( ); } ); - test( 'Accessing the transitional page when the CYS flow is not completed should redirect to the Intro page', async ( { - page, - baseURL, - } ) => { - await page.goto( TRANSITIONAL_URL ); + test( + 'Accessing the transitional page when the CYS flow is not completed should redirect to the Intro page', + { tag: '@skip-on-default-pressable' }, + async ( { page, baseURL } ) => { + await page.goto( TRANSITIONAL_URL ); - const locator = page.locator( 'h1:visible' ); - await expect( locator ).not.toHaveText( 'Your store looks great!' ); + const locator = page.locator( 'h1:visible' ); + await expect( locator ).not.toHaveText( + 'Your store looks great!' + ); - await expect( page.url() ).toBe( `${ baseURL }${ INTRO_URL }` ); - } ); + await expect( page.url() ).toBe( `${ baseURL }${ INTRO_URL }` ); + } + ); test( 'Clicking on "Finish customizing" in the assembler should go to the transitional page', async ( { pageObject, diff --git a/plugins/woocommerce/tests/e2e-pw/tests/merchant/create-cart-block.spec.js b/plugins/woocommerce/tests/e2e-pw/tests/merchant/create-cart-block.spec.js index 1f612946ce5..6e4365b84ef 100644 --- a/plugins/woocommerce/tests/e2e-pw/tests/merchant/create-cart-block.spec.js +++ b/plugins/woocommerce/tests/e2e-pw/tests/merchant/create-cart-block.spec.js @@ -16,7 +16,7 @@ const test = baseTest.extend( { test.describe( 'Transform Classic Cart To Cart Block', - { tag: [ '@gutenberg', '@services' ] }, + { tag: [ '@gutenberg', '@services', '@skip-on-default-pressable' ] }, () => { test( 'can transform classic cart to cart block', async ( { page, diff --git a/plugins/woocommerce/tests/e2e-pw/tests/merchant/create-checkout-block.spec.js b/plugins/woocommerce/tests/e2e-pw/tests/merchant/create-checkout-block.spec.js index 53479325a1b..c5f0d7ec448 100644 --- a/plugins/woocommerce/tests/e2e-pw/tests/merchant/create-checkout-block.spec.js +++ b/plugins/woocommerce/tests/e2e-pw/tests/merchant/create-checkout-block.spec.js @@ -68,105 +68,109 @@ test.describe( } ); } ); - test( 'can transform classic checkout to checkout block', async ( { - page, - api, - testPage, - } ) => { - await goToPageEditor( { page } ); + test( + 'can transform classic checkout to checkout block', + { tag: '@skip-on-default-pressable' }, + async ( { page, api, testPage } ) => { + await goToPageEditor( { page } ); - await closeChoosePatternModal( { page } ); + await closeChoosePatternModal( { page } ); - await fillPageTitle( page, testPage.title ); - const wordPressVersion = await getInstalledWordPressVersion(); - await insertBlock( page, 'Classic Checkout', wordPressVersion ); - await transformIntoBlocks( page ); + await fillPageTitle( page, testPage.title ); + const wordPressVersion = await getInstalledWordPressVersion(); + await insertBlock( page, 'Classic Checkout', wordPressVersion ); + await transformIntoBlocks( page ); - // When Gutenberg is active, the canvas is in an iframe - let canvas = await getCanvas( page ); + // When Gutenberg is active, the canvas is in an iframe + let canvas = await getCanvas( page ); - // Open Settings sidebar if closed - await openEditorSettings( { page } ); + // Open Settings sidebar if closed + await openEditorSettings( { page } ); - // Activate the terms and conditions checkbox - await canvas.getByLabel( 'Block: Terms and Conditions' ).click(); - await page.getByLabel( 'Require checkbox' ).check(); + // Activate the terms and conditions checkbox + await canvas + .getByLabel( 'Block: Terms and Conditions' ) + .click(); + await page.getByLabel( 'Require checkbox' ).check(); - await publishPage( page, testPage.title ); + await publishPage( page, testPage.title ); - // add additional payment option after page creation - const r = await api.put( 'payment_gateways/bacs', { - enabled: true, - } ); - expect( r.data.enabled ).toBe( true ); - await page.reload(); + // add additional payment option after page creation + const r = await api.put( 'payment_gateways/bacs', { + enabled: true, + } ); + expect( r.data.enabled ).toBe( true ); + await page.reload(); - // Mandatory to wait for the editor content, to ensure the iframe is loaded (if Gutenberg is active) - await expect( page.getByLabel( 'Editor content' ) ).toBeVisible(); + // Mandatory to wait for the editor content, to ensure the iframe is loaded (if Gutenberg is active) + await expect( + page.getByLabel( 'Editor content' ) + ).toBeVisible(); - // Get the canvas again after the page reload - canvas = await getCanvas( page ); + // Get the canvas again after the page reload + canvas = await getCanvas( page ); - await expect( - canvas.getByText( 'Direct bank transfer' ) - ).toBeVisible(); - await expect( - canvas.getByText( 'Cash on delivery' ) - ).toBeVisible(); + await expect( + canvas.getByText( 'Direct bank transfer' ) + ).toBeVisible(); + await expect( + canvas.getByText( 'Cash on delivery' ) + ).toBeVisible(); - // add additional shipping methods after page creation - await api.post( `shipping/zones/${ shippingZoneId }/methods`, { - method_id: 'flat_rate', - settings: { - cost: '5.00', - }, - } ); - await api.post( `shipping/zones/${ shippingZoneId }/methods`, { - method_id: 'local_pickup', - } ); - await page.reload(); + // add additional shipping methods after page creation + await api.post( `shipping/zones/${ shippingZoneId }/methods`, { + method_id: 'flat_rate', + settings: { + cost: '5.00', + }, + } ); + await api.post( `shipping/zones/${ shippingZoneId }/methods`, { + method_id: 'local_pickup', + } ); + await page.reload(); - // verify that added shipping methods are present - // there is issue in blocks: #45747 unable to verify the shipping methods - // please uncomment below when the issue is resolved - // await expect( page.getByLabel( 'Free shipping' ) ).toBeVisible(); - // await expect( page.getByLabel( 'Local pickup' ) ).toBeVisible(); - // await expect( page.getByLabel( 'Flat rate' ) ).toBeVisible(); + // verify that added shipping methods are present + // there is issue in blocks: #45747 unable to verify the shipping methods + // please uncomment below when the issue is resolved + // await expect( page.getByLabel( 'Free shipping' ) ).toBeVisible(); + // await expect( page.getByLabel( 'Local pickup' ) ).toBeVisible(); + // await expect( page.getByLabel( 'Flat rate' ) ).toBeVisible(); - // go to frontend to verify transformed checkout block - // before that add product to cart to be able to visit checkout page - await page.goto( `/cart/?add-to-cart=${ productId }` ); - await page.goto( testPage.slug ); - await expect( - page.getByRole( 'heading', { name: testPage.title } ) - ).toBeVisible(); - await expect( - page - .getByRole( 'group', { name: 'Contact information' } ) - .locator( 'legend' ) - ).toBeVisible(); - await expect( - page.locator( - '.wp-block-woocommerce-checkout-order-summary-block' - ) - ).toBeVisible(); - await expect( - page.locator( '.wc-block-components-address-form' ).first() - ).toBeVisible(); + // go to frontend to verify transformed checkout block + // before that add product to cart to be able to visit checkout page + await page.goto( `/cart/?add-to-cart=${ productId }` ); + await page.goto( testPage.slug ); + await expect( + page.getByRole( 'heading', { name: testPage.title } ) + ).toBeVisible(); + await expect( + page + .getByRole( 'group', { name: 'Contact information' } ) + .locator( 'legend' ) + ).toBeVisible(); + await expect( + page.locator( + '.wp-block-woocommerce-checkout-order-summary-block' + ) + ).toBeVisible(); + await expect( + page.locator( '.wc-block-components-address-form' ).first() + ).toBeVisible(); - // verify existence of the terms & conditions and privacy policy checkbox - await expect( - page.getByText( - 'You must accept our Terms and Conditions and Privacy Policy to continue with your purchase.' - ) - ).toBeVisible(); - await expect( - page.locator( '#terms-and-conditions' ) - ).toBeVisible(); - await page.locator( '#terms-and-conditions' ).check(); - await expect( - page.locator( '#terms-and-conditions' ) - ).toBeChecked(); - } ); + // verify existence of the terms & conditions and privacy policy checkbox + await expect( + page.getByText( + 'You must accept our Terms and Conditions and Privacy Policy to continue with your purchase.' + ) + ).toBeVisible(); + await expect( + page.locator( '#terms-and-conditions' ) + ).toBeVisible(); + await page.locator( '#terms-and-conditions' ).check(); + await expect( + page.locator( '#terms-and-conditions' ) + ).toBeChecked(); + } + ); } ); diff --git a/plugins/woocommerce/tests/e2e-pw/tests/merchant/products/block-editor/create-simple-product-block-editor.spec.js b/plugins/woocommerce/tests/e2e-pw/tests/merchant/products/block-editor/create-simple-product-block-editor.spec.js index d1742772d3c..c929fcbd938 100644 --- a/plugins/woocommerce/tests/e2e-pw/tests/merchant/products/block-editor/create-simple-product-block-editor.spec.js +++ b/plugins/woocommerce/tests/e2e-pw/tests/merchant/products/block-editor/create-simple-product-block-editor.spec.js @@ -59,365 +59,378 @@ test.describe( 'General tab', { tag: '@gutenberg' }, () => { 'The block product editor is not being tested' ); - test( 'can create a simple product', async ( { page } ) => { - await test.step( 'add new product', async () => { - await page.goto( NEW_EDITOR_ADD_PRODUCT_URL ); - } ); + test( + 'can create a simple product', + { tag: '@skip-on-default-pressable' }, + async ( { page } ) => { + await test.step( 'add new product', async () => { + await page.goto( NEW_EDITOR_ADD_PRODUCT_URL ); + } ); - await test.step( 'add product name', async () => { - await clickOnTab( 'General', page ); - await page - .getByPlaceholder( 'e.g. 12 oz Coffee Mug' ) - // Have to use pressSequentially in order for the SKU to be auto-updated - // before we move to the SKU field and attempt to fill it in; otherwise, - // the SKU field can sometimes end up getting auto-updated after we have filled it in, - // wiping out the value we entered. - .pressSequentially( productData.name ); - } ); + await test.step( 'add product name', async () => { + await clickOnTab( 'General', page ); + await page + .getByPlaceholder( 'e.g. 12 oz Coffee Mug' ) + // Have to use pressSequentially in order for the SKU to be auto-updated + // before we move to the SKU field and attempt to fill it in; otherwise, + // the SKU field can sometimes end up getting auto-updated after we have filled it in, + // wiping out the value we entered. + .pressSequentially( productData.name ); + } ); - await test.step( 'add simple product description', async () => { - const descriptionSimpleParagraph = page.locator( - '[data-template-block-id="product-description__content"] > p' - ); + await test.step( 'add simple product description', async () => { + const descriptionSimpleParagraph = page.locator( + '[data-template-block-id="product-description__content"] > p' + ); - await descriptionSimpleParagraph.fill( - productData.descriptionSimple - ); - } ); + await descriptionSimpleParagraph.fill( + productData.descriptionSimple + ); + } ); - await test.step( 'add full product description', async () => { - // Helps to ensure that block toolbar appears, by letting the editor - // know that the user is done typing. - await page.keyboard.press( 'Escape' ); + await test.step( 'add full product description', async () => { + // Helps to ensure that block toolbar appears, by letting the editor + // know that the user is done typing. + await page.keyboard.press( 'Escape' ); - await page.getByText( 'Full editor' ).click(); + await page.getByText( 'Full editor' ).click(); - const wordPressVersion = await getInstalledWordPressVersion(); - await insertBlock( page, 'Heading', wordPressVersion ); + const wordPressVersion = + await getInstalledWordPressVersion(); + await insertBlock( page, 'Heading', wordPressVersion ); - const editorCanvasLocator = page.frameLocator( - 'iframe[name="editor-canvas"]' - ); + const editorCanvasLocator = page.frameLocator( + 'iframe[name="editor-canvas"]' + ); - await editorCanvasLocator - .locator( '[data-title="Heading"]' ) - .fill( productData.descriptionTitle ); + await editorCanvasLocator + .locator( '[data-title="Heading"]' ) + .fill( productData.descriptionTitle ); - await editorCanvasLocator - .locator( '[data-title="Heading"]' ) - .blur(); + await editorCanvasLocator + .locator( '[data-title="Heading"]' ) + .blur(); - await insertBlock( page, 'Paragraph', wordPressVersion ); + await insertBlock( page, 'Paragraph', wordPressVersion ); - await editorCanvasLocator - .locator( '[data-title="Paragraph"]' ) - .last() - .fill( productData.descriptionParagraph ); + await editorCanvasLocator + .locator( '[data-title="Paragraph"]' ) + .last() + .fill( productData.descriptionParagraph ); - await page.getByRole( 'button', { name: 'Done' } ).click(); - } ); + await page.getByRole( 'button', { name: 'Done' } ).click(); + } ); - await test.step( 'verify full product description', async () => { - const previewContainerIframe = page - .locator( '.block-editor-block-preview__container' ) - .frameLocator( 'iframe[title="Editor canvas"]' ); + await test.step( 'verify full product description', async () => { + const previewContainerIframe = page + .locator( '.block-editor-block-preview__container' ) + .frameLocator( 'iframe[title="Editor canvas"]' ); - const descriptionTitle = previewContainerIframe.locator( - '[data-title="Heading"]' - ); - const descriptionInitialParagraph = previewContainerIframe - .locator( '[data-title="Paragraph"]' ) - .first(); - const descriptionSecondParagraph = previewContainerIframe - .locator( '[data-title="Paragraph"]' ) - .last(); + const descriptionTitle = previewContainerIframe.locator( + '[data-title="Heading"]' + ); + const descriptionInitialParagraph = previewContainerIframe + .locator( '[data-title="Paragraph"]' ) + .first(); + const descriptionSecondParagraph = previewContainerIframe + .locator( '[data-title="Paragraph"]' ) + .last(); - await expect( descriptionTitle ).toHaveText( - productData.descriptionTitle - ); - await expect( descriptionInitialParagraph ).toHaveText( - productData.descriptionSimple - ); - await expect( descriptionSecondParagraph ).toHaveText( - productData.descriptionParagraph - ); + await expect( descriptionTitle ).toHaveText( + productData.descriptionTitle + ); + await expect( descriptionInitialParagraph ).toHaveText( + productData.descriptionSimple + ); + await expect( descriptionSecondParagraph ).toHaveText( + productData.descriptionParagraph + ); - await descriptionTitle.click(); + await descriptionTitle.click(); - await expect( - page.getByText( 'Edit in full editor' ) - ).toBeVisible(); - } ); + await expect( + page.getByText( 'Edit in full editor' ) + ).toBeVisible(); + } ); - await test.step( 'add product summary', async () => { - await page - .locator( - '[data-template-block-id="basic-details"] .components-summary-control' - ) - .last() - .fill( productData.summary ); + await test.step( 'add product summary', async () => { + await page + .locator( + '[data-template-block-id="basic-details"] .components-summary-control' + ) + .last() + .fill( productData.summary ); - // Blur the summary field to hide the toolbar before clicking on the regular price field. - await page - .locator( - '[data-template-block-id="basic-details"] .components-summary-control' - ) - .last() - .blur(); - } ); + // Blur the summary field to hide the toolbar before clicking on the regular price field. + await page + .locator( + '[data-template-block-id="basic-details"] .components-summary-control' + ) + .last() + .blur(); + } ); - await test.step( 'add product price', async () => { - const regularPrice = page - .locator( 'input[name="regular_price"]' ) - .first(); - await regularPrice.waitFor( { state: 'visible' } ); - await regularPrice.click(); - await regularPrice.fill( productData.productPrice ); + await test.step( 'add product price', async () => { + const regularPrice = page + .locator( 'input[name="regular_price"]' ) + .first(); + await regularPrice.waitFor( { state: 'visible' } ); + await regularPrice.click(); + await regularPrice.fill( productData.productPrice ); - const salePrice = page - .locator( 'input[name="sale_price"]' ) - .first(); - await salePrice.waitFor( { state: 'visible' } ); - await salePrice.click(); - await salePrice.fill( productData.salePrice ); - } ); + const salePrice = page + .locator( 'input[name="sale_price"]' ) + .first(); + await salePrice.waitFor( { state: 'visible' } ); + await salePrice.click(); + await salePrice.fill( productData.salePrice ); + } ); - await test.step( 'add custom fields', async () => { - await clickOnTab( 'Organization', page ); + await test.step( 'add custom fields', async () => { + await clickOnTab( 'Organization', page ); - const customFieldsAddNewButton = page - .getByLabel( 'Block: Product custom fields toggle control' ) - .getByRole( 'button', { name: 'Add new' } ); + const customFieldsAddNewButton = page + .getByLabel( + 'Block: Product custom fields toggle control' + ) + .getByRole( 'button', { name: 'Add new' } ); - // When re-running the test without resetting the env, - // the custom fields toggle might be already checked, - // so we need to check if the "Add new" button is already visible. - // - // eslint-disable-next-line playwright/no-conditional-in-test - if ( ! ( await customFieldsAddNewButton.isVisible() ) ) { - // Toggle the "Show custom fields" so that the "Add new" button is visible - - const customFieldsToggle = page.getByRole( 'checkbox', { - name: 'Show custom fields', - } ); - - await customFieldsToggle.scrollIntoViewIfNeeded(); - - // click() is used instead of check() because - // Playwright sometimes has issues with custom checkboxes: - // - https://github.com/microsoft/playwright/issues/13470 - // - https://github.com/microsoft/playwright/issues/20893 - // - https://github.com/microsoft/playwright/issues/27016 + // When re-running the test without resetting the env, + // the custom fields toggle might be already checked, + // so we need to check if the "Add new" button is already visible. // // eslint-disable-next-line playwright/no-conditional-in-test - if ( ! ( await customFieldsToggle.isChecked() ) ) { - await customFieldsToggle.click(); + if ( ! ( await customFieldsAddNewButton.isVisible() ) ) { + // Toggle the "Show custom fields" so that the "Add new" button is visible + + const customFieldsToggle = page.getByRole( 'checkbox', { + name: 'Show custom fields', + } ); + + await customFieldsToggle.scrollIntoViewIfNeeded(); + + // click() is used instead of check() because + // Playwright sometimes has issues with custom checkboxes: + // - https://github.com/microsoft/playwright/issues/13470 + // - https://github.com/microsoft/playwright/issues/20893 + // - https://github.com/microsoft/playwright/issues/27016 + // + // eslint-disable-next-line playwright/no-conditional-in-test + if ( ! ( await customFieldsToggle.isChecked() ) ) { + await customFieldsToggle.click(); + } + + await customFieldsToggle.isEnabled(); } - await customFieldsToggle.isEnabled(); - } + await expect( customFieldsAddNewButton ).toBeVisible(); - await expect( customFieldsAddNewButton ).toBeVisible(); + await customFieldsAddNewButton.click(); - await customFieldsAddNewButton.click(); + // Add custom fields modal + const modal = page.locator( + '.woocommerce-product-custom-fields__create-modal' + ); - // Add custom fields modal - const modal = page.locator( - '.woocommerce-product-custom-fields__create-modal' - ); + await expect( + modal.getByText( 'Add custom fields' ) + ).toBeVisible(); - await expect( - modal.getByText( 'Add custom fields' ) - ).toBeVisible(); - - const nameInput = modal.getByLabel( 'Name' ); - // Have to use pressSequentially in order to get the dropdown to show up and be able to select the option - await nameInput.pressSequentially( - productData.customFields[ 0 ].name - ); - - await expect( - modal.getByRole( - 'option', + const nameInput = modal.getByLabel( 'Name' ); + // Have to use pressSequentially in order to get the dropdown to show up and be able to select the option + await nameInput.pressSequentially( productData.customFields[ 0 ].name - ) - ).toBeVisible(); + ); - await nameInput.press( 'Enter' ); + await expect( + modal.getByRole( + 'option', + productData.customFields[ 0 ].name + ) + ).toBeVisible(); - const valueInput = modal.getByLabel( 'Value' ); - await valueInput.fill( productData.customFields[ 0 ].value ); + await nameInput.press( 'Enter' ); - await modal - .getByRole( 'button', { name: 'Add', exact: true } ) - .click(); + const valueInput = modal.getByLabel( 'Value' ); + await valueInput.fill( + productData.customFields[ 0 ].value + ); - await expect( - modal.getByText( 'Add custom fields' ) - ).toBeHidden(); + await modal + .getByRole( 'button', { name: 'Add', exact: true } ) + .click(); - await expect( - page.getByText( productData.customFields[ 0 ].name ) - ).toBeVisible(); - await expect( - page.getByText( productData.customFields[ 0 ].value ) - ).toBeVisible(); - } ); + await expect( + modal.getByText( 'Add custom fields' ) + ).toBeHidden(); - await test.step( 'add inventory details', async () => { - await clickOnTab( 'Inventory', page ); + await expect( + page.getByText( productData.customFields[ 0 ].name ) + ).toBeVisible(); + await expect( + page.getByText( productData.customFields[ 0 ].value ) + ).toBeVisible(); + } ); - await page - .getByLabel( 'SKU (Stock Keeping Unit)' ) - .fill( productData.sku ); - await page - .getByLabel( 'GTIN, UPC, EAN, or ISBN' ) - .fill( productData.gtin ); - } ); + await test.step( 'add inventory details', async () => { + await clickOnTab( 'Inventory', page ); - await test.step( 'add shipping details', async () => { - await clickOnTab( 'Shipping', page ); + await page + .getByLabel( 'SKU (Stock Keeping Unit)' ) + .fill( productData.sku ); + await page + .getByLabel( 'GTIN, UPC, EAN, or ISBN' ) + .fill( productData.gtin ); + } ); - // Shipping class - await page - .getByLabel( 'Shipping class', { exact: true } ) - //.locator( 'select[name="shipping_class"]' ) - .selectOption( 'Add new shipping class' ); + await test.step( 'add shipping details', async () => { + await clickOnTab( 'Shipping', page ); - // New shipping class modal - const modal = page.locator( - '.woocommerce-add-new-shipping-class-modal' - ); + // Shipping class + await page + .getByLabel( 'Shipping class', { exact: true } ) + //.locator( 'select[name="shipping_class"]' ) + .selectOption( 'Add new shipping class' ); - await expect( - modal.getByText( 'New shipping class' ) - ).toBeVisible(); + // New shipping class modal + const modal = page.locator( + '.woocommerce-add-new-shipping-class-modal' + ); - await modal - .getByLabel( 'Name (Required)' ) - .fill( productData.shipping.shippingClassName ); + await expect( + modal.getByText( 'New shipping class' ) + ).toBeVisible(); - await modal.getByText( 'Add' ).click(); + await modal + .getByLabel( 'Name (Required)' ) + .fill( productData.shipping.shippingClassName ); - await expect( - modal.getByText( 'New shipping class' ) - ).toBeHidden(); + await modal.getByText( 'Add' ).click(); - await expect( - page.getByLabel( 'Shipping class', { exact: true } ) - ).toHaveValue( productData.shipping.shippingClassName ); + await expect( + modal.getByText( 'New shipping class' ) + ).toBeHidden(); - // Shipping dimensions - await page - .getByLabel( 'Width A' ) - .fill( productData.shipping.width ); - await page - .getByLabel( 'Length B' ) - .fill( productData.shipping.length ); - await page - .getByLabel( 'Height C' ) - .fill( productData.shipping.height ); - await page - .getByLabel( 'Weight' ) - .fill( productData.shipping.weight ); - } ); + await expect( + page.getByLabel( 'Shipping class', { exact: true } ) + ).toHaveValue( productData.shipping.shippingClassName ); - await test.step( 'publish the product', async () => { - await page - .locator( '.woocommerce-product-header__actions' ) - .getByRole( 'button', { - name: 'Publish', - } ) - .click(); + // Shipping dimensions + await page + .getByLabel( 'Width A' ) + .fill( productData.shipping.width ); + await page + .getByLabel( 'Length B' ) + .fill( productData.shipping.length ); + await page + .getByLabel( 'Height C' ) + .fill( productData.shipping.height ); + await page + .getByLabel( 'Weight' ) + .fill( productData.shipping.weight ); + } ); - await expect( - page.getByLabel( 'Dismiss this notice' ) - ).toContainText( 'Product published' ); + await test.step( 'publish the product', async () => { + await page + .locator( '.woocommerce-product-header__actions' ) + .getByRole( 'button', { + name: 'Publish', + } ) + .click(); - const title = page.locator( - '.woocommerce-product-header__title' - ); + await expect( + page.getByLabel( 'Dismiss this notice' ) + ).toContainText( 'Product published' ); - // Save product ID - const productIdRegex = /product%2F(\d+)/; - const url = page.url(); - const productIdMatch = productIdRegex.exec( url ); - // This isn't really a conditional branch in the test; - // just making sure we don't blow up if the regex doesn't match - // (it will be caught in the expect below). - // eslint-disable-next-line playwright/no-conditional-in-test - productId = productIdMatch ? productIdMatch[ 1 ] : null; + const title = page.locator( + '.woocommerce-product-header__title' + ); - expect( productId ).toBeDefined(); - await expect( title ).toHaveText( productData.name ); - } ); + // Save product ID + const productIdRegex = /product%2F(\d+)/; + const url = page.url(); + const productIdMatch = productIdRegex.exec( url ); + // This isn't really a conditional branch in the test; + // just making sure we don't blow up if the regex doesn't match + // (it will be caught in the expect below). + // eslint-disable-next-line playwright/no-conditional-in-test + productId = productIdMatch ? productIdMatch[ 1 ] : null; - // Note for future refactoring: It would be good to reuse the verification step - // from product-create-simple.spec.js, as both tests are just verifying that the - // product was created correctly by looking at the front end. - await test.step( 'verify the saved product in frontend', async () => { - const permalink = await page - .locator( '.product-details-section__product-link a' ) - .getAttribute( 'href' ); + expect( productId ).toBeDefined(); + await expect( title ).toHaveText( productData.name ); + } ); - await page.goto( permalink ); + // Note for future refactoring: It would be good to reuse the verification step + // from product-create-simple.spec.js, as both tests are just verifying that the + // product was created correctly by looking at the front end. + await test.step( 'verify the saved product in frontend', async () => { + const permalink = await page + .locator( '.product-details-section__product-link a' ) + .getAttribute( 'href' ); - // Verify product name - await expect( - page.getByRole( 'heading', { - name: productData.name, - } ) - ).toBeVisible(); + await page.goto( permalink ); - // Verify price - await expect( - page.getByText( productData.productPrice ).first() - ).toBeVisible(); - await expect( - page.getByText( productData.salePrice ).first() - ).toBeVisible(); + // Verify product name + await expect( + page.getByRole( 'heading', { + name: productData.name, + } ) + ).toBeVisible(); - // Verify summary - await expect( - page.getByText( productData.summary ) - ).toBeVisible(); + // Verify price + await expect( + page.getByText( productData.productPrice ).first() + ).toBeVisible(); + await expect( + page.getByText( productData.salePrice ).first() + ).toBeVisible(); - // Verify description - await page.getByRole( 'tab', { name: 'Description' } ).click(); + // Verify summary + await expect( + page.getByText( productData.summary ) + ).toBeVisible(); - await expect( - page.getByText( productData.descriptionTitle ) - ).toBeVisible(); - await expect( - page.getByText( productData.descriptionSimple ) - ).toBeVisible(); - await expect( - page.getByText( productData.descriptionParagraph ) - ).toBeVisible(); + // Verify description + await page + .getByRole( 'tab', { name: 'Description' } ) + .click(); - // Verify inventory details - await expect( - page.getByText( `SKU: ${ productData.sku }` ) - ).toBeVisible(); - // Note: GTIN is not displayed in the front end in the theme used in the test + await expect( + page.getByText( productData.descriptionTitle ) + ).toBeVisible(); + await expect( + page.getByText( productData.descriptionSimple ) + ).toBeVisible(); + await expect( + page.getByText( productData.descriptionParagraph ) + ).toBeVisible(); - // Note: Shipping class is not displayed in the front end in the theme used in the test + // Verify inventory details + await expect( + page.getByText( `SKU: ${ productData.sku }` ) + ).toBeVisible(); + // Note: GTIN is not displayed in the front end in the theme used in the test - // Verify shipping dimensions - await page - .getByRole( 'tab', { name: 'Additional information' } ) - .click(); + // Note: Shipping class is not displayed in the front end in the theme used in the test - await expect( - page.getByText( `Weight ${ productData.shipping.weight }` ) - ).toBeVisible(); - await expect( - page.getByText( - `Dimensions ${ productData.shipping.length } × ${ productData.shipping.width } × ${ productData.shipping.height }` - ) - ).toBeVisible(); - } ); - } ); + // Verify shipping dimensions + await page + .getByRole( 'tab', { name: 'Additional information' } ) + .click(); + + await expect( + page.getByText( + `Weight ${ productData.shipping.weight }` + ) + ).toBeVisible(); + await expect( + page.getByText( + `Dimensions ${ productData.shipping.length } × ${ productData.shipping.width } × ${ productData.shipping.height }` + ) + ).toBeVisible(); + } ); + } + ); test( 'can not create a product with duplicated SKU', async ( { page, diff --git a/plugins/woocommerce/tests/e2e-pw/tests/merchant/products/block-editor/linked-product-tab-product-block-editor.spec.js b/plugins/woocommerce/tests/e2e-pw/tests/merchant/products/block-editor/linked-product-tab-product-block-editor.spec.js index 777c933b3fb..7f1e585a0b6 100644 --- a/plugins/woocommerce/tests/e2e-pw/tests/merchant/products/block-editor/linked-product-tab-product-block-editor.spec.js +++ b/plugins/woocommerce/tests/e2e-pw/tests/merchant/products/block-editor/linked-product-tab-product-block-editor.spec.js @@ -68,130 +68,139 @@ test.describe( 'General tab', { tag: '@gutenberg' }, () => { 'The block product editor is not being tested' ); - test( 'can create a product with linked products', async ( { - page, - } ) => { - await page.goto( NEW_EDITOR_ADD_PRODUCT_URL ); - await clickOnTab( 'General', page ); - await page - .getByPlaceholder( 'e.g. 12 oz Coffee Mug' ) - .fill( productData.name ); - await page - .locator( - '[data-template-block-id="basic-details"] .components-summary-control' - ) - .last() - .fill( productData.summary ); + test( + 'can create a product with linked products', + { tag: '@skip-on-default-pressable' }, + async ( { page } ) => { + await page.goto( NEW_EDITOR_ADD_PRODUCT_URL ); + await clickOnTab( 'General', page ); + await page + .getByPlaceholder( 'e.g. 12 oz Coffee Mug' ) + .fill( productData.name ); + await page + .locator( + '[data-template-block-id="basic-details"] .components-summary-control' + ) + .last() + .fill( productData.summary ); - // Include in category - await clickOnTab( 'Organization', page ); - const waitForCategoriesResponse = page.waitForResponse( - ( response ) => - response.url().includes( '/wp-json/wp/v2/product_cat' ) && - response.status() === 200 - ); - await page.getByLabel( 'Categories' ).click(); - await waitForCategoriesResponse; - await page.getByLabel( categoryName ).check(); - await page.getByLabel( `Remove Uncategorized` ).click(); - await expect( - page.getByLabel( `Remove ${ categoryName }` ) - ).toBeVisible(); + // Include in category + await clickOnTab( 'Organization', page ); + const waitForCategoriesResponse = page.waitForResponse( + ( response ) => + response + .url() + .includes( '/wp-json/wp/v2/product_cat' ) && + response.status() === 200 + ); + await page.getByLabel( 'Categories' ).click(); + await waitForCategoriesResponse; + await page.getByLabel( categoryName ).check(); + await page.getByLabel( `Remove Uncategorized` ).click(); + await expect( + page.getByLabel( `Remove ${ categoryName }` ) + ).toBeVisible(); - const waitForProductsSearchResponse = page.waitForResponse( - ( response ) => - response - .url() - .includes( '/wp-json/wc/v3/products?search' ) && - response.status() === 200 - ); - await clickOnTab( 'Linked products', page ); - await waitForProductsSearchResponse; + const waitForProductsSearchResponse = page.waitForResponse( + ( response ) => + response + .url() + .includes( '/wp-json/wc/v3/products?search' ) && + response.status() === 200 + ); + await clickOnTab( 'Linked products', page ); + await waitForProductsSearchResponse; - await expect( - page.getByRole( 'heading', { - name: 'Cross-sells', - } ) - ).toBeVisible(); + await expect( + page.getByRole( 'heading', { + name: 'Cross-sells', + } ) + ).toBeVisible(); - await page - .locator( - '.wp-block-woocommerce-product-linked-list-field__form-group-content' - ) - .first() - .getByRole( 'combobox' ) - .fill( productName ); + await page + .locator( + '.wp-block-woocommerce-product-linked-list-field__form-group-content' + ) + .first() + .getByRole( 'combobox' ) + .fill( productName ); - await page.getByText( linkedProductsData[ 0 ].name ).click(); + await page.getByText( linkedProductsData[ 0 ].name ).click(); - const chooseProductsResponsePromise = page.waitForResponse( - ( response ) => - response - .url() - .includes( - '/wp-json/wc/v3/products/suggested-products' - ) && response.status() === 200 - ); + const chooseProductsResponsePromise = page.waitForResponse( + ( response ) => + response + .url() + .includes( + '/wp-json/wc/v3/products/suggested-products' + ) && response.status() === 200 + ); - await page.getByText( 'Choose products for me' ).first().click(); - await chooseProductsResponsePromise; + await page + .getByText( 'Choose products for me' ) + .first() + .click(); + await chooseProductsResponsePromise; - await expect( - page.getByRole( 'row', { name: productName } ) - ).toHaveCount( 4 ); + await expect( + page.getByRole( 'row', { name: productName } ) + ).toHaveCount( 4 ); - const upsellsRows = page.locator( - 'div.woocommerce-product-list div[role="table"] div[role="rowgroup"] div[role="row"]' - ); + const upsellsRows = page.locator( + 'div.woocommerce-product-list div[role="table"] div[role="rowgroup"] div[role="row"]' + ); - await expect( upsellsRows ).toHaveCount( 4 ); + await expect( upsellsRows ).toHaveCount( 4 ); - await page - .locator( - '.wp-block-woocommerce-product-linked-list-field__form-group-content' - ) - .last() - .getByRole( 'combobox' ) - .fill( linkedProductsData[ 1 ].name ); + await page + .locator( + '.wp-block-woocommerce-product-linked-list-field__form-group-content' + ) + .last() + .getByRole( 'combobox' ) + .fill( linkedProductsData[ 1 ].name ); - await page - .getByText( linkedProductsData[ 1 ].name ) - .first() - .click(); + await page + .getByText( linkedProductsData[ 1 ].name ) + .first() + .click(); - await page - .locator( '.woocommerce-product-header__actions' ) - .getByRole( 'button', { - name: 'Publish', - } ) - .click(); + await page + .locator( '.woocommerce-product-header__actions' ) + .getByRole( 'button', { + name: 'Publish', + } ) + .click(); - await expect( - page.getByLabel( 'Dismiss this notice' ) - ).toContainText( 'Product published' ); + await expect( + page.getByLabel( 'Dismiss this notice' ) + ).toContainText( 'Product published' ); - const title = page.locator( '.woocommerce-product-header__title' ); + const title = page.locator( + '.woocommerce-product-header__title' + ); - // Save product ID - const productIdRegex = /product%2F(\d+)/; - const url = page.url(); - const productIdMatch = productIdRegex.exec( url ); - productId = productIdMatch ? productIdMatch[ 1 ] : null; + // Save product ID + const productIdRegex = /product%2F(\d+)/; + const url = page.url(); + const productIdMatch = productIdRegex.exec( url ); + productId = productIdMatch ? productIdMatch[ 1 ] : null; - await expect( productId ).toBeDefined(); - await expect( title ).toHaveText( productData.name ); + await expect( productId ).toBeDefined(); + await expect( title ).toHaveText( productData.name ); - await page.goto( `/?post_type=product&p=${ productId }` ); + await page.goto( `/?post_type=product&p=${ productId }` ); - await expect( - page.getByRole( 'heading', { name: productData.name } ) - ).toBeVisible(); + await expect( + page.getByRole( 'heading', { name: productData.name } ) + ).toBeVisible(); - const productsList = page.locator( - 'section.upsells.products ul > li' - ); + const productsList = page.locator( + 'section.upsells.products ul > li' + ); - await expect( productsList ).toHaveCount( 4 ); - } ); + await expect( productsList ).toHaveCount( 4 ); + } + ); } ); } );