Add new E2E tests to cover Shopper Checkout Block flow (#41218)
* Add few E2E tests to cover half of the milestone * Improve welcome modal closing * Add new test scenarios * Add more tests to cover creating account and shipping * Update shipping zone labels to fulfil latest design changes * Add tests for checkout block coupons and cart block coupons * Remove only flag leftover * Add checkout block tax tests and merge with cart test * Update selectors to match checkout page * Update checkout block test and comment scenario until issue resolved * Remove only leftover * Update checkout block test * Improve filling shipping and billing checkout * Create order via API with coupon * Include checkout filling util helper * Update test to use get by role for alerts * Remove only leftover * Adjust scenario for placing an order as a customer * Improve existing customer placing order scenario * Add util helper for adding products to cart * Remove leftover from testing --------- Co-authored-by: Jon Lane <jon.lane@automattic.com>
This commit is contained in:
parent
9c2048f029
commit
eb49308781
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: dev
|
||||
|
||||
Adds tests for shopper checkout block flows
|
|
@ -3,7 +3,7 @@ const { admin } = require( '../../test-data/data' );
|
|||
const { closeWelcomeModal } = require( '../../utils/editor' );
|
||||
const wcApi = require( '@woocommerce/woocommerce-rest-api' ).default;
|
||||
|
||||
const simpleProductName = 'A Simple Product';
|
||||
const simpleProductName = 'Cart Coupons Product';
|
||||
const singleProductFullPrice = '110.00';
|
||||
const singleProductSalePrice = '55.00';
|
||||
const coupons = [
|
||||
|
@ -23,11 +23,15 @@ const coupons = [
|
|||
amount: '10.00',
|
||||
},
|
||||
];
|
||||
const couponLimitedCode = '10fixedcartlimited';
|
||||
const customerBilling = {
|
||||
email: 'john.doe.merchant.test@example.com',
|
||||
};
|
||||
|
||||
const pageTitle = 'Cart Block';
|
||||
const pageSlug = pageTitle.replace( / /gi, '-' ).toLowerCase();
|
||||
|
||||
let product1Id;
|
||||
let productId, orderId, limitedCouponId;
|
||||
|
||||
test.describe( 'Cart Block Applying Coupons', () => {
|
||||
const couponBatchId = new Array();
|
||||
|
@ -52,7 +56,7 @@ test.describe( 'Cart Block Applying Coupons', () => {
|
|||
sale_price: singleProductSalePrice,
|
||||
} )
|
||||
.then( ( response ) => {
|
||||
product1Id = response.data.id;
|
||||
productId = response.data.id;
|
||||
} );
|
||||
// add coupons
|
||||
await api
|
||||
|
@ -64,6 +68,32 @@ test.describe( 'Cart Block Applying Coupons', () => {
|
|||
couponBatchId.push( response.data.create[ i ].id );
|
||||
}
|
||||
} );
|
||||
// add limited coupon
|
||||
await api
|
||||
.post( 'coupons', {
|
||||
code: couponLimitedCode,
|
||||
discount_type: 'fixed_cart',
|
||||
amount: '10.00',
|
||||
usage_limit: 1,
|
||||
usage_count: 1,
|
||||
} )
|
||||
.then( ( response ) => {
|
||||
limitedCouponId = response.data.id;
|
||||
} );
|
||||
// add order with applied limited coupon
|
||||
await api
|
||||
.post( 'orders', {
|
||||
status: 'processing',
|
||||
billing: customerBilling,
|
||||
coupon_lines: [
|
||||
{
|
||||
code: couponLimitedCode,
|
||||
},
|
||||
],
|
||||
} )
|
||||
.then( ( response ) => {
|
||||
orderId = response.data.id;
|
||||
} );
|
||||
} );
|
||||
|
||||
test.afterAll( async ( { baseURL } ) => {
|
||||
|
@ -74,9 +104,14 @@ test.describe( 'Cart Block Applying Coupons', () => {
|
|||
version: 'wc/v3',
|
||||
} );
|
||||
await api.post( 'products/batch', {
|
||||
delete: [ product1Id ],
|
||||
delete: [ productId ],
|
||||
} );
|
||||
await api.post( 'coupons/batch', {
|
||||
delete: [ ...couponBatchId, limitedCouponId ],
|
||||
} );
|
||||
await api.post( 'orders/batch', {
|
||||
delete: [ orderId ],
|
||||
} );
|
||||
await api.post( 'coupons/batch', { delete: [ ...couponBatchId ] } );
|
||||
} );
|
||||
|
||||
test.beforeEach( async ( { context } ) => {
|
||||
|
@ -121,7 +156,7 @@ test.describe( 'Cart Block Applying Coupons', () => {
|
|||
} ) => {
|
||||
const totals = [ '$50.00', '$27.50', '$45.00' ];
|
||||
// add product to cart block
|
||||
await page.goto( `/shop/?add-to-cart=${ product1Id }` );
|
||||
await page.goto( `/shop/?add-to-cart=${ productId }` );
|
||||
await page.waitForLoadState( 'networkidle' );
|
||||
await page.goto( pageSlug );
|
||||
await expect(
|
||||
|
@ -165,7 +200,7 @@ test.describe( 'Cart Block Applying Coupons', () => {
|
|||
const totalsReverse = [ '$17.50', '$45.00', '$55.00' ];
|
||||
const discounts = [ '-$5.00', '-$32.50', '-$42.50' ];
|
||||
// add product to cart block
|
||||
await page.goto( `/shop/?add-to-cart=${ product1Id }` );
|
||||
await page.goto( `/shop/?add-to-cart=${ productId }` );
|
||||
await page.waitForLoadState( 'networkidle' );
|
||||
await page.goto( pageSlug );
|
||||
await expect(
|
||||
|
@ -214,7 +249,7 @@ test.describe( 'Cart Block Applying Coupons', () => {
|
|||
page,
|
||||
} ) => {
|
||||
// add product to cart block
|
||||
await page.goto( `/shop/?add-to-cart=${ product1Id }` );
|
||||
await page.goto( `/shop/?add-to-cart=${ productId }` );
|
||||
await page.waitForLoadState( 'networkidle' );
|
||||
await page.goto( pageSlug );
|
||||
await expect(
|
||||
|
@ -247,4 +282,28 @@ test.describe( 'Cart Block Applying Coupons', () => {
|
|||
)
|
||||
).toBeVisible();
|
||||
} );
|
||||
|
||||
test( 'prevents cart block applying coupon with usage limit', async ( {
|
||||
page,
|
||||
} ) => {
|
||||
// add product to cart block and go to cart
|
||||
await page.goto( `/shop/?add-to-cart=${ productId }` );
|
||||
await page.waitForLoadState( 'networkidle' );
|
||||
await page.goto( pageSlug );
|
||||
await expect(
|
||||
page.getByRole( 'heading', { name: pageTitle } )
|
||||
).toBeVisible();
|
||||
|
||||
// add coupon with usage limit
|
||||
await page.getByRole( 'button', { name: 'Add a coupon' } ).click();
|
||||
await page
|
||||
.locator( '#wc-block-components-totals-coupon__input-0' )
|
||||
.fill( couponLimitedCode );
|
||||
await page.getByText( 'Apply', { exact: true } ).click();
|
||||
await expect(
|
||||
page
|
||||
.getByRole( 'alert' )
|
||||
.getByText( 'Coupon usage limit has been reached.' )
|
||||
).toBeVisible();
|
||||
} );
|
||||
} );
|
||||
|
|
|
@ -8,8 +8,14 @@ const productPrice = '100.00';
|
|||
const messyProductPrice = '13.47';
|
||||
const secondProductName = 'Second Product Cart Block Taxing';
|
||||
|
||||
const pageTitle = 'Cart Block';
|
||||
const pageSlug = pageTitle.replace( / /gi, '-' ).toLowerCase();
|
||||
const cartBlockPageTitle = 'Cart Block';
|
||||
const cartBlockPageSlug = cartBlockPageTitle
|
||||
.replace( / /gi, '-' )
|
||||
.toLowerCase();
|
||||
const checkoutBlockPageTitle = 'Checkout Block';
|
||||
const checkoutBlockPageSlug = checkoutBlockPageTitle
|
||||
.replace( / /gi, '-' )
|
||||
.toLowerCase();
|
||||
|
||||
let productId,
|
||||
productId2,
|
||||
|
@ -24,7 +30,7 @@ let productId,
|
|||
shippingZoneId,
|
||||
shippingMethodId;
|
||||
|
||||
test.describe( 'Shopper Cart Block Tax Display', () => {
|
||||
test.describe( 'Shopper Cart & Checkout Block Tax Display', () => {
|
||||
test.beforeAll( async ( { baseURL } ) => {
|
||||
const api = new wcApi( {
|
||||
url: baseURL,
|
||||
|
@ -111,7 +117,7 @@ test.describe( 'Shopper Cart Block Tax Display', () => {
|
|||
|
||||
await page
|
||||
.getByRole( 'textbox', { name: 'Add title' } )
|
||||
.fill( pageTitle );
|
||||
.fill( cartBlockPageTitle );
|
||||
await page.getByRole( 'button', { name: 'Add default block' } ).click();
|
||||
await page
|
||||
.getByRole( 'document', {
|
||||
|
@ -127,16 +133,56 @@ test.describe( 'Shopper Cart Block Tax Display', () => {
|
|||
.getByRole( 'button', { name: 'Publish', exact: true } )
|
||||
.click();
|
||||
await expect(
|
||||
page.getByText( `${ pageTitle } is now live.` )
|
||||
page.getByText( `${ cartBlockPageTitle } is now live.` )
|
||||
).toBeVisible();
|
||||
} );
|
||||
|
||||
test( 'that inclusive tax is displayed properly in Cart Block page', async ( {
|
||||
test( 'can create Checkout Block page', async ( { page } ) => {
|
||||
// create a new page with checkout block
|
||||
await page.goto( 'wp-admin/post-new.php?post_type=page' );
|
||||
await page.waitForLoadState( 'networkidle' );
|
||||
await page.locator( 'input[name="log"]' ).fill( admin.username );
|
||||
await page.locator( 'input[name="pwd"]' ).fill( admin.password );
|
||||
await page.locator( 'text=Log In' ).click();
|
||||
|
||||
// Close welcome popup if prompted
|
||||
try {
|
||||
await page
|
||||
.getByLabel( 'Close', { exact: true } )
|
||||
.click( { timeout: 5000 } );
|
||||
} catch ( error ) {
|
||||
console.log( "Welcome modal wasn't present, skipping action." );
|
||||
}
|
||||
|
||||
await page
|
||||
.getByRole( 'textbox', { name: 'Add title' } )
|
||||
.fill( checkoutBlockPageTitle );
|
||||
await page.getByRole( 'button', { name: 'Add default block' } ).click();
|
||||
await page
|
||||
.getByRole( 'document', {
|
||||
name: 'Empty block; start writing or type forward slash to choose a block',
|
||||
} )
|
||||
.fill( '/checkout' );
|
||||
await page.keyboard.press( 'Enter' );
|
||||
await page
|
||||
.getByRole( 'button', { name: 'Publish', exact: true } )
|
||||
.click();
|
||||
await page
|
||||
.getByRole( 'region', { name: 'Editor publish' } )
|
||||
.getByRole( 'button', { name: 'Publish', exact: true } )
|
||||
.click();
|
||||
await expect(
|
||||
page.getByText( `${ checkoutBlockPageTitle } is now live.` )
|
||||
).toBeVisible();
|
||||
} );
|
||||
|
||||
test( 'that inclusive tax is displayed properly in blockbased Cart & Checkout pages', async ( {
|
||||
page,
|
||||
} ) => {
|
||||
await page.goto( pageSlug );
|
||||
await test.step( 'Load cart page and confirm price display', async () => {
|
||||
await page.goto( cartBlockPageSlug );
|
||||
await expect(
|
||||
page.getByRole( 'heading', { name: pageTitle } )
|
||||
page.getByRole( 'heading', { name: cartBlockPageTitle } )
|
||||
).toBeVisible();
|
||||
|
||||
await expect(
|
||||
|
@ -152,7 +198,27 @@ test.describe( 'Shopper Cart Block Tax Display', () => {
|
|||
).toHaveText( 'Including $25.00 Nasty Tax' );
|
||||
} );
|
||||
|
||||
test( 'that exclusive tax is displayed properly in Cart Block page', async ( {
|
||||
await test.step( 'Load checkout page and confirm price display', async () => {
|
||||
await page.goto( checkoutBlockPageSlug );
|
||||
await expect(
|
||||
page.getByRole( 'heading', { name: checkoutBlockPageTitle } )
|
||||
).toBeVisible();
|
||||
|
||||
await expect(
|
||||
page.locator(
|
||||
'.wp-block-woocommerce-checkout-order-summary-subtotal-block'
|
||||
)
|
||||
).toContainText( '$125.00' );
|
||||
await expect(
|
||||
page.locator( '.wc-block-components-totals-footer-item' )
|
||||
).toContainText( '$125.00' );
|
||||
await expect(
|
||||
page.locator( '.wc-block-components-totals-footer-item-tax' )
|
||||
).toHaveText( 'Including $25.00 Nasty Tax' );
|
||||
} );
|
||||
} );
|
||||
|
||||
test( 'that exclusive tax is displayed properly in blockbased Cart & Checkout pages', async ( {
|
||||
page,
|
||||
baseURL,
|
||||
} ) => {
|
||||
|
@ -165,9 +231,11 @@ test.describe( 'Shopper Cart Block Tax Display', () => {
|
|||
await api.put( 'settings/tax/woocommerce_tax_display_cart', {
|
||||
value: 'excl',
|
||||
} );
|
||||
await page.goto( pageSlug );
|
||||
|
||||
await test.step( 'Load cart page and confirm price display', async () => {
|
||||
await page.goto( cartBlockPageSlug );
|
||||
await expect(
|
||||
page.getByRole( 'heading', { name: pageTitle } )
|
||||
page.getByRole( 'heading', { name: cartBlockPageTitle } )
|
||||
).toBeVisible();
|
||||
|
||||
await expect(
|
||||
|
@ -182,9 +250,29 @@ test.describe( 'Shopper Cart Block Tax Display', () => {
|
|||
page.locator( '.wc-block-components-totals-taxes' )
|
||||
).toContainText( '$25.00' );
|
||||
} );
|
||||
|
||||
await test.step( 'Load checkout page and confirm price display', async () => {
|
||||
await page.goto( checkoutBlockPageSlug );
|
||||
await expect(
|
||||
page.getByRole( 'heading', { name: checkoutBlockPageTitle } )
|
||||
).toBeVisible();
|
||||
|
||||
await expect(
|
||||
page.locator(
|
||||
'.wp-block-woocommerce-checkout-order-summary-subtotal-block'
|
||||
)
|
||||
).toContainText( '$100.00' );
|
||||
await expect(
|
||||
page.locator( '.wc-block-components-totals-footer-item' )
|
||||
).toContainText( '$125.00' );
|
||||
await expect(
|
||||
page.locator( '.wc-block-components-totals-taxes' )
|
||||
).toContainText( '$25.00' );
|
||||
} );
|
||||
} );
|
||||
} );
|
||||
|
||||
test.describe( 'Shopper Cart Block Tax Rounding', () => {
|
||||
test.describe( 'Shopper Cart & Checkout Block Tax Rounding', () => {
|
||||
test.beforeAll( async ( { baseURL } ) => {
|
||||
const api = new wcApi( {
|
||||
url: baseURL,
|
||||
|
@ -294,7 +382,7 @@ test.describe( 'Shopper Cart Block Tax Rounding', () => {
|
|||
} );
|
||||
} );
|
||||
|
||||
test( 'that tax rounding is present at subtotal level', async ( {
|
||||
test( 'that tax rounding is present at subtotal level in blockbased Cart & Checkout pages', async ( {
|
||||
page,
|
||||
baseURL,
|
||||
} ) => {
|
||||
|
@ -313,9 +401,11 @@ test.describe( 'Shopper Cart Block Tax Rounding', () => {
|
|||
await api.put( 'settings/tax/woocommerce_tax_total_display', {
|
||||
value: 'single',
|
||||
} );
|
||||
await page.goto( pageSlug );
|
||||
|
||||
await test.step( 'Load cart page and confirm price display', async () => {
|
||||
await page.goto( cartBlockPageSlug );
|
||||
await expect(
|
||||
page.getByRole( 'heading', { name: pageTitle } )
|
||||
page.getByRole( 'heading', { name: cartBlockPageTitle } )
|
||||
).toBeVisible();
|
||||
|
||||
await expect(
|
||||
|
@ -331,7 +421,27 @@ test.describe( 'Shopper Cart Block Tax Rounding', () => {
|
|||
).toContainText( '$9.71' );
|
||||
} );
|
||||
|
||||
test( 'that tax rounding is off at subtotal level', async ( {
|
||||
await test.step( 'Load checkout page and confirm price display', async () => {
|
||||
await page.goto( checkoutBlockPageSlug );
|
||||
await expect(
|
||||
page.getByRole( 'heading', { name: checkoutBlockPageTitle } )
|
||||
).toBeVisible();
|
||||
|
||||
await expect(
|
||||
page.locator(
|
||||
'.wp-block-woocommerce-checkout-order-summary-subtotal-block'
|
||||
)
|
||||
).toContainText( '$40.41' );
|
||||
await expect(
|
||||
page.locator( '.wc-block-components-totals-footer-item' )
|
||||
).toContainText( '$50.12' );
|
||||
await expect(
|
||||
page.locator( '.wc-block-components-totals-taxes' )
|
||||
).toContainText( '$9.71' );
|
||||
} );
|
||||
} );
|
||||
|
||||
test( 'that tax rounding is off at subtotal level in blockbased Cart & Checkout pages', async ( {
|
||||
page,
|
||||
baseURL,
|
||||
} ) => {
|
||||
|
@ -350,9 +460,11 @@ test.describe( 'Shopper Cart Block Tax Rounding', () => {
|
|||
await api.put( 'settings/tax/woocommerce_tax_total_display', {
|
||||
value: 'itemized',
|
||||
} );
|
||||
await page.goto( pageSlug );
|
||||
|
||||
await test.step( 'Load cart page and confirm price display', async () => {
|
||||
await page.goto( cartBlockPageSlug );
|
||||
await expect(
|
||||
page.getByRole( 'heading', { name: pageTitle } )
|
||||
page.getByRole( 'heading', { name: cartBlockPageTitle } )
|
||||
).toBeVisible();
|
||||
|
||||
await expect(
|
||||
|
@ -374,9 +486,36 @@ test.describe( 'Shopper Cart Block Tax Rounding', () => {
|
|||
)
|
||||
).toContainText( '$2.84' );
|
||||
} );
|
||||
|
||||
await test.step( 'Load checkout page and confirm price display', async () => {
|
||||
await page.goto( checkoutBlockPageSlug );
|
||||
await expect(
|
||||
page.getByRole( 'heading', { name: checkoutBlockPageTitle } )
|
||||
).toBeVisible();
|
||||
|
||||
await expect(
|
||||
page.locator(
|
||||
'.wp-block-woocommerce-checkout-order-summary-subtotal-block'
|
||||
)
|
||||
).toContainText( '$40.41' );
|
||||
await expect(
|
||||
page.locator( '.wc-block-components-totals-footer-item' )
|
||||
).toContainText( '$50.12' );
|
||||
await expect(
|
||||
page.locator(
|
||||
'.wp-block-woocommerce-checkout-order-summary-taxes-block'
|
||||
)
|
||||
).toContainText( '$6.87' );
|
||||
await expect(
|
||||
page.locator(
|
||||
'.wp-block-woocommerce-checkout-order-summary-taxes-block'
|
||||
)
|
||||
).toContainText( '$2.84' );
|
||||
} );
|
||||
} );
|
||||
} );
|
||||
|
||||
test.describe( 'Shopper Cart Block Tax Levels', () => {
|
||||
test.describe( 'Shopper Cart & Checkout Block Tax Levels', () => {
|
||||
test.beforeAll( async ( { baseURL } ) => {
|
||||
const api = new wcApi( {
|
||||
url: baseURL,
|
||||
|
@ -558,9 +697,10 @@ test.describe( 'Shopper Cart Block Tax Levels', () => {
|
|||
'Shipping costs updated.'
|
||||
);
|
||||
|
||||
await page.goto( pageSlug );
|
||||
await test.step( 'Load cart page and confirm price display', async () => {
|
||||
await page.goto( cartBlockPageSlug );
|
||||
await expect(
|
||||
page.getByRole( 'heading', { name: pageTitle } )
|
||||
page.getByRole( 'heading', { name: cartBlockPageTitle } )
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page.locator(
|
||||
|
@ -592,7 +732,43 @@ test.describe( 'Shopper Cart Block Tax Levels', () => {
|
|||
).toContainText( '$1.25' );
|
||||
} );
|
||||
|
||||
test( 'that applying taxes in Cart Block of 2 different levels (2 excluded) calculates properly', async ( {
|
||||
await test.step( 'Load checkout page and confirm price display', async () => {
|
||||
await page.goto( checkoutBlockPageSlug );
|
||||
await expect(
|
||||
page.getByRole( 'heading', { name: checkoutBlockPageTitle } )
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page.locator(
|
||||
'.wp-block-woocommerce-checkout-order-summary-subtotal-block'
|
||||
)
|
||||
).toContainText( '$100.00' );
|
||||
await expect(
|
||||
page.locator( '.wc-block-components-totals-footer-item' )
|
||||
).toContainText( '$118.75' );
|
||||
await expect(
|
||||
page.locator(
|
||||
'.wp-block-woocommerce-checkout-order-summary-taxes-block'
|
||||
)
|
||||
).toContainText( '$10.00' );
|
||||
await expect(
|
||||
page.locator(
|
||||
'.wp-block-woocommerce-checkout-order-summary-taxes-block'
|
||||
)
|
||||
).toContainText( '$5.00' );
|
||||
await expect(
|
||||
page.locator(
|
||||
'.wp-block-woocommerce-checkout-order-summary-taxes-block'
|
||||
)
|
||||
).toContainText( '$2.50' );
|
||||
await expect(
|
||||
page.locator(
|
||||
'.wp-block-woocommerce-checkout-order-summary-taxes-block'
|
||||
)
|
||||
).toContainText( '$1.25' );
|
||||
} );
|
||||
} );
|
||||
|
||||
test( 'that applying taxes in blockbased Cart & Checkout of 2 different levels (2 excluded) calculates properly', async ( {
|
||||
page,
|
||||
baseURL,
|
||||
} ) => {
|
||||
|
@ -605,9 +781,11 @@ test.describe( 'Shopper Cart Block Tax Levels', () => {
|
|||
await api.put( 'settings/tax/woocommerce_tax_total_display', {
|
||||
value: 'itemized',
|
||||
} );
|
||||
await page.goto( pageSlug );
|
||||
|
||||
await test.step( 'Load cart page and confirm price display', async () => {
|
||||
await page.goto( cartBlockPageSlug );
|
||||
await expect(
|
||||
page.getByRole( 'heading', { name: pageTitle } )
|
||||
page.getByRole( 'heading', { name: cartBlockPageTitle } )
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page.locator(
|
||||
|
@ -628,9 +806,35 @@ test.describe( 'Shopper Cart Block Tax Levels', () => {
|
|||
)
|
||||
).toContainText( '$5.00' );
|
||||
} );
|
||||
|
||||
await test.step( 'Load checkout page and confirm price display', async () => {
|
||||
await page.goto( checkoutBlockPageSlug );
|
||||
await expect(
|
||||
page.getByRole( 'heading', { name: checkoutBlockPageTitle } )
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page.locator(
|
||||
'.wp-block-woocommerce-checkout-order-summary-subtotal-block'
|
||||
)
|
||||
).toContainText( '$100.00' );
|
||||
await expect(
|
||||
page.locator( '.wc-block-components-totals-footer-item' )
|
||||
).toContainText( '$115.00' );
|
||||
await expect(
|
||||
page.locator(
|
||||
'.wp-block-woocommerce-checkout-order-summary-taxes-block'
|
||||
)
|
||||
).toContainText( '$10.00' );
|
||||
await expect(
|
||||
page.locator(
|
||||
'.wp-block-woocommerce-checkout-order-summary-taxes-block'
|
||||
)
|
||||
).toContainText( '$5.00' );
|
||||
} );
|
||||
} );
|
||||
} );
|
||||
|
||||
test.describe( 'Shipping Cart Block Tax', () => {
|
||||
test.describe( 'Shipping Cart & Checkout Block Tax', () => {
|
||||
test.beforeAll( async ( { baseURL } ) => {
|
||||
const api = new wcApi( {
|
||||
url: baseURL,
|
||||
|
@ -743,9 +947,11 @@ test.describe( 'Shipping Cart Block Tax', () => {
|
|||
await api.put( 'settings/tax/woocommerce_tax_display_cart', {
|
||||
value: 'incl',
|
||||
} );
|
||||
await page.goto( pageSlug );
|
||||
|
||||
await test.step( 'Load cart page and confirm price display', async () => {
|
||||
await page.goto( cartBlockPageSlug );
|
||||
await expect(
|
||||
page.getByRole( 'heading', { name: pageTitle } )
|
||||
page.getByRole( 'heading', { name: cartBlockPageTitle } )
|
||||
).toBeVisible();
|
||||
|
||||
await expect(
|
||||
|
@ -762,4 +968,26 @@ test.describe( 'Shipping Cart Block Tax', () => {
|
|||
page.locator( '.wc-block-components-totals-footer-item' )
|
||||
).toContainText( '$138.00' );
|
||||
} );
|
||||
|
||||
await test.step( 'Load checkout page and confirm price display', async () => {
|
||||
await page.goto( checkoutBlockPageSlug );
|
||||
await expect(
|
||||
page.getByRole( 'heading', { name: checkoutBlockPageTitle } )
|
||||
).toBeVisible();
|
||||
|
||||
await expect(
|
||||
page.locator(
|
||||
'.wp-block-woocommerce-checkout-order-summary-subtotal-block'
|
||||
)
|
||||
).toContainText( '$115.00' );
|
||||
await expect(
|
||||
page.locator(
|
||||
'.wp-block-woocommerce-checkout-order-summary-shipping-block'
|
||||
)
|
||||
).toContainText( '$23.00' );
|
||||
await expect(
|
||||
page.locator( '.wc-block-components-totals-footer-item' )
|
||||
).toContainText( '$138.00' );
|
||||
} );
|
||||
} );
|
||||
} );
|
|
@ -0,0 +1,317 @@
|
|||
const { test, expect } = require( '@playwright/test' );
|
||||
const { admin } = require( '../../test-data/data' );
|
||||
const wcApi = require( '@woocommerce/woocommerce-rest-api' ).default;
|
||||
|
||||
const simpleProductName = 'Checkout Coupons Product';
|
||||
const singleProductFullPrice = '110.00';
|
||||
const singleProductSalePrice = '55.00';
|
||||
const coupons = [
|
||||
{
|
||||
code: '5fixedcheckout',
|
||||
discount_type: 'fixed_cart',
|
||||
amount: '5.00',
|
||||
},
|
||||
{
|
||||
code: '50percoffcheckout',
|
||||
discount_type: 'percent',
|
||||
amount: '50',
|
||||
},
|
||||
{
|
||||
code: '10fixedproductcheckout',
|
||||
discount_type: 'fixed_product',
|
||||
amount: '10.00',
|
||||
},
|
||||
];
|
||||
const couponLimitedCode = '10fixedcheckoutlimited';
|
||||
const customerBilling = {
|
||||
email: 'john.doe.merchant.test@example.com',
|
||||
};
|
||||
|
||||
const pageTitle = 'Checkout Block';
|
||||
const pageSlug = pageTitle.replace( / /gi, '-' ).toLowerCase();
|
||||
|
||||
let productId, orderId, limitedCouponId;
|
||||
|
||||
test.describe( 'Checkout Block Applying Coupons', () => {
|
||||
const couponBatchId = new Array();
|
||||
|
||||
test.beforeAll( async ( { baseURL } ) => {
|
||||
const api = new wcApi( {
|
||||
url: baseURL,
|
||||
consumerKey: process.env.CONSUMER_KEY,
|
||||
consumerSecret: process.env.CONSUMER_SECRET,
|
||||
version: 'wc/v3',
|
||||
} );
|
||||
// make sure the currency is USD
|
||||
await api.put( 'settings/general/woocommerce_currency', {
|
||||
value: 'USD',
|
||||
} );
|
||||
// add a product
|
||||
await api
|
||||
.post( 'products', {
|
||||
name: simpleProductName,
|
||||
type: 'simple',
|
||||
regular_price: singleProductFullPrice,
|
||||
sale_price: singleProductSalePrice,
|
||||
} )
|
||||
.then( ( response ) => {
|
||||
productId = response.data.id;
|
||||
} );
|
||||
// add coupons
|
||||
await api
|
||||
.post( 'coupons/batch', {
|
||||
create: coupons,
|
||||
} )
|
||||
.then( ( response ) => {
|
||||
for ( let i = 0; i < response.data.create.length; i++ ) {
|
||||
couponBatchId.push( response.data.create[ i ].id );
|
||||
}
|
||||
} );
|
||||
// add limited coupon
|
||||
await api
|
||||
.post( 'coupons', {
|
||||
code: couponLimitedCode,
|
||||
discount_type: 'fixed_cart',
|
||||
amount: '10.00',
|
||||
usage_limit: 1,
|
||||
usage_count: 1,
|
||||
} )
|
||||
.then( ( response ) => {
|
||||
limitedCouponId = response.data.id;
|
||||
} );
|
||||
// add order with applied limited coupon
|
||||
await api
|
||||
.post( 'orders', {
|
||||
status: 'processing',
|
||||
billing: customerBilling,
|
||||
coupon_lines: [
|
||||
{
|
||||
code: couponLimitedCode,
|
||||
},
|
||||
],
|
||||
} )
|
||||
.then( ( response ) => {
|
||||
orderId = response.data.id;
|
||||
} );
|
||||
} );
|
||||
|
||||
test.afterAll( async ( { baseURL } ) => {
|
||||
const api = new wcApi( {
|
||||
url: baseURL,
|
||||
consumerKey: process.env.CONSUMER_KEY,
|
||||
consumerSecret: process.env.CONSUMER_SECRET,
|
||||
version: 'wc/v3',
|
||||
} );
|
||||
await api.post( 'products/batch', {
|
||||
delete: [ productId ],
|
||||
} );
|
||||
await api.post( 'coupons/batch', {
|
||||
delete: [ ...couponBatchId, limitedCouponId ],
|
||||
} );
|
||||
await api.post( 'orders/batch', {
|
||||
delete: [ orderId ],
|
||||
} );
|
||||
} );
|
||||
|
||||
test.beforeEach( async ( { context } ) => {
|
||||
// Shopping cart is very sensitive to cookies, so be explicit
|
||||
await context.clearCookies();
|
||||
} );
|
||||
|
||||
test( 'can create checkout block page', async ( { page } ) => {
|
||||
// create a new page with checkout block
|
||||
await page.goto( 'wp-admin/post-new.php?post_type=page' );
|
||||
await page.waitForLoadState( 'networkidle' );
|
||||
await page.locator( 'input[name="log"]' ).fill( admin.username );
|
||||
await page.locator( 'input[name="pwd"]' ).fill( admin.password );
|
||||
await page.locator( 'text=Log In' ).click();
|
||||
|
||||
// Close welcome popup if prompted
|
||||
try {
|
||||
await page
|
||||
.getByLabel( 'Close', { exact: true } )
|
||||
.click( { timeout: 5000 } );
|
||||
} catch ( error ) {
|
||||
console.log( "Welcome modal wasn't present, skipping action." );
|
||||
}
|
||||
|
||||
await page
|
||||
.getByRole( 'textbox', { name: 'Add title' } )
|
||||
.fill( pageTitle );
|
||||
await page.getByRole( 'button', { name: 'Add default block' } ).click();
|
||||
await page
|
||||
.getByRole( 'document', {
|
||||
name: 'Empty block; start writing or type forward slash to choose a block',
|
||||
} )
|
||||
.fill( '/checkout' );
|
||||
await page.keyboard.press( 'Enter' );
|
||||
await page
|
||||
.getByRole( 'button', { name: 'Publish', exact: true } )
|
||||
.click();
|
||||
await page
|
||||
.getByRole( 'region', { name: 'Editor publish' } )
|
||||
.getByRole( 'button', { name: 'Publish', exact: true } )
|
||||
.click();
|
||||
await expect(
|
||||
page.getByText( `${ pageTitle } is now live.` )
|
||||
).toBeVisible();
|
||||
} );
|
||||
|
||||
test( 'allows checkout block to apply coupon of any type', async ( {
|
||||
page,
|
||||
} ) => {
|
||||
const totals = [ '$50.00', '$27.50', '$45.00' ];
|
||||
// add product to cart block and go to checkout
|
||||
await page.goto( `/shop/?add-to-cart=${ productId }` );
|
||||
await page.waitForLoadState( 'networkidle' );
|
||||
await page.goto( pageSlug );
|
||||
await expect(
|
||||
page.getByRole( 'heading', { name: pageTitle } )
|
||||
).toBeVisible();
|
||||
|
||||
// apply all coupon types
|
||||
for ( let i = 0; i < coupons.length; i++ ) {
|
||||
await page.getByRole( 'button', { name: 'Add a coupon' } ).click();
|
||||
await page
|
||||
.locator( '#wc-block-components-totals-coupon__input-0' )
|
||||
.fill( coupons[ i ].code );
|
||||
await page.getByText( 'Apply', { exact: true } ).click();
|
||||
await expect(
|
||||
page
|
||||
.locator( '.wc-block-components-notice-banner__content' )
|
||||
.getByText(
|
||||
`Coupon code "${ coupons[ i ].code }" has been applied to your cart.`
|
||||
)
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page.locator(
|
||||
'.wc-block-components-totals-footer-item > .wc-block-components-totals-item__value'
|
||||
)
|
||||
).toHaveText( totals[ i ] );
|
||||
await page
|
||||
.getByLabel( `Remove coupon "${ coupons[ i ].code }"` )
|
||||
.click();
|
||||
await expect(
|
||||
page
|
||||
.locator( '.wc-block-components-notice-banner__content' )
|
||||
.getByText(
|
||||
`Coupon code "${ coupons[ i ].code }" has been removed from your cart.`
|
||||
)
|
||||
).toBeVisible();
|
||||
}
|
||||
} );
|
||||
|
||||
test( 'allows checkout block to apply multiple coupons', async ( {
|
||||
page,
|
||||
} ) => {
|
||||
const totals = [ '$50.00', '$22.50', '$12.50' ];
|
||||
const totalsReverse = [ '$17.50', '$45.00', '$55.00' ];
|
||||
const discounts = [ '-$5.00', '-$32.50', '-$42.50' ];
|
||||
// add product to cart block and go to checkout
|
||||
await page.goto( `/shop/?add-to-cart=${ productId }` );
|
||||
await page.waitForLoadState( 'networkidle' );
|
||||
await page.goto( pageSlug );
|
||||
await expect(
|
||||
page.getByRole( 'heading', { name: pageTitle } )
|
||||
).toBeVisible();
|
||||
|
||||
// add all coupons and verify prices
|
||||
for ( let i = 0; i < coupons.length; i++ ) {
|
||||
await page.getByRole( 'button', { name: 'Add a coupon' } ).click();
|
||||
await page
|
||||
.locator( '#wc-block-components-totals-coupon__input-0' )
|
||||
.fill( coupons[ i ].code );
|
||||
await page.getByText( 'Apply', { exact: true } ).click();
|
||||
await expect(
|
||||
page
|
||||
.locator( '.wc-block-components-notice-banner__content' )
|
||||
.getByText(
|
||||
`Coupon code "${ coupons[ i ].code }" has been applied to your cart.`
|
||||
)
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page.locator(
|
||||
'.wc-block-components-totals-discount > .wc-block-components-totals-item__value'
|
||||
)
|
||||
).toHaveText( discounts[ i ] );
|
||||
await expect(
|
||||
page.locator(
|
||||
'.wc-block-components-totals-footer-item > .wc-block-components-totals-item__value'
|
||||
)
|
||||
).toHaveText( totals[ i ] );
|
||||
}
|
||||
|
||||
for ( let i = 0; i < coupons.length; i++ ) {
|
||||
await page
|
||||
.getByLabel( `Remove coupon "${ coupons[ i ].code }"` )
|
||||
.click();
|
||||
await expect(
|
||||
page.locator(
|
||||
'.wc-block-components-totals-footer-item > .wc-block-components-totals-item__value'
|
||||
)
|
||||
).toHaveText( totalsReverse[ i ] );
|
||||
}
|
||||
} );
|
||||
|
||||
test( 'prevents checkout block applying same coupon twice', async ( {
|
||||
page,
|
||||
} ) => {
|
||||
// add product to cart block and go to checkout
|
||||
await page.goto( `/shop/?add-to-cart=${ productId }` );
|
||||
await page.waitForLoadState( 'networkidle' );
|
||||
await page.goto( pageSlug );
|
||||
await expect(
|
||||
page.getByRole( 'heading', { name: pageTitle } )
|
||||
).toBeVisible();
|
||||
|
||||
// try to add two same coupons and verify the error message
|
||||
await page.getByRole( 'button', { name: 'Add a coupon' } ).click();
|
||||
await page
|
||||
.locator( '#wc-block-components-totals-coupon__input-0' )
|
||||
.fill( coupons[ 0 ].code );
|
||||
await page.getByText( 'Apply', { exact: true } ).click();
|
||||
await expect(
|
||||
page
|
||||
.locator( '.wc-block-components-notice-banner__content' )
|
||||
.getByText(
|
||||
`Coupon code "${ coupons[ 0 ].code }" has been applied to your cart.`
|
||||
)
|
||||
).toBeVisible();
|
||||
await page.getByRole( 'button', { name: 'Add a coupon' } ).click();
|
||||
await page
|
||||
.locator( '#wc-block-components-totals-coupon__input-0' )
|
||||
.fill( coupons[ 0 ].code );
|
||||
await page.getByText( 'Apply', { exact: true } ).click();
|
||||
await expect(
|
||||
page
|
||||
.getByRole( 'alert' )
|
||||
.getByText(
|
||||
`Coupon code "${ coupons[ 0 ].code }" has already been applied.`
|
||||
)
|
||||
).toBeVisible();
|
||||
} );
|
||||
|
||||
test( 'prevents checkout block applying coupon with usage limit', async ( {
|
||||
page,
|
||||
} ) => {
|
||||
// add product to cart block and go to checkout
|
||||
await page.goto( `/shop/?add-to-cart=${ productId }` );
|
||||
await page.waitForLoadState( 'networkidle' );
|
||||
await page.goto( pageSlug );
|
||||
await expect(
|
||||
page.getByRole( 'heading', { name: pageTitle } )
|
||||
).toBeVisible();
|
||||
|
||||
// add coupon with usage limit
|
||||
await page.getByRole( 'button', { name: 'Add a coupon' } ).click();
|
||||
await page
|
||||
.locator( '#wc-block-components-totals-coupon__input-0' )
|
||||
.fill( couponLimitedCode );
|
||||
await page.getByText( 'Apply', { exact: true } ).click();
|
||||
await expect(
|
||||
page
|
||||
.getByRole( 'alert' )
|
||||
.getByText( 'Coupon usage limit has been reached.' )
|
||||
).toBeVisible();
|
||||
} );
|
||||
} );
|
|
@ -0,0 +1,865 @@
|
|||
const { test, expect } = require( '@playwright/test' );
|
||||
const wcApi = require( '@woocommerce/woocommerce-rest-api' ).default;
|
||||
const { admin, customer } = require( '../../test-data/data' );
|
||||
const { setFilterValue, clearFilters } = require( '../../utils/filters' );
|
||||
const { addProductsToCart } = require( '../../utils/pdp' );
|
||||
const {
|
||||
fillShippingCheckoutBlocks,
|
||||
fillBillingCheckoutBlocks,
|
||||
} = require( '../../utils/checkout' );
|
||||
|
||||
const guestEmail = 'checkout-guest@example.com';
|
||||
const newAccountEmail = 'marge-test-account@example.com';
|
||||
|
||||
const simpleProductName = 'Very Simple Product';
|
||||
const simpleProductDesc = 'Lorem ipsum dolor.';
|
||||
const singleProductFullPrice = '150.00';
|
||||
const singleProductSalePrice = '75.00';
|
||||
const twoProductPrice = ( singleProductSalePrice * 2 ).toString();
|
||||
const threeProductPrice = ( singleProductSalePrice * 3 ).toString();
|
||||
|
||||
const pageTitle = 'Checkout Block';
|
||||
const pageSlug = pageTitle.replace( / /gi, '-' ).toLowerCase();
|
||||
|
||||
let guestOrderId1,
|
||||
guestOrderId2,
|
||||
customerOrderId,
|
||||
newAccountOrderId,
|
||||
productId,
|
||||
shippingZoneId;
|
||||
|
||||
test.describe( 'Checkout Block page', () => {
|
||||
test.beforeAll( async ( { baseURL } ) => {
|
||||
const api = new wcApi( {
|
||||
url: baseURL,
|
||||
consumerKey: process.env.CONSUMER_KEY,
|
||||
consumerSecret: process.env.CONSUMER_SECRET,
|
||||
version: 'wc/v3',
|
||||
} );
|
||||
// ensure store address is US
|
||||
await api.post( 'settings/general/batch', {
|
||||
update: [
|
||||
{
|
||||
id: 'woocommerce_store_address',
|
||||
value: 'addr 1',
|
||||
},
|
||||
{
|
||||
id: 'woocommerce_store_city',
|
||||
value: 'San Francisco',
|
||||
},
|
||||
{
|
||||
id: 'woocommerce_default_country',
|
||||
value: 'US:CA',
|
||||
},
|
||||
{
|
||||
id: 'woocommerce_store_postcode',
|
||||
value: '94107',
|
||||
},
|
||||
],
|
||||
} );
|
||||
// add product
|
||||
await api
|
||||
.post( 'products', {
|
||||
name: simpleProductName,
|
||||
description: simpleProductDesc,
|
||||
type: 'simple',
|
||||
regular_price: singleProductFullPrice,
|
||||
sale_price: singleProductSalePrice,
|
||||
} )
|
||||
.then( ( response ) => {
|
||||
productId = response.data.id;
|
||||
} );
|
||||
// enable logging through checkout
|
||||
await api.put(
|
||||
'settings/account/woocommerce_enable_checkout_login_reminder',
|
||||
{
|
||||
value: 'yes',
|
||||
}
|
||||
);
|
||||
// enable creating account through checkout
|
||||
await api.put(
|
||||
'settings/account/woocommerce_enable_signup_and_login_from_checkout',
|
||||
{
|
||||
value: 'yes',
|
||||
}
|
||||
);
|
||||
// add a shipping zone and method
|
||||
await api
|
||||
.post( 'shipping/zones', {
|
||||
name: 'California and Oregon Shipping Zone',
|
||||
} )
|
||||
.then( ( response ) => {
|
||||
shippingZoneId = response.data.id;
|
||||
} );
|
||||
await api.put( `shipping/zones/${ shippingZoneId }/locations`, [
|
||||
{
|
||||
code: 'US:CA',
|
||||
type: 'state',
|
||||
},
|
||||
{
|
||||
code: 'US:OR',
|
||||
type: 'state',
|
||||
},
|
||||
] );
|
||||
await api.post( `shipping/zones/${ shippingZoneId }/methods`, {
|
||||
method_id: 'free_shipping',
|
||||
settings: {
|
||||
title: 'Free shipping',
|
||||
},
|
||||
} );
|
||||
await api.post( `shipping/zones/${ shippingZoneId }/methods`, {
|
||||
method_id: 'local_pickup',
|
||||
settings: {
|
||||
title: 'Local pickup',
|
||||
},
|
||||
} );
|
||||
await api.post( `shipping/zones/${ shippingZoneId }/methods`, {
|
||||
method_id: 'flat_rate',
|
||||
settings: {
|
||||
title: 'Flat rate',
|
||||
cost: singleProductSalePrice,
|
||||
},
|
||||
} );
|
||||
// enable bank transfers and COD for payment
|
||||
await api.put( 'payment_gateways/bacs', {
|
||||
enabled: true,
|
||||
} );
|
||||
await api.put( 'payment_gateways/cod', {
|
||||
enabled: true,
|
||||
} );
|
||||
// make sure there's no pre-existing customer that has the same email we're going to use for account creation
|
||||
const { data: customersList } = await api.get( 'customers', {
|
||||
email: newAccountEmail,
|
||||
} );
|
||||
|
||||
if ( customersList && customersList.length ) {
|
||||
const customerId = customersList[ 0 ].id;
|
||||
|
||||
console.log(
|
||||
`Customer with email ${ newAccountEmail } exists! Deleting it before starting test...`
|
||||
);
|
||||
|
||||
await api.delete( `customers/${ customerId }`, { force: true } );
|
||||
}
|
||||
} );
|
||||
|
||||
test.afterAll( async ( { baseURL } ) => {
|
||||
const api = new wcApi( {
|
||||
url: baseURL,
|
||||
consumerKey: process.env.CONSUMER_KEY,
|
||||
consumerSecret: process.env.CONSUMER_SECRET,
|
||||
version: 'wc/v3',
|
||||
} );
|
||||
await api.delete( `products/${ productId }`, {
|
||||
force: true,
|
||||
} );
|
||||
await api.delete( `shipping/zones/${ shippingZoneId }`, {
|
||||
force: true,
|
||||
} );
|
||||
await api.put( 'payment_gateways/bacs', {
|
||||
enabled: false,
|
||||
} );
|
||||
await api.put( 'payment_gateways/cod', {
|
||||
enabled: false,
|
||||
} );
|
||||
await api.put(
|
||||
'settings/account/woocommerce_enable_checkout_login_reminder',
|
||||
{
|
||||
value: 'no',
|
||||
}
|
||||
);
|
||||
await api.put(
|
||||
'settings/account/woocommerce_enable_signup_and_login_from_checkout',
|
||||
{
|
||||
value: 'no',
|
||||
}
|
||||
);
|
||||
// delete the orders we created
|
||||
if ( guestOrderId1 ) {
|
||||
await api.delete( `orders/${ guestOrderId1 }`, { force: true } );
|
||||
}
|
||||
if ( guestOrderId2 ) {
|
||||
await api.delete( `orders/${ guestOrderId2 }`, { force: true } );
|
||||
}
|
||||
if ( customerOrderId ) {
|
||||
await api.delete( `orders/${ customerOrderId }`, { force: true } );
|
||||
}
|
||||
if ( newAccountOrderId ) {
|
||||
await api.delete( `orders/${ newAccountOrderId }`, {
|
||||
force: true,
|
||||
} );
|
||||
}
|
||||
// clear out the customer we create during the test
|
||||
await api.get( 'customers' ).then( async ( response ) => {
|
||||
for ( let i = 0; i < response.data.length; i++ ) {
|
||||
if ( response.data[ i ].billing.email === newAccountEmail ) {
|
||||
await api.delete( `customers/${ response.data[ i ].id }`, {
|
||||
force: true,
|
||||
} );
|
||||
}
|
||||
}
|
||||
} );
|
||||
} );
|
||||
|
||||
test.beforeEach( async ( { context } ) => {
|
||||
// Shopping cart is very sensitive to cookies, so be explicit
|
||||
await context.clearCookies();
|
||||
} );
|
||||
|
||||
test( 'can see empty checkout block page', async ( { page } ) => {
|
||||
// create a new page with checkout block
|
||||
await page.goto( 'wp-admin/post-new.php?post_type=page' );
|
||||
await page.waitForLoadState( 'networkidle' );
|
||||
await page.locator( 'input[name="log"]' ).fill( admin.username );
|
||||
await page.locator( 'input[name="pwd"]' ).fill( admin.password );
|
||||
await page.locator( 'text=Log In' ).click();
|
||||
|
||||
// Close welcome popup if prompted
|
||||
try {
|
||||
await page
|
||||
.getByLabel( 'Close', { exact: true } )
|
||||
.click( { timeout: 5000 } );
|
||||
} catch ( error ) {
|
||||
console.log( "Welcome modal wasn't present, skipping action." );
|
||||
}
|
||||
|
||||
await page
|
||||
.getByRole( 'textbox', { name: 'Add title' } )
|
||||
.fill( pageTitle );
|
||||
await page.getByRole( 'button', { name: 'Add default block' } ).click();
|
||||
await page
|
||||
.getByRole( 'document', {
|
||||
name: 'Empty block; start writing or type forward slash to choose a block',
|
||||
} )
|
||||
.fill( '/checkout' );
|
||||
await page.keyboard.press( 'Enter' );
|
||||
await page
|
||||
.getByRole( 'button', { name: 'Publish', exact: true } )
|
||||
.click();
|
||||
await page
|
||||
.getByRole( 'region', { name: 'Editor publish' } )
|
||||
.getByRole( 'button', { name: 'Publish', exact: true } )
|
||||
.click();
|
||||
await expect(
|
||||
page.getByText( `${ pageTitle } is now live.` )
|
||||
).toBeVisible();
|
||||
|
||||
// go to the page to test empty cart block
|
||||
await page.goto( pageSlug );
|
||||
await expect(
|
||||
page.getByRole( 'heading', { name: pageTitle } )
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page.getByText( 'Your cart is currently empty!' )
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page.getByRole( 'link', { name: 'Browse store' } )
|
||||
).toBeVisible();
|
||||
await page.getByRole( 'link', { name: 'Browse store' } ).click();
|
||||
await expect(
|
||||
page.getByRole( 'heading', { name: 'Shop' } )
|
||||
).toBeVisible();
|
||||
} );
|
||||
|
||||
test( 'allows customer to choose available payment methods', async ( {
|
||||
page,
|
||||
} ) => {
|
||||
// this time we're going to add two products to the cart
|
||||
await addProductsToCart( page, simpleProductName, '2' );
|
||||
|
||||
await page.goto( pageSlug );
|
||||
await expect(
|
||||
page.getByRole( 'heading', { name: pageTitle } )
|
||||
).toBeVisible();
|
||||
|
||||
// check the order summary
|
||||
await expect(
|
||||
page.locator( '.wc-block-components-order-summary-item__quantity' )
|
||||
).toContainText( '2' );
|
||||
await expect(
|
||||
page.locator(
|
||||
'.wc-block-components-order-summary-item__individual-price'
|
||||
)
|
||||
).toContainText( `$${ singleProductSalePrice }` );
|
||||
await expect(
|
||||
page.locator( '.wc-block-components-product-metadata__description' )
|
||||
).toContainText( simpleProductDesc );
|
||||
await expect(
|
||||
page.locator(
|
||||
'.wc-block-components-totals-footer-item > .wc-block-components-totals-item__value'
|
||||
)
|
||||
).toContainText( twoProductPrice );
|
||||
|
||||
// check the payment methods
|
||||
await expect( page.getByLabel( 'Direct bank transfer' ) ).toBeVisible();
|
||||
await expect( page.getByLabel( 'Cash on delivery' ) ).toBeVisible();
|
||||
await page.getByLabel( 'Cash on delivery' ).check();
|
||||
await expect( page.getByLabel( 'Cash on delivery' ) ).toBeChecked();
|
||||
} );
|
||||
|
||||
test( 'allows customer to fill shipping details', async ( { page } ) => {
|
||||
// this time we're going to add three products to the cart
|
||||
await addProductsToCart( page, simpleProductName, '3' );
|
||||
|
||||
await page.goto( pageSlug );
|
||||
await expect(
|
||||
page.getByRole( 'heading', { name: pageTitle } )
|
||||
).toBeVisible();
|
||||
|
||||
// check the order summary
|
||||
await expect(
|
||||
page.locator( '.wc-block-components-order-summary-item__quantity' )
|
||||
).toContainText( '3' );
|
||||
await expect(
|
||||
page.locator(
|
||||
'.wc-block-components-totals-footer-item > .wc-block-components-totals-item__value'
|
||||
)
|
||||
).toContainText( threeProductPrice );
|
||||
|
||||
// asserting that you can fill in the shipping details
|
||||
await expect( page.getByLabel( 'Email address' ) ).toBeEditable();
|
||||
await expect( page.getByLabel( 'First name' ) ).toBeEditable();
|
||||
await expect( page.getByLabel( 'Last name' ) ).toBeEditable();
|
||||
await expect(
|
||||
page.getByLabel( 'Address', { exact: true } )
|
||||
).toBeEditable();
|
||||
await expect(
|
||||
page.getByLabel( 'Apartment, suite, etc. (optional)' )
|
||||
).toBeEnabled();
|
||||
await expect(
|
||||
page.getByLabel( 'United States (US), Country/Region' )
|
||||
).toBeEditable();
|
||||
await expect( page.getByLabel( 'California, State' ) ).toBeEditable();
|
||||
await expect( page.getByLabel( 'City' ) ).toBeEditable();
|
||||
await expect( page.getByLabel( 'ZIP Code' ) ).toBeEnabled();
|
||||
await expect( page.getByLabel( 'Phone (optional)' ) ).toBeEditable();
|
||||
} );
|
||||
|
||||
test( 'allows customer to fill different shipping and billing details', async ( {
|
||||
page,
|
||||
} ) => {
|
||||
await page.goto( `/shop/?add-to-cart=${ productId }`, {
|
||||
waitUntil: 'networkidle',
|
||||
} );
|
||||
await page.goto( pageSlug );
|
||||
await expect(
|
||||
page.getByRole( 'heading', { name: pageTitle } )
|
||||
).toBeVisible();
|
||||
|
||||
await page.getByLabel( 'Email address' ).fill( guestEmail );
|
||||
|
||||
// fill shipping address
|
||||
await fillShippingCheckoutBlocks( page );
|
||||
|
||||
await page.getByLabel( 'Use same address for billing' ).click();
|
||||
|
||||
// fill billing details
|
||||
await fillBillingCheckoutBlocks( page );
|
||||
|
||||
// add note to the order
|
||||
await page.getByLabel( 'Add a note to your order' ).check();
|
||||
await page
|
||||
.getByPlaceholder(
|
||||
'Notes about your order, e.g. special notes for delivery.'
|
||||
)
|
||||
.fill( 'This is to avoid flakiness' );
|
||||
|
||||
// place an order
|
||||
await page.getByRole( 'button', { name: 'Place order' } ).click();
|
||||
await expect(
|
||||
page.getByRole( 'heading', { name: 'Order received' } )
|
||||
).toBeVisible();
|
||||
|
||||
// get order ID from the page
|
||||
const orderReceivedText = await page
|
||||
.locator( '.woocommerce-order-overview__order.order' )
|
||||
.textContent();
|
||||
guestOrderId2 = await orderReceivedText
|
||||
.split( /(\s+)/ )[ 6 ]
|
||||
.toString();
|
||||
|
||||
// go again to the checkout to verify details
|
||||
await page.goto( `/shop/?add-to-cart=${ productId }`, {
|
||||
waitUntil: 'networkidle',
|
||||
} );
|
||||
await page.goto( pageSlug );
|
||||
await expect(
|
||||
page.getByRole( 'heading', { name: pageTitle } )
|
||||
).toBeVisible();
|
||||
|
||||
// verify shipping details
|
||||
await page
|
||||
.getByLabel( 'Edit address', { exact: true } )
|
||||
.first()
|
||||
.click();
|
||||
await expect(
|
||||
page
|
||||
.getByRole( 'group', { name: 'Shipping address' } )
|
||||
.getByLabel( 'First name' )
|
||||
).toHaveValue( 'Homer' );
|
||||
await expect(
|
||||
page
|
||||
.getByRole( 'group', { name: 'Shipping address' } )
|
||||
.getByLabel( 'Last name' )
|
||||
).toHaveValue( 'Simpson' );
|
||||
await expect(
|
||||
page
|
||||
.getByRole( 'group', { name: 'Shipping address' } )
|
||||
.getByLabel( 'Address', { exact: true } )
|
||||
).toHaveValue( '123 Evergreen Terrace' );
|
||||
await expect(
|
||||
page
|
||||
.getByRole( 'group', { name: 'Shipping address' } )
|
||||
.getByLabel( 'City' )
|
||||
).toHaveValue( 'Springfield' );
|
||||
await expect(
|
||||
page
|
||||
.getByRole( 'group', { name: 'Shipping address' } )
|
||||
.getByLabel( 'ZIP Code' )
|
||||
).toHaveValue( '97403' );
|
||||
|
||||
// verify billing details
|
||||
// ISSUE REPORTED #42967, please uncomment below once fixed
|
||||
// await page.getByLabel( 'Edit address', { exact: true } ).last().click();
|
||||
// await expect(
|
||||
// page
|
||||
// .getByRole( 'group', { name: 'Billing address' } )
|
||||
// .getByLabel( 'First name' )
|
||||
// ).toHaveValue( 'Mister' );
|
||||
// await expect(
|
||||
// page
|
||||
// .getByRole( 'group', { name: 'Billing address' } )
|
||||
// .getByLabel( 'Last name' )
|
||||
// ).toHaveValue( 'Burns' );
|
||||
// await expect(
|
||||
// page
|
||||
// .getByRole( 'group', { name: 'Billing address' } )
|
||||
// .getByLabel( 'Address', { exact: true } )
|
||||
// ).toHaveValue( '156th Street' );
|
||||
// await expect(
|
||||
// page
|
||||
// .getByRole( 'group', { name: 'Billing address' } )
|
||||
// .getByLabel( 'City' )
|
||||
// ).toHaveValue( 'Springfield' );
|
||||
// await expect(
|
||||
// page
|
||||
// .getByRole( 'group', { name: 'Billing address' } )
|
||||
// .getByLabel( 'ZIP Code' )
|
||||
// ).toHaveValue( '98500' );
|
||||
} );
|
||||
|
||||
test( 'warn when customer is missing required details', async ( {
|
||||
page,
|
||||
} ) => {
|
||||
await page.goto( `/shop/?add-to-cart=${ productId }`, {
|
||||
waitUntil: 'networkidle',
|
||||
} );
|
||||
await page.goto( pageSlug );
|
||||
await expect(
|
||||
page.getByRole( 'heading', { name: pageTitle } )
|
||||
).toBeVisible();
|
||||
|
||||
// first try submitting the form with no fields complete
|
||||
await page.getByRole( 'button', { name: 'Place order' } ).click();
|
||||
await expect(
|
||||
page.getByText( 'Please enter a valid email address' )
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page.getByText( 'Please enter a valid first name' )
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page.getByText( 'Please enter a valid last name' )
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page.getByText( 'Please enter a valid address' )
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page.getByText( 'Please enter a valid city' )
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page.getByText( 'Please enter a valid zip code' )
|
||||
).toBeVisible();
|
||||
} );
|
||||
|
||||
test( 'allows customer to fill shipping details and toggle different billing', async ( {
|
||||
page,
|
||||
} ) => {
|
||||
await page.goto( `/shop/?add-to-cart=${ productId }`, {
|
||||
waitUntil: 'networkidle',
|
||||
} );
|
||||
await page.goto( pageSlug );
|
||||
await expect(
|
||||
page.getByRole( 'heading', { name: pageTitle } )
|
||||
).toBeVisible();
|
||||
|
||||
await page.getByLabel( 'Email address' ).fill( customer.email );
|
||||
|
||||
// fill shipping address and check the toggle to use a different address for billing
|
||||
await fillShippingCheckoutBlocks( page );
|
||||
|
||||
await expect(
|
||||
page.getByLabel( 'Use same address for billing' )
|
||||
).toBeVisible();
|
||||
await page.getByLabel( 'Use same address for billing' ).click();
|
||||
await expect(
|
||||
page
|
||||
.getByRole( 'group', { name: 'Billing address' } )
|
||||
.locator( 'h2' )
|
||||
).toBeVisible();
|
||||
} );
|
||||
|
||||
test( 'can choose different shipping types in the checkout', async ( {
|
||||
page,
|
||||
} ) => {
|
||||
await page.goto( `/shop/?add-to-cart=${ productId }`, {
|
||||
waitUntil: 'networkidle',
|
||||
} );
|
||||
await page.goto( pageSlug );
|
||||
await expect(
|
||||
page.getByRole( 'heading', { name: pageTitle } )
|
||||
).toBeVisible();
|
||||
|
||||
await page.getByLabel( 'Email address' ).fill( customer.email );
|
||||
|
||||
// fill shipping address
|
||||
await fillShippingCheckoutBlocks( page );
|
||||
|
||||
await page
|
||||
.locator( '.wc-block-components-loading-mask' )
|
||||
.waitFor( { state: 'visible' } );
|
||||
await page
|
||||
.locator( '.wc-block-components-loading-mask' )
|
||||
.waitFor( { state: 'hidden' } );
|
||||
|
||||
// check if you see all three shipping options
|
||||
await expect( page.getByLabel( 'Free shipping' ) ).toBeVisible();
|
||||
await expect( page.getByLabel( 'Local pickup' ) ).toBeVisible();
|
||||
await expect( page.getByLabel( 'Flat rate' ) ).toBeVisible();
|
||||
|
||||
// check free shipping option
|
||||
await page.getByLabel( 'Free shipping' ).check();
|
||||
await page
|
||||
.locator( '.wc-block-components-loading-mask' )
|
||||
.waitFor( { state: 'visible' } );
|
||||
await page
|
||||
.locator( '.wc-block-components-loading-mask' )
|
||||
.waitFor( { state: 'hidden' } );
|
||||
await expect( page.getByLabel( 'Free shipping' ) ).toBeChecked();
|
||||
await expect(
|
||||
page.locator( '.wc-block-components-totals-shipping__via' )
|
||||
).toHaveText( 'Free shipping' );
|
||||
await expect(
|
||||
page.locator(
|
||||
'.wc-block-components-totals-footer-item > .wc-block-components-totals-item__value'
|
||||
)
|
||||
).toContainText( singleProductSalePrice );
|
||||
|
||||
// check local pickup option
|
||||
await page.getByLabel( 'Local pickup' ).check();
|
||||
await page
|
||||
.locator( '.wc-block-components-loading-mask' )
|
||||
.waitFor( { state: 'hidden' } );
|
||||
await expect( page.getByLabel( 'Local pickup' ) ).toBeChecked();
|
||||
await expect(
|
||||
page.locator( '.wc-block-components-totals-shipping__via' )
|
||||
).toHaveText( 'Local pickup' );
|
||||
await expect(
|
||||
page.locator(
|
||||
'.wc-block-components-totals-footer-item > .wc-block-components-totals-item__value'
|
||||
)
|
||||
).toContainText( singleProductSalePrice );
|
||||
|
||||
// check flat rate option
|
||||
await page.getByLabel( 'Flat rate' ).check();
|
||||
await page
|
||||
.locator( '.wc-block-components-loading-mask' )
|
||||
.waitFor( { state: 'hidden' } );
|
||||
await expect( page.getByLabel( 'Flat rate' ) ).toBeChecked();
|
||||
await expect(
|
||||
page.locator( '.wc-block-components-totals-shipping__via' )
|
||||
).toHaveText( 'Flat rate' );
|
||||
await expect(
|
||||
page.locator(
|
||||
'.wc-block-components-totals-footer-item > .wc-block-components-totals-item__value'
|
||||
)
|
||||
).toContainText( twoProductPrice );
|
||||
} );
|
||||
|
||||
test( 'allows guest customer to place an order', async ( { page } ) => {
|
||||
await addProductsToCart( page, simpleProductName, '2' );
|
||||
|
||||
await page.goto( pageSlug );
|
||||
await expect(
|
||||
page.getByRole( 'heading', { name: pageTitle } )
|
||||
).toBeVisible();
|
||||
|
||||
await page.getByLabel( 'Email address' ).fill( guestEmail );
|
||||
|
||||
// fill shipping address and check cash on delivery method
|
||||
await fillShippingCheckoutBlocks( page );
|
||||
await page.getByLabel( 'Cash on delivery' ).check();
|
||||
await expect( page.getByLabel( 'Cash on delivery' ) ).toBeChecked();
|
||||
|
||||
// add note to the order
|
||||
await page.getByLabel( 'Add a note to your order' ).check();
|
||||
await page
|
||||
.getByPlaceholder(
|
||||
'Notes about your order, e.g. special notes for delivery.'
|
||||
)
|
||||
.fill( 'This is to avoid flakiness' );
|
||||
|
||||
// place an order
|
||||
await page.getByRole( 'button', { name: 'Place order' } ).click();
|
||||
await expect(
|
||||
page.getByRole( 'heading', { name: 'Order received' } )
|
||||
).toBeVisible();
|
||||
|
||||
// get order ID from the page
|
||||
const orderReceivedText = await page
|
||||
.locator( '.woocommerce-order-overview__order.order' )
|
||||
.textContent();
|
||||
guestOrderId1 = await orderReceivedText
|
||||
.split( /(\s+)/ )[ 6 ]
|
||||
.toString();
|
||||
|
||||
// Let's simulate a new browser context (by dropping all cookies), and reload the page. This approximates a
|
||||
// scenario where the server can no longer identify the shopper. However, so long as we are within the 10 minute
|
||||
// grace period following initial order placement, the 'order received' page should still be rendered.
|
||||
await page.context().clearCookies();
|
||||
await page.reload();
|
||||
await expect(
|
||||
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
|
||||
// be presented with a request to verify their email address.
|
||||
await setFilterValue(
|
||||
page,
|
||||
'woocommerce_order_email_verification_grace_period',
|
||||
0
|
||||
);
|
||||
await page.reload();
|
||||
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
|
||||
// page with an error message.
|
||||
await page.fill( '#email', 'incorrect@email.address' );
|
||||
await page.locator( 'form.woocommerce-verify-email button' ).click();
|
||||
await expect(
|
||||
page.locator( 'form.woocommerce-verify-email p:nth-child(4)' )
|
||||
).toContainText( /verify the email address associated with the order/ );
|
||||
await expect(
|
||||
page
|
||||
.getByRole( 'alert' )
|
||||
.getByText(
|
||||
'We were unable to verify the email address you provided. Please try again.'
|
||||
)
|
||||
).toBeVisible();
|
||||
|
||||
// However if they supply the *correct* billing email address, they should see the order received page again.
|
||||
await page.fill( '#email', guestEmail );
|
||||
await page.locator( 'form.woocommerce-verify-email button' ).click();
|
||||
await expect(
|
||||
page.getByRole( 'heading', { name: 'Order received' } )
|
||||
).toBeVisible();
|
||||
|
||||
await page.goto( 'wp-login.php' );
|
||||
await page.locator( 'input[name="log"]' ).fill( admin.username );
|
||||
await page.locator( 'input[name="pwd"]' ).fill( admin.password );
|
||||
await page.locator( 'text=Log In' ).click();
|
||||
|
||||
// load the order placed as a guest
|
||||
await page.goto(
|
||||
`wp-admin/post.php?post=${ guestOrderId1 }&action=edit`
|
||||
);
|
||||
|
||||
await expect(
|
||||
page.getByRole( 'heading', {
|
||||
name: `Order #${ guestOrderId1 } details`,
|
||||
} )
|
||||
).toBeVisible();
|
||||
await expect( page.locator( '.wc-order-item-name' ) ).toContainText(
|
||||
simpleProductName
|
||||
);
|
||||
await expect( page.locator( 'td.quantity >> nth=0' ) ).toContainText(
|
||||
'2'
|
||||
);
|
||||
await expect( page.locator( 'td.item_cost >> nth=0' ) ).toContainText(
|
||||
singleProductSalePrice
|
||||
);
|
||||
await expect( page.locator( 'td.line_cost >> nth=0' ) ).toContainText(
|
||||
twoProductPrice
|
||||
);
|
||||
await clearFilters( page );
|
||||
} );
|
||||
|
||||
test( 'allows existing customer to place an order', async ( { page } ) => {
|
||||
await addProductsToCart( page, simpleProductName, '2' );
|
||||
|
||||
await page.goto( pageSlug );
|
||||
await expect(
|
||||
page.getByRole( 'heading', { name: pageTitle } )
|
||||
).toBeVisible();
|
||||
|
||||
// click to log in and make sure you are on the same page after logging in
|
||||
await page.locator( 'text=Log in.' ).click();
|
||||
await page.waitForLoadState( 'networkidle' );
|
||||
await page
|
||||
.locator( 'input[name="username"]' )
|
||||
.fill( customer.username );
|
||||
await page
|
||||
.locator( 'input[name="password"]' )
|
||||
.fill( customer.password );
|
||||
await page.locator( 'text=Log in' ).click();
|
||||
await page.waitForLoadState( 'networkidle' );
|
||||
await expect(
|
||||
page.getByRole( 'heading', { name: pageTitle } )
|
||||
).toBeVisible();
|
||||
|
||||
// if edit address is present click it, otherwise fill shipping details
|
||||
if (
|
||||
await page
|
||||
.getByLabel( 'Edit address', { exact: true } )
|
||||
.first()
|
||||
.isVisible()
|
||||
) {
|
||||
await page
|
||||
.getByLabel( 'Edit address', { exact: true } )
|
||||
.first()
|
||||
.click();
|
||||
} else {
|
||||
console.log(
|
||||
'No saved shipping address found, filling it instead.'
|
||||
);
|
||||
// fill shipping address
|
||||
await fillShippingCheckoutBlocks( page );
|
||||
}
|
||||
|
||||
// check COD payment method
|
||||
await page.getByLabel( 'Cash on delivery' ).check();
|
||||
await expect( page.getByLabel( 'Cash on delivery' ) ).toBeChecked();
|
||||
|
||||
// add note to the order
|
||||
await page.getByLabel( 'Add a note to your order' ).check();
|
||||
await page
|
||||
.getByPlaceholder(
|
||||
'Notes about your order, e.g. special notes for delivery.'
|
||||
)
|
||||
.fill( 'This is to avoid flakiness' );
|
||||
|
||||
// place an order
|
||||
await page.getByRole( 'button', { name: 'Place order' } ).click();
|
||||
await expect(
|
||||
page.getByRole( 'heading', { name: 'Order received' } )
|
||||
).toBeVisible();
|
||||
|
||||
// get order ID from the page
|
||||
const orderReceivedText = await page
|
||||
.locator( '.woocommerce-order-overview__order.order' )
|
||||
.textContent();
|
||||
customerOrderId = await orderReceivedText
|
||||
.split( /(\s+)/ )[ 6 ]
|
||||
.toString();
|
||||
|
||||
// Effect a log out/simulate a new browsing session by dropping all cookies.
|
||||
await page.context().clearCookies();
|
||||
await page.reload();
|
||||
|
||||
// Now we are logged out, return to the confirmation page: we should be asked to log back in.
|
||||
await expect(
|
||||
page
|
||||
.getByRole( 'alert' )
|
||||
.getByText( 'Please log in to your account to view this order' )
|
||||
).toBeVisible();
|
||||
|
||||
// Switch to admin user.
|
||||
await page.goto( 'wp-login.php?loggedout=true' );
|
||||
await page.locator( 'input[name="log"]' ).fill( admin.username );
|
||||
await page.locator( 'input[name="pwd"]' ).fill( admin.password );
|
||||
await page.locator( 'text=Log In' ).click();
|
||||
|
||||
// load the order placed as a customer
|
||||
await page.goto(
|
||||
`wp-admin/post.php?post=${ customerOrderId }&action=edit`
|
||||
);
|
||||
await expect(
|
||||
page.locator( 'h2.woocommerce-order-data__heading' )
|
||||
).toContainText( `Order #${ customerOrderId } details` );
|
||||
await expect( page.locator( '.wc-order-item-name' ) ).toContainText(
|
||||
simpleProductName
|
||||
);
|
||||
await expect( page.locator( 'td.quantity >> nth=0' ) ).toContainText(
|
||||
'2'
|
||||
);
|
||||
await expect( page.locator( 'td.item_cost >> nth=0' ) ).toContainText(
|
||||
singleProductSalePrice
|
||||
);
|
||||
await expect( page.locator( 'td.line_cost >> nth=0' ) ).toContainText(
|
||||
twoProductPrice
|
||||
);
|
||||
} );
|
||||
|
||||
test( 'can create an account during checkout', async ( { page } ) => {
|
||||
await page.goto( `/shop/?add-to-cart=${ productId }`, {
|
||||
waitUntil: 'networkidle',
|
||||
} );
|
||||
await page.goto( pageSlug );
|
||||
await expect(
|
||||
page.getByRole( 'heading', { name: pageTitle } )
|
||||
).toBeVisible();
|
||||
|
||||
// check create account during checkout
|
||||
await expect( page.getByLabel( 'Create an account?' ) ).toBeVisible();
|
||||
await page.getByLabel( 'Create an account?' ).check();
|
||||
await expect( page.getByLabel( 'Create an account?' ) ).toBeChecked();
|
||||
|
||||
await page.getByLabel( 'Email address' ).fill( newAccountEmail );
|
||||
|
||||
// fill shipping address and check cash on delivery method
|
||||
await fillShippingCheckoutBlocks( page, 'Marge' );
|
||||
await page.getByLabel( 'Cash on delivery' ).check();
|
||||
await expect( page.getByLabel( 'Cash on delivery' ) ).toBeChecked();
|
||||
|
||||
// add note to the order
|
||||
await page.getByLabel( 'Add a note to your order' ).check();
|
||||
await page
|
||||
.getByPlaceholder(
|
||||
'Notes about your order, e.g. special notes for delivery.'
|
||||
)
|
||||
.fill( 'This is to avoid flakiness' );
|
||||
|
||||
// place an order
|
||||
await page.getByRole( 'button', { name: 'Place order' } ).click();
|
||||
await expect(
|
||||
page.getByRole( 'heading', { name: 'Order received' } )
|
||||
).toBeVisible();
|
||||
|
||||
// get order ID from the page
|
||||
const orderReceivedText = await page
|
||||
.locator( '.woocommerce-order-overview__order.order' )
|
||||
.textContent();
|
||||
newAccountOrderId = orderReceivedText.split( /(\s+)/ )[ 6 ].toString();
|
||||
|
||||
// confirms that an account was created
|
||||
await page.goto( '/my-account/' );
|
||||
await expect(
|
||||
page.getByRole( 'heading', { name: 'My account' } )
|
||||
).toBeVisible();
|
||||
await page
|
||||
.getByRole( 'navigation' )
|
||||
.getByRole( 'link', { name: 'Log out' } )
|
||||
.click();
|
||||
|
||||
// sign in as admin to confirm account creation
|
||||
await page.goto( 'wp-admin/users.php' );
|
||||
await page.waitForLoadState( 'networkidle' );
|
||||
await page.locator( 'input[name="log"]' ).fill( admin.username );
|
||||
await page.locator( 'input[name="pwd"]' ).fill( admin.password );
|
||||
await page.locator( 'text=Log in' ).click();
|
||||
await expect( page.locator( 'tbody#the-list' ) ).toContainText(
|
||||
newAccountEmail
|
||||
);
|
||||
} );
|
||||
} );
|
|
@ -2,6 +2,7 @@ const { test, expect } = require( '@playwright/test' );
|
|||
const wcApi = require( '@woocommerce/woocommerce-rest-api' ).default;
|
||||
const { admin, customer } = require( '../../test-data/data' );
|
||||
const { setFilterValue, clearFilters } = require( '../../utils/filters' );
|
||||
const { addProductsToCart } = require( '../../utils/pdp' );
|
||||
|
||||
const guestEmail = 'checkout-guest@example.com';
|
||||
|
||||
|
@ -143,10 +144,7 @@ test.describe( 'Checkout page', () => {
|
|||
page,
|
||||
} ) => {
|
||||
// this time we're going to add two products to the cart
|
||||
for ( let i = 1; i < 3; i++ ) {
|
||||
await page.goto( `/shop/?add-to-cart=${ productId }` );
|
||||
await page.waitForLoadState( 'networkidle' );
|
||||
}
|
||||
await addProductsToCart( page, simpleProductName, '2' );
|
||||
|
||||
await page.goto( '/checkout/' );
|
||||
await expect( page.locator( 'strong.product-quantity' ) ).toContainText(
|
||||
|
@ -169,10 +167,7 @@ test.describe( 'Checkout page', () => {
|
|||
|
||||
test( 'allows customer to fill billing details', async ( { page } ) => {
|
||||
// this time we're going to add three products to the cart
|
||||
for ( let i = 1; i < 4; i++ ) {
|
||||
await page.goto( `/shop/?add-to-cart=${ productId }` );
|
||||
await page.waitForLoadState( 'networkidle' );
|
||||
}
|
||||
await addProductsToCart( page, simpleProductName, '3' );
|
||||
|
||||
await page.goto( '/checkout/' );
|
||||
await expect( page.locator( 'strong.product-quantity' ) ).toContainText(
|
||||
|
@ -272,10 +267,7 @@ test.describe( 'Checkout page', () => {
|
|||
} );
|
||||
|
||||
test( 'allows customer to fill shipping details', async ( { page } ) => {
|
||||
for ( let i = 1; i < 3; i++ ) {
|
||||
await page.goto( `/shop/?add-to-cart=${ productId }` );
|
||||
await page.waitForLoadState( 'networkidle' );
|
||||
}
|
||||
await addProductsToCart( page, simpleProductName, '2' );
|
||||
|
||||
await page.goto( '/checkout/' );
|
||||
await expect( page.locator( 'strong.product-quantity' ) ).toContainText(
|
||||
|
@ -306,10 +298,7 @@ test.describe( 'Checkout page', () => {
|
|||
} );
|
||||
|
||||
test( 'allows guest customer to place an order', async ( { page } ) => {
|
||||
for ( let i = 1; i < 3; i++ ) {
|
||||
await page.goto( `/shop/?add-to-cart=${ productId }` );
|
||||
await page.waitForLoadState( 'networkidle' );
|
||||
}
|
||||
await addProductsToCart( page, simpleProductName, '2' );
|
||||
|
||||
await page.goto( '/checkout/' );
|
||||
await expect( page.locator( 'strong.product-quantity' ) ).toContainText(
|
||||
|
@ -430,10 +419,7 @@ test.describe( 'Checkout page', () => {
|
|||
.fill( customer.password );
|
||||
await page.locator( 'text=Log In' ).click();
|
||||
await page.waitForLoadState( 'networkidle' );
|
||||
for ( let i = 1; i < 3; i++ ) {
|
||||
await page.goto( `/shop/?add-to-cart=${ productId }` );
|
||||
await page.waitForLoadState( 'networkidle' );
|
||||
}
|
||||
await addProductsToCart( page, simpleProductName, '2' );
|
||||
|
||||
await page.goto( '/checkout/' );
|
||||
await expect( page.locator( 'strong.product-quantity' ) ).toContainText(
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
/**
|
||||
* Util helper made for filling shipping details in the blockbased checkout
|
||||
*
|
||||
* @param page
|
||||
* @param firstName
|
||||
* @param lastName
|
||||
* @param address
|
||||
* @param city
|
||||
* @param zip
|
||||
*/
|
||||
export async function fillShippingCheckoutBlocks(
|
||||
page,
|
||||
firstName = 'Homer',
|
||||
lastName = 'Simpson',
|
||||
address = '123 Evergreen Terrace',
|
||||
city = 'Springfield',
|
||||
zip = '97403'
|
||||
) {
|
||||
await page
|
||||
.getByRole( 'group', { name: 'Shipping address' } )
|
||||
.getByLabel( 'First name' )
|
||||
.fill( firstName );
|
||||
await page
|
||||
.getByRole( 'group', { name: 'Shipping address' } )
|
||||
.getByLabel( 'Last name' )
|
||||
.fill( lastName );
|
||||
await page
|
||||
.getByRole( 'group', { name: 'Shipping address' } )
|
||||
.getByLabel( 'Address', { exact: true } )
|
||||
.fill( address );
|
||||
await page
|
||||
.getByRole( 'group', { name: 'Shipping address' } )
|
||||
.getByLabel( 'City' )
|
||||
.fill( city );
|
||||
await page
|
||||
.getByRole( 'group', { name: 'Shipping address' } )
|
||||
.getByLabel( 'ZIP Code' )
|
||||
.fill( zip );
|
||||
}
|
||||
|
||||
/**
|
||||
* Util helper made for filling billing details in the blockbased checkout
|
||||
*
|
||||
* @param page
|
||||
* @param firstName
|
||||
* @param lastName
|
||||
* @param address
|
||||
* @param city
|
||||
* @param zip
|
||||
*/
|
||||
export async function fillBillingCheckoutBlocks(
|
||||
page,
|
||||
firstName = 'Mister',
|
||||
lastName = 'Burns',
|
||||
address = '156th Street',
|
||||
city = 'Springfield',
|
||||
zip = '98500'
|
||||
) {
|
||||
await page
|
||||
.getByRole( 'group', { name: 'Billing address' } )
|
||||
.getByLabel( 'First name' )
|
||||
.fill( firstName );
|
||||
await page
|
||||
.getByRole( 'group', { name: 'Billing address' } )
|
||||
.getByLabel( 'Last name' )
|
||||
.fill( lastName );
|
||||
await page
|
||||
.getByRole( 'group', { name: 'Billing address' } )
|
||||
.getByLabel( 'Address', { exact: true } )
|
||||
.fill( address );
|
||||
await page
|
||||
.getByRole( 'group', { name: 'Billing address' } )
|
||||
.getByLabel( 'City' )
|
||||
.fill( city );
|
||||
await page
|
||||
.getByRole( 'group', { name: 'Billing address' } )
|
||||
.getByLabel( 'ZIP Code' )
|
||||
.fill( zip );
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
const { expect } = require( '@playwright/test' );
|
||||
|
||||
/**
|
||||
* Util helper made for adding multiple same products to cart
|
||||
*
|
||||
* @param page
|
||||
* @param productName
|
||||
* @param quantityCount
|
||||
*/
|
||||
export async function addProductsToCart( page, productName, quantityCount ) {
|
||||
await page.goto(
|
||||
`product/${ productName.replace( / /gi, '-' ).toLowerCase() }`
|
||||
);
|
||||
await expect( page.locator( '.product_title' ) ).toContainText(
|
||||
productName
|
||||
);
|
||||
await page.getByLabel( 'Product quantity' ).fill( quantityCount );
|
||||
await page.getByRole( 'button', { name: 'Add to cart' } ).click();
|
||||
await expect(
|
||||
page
|
||||
.getByRole( 'alert' )
|
||||
.getByText(
|
||||
`${ quantityCount } × “${ productName }” have been added to your cart.`
|
||||
)
|
||||
).toBeVisible();
|
||||
}
|
Loading…
Reference in New Issue