Tidy up and organise e2e tests (https://github.com/woocommerce/woocommerce-blocks/pull/6206)
* rename some things * Refactor e2e tests * remove only from checkout test * Typo in test * Add --testPathIgnorePatterns performance back into package.json * Niels feedback and fix a test * Update import from utils
This commit is contained in:
parent
6c2d24e3e5
commit
5c396c4e26
|
@ -1,36 +0,0 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { shopper } from '../../../utils';
|
||||
import { SIMPLE_VIRTUAL_PRODUCT_NAME } from '../../../utils/constants';
|
||||
|
||||
if ( process.env.WOOCOMMERCE_BLOCKS_PHASE < 2 ) {
|
||||
// eslint-disable-next-line jest/no-focused-tests
|
||||
test.only( `skipping Cart & Checkout tests`, () => {} );
|
||||
}
|
||||
|
||||
describe( 'Shopper → Cart/Checkout → Can use express checkout', () => {
|
||||
it( 'Express Payment button is available on both Cart & Checkout pages', async () => {
|
||||
await shopper.goToShop();
|
||||
await shopper.addToCartFromShopPage( SIMPLE_VIRTUAL_PRODUCT_NAME );
|
||||
await shopper.block.goToCart();
|
||||
await shopper.block.mockExpressPaymentMethod();
|
||||
// We need to re-render the cart for the express payments block to be updated,
|
||||
// so we update the qty, which update one of it's attributes and in turn causes a re-render
|
||||
await page.click(
|
||||
'.wc-block-components-quantity-selector__button--plus'
|
||||
);
|
||||
await page.waitForNetworkIdle( { idleTime: 1000 } );
|
||||
await await expect( page ).toMatchElement(
|
||||
'#express-payment-method-mock_express_payment'
|
||||
);
|
||||
await shopper.block.goToCheckout();
|
||||
await shopper.block.mockExpressPaymentMethod();
|
||||
// We need to re-render the checkout for the express payments block to be updated,
|
||||
// so we just type a space in the email field.
|
||||
await expect( page ).toFill( '#email', ' ' );
|
||||
await expect( page ).toMatchElement(
|
||||
'#express-payment-method-mock_express_payment'
|
||||
);
|
||||
} );
|
||||
} );
|
|
@ -1,18 +1,14 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { shopper } from '../../../utils';
|
||||
import { SIMPLE_VIRTUAL_PRODUCT_NAME } from '../../../utils/constants';
|
||||
import { shopper, SIMPLE_VIRTUAL_PRODUCT_NAME } from '../../../../utils';
|
||||
|
||||
const block = {
|
||||
name: 'Cart',
|
||||
};
|
||||
|
||||
if ( process.env.WOOCOMMERCE_BLOCKS_PHASE < 2 )
|
||||
if ( process.env.WOOCOMMERCE_BLOCKS_PHASE < 2 ) {
|
||||
// eslint-disable-next-line jest/no-focused-tests
|
||||
test.only( `skipping ${ block.name } tests`, () => {} );
|
||||
test.only( `Skipping Cart & Checkout tests`, () => {} );
|
||||
}
|
||||
|
||||
describe( 'Shopper → Cart → Can update product quantity', () => {
|
||||
describe( 'Shopper → Cart', () => {
|
||||
beforeAll( async () => {
|
||||
await shopper.block.emptyCart();
|
||||
} );
|
||||
|
@ -21,7 +17,34 @@ describe( 'Shopper → Cart → Can update product quantity', () => {
|
|||
await shopper.block.emptyCart();
|
||||
} );
|
||||
|
||||
it( 'allows customer to update product quantity via the input field', async () => {
|
||||
it( 'User can view empty cart message', async () => {
|
||||
await shopper.block.goToCart();
|
||||
|
||||
// Verify cart is empty'
|
||||
await expect( page ).toMatchElement( 'h2', {
|
||||
text: 'Your cart is currently empty!',
|
||||
} );
|
||||
} );
|
||||
|
||||
it( 'User can remove a product from cart', async () => {
|
||||
await shopper.goToShop();
|
||||
await shopper.addToCartFromShopPage( SIMPLE_VIRTUAL_PRODUCT_NAME );
|
||||
await shopper.block.goToCart();
|
||||
const removeProductLink = await page.$(
|
||||
'.wc-block-cart-item__remove-link'
|
||||
);
|
||||
|
||||
await removeProductLink.click();
|
||||
// we need to wait to ensure the cart is updated
|
||||
await page.waitForSelector( '.wc-block-cart__empty-cart__title' );
|
||||
|
||||
// Verify product is removed from the cart'
|
||||
await expect( page ).toMatchElement( 'h2', {
|
||||
text: 'Your cart is currently empty!',
|
||||
} );
|
||||
} );
|
||||
|
||||
it( 'User can update product quantity via the input field', async () => {
|
||||
await shopper.goToShop();
|
||||
await shopper.addToCartFromShopPage( SIMPLE_VIRTUAL_PRODUCT_NAME );
|
||||
await shopper.block.goToCart();
|
||||
|
@ -38,7 +61,7 @@ describe( 'Shopper → Cart → Can update product quantity', () => {
|
|||
await shopper.block.productIsInCart( SIMPLE_VIRTUAL_PRODUCT_NAME, 4 );
|
||||
} );
|
||||
|
||||
it( 'allows customer to increase product quantity via the plus button', async () => {
|
||||
it( 'User can increase product quantity via the plus button', async () => {
|
||||
await shopper.block.increaseCartQuantityByOne(
|
||||
SIMPLE_VIRTUAL_PRODUCT_NAME
|
||||
);
|
||||
|
@ -53,7 +76,7 @@ describe( 'Shopper → Cart → Can update product quantity', () => {
|
|||
await shopper.block.productIsInCart( SIMPLE_VIRTUAL_PRODUCT_NAME, 5 );
|
||||
} );
|
||||
|
||||
it( 'allows customer to decrease product quantity via the minus button', async () => {
|
||||
it( 'User can decrease product quantity via the minus button', async () => {
|
||||
await shopper.block.decreaseCartQuantityByOne(
|
||||
SIMPLE_VIRTUAL_PRODUCT_NAME
|
||||
);
|
||||
|
@ -67,4 +90,16 @@ describe( 'Shopper → Cart → Can update product quantity', () => {
|
|||
|
||||
await shopper.block.productIsInCart( SIMPLE_VIRTUAL_PRODUCT_NAME, 4 );
|
||||
} );
|
||||
|
||||
it( 'User can proceed to checkout', async () => {
|
||||
await shopper.goToShop();
|
||||
await shopper.addToCartFromShopPage( SIMPLE_VIRTUAL_PRODUCT_NAME );
|
||||
await shopper.block.goToCart();
|
||||
|
||||
// Click on "Proceed to Checkout" button
|
||||
await shopper.block.proceedToCheckout();
|
||||
|
||||
// Verify that you see the Checkout Block page
|
||||
await expect( page ).toMatchElement( 'h1', { text: 'Checkout' } );
|
||||
} );
|
||||
} );
|
|
@ -0,0 +1,299 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import {
|
||||
merchant,
|
||||
openDocumentSettingsSidebar,
|
||||
setCheckbox,
|
||||
unsetCheckbox,
|
||||
withRestApi,
|
||||
} from '@woocommerce/e2e-utils';
|
||||
|
||||
import {
|
||||
visitBlockPage,
|
||||
selectBlockByName,
|
||||
saveOrPublish,
|
||||
} from '@woocommerce/blocks-test-utils';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import {
|
||||
shopper,
|
||||
preventCompatibilityNotice,
|
||||
reactivateCompatibilityNotice,
|
||||
BILLING_DETAILS,
|
||||
SHIPPING_DETAILS,
|
||||
SIMPLE_PHYSICAL_PRODUCT_NAME,
|
||||
SIMPLE_VIRTUAL_PRODUCT_NAME,
|
||||
} from '../../../../utils';
|
||||
|
||||
import { createCoupon } from '../../../utils';
|
||||
|
||||
if ( process.env.WOOCOMMERCE_BLOCKS_PHASE < 2 ) {
|
||||
// eslint-disable-next-line jest/no-focused-tests
|
||||
test.only( 'Skipping Cart & Checkout tests', () => {} );
|
||||
}
|
||||
|
||||
let companyCheckboxId = null;
|
||||
let coupon;
|
||||
|
||||
describe( 'Shopper → Checkout', () => {
|
||||
beforeAll( async () => {
|
||||
await shopper.block.emptyCart();
|
||||
} );
|
||||
|
||||
it( 'User can view empty cart message', async () => {
|
||||
await shopper.block.goToCheckout();
|
||||
// Verify cart is empty'
|
||||
await expect( page ).toMatchElement(
|
||||
'strong.wc-block-checkout-empty__title',
|
||||
{
|
||||
text: 'Your cart is empty!',
|
||||
}
|
||||
);
|
||||
} );
|
||||
|
||||
describe( 'Shipping and Billing Addresses', () => {
|
||||
beforeAll( async () => {
|
||||
await preventCompatibilityNotice();
|
||||
await merchant.login();
|
||||
await visitBlockPage( 'Checkout Block' );
|
||||
await openDocumentSettingsSidebar();
|
||||
await selectBlockByName(
|
||||
'woocommerce/checkout-shipping-address-block'
|
||||
);
|
||||
|
||||
// This checkbox ID is unstable, so, we're getting its value from "for" attribute of the label
|
||||
const [ companyCheckboxLabel ] = await page.$x(
|
||||
`//label[contains(text(), "Company") and contains(@class, "components-toggle-control__label")]`
|
||||
);
|
||||
companyCheckboxId = await page.evaluate(
|
||||
( label ) => `#${ label.getAttribute( 'for' ) }`,
|
||||
companyCheckboxLabel
|
||||
);
|
||||
|
||||
await setCheckbox( companyCheckboxId );
|
||||
await saveOrPublish();
|
||||
await shopper.block.emptyCart();
|
||||
} );
|
||||
|
||||
afterAll( async () => {
|
||||
await shopper.block.emptyCart();
|
||||
await visitBlockPage( 'Checkout Block' );
|
||||
await openDocumentSettingsSidebar();
|
||||
await selectBlockByName(
|
||||
'woocommerce/checkout-shipping-address-block'
|
||||
);
|
||||
await unsetCheckbox( companyCheckboxId );
|
||||
await saveOrPublish();
|
||||
await merchant.logout();
|
||||
await reactivateCompatibilityNotice();
|
||||
} );
|
||||
|
||||
it( 'User can have different shipping and billing addresses', async () => {
|
||||
await shopper.goToShop();
|
||||
await shopper.addToCartFromShopPage( SIMPLE_PHYSICAL_PRODUCT_NAME );
|
||||
await shopper.block.goToCheckout();
|
||||
await unsetCheckbox( '#checkbox-control-0' );
|
||||
await shopper.block.fillShippingDetails( SHIPPING_DETAILS );
|
||||
await shopper.block.fillBillingDetails( BILLING_DETAILS );
|
||||
await shopper.block.placeOrder();
|
||||
await shopper.block.verifyShippingDetails( SHIPPING_DETAILS );
|
||||
await shopper.block.verifyBillingDetails( BILLING_DETAILS );
|
||||
} );
|
||||
} );
|
||||
|
||||
describe( 'Checkout Form Errors', () => {
|
||||
beforeAll( async () => {
|
||||
const isShopperLoggedIn = await shopper.isLoggedIn();
|
||||
|
||||
// @todo Find a better way to reset the checkout form instead of login then logout
|
||||
if ( isShopperLoggedIn ) {
|
||||
// Click on the "Log out" link in "My account" page
|
||||
await await shopper.logout();
|
||||
} else {
|
||||
await shopper.login();
|
||||
await shopper.logout();
|
||||
}
|
||||
} );
|
||||
|
||||
it( 'User can see errors when form is incomplete', async () => {
|
||||
await shopper.goToShop();
|
||||
await shopper.addToCartFromShopPage( SIMPLE_VIRTUAL_PRODUCT_NAME );
|
||||
await shopper.block.goToCheckout();
|
||||
|
||||
// Click on "Place Order" button
|
||||
await expect( page ).toClick(
|
||||
'.wc-block-components-checkout-place-order-button',
|
||||
{
|
||||
text: 'Place Order',
|
||||
}
|
||||
);
|
||||
|
||||
// Verify that all required fields show the correct warning.
|
||||
await expect( page ).toMatchElement(
|
||||
'#email ~ .wc-block-components-validation-error p',
|
||||
{
|
||||
text: 'Please fill out this field.',
|
||||
}
|
||||
);
|
||||
await expect( page ).toMatchElement(
|
||||
'#billing-first_name ~ .wc-block-components-validation-error p',
|
||||
{
|
||||
text: 'Please fill out this field.',
|
||||
}
|
||||
);
|
||||
await expect( page ).toMatchElement(
|
||||
'#billing-last_name ~ .wc-block-components-validation-error p',
|
||||
{
|
||||
text: 'Please fill out this field.',
|
||||
}
|
||||
);
|
||||
await expect( page ).toMatchElement(
|
||||
'#billing-address_1 ~ .wc-block-components-validation-error p',
|
||||
{
|
||||
text: 'Please fill out this field.',
|
||||
}
|
||||
);
|
||||
await expect( page ).toMatchElement(
|
||||
'#billing-city ~ .wc-block-components-validation-error p',
|
||||
{
|
||||
text: 'Please fill out this field.',
|
||||
}
|
||||
);
|
||||
await expect( page ).toMatchElement(
|
||||
'#billing-postcode ~ .wc-block-components-validation-error p',
|
||||
{
|
||||
text: 'Please fill out this field.',
|
||||
}
|
||||
);
|
||||
} );
|
||||
} );
|
||||
|
||||
describe( 'Place Order', () => {
|
||||
it( 'Guest user can place order', async () => {
|
||||
if ( await shopper.isLoggedIn() ) {
|
||||
await shopper.logout();
|
||||
}
|
||||
await shopper.goToShop();
|
||||
await shopper.addToCartFromShopPage( SIMPLE_VIRTUAL_PRODUCT_NAME );
|
||||
await shopper.block.goToCheckout();
|
||||
await shopper.block.fillBillingDetails( BILLING_DETAILS );
|
||||
await shopper.block.placeOrder();
|
||||
await expect( page ).toMatch( 'Your order has been received.' );
|
||||
} );
|
||||
|
||||
it( 'Logged in user can place an order', async () => {
|
||||
await shopper.login();
|
||||
await shopper.goToShop();
|
||||
await shopper.addToCartFromShopPage( SIMPLE_VIRTUAL_PRODUCT_NAME );
|
||||
await shopper.block.goToCheckout();
|
||||
await shopper.block.fillBillingDetails( BILLING_DETAILS );
|
||||
await shopper.block.placeOrder();
|
||||
await expect( page ).toMatch( 'Your order has been received.' );
|
||||
await shopper.logout();
|
||||
} );
|
||||
} );
|
||||
|
||||
describe( `Shipping`, () => {
|
||||
const FREE_SHIPPING_NAME = 'Free Shipping';
|
||||
const FREE_SHIPPING_PRICE = '$0.00';
|
||||
const NORMAL_SHIPPING_NAME = 'Normal Shipping';
|
||||
const NORMAL_SHIPPING_PRICE = '$20.00';
|
||||
|
||||
beforeAll( async () => {
|
||||
await merchant.login();
|
||||
} );
|
||||
|
||||
afterAll( async () => {
|
||||
await merchant.logout();
|
||||
} );
|
||||
|
||||
it( 'User can choose free shipping', async () => {
|
||||
await shopper.goToShop();
|
||||
await shopper.addToCartFromShopPage( SIMPLE_PHYSICAL_PRODUCT_NAME );
|
||||
await shopper.block.goToCheckout();
|
||||
await shopper.block.selectAndVerifyShippingOption(
|
||||
FREE_SHIPPING_NAME,
|
||||
FREE_SHIPPING_PRICE
|
||||
);
|
||||
await shopper.block.placeOrder();
|
||||
await page.waitForTimeout( 2000 );
|
||||
await expect( page ).toMatch( 'Order received' );
|
||||
await expect( page ).toMatch( FREE_SHIPPING_NAME );
|
||||
} );
|
||||
|
||||
it( 'User can choose flat rate shipping', async () => {
|
||||
await shopper.goToShop();
|
||||
await shopper.addToCartFromShopPage( SIMPLE_PHYSICAL_PRODUCT_NAME );
|
||||
await shopper.block.goToCheckout();
|
||||
await shopper.block.selectAndVerifyShippingOption(
|
||||
NORMAL_SHIPPING_NAME,
|
||||
NORMAL_SHIPPING_PRICE
|
||||
);
|
||||
await shopper.block.placeOrder();
|
||||
await page.waitForTimeout( 2000 );
|
||||
await expect( page ).toMatch( 'Order received' );
|
||||
await expect( page ).toMatch( NORMAL_SHIPPING_NAME );
|
||||
} );
|
||||
} );
|
||||
|
||||
describe( 'Coupons', () => {
|
||||
beforeAll( async () => {
|
||||
coupon = await createCoupon( { usageLimit: 1 } );
|
||||
} );
|
||||
|
||||
afterAll( async () => {
|
||||
await withRestApi.deleteCoupon( coupon.id );
|
||||
} );
|
||||
|
||||
it( 'User can apply single-use coupon once', async () => {
|
||||
await shopper.goToShop();
|
||||
await shopper.addToCartFromShopPage( SIMPLE_VIRTUAL_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( 'User cannot apply single-use coupon twice', async () => {
|
||||
await shopper.goToShop();
|
||||
await shopper.addToCartFromShopPage( SIMPLE_VIRTUAL_PRODUCT_NAME );
|
||||
await shopper.block.goToCheckout();
|
||||
await shopper.block.applyCouponFromCheckout( coupon.code );
|
||||
await expect( page ).toMatch(
|
||||
'Coupon usage limit has been reached.'
|
||||
);
|
||||
} );
|
||||
} );
|
||||
} );
|
|
@ -1,35 +1,36 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { shopper } from '../../../utils';
|
||||
import { Taxes, Products } from '../../fixtures/fixture-data';
|
||||
import {
|
||||
shopper,
|
||||
getExpectedTaxes,
|
||||
getTaxesFromCurrentPage,
|
||||
getTaxesFromOrderSummaryPage,
|
||||
showTaxes,
|
||||
} from '../../../utils/taxes';
|
||||
SIMPLE_VIRTUAL_PRODUCT_NAME,
|
||||
} from '../../../../utils';
|
||||
import { Taxes, Products } from '../../../fixtures/fixture-data';
|
||||
|
||||
const taxRates = Taxes();
|
||||
const productWooSingle1 = Products().find(
|
||||
( prod ) => prod.name === 'Woo Single #1'
|
||||
);
|
||||
|
||||
if ( process.env.WOOCOMMERCE_BLOCKS_PHASE < 2 )
|
||||
if ( process.env.WOOCOMMERCE_BLOCKS_PHASE < 2 ) {
|
||||
// eslint-disable-next-line jest/no-focused-tests
|
||||
test.only( `skipping ${ block.name } tests`, () => {} );
|
||||
test.only( `Skipping Cart & Checkout tests`, () => {} );
|
||||
}
|
||||
|
||||
describe( 'Shopper -> Tax', () => {
|
||||
describe( 'Shopper → Cart & Checkout → Taxes', () => {
|
||||
beforeEach( async () => {
|
||||
await shopper.block.emptyCart();
|
||||
} );
|
||||
|
||||
describe( '"Enable tax rate calculations" is unchecked in WC settings -> general', () => {
|
||||
it( 'Tax is not displayed', async () => {
|
||||
it( 'User cannot view the tax on Cart, Checkout & Order Summary', async () => {
|
||||
await showTaxes( false );
|
||||
await shopper.goToShop();
|
||||
await shopper.block.searchForProduct( productWooSingle1.name );
|
||||
await shopper.addToCart();
|
||||
await shopper.addToCartFromShopPage( SIMPLE_VIRTUAL_PRODUCT_NAME );
|
||||
await shopper.block.goToCart();
|
||||
|
||||
const cartTaxes = await getTaxesFromCurrentPage();
|
||||
|
@ -50,11 +51,10 @@ describe( 'Shopper -> Tax', () => {
|
|||
} );
|
||||
|
||||
describe( '"Enable tax rate calculations" is checked in WC settings -> general', () => {
|
||||
it( 'Tax is displayed correctly on Cart & Checkout ', async () => {
|
||||
it( 'User can view the tax on Cart, Checkout & Order Summary', async () => {
|
||||
await showTaxes( true );
|
||||
await shopper.goToShop();
|
||||
await shopper.block.searchForProduct( productWooSingle1.name );
|
||||
await shopper.addToCart();
|
||||
await shopper.addToCartFromShopPage( SIMPLE_VIRTUAL_PRODUCT_NAME );
|
||||
await shopper.block.goToCart();
|
||||
|
||||
const expectedTaxes = getExpectedTaxes( taxRates, 'US', [
|
|
@ -1,16 +1,14 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { cli } from '../../../utils/run-cli-from-test';
|
||||
import { merchant } from '../../../utils/merchant';
|
||||
import { shopper } from '../../../utils/shopper';
|
||||
import { cli, merchant, shopper } from '../../../../utils';
|
||||
|
||||
if ( process.env.WOOCOMMERCE_BLOCKS_PHASE < 2 ) {
|
||||
// eslint-disable-next-line jest/no-focused-tests
|
||||
test.only( 'Skipping Checkout tests', () => {} );
|
||||
test.only( 'Skipping Cart & Checkout tests', () => {} );
|
||||
}
|
||||
|
||||
describe( 'Shopper → Cart → Can view translated cart & checkout blocks', () => {
|
||||
describe( 'Shopper → Cart & Checkout → Translations', () => {
|
||||
// We need to install the language files for the blocks plugin.
|
||||
// We also need to install the plugin from w.org via the cli. This is because
|
||||
// on w.org, the slug is `woo-gutenberg-products-block` where as here it's
|
||||
|
@ -42,7 +40,7 @@ describe( 'Shopper → Cart → Can view translated cart & checkout blocks', ()
|
|||
expect( resultUninstallLanguages.code ).toEqual( 0 );
|
||||
} );
|
||||
|
||||
it( 'should be able to view translated Cart block ', async () => {
|
||||
it( 'User can view translated Cart block ', async () => {
|
||||
await shopper.goToShop();
|
||||
await shopper.addToCartFromShopPage( '128GB USB Stick' );
|
||||
await shopper.block.goToCart();
|
||||
|
@ -73,7 +71,7 @@ describe( 'Shopper → Cart → Can view translated cart & checkout blocks', ()
|
|||
await expect( orderSummary ).toMatch( 'Coupon code' );
|
||||
} );
|
||||
|
||||
it( 'should be able to view translated Checkout block', async () => {
|
||||
it( 'USer can view translated Checkout block', async () => {
|
||||
await shopper.block.goToCheckout();
|
||||
|
||||
const contactHeading = await page.$(
|
|
@ -1,24 +0,0 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { shopper } from '../../../utils';
|
||||
|
||||
if ( process.env.WOOCOMMERCE_BLOCKS_PHASE < 2 ) {
|
||||
// eslint-disable-next-line jest/no-focused-tests
|
||||
test.only( `skipping ${ block.name } tests`, () => {} );
|
||||
}
|
||||
|
||||
describe( 'Shopper → Cart → Can view empty cart message', () => {
|
||||
beforeAll( async () => {
|
||||
await shopper.block.emptyCart();
|
||||
} );
|
||||
|
||||
it( 'Shopper Can view empty cart message', async () => {
|
||||
await shopper.block.goToCart();
|
||||
|
||||
// Verify cart is empty'
|
||||
await expect( page ).toMatchElement( 'h2', {
|
||||
text: 'Your cart is currently empty!',
|
||||
} );
|
||||
} );
|
||||
} );
|
|
@ -1,35 +0,0 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { shopper } from '../../../utils';
|
||||
import { SIMPLE_VIRTUAL_PRODUCT_NAME } from '../../../utils/constants';
|
||||
|
||||
const block = {
|
||||
name: 'Cart',
|
||||
};
|
||||
|
||||
if ( process.env.WOOCOMMERCE_BLOCKS_PHASE < 2 )
|
||||
// eslint-disable-next-line jest/no-focused-tests
|
||||
test.only( `skipping ${ block.name } tests`, () => {} );
|
||||
|
||||
describe( 'Shopper → Cart → Can proceed to checkout', () => {
|
||||
beforeEach( async () => {
|
||||
await shopper.block.emptyCart();
|
||||
} );
|
||||
|
||||
afterAll( async () => {
|
||||
await shopper.block.emptyCart();
|
||||
} );
|
||||
|
||||
it( 'allows customer to proceed to checkout', async () => {
|
||||
await shopper.goToShop();
|
||||
await shopper.addToCartFromShopPage( SIMPLE_VIRTUAL_PRODUCT_NAME );
|
||||
await shopper.block.goToCart();
|
||||
|
||||
// Click on "Proceed to Checkout" button
|
||||
await shopper.block.proceedToCheckout();
|
||||
|
||||
// Verify that you see the Checkout Block page
|
||||
await expect( page ).toMatchElement( 'h1', { text: 'Checkout' } );
|
||||
} );
|
||||
} );
|
|
@ -1,33 +0,0 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { shopper } from '../../../utils';
|
||||
import { SIMPLE_VIRTUAL_PRODUCT_NAME } from '../../../utils/constants';
|
||||
|
||||
if ( process.env.WOOCOMMERCE_BLOCKS_PHASE < 2 )
|
||||
// eslint-disable-next-line jest/no-focused-tests
|
||||
test.only( `skipping ${ block.name } tests`, () => {} );
|
||||
|
||||
describe( 'Shopper → Cart → Can remove product', () => {
|
||||
beforeAll( async () => {
|
||||
await shopper.block.emptyCart();
|
||||
} );
|
||||
|
||||
it( 'Can remove product from cart', async () => {
|
||||
await shopper.goToShop();
|
||||
await shopper.addToCartFromShopPage( SIMPLE_VIRTUAL_PRODUCT_NAME );
|
||||
await shopper.block.goToCart();
|
||||
const removeProductLink = await page.$(
|
||||
'.wc-block-cart-item__remove-link'
|
||||
);
|
||||
|
||||
await removeProductLink.click();
|
||||
// we need to wait to ensure the cart is updated
|
||||
await page.waitForSelector( '.wc-block-cart__empty-cart__title' );
|
||||
|
||||
// Verify product is removed from the cart'
|
||||
await expect( page ).toMatchElement( 'h2', {
|
||||
text: 'Your cart is currently empty!',
|
||||
} );
|
||||
} );
|
||||
} );
|
|
@ -1,86 +0,0 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import {
|
||||
merchant,
|
||||
openDocumentSettingsSidebar,
|
||||
setCheckbox,
|
||||
unsetCheckbox,
|
||||
} from '@woocommerce/e2e-utils';
|
||||
|
||||
import {
|
||||
visitBlockPage,
|
||||
selectBlockByName,
|
||||
saveOrPublish,
|
||||
} from '@woocommerce/blocks-test-utils';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import {
|
||||
shopper,
|
||||
preventCompatibilityNotice,
|
||||
reactivateCompatibilityNotice,
|
||||
} from '../../../utils';
|
||||
|
||||
import {
|
||||
BILLING_DETAILS,
|
||||
SHIPPING_DETAILS,
|
||||
SIMPLE_PHYSICAL_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 companyCheckboxId = null;
|
||||
|
||||
describe( 'Shopper → Checkout → Can have different shipping and billing addresses', () => {
|
||||
beforeAll( async () => {
|
||||
await preventCompatibilityNotice();
|
||||
await merchant.login();
|
||||
await visitBlockPage( 'Checkout Block' );
|
||||
await openDocumentSettingsSidebar();
|
||||
await selectBlockByName(
|
||||
'woocommerce/checkout-shipping-address-block'
|
||||
);
|
||||
|
||||
// This checkbox ID is unstable, so, we're getting its value from "for" attribute of the label
|
||||
const [ companyCheckboxLabel ] = await page.$x(
|
||||
`//label[contains(text(), "Company") and contains(@class, "components-toggle-control__label")]`
|
||||
);
|
||||
companyCheckboxId = await page.evaluate(
|
||||
( label ) => `#${ label.getAttribute( 'for' ) }`,
|
||||
companyCheckboxLabel
|
||||
);
|
||||
|
||||
await setCheckbox( companyCheckboxId );
|
||||
await saveOrPublish();
|
||||
await shopper.block.emptyCart();
|
||||
} );
|
||||
|
||||
afterAll( async () => {
|
||||
await shopper.block.emptyCart();
|
||||
await visitBlockPage( 'Checkout Block' );
|
||||
await openDocumentSettingsSidebar();
|
||||
await selectBlockByName(
|
||||
'woocommerce/checkout-shipping-address-block'
|
||||
);
|
||||
await unsetCheckbox( companyCheckboxId );
|
||||
await saveOrPublish();
|
||||
await merchant.logout();
|
||||
await reactivateCompatibilityNotice();
|
||||
} );
|
||||
|
||||
it( 'allows customer to have different shipping and billing addresses', async () => {
|
||||
await shopper.goToShop();
|
||||
await shopper.addToCartFromShopPage( SIMPLE_PHYSICAL_PRODUCT_NAME );
|
||||
await shopper.block.goToCheckout();
|
||||
await unsetCheckbox( '#checkbox-control-0' );
|
||||
await shopper.block.fillShippingDetails( SHIPPING_DETAILS );
|
||||
await shopper.block.fillBillingDetails( BILLING_DETAILS );
|
||||
await shopper.block.placeOrder();
|
||||
await shopper.block.verifyShippingDetails( SHIPPING_DETAILS );
|
||||
await shopper.block.verifyBillingDetails( BILLING_DETAILS );
|
||||
} );
|
||||
} );
|
|
@ -1,25 +0,0 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { shopper } from '../../../utils';
|
||||
|
||||
if ( process.env.WOOCOMMERCE_BLOCKS_PHASE < 2 )
|
||||
// eslint-disable-next-line jest/no-focused-tests
|
||||
test.only( `Skipping checkout tests`, () => {} );
|
||||
|
||||
describe( 'Shopper → Checkout → Can view empty checkout message', () => {
|
||||
beforeAll( async () => {
|
||||
await shopper.block.emptyCart();
|
||||
} );
|
||||
|
||||
it( 'Shopper can view empty cart message on the checkout page', async () => {
|
||||
await shopper.block.goToCheckout();
|
||||
// Verify cart is empty'
|
||||
await expect( page ).toMatchElement(
|
||||
'strong.wc-block-checkout-empty__title',
|
||||
{
|
||||
text: 'Your cart is empty!',
|
||||
}
|
||||
);
|
||||
} );
|
||||
} );
|
|
@ -1,100 +0,0 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { shopper } from '../../../utils';
|
||||
import {
|
||||
SIMPLE_VIRTUAL_PRODUCT_NAME,
|
||||
CUSTOMER_USERNAME,
|
||||
CUSTOMER_PASSWORD,
|
||||
} from '../../../utils/constants';
|
||||
|
||||
const block = {
|
||||
name: 'Checkout',
|
||||
};
|
||||
|
||||
if ( process.env.WOOCOMMERCE_BLOCKS_PHASE < 2 )
|
||||
// eslint-disable-next-line jest/no-focused-tests
|
||||
test.only( `skipping ${ block.name } tests`, () => {} );
|
||||
|
||||
describe( 'Shopper → Checkout → Can see warnings when form is incomplete', () => {
|
||||
beforeAll( async () => {
|
||||
const isShopperLoggedIn = await shopper.isLoggedIn();
|
||||
|
||||
// @todo Find a better way to reset the checkout form instead of login then logout
|
||||
if ( isShopperLoggedIn ) {
|
||||
// Click on the "Log out" link in "My account" page
|
||||
await await page.click(
|
||||
'.woocommerce-MyAccount-navigation-link--customer-logout a'
|
||||
);
|
||||
} else {
|
||||
await shopper.loginFromMyAccountPage(
|
||||
CUSTOMER_USERNAME,
|
||||
CUSTOMER_PASSWORD
|
||||
);
|
||||
|
||||
await await page.click(
|
||||
'.woocommerce-MyAccount-navigation-link--customer-logout a'
|
||||
);
|
||||
}
|
||||
} );
|
||||
|
||||
beforeEach( async () => {
|
||||
await shopper.block.emptyCart();
|
||||
} );
|
||||
|
||||
afterAll( async () => {
|
||||
await shopper.block.emptyCart();
|
||||
} );
|
||||
|
||||
it( 'Shows warnings when form is incomplete', async () => {
|
||||
await shopper.goToShop();
|
||||
await shopper.addToCartFromShopPage( SIMPLE_VIRTUAL_PRODUCT_NAME );
|
||||
await shopper.block.goToCheckout();
|
||||
|
||||
// Click on "Place Order" button
|
||||
await expect( page ).toClick(
|
||||
'.wc-block-components-checkout-place-order-button',
|
||||
{
|
||||
text: 'Place Order',
|
||||
}
|
||||
);
|
||||
|
||||
// Verify that all required fields show the correct warning.
|
||||
await expect( page ).toMatchElement(
|
||||
'#email ~ .wc-block-components-validation-error p',
|
||||
{
|
||||
text: 'Please fill out this field.',
|
||||
}
|
||||
);
|
||||
await expect( page ).toMatchElement(
|
||||
'#billing-first_name ~ .wc-block-components-validation-error p',
|
||||
{
|
||||
text: 'Please fill out this field.',
|
||||
}
|
||||
);
|
||||
await expect( page ).toMatchElement(
|
||||
'#billing-last_name ~ .wc-block-components-validation-error p',
|
||||
{
|
||||
text: 'Please fill out this field.',
|
||||
}
|
||||
);
|
||||
await expect( page ).toMatchElement(
|
||||
'#billing-address_1 ~ .wc-block-components-validation-error p',
|
||||
{
|
||||
text: 'Please fill out this field.',
|
||||
}
|
||||
);
|
||||
await expect( page ).toMatchElement(
|
||||
'#billing-city ~ .wc-block-components-validation-error p',
|
||||
{
|
||||
text: 'Please fill out this field.',
|
||||
}
|
||||
);
|
||||
await expect( page ).toMatchElement(
|
||||
'#billing-postcode ~ .wc-block-components-validation-error p',
|
||||
{
|
||||
text: 'Please fill out this field.',
|
||||
}
|
||||
);
|
||||
} );
|
||||
} );
|
|
@ -1,57 +0,0 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { shopper } from '../../../utils';
|
||||
|
||||
import { SIMPLE_VIRTUAL_PRODUCT_NAME } from '../../../utils/constants';
|
||||
|
||||
const PAYMENT_COD = 'Cash on delivery';
|
||||
const PAYMENT_BACS = 'Direct bank transfer';
|
||||
const PAYMENT_CHEQUE = 'Check payments';
|
||||
|
||||
if ( process.env.WOOCOMMERCE_BLOCKS_PHASE < 2 )
|
||||
// eslint-disable-next-line jest/no-focused-tests
|
||||
test.only( `Skipping checkout tests`, () => {} );
|
||||
|
||||
describe( 'Shopper → Checkout → Can choose payment option', () => {
|
||||
beforeEach( async () => {
|
||||
await shopper.block.emptyCart();
|
||||
} );
|
||||
|
||||
afterAll( async () => {
|
||||
await shopper.block.emptyCart();
|
||||
} );
|
||||
|
||||
it( 'allows customer to pay using Direct bank transfer', async () => {
|
||||
await shopper.goToShop();
|
||||
await shopper.addToCartFromShopPage( SIMPLE_VIRTUAL_PRODUCT_NAME );
|
||||
await shopper.block.goToCheckout();
|
||||
await shopper.block.selectPayment( PAYMENT_BACS );
|
||||
await shopper.block.fillInCheckoutWithTestData();
|
||||
await shopper.block.placeOrder();
|
||||
await expect( page ).toMatch( 'Order received' );
|
||||
await expect( page ).toMatch( PAYMENT_BACS );
|
||||
} );
|
||||
|
||||
it( 'allows customer to pay using Cash on delivery', async () => {
|
||||
await shopper.goToShop();
|
||||
await shopper.addToCartFromShopPage( SIMPLE_VIRTUAL_PRODUCT_NAME );
|
||||
await shopper.block.goToCheckout();
|
||||
await shopper.block.selectPayment( PAYMENT_COD );
|
||||
await shopper.block.fillInCheckoutWithTestData();
|
||||
await shopper.block.placeOrder();
|
||||
await expect( page ).toMatch( 'Order received' );
|
||||
await expect( page ).toMatch( PAYMENT_COD );
|
||||
} );
|
||||
|
||||
it( 'allows customer to pay using Check payments', async () => {
|
||||
await shopper.goToShop();
|
||||
await shopper.addToCartFromShopPage( SIMPLE_VIRTUAL_PRODUCT_NAME );
|
||||
await shopper.block.goToCheckout();
|
||||
await shopper.block.selectPayment( PAYMENT_CHEQUE );
|
||||
await shopper.block.fillInCheckoutWithTestData();
|
||||
await shopper.block.placeOrder();
|
||||
await expect( page ).toMatch( 'Order received' );
|
||||
await expect( page ).toMatch( PAYMENT_CHEQUE );
|
||||
} );
|
||||
} );
|
|
@ -1,35 +0,0 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { shopper } from '../../../utils';
|
||||
import {
|
||||
SIMPLE_VIRTUAL_PRODUCT_NAME,
|
||||
BILLING_DETAILS,
|
||||
} from '../../../utils/constants';
|
||||
|
||||
if ( process.env.WOOCOMMERCE_BLOCKS_PHASE < 2 )
|
||||
// eslint-disable-next-line jest/no-focused-tests
|
||||
test.only( `Skipping checkout tests`, () => {} );
|
||||
|
||||
describe( 'Shopper → Checkout → Can place an order', () => {
|
||||
it( 'allows customer to place an order as a guest', async () => {
|
||||
await shopper.logout();
|
||||
await shopper.goToShop();
|
||||
await shopper.addToCartFromShopPage( SIMPLE_VIRTUAL_PRODUCT_NAME );
|
||||
await shopper.block.goToCheckout();
|
||||
await shopper.block.fillBillingDetails( BILLING_DETAILS );
|
||||
await shopper.block.placeOrder();
|
||||
await expect( page ).toMatch( 'Your order has been received.' );
|
||||
} );
|
||||
|
||||
it( 'allows customer to place an order as a logged in user', async () => {
|
||||
await shopper.login();
|
||||
await shopper.goToShop();
|
||||
await shopper.addToCartFromShopPage( SIMPLE_VIRTUAL_PRODUCT_NAME );
|
||||
await shopper.block.goToCheckout();
|
||||
await shopper.block.fillBillingDetails( BILLING_DETAILS );
|
||||
await shopper.block.placeOrder();
|
||||
await expect( page ).toMatch( 'Your order has been received.' );
|
||||
await shopper.logout();
|
||||
} );
|
||||
} );
|
|
@ -1,57 +0,0 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { merchant } from '@woocommerce/e2e-utils';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { shopper } from '../../../utils';
|
||||
|
||||
const productName = '128GB USB Stick';
|
||||
const freeShippingName = 'Free Shipping';
|
||||
const freeShippingPrice = '$0.00';
|
||||
const normalShippingName = 'Normal Shipping';
|
||||
const normalShippingPrice = '$20.00';
|
||||
|
||||
if ( process.env.WOOCOMMERCE_BLOCKS_PHASE < 2 )
|
||||
// eslint-disable-next-line jest/no-focused-tests
|
||||
test.only( 'Skipping Checkout tests', () => {} );
|
||||
|
||||
describe( `Shopper → Checkout → Can choose shipping option`, () => {
|
||||
beforeAll( async () => {
|
||||
await merchant.login();
|
||||
} );
|
||||
|
||||
afterAll( async () => {
|
||||
await merchant.logout();
|
||||
} );
|
||||
|
||||
it( 'allows customer to choose free shipping', async () => {
|
||||
await shopper.goToShop();
|
||||
await shopper.addToCartFromShopPage( productName );
|
||||
await shopper.block.goToCheckout();
|
||||
await shopper.block.selectAndVerifyShippingOption(
|
||||
freeShippingName,
|
||||
freeShippingPrice
|
||||
);
|
||||
await shopper.block.placeOrder();
|
||||
await page.waitForTimeout( 2000 );
|
||||
await expect( page ).toMatch( 'Order received' );
|
||||
await expect( page ).toMatch( freeShippingName );
|
||||
} );
|
||||
|
||||
it( 'allows customer to choose flat rate shipping', async () => {
|
||||
await shopper.goToShop();
|
||||
await shopper.addToCartFromShopPage( productName );
|
||||
await shopper.block.goToCheckout();
|
||||
await shopper.block.selectAndVerifyShippingOption(
|
||||
normalShippingName,
|
||||
normalShippingPrice
|
||||
);
|
||||
await shopper.block.placeOrder();
|
||||
await page.waitForTimeout( 2000 );
|
||||
await expect( page ).toMatch( 'Order received' );
|
||||
await expect( page ).toMatch( normalShippingName );
|
||||
} );
|
||||
} );
|
|
@ -1,71 +0,0 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { withRestApi } from '@woocommerce/e2e-utils';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { shopper } from '../../../utils';
|
||||
import { createCoupon } from '../../utils';
|
||||
import { SIMPLE_VIRTUAL_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_VIRTUAL_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_VIRTUAL_PRODUCT_NAME );
|
||||
await shopper.block.goToCheckout();
|
||||
await shopper.block.applyCouponFromCheckout( coupon.code );
|
||||
await expect( page ).toMatch( 'Coupon usage limit has been reached.' );
|
||||
} );
|
||||
} );
|
|
@ -54,7 +54,7 @@ const WooCommerce = new WooCommerceRestApi( {
|
|||
|
||||
if ( process.env.WOOCOMMERCE_BLOCKS_PHASE < 3 ) {
|
||||
// eslint-disable-next-line jest/no-focused-tests
|
||||
test.only( `skipping ${ block.name } tests`, () => {} );
|
||||
test.only( `Skipping ${ block.name } tests`, () => {} );
|
||||
}
|
||||
|
||||
describe( 'Shopper → Mini Cart', () => {
|
||||
|
|
|
@ -10,8 +10,9 @@ const config = require( 'config' );
|
|||
*/
|
||||
export const SIMPLE_VIRTUAL_PRODUCT_NAME = 'Woo Single #1';
|
||||
export const SIMPLE_PHYSICAL_PRODUCT_NAME = '128GB USB Stick';
|
||||
export const PAYMENT_COD = 'Cash on delivery';
|
||||
export const PAYMENT_BACS = 'Direct bank transfer';
|
||||
export const PAYMENT_CHEQUE = 'Check payments';
|
||||
export const BILLING_DETAILS = config.get( 'addresses.customer.billing' );
|
||||
export const PERFORMANCE_REPORT_FILENAME = 'reports/e2e-performance.json';
|
||||
export const SHIPPING_DETAILS = config.get( 'addresses.customer.shipping' );
|
||||
export const CUSTOMER_USERNAME = config.get( 'users.customer.username' );
|
||||
export const CUSTOMER_PASSWORD = config.get( 'users.customer.password' );
|
||||
|
|
|
@ -11,3 +11,7 @@ export {
|
|||
export { shopper } from './shopper';
|
||||
export { getLoadingDurations } from './performance';
|
||||
export { selectBlockByName } from './select-block-by-name';
|
||||
export { merchant } from './merchant';
|
||||
export { cli } from './run-cli-from-test';
|
||||
export * from './taxes';
|
||||
export * from './constants';
|
||||
|
|
Loading…
Reference in New Issue