I am having some issues testing a react infinite controller. This is my element file:
import InfiniteScroll from 'react-infinite-scroll-component';
import { List } from 'semantic-ui-react';
import styled from 'styled-components';
const StyledList = styled(List)`
margin-bottom: 0.25rem;
flex: 1;
overflow-y: auto;
height: calc(100vh - 190px);
overflow-x: hidden;
padding-top: 5px;
&::-webkit-scrollbar {
width: 5px;
padding: 0px;
}
`;
const StyledInfiniteScroll = styled(InfiniteScroll)`
&& {
padding: 0;
}
`;
export const Styled = {
List: StyledList,
InfiniteScroll: StyledInfiniteScroll,
};
import { ContentArea } from 'Components/shared/ContentArea';
import { FilterBox } from 'Components/shared/FilterBox';
import { InfoMessageBanner } from 'Components/shared/InfoMessageBanner';
import { debounce } from 'lodash';
import { MobXProviderContext, observer } from 'mobx-react';
import * as React from 'react';
import { RootStoreProps } from 'Stores/RootStore.types';
import { DirectoryListItem } from '../DirectoryListItem';
import { Styled } from './index.styles';
export const Directory: React.FC = observer(() => {
const {
search: {
directoryPageNumber,
getDirectorySearch,
isDirectoryLoading,
searchValue,
selectDirectorySearchById,
setDirectorySearchValue,
isTopBarDirectoryLoading,
},
ui,
conversation,
phoneCall,
person,
} = React.useContext<RootStoreProps>(MobXProviderContext);
const [pageNumber, setPageNumber] = React.useState(0);
const [maxContacts, setMaxContacts] = React.useState(0);
const testid = 'directory';
React.useEffect(() => {
const loadContacts = async () => {
const data = await getDirectorySearch('DIRECTORY', '', 20, 1);
if (data?.data?.hits) setMaxContacts(data?.data?.hits);
setPageNumber(1);
};
loadContacts().catch((err) => console.error(err));
}, [isTopBarDirectoryLoading]);
const filter = debounce((q: string) => {
setDirectorySearchValue(q);
if (searchValue && directoryPageNumber > 1) setPageNumber(1);
getDirectorySearch('DIRECTORY', q, 20, pageNumber);
}, 500);
const handleLoadMoreContacts = debounce(async () => {
if (maxContacts === directory.data.results.length) return;
const nextPageNumber = pageNumber + 1;
setPageNumber(nextPageNumber);
await getDirectorySearch(
'DIRECTORY',
searchValue,
20,
nextPageNumber,
true
);
}, 500);
const directory = selectDirectorySearchById('DIRECTORY');
return (
<ContentArea>
<FilterBox
placeholder="Search Directory (min 3 characters)"
sendInput={filter}
loading={isDirectoryLoading}
testid={`${testid}-filterBoxDirectory`}
/>
<Styled.InfiniteScroll
dataLength={pageNumber * 20} //This is important field to render the next data
next={handleLoadMoreContacts}
hasMore
loader={<React.Fragment />}
// below props only if you need pull down functionality
refreshFunction={handleLoadMoreContacts}
pullDownToRefresh
pullDownToRefreshThreshold={2}
scrollableTarget="directory-list"
>
<Styled.List id="directory-list">
{directory?.data?.results?.map(({ source: { id } }) => (
<DirectoryListItem
key={id}
phoneStore={phoneCall}
searchItemId={Number(id)}
uiStore={ui}
{...{ conversation, person, testid }}
/>
))}
<InfoMessageBanner
testid={`${testid}-bannerInfoNoResultsFound`}
show={directory?.query && !directory?.data?.hits}
content={`No results found for "${directory?.query}"`}
/>
</Styled.List>
</Styled.InfiniteScroll>
</ContentArea>
);
});
And this is my test file where i am mocking all the components and then where i am testing that the infinite scroll component is created with the correct props.
import { render } from '@testing-library/react';
import type { RenderResult } from '@testing-library/react';
import React from 'react';
import type { DirectoryPanelProps } from './types';
const mockInject = jest.fn(() => (Component) => Component);
jest.mock('mobx-react', () => ({
...jest.requireActual('mobx-react'),
inject: mockInject,
observer: (Component) => Component,
}));
const mockDirectory = jest.fn(() => <span>Directory</span>);
jest.mock('Components/DirectoryPanel/Directory', () => ({
Directory: mockDirectory,
}));
const mockRoutes = jest.fn(({ children }) => children);
const mockRoute = jest.fn(({ element }) => element);
jest.mock('react-router-dom', () => ({
Routes: mockRoutes,
Route: mockRoute,
}));
const mockGridColumn = jest.fn(({ children }) => children);
jest.mock('./index.styles', () => ({
Styled: {
GridColumn: mockGridColumn,
},
}));
const DEFAULT_PROPS = {
person: { IsLoggedIn: true },
} as unknown as DirectoryPanelProps;
describe('DirectoryPanel', () => {
let renderComponent: (props?: Partial<DirectoryPanelProps>) => RenderResult;
beforeEach(async () => {
const { DirectoryPanel } = await import('./index');
renderComponent = (props) =>
render(<DirectoryPanel {...DEFAULT_PROPS} {...props} />);
});
afterEach(jest.clearAllMocks);
it('does not render when person is not logged in', () => {
const { container } = renderComponent({
person: { IsLoggedIn: false },
} as unknown as DirectoryPanelProps);
expect(container.firstChild).toBeNull();
});
describe.each`
component | mockComponent | expectedResult
${'GridColumn'} | ${mockGridColumn} | ${{ children: expect.anything(), id: 'action-panel' }}
${'Routes'} | ${mockRoutes} | ${{ children: expect.anything() }}
${'Route'} | ${mockRoute} | ${{ path: '/', element: expect.anything() }}
${'Directory'} | ${mockDirectory} | ${{}}
`('$component', ({ mockComponent, expectedResult }) => {
it('renders with correct props', () => {
renderComponent();
expect(mockComponent).toBeCalledTimes(1);
expect(mockComponent).toBeCalledWith(expectedResult, {});
});
});
});
The error i am having is the following:
● Directory › InfiniteScroll › renders with correct props
expect(jest.fn()).toBeCalledWith(...expected)
- Expected
+ Received
@@ -1,7 +1,7 @@
Object {
- "children": Anything,
+ "children": <mockConstructor />,
"dataLength": 0,
"hasMore": true,
"loader": <React.Fragment />,
"next": [Function mockConstructor],
"pullDownToRefresh": true,,
{},
Number of calls: 1
105 |
106 | expect(mockComponent).toBeCalledTimes(1);
> 107 | expect(mockComponent).toBeCalledWith(expectedResult, {});
| ^
108 | });
109 | });
110 | });
at Object.<anonymous> (src/app/components/DirectoryPanel/Directory/index.test.tsx:107:29)
Should't the expect.anything() work here? What am i doing wrong?