Shopper → Checkout → Can apply single-use coupon once (https://github.com/woocommerce/woocommerce-blocks/pull/6174)
* Add "single-use" coupon to the fixture data * Create a first draft of the coupon e2e test * Create single use coupon code constant * Create "applyCouponFromCheckout" function * Remove the "single-use" coupon from the fixture data * Setup coupon creation using Woo's Rest API * Add single-use coupon E2E test * Move discount XPath definition to the expressions file * Clean comments * Remove unnecessary delay function * Refactor to a more human friendly check * Clear the setup in the afterAll branch (delete coupon) Co-authored-by: Saad Tarhi <saad.tarhi@automattic.com>
This commit is contained in:
parent
eb196226d8
commit
c636cb1bbe
|
@ -0,0 +1,71 @@
|
||||||
|
/**
|
||||||
|
* External dependencies
|
||||||
|
*/
|
||||||
|
import { withRestApi } from '@woocommerce/e2e-utils';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal dependencies
|
||||||
|
*/
|
||||||
|
import { shopper } from '../../../utils';
|
||||||
|
import { createCoupon } from '../../utils';
|
||||||
|
import { SIMPLE_PRODUCT_NAME } from '../../../utils/constants';
|
||||||
|
|
||||||
|
if ( process.env.WOOCOMMERCE_BLOCKS_PHASE < 2 )
|
||||||
|
// eslint-disable-next-line jest/no-focused-tests
|
||||||
|
test.only( `Skipping checkout tests`, () => {} );
|
||||||
|
|
||||||
|
let coupon;
|
||||||
|
|
||||||
|
beforeAll( async () => {
|
||||||
|
coupon = await createCoupon( { usageLimit: 1 } );
|
||||||
|
await shopper.block.emptyCart();
|
||||||
|
} );
|
||||||
|
|
||||||
|
afterAll( async () => {
|
||||||
|
await withRestApi.deleteCoupon( coupon.id );
|
||||||
|
await shopper.block.emptyCart();
|
||||||
|
} );
|
||||||
|
|
||||||
|
describe( 'Shopper → Checkout → Can apply single-use coupon once', () => {
|
||||||
|
it( 'allows checkout to apply single-use coupon once', async () => {
|
||||||
|
await shopper.goToShop();
|
||||||
|
await shopper.addToCartFromShopPage( SIMPLE_PRODUCT_NAME );
|
||||||
|
await shopper.block.goToCheckout();
|
||||||
|
await shopper.block.applyCouponFromCheckout( coupon.code );
|
||||||
|
|
||||||
|
const discountBlockSelector = '.wc-block-components-totals-discount';
|
||||||
|
const discountAppliedCouponCodeSelector =
|
||||||
|
'.wc-block-components-totals-discount__coupon-list-item span.wc-block-components-chip__text';
|
||||||
|
const discountValueSelector =
|
||||||
|
'.wc-block-components-totals-discount .wc-block-components-totals-item__value';
|
||||||
|
|
||||||
|
// Verify that the discount had been applied correctly on the checkout page.
|
||||||
|
await page.waitForSelector( discountBlockSelector );
|
||||||
|
await expect( page ).toMatchElement( discountValueSelector, {
|
||||||
|
text: coupon.amount,
|
||||||
|
} );
|
||||||
|
await expect( page ).toMatchElement(
|
||||||
|
discountAppliedCouponCodeSelector,
|
||||||
|
{
|
||||||
|
text: coupon.code,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
await shopper.block.placeOrder();
|
||||||
|
await expect( page ).toMatch( 'Your order has been received.' );
|
||||||
|
|
||||||
|
// Verify that the discount had been applied correctly on the order confirmation page.
|
||||||
|
await expect( page ).toMatchElement( `th`, { text: 'Discount' } );
|
||||||
|
await expect( page ).toMatchElement( `span.woocommerce-Price-amount`, {
|
||||||
|
text: coupon.amount,
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
it( 'Prevents checkout applying single-use coupon twice', async () => {
|
||||||
|
await shopper.goToShop();
|
||||||
|
await shopper.addToCartFromShopPage( SIMPLE_PRODUCT_NAME );
|
||||||
|
await shopper.block.goToCheckout();
|
||||||
|
await shopper.block.applyCouponFromCheckout( coupon.code );
|
||||||
|
await expect( page ).toMatch( 'Coupon usage limit has been reached.' );
|
||||||
|
} );
|
||||||
|
} );
|
|
@ -1,6 +1,7 @@
|
||||||
/**
|
/**
|
||||||
* External dependencies
|
* External dependencies
|
||||||
*/
|
*/
|
||||||
|
import { Coupon, HTTPClientFactory } from '@woocommerce/api';
|
||||||
import config from 'config';
|
import config from 'config';
|
||||||
import {
|
import {
|
||||||
activateTheme,
|
activateTheme,
|
||||||
|
@ -29,6 +30,11 @@ import { elementExists, getElementData, getTextContent } from './page-utils';
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export const BASE_URL = config.get( 'url' );
|
export const BASE_URL = config.get( 'url' );
|
||||||
|
export const adminUsername = config.get( 'users.admin.username' );
|
||||||
|
export const adminPassword = config.get( 'users.admin.password' );
|
||||||
|
export const client = HTTPClientFactory.build( BASE_URL )
|
||||||
|
.withBasicAuth( adminUsername, adminPassword )
|
||||||
|
.create();
|
||||||
export const GUTENBERG_EDITOR_CONTEXT =
|
export const GUTENBERG_EDITOR_CONTEXT =
|
||||||
process.env.GUTENBERG_EDITOR_CONTEXT || 'core';
|
process.env.GUTENBERG_EDITOR_CONTEXT || 'core';
|
||||||
export const DEFAULT_TIMEOUT = 30000;
|
export const DEFAULT_TIMEOUT = 30000;
|
||||||
|
@ -352,3 +358,46 @@ export const addBlockToFSEArea = async ( blockName ) => {
|
||||||
);
|
);
|
||||||
await insertButton.click();
|
await insertButton.click();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a basic coupon with the provided coupon amount. Returns the coupon code.
|
||||||
|
*
|
||||||
|
* @param {Object} [coupon] Coupon object. Default to fixed cart type and amount = 5.
|
||||||
|
* @param {string} [coupon.amount] Amount to be applied. Defaults to 5.
|
||||||
|
* @param {string} [coupon.discountType] Type of a coupon. Defaults to Fixed cart discount.
|
||||||
|
* @param {number} [coupon.usageLimit] How many times the coupon can be used in total. Defaults to -1.
|
||||||
|
*/
|
||||||
|
export const createCoupon = async ( coupon ) => {
|
||||||
|
const {
|
||||||
|
amount = '5',
|
||||||
|
discountType = 'Fixed cart discount',
|
||||||
|
usageLimit = -1,
|
||||||
|
} = coupon || { amount: '5', discountType: 'Fixed cart discount' };
|
||||||
|
|
||||||
|
let couponType;
|
||||||
|
switch ( discountType ) {
|
||||||
|
case 'Fixed cart discount':
|
||||||
|
couponType = 'fixed_cart';
|
||||||
|
break;
|
||||||
|
case 'Fixed product discount':
|
||||||
|
couponType = 'fixed_product';
|
||||||
|
break;
|
||||||
|
case 'Percentage discount':
|
||||||
|
couponType = 'percent';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
couponType = discountType;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill in coupon code
|
||||||
|
const couponCode = 'code-' + couponType + new Date().getTime().toString();
|
||||||
|
const repository = Coupon.restRepository( client );
|
||||||
|
const createdCoupon = await repository.create( {
|
||||||
|
code: couponCode,
|
||||||
|
discountType: couponType,
|
||||||
|
amount,
|
||||||
|
usageLimit,
|
||||||
|
} );
|
||||||
|
|
||||||
|
return createdCoupon;
|
||||||
|
};
|
||||||
|
|
|
@ -390,6 +390,20 @@ export const shopper = {
|
||||||
|
|
||||||
await expect( page.$x( cartItemXPath ) ).resolves.toHaveLength( 1 );
|
await expect( page.$x( cartItemXPath ) ).resolves.toHaveLength( 1 );
|
||||||
},
|
},
|
||||||
|
|
||||||
|
applyCouponFromCheckout: async ( couponCode ) => {
|
||||||
|
const couponInputSelector =
|
||||||
|
'#wc-block-components-totals-coupon__input-0';
|
||||||
|
const couponApplyButtonSelector =
|
||||||
|
'.wc-block-components-totals-coupon__button';
|
||||||
|
const couponExpandButtonSelector =
|
||||||
|
'.wc-block-components-totals-coupon button';
|
||||||
|
|
||||||
|
await expect( page ).toClick( couponExpandButtonSelector );
|
||||||
|
await expect( page ).toFill( couponInputSelector, couponCode );
|
||||||
|
await expect( page ).toClick( couponApplyButtonSelector );
|
||||||
|
await page.waitForNetworkIdle();
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
isLoggedIn: async () => {
|
isLoggedIn: async () => {
|
||||||
|
|
Loading…
Reference in New Issue