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
2023-09-05 04:03:35 +00:00
jest . mock ( '@wordpress/compose' , ( ) => ( {
... jest . requireActual ( '@wordpress/compose' ) ,
useResizeObserver : jest . fn ( ) . mockReturnValue ( [ null , { width : 0 } ] ) ,
} ) ) ;
2021-10-25 14:46:34 +00:00
const CartBlock = ( {
attributes = {
showRateAfterTaxName : false ,
checkoutPageId : 0 ,
} ,
} ) => {
2023-10-11 14:09:43 +00:00
const { showRateAfterTaxName , checkoutPageId } = attributes ;
2021-10-25 14:46:34 +00:00
return (
< Cart attributes = { attributes } >
< FilledCart >
< ItemsBlock >
< LineItemsBlock / >
< / I t e m s B l o c k >
< 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 / >
2023-10-11 14:09:43 +00:00
< OrderSummaryShippingBlock / >
2022-04-01 13:45:18 +00:00
< OrderSummaryTaxesBlock
showRateAfterTaxName = { showRateAfterTaxName }
/ >
< / O r d e r S u m m a r y B l o c k >
2021-10-25 14:46:34 +00:00
< ExpressPaymentBlock / >
< ProceedToCheckoutBlock checkoutPageId = { checkoutPageId } / >
< AcceptedPaymentMethodsIcons / >
< / T o t a l s B l o c k >
< / F i l l e d C a r t >
< EmptyCart >
< p > Empty Cart < / p >
< / E m p t y C a r t >
< / C a r t >
) ;
} ;
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 / > ) ;
2024-05-03 03:28:39 +00:00
// TODO: Fix a recent deprecation of showSpinner prop of Button called in this component.
expect ( console ) . toHaveWarned ( ) ;
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' ) ;
2024-05-15 09:33:36 +00:00
// React Transition Group uses deprecated findDOMNode, so we need to suppress the warning. This will have to be fixed in React 19.
expect ( console ) . toHaveErroredWith (
` Warning: findDOMNode is deprecated and will be removed in the next major release. Instead, add a ref directly to the element you want to reference. Learn more about using refs safely here: https://reactjs.org/link/strict-mode-find-node%s ` ,
// The stack trace
expect . any ( String )
) ;
2021-12-10 15:26:57 +00:00
} ) ;
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
} ) ;