2021-10-15 10:53:44 +00:00
/ * *
* External dependencies
* /
2021-10-25 16:05:01 +00:00
import {
act ,
render ,
screen ,
2022-08-02 14:28:52 +00:00
queryByText ,
2021-10-25 16:05:01 +00:00
waitFor ,
waitForElementToBeRemoved ,
} from '@testing-library/react' ;
2021-10-15 10:53:44 +00:00
import { previewCart } from '@woocommerce/resource-previews' ;
import { dispatch } from '@wordpress/data' ;
import { CART _STORE _KEY as storeKey } from '@woocommerce/block-data' ;
import { SlotFillProvider } from '@woocommerce/blocks-checkout' ;
import { default as fetchMock } from 'jest-fetch-mock' ;
2022-01-31 10:53:21 +00:00
import userEvent from '@testing-library/user-event' ;
2021-10-15 10:53:44 +00:00
/ * *
* Internal dependencies
* /
import Block from '../block' ;
2022-07-08 05:53:24 +00:00
import { defaultCartState } from '../../../data/cart/default-state' ;
2021-10-15 10:53:44 +00:00
const MiniCartBlock = ( props ) => (
< SlotFillProvider >
2021-11-19 11:47:48 +00:00
< Block
2023-05-30 13:39:19 +00:00
contents = ' < div data - block - name = "woocommerce/mini-cart-contents" class = "wp-block-woocommerce-mini-cart-contents" > < div data - block - name = "woocommerce/filled-mini-cart-contents-block" class = "wp-block-woocommerce-filled-mini-cart-contents-block" > < div data - block - name = "woocommerce/mini-cart-title-block" class = "wp-block-woocommerce-mini-cart-title-block" > < div data - block - name = "woocommerce/mini-cart-title-label-block" class = "wp-block-woocommerce-mini-cart-title-label-block" > < / d i v >
< div data - block - name = "woocommerce/mini-cart-title-items-counter-block" class = "wp-block-woocommerce-mini-cart-title-items-counter-block" > < / d i v > < / d i v >
< div data - block - name = "woocommerce/mini-cart-items-block" class = "wp-block-woocommerce-mini-cart-items-block" > < div data - block - name = "woocommerce/mini-cart-products-table-block" class = "wp-block-woocommerce-mini-cart-products-table-block" > < / d i v > < / d i v >
< div data - block - name = "woocommerce/mini-cart-footer-block" class = "wp-block-woocommerce-mini-cart-footer-block" > < div data - block - name = "woocommerce/mini-cart-cart-button-block" class = "wp-block-woocommerce-mini-cart-cart-button-block" > < / d i v >
< div data - block - name = "woocommerce/mini-cart-checkout-button-block" class = "wp-block-woocommerce-mini-cart-checkout-button-block" > < / d i v > < / d i v > < / d i v >
< div data - block - name = "woocommerce/empty-mini-cart-contents-block" class = "wp-block-woocommerce-empty-mini-cart-contents-block" >
< p class = "has-text-align-center" > < strong > Your cart is currently empty ! < / s t r o n g > < / p >
< div data - block - name = "woocommerce/mini-cart-shopping-button-block" class = "wp-block-woocommerce-mini-cart-shopping-button-block" > < / d i v > < / d i v > < / d i v > '
2021-11-19 11:47:48 +00:00
{ ... props }
/ >
2021-10-15 10:53:44 +00:00
< / S l o t F i l l P r o v i d e r >
) ;
2021-10-25 16:05:01 +00:00
const mockEmptyCart = ( ) => {
fetchMock . mockResponse ( ( req ) => {
2022-02-23 12:00:45 +00:00
if ( req . url . match ( /wc\/store\/v1\/cart/ ) ) {
2021-10-25 16:05:01 +00:00
return Promise . resolve (
JSON . stringify ( defaultCartState . cartData )
) ;
}
return Promise . resolve ( '' ) ;
} ) ;
} ;
const mockFullCart = ( ) => {
fetchMock . mockResponse ( ( req ) => {
2022-02-23 12:00:45 +00:00
if ( req . url . match ( /wc\/store\/v1\/cart/ ) ) {
2021-10-25 16:05:01 +00:00
return Promise . resolve ( JSON . stringify ( previewCart ) ) ;
}
return Promise . resolve ( '' ) ;
} ) ;
} ;
2023-06-30 14:05:27 +00:00
const initializeLocalStorage = ( ) => {
Object . defineProperty ( window , 'localStorage' , {
value : {
setItem : jest . fn ( ) ,
} ,
writable : true ,
} ) ;
} ;
2023-05-11 12:52:03 +00:00
describe ( 'Testing Mini-Cart' , ( ) => {
2021-12-07 15:47:50 +00:00
beforeEach ( ( ) => {
act ( ( ) => {
mockFullCart ( ) ;
// need to clear the store resolution state between tests.
dispatch ( storeKey ) . invalidateResolutionForStore ( ) ;
dispatch ( storeKey ) . receiveCart ( defaultCartState . cartData ) ;
} ) ;
2021-10-15 10:53:44 +00:00
} ) ;
afterEach ( ( ) => {
fetchMock . resetMocks ( ) ;
} ) ;
2023-05-11 15:23:36 +00:00
it ( 'shows Mini-Cart count badge when there are items in the cart' , async ( ) => {
render ( < MiniCartBlock / > ) ;
await waitFor ( ( ) => expect ( fetchMock ) . toHaveBeenCalled ( ) ) ;
await waitFor ( ( ) =>
expect ( screen . getByText ( '3' ) ) . toBeInTheDocument ( )
) ;
} ) ;
it ( "doesn't show Mini-Cart count badge when cart is empty" , async ( ) => {
mockEmptyCart ( ) ;
render ( < MiniCartBlock / > ) ;
await waitFor ( ( ) => expect ( fetchMock ) . toHaveBeenCalled ( ) ) ;
const badgeWith0Count = screen . queryByText ( '0' ) ;
expect ( badgeWith0Count ) . toBeNull ( ) ;
} ) ;
2023-05-11 12:52:03 +00:00
it ( 'opens Mini-Cart drawer when clicking on button' , async ( ) => {
2024-05-15 09:33:36 +00:00
const user = userEvent . setup ( ) ;
2021-10-15 10:53:44 +00:00
render ( < MiniCartBlock / > ) ;
2024-05-15 09:33:36 +00:00
2021-10-15 10:53:44 +00:00
await waitFor ( ( ) => expect ( fetchMock ) . toHaveBeenCalled ( ) ) ;
2024-05-15 09:33:36 +00:00
await act ( async ( ) => {
await user . click ( screen . getByLabelText ( /items/i ) ) ;
} ) ;
2021-10-15 10:53:44 +00:00
2023-05-30 13:39:19 +00:00
await waitFor ( ( ) =>
expect ( screen . getByText ( /your cart/i ) ) . toBeInTheDocument ( )
) ;
2024-05-15 09:33:36 +00:00
// The opening of the drawer uses deprecated ReactDOM.render.
expect ( console ) . toHaveErroredWith (
` Warning: ReactDOM.render is no longer supported in React 18. Use createRoot instead. Until you switch to the new API, your app will behave as if it's running React 17. Learn more: https://reactjs.org/link/switch-to-createroot%s ` ,
// The stack trace
expect . any ( String )
) ;
2023-05-30 13:39:19 +00:00
} ) ;
it ( 'closes the drawer when clicking on the close button' , async ( ) => {
2024-05-15 09:33:36 +00:00
const user = userEvent . setup ( ) ;
2023-05-30 13:39:19 +00:00
render ( < MiniCartBlock / > ) ;
await waitFor ( ( ) => expect ( fetchMock ) . toHaveBeenCalled ( ) ) ;
// Open drawer.
2024-05-15 09:33:36 +00:00
await act ( async ( ) => {
await user . click ( screen . getByLabelText ( /items/i ) ) ;
} ) ;
2023-05-30 13:39:19 +00:00
// Close drawer.
let closeButton = null ;
await waitFor ( ( ) => {
closeButton = screen . getByLabelText ( /close/i ) ;
} ) ;
if ( closeButton ) {
2024-05-15 09:33:36 +00:00
await act ( async ( ) => {
await user . click ( closeButton ) ;
} ) ;
2023-05-30 13:39:19 +00:00
}
await waitFor ( ( ) => {
expect (
screen . queryByText ( /your cart/i )
) . not . toBeInTheDocument ( ) ;
} ) ;
2024-05-15 09:33:36 +00:00
// The opening of the drawer uses deprecated ReactDOM.render.
expect ( console ) . toHaveErroredWith (
` Warning: ReactDOM.render is no longer supported in React 18. Use createRoot instead. Until you switch to the new API, your app will behave as if it's running React 17. Learn more: https://reactjs.org/link/switch-to-createroot%s ` ,
// The stack trace
expect . any ( String )
) ;
2021-10-15 10:53:44 +00:00
} ) ;
it ( 'renders empty cart if there are no items in the cart' , async ( ) => {
2024-05-15 09:33:36 +00:00
const user = userEvent . setup ( ) ;
2021-10-25 16:05:01 +00:00
mockEmptyCart ( ) ;
2021-10-15 10:53:44 +00:00
render ( < MiniCartBlock / > ) ;
await waitFor ( ( ) => expect ( fetchMock ) . toHaveBeenCalled ( ) ) ;
2024-05-15 09:33:36 +00:00
await act ( async ( ) => {
await user . click ( screen . getByLabelText ( /items/i ) ) ;
} ) ;
2021-10-15 10:53:44 +00:00
expect ( fetchMock ) . toHaveBeenCalledTimes ( 1 ) ;
2024-05-15 09:33:36 +00:00
// The opening of the drawer uses deprecated ReactDOM.render.
expect ( console ) . toHaveErroredWith (
` Warning: ReactDOM.render is no longer supported in React 18. Use createRoot instead. Until you switch to the new API, your app will behave as if it's running React 17. Learn more: https://reactjs.org/link/switch-to-createroot%s ` ,
// The stack trace
expect . any ( String )
) ;
2021-10-15 10:53:44 +00:00
} ) ;
2021-10-25 16:05:01 +00:00
it ( 'updates contents when removed from cart event is triggered' , async ( ) => {
render ( < MiniCartBlock / > ) ;
await waitFor ( ( ) => expect ( fetchMock ) . toHaveBeenCalled ( ) ) ;
mockEmptyCart ( ) ;
// eslint-disable-next-line no-undef
const removedFromCartEvent = new Event ( 'wc-blocks_removed_from_cart' ) ;
act ( ( ) => {
document . body . dispatchEvent ( removedFromCartEvent ) ;
} ) ;
await waitForElementToBeRemoved ( ( ) =>
2021-11-19 11:47:48 +00:00
screen . queryByLabelText ( /3 items in cart/i )
2021-10-25 16:05:01 +00:00
) ;
await waitFor ( ( ) =>
2021-11-19 11:47:48 +00:00
expect (
screen . getByLabelText ( /0 items in cart/i )
) . toBeInTheDocument ( )
2021-10-25 16:05:01 +00:00
) ;
} ) ;
it ( 'updates contents when added to cart event is triggered' , async ( ) => {
mockEmptyCart ( ) ;
render ( < MiniCartBlock / > ) ;
await waitFor ( ( ) => expect ( fetchMock ) . toHaveBeenCalled ( ) ) ;
mockFullCart ( ) ;
// eslint-disable-next-line no-undef
2021-11-19 11:47:48 +00:00
const addedToCartEvent = new Event ( 'wc-blocks_added_to_cart' ) ;
2021-10-25 16:05:01 +00:00
act ( ( ) => {
2021-11-19 11:47:48 +00:00
document . body . dispatchEvent ( addedToCartEvent ) ;
2021-10-25 16:05:01 +00:00
} ) ;
await waitForElementToBeRemoved ( ( ) =>
2021-11-19 11:47:48 +00:00
screen . queryByLabelText ( /0 items in cart/i )
2021-10-25 16:05:01 +00:00
) ;
await waitFor ( ( ) =>
2021-11-19 11:47:48 +00:00
expect (
screen . getByLabelText ( /3 items in cart/i )
) . toBeInTheDocument ( )
2021-10-25 16:05:01 +00:00
) ;
} ) ;
2022-08-02 14:28:52 +00:00
2023-06-30 14:05:27 +00:00
it ( 'updates local storage when cart finishes loading' , async ( ) => {
initializeLocalStorage ( ) ;
mockFullCart ( ) ;
render ( < MiniCartBlock / > ) ;
await waitFor ( ( ) => expect ( fetchMock ) . toHaveBeenCalled ( ) ) ;
// Assert we saved the values returned to the localStorage.
await waitFor ( ( ) =>
expect (
JSON . parse ( window . localStorage . setItem . mock . calls [ 0 ] [ 1 ] )
. itemsCount
) . toEqual ( 3 )
) ;
} ) ;
2022-08-02 14:28:52 +00:00
it ( 'renders cart price if "Hide Cart Price" setting is not enabled' , async ( ) => {
mockEmptyCart ( ) ;
2023-12-04 16:27:27 +00:00
render ( < MiniCartBlock hasHiddenPrice = { false } / > ) ;
2022-08-02 14:28:52 +00:00
await waitFor ( ( ) => expect ( fetchMock ) . toHaveBeenCalled ( ) ) ;
await waitFor ( ( ) =>
expect ( screen . getByText ( '$0.00' ) ) . toBeInTheDocument ( )
) ;
} ) ;
it ( 'does not render cart price if "Hide Cart Price" setting is enabled' , async ( ) => {
mockEmptyCart ( ) ;
2023-12-04 16:27:27 +00:00
const { container } = render ( < MiniCartBlock / > ) ;
2022-08-02 14:28:52 +00:00
await waitFor ( ( ) => expect ( fetchMock ) . toHaveBeenCalled ( ) ) ;
await waitFor ( ( ) =>
expect ( queryByText ( container , '$0.00' ) ) . not . toBeInTheDocument ( )
) ;
} ) ;
2021-10-15 10:53:44 +00:00
} ) ;