From 0227a15e58aa499bfdb14526bc807cbc29eae1e2 Mon Sep 17 00:00:00 2001 From: rodelgc Date: Fri, 14 Apr 2023 15:07:52 +0800 Subject: [PATCH 1/8] Initial draft for `can create product, attributes and variations` test --- .../merchant/create-variable-product.spec.js | 504 +++++++++++++----- 1 file changed, 359 insertions(+), 145 deletions(-) diff --git a/plugins/woocommerce/tests/e2e-pw/tests/merchant/create-variable-product.spec.js b/plugins/woocommerce/tests/e2e-pw/tests/merchant/create-variable-product.spec.js index ad4842cfb60..3b649244732 100644 --- a/plugins/woocommerce/tests/e2e-pw/tests/merchant/create-variable-product.spec.js +++ b/plugins/woocommerce/tests/e2e-pw/tests/merchant/create-variable-product.spec.js @@ -67,7 +67,7 @@ async function resetVariableProductTour( baseURL, browser ) { ); } -test.describe( 'Add New Variable Product Page', () => { +test.describe.serial( 'Add New Variable Product Page', () => { test.use( { storageState: process.env.ADMINSTATE } ); test.afterAll( async ( { baseURL, browser } ) => { @@ -75,165 +75,377 @@ test.describe( 'Add New Variable Product Page', () => { await resetVariableProductTour( baseURL, browser ); } ); - test( 'can create product, attributes and variations, edit variations and delete variations', async ( { + // test( 'can create product, attributes and variations, edit variations and delete variations', async ( { + // page, + // } ) => { + // await page.goto( productPageURL ); + // await page.fill( '#title', variableProductName ); + // await page.selectOption( '#product-type', 'variable' ); + + // await page + // .locator( '.attribute_tab' ) + // .getByRole( 'link', { name: 'Attributes' } ) + // .scrollIntoViewIfNeeded(); + + // // the tour only seems to display when not running headless, so just make sure + // if ( await page.locator( '.woocommerce-tour-kit-step__heading' ).isVisible() ) { + // // dismiss the variable product tour + // await page + // .getByRole( 'button', { name: 'Close Tour' } ) + // .click(); + + // // wait for the tour's dismissal to be saved + // await page.waitForResponse( + // ( response ) => + // response.url().includes( '/users/' ) && + // response.status() === 200 + // ); + // } + + // await page.click( 'a[href="#product_attributes"]' ); + + // // add 3 attributes + // for ( let i = 0; i < 3; i++ ) { + // if ( i > 0 ) { + // await page.getByRole( 'button', { name: 'Add' } ) + // .nth(2) + // .click(); + // } + // await page.waitForSelector( + // `input[name="attribute_names[${ i }]"]` + // ); + + // await page + // .locator( `input[name="attribute_names[${ i }]"]` ) + // .first() + // .type( `attr #${ i + 1 }` ); + // await page + // .locator( `textarea[name="attribute_values[${ i }]"]` ) + // .first() + // .type( 'val1 | val2' ); + // } + + // await page.getByRole( 'button', { name: 'Save attributes'} ).click( { clickCount: 3 }); + + // // wait for the tour's dismissal to be saved + // await page.waitForResponse( + // ( response ) => + // response.url().includes( '/post.php' ) && + // response.status() === 200 + // ); + + // // Save before going to the Variations tab to prevent variations from all attributes to be automatically created + // await page.locator( '#save-post' ).click(); + // await expect( + // page.getByText( 'Product draft updated. ' ) + // ).toBeVisible(); + + // await page.click( 'a[href="#variable_product_options"]' ); + + // // event listener for handling the link_all_variations confirmation dialog + // page.on( 'dialog', ( dialog ) => dialog.accept() ); + + // // generate variations from all attributes + // await page.click( 'button.generate_variations' ); + + // // verify variations have the correct attribute values + // for ( let i = 0; i < 8; i++ ) { + // const val1 = 'val1'; + // const val2 = 'val2'; + // const attr3 = !! ( i % 2 ); // 0-1,4-5 / 2-3,6-7 + // const attr2 = i % 4 > 1; // 0-3 / 4-7 + // const attr1 = i > 3; + // await expect( + // page.locator( `select[name="attribute_attr-1[${ i }]"]` ) + // ).toHaveValue( attr1 ? val2 : val1 ); + // await expect( + // page.locator( `select[name="attribute_attr-2[${ i }]"]` ) + // ).toHaveValue( attr2 ? val2 : val1 ); + // await expect( + // page.locator( `select[name="attribute_attr-3[${ i }]"]` ) + // ).toHaveValue( attr3 ? val2 : val1 ); + // } + + // await page.locator( '#save-post' ).click(); + // await expect( page.locator( '#message.notice-success' ) ).toContainText( + // 'Product draft updated.' + // ); + + // // set variation attributes and bulk edit variations + // await page.click( 'a[href="#variable_product_options"]' ); + + // // set the variation attributes + // await page.click( + // '#variable_product_options .toolbar-top a.expand_all' + // ); + // await page.check( 'input[name="variable_is_virtual[0]"]' ); + // await page.fill( + // 'input[name="variable_regular_price[0]"]', + // variationOnePrice + // ); + // await page.check( 'input[name="variable_is_virtual[1]"]' ); + // await page.fill( + // 'input[name="variable_regular_price[1]"]', + // variationTwoPrice + // ); + // await page.check( 'input[name="variable_manage_stock[2]"]' ); + // await page.fill( + // 'input[name="variable_regular_price[2]"]', + // variationThreePrice + // ); + // await page.fill( 'input[name="variable_weight[2]"]', productWeight ); + // await page.fill( 'input[name="variable_length[2]"]', productLength ); + // await page.fill( 'input[name="variable_width[2]"]', productWidth ); + // await page.fill( 'input[name="variable_height[2]"]', productHeight ); + // await page.keyboard.press( 'ArrowUp' ); + // await page.click( 'button.save-variation-changes' ); + + // // bulk-edit variations + // await page.click( + // '#variable_product_options .toolbar-top a.expand_all' + // ); + // for ( let i = 0; i < 4; i++ ) { + // const checkBox = page.locator( + // `input[name="variable_is_downloadable[${ i }]"]` + // ); + // await expect( checkBox ).not.toBeChecked(); + // } + // await page.selectOption( '#field_to_edit', 'toggle_downloadable', { + // force: true, + // } ); + // await page.click( + // '#variable_product_options .toolbar-top a.expand_all' + // ); + // for ( let i = 0; i < 4; i++ ) { + // const checkBox = await page.locator( + // `input[name="variable_is_downloadable[${ i }]"]` + // ); + // await expect( checkBox ).toBeChecked(); + // } + + // await page.locator( '#save-post' ).click(); + + // // delete all variations + // await page.click( 'a[href="#variable_product_options"]' ); + // await page.waitForLoadState( 'networkidle' ); + // await page.selectOption( '#field_to_edit', 'delete_all' ); + // await page.waitForSelector( '.woocommerce_variation', { + // state: 'detached', + // } ); + // const variationsCount = await page.$$( '.woocommerce_variation' ); + // await expect( variationsCount ).toHaveLength( 0 ); + // } ); + + test( 'can create product, attributes and variations', async ( { page, } ) => { - await page.goto( productPageURL ); - await page.fill( '#title', variableProductName ); - await page.selectOption( '#product-type', 'variable' ); + await test.step( 'Go to "Products > Add New page".', async () => { + await page.goto( productPageURL ); + } ); - await page - .locator( '.attribute_tab' ) - .getByRole( 'link', { name: 'Attributes' } ) - .scrollIntoViewIfNeeded(); + await test.step( + `Type "${ variableProductName }" into the "Product name" input field.`, + async () => { + await page.fill( '#title', variableProductName ); + } + ); + + await test.step( + 'Select the "Variable product" product type.', + async () => { + await page.selectOption( '#product-type', 'variable' ); + } + ); + + await test.step( 'Click on the "Attributes" tab.', async () => { + await page + .locator( '.attribute_tab' ) + .getByRole( 'link', { name: 'Attributes' } ) + .scrollIntoViewIfNeeded(); + } ); // the tour only seems to display when not running headless, so just make sure - if ( await page.locator( '.woocommerce-tour-kit-step__heading' ).isVisible() ) { - // dismiss the variable product tour - await page - .getByRole( 'button', { name: 'Close Tour' } ) - .click(); - - // wait for the tour's dismissal to be saved - await page.waitForResponse( - ( response ) => - response.url().includes( '/users/' ) && - response.status() === 200 - ); - } - - await page.click( 'a[href="#product_attributes"]' ); - - // add 3 attributes - for ( let i = 0; i < 3; i++ ) { - if ( i > 0 ) { - await page.getByRole( 'button', { name: 'Add' } ) - .nth(2) - .click(); + const tourWasDisplayed = await test.step( + 'See if the tour was displayed.', + async () => { + return await page + .locator( '.woocommerce-tour-kit-step__heading' ) + .isVisible(); } - await page.waitForSelector( - `input[name="attribute_names[${ i }]"]` + ); + + if ( tourWasDisplayed ) { + await test.step( 'Tour was displayed, so dismiss it.', async () => { + await page + .getByRole( 'button', { name: 'Close Tour' } ) + .click(); + } ); + + await test.step( + "Wait for the tour's dismissal to be saved", + async () => { + await page.waitForResponse( + ( response ) => + response.url().includes( '/users/' ) && + response.status() === 200 + ); + } ); - - await page - .locator( `input[name="attribute_names[${ i }]"]` ) - .first() - .type( `attr #${ i + 1 }` ); - await page - .locator( `textarea[name="attribute_values[${ i }]"]` ) - .first() - .type( 'val1 | val2' ); } - await page.getByRole( 'button', { name: 'Save attributes'} ).click( { clickCount: 3 }); + await test.step( 'Add 3 attributes.', async () => { + for ( let i = 0; i < 3; i++ ) { + if ( i > 0 ) { + await test.step( "Click 'Add'.", async () => { + await page + .locator( '.add-attribute-container' ) + .getByRole( 'button', { name: 'Add' } ) + .click(); + } ); + } - // wait for the tour's dismissal to be saved - await page.waitForResponse( - ( response ) => - response.url().includes( '/post.php' ) && - response.status() === 200 - ); + await test.step( + `Add the attribute "attr #${ + i + 1 + }" with values "val1 | val2"`, + async () => { + await test.step( + 'Wait for the "Attribute name" input field to appear.', + async () => { + await page.waitForSelector( + `input[name="attribute_names[${ i }]"]` + ); + } + ); - // Save before going to the Variations tab to prevent variations from all attributes to be automatically created - await page.locator( '#save-post' ).click(); - await expect( - page.getByText( 'Product draft updated. ' ) - ).toBeVisible(); + await test.step( + `Type "attr #${ + i + 1 + }" in the "Attribute name" input field.`, + async () => { + await page + .locator( + `input[name="attribute_names[${ i }]"]` + ) + .first() + .type( `attr #${ i + 1 }` ); + } + ); - await page.click( 'a[href="#variable_product_options"]' ); + await test.step( + 'Type the attribute values "val1 | val2".', + async () => { + await page + .locator( + `textarea[name="attribute_values[${ i }]"]` + ) + .first() + .type( 'val1 | val2' ); + } + ); - // event listener for handling the link_all_variations confirmation dialog - page.on( 'dialog', ( dialog ) => dialog.accept() ); + await test.step( + 'Click "Save attributes".', + async () => { + await page + .getByRole( 'button', { + name: 'Save attributes', + } ) + .click( { clickCount: 3 } ); + } + ); - // generate variations from all attributes - await page.click( 'button.generate_variations' ); - - // verify variations have the correct attribute values - for ( let i = 0; i < 8; i++ ) { - const val1 = 'val1'; - const val2 = 'val2'; - const attr3 = !! ( i % 2 ); // 0-1,4-5 / 2-3,6-7 - const attr2 = i % 4 > 1; // 0-3 / 4-7 - const attr1 = i > 3; - await expect( - page.locator( `select[name="attribute_attr-1[${ i }]"]` ) - ).toHaveValue( attr1 ? val2 : val1 ); - await expect( - page.locator( `select[name="attribute_attr-2[${ i }]"]` ) - ).toHaveValue( attr2 ? val2 : val1 ); - await expect( - page.locator( `select[name="attribute_attr-3[${ i }]"]` ) - ).toHaveValue( attr3 ? val2 : val1 ); - } - - await page.locator( '#save-post' ).click(); - await expect( page.locator( '#message.notice-success' ) ).toContainText( - 'Product draft updated.' - ); - - // set variation attributes and bulk edit variations - await page.click( 'a[href="#variable_product_options"]' ); - - // set the variation attributes - await page.click( - '#variable_product_options .toolbar-top a.expand_all' - ); - await page.check( 'input[name="variable_is_virtual[0]"]' ); - await page.fill( - 'input[name="variable_regular_price[0]"]', - variationOnePrice - ); - await page.check( 'input[name="variable_is_virtual[1]"]' ); - await page.fill( - 'input[name="variable_regular_price[1]"]', - variationTwoPrice - ); - await page.check( 'input[name="variable_manage_stock[2]"]' ); - await page.fill( - 'input[name="variable_regular_price[2]"]', - variationThreePrice - ); - await page.fill( 'input[name="variable_weight[2]"]', productWeight ); - await page.fill( 'input[name="variable_length[2]"]', productLength ); - await page.fill( 'input[name="variable_width[2]"]', productWidth ); - await page.fill( 'input[name="variable_height[2]"]', productHeight ); - await page.keyboard.press( 'ArrowUp' ); - await page.click( 'button.save-variation-changes' ); - - // bulk-edit variations - await page.click( - '#variable_product_options .toolbar-top a.expand_all' - ); - for ( let i = 0; i < 4; i++ ) { - const checkBox = page.locator( - `input[name="variable_is_downloadable[${ i }]"]` - ); - await expect( checkBox ).not.toBeChecked(); - } - await page.selectOption( '#field_to_edit', 'toggle_downloadable', { - force: true, + await test.step( + "Wait for the tour's dismissal to be saved", + async () => { + await page.waitForResponse( + ( response ) => + response + .url() + .includes( '/post.php' ) && + response.status() === 200 + ); + } + ); + } + ); + } } ); - await page.click( - '#variable_product_options .toolbar-top a.expand_all' + + await test.step( + 'Save before going to the Variations tab to prevent variations from all attributes to be automatically created.', + async () => { + await page.locator( '#save-post' ).click(); + } ); - for ( let i = 0; i < 4; i++ ) { - const checkBox = await page.locator( - `input[name="variable_is_downloadable[${ i }]"]` - ); - await expect( checkBox ).toBeChecked(); - } - await page.locator( '#save-post' ).click(); + await test.step( + 'Expect the "Product draft updated." notice to appear.', + async () => { + await expect( + page.getByText( 'Product draft updated. ' ) + ).toBeVisible(); + } + ); - // delete all variations - await page.click( 'a[href="#variable_product_options"]' ); - await page.waitForLoadState( 'networkidle' ); - await page.selectOption( '#field_to_edit', 'delete_all' ); - await page.waitForSelector( '.woocommerce_variation', { - state: 'detached', + await test.step( 'Click on the "Variations" tab.', async () => { + await page.click( 'a[href="#variable_product_options"]' ); } ); - const variationsCount = await page.$$( '.woocommerce_variation' ); - await expect( variationsCount ).toHaveLength( 0 ); + + await test.step( + 'Create event listener for handling the link_all_variations confirmation dialog.', + async () => { + page.on( 'dialog', ( dialog ) => dialog.accept() ); + } + ); + + await test.step( + 'Click on the "Generate variations" button.', + async () => { + await page.click( 'button.generate_variations' ); + } + ); + + await test.step( + 'Expect variations to have the correct attribute values', + async () => { + for ( let i = 0; i < 8; i++ ) { + const val1 = 'val1'; + const val2 = 'val2'; + const attr3 = !! ( i % 2 ); // 0-1,4-5 / 2-3,6-7 + const attr2 = i % 4 > 1; // 0-3 / 4-7 + const attr1 = i > 3; + await expect( + page.locator( + `select[name="attribute_attr-1[${ i }]"]` + ) + ).toHaveValue( attr1 ? val2 : val1 ); + await expect( + page.locator( + `select[name="attribute_attr-2[${ i }]"]` + ) + ).toHaveValue( attr2 ? val2 : val1 ); + await expect( + page.locator( + `select[name="attribute_attr-3[${ i }]"]` + ) + ).toHaveValue( attr3 ? val2 : val1 ); + } + } + ); + + await test.step( 'Click "Save Draft" button.', async () => { + await page.locator( '#save-post' ).click(); + } ); + + await test.step( + 'Expect the "Product draft updated." notice to appear.', + async () => { + await expect( + page.locator( '#message.notice-success' ) + ).toContainText( 'Product draft updated.' ); + } + ); } ); test( 'can manually add a variation, manage stock levels, set variation defaults and remove a variation', async ( { @@ -249,11 +461,13 @@ test.describe( 'Add New Variable Product Page', () => { .scrollIntoViewIfNeeded(); // the tour only seems to display when not running headless, so just make sure - if ( await page.locator( '.woocommerce-tour-kit-step__heading' ).isVisible() ) { - // dismiss the variable product tour + if ( await page - .getByRole( 'button', { name: 'Close Tour' } ) - .click(); + .locator( '.woocommerce-tour-kit-step__heading' ) + .isVisible() + ) { + // dismiss the variable product tour + await page.getByRole( 'button', { name: 'Close Tour' } ).click(); // wait for the tour's dismissal to be saved await page.waitForResponse( From caa6af608dcabdf86af9e975ad9c8672bc92a1f6 Mon Sep 17 00:00:00 2001 From: rodelgc Date: Fri, 14 Apr 2023 15:24:07 +0800 Subject: [PATCH 2/8] Add changelog --- plugins/woocommerce/changelog/e2e-split-variable-product-test | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 plugins/woocommerce/changelog/e2e-split-variable-product-test diff --git a/plugins/woocommerce/changelog/e2e-split-variable-product-test b/plugins/woocommerce/changelog/e2e-split-variable-product-test new file mode 100644 index 00000000000..9c587cb0eaa --- /dev/null +++ b/plugins/woocommerce/changelog/e2e-split-variable-product-test @@ -0,0 +1,4 @@ +Significance: patch +Type: dev + +Split can create product, attributes and variations, edit variations and delete variations into smaller tests to avoid timing out From e76f452d351991607e181efdfb28ecea99239889 Mon Sep 17 00:00:00 2001 From: rodelgc Date: Fri, 14 Apr 2023 17:26:58 +0800 Subject: [PATCH 3/8] Split into smaller tests --- .../merchant/create-variable-product.spec.js | 461 +++++++++++------- 1 file changed, 285 insertions(+), 176 deletions(-) diff --git a/plugins/woocommerce/tests/e2e-pw/tests/merchant/create-variable-product.spec.js b/plugins/woocommerce/tests/e2e-pw/tests/merchant/create-variable-product.spec.js index 3b649244732..9d5475437a8 100644 --- a/plugins/woocommerce/tests/e2e-pw/tests/merchant/create-variable-product.spec.js +++ b/plugins/woocommerce/tests/e2e-pw/tests/merchant/create-variable-product.spec.js @@ -16,6 +16,8 @@ const defaultAttributes = [ 'val2', 'val1', 'val2' ]; const stockAmount = '100'; const lowStockAmount = '10'; +let variableProductId; + async function deleteProductsAddedByTests( baseURL ) { const api = new wcApi( { url: baseURL, @@ -67,7 +69,7 @@ async function resetVariableProductTour( baseURL, browser ) { ); } -test.describe.serial( 'Add New Variable Product Page', () => { +test.describe( 'Add New Variable Product Page', () => { test.use( { storageState: process.env.ADMINSTATE } ); test.afterAll( async ( { baseURL, browser } ) => { @@ -75,167 +77,6 @@ test.describe.serial( 'Add New Variable Product Page', () => { await resetVariableProductTour( baseURL, browser ); } ); - // test( 'can create product, attributes and variations, edit variations and delete variations', async ( { - // page, - // } ) => { - // await page.goto( productPageURL ); - // await page.fill( '#title', variableProductName ); - // await page.selectOption( '#product-type', 'variable' ); - - // await page - // .locator( '.attribute_tab' ) - // .getByRole( 'link', { name: 'Attributes' } ) - // .scrollIntoViewIfNeeded(); - - // // the tour only seems to display when not running headless, so just make sure - // if ( await page.locator( '.woocommerce-tour-kit-step__heading' ).isVisible() ) { - // // dismiss the variable product tour - // await page - // .getByRole( 'button', { name: 'Close Tour' } ) - // .click(); - - // // wait for the tour's dismissal to be saved - // await page.waitForResponse( - // ( response ) => - // response.url().includes( '/users/' ) && - // response.status() === 200 - // ); - // } - - // await page.click( 'a[href="#product_attributes"]' ); - - // // add 3 attributes - // for ( let i = 0; i < 3; i++ ) { - // if ( i > 0 ) { - // await page.getByRole( 'button', { name: 'Add' } ) - // .nth(2) - // .click(); - // } - // await page.waitForSelector( - // `input[name="attribute_names[${ i }]"]` - // ); - - // await page - // .locator( `input[name="attribute_names[${ i }]"]` ) - // .first() - // .type( `attr #${ i + 1 }` ); - // await page - // .locator( `textarea[name="attribute_values[${ i }]"]` ) - // .first() - // .type( 'val1 | val2' ); - // } - - // await page.getByRole( 'button', { name: 'Save attributes'} ).click( { clickCount: 3 }); - - // // wait for the tour's dismissal to be saved - // await page.waitForResponse( - // ( response ) => - // response.url().includes( '/post.php' ) && - // response.status() === 200 - // ); - - // // Save before going to the Variations tab to prevent variations from all attributes to be automatically created - // await page.locator( '#save-post' ).click(); - // await expect( - // page.getByText( 'Product draft updated. ' ) - // ).toBeVisible(); - - // await page.click( 'a[href="#variable_product_options"]' ); - - // // event listener for handling the link_all_variations confirmation dialog - // page.on( 'dialog', ( dialog ) => dialog.accept() ); - - // // generate variations from all attributes - // await page.click( 'button.generate_variations' ); - - // // verify variations have the correct attribute values - // for ( let i = 0; i < 8; i++ ) { - // const val1 = 'val1'; - // const val2 = 'val2'; - // const attr3 = !! ( i % 2 ); // 0-1,4-5 / 2-3,6-7 - // const attr2 = i % 4 > 1; // 0-3 / 4-7 - // const attr1 = i > 3; - // await expect( - // page.locator( `select[name="attribute_attr-1[${ i }]"]` ) - // ).toHaveValue( attr1 ? val2 : val1 ); - // await expect( - // page.locator( `select[name="attribute_attr-2[${ i }]"]` ) - // ).toHaveValue( attr2 ? val2 : val1 ); - // await expect( - // page.locator( `select[name="attribute_attr-3[${ i }]"]` ) - // ).toHaveValue( attr3 ? val2 : val1 ); - // } - - // await page.locator( '#save-post' ).click(); - // await expect( page.locator( '#message.notice-success' ) ).toContainText( - // 'Product draft updated.' - // ); - - // // set variation attributes and bulk edit variations - // await page.click( 'a[href="#variable_product_options"]' ); - - // // set the variation attributes - // await page.click( - // '#variable_product_options .toolbar-top a.expand_all' - // ); - // await page.check( 'input[name="variable_is_virtual[0]"]' ); - // await page.fill( - // 'input[name="variable_regular_price[0]"]', - // variationOnePrice - // ); - // await page.check( 'input[name="variable_is_virtual[1]"]' ); - // await page.fill( - // 'input[name="variable_regular_price[1]"]', - // variationTwoPrice - // ); - // await page.check( 'input[name="variable_manage_stock[2]"]' ); - // await page.fill( - // 'input[name="variable_regular_price[2]"]', - // variationThreePrice - // ); - // await page.fill( 'input[name="variable_weight[2]"]', productWeight ); - // await page.fill( 'input[name="variable_length[2]"]', productLength ); - // await page.fill( 'input[name="variable_width[2]"]', productWidth ); - // await page.fill( 'input[name="variable_height[2]"]', productHeight ); - // await page.keyboard.press( 'ArrowUp' ); - // await page.click( 'button.save-variation-changes' ); - - // // bulk-edit variations - // await page.click( - // '#variable_product_options .toolbar-top a.expand_all' - // ); - // for ( let i = 0; i < 4; i++ ) { - // const checkBox = page.locator( - // `input[name="variable_is_downloadable[${ i }]"]` - // ); - // await expect( checkBox ).not.toBeChecked(); - // } - // await page.selectOption( '#field_to_edit', 'toggle_downloadable', { - // force: true, - // } ); - // await page.click( - // '#variable_product_options .toolbar-top a.expand_all' - // ); - // for ( let i = 0; i < 4; i++ ) { - // const checkBox = await page.locator( - // `input[name="variable_is_downloadable[${ i }]"]` - // ); - // await expect( checkBox ).toBeChecked(); - // } - - // await page.locator( '#save-post' ).click(); - - // // delete all variations - // await page.click( 'a[href="#variable_product_options"]' ); - // await page.waitForLoadState( 'networkidle' ); - // await page.selectOption( '#field_to_edit', 'delete_all' ); - // await page.waitForSelector( '.woocommerce_variation', { - // state: 'detached', - // } ); - // const variationsCount = await page.$$( '.woocommerce_variation' ); - // await expect( variationsCount ).toHaveLength( 0 ); - // } ); - test( 'can create product, attributes and variations', async ( { page, } ) => { @@ -257,12 +98,20 @@ test.describe.serial( 'Add New Variable Product Page', () => { } ); - await test.step( 'Click on the "Attributes" tab.', async () => { - await page - .locator( '.attribute_tab' ) - .getByRole( 'link', { name: 'Attributes' } ) - .scrollIntoViewIfNeeded(); - } ); + await test.step( + 'Scroll into the "Attributes" tab and click it.', + async () => { + await page + .locator( '.attribute_tab' ) + .getByRole( 'link', { name: 'Attributes' } ) + .scrollIntoViewIfNeeded(); + + await page + .locator( '.attribute_tab' ) + .getByRole( 'link', { name: 'Attributes' } ) + .click(); + } + ); // the tour only seems to display when not running headless, so just make sure const tourWasDisplayed = await test.step( @@ -388,20 +237,23 @@ test.describe.serial( 'Add New Variable Product Page', () => { } ); + await test.step( 'Save the product ID.', async () => { + variableProductId = page + .url() + .match( /post=\d+/ )[ 0 ] + .replace( 'post=', '' ); + } ); + await test.step( 'Click on the "Variations" tab.', async () => { await page.click( 'a[href="#variable_product_options"]' ); } ); - await test.step( - 'Create event listener for handling the link_all_variations confirmation dialog.', - async () => { - page.on( 'dialog', ( dialog ) => dialog.accept() ); - } - ); - await test.step( 'Click on the "Generate variations" button.', async () => { + // event listener for handling the link_all_variations confirmation dialog + page.on( 'dialog', ( dialog ) => dialog.accept() ); + await page.click( 'button.generate_variations' ); } ); @@ -448,7 +300,264 @@ test.describe.serial( 'Add New Variable Product Page', () => { ); } ); - test( 'can manually add a variation, manage stock levels, set variation defaults and remove a variation', async ( { + test( 'can individually edit variations', async ( { page } ) => { + // mytodo setup: create variable product with the same attributes and variations + + await test.step( 'Go to the "Edit product" page.', async () => { + await page.goto( + `/wp-admin/post.php?post=${ variableProductId }&action=edit` + ); + } ); + + await test.step( 'Click on the "Variations" tab.', async () => { + await page.click( 'a[href="#variable_product_options"]' ); + } ); + + await test.step( 'Expand all variations.', async () => { + await page.click( + '#variable_product_options .toolbar-top a.expand_all' + ); + } ); + + await test.step( 'Set the first variation to be virtual.', async () => { + await page.check( 'input[name="variable_is_virtual[0]"]' ); + } ); + + await test.step( + `Set regular price of first variation to ${ variationOnePrice }.`, + async () => { + await page.fill( + 'input[name="variable_regular_price[0]"]', + variationOnePrice + ); + } + ); + + await test.step( + 'Set the second variation to be virtual.', + async () => { + await page.check( 'input[name="variable_is_virtual[1]"]' ); + } + ); + + await test.step( + `Set regular price of second variation to ${ variationTwoPrice }.`, + async () => { + await page.fill( + 'input[name="variable_regular_price[1]"]', + variationTwoPrice + ); + } + ); + + await test.step( + 'Check "Manage stock?" in the third variation.', + async () => { + await page.check( 'input[name="variable_manage_stock[2]"]' ); + } + ); + + await test.step( + `Set regular price of third variation to ${ variationThreePrice }.`, + async () => { + await page.fill( + 'input[name="variable_regular_price[2]"]', + variationThreePrice + ); + } + ); + + await test.step( + 'Set the weight and dimensions of the third variation.', + async () => { + await page.fill( + 'input[name="variable_weight[2]"]', + productWeight + ); + await page.fill( + 'input[name="variable_length[2]"]', + productLength + ); + await page.fill( + 'input[name="variable_width[2]"]', + productWidth + ); + await page.fill( + 'input[name="variable_height[2]"]', + productHeight + ); + await page.keyboard.press( 'ArrowUp' ); + } + ); + + await test.step( 'Click "Save changes".', async () => { + await page.click( 'button.save-variation-changes' ); + await page.waitForLoadState( 'networkidle' ); + } ); + + await test.step( 'Click on the "Variations" tab.', async () => { + await page.click( 'a[href="#variable_product_options"]' ); + } ); + + await test.step( 'Expand all variations.', async () => { + await page.click( + '#variable_product_options .toolbar-top a.expand_all' + ); + } ); + + await test.step( + 'Expect the first variation to be virtual.', + async () => { + await expect( + page.locator( 'input[name="variable_is_virtual[0]"]' ) + ).toBeChecked(); + } + ); + + await test.step( + `Expect the price of the first variation to be ${ variationOnePrice }.`, + async () => { + await expect( + page.locator( 'input[name="variable_regular_price[0]"]' ) + ).toHaveValue( variationOnePrice ); + } + ); + + await test.step( + 'Expect the second variation to be virtual.', + async () => { + await expect( + page.locator( 'input[name="variable_is_virtual[1]"]' ) + ).toBeChecked(); + } + ); + + await test.step( + `Expect the price of the second variation to be ${ variationTwoPrice }.`, + async () => { + await expect( + page.locator( 'input[name="variable_regular_price[1]"]' ) + ).toHaveValue( variationTwoPrice ); + } + ); + + await test.step( + 'Expect the "Manage stock?" checkbox of the third variation to be checked.', + async () => { + await expect( + page.locator( 'input[name="variable_manage_stock[2]"]' ) + ).toBeChecked(); + } + ); + + await test.step( + `Expect the price of the third variation to be ${ variationThreePrice }.`, + async () => { + await expect( + page.locator( 'input[name="variable_regular_price[2]"]' ) + ).toHaveValue( variationThreePrice ); + } + ); + + await test.step( + 'Expect the weight and dimensions of the third variation to be correct.', + async () => { + await expect( + page.locator( 'input[name="variable_weight[2]"]' ) + ).toHaveValue( productWeight ); + + await expect( + page.locator( 'input[name="variable_length[2]"]' ) + ).toHaveValue( productLength ); + + await expect( + page.locator( 'input[name="variable_width[2]"]' ) + ).toHaveValue( productWidth ); + + await expect( + page.locator( 'input[name="variable_height[2]"]' ) + ).toHaveValue( productHeight ); + } + ); + } ); + + test( 'can bulk edit variations', async ( { page } ) => { + // mytodo setup: create variable product with the same attributes and variations + + await test.step( 'Go to the "Edit product" page.', async () => { + await page.goto( + `/wp-admin/post.php?post=${ variableProductId }&action=edit` + ); + } ); + + await test.step( 'Click on the "Variations" tab.', async () => { + await page.click( 'a[href="#variable_product_options"]' ); + } ); + + await test.step( + 'Select the \'Toggle "Downloadable"\' bulk action.', + async () => { + await page.selectOption( + '#field_to_edit', + 'toggle_downloadable' + ); + } + ); + + await test.step( 'Expand all variations.', async () => { + await page.click( + '#variable_product_options .toolbar-top a.expand_all' + ); + } ); + + await test.step( + 'Expect all "Downloadable" checkboxes to be checked.', + async () => { + const checkBoxes = page.locator( + 'input[name^="variable_is_downloadable"]' + ); + const count = await checkBoxes.count(); + + for ( let i = 0; i < count; i++ ) { + await expect( checkBoxes.nth( i ) ).toBeChecked(); + } + } + ); + } ); + + test( 'can delete all variations', async ( { page } ) => { + // mytodo setup: create variable product with the same attributes and variations + + await test.step( 'Go to the "Edit product" page.', async () => { + await page.goto( + `/wp-admin/post.php?post=${ variableProductId }&action=edit` + ); + } ); + + await test.step( 'Click on the "Variations" tab.', async () => { + await page.click( 'a[href="#variable_product_options"]' ); + } ); + + await test.step( + 'Select the bulk action "Delete all variations".', + async () => { + page.on( 'dialog', ( dialog ) => dialog.accept() ); + await page.selectOption( '#field_to_edit', 'delete_all' ); + } + ); + + await test.step( + 'Expect that there are no more variations.', + async () => { + await expect( + page.locator( '.woocommerce_variation' ) + ).toHaveCount( 0 ); + } + ); + } ); + + // mytodo remove skip + test.skip( 'can manually add a variation, manage stock levels, set variation defaults and remove a variation', async ( { page, } ) => { await page.goto( productPageURL ); From 4262cd99abfd3e42c8e6483411ff3e0c8f1c9a67 Mon Sep 17 00:00:00 2001 From: rodelgc Date: Fri, 14 Apr 2023 23:14:08 +0800 Subject: [PATCH 4/8] Use a fixed variable product as test data to eliminate inter-dependence between tests --- .../merchant/create-variable-product.spec.js | 335 ++++++++++++------ 1 file changed, 233 insertions(+), 102 deletions(-) diff --git a/plugins/woocommerce/tests/e2e-pw/tests/merchant/create-variable-product.spec.js b/plugins/woocommerce/tests/e2e-pw/tests/merchant/create-variable-product.spec.js index 9d5475437a8..e3a42fa457b 100644 --- a/plugins/woocommerce/tests/e2e-pw/tests/merchant/create-variable-product.spec.js +++ b/plugins/woocommerce/tests/e2e-pw/tests/merchant/create-variable-product.spec.js @@ -16,7 +16,8 @@ const defaultAttributes = [ 'val2', 'val1', 'val2' ]; const stockAmount = '100'; const lowStockAmount = '10'; -let variableProductId; +let fixedVariableProductId; +let fixedVariationIds; async function deleteProductsAddedByTests( baseURL ) { const api = new wcApi( { @@ -36,8 +37,10 @@ async function deleteProductsAddedByTests( baseURL ) { const ids = varProducts .map( ( { id } ) => id ) - .concat( manualProducts.map( ( { id } ) => id ) ); + .concat( manualProducts.map( ( { id } ) => id ) ) + .push( fixedVariableProductId ); // mytodo why not being deleted? + console.log( `ids to delete: ${ ids }` ); // mytodo delete await api.post( 'products/batch', { delete: ids } ); } @@ -69,9 +72,125 @@ async function resetVariableProductTour( baseURL, browser ) { ); } +async function createVariableProductFixture( baseURL ) { + const api = new wcApi( { + url: baseURL, + consumerKey: process.env.CONSUMER_KEY, + consumerSecret: process.env.CONSUMER_SECRET, + version: 'wc/v3', + } ); + + const createVariableProductRequestPayload = { + name: 'Unbranded Granite Shirt', + type: 'variable', + attributes: [ + { + name: 'Colour', + visible: true, + variation: true, + options: [ 'Red', 'Green' ], + }, + { + name: 'Size', + visible: true, + variation: true, + options: [ 'Small', 'Medium' ], + }, + { + name: 'Logo', + visible: true, + variation: true, + options: [ 'Woo', 'WordPress' ], + }, + ], + }; + + const batchCreateVariationsPayload = { + create: [ + { + attributes: [ + { name: 'Colour', option: 'Red' }, + { name: 'Size', option: 'Small' }, + { name: 'Logo', option: 'Woo' }, + ], + }, + { + attributes: [ + { name: 'Colour', option: 'Red' }, + { name: 'Size', option: 'Small' }, + { name: 'Logo', option: 'WordPress' }, + ], + }, + { + attributes: [ + { name: 'Colour', option: 'Red' }, + { name: 'Size', option: 'Medium' }, + { name: 'Logo', option: 'Woo' }, + ], + }, + { + attributes: [ + { name: 'Colour', option: 'Red' }, + { name: 'Size', option: 'Medium' }, + { name: 'Logo', option: 'WordPress' }, + ], + }, + { + attributes: [ + { name: 'Colour', option: 'Green' }, + { name: 'Size', option: 'Small' }, + { name: 'Logo', option: 'Woo' }, + ], + }, + { + attributes: [ + { name: 'Colour', option: 'Green' }, + { name: 'Size', option: 'Small' }, + { name: 'Logo', option: 'WordPress' }, + ], + }, + { + attributes: [ + { name: 'Colour', option: 'Green' }, + { name: 'Size', option: 'Medium' }, + { name: 'Logo', option: 'Woo' }, + ], + }, + { + attributes: [ + { name: 'Colour', option: 'Green' }, + { name: 'Size', option: 'Medium' }, + { name: 'Logo', option: 'WordPress' }, + ], + }, + ], + }; + + await api + .post( 'products', createVariableProductRequestPayload ) + .then( ( response ) => { + fixedVariableProductId = response.data.id; + } ); + + await api + .post( + `products/${ fixedVariableProductId }/variations/batch`, + batchCreateVariationsPayload + ) + .then( ( response ) => { + fixedVariationIds = response.data.create + .map( ( variation ) => variation.id ) + .sort(); + } ); +} + test.describe( 'Add New Variable Product Page', () => { test.use( { storageState: process.env.ADMINSTATE } ); + test.beforeAll( async ( { baseURL } ) => { + await createVariableProductFixture( baseURL ); + } ); + test.afterAll( async ( { baseURL, browser } ) => { await deleteProductsAddedByTests( baseURL ); await resetVariableProductTour( baseURL, browser ); @@ -101,15 +220,13 @@ test.describe( 'Add New Variable Product Page', () => { await test.step( 'Scroll into the "Attributes" tab and click it.', async () => { - await page + const attributesTab = page .locator( '.attribute_tab' ) - .getByRole( 'link', { name: 'Attributes' } ) - .scrollIntoViewIfNeeded(); + .getByRole( 'link', { name: 'Attributes' } ); - await page - .locator( '.attribute_tab' ) - .getByRole( 'link', { name: 'Attributes' } ) - .click(); + await attributesTab.scrollIntoViewIfNeeded(); + + await attributesTab.click(); } ); @@ -237,13 +354,6 @@ test.describe( 'Add New Variable Product Page', () => { } ); - await test.step( 'Save the product ID.', async () => { - variableProductId = page - .url() - .match( /post=\d+/ )[ 0 ] - .replace( 'post=', '' ); - } ); - await test.step( 'Click on the "Variations" tab.', async () => { await page.click( 'a[href="#variable_product_options"]' ); } ); @@ -301,11 +411,20 @@ test.describe( 'Add New Variable Product Page', () => { } ); test( 'can individually edit variations', async ( { page } ) => { - // mytodo setup: create variable product with the same attributes and variations + const variationRows = page.locator( '.woocommerce_variation' ); + const firstVariation = variationRows.filter( { + hasText: `#${ fixedVariationIds[ 0 ] }`, + } ); + const secondVariation = variationRows.filter( { + hasText: `#${ fixedVariationIds[ 1 ] }`, + } ); + const thirdVariation = variationRows.filter( { + hasText: `#${ fixedVariationIds[ 2 ] }`, + } ); await test.step( 'Go to the "Edit product" page.', async () => { await page.goto( - `/wp-admin/post.php?post=${ variableProductId }&action=edit` + `/wp-admin/post.php?post=${ fixedVariableProductId }&action=edit` ); } ); @@ -319,76 +438,81 @@ test.describe( 'Add New Variable Product Page', () => { ); } ); - await test.step( 'Set the first variation to be virtual.', async () => { - await page.check( 'input[name="variable_is_virtual[0]"]' ); + await test.step( 'Edit the first variation.', async () => { + await test.step( 'Check the "Virtual" checkbox.', async () => { + await firstVariation + .getByRole( 'checkbox', { + name: 'Virtual', + } ) + .check(); + } ); + + await test.step( + `Set regular price to "${ variationOnePrice }".`, + async () => { + await firstVariation + .getByRole( 'textbox', { name: 'Regular price' } ) + .fill( variationOnePrice ); + } + ); } ); - await test.step( - `Set regular price of first variation to ${ variationOnePrice }.`, - async () => { - await page.fill( - 'input[name="variable_regular_price[0]"]', - variationOnePrice - ); - } - ); + await test.step( 'Edit the second variation.', async () => { + await test.step( 'Check the "Virtual" checkbox.', async () => { + await secondVariation + .getByRole( 'checkbox', { + name: 'Virtual', + } ) + .check(); + } ); - await test.step( - 'Set the second variation to be virtual.', - async () => { - await page.check( 'input[name="variable_is_virtual[1]"]' ); - } - ); + await test.step( + `Set regular price to "${ variationTwoPrice }".`, + async () => { + await secondVariation + .getByRole( 'textbox', { name: 'Regular price' } ) + .fill( variationTwoPrice ); + } + ); + } ); - await test.step( - `Set regular price of second variation to ${ variationTwoPrice }.`, - async () => { - await page.fill( - 'input[name="variable_regular_price[1]"]', - variationTwoPrice - ); - } - ); + await test.step( 'Edit the third variation.', async () => { + await test.step( 'Check "Manage stock?"', async () => { + await thirdVariation + .getByRole( 'checkbox', { name: 'Manage stock?' } ) + .check(); + } ); - await test.step( - 'Check "Manage stock?" in the third variation.', - async () => { - await page.check( 'input[name="variable_manage_stock[2]"]' ); - } - ); + await test.step( + `Set regular price to "${ variationThreePrice }".`, + async () => { + await thirdVariation + .getByRole( 'textbox', { name: 'Regular price' } ) + .fill( variationThreePrice ); + } + ); - await test.step( - `Set regular price of third variation to ${ variationThreePrice }.`, - async () => { - await page.fill( - 'input[name="variable_regular_price[2]"]', - variationThreePrice - ); - } - ); + await test.step( + 'Set the weight and dimensions.', + async () => { + await thirdVariation + .getByRole( 'textbox', { name: 'Weight' } ) + .type( productWeight ); - await test.step( - 'Set the weight and dimensions of the third variation.', - async () => { - await page.fill( - 'input[name="variable_weight[2]"]', - productWeight - ); - await page.fill( - 'input[name="variable_length[2]"]', - productLength - ); - await page.fill( - 'input[name="variable_width[2]"]', - productWidth - ); - await page.fill( - 'input[name="variable_height[2]"]', - productHeight - ); - await page.keyboard.press( 'ArrowUp' ); - } - ); + await thirdVariation + .getByRole( 'textbox', { name: 'Length' } ) + .type( productLength ); + + await thirdVariation + .getByRole( 'textbox', { name: 'Width' } ) + .type( productWidth ); + + await thirdVariation + .getByRole( 'textbox', { name: 'Height' } ) + .type( productHeight ); + } + ); + } ); await test.step( 'Click "Save changes".', async () => { await page.click( 'button.save-variation-changes' ); @@ -409,16 +533,20 @@ test.describe( 'Add New Variable Product Page', () => { 'Expect the first variation to be virtual.', async () => { await expect( - page.locator( 'input[name="variable_is_virtual[0]"]' ) + firstVariation.getByRole( 'checkbox', { + name: 'Virtual', + } ) ).toBeChecked(); } ); await test.step( - `Expect the price of the first variation to be ${ variationOnePrice }.`, + `Expect the regular price of the first variation to be "${ variationOnePrice }".`, async () => { await expect( - page.locator( 'input[name="variable_regular_price[0]"]' ) + firstVariation.getByRole( 'textbox', { + name: 'Regular price', + } ) ).toHaveValue( variationOnePrice ); } ); @@ -427,16 +555,20 @@ test.describe( 'Add New Variable Product Page', () => { 'Expect the second variation to be virtual.', async () => { await expect( - page.locator( 'input[name="variable_is_virtual[1]"]' ) + secondVariation.getByRole( 'checkbox', { + name: 'Virtual', + } ) ).toBeChecked(); } ); await test.step( - `Expect the price of the second variation to be ${ variationTwoPrice }.`, + `Expect the regular price of the second variation to be "${ variationTwoPrice }".`, async () => { await expect( - page.locator( 'input[name="variable_regular_price[1]"]' ) + secondVariation.getByRole( 'textbox', { + name: 'Regular price', + } ) ).toHaveValue( variationTwoPrice ); } ); @@ -445,16 +577,20 @@ test.describe( 'Add New Variable Product Page', () => { 'Expect the "Manage stock?" checkbox of the third variation to be checked.', async () => { await expect( - page.locator( 'input[name="variable_manage_stock[2]"]' ) + thirdVariation.getByRole( 'checkbox', { + name: 'Manage stock?', + } ) ).toBeChecked(); } ); await test.step( - `Expect the price of the third variation to be ${ variationThreePrice }.`, + `Expect the regular price of the third variation to be "${ variationThreePrice }".`, async () => { await expect( - page.locator( 'input[name="variable_regular_price[2]"]' ) + thirdVariation.getByRole( 'textbox', { + name: 'Regular price', + } ) ).toHaveValue( variationThreePrice ); } ); @@ -463,30 +599,28 @@ test.describe( 'Add New Variable Product Page', () => { 'Expect the weight and dimensions of the third variation to be correct.', async () => { await expect( - page.locator( 'input[name="variable_weight[2]"]' ) + thirdVariation.getByRole( 'textbox', { name: 'Weight' } ) ).toHaveValue( productWeight ); await expect( - page.locator( 'input[name="variable_length[2]"]' ) + thirdVariation.getByRole( 'textbox', { name: 'Length' } ) ).toHaveValue( productLength ); await expect( - page.locator( 'input[name="variable_width[2]"]' ) + thirdVariation.getByRole( 'textbox', { name: 'Width' } ) ).toHaveValue( productWidth ); await expect( - page.locator( 'input[name="variable_height[2]"]' ) + thirdVariation.getByRole( 'textbox', { name: 'Height' } ) ).toHaveValue( productHeight ); } ); } ); test( 'can bulk edit variations', async ( { page } ) => { - // mytodo setup: create variable product with the same attributes and variations - await test.step( 'Go to the "Edit product" page.', async () => { await page.goto( - `/wp-admin/post.php?post=${ variableProductId }&action=edit` + `/wp-admin/post.php?post=${ fixedVariableProductId }&action=edit` ); } ); @@ -526,11 +660,9 @@ test.describe( 'Add New Variable Product Page', () => { } ); test( 'can delete all variations', async ( { page } ) => { - // mytodo setup: create variable product with the same attributes and variations - await test.step( 'Go to the "Edit product" page.', async () => { await page.goto( - `/wp-admin/post.php?post=${ variableProductId }&action=edit` + `/wp-admin/post.php?post=${ fixedVariableProductId }&action=edit` ); } ); @@ -556,8 +688,7 @@ test.describe( 'Add New Variable Product Page', () => { ); } ); - // mytodo remove skip - test.skip( 'can manually add a variation, manage stock levels, set variation defaults and remove a variation', async ( { + test( 'can manually add a variation, manage stock levels, set variation defaults and remove a variation', async ( { page, } ) => { await page.goto( productPageURL ); From 9cc66e793eafe40a99caab3434d524a5c269add8 Mon Sep 17 00:00:00 2001 From: rodelgc Date: Fri, 14 Apr 2023 23:33:08 +0800 Subject: [PATCH 5/8] Fix cleaning up of created fixture --- .../merchant/create-variable-product.spec.js | 34 ++++++++----------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/plugins/woocommerce/tests/e2e-pw/tests/merchant/create-variable-product.spec.js b/plugins/woocommerce/tests/e2e-pw/tests/merchant/create-variable-product.spec.js index e3a42fa457b..758b9c89134 100644 --- a/plugins/woocommerce/tests/e2e-pw/tests/merchant/create-variable-product.spec.js +++ b/plugins/woocommerce/tests/e2e-pw/tests/merchant/create-variable-product.spec.js @@ -38,9 +38,8 @@ async function deleteProductsAddedByTests( baseURL ) { const ids = varProducts .map( ( { id } ) => id ) .concat( manualProducts.map( ( { id } ) => id ) ) - .push( fixedVariableProductId ); // mytodo why not being deleted? + .concat( [ fixedVariableProductId ] ); - console.log( `ids to delete: ${ ids }` ); // mytodo delete await api.post( 'products/batch', { delete: ids } ); } @@ -492,26 +491,23 @@ test.describe( 'Add New Variable Product Page', () => { } ); - await test.step( - 'Set the weight and dimensions.', - async () => { - await thirdVariation - .getByRole( 'textbox', { name: 'Weight' } ) - .type( productWeight ); + await test.step( 'Set the weight and dimensions.', async () => { + await thirdVariation + .getByRole( 'textbox', { name: 'Weight' } ) + .type( productWeight ); - await thirdVariation - .getByRole( 'textbox', { name: 'Length' } ) - .type( productLength ); + await thirdVariation + .getByRole( 'textbox', { name: 'Length' } ) + .type( productLength ); - await thirdVariation - .getByRole( 'textbox', { name: 'Width' } ) - .type( productWidth ); + await thirdVariation + .getByRole( 'textbox', { name: 'Width' } ) + .type( productWidth ); - await thirdVariation - .getByRole( 'textbox', { name: 'Height' } ) - .type( productHeight ); - } - ); + await thirdVariation + .getByRole( 'textbox', { name: 'Height' } ) + .type( productHeight ); + } ); } ); await test.step( 'Click "Save changes".', async () => { From e6774378780f8e6df18facc8c3638485fde18e82 Mon Sep 17 00:00:00 2001 From: rodelgc Date: Sat, 15 Apr 2023 00:22:35 +0800 Subject: [PATCH 6/8] Reset tour at the start of the first test --- .../merchant/create-variable-product.spec.js | 118 +++++++++++------- 1 file changed, 72 insertions(+), 46 deletions(-) diff --git a/plugins/woocommerce/tests/e2e-pw/tests/merchant/create-variable-product.spec.js b/plugins/woocommerce/tests/e2e-pw/tests/merchant/create-variable-product.spec.js index 758b9c89134..214c65afdbf 100644 --- a/plugins/woocommerce/tests/e2e-pw/tests/merchant/create-variable-product.spec.js +++ b/plugins/woocommerce/tests/e2e-pw/tests/merchant/create-variable-product.spec.js @@ -43,32 +43,44 @@ async function deleteProductsAddedByTests( baseURL ) { await api.post( 'products/batch', { delete: ids } ); } -async function resetVariableProductTour( baseURL, browser ) { - // Go to the product page, so that the `window.wp.data` module is available - const page = await browser.newPage( { baseURL: baseURL } ); - await page.goto( productPageURL ); - - // Get the current user's ID and user preferences - const { id: userId, woocommerce_meta } = await page.evaluate( () => { - return window.wp.data.select( 'core' ).getCurrentUser(); - } ); - - // Reset the variable product tour preference, so that it will be shown again - const updatedWooCommerceMeta = { - ...woocommerce_meta, - variable_product_tour_shown: '', - }; - - // Save the updated user preferences - await page.evaluate( - async ( { userId, updatedWooCommerceMeta } ) => { - await window.wp.data.dispatch( 'core' ).saveUser( { - id: userId, - woocommerce_meta: updatedWooCommerceMeta, - } ); - }, - { userId, updatedWooCommerceMeta } +async function resetVariableProductTour( page ) { + await test.step( + 'Go to the product page, so that the `window.wp.data` module is available', + async () => { + await page.goto( productPageURL ); + } ); + + const { id: userId, woocommerce_meta } = await test.step( + "Get the current user's ID and user preferences", + async () => { + return await page.evaluate( () => { + return window.wp.data.select( 'core' ).getCurrentUser(); + } ); + } + ); + + const updatedWooCommerceMeta = await test.step( + 'Reset the variable product tour preference, so that it will be shown again', + async () => { + return { + ...woocommerce_meta, + variable_product_tour_shown: '', + }; + } + ); + + await test.step( 'Save the updated user preferences', async () => { + await page.evaluate( + async ( { userId, updatedWooCommerceMeta } ) => { + await window.wp.data.dispatch( 'core' ).saveUser( { + id: userId, + woocommerce_meta: updatedWooCommerceMeta, + } ); + }, + { userId, updatedWooCommerceMeta } + ); + } ); } async function createVariableProductFixture( baseURL ) { @@ -165,42 +177,56 @@ async function createVariableProductFixture( baseURL ) { ], }; - await api - .post( 'products', createVariableProductRequestPayload ) - .then( ( response ) => { - fixedVariableProductId = response.data.id; - } ); + await test.step( + 'Create the variable product and its attributes.', + async () => { + await api + .post( 'products', createVariableProductRequestPayload ) + .then( ( response ) => { + fixedVariableProductId = response.data.id; + } ); + } + ); - await api - .post( - `products/${ fixedVariableProductId }/variations/batch`, - batchCreateVariationsPayload - ) - .then( ( response ) => { - fixedVariationIds = response.data.create - .map( ( variation ) => variation.id ) - .sort(); - } ); + await test.step( 'Generate all variations.', async () => { + await api + .post( + `products/${ fixedVariableProductId }/variations/batch`, + batchCreateVariationsPayload + ) + .then( ( response ) => { + fixedVariationIds = response.data.create + .map( ( variation ) => variation.id ) + .sort(); + } ); + } ); } test.describe( 'Add New Variable Product Page', () => { test.use( { storageState: process.env.ADMINSTATE } ); test.beforeAll( async ( { baseURL } ) => { - await createVariableProductFixture( baseURL ); + await test.step( + 'Set up a variable product fixture through the REST API.', + async () => { + await createVariableProductFixture( baseURL ); + } + ); } ); - test.afterAll( async ( { baseURL, browser } ) => { + test.afterAll( async ( { baseURL } ) => { await deleteProductsAddedByTests( baseURL ); - await resetVariableProductTour( baseURL, browser ); } ); test( 'can create product, attributes and variations', async ( { page, } ) => { - await test.step( 'Go to "Products > Add New page".', async () => { - await page.goto( productPageURL ); - } ); + await test.step( + 'Go to the product page, and reset the variable product tour.', + async () => { + await resetVariableProductTour( page ); + } + ); await test.step( `Type "${ variableProductName }" into the "Product name" input field.`, From 136b76834b849db13fba48fb541f490ed3807174 Mon Sep 17 00:00:00 2001 From: rodelgc Date: Sat, 15 Apr 2023 00:28:59 +0800 Subject: [PATCH 7/8] Trivial correction to test step --- .../tests/e2e-pw/tests/merchant/create-variable-product.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/woocommerce/tests/e2e-pw/tests/merchant/create-variable-product.spec.js b/plugins/woocommerce/tests/e2e-pw/tests/merchant/create-variable-product.spec.js index 214c65afdbf..a0d7ddcd381 100644 --- a/plugins/woocommerce/tests/e2e-pw/tests/merchant/create-variable-product.spec.js +++ b/plugins/woocommerce/tests/e2e-pw/tests/merchant/create-variable-product.spec.js @@ -222,7 +222,7 @@ test.describe( 'Add New Variable Product Page', () => { page, } ) => { await test.step( - 'Go to the product page, and reset the variable product tour.', + 'Go to "Products > Add new" page, and reset the variable product tour.', async () => { await resetVariableProductTour( page ); } From c226fa164bf9f6c98d40c0337a3349917572418a Mon Sep 17 00:00:00 2001 From: rodelgc Date: Sat, 15 Apr 2023 01:45:20 +0800 Subject: [PATCH 8/8] Re-navigate to ensure tour displays --- .../tests/merchant/create-variable-product.spec.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/plugins/woocommerce/tests/e2e-pw/tests/merchant/create-variable-product.spec.js b/plugins/woocommerce/tests/e2e-pw/tests/merchant/create-variable-product.spec.js index a0d7ddcd381..3e5d4f0c4e4 100644 --- a/plugins/woocommerce/tests/e2e-pw/tests/merchant/create-variable-product.spec.js +++ b/plugins/woocommerce/tests/e2e-pw/tests/merchant/create-variable-product.spec.js @@ -221,12 +221,13 @@ test.describe( 'Add New Variable Product Page', () => { test( 'can create product, attributes and variations', async ( { page, } ) => { - await test.step( - 'Go to "Products > Add new" page, and reset the variable product tour.', - async () => { - await resetVariableProductTour( page ); - } - ); + await test.step( 'Reset the variable product tour.', async () => { + await resetVariableProductTour( page ); + } ); + + await test.step( 'Go to "Products > Add new" page.', async () => { + await page.goto( productPageURL ); + } ); await test.step( `Type "${ variableProductName }" into the "Product name" input field.`,