-
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.
Convert shopper checkout purchase with UPE tests to Playwright (#10203)
- Loading branch information
Showing
11 changed files
with
495 additions
and
334 deletions.
There are no files selected for viewing
4 changes: 4 additions & 0 deletions
4
changelog/dev-10064-playwright-migration-shopper-checkout-purchase-with-upe-methods
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,4 @@ | ||
Significance: patch | ||
Type: dev | ||
|
||
Convert shopper checkout with UPE methods E2E test to Playwright, split saving card tests to separate file |
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 |
---|---|---|
|
@@ -74,6 +74,35 @@ export const config = { | |
email: '[email protected]', | ||
}, | ||
}, | ||
'upe-customer': { | ||
billing: { | ||
be: { | ||
firstname: 'I am', | ||
lastname: 'Customer', | ||
company: 'Automattic', | ||
country: 'Belgium', | ||
addressfirstline: 'Rue de l’Étuve, 1000', | ||
addresssecondline: 'billing-be', | ||
city: 'Bruxelles', | ||
postcode: '1000', | ||
phone: '123456789', | ||
email: '[email protected]', | ||
}, | ||
de: { | ||
firstname: 'I am', | ||
lastname: 'Customer', | ||
company: 'Automattic', | ||
country: 'Germany', | ||
addressfirstline: 'Petuelring 130', | ||
addresssecondline: 'billing-de', | ||
city: 'München', | ||
postcode: '80809', | ||
state: 'DE-BY', | ||
phone: '123456789', | ||
email: '[email protected]', | ||
}, | ||
}, | ||
}, | ||
'subscriptions-customer': { | ||
billing: { | ||
firstname: 'I am', | ||
|
@@ -125,11 +154,11 @@ export const config = { | |
basic3: { | ||
number: '378282246310005', | ||
expires: { | ||
month: '11', | ||
month: '12', | ||
year: '45', | ||
}, | ||
cvc: '1234', | ||
label: 'Amex ending in 0005', | ||
label: 'American Express ending in 0005', | ||
}, | ||
'3ds': { | ||
number: '4000002760003184', | ||
|
@@ -272,4 +301,9 @@ export const config = { | |
}, | ||
}; | ||
|
||
export type CustomerAddress = typeof config.addresses.customer.billing; | ||
export type CustomerAddress = Omit< | ||
typeof config.addresses.customer.billing, | ||
'state' | ||
> & { | ||
state?: string; | ||
}; |
113 changes: 113 additions & 0 deletions
113
tests/e2e-pw/specs/shopper/shopper-checkout-purchase-with-upe-methods.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,113 @@ | ||
/** | ||
* External dependencies | ||
*/ | ||
import test, { Page, expect } from '@playwright/test'; | ||
|
||
/** | ||
* Internal dependencies | ||
*/ | ||
import { | ||
activateMulticurrency, | ||
addCurrency, | ||
deactivateMulticurrency, | ||
disablePaymentMethods, | ||
enablePaymentMethods, | ||
restoreCurrencies, | ||
} from '../../utils/merchant'; | ||
import { getShopper, getMerchant } from '../../utils/helpers'; | ||
import { | ||
disableCardTestingProtection, | ||
enableCardTestingProtection, | ||
} from '../../utils/devtools'; | ||
import { | ||
addToCartFromShopPage, | ||
changeAccountCurrency, | ||
emptyCart, | ||
expectFraudPreventionToken, | ||
fillBillingAddress, | ||
focusPlaceOrderButton, | ||
placeOrder, | ||
} from '../../utils/shopper'; | ||
import { config } from '../../config/default'; | ||
import { goToCheckout, goToShop } from '../../utils/shopper-navigation'; | ||
|
||
test.describe( 'Enable UPE with deferred intent creation', () => { | ||
let wasMultiCurrencyEnabled = false; | ||
let merchantPage: Page, shopperPage: Page; | ||
test.beforeAll( async ( { browser } ) => { | ||
// Open browsers. | ||
merchantPage = ( await getMerchant( browser ) ).merchantPage; | ||
shopperPage = ( await getShopper( browser ) ).shopperPage; | ||
|
||
// Prepare merchant side of tests. | ||
wasMultiCurrencyEnabled = await activateMulticurrency( merchantPage ); | ||
await addCurrency( merchantPage, 'EUR' ); | ||
await enablePaymentMethods( merchantPage, [ 'bancontact' ] ); | ||
// Prepare shopper side of tests. | ||
await changeAccountCurrency( | ||
shopperPage, | ||
config.addresses.customer.billing, | ||
'EUR' | ||
); | ||
await emptyCart( shopperPage ); | ||
} ); | ||
|
||
test.afterAll( async () => { | ||
// Restore shopper side of tests. | ||
await emptyCart( shopperPage ); | ||
|
||
// Restore merchant side of tests | ||
await disablePaymentMethods( merchantPage, [ 'bancontact' ] ); | ||
await restoreCurrencies( merchantPage ); | ||
if ( ! wasMultiCurrencyEnabled ) { | ||
await deactivateMulticurrency( merchantPage ); | ||
} | ||
} ); | ||
|
||
const testBancontactOrder = async ( | ||
cardTestingPreventionState: boolean | ||
) => { | ||
await goToShop( shopperPage ); | ||
await addToCartFromShopPage( shopperPage, 'Beanie' ); | ||
await goToCheckout( shopperPage ); | ||
await fillBillingAddress( | ||
shopperPage, | ||
config.addresses[ 'upe-customer' ].billing.be | ||
); | ||
await shopperPage.waitForLoadState( 'networkidle' ); | ||
await expectFraudPreventionToken( | ||
shopperPage, | ||
cardTestingPreventionState | ||
); | ||
await shopperPage.getByText( 'Bancontact' ).click(); | ||
await focusPlaceOrderButton( shopperPage ); | ||
await placeOrder( shopperPage ); | ||
await shopperPage.waitForLoadState( 'networkidle' ); | ||
await shopperPage | ||
.getByRole( 'link', { | ||
name: 'Authorize Test Payment', | ||
} ) | ||
.click(); | ||
await expect( | ||
shopperPage.getByText( 'Order received' ).first() | ||
).toBeVisible(); | ||
}; | ||
|
||
test.describe( 'Card testing prevention enabled', () => { | ||
test.beforeAll( async () => { | ||
await enableCardTestingProtection( merchantPage ); | ||
} ); | ||
test.afterAll( async () => { | ||
await disableCardTestingProtection( merchantPage ); | ||
} ); | ||
test( 'should successfully place order with Bancontact', async () => { | ||
await testBancontactOrder( true ); | ||
} ); | ||
} ); | ||
|
||
test.describe( 'Card testing prevention disabled', () => { | ||
test( 'should successfully place order with Bancontact', async () => { | ||
await testBancontactOrder( false ); | ||
} ); | ||
} ); | ||
} ); |
199 changes: 199 additions & 0 deletions
199
tests/e2e-pw/specs/shopper/shopper-myaccount-saved-cards.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,199 @@ | ||
/** | ||
* External dependencies | ||
*/ | ||
import test, { Page, expect } from '@playwright/test'; | ||
|
||
/** | ||
* Internal dependencies | ||
*/ | ||
import { config } from '../../config/default'; | ||
import { goToMyAccount, goToShop } from '../../utils/shopper-navigation'; | ||
import { getAnonymousShopper } from '../../utils/helpers'; | ||
import { | ||
addSavedCard, | ||
confirmCardAuthentication, | ||
deleteSavedCard, | ||
placeOrder, | ||
placeOrderWithOptions, | ||
selectSavedCardOnCheckout, | ||
setDefaultPaymentMethod, | ||
setupProductCheckout, | ||
} from '../../utils/shopper'; | ||
import RestAPI from '../../utils/rest-api'; | ||
|
||
const cards = { | ||
basic: config.cards.basic, | ||
'3ds': config.cards[ '3ds' ], | ||
'3ds2': config.cards[ '3ds2' ], | ||
} as { [ key: string ]: typeof config.cards.basic }; | ||
|
||
test.describe( 'Shopper can save and delete cards', () => { | ||
let timeAdded: number; | ||
// Use cards different than other tests to prevent conflicts. | ||
const card2 = config.cards.basic3; | ||
let shopperPage: Page = null; | ||
const customerBillingConfig = | ||
config.addresses[ 'subscriptions-customer' ].billing; | ||
|
||
test.beforeAll( async ( { browser }, { project } ) => { | ||
// Delete the user, if present, and create a new one with a new order. | ||
// This is required to avoid running this test on a customer that already has a saved card. | ||
const restApi = new RestAPI( project.use.baseURL ); | ||
await restApi.deleteCustomerByEmailAddress( | ||
customerBillingConfig.email | ||
); | ||
|
||
shopperPage = ( await getAnonymousShopper( browser ) ).shopperPage; | ||
await placeOrderWithOptions( shopperPage, { | ||
billingAddress: customerBillingConfig, | ||
createAccount: true, | ||
} ); | ||
} ); | ||
|
||
async function waitTwentySecondsSinceLastCardAdded( page: Page ) { | ||
// Make sure that at least 20s had already elapsed since the last card was added. | ||
// Otherwise, you will get the error message, | ||
// "You cannot add a new payment method so soon after the previous one." | ||
// Source: /docker/wordpress/wp-content/plugins/woocommerce/includes/class-wc-form-handler.php#L509-L521 | ||
const timeTestFinished = Date.now(); | ||
const elapsedWaitTime = timeTestFinished - timeAdded; | ||
const remainingWaitTime = | ||
20000 > elapsedWaitTime ? 20000 - elapsedWaitTime : 0; | ||
|
||
await page.waitForTimeout( remainingWaitTime ); | ||
} | ||
|
||
// No need to run this test for all card types. | ||
test( 'prevents adding another card for 20 seconds after a card is added', async () => { | ||
await goToMyAccount( shopperPage, 'payment-methods' ); | ||
// Take note of the time when we added this card | ||
await addSavedCard( shopperPage, config.cards.basic, 'US', '94110' ); | ||
timeAdded = +Date.now(); | ||
|
||
// Try to add a new card before 20 seconds have passed | ||
await addSavedCard( shopperPage, config.cards.basic2, 'US', '94110' ); | ||
|
||
// Verify that the card was not added | ||
await expect( | ||
shopperPage.getByText( | ||
'You cannot add a new payment method so soon after the previous one. Please wait for 20 seconds.' | ||
) | ||
).toBeVisible(); | ||
|
||
await expect( | ||
shopperPage.getByText( 'Payment method successfully added' ) | ||
).not.toBeVisible(); | ||
|
||
await expect( | ||
shopperPage.getByText( | ||
`${ config.cards.basic2.expires.month }/${ config.cards.basic2.expires.year }` | ||
) | ||
).not.toBeVisible(); | ||
|
||
await waitTwentySecondsSinceLastCardAdded( shopperPage ); | ||
// cleanup for the next tests | ||
await goToMyAccount( shopperPage, 'payment-methods' ); | ||
await deleteSavedCard( shopperPage, config.cards.basic ); | ||
} ); | ||
|
||
Object.entries( cards ).forEach( ( [ cardName, card ] ) => { | ||
test.describe( 'Testing card: ' + cardName, () => { | ||
test( `should add the ${ cardName } card as a new payment method`, async () => { | ||
await goToMyAccount( shopperPage, 'payment-methods' ); | ||
await addSavedCard( shopperPage, card, 'US', '94110' ); | ||
// Take note of the time when we added this card | ||
timeAdded = +Date.now(); | ||
|
||
if ( cardName === '3ds' || cardName === '3ds2' ) { | ||
await confirmCardAuthentication( shopperPage ); | ||
} | ||
|
||
await shopperPage.waitForURL( /\/my-account\/payment-methods/, { | ||
waitUntil: 'load', | ||
} ); | ||
|
||
// Verify that the card was added | ||
await expect( | ||
shopperPage.getByText( | ||
'You cannot add a new payment method so soon after the previous one. Please wait for 20 seconds.' | ||
) | ||
).not.toBeVisible(); | ||
|
||
await expect( | ||
shopperPage.getByText( 'Payment method successfully added' ) | ||
).toBeVisible(); | ||
|
||
await expect( | ||
shopperPage.getByText( | ||
`${ card.expires.month }/${ card.expires.year }` | ||
) | ||
).toBeVisible(); | ||
|
||
await waitTwentySecondsSinceLastCardAdded( shopperPage ); | ||
} ); | ||
|
||
test( `should be able to purchase with the saved ${ cardName } card`, async () => { | ||
await goToShop( shopperPage ); | ||
await setupProductCheckout( shopperPage ); | ||
await selectSavedCardOnCheckout( shopperPage, card ); | ||
if ( cardName === 'basic' ) { | ||
await placeOrder( shopperPage ); | ||
} else { | ||
await shopperPage | ||
.getByRole( 'button', { name: 'Place order' } ) | ||
.click(); | ||
await confirmCardAuthentication( shopperPage ); | ||
} | ||
|
||
await shopperPage.waitForURL( /\/order-received\//, { | ||
waitUntil: 'load', | ||
} ); | ||
await expect( | ||
shopperPage.getByRole( 'heading', { | ||
name: 'Order received', | ||
} ) | ||
).toBeVisible(); | ||
} ); | ||
|
||
test( `should be able to set the ${ cardName } card as default payment method`, async () => { | ||
await goToMyAccount( shopperPage, 'payment-methods' ); | ||
await addSavedCard( shopperPage, card2, 'US', '94110' ); | ||
// Take note of the time when we added this card | ||
timeAdded = +Date.now(); | ||
|
||
await expect( | ||
shopperPage.getByText( 'Payment method successfully added' ) | ||
).toBeVisible(); | ||
await expect( | ||
shopperPage.getByText( | ||
`${ card2.expires.month }/${ card2.expires.year }` | ||
) | ||
).toBeVisible(); | ||
await setDefaultPaymentMethod( shopperPage, card2 ); | ||
// Verify that the card was set as default | ||
await expect( | ||
shopperPage.getByText( | ||
'This payment method was successfully set as your default.' | ||
) | ||
).toBeVisible(); | ||
} ); | ||
|
||
test( `should be able to delete ${ cardName } card`, async () => { | ||
await goToMyAccount( shopperPage, 'payment-methods' ); | ||
await deleteSavedCard( shopperPage, card ); | ||
await expect( | ||
shopperPage.getByText( 'Payment method deleted.' ) | ||
).toBeVisible(); | ||
|
||
await deleteSavedCard( shopperPage, card2 ); | ||
await expect( | ||
shopperPage.getByText( 'Payment method deleted.' ) | ||
).toBeVisible(); | ||
} ); | ||
|
||
test.afterAll( async () => { | ||
waitTwentySecondsSinceLastCardAdded( shopperPage ); | ||
} ); | ||
} ); | ||
} ); | ||
} ); |
Oops, something went wrong.