Improve flaky e2e tests (#44208)

* Fix flaky guest checkout tests

* Removed a couple of extra assertions (not needed)

* Enable payment gateway

* Add changelog

---------

Co-authored-by: Jon Lane <jon.lane@automattic.com>
This commit is contained in:
Jonathan Lane 2024-01-31 10:08:11 -08:00 committed by GitHub
parent 7c4dca8348
commit 9c00c2676b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 146 additions and 96 deletions

View File

@ -0,0 +1,4 @@
Significance: patch
Type: dev
Fix a couple of flaky e2e tests

View File

@ -22,6 +22,10 @@ test.describe( 'Cart & Checkout Restricted Coupons', () => {
await api.put( 'settings/general/woocommerce_currency', { await api.put( 'settings/general/woocommerce_currency', {
value: 'USD', value: 'USD',
} ); } );
// enable COD
await api.put( 'payment_gateways/cod', {
enabled: true,
} );
// add categories // add categories
await api await api
.post( 'products/categories', { .post( 'products/categories', {
@ -154,6 +158,10 @@ test.describe( 'Cart & Checkout Restricted Coupons', () => {
force: true, force: true,
} ); } );
await api.post( 'coupons/batch', { delete: [ ...couponBatchId ] } ); await api.post( 'coupons/batch', { delete: [ ...couponBatchId ] } );
await api.put( 'payment_gateways/cod', {
enabled: false,
} );
} ); } );
test( 'expired coupon cannot be used', async ( { page, context } ) => { test( 'expired coupon cannot be used', async ( { page, context } ) => {

View File

@ -298,115 +298,153 @@ test.describe( 'Checkout page', () => {
} ); } );
test( 'allows guest customer to place an order', async ( { page } ) => { test( 'allows guest customer to place an order', async ( { page } ) => {
await addProductsToCart( page, simpleProductName, '2' ); await test.step( 'Add 2 products to the cart', async () => {
await addProductsToCart( page, simpleProductName, '2' );
} );
await page.goto( '/checkout/' ); await test.step( 'Go to checkout and confirm that products and totals are as expected', async () => {
await expect( page.locator( 'strong.product-quantity' ) ).toContainText( await page.goto( '/checkout/' );
'2' await expect(
); page.locator( 'strong.product-quantity' )
let totalPrice = await page ).toContainText( '2' );
.getByRole( 'row', { name: 'Total' } ) let totalPrice = await page
.last() .getByRole( 'row', { name: 'Total' } )
.locator( 'td' ) .last()
.textContent(); .locator( 'td' )
totalPrice = Number( totalPrice.replace( /\$([\d.]+).*/, '$1' ) ); .textContent();
await expect( totalPrice ).toBeGreaterThanOrEqual( totalPrice = Number( totalPrice.replace( /\$([\d.]+).*/, '$1' ) );
Number( twoProductPrice ) await expect( totalPrice ).toBeGreaterThanOrEqual(
); Number( twoProductPrice )
); // account for taxes or shipping that may be present
} );
await page.locator( '#billing_first_name' ).fill( 'Lisa' ); await test.step( 'Complete the checkout form', async () => {
await page.locator( '#billing_last_name' ).fill( 'Simpson' ); await page
await page .getByRole( 'textbox', { name: 'First name *' } )
.locator( '#billing_address_1' ) .fill( 'Lisa' );
.fill( '123 Evergreen Terrace' ); await page
await page.locator( '#billing_city' ).fill( 'Springfield' ); .getByRole( 'textbox', { name: 'Last name *' } )
await page.locator( '#billing_state' ).selectOption( 'OR' ); .fill( 'Simpson' );
await page.locator( '#billing_postcode' ).fill( '97403' ); await page
await page.locator( '#billing_phone' ).fill( '555 555-5555' ); .getByRole( 'textbox', { name: 'Street address *' } )
await page.locator( '#billing_email' ).fill( guestEmail ); .fill( '123 Evergreen Terrace' );
await page
.getByRole( 'textbox', { name: 'Town / City *' } )
.fill( 'Springfield' );
await page.locator( '#billing_state' ).selectOption( 'OR' );
await page
.getByRole( 'textbox', { name: 'ZIP Code *' } )
.fill( '97403' );
await page.getByLabel( 'Phone *' ).fill( '555 555-5555' );
await page.getByLabel( 'Email address *' ).fill( guestEmail );
await page.locator( 'text=Cash on delivery' ).click(); await page.getByText( 'Cash on delivery' ).click();
await expect( page.locator( 'div.payment_method_cod' ) ).toBeVisible();
await page.locator( 'text=Place order' ).click(); await page.getByRole( 'button', { name: 'Place order' } ).click();
} );
await expect( await test.step( 'Load the order confirmation page, extract order number', async () => {
page.getByRole( 'heading', { name: 'Order received' } ) await expect(
).toBeVisible(); page.getByRole( 'heading', { name: 'Order received' } )
).toBeVisible();
// get order ID from the page // get order ID from the page
const orderReceivedText = await page const orderReceivedText = await page
.locator( '.woocommerce-order-overview__order.order' ) .locator( '.woocommerce-order-overview__order.order' )
.textContent(); .textContent();
guestOrderId = await orderReceivedText.split( /(\s+)/ )[ 6 ].toString(); guestOrderId = await orderReceivedText
.split( /(\s+)/ )[ 6 ]
.toString();
} );
// Let's simulate a new browser context (by dropping all cookies), and reload the page. This approximates a await test.step( 'Simulate cookies cleared, but within 10 minute grace period', async () => {
// scenario where the server can no longer identify the shopper. However, so long as we are within the 10 minute // Let's simulate a new browser context (by dropping all cookies), and reload the page. This approximates a
// grace period following initial order placement, the 'order received' page should still be rendered. // scenario where the server can no longer identify the shopper. However, so long as we are within the 10 minute
await page.context().clearCookies(); // grace period following initial order placement, the 'order received' page should still be rendered.
await page.reload(); await page.context().clearCookies();
await expect( await page.reload();
page.getByRole( 'heading', { name: 'Order received' } ) await expect(
).toBeVisible(); page.getByRole( 'heading', { name: 'Order received' } )
).toBeVisible();
} );
// Let's simulate a scenario where the 10 minute grace period has expired. This time, we expect the shopper to await test.step( 'Simulate cookies cleared, outside 10 minute window', async () => {
// be presented with a request to verify their email address. // Let's simulate a scenario where the 10 minute grace period has expired. This time, we expect the shopper to
await setFilterValue( // be presented with a request to verify their email address.
page, await setFilterValue(
'woocommerce_order_email_verification_grace_period', page,
0 'woocommerce_order_email_verification_grace_period',
); 0
await page.reload(); );
await expect( await page.waitForTimeout( 2000 ); // needs some time before reload for change to take effect.
page.locator( 'form.woocommerce-verify-email p:nth-child(3)' ) await page.reload( { waitForLoadState: 'networkidle' } );
).toContainText( /verify the email address associated with the order/ ); await expect(
page.getByRole( 'button', { name: 'Verify' } )
).toBeVisible();
await expect( page.getByLabel( 'Email address *' ) ).toBeVisible();
await expect(
page.locator( 'form.woocommerce-verify-email p:nth-child(3)' )
).toContainText(
/verify the email address associated with the order/
);
} );
// Supplying an email address other than the actual order billing email address will take them back to the same await test.step( 'Supply incorrect email address for the order, error', async () => {
// page with an error message. // Supplying an email address other than the actual order billing email address will take them back to the same
await page.fill( '#email', 'incorrect@email.address' ); // page with an error message.
await page.locator( 'form.woocommerce-verify-email button' ).click(); await page
await expect( .getByLabel( 'Email address *' )
page.locator( 'form.woocommerce-verify-email p:nth-child(4)' ) .fill( 'incorrect@email.address' );
).toContainText( /verify the email address associated with the order/ ); await page.getByRole( 'button', { name: 'Verify' } ).click();
await expect( page.locator( '.is-error' ) ).toContainText( await expect(
/We were unable to verify the email address you provided/ page.locator( 'form.woocommerce-verify-email p:nth-child(4)' )
); ).toContainText(
/verify the email address associated with the order/
);
await expect( page.getByRole( 'alert' ) ).toContainText(
/We were unable to verify the email address you provided/
);
} );
// However if they supply the *correct* billing email address, they should see the order received page again. await test.step( 'Supply the correct email address for the order, display order confirmation', async () => {
await page.fill( '#email', guestEmail ); // However if they supply the *correct* billing email address, they should see the order received page again.
await page.locator( 'form.woocommerce-verify-email button' ).click(); await page.getByLabel( 'Email address *' ).fill( guestEmail );
await expect( await page.getByRole( 'button', { name: 'Verify' } ).click();
page.getByRole( 'heading', { name: 'Order received' } ) await expect(
).toBeVisible(); page.getByRole( 'heading', { name: 'Order received' } )
).toBeVisible();
} );
await page.goto( 'wp-login.php' ); await test.step( 'Confirm order details on the backend (as a merchant)', async () => {
await page.locator( 'input[name="log"]' ).fill( admin.username ); await page.goto( 'wp-login.php' );
await page.locator( 'input[name="pwd"]' ).fill( admin.password ); await page.locator( 'input[name="log"]' ).fill( admin.username );
await page.locator( 'text=Log In' ).click(); await page.locator( 'input[name="pwd"]' ).fill( admin.password );
await page.locator( 'text=Log In' ).click();
// load the order placed as a guest // load the order placed as a guest
await page.goto( await page.goto(
`wp-admin/post.php?post=${ guestOrderId }&action=edit` `wp-admin/post.php?post=${ guestOrderId }&action=edit`
); );
await expect( await expect(
page.getByRole( 'heading', { page.getByRole( 'heading', {
name: `Order #${ guestOrderId } details`, name: `Order #${ guestOrderId } details`,
} ) } )
).toBeVisible(); ).toBeVisible();
await expect( page.locator( '.wc-order-item-name' ) ).toContainText( await expect( page.locator( '.wc-order-item-name' ) ).toContainText(
simpleProductName simpleProductName
); );
await expect( page.locator( 'td.quantity >> nth=0' ) ).toContainText( await expect(
'2' page.locator( 'td.quantity >> nth=0' )
); ).toContainText( '2' );
await expect( page.locator( 'td.item_cost >> nth=0' ) ).toContainText( await expect(
singleProductPrice page.locator( 'td.item_cost >> nth=0' )
); ).toContainText( singleProductPrice );
await expect( page.locator( 'td.line_cost >> nth=0' ) ).toContainText( await expect(
twoProductPrice page.locator( 'td.line_cost >> nth=0' )
); ).toContainText( twoProductPrice );
await clearFilters( page ); await clearFilters( page );
} );
} ); } );
test( 'allows existing customer to place order', async ( { page } ) => { test( 'allows existing customer to place order', async ( { page } ) => {