Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Testing product sets - @W-12414116@ #1003

Merged
merged 23 commits into from
Feb 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ const ProductTile = (props) => {
<Text {...styles.title}>{localizedProductName}</Text>

{/* Price */}
<Text {...styles.price}>
<Text {...styles.price} data-testid="product-tile-price">
{hitType === 'set' &&
intl.formatMessage({
id: 'product_tile.label.starting_at_price',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,58 @@ const mockProductSearchItem = {
productName: 'Charcoal Single Pleat Wool Suit'
}

test('Renders Breadcrumb', () => {
const mockProductSet = {
currency: 'GBP',
hitType: 'set',
image: {
alt: 'Winter Look, , large',
disBaseLink:
'https://edge.disstg.commercecloud.salesforce.com/dw/image/v2/ZZRF_001/on/demandware.static/-/Sites-apparel-m-catalog/default/dwe1c4cd52/images/large/PG.10205921.JJ5FUXX.PZ.jpg',
link: 'https://zzrf-001.dx.commercecloud.salesforce.com/on/demandware.static/-/Sites-apparel-m-catalog/default/dwe1c4cd52/images/large/PG.10205921.JJ5FUXX.PZ.jpg',
title: 'Winter Look, '
},
orderable: true,
price: 44.16,
priceMax: 71.03,
pricePerUnit: 44.16,
pricePerUnitMax: 71.03,
productId: 'winter-lookM',
productName: 'Winter Look',
productType: {
set: true
},
representedProduct: {
id: '701642853695M'
},
representedProducts: [
{id: '701642853695M'},
{id: '701642853718M'},
{id: '701642853725M'},
{id: '701642853701M'},
{id: '740357357531M'},
{id: '740357358095M'},
{id: '740357357623M'},
{id: '740357357609M'},
{id: '740357358156M'},
{id: '740357358132M'},
{id: '740357358101M'},
{id: '740357357562M'},
{id: '740357357548M'},
{id: '740357358187M'},
{id: '740357357593M'},
{id: '740357357555M'},
{id: '740357357524M'},
{id: '740357358149M'},
{id: '740357358088M'},
{id: '701642867098M'},
{id: '701642867111M'},
{id: '701642867104M'},
{id: '701642867128M'},
{id: '701642867135M'}
]
}

test('Renders links and images', () => {
const {getAllByRole} = renderWithProviders(<ProductTile product={mockProductSearchItem} />)

const link = getAllByRole('link')
Expand All @@ -36,3 +87,10 @@ test('Renders Skeleton', () => {

expect(skeleton).toBeDefined()
})

test('Product set - renders the appropriate price label', async () => {
const {getByTestId} = renderWithProviders(<ProductTile product={mockProductSet} />)

const container = getByTestId('product-tile-price')
expect(container).toHaveTextContent(/starting at/i)
})
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ import {useProductViewModal} from '../../hooks/use-product-view-modal'
const ProductViewModal = ({product, isOpen, onClose, ...props}) => {
const productViewModalData = useProductViewModal(product)
return (
<Modal data-testid={'sf-product-view-modal'} size="4xl" isOpen={isOpen} onClose={onClose}>
<Modal size="4xl" isOpen={isOpen} onClose={onClose}>
<ModalOverlay />
<ModalContent>
<ModalContent containerProps={{'data-testid': 'product-view-modal'}}>
Comment on lines -20 to +22
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unlike other Chakra components, Modal does not accept any props you pass in. So to set the test id, using containerProps like this is one way to do it.

<ModalCloseButton />
<ModalBody pb={8} bg="white" paddingBottom={6} marginTop={6}>
<ProductView
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,18 @@ export const AddToCartModal = () => {
const intl = useIntl()
const basket = useBasket()
const size = useBreakpointValue({base: 'full', lg: '2xl', xl: '4xl'})
const {currency, productItems, productSubTotal, itemAccumulatedCount} = basket
const {currency, productItems, productSubTotal} = basket
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

itemAccumulatedCount is a duplicate, when we're calculating totalQuantity in the line below. Removing the duplicate is also aligned with what's happening in the hooks-integration branch.

const totalQuantity = itemsAdded.reduce((acc, {quantity}) => acc + quantity, 0)

return (
<Modal size={size} isOpen={isOpen} onClose={onClose} scrollBehavior="inside" isCentered>
<ModalOverlay />
<ModalContent margin="0" borderRadius={{base: 'none', md: 'base'}} bgColor="gray.50">
<ModalContent
margin="0"
borderRadius={{base: 'none', md: 'base'}}
bgColor="gray.50"
containerProps={{'data-testid': 'add-to-cart-modal'}}
>
<ModalHeader paddingY="8" bgColor="white" fontSize="2xl" fontWeight="700">
{intl.formatMessage(
{
Expand Down Expand Up @@ -118,6 +123,7 @@ export const AddToCartModal = () => {
borderBottomWidth={{base: '1px', lg: '0px'}}
borderColor="gray.200"
borderStyle="solid"
data-testid="product-added"
>
<Flex gridGap="4">
<Box w="24" flex="none">
Expand Down Expand Up @@ -180,7 +186,7 @@ export const AddToCartModal = () => {
'Cart Subtotal ({itemAccumulatedCount} item)',
id: 'add_to_cart_modal.label.cart_subtotal'
},
{itemAccumulatedCount}
{itemAccumulatedCount: totalQuantity}
)}
</Text>
<Text alignSelf="flex-end" fontWeight="600">
Expand Down Expand Up @@ -245,7 +251,7 @@ export const AddToCartModal = () => {
defaultMessage: 'Cart Subtotal ({itemAccumulatedCount} item)',
id: 'add_to_cart_modal.label.cart_subtotal'
},
{itemAccumulatedCount}
{itemAccumulatedCount: totalQuantity}
)}
</Text>
<Text alignSelf="flex-end" fontWeight="600">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import React from 'react'
import {AddToCartModal, AddToCartModalContext} from './use-add-to-cart-modal'
import {renderWithProviders} from '../utils/test-utils'
import {screen} from '@testing-library/react'

const MOCK_PRODUCT = {
currency: 'USD',
Expand Down Expand Up @@ -560,18 +561,24 @@ const MOCK_PRODUCT = {
c_width: 'Z'
}

test('Renders AddToCartModal', () => {
test('Renders AddToCartModal with multiple products', () => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tend to make all tests use at least some amount of await / async / waitFor so I would make this an async function

const MOCK_DATA = {
product: MOCK_PRODUCT,
itemsAdded: [
{
product: MOCK_PRODUCT,
variant: MOCK_PRODUCT.variants[0],
quantity: 22
},
{
product: MOCK_PRODUCT,
variant: MOCK_PRODUCT.variants[0],
quantity: 1
}
]
}
const {getByText} = renderWithProviders(

renderWithProviders(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would await renderWithProviders(

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Our renderWithProviders, which would call render from the testing library, is not an async method. It returns an object. So calling await here would not do anything.

iTerm2 2023-02-27 at 13 43 50

<AddToCartModalContext.Provider
value={{
isOpen: true,
Expand All @@ -582,7 +589,11 @@ test('Renders AddToCartModal', () => {
</AddToCartModalContext.Provider>
)

expect(getByText(MOCK_PRODUCT.name)).toBeInTheDocument()
expect(screen.getAllByText(MOCK_PRODUCT.name)[0]).toBeInTheDocument()
expect(screen.getByRole('dialog', {name: /23 items added to cart/i})).toBeInTheDocument()

const numOfRowsRendered = screen.getAllByTestId('product-added').length
expect(numOfRowsRendered).toEqual(MOCK_DATA.itemsAdded.length)
Comment on lines +592 to +596
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I remember you saying something about "awaiting too many things" which I'm still a bit confused about. If you want all of the expect conditions to be true at the same time (usually true, I believe) then I would wrap this in waitFor(() => {})

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I won't use the waitFor in this case (in the product-sets feature branch). Maybe it becomes necessary within the hooks-integration work.

After the component is rendered, I expect all those expect conditions to be true.. all at the same time, yup. Because one render of the component is enough. It won't be re-rendered by some data fetching or async operation.

})

test('Do not render when isOpen is false', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright (c) 2023, Salesforce, Inc.
* All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/

import React from 'react'
import {screen} from '@testing-library/react'
import PropTypes from 'prop-types'
import {usePDPSearchParams} from './use-pdp-search-params'
import {renderWithProviders} from '../utils/test-utils'

const MockComponent = ({productId} = {}) => {
const [allParams, productParams] = usePDPSearchParams(productId)

return (
<>
<div data-testid="all-params">{allParams.toString()}</div>
<div data-testid="product-params">{productParams.toString()}</div>{' '}
</>
)
}
MockComponent.propTypes = {
productId: PropTypes.string
}

test('product set', () => {
const url =
// The parent's id is `winter-lookM`, while the children's are `25518447M` and `25518704M`
'/global/en-GB/product/winter-lookM?25518447M=color%3DJJ5FUXX%26size%3D9XL&25518704M=color%3DJJ2XNXX%26size%3D9MD'
window.history.pushState({}, '', url)

renderWithProviders(<MockComponent productId="25518704M" />)

expect(screen.getByTestId('all-params')).toHaveTextContent(
/^25518447M=color%3DJJ5FUXX%26size%3D9XL&25518704M=color%3DJJ2XNXX%26size%3D9MD$/
)
expect(screen.getByTestId('product-params')).toHaveTextContent(/^color=JJ2XNXX&size=9MD$/)
})

test('regular product with variant', () => {
const url = '/global/en-GB/product/25502228M?color=JJ0NLD0&size=9MD&pid=701642889830M'
window.history.pushState({}, '', url)

renderWithProviders(<MockComponent />)

expect(screen.getByTestId('all-params')).toHaveTextContent(
/^color=JJ0NLD0&size=9MD&pid=701642889830M$/
)
expect(screen.getByTestId('product-params')).toHaveTextContent(/^$/)
})
Loading