-
Notifications
You must be signed in to change notification settings - Fork 69
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Initial shopper-checkout-purchase.spec.ts migration
To review required changes and refactors to also get rid of @woocommerce/e2e-utils
- Loading branch information
1 parent
b5a8d52
commit 961edc8
Showing
3 changed files
with
178 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -271,3 +271,5 @@ export const config = { | |
}, | ||
}, | ||
}; | ||
|
||
export type CustomerAddress = typeof config.addresses.customer.billing; |
43 changes: 43 additions & 0 deletions
43
tests/e2e-pw/specs/shopper/shopper-checkout-purchase.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
/** | ||
* External dependencies | ||
*/ | ||
import { test, expect } from '@playwright/test'; | ||
|
||
/** | ||
* Internal dependencies | ||
*/ | ||
|
||
import { config } from '../../config/default'; | ||
import * as shopper from '../../utils/shopper'; | ||
|
||
test.describe( 'Successful purchase', () => { | ||
test.beforeEach( async ( { page } ) => { | ||
await page.goto( '/cart/' ); | ||
await shopper.addCartProduct( page ); | ||
|
||
await page.goto( '/checkout/' ); | ||
await shopper.fillBillingAddress( | ||
page, | ||
config.addresses.customer.billing | ||
); | ||
} ); | ||
|
||
test( 'using a basic card', async ( { page } ) => { | ||
await shopper.fillCardDetails( page ); | ||
await shopper.placeOrder( page ); | ||
|
||
await expect( | ||
page.getByText( 'Order received' ).first() | ||
).toBeVisible(); | ||
} ); | ||
|
||
test( 'using a 3DS card', async ( { page } ) => { | ||
await shopper.fillCardDetails( page, config.cards[ '3ds' ] ); | ||
await shopper.placeOrder( page ); | ||
await shopper.confirmCardAuthentication( page, '3DS' ); | ||
|
||
await expect( | ||
page.getByText( 'Order received' ).first() | ||
).toBeVisible(); | ||
} ); | ||
} ); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
/** | ||
* External dependencies | ||
*/ | ||
import { Page } from 'playwright/test'; | ||
|
||
/** | ||
* Internal dependencies | ||
*/ | ||
|
||
import { config, CustomerAddress } from '../config/default'; | ||
|
||
export const fillBillingAddress = async ( | ||
page: Page, | ||
billingAddress: CustomerAddress | ||
): Promise< void > => { | ||
await page | ||
.locator( '#billing_first_name' ) | ||
.fill( billingAddress.firstname ); | ||
await page.locator( '#billing_last_name' ).fill( billingAddress.lastname ); | ||
await page.locator( '#billing_company' ).fill( billingAddress.company ); | ||
await page | ||
.locator( '#billing_country' ) | ||
.selectOption( billingAddress.country ); | ||
await page | ||
.locator( '#billing_address_1' ) | ||
.fill( billingAddress.addressfirstline ); | ||
await page | ||
.locator( '#billing_address_2' ) | ||
.fill( billingAddress.addresssecondline ); | ||
await page.locator( '#billing_city' ).fill( billingAddress.city ); | ||
await page.locator( '#billing_state' ).selectOption( billingAddress.state ); | ||
await page.locator( '#billing_postcode' ).fill( billingAddress.postcode ); | ||
await page.locator( '#billing_phone' ).fill( billingAddress.phone ); | ||
await page.locator( '#billing_email' ).fill( billingAddress.email ); | ||
}; | ||
|
||
export const placeOrder = async ( page: Page ): Promise< void > => { | ||
await page.locator( '#place_order' ).click(); | ||
}; | ||
|
||
export const addCartProduct = async ( | ||
page: Page, | ||
productSlug = 'beanie' | ||
): Promise< void > => { | ||
await page.goto( `/product/${ productSlug }/` ); | ||
await page.getByRole( 'button', { name: /add to cart/i } ).click(); | ||
await page.waitForLoadState( 'networkidle' ); | ||
}; | ||
|
||
export const fillCardDetails = async ( | ||
page: Page, | ||
card = config.cards.basic | ||
): Promise< void > => { | ||
if ( | ||
await page.$( | ||
'#payment .payment_method_woocommerce_payments .wcpay-upe-element' | ||
) | ||
) { | ||
const frameHandle = await page.waitForSelector( | ||
'#payment .payment_method_woocommerce_payments .wcpay-upe-element iframe' | ||
); | ||
|
||
const stripeFrame = await frameHandle.contentFrame(); | ||
|
||
if ( ! stripeFrame ) return; | ||
|
||
await stripeFrame.locator( '[name="number"]' ).fill( card.number ); | ||
|
||
await stripeFrame | ||
.locator( '[name="expiry"]' ) | ||
.fill( card.expires.month + card.expires.year ); | ||
|
||
await stripeFrame.locator( '[name="cvc"]' ).fill( card.cvc ); | ||
|
||
const zip = stripeFrame.locator( '[name="postalCode"]' ); | ||
|
||
if ( await zip.isVisible() ) { | ||
await zip.fill( '90210' ); | ||
} | ||
} else { | ||
const frameHandle = await page.waitForSelector( | ||
'#payment #wcpay-card-element iframe[name^="__privateStripeFrame"]' | ||
); | ||
const stripeFrame = await frameHandle.contentFrame(); | ||
|
||
if ( ! stripeFrame ) return; | ||
|
||
await stripeFrame.locator( '[name="cardnumber"]' ).fill( card.number ); | ||
|
||
await stripeFrame | ||
.locator( '[name="exp-date"]' ) | ||
.fill( card.expires.month + card.expires.year ); | ||
|
||
await stripeFrame.locator( '[name="cvc"]' ).fill( card.cvc ); | ||
} | ||
}; | ||
|
||
export const confirmCardAuthentication = async ( | ||
page: Page, | ||
cardType = '3DS', | ||
authorize = true | ||
): Promise< void > => { | ||
const target = authorize | ||
? '#test-source-authorize-3ds' | ||
: '#test-source-fail-3ds'; | ||
|
||
// Stripe card input also uses __privateStripeFrame as a prefix, so need to make sure we wait for an iframe that | ||
// appears at the top of the DOM. | ||
const frameHandle = await page.waitForSelector( | ||
'body>div>iframe[name^="__privateStripeFrame"]' | ||
); | ||
const stripeFrame = await frameHandle.contentFrame(); | ||
if ( ! stripeFrame ) return; | ||
|
||
const challengeFrameHandle = await stripeFrame.waitForSelector( | ||
'iframe#challengeFrame' | ||
); | ||
let challengeFrame = await challengeFrameHandle.contentFrame(); | ||
if ( ! challengeFrame ) return; | ||
|
||
// 3DS 1 cards have another iframe enclosing the authorize form | ||
if ( cardType.toUpperCase() === '3DS' ) { | ||
const acsFrameHandle = await challengeFrame.waitForSelector( | ||
'iframe[name="acsFrame"]' | ||
); | ||
challengeFrame = await acsFrameHandle.contentFrame(); | ||
} | ||
if ( ! challengeFrame ) return; | ||
// Need to wait for the CSS animations to complete. | ||
await page.waitForTimeout( 500 ); | ||
const button = await challengeFrame.waitForSelector( target ); | ||
await button.click(); | ||
}; |