UNPKG

@shopgate/pwa-common

Version:

Common library for the Shopgate Connect PWA.

208 lines (200 loc) • 6.97 kB
import range from 'lodash/range'; import React from 'react'; import { shallow, mount } from 'enzyme'; import { ITEMS_PER_LOAD } from "../../constants/DisplayOptions"; import InfiniteContainer from "./index"; import { jsx as _jsx } from "react/jsx-runtime"; global.console.error = jest.fn(); const context = { state: {} }; describe('<InfiniteContainer />', () => { let renderedElement; let renderedInstance; let mockLoader; let mockIterator; let mockItems; const mockData = range(100).map(id => ({ id, title: `Item ${id}` })); /** * The view component * @param {Object} props The component props. */ const renderComponent = props => { renderedElement = shallow(/*#__PURE__*/_jsx(InfiniteContainer, { ...props }), { context }); renderedInstance = renderedElement.instance(); }; /** * Mocks the mapStateToProps connector. * @param {number} amount The new product amount. */ const receiveItemsByProp = amount => { mockItems = mockData.slice(0, amount); const nextProps = { ...renderedInstance.props, items: mockItems, totalItems: mockData.length }; renderedElement.setProps(nextProps); }; beforeEach(() => { mockLoader = jest.fn(); mockIterator = jest.fn(data => /*#__PURE__*/_jsx("li", { children: data.title }, data.id)); }); describe('Given the component was mounted to the DOM', () => { beforeEach(() => { renderComponent({ items: [], loader: mockLoader, iterator: mockIterator, totalItems: null }); renderedInstance.componentDidMount(); }); it('should match snapshot', () => { expect(renderedElement).toMatchSnapshot(); }); it('should call the loader function', () => { const [offset] = renderedInstance.state.offset; expect(mockLoader).toBeCalledWith(offset); }); describe('Given the loader requested new items', () => { const mockItemsLength = 10; beforeEach(() => { receiveItemsByProp(mockItemsLength); }); it('should call the iterator function according to the number of loaded items', () => { expect(mockIterator).toBeCalled(); expect(mockIterator.mock.calls.length).toBe(mockItemsLength); }); it('should render the loaded items', () => { expect(renderedElement.find('li').length).toBe(mockItemsLength); }); }); describe('Given the component was mounted within a scroll container', () => { const mockItemsLength = 11; beforeEach(() => { // Receive items from initial mounting before proceeding... receiveItemsByProp(mockItemsLength); // Reset any previous calls (e.g. from componentDidMount()) mockLoader.mock.calls = []; renderedInstance.componentDidUpdate(); }); it('should call the loader function if scrolled to the bottom', () => { renderedInstance.domScrollContainer = { scrollTop: 900, scrollHeight: 1000, clientHeight: 100 }; renderedInstance.handleLoading(); expect(mockLoader).toBeCalled(); }); it('should not call the loader function if the scroll position did not change', () => { renderedInstance.domScrollContainer = { scrollTop: 0, scrollHeight: 1000, clientHeight: 100 }; renderedInstance.handleLoading(); expect(mockLoader.mock.calls.length).toBe(0); }); }); describe('Given all items have been received', () => { const mockItemsLength = mockData.length; beforeEach(() => { receiveItemsByProp(mockItemsLength); }); it('should expect no more items to be received', () => { expect(renderedInstance.needsToReceiveItems()).toBe(false); }); it('should keep state.awaitingItems as true if not all items are rendered', () => { expect(renderedInstance.allItemsAreRendered()).toBe(false); expect(renderedInstance.state.awaitingItems).toBe(true); expect(renderedElement.find('li').length).toBeLessThan(mockItemsLength); }); it('should set state.awaitingItems to false if all items are rendered', () => { renderedElement.setState({ offset: [0, mockItemsLength] }); renderedInstance.handleLoading(); expect(renderedInstance.allItemsAreRendered()).toBe(true); expect(renderedInstance.state.awaitingItems).toBe(false); expect(renderedElement.find('li').length).toBe(mockItemsLength); }); }); }); describe('Given that the initialLimit is used in the correct ways', () => { describe('Given that the initialLimit is used', () => { it('should render with the initialLimit', () => { renderComponent({ items: mockData, loader: mockLoader, iterator: mockIterator, totalItems: mockData.length }); // Check if the iniLimit was used expect(renderedElement.find('li').length).toBe(renderedInstance.props.initialLimit); // Reset the limit from props.initialLimit back to props.limit renderedInstance.componentDidMount(); renderedInstance.handleLoading(); // Re-render with the new limit renderedElement.update(); // Check if the correct limit was used for the second render const newLimit = renderedInstance.props.initialLimit + renderedInstance.props.limit; expect(renderedElement.find('li').length).toBe(newLimit); }); }); describe('Given that the initialLimit is NOT used', () => { it('should render without the initialLimit', () => { renderComponent({ items: [], loader: mockLoader, iterator: mockIterator, totalItems: null }); renderedInstance.componentDidMount(); receiveItemsByProp(ITEMS_PER_LOAD); // Check if the iniLimit wasn't used expect(renderedElement).toMatchSnapshot(); expect(renderedElement.find('li').length).toBe(renderedInstance.props.limit); }); }); }); describe('Given that the requestHash changes', () => { it('should reset the component', () => { const props = { items: mockData, loader: mockLoader, iterator: mockIterator, totalItems: mockData.length, requestHash: 'default' }; const wrapper = mount(/*#__PURE__*/_jsx(InfiniteContainer, { ...props })); const instance = wrapper.instance(); instance.componentDidMount(); instance.domScrollContainer = document.createElement('div'); wrapper.setState({ awaitingItems: false, offset: [10, 10] }); wrapper.setProps({ requestHash: 'price_desc' }); expect(wrapper.state()).toEqual({ offset: [0, 32], awaitingItems: true, itemCount: 0 }); }); }); });