2020-06-10 18:21:34 +00:00
|
|
|
/**
|
|
|
|
* External dependencies
|
|
|
|
*/
|
2021-12-07 15:47:50 +00:00
|
|
|
import { render, screen, waitFor, act } from '@testing-library/react';
|
2020-06-10 18:21:34 +00:00
|
|
|
import { previewCart } from '@woocommerce/resource-previews';
|
|
|
|
import { dispatch } from '@wordpress/data';
|
|
|
|
import { CART_STORE_KEY as storeKey } from '@woocommerce/block-data';
|
2021-02-24 01:36:24 +00:00
|
|
|
import { default as fetchMock } from 'jest-fetch-mock';
|
2023-02-13 11:30:09 +00:00
|
|
|
import { registerCheckoutFilters } from '@woocommerce/blocks-checkout';
|
2022-10-04 12:51:07 +00:00
|
|
|
|
2020-06-10 18:21:34 +00:00
|
|
|
/**
|
|
|
|
* Internal dependencies
|
|
|
|
*/
|
2022-07-08 05:53:24 +00:00
|
|
|
import { defaultCartState } from '../../../data/cart/default-state';
|
2022-04-01 13:45:18 +00:00
|
|
|
import { allSettings } from '../../../settings/shared/settings-init';
|
2020-06-10 18:21:34 +00:00
|
|
|
|
2021-10-25 14:46:34 +00:00
|
|
|
import Cart from '../block';
|
|
|
|
|
|
|
|
import FilledCart from '../inner-blocks/filled-cart-block/frontend';
|
|
|
|
import EmptyCart from '../inner-blocks/empty-cart-block/frontend';
|
|
|
|
|
|
|
|
import ItemsBlock from '../inner-blocks/cart-items-block/frontend';
|
|
|
|
import TotalsBlock from '../inner-blocks/cart-totals-block/frontend';
|
|
|
|
|
|
|
|
import LineItemsBlock from '../inner-blocks/cart-line-items-block/block';
|
2022-04-01 13:45:18 +00:00
|
|
|
import OrderSummaryBlock from '../inner-blocks/cart-order-summary-block/frontend';
|
2021-10-25 14:46:34 +00:00
|
|
|
import ExpressPaymentBlock from '../inner-blocks/cart-express-payment-block/block';
|
|
|
|
import ProceedToCheckoutBlock from '../inner-blocks/proceed-to-checkout-block/block';
|
|
|
|
import AcceptedPaymentMethodsIcons from '../inner-blocks/cart-accepted-payment-methods-block/block';
|
2022-04-12 15:13:43 +00:00
|
|
|
import OrderSummaryHeadingBlock from '../inner-blocks/cart-order-summary-heading/frontend';
|
2022-04-01 13:45:18 +00:00
|
|
|
import OrderSummarySubtotalBlock from '../inner-blocks/cart-order-summary-subtotal/frontend';
|
|
|
|
import OrderSummaryShippingBlock from '../inner-blocks/cart-order-summary-shipping/frontend';
|
|
|
|
import OrderSummaryTaxesBlock from '../inner-blocks/cart-order-summary-taxes/frontend';
|
2021-10-25 14:46:34 +00:00
|
|
|
|
|
|
|
const CartBlock = ( {
|
|
|
|
attributes = {
|
|
|
|
showRateAfterTaxName: false,
|
|
|
|
isShippingCalculatorEnabled: false,
|
|
|
|
checkoutPageId: 0,
|
|
|
|
},
|
|
|
|
} ) => {
|
|
|
|
const {
|
|
|
|
showRateAfterTaxName,
|
|
|
|
isShippingCalculatorEnabled,
|
|
|
|
checkoutPageId,
|
|
|
|
} = attributes;
|
|
|
|
return (
|
|
|
|
<Cart attributes={ attributes }>
|
|
|
|
<FilledCart>
|
|
|
|
<ItemsBlock>
|
|
|
|
<LineItemsBlock />
|
|
|
|
</ItemsBlock>
|
|
|
|
<TotalsBlock>
|
2022-04-01 13:45:18 +00:00
|
|
|
<OrderSummaryBlock>
|
2022-04-12 15:13:43 +00:00
|
|
|
<OrderSummaryHeadingBlock />
|
2022-04-01 13:45:18 +00:00
|
|
|
<OrderSummarySubtotalBlock />
|
|
|
|
<OrderSummaryShippingBlock
|
|
|
|
isShippingCalculatorEnabled={
|
|
|
|
isShippingCalculatorEnabled
|
|
|
|
}
|
|
|
|
/>
|
|
|
|
<OrderSummaryTaxesBlock
|
|
|
|
showRateAfterTaxName={ showRateAfterTaxName }
|
|
|
|
/>
|
|
|
|
</OrderSummaryBlock>
|
2021-10-25 14:46:34 +00:00
|
|
|
<ExpressPaymentBlock />
|
|
|
|
<ProceedToCheckoutBlock checkoutPageId={ checkoutPageId } />
|
|
|
|
<AcceptedPaymentMethodsIcons />
|
|
|
|
</TotalsBlock>
|
|
|
|
</FilledCart>
|
|
|
|
<EmptyCart>
|
|
|
|
<p>Empty Cart</p>
|
|
|
|
</EmptyCart>
|
|
|
|
</Cart>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2020-06-10 18:21:34 +00:00
|
|
|
describe( 'Testing cart', () => {
|
2021-12-07 15:47:50 +00:00
|
|
|
beforeEach( () => {
|
|
|
|
act( () => {
|
|
|
|
fetchMock.mockResponse( ( req ) => {
|
2022-02-23 12:00:45 +00:00
|
|
|
if ( req.url.match( /wc\/store\/v1\/cart/ ) ) {
|
2021-12-07 15:47:50 +00:00
|
|
|
return Promise.resolve( JSON.stringify( previewCart ) );
|
|
|
|
}
|
|
|
|
return Promise.resolve( '' );
|
|
|
|
} );
|
|
|
|
// need to clear the store resolution state between tests.
|
|
|
|
dispatch( storeKey ).invalidateResolutionForStore();
|
|
|
|
dispatch( storeKey ).receiveCart( defaultCartState.cartData );
|
2020-06-10 18:21:34 +00:00
|
|
|
} );
|
|
|
|
} );
|
2021-02-22 13:16:45 +00:00
|
|
|
|
2020-07-02 19:10:19 +00:00
|
|
|
afterEach( () => {
|
|
|
|
fetchMock.resetMocks();
|
|
|
|
} );
|
2021-02-22 13:16:45 +00:00
|
|
|
|
2020-06-10 18:21:34 +00:00
|
|
|
it( 'renders cart if there are items in the cart', async () => {
|
2022-04-08 13:47:19 +00:00
|
|
|
render( <CartBlock /> );
|
2020-07-02 19:10:19 +00:00
|
|
|
await waitFor( () => expect( fetchMock ).toHaveBeenCalled() );
|
2022-04-12 15:13:43 +00:00
|
|
|
|
2020-07-02 19:10:19 +00:00
|
|
|
expect(
|
2020-09-26 21:59:51 +00:00
|
|
|
screen.getByText( /Proceed to Checkout/i )
|
2020-07-02 19:10:19 +00:00
|
|
|
).toBeInTheDocument();
|
|
|
|
|
2020-10-27 14:37:18 +00:00
|
|
|
expect( fetchMock ).toHaveBeenCalledTimes( 1 );
|
2020-06-10 18:21:34 +00:00
|
|
|
} );
|
2021-02-22 13:16:45 +00:00
|
|
|
|
2021-05-17 14:00:57 +00:00
|
|
|
it( 'Contains a Taxes section if Core options are set to show it', async () => {
|
|
|
|
allSettings.displayCartPricesIncludingTax = false;
|
|
|
|
// The criteria for showing the Taxes section is:
|
|
|
|
// Display prices during basket and checkout: 'Excluding tax'.
|
2022-04-08 13:47:19 +00:00
|
|
|
render( <CartBlock /> );
|
2021-10-25 14:46:34 +00:00
|
|
|
|
2021-05-17 14:00:57 +00:00
|
|
|
await waitFor( () => expect( fetchMock ).toHaveBeenCalled() );
|
2021-10-25 14:46:34 +00:00
|
|
|
expect( screen.getByText( /Tax/i ) ).toBeInTheDocument();
|
2021-05-17 14:00:57 +00:00
|
|
|
} );
|
|
|
|
|
2022-04-12 15:13:43 +00:00
|
|
|
it( 'Contains a Order summary header', async () => {
|
|
|
|
render( <CartBlock /> );
|
|
|
|
|
|
|
|
await waitFor( () => expect( fetchMock ).toHaveBeenCalled() );
|
|
|
|
expect( screen.getByText( /Cart totals/i ) ).toBeInTheDocument();
|
|
|
|
} );
|
|
|
|
|
|
|
|
it( 'Contains a Order summary Subtotal section', async () => {
|
|
|
|
render( <CartBlock /> );
|
|
|
|
|
|
|
|
await waitFor( () => expect( fetchMock ).toHaveBeenCalled() );
|
|
|
|
expect( screen.getByText( /Subtotal/i ) ).toBeInTheDocument();
|
|
|
|
} );
|
|
|
|
|
2021-05-17 14:00:57 +00:00
|
|
|
it( 'Shows individual tax lines if the store is set to do so', async () => {
|
|
|
|
allSettings.displayCartPricesIncludingTax = false;
|
|
|
|
allSettings.displayItemizedTaxes = true;
|
|
|
|
// The criteria for showing the lines in the Taxes section is:
|
|
|
|
// Display prices during basket and checkout: 'Excluding tax'.
|
|
|
|
// Display tax totals: 'Itemized';
|
2022-04-08 13:47:19 +00:00
|
|
|
render( <CartBlock /> );
|
2021-05-17 14:00:57 +00:00
|
|
|
await waitFor( () => expect( fetchMock ).toHaveBeenCalled() );
|
2021-10-25 14:46:34 +00:00
|
|
|
expect( screen.getByText( /Sales tax/i ) ).toBeInTheDocument();
|
2021-05-17 14:00:57 +00:00
|
|
|
} );
|
|
|
|
|
|
|
|
it( 'Shows rate percentages after tax lines if the block is set to do so', async () => {
|
|
|
|
allSettings.displayCartPricesIncludingTax = false;
|
|
|
|
allSettings.displayItemizedTaxes = true;
|
|
|
|
// The criteria for showing the lines in the Taxes section is:
|
|
|
|
// Display prices during basket and checkout: 'Excluding tax'.
|
|
|
|
// Display tax totals: 'Itemized';
|
2021-10-25 14:46:34 +00:00
|
|
|
render(
|
2021-05-17 14:00:57 +00:00
|
|
|
<CartBlock
|
|
|
|
attributes={ {
|
|
|
|
showRateAfterTaxName: true,
|
|
|
|
} }
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
await waitFor( () => expect( fetchMock ).toHaveBeenCalled() );
|
2021-10-25 14:46:34 +00:00
|
|
|
expect( screen.getByText( /Sales tax 20%/i ) ).toBeInTheDocument();
|
2021-05-17 14:00:57 +00:00
|
|
|
} );
|
|
|
|
|
2020-06-10 18:21:34 +00:00
|
|
|
it( 'renders empty cart if there are no items in the cart', async () => {
|
2022-03-10 13:22:05 +00:00
|
|
|
act( () => {
|
|
|
|
fetchMock.mockResponse( ( req ) => {
|
|
|
|
if ( req.url.match( /wc\/store\/v1\/cart/ ) ) {
|
|
|
|
return Promise.resolve(
|
|
|
|
JSON.stringify( defaultCartState.cartData )
|
|
|
|
);
|
|
|
|
}
|
|
|
|
return Promise.resolve( '' );
|
|
|
|
} );
|
|
|
|
} );
|
2022-04-08 13:47:19 +00:00
|
|
|
render( <CartBlock /> );
|
2020-07-02 19:10:19 +00:00
|
|
|
|
|
|
|
await waitFor( () => expect( fetchMock ).toHaveBeenCalled() );
|
2020-09-26 21:59:51 +00:00
|
|
|
expect( screen.getByText( /Empty Cart/i ) ).toBeInTheDocument();
|
2020-07-02 19:10:19 +00:00
|
|
|
expect( fetchMock ).toHaveBeenCalledTimes( 1 );
|
2020-06-10 18:21:34 +00:00
|
|
|
} );
|
2021-02-22 13:16:45 +00:00
|
|
|
|
|
|
|
it( 'renders correct cart line subtotal when currency has 0 decimals', async () => {
|
|
|
|
fetchMock.mockResponse( ( req ) => {
|
2022-02-23 12:00:45 +00:00
|
|
|
if ( req.url.match( /wc\/store\/v1\/cart/ ) ) {
|
2021-02-22 13:16:45 +00:00
|
|
|
const cart = {
|
|
|
|
...previewCart,
|
|
|
|
// Make it so there is only one item to simplify things.
|
|
|
|
items: [
|
|
|
|
{
|
|
|
|
...previewCart.items[ 0 ],
|
|
|
|
totals: {
|
|
|
|
...previewCart.items[ 0 ].totals,
|
|
|
|
// Change price format so there are no decimals.
|
|
|
|
currency_minor_unit: 0,
|
|
|
|
currency_prefix: '',
|
|
|
|
currency_suffix: '€',
|
|
|
|
line_subtotal: '16',
|
2021-03-02 14:47:43 +00:00
|
|
|
line_total: '18',
|
2021-02-22 13:16:45 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
],
|
|
|
|
};
|
|
|
|
|
|
|
|
return Promise.resolve( JSON.stringify( cart ) );
|
|
|
|
}
|
|
|
|
} );
|
2022-04-08 13:47:19 +00:00
|
|
|
render( <CartBlock /> );
|
2021-02-22 13:16:45 +00:00
|
|
|
|
|
|
|
await waitFor( () => expect( fetchMock ).toHaveBeenCalled() );
|
|
|
|
expect( screen.getAllByRole( 'cell' )[ 1 ] ).toHaveTextContent( '16€' );
|
|
|
|
} );
|
2021-12-10 15:26:57 +00:00
|
|
|
|
|
|
|
it( 'updates quantity when changed in server', async () => {
|
|
|
|
const cart = {
|
|
|
|
...previewCart,
|
|
|
|
// Make it so there is only one item to simplify things.
|
|
|
|
items: [
|
|
|
|
{
|
|
|
|
...previewCart.items[ 0 ],
|
|
|
|
quantity: 5,
|
|
|
|
},
|
|
|
|
],
|
|
|
|
};
|
|
|
|
const itemName = cart.items[ 0 ].name;
|
2022-04-08 13:47:19 +00:00
|
|
|
render( <CartBlock /> );
|
2021-12-10 15:26:57 +00:00
|
|
|
|
|
|
|
await waitFor( () => expect( fetchMock ).toHaveBeenCalled() );
|
|
|
|
const quantityInput = screen.getByLabelText(
|
|
|
|
`Quantity of ${ itemName } in your cart.`
|
|
|
|
);
|
|
|
|
expect( quantityInput.value ).toBe( '2' );
|
|
|
|
|
|
|
|
act( () => {
|
|
|
|
dispatch( storeKey ).receiveCart( cart );
|
|
|
|
} );
|
|
|
|
|
|
|
|
expect( quantityInput.value ).toBe( '5' );
|
|
|
|
} );
|
2022-10-04 12:51:07 +00:00
|
|
|
|
|
|
|
it( 'does not show the remove item button when a filter prevents this', async () => {
|
|
|
|
const cart = {
|
|
|
|
...previewCart,
|
|
|
|
// Make it so there is only one item to simplify things.
|
|
|
|
items: [ previewCart.items[ 0 ] ],
|
|
|
|
};
|
|
|
|
|
2023-02-13 11:30:09 +00:00
|
|
|
registerCheckoutFilters( 'woo-blocks-test-extension', {
|
2022-10-04 12:51:07 +00:00
|
|
|
showRemoveItemLink: ( value, extensions, { cartItem } ) => {
|
|
|
|
return cartItem.id !== cart.items[ 0 ].id;
|
|
|
|
},
|
|
|
|
} );
|
|
|
|
render( <CartBlock /> );
|
|
|
|
|
|
|
|
await waitFor( () => expect( fetchMock ).toHaveBeenCalled() );
|
|
|
|
|
|
|
|
act( () => {
|
|
|
|
dispatch( storeKey ).receiveCart( cart );
|
|
|
|
} );
|
|
|
|
|
|
|
|
expect( screen.queryAllByText( /Remove item/i ).length ).toBe( 0 );
|
|
|
|
} );
|
2020-06-10 18:21:34 +00:00
|
|
|
} );
|