Unit testing components
Be careful when using jest.mock on modules like Reactive Data Client. Eliminating expected
exports can lead to hard-to trace
errors like TypeError: Class extends value undefined is not a function or null
.
Instead either do a partial mock, or better mockResolvedValue on your endpoints.
If you need to add unit tests to your components to check some behavior you might want avoid dealing with network fetch cycle as that is probably orthogonal to what your are trying to test. Using <DataProvider /> with mockInitialState and Fixtures in our tests allow us to prime the cache with provided fixtures so the components will immediately render with said results.
Testing user interactions that trigger mutations can be aided with the use of <MockResolver /> and Interceptors
export default {
full: [
{
endpoint: ArticleResource.getList,
args: [{ maxResults: 10 }] as const,
response: [
{
id: 5,
content: 'have a merry christmas',
author: 2,
contributors: [],
},
{
id: 532,
content: 'never again',
author: 23,
contributors: [5],
},
],
},
{
endpoint: ArticleResource.update,
args: [{ id: 532 }] as const,
response({ id }, body) {
return {
id,
...body,
};
},
},
],
empty: [
{
endpoint: ArticleResource.getList,
args: [{ maxResults: 10 }] as const,
response: [],
},
],
error: [
{
endpoint: ArticleResource.getList,
args: [{ maxResults: 10 }] as const,
response: { message: 'Bad request', status: 400, name: 'Not Found' },
error: true,
},
],
loading: [],
};
import { DataProvider, AsyncBoundary } from '@data-client/react';
import { render, waitFor } from '@testing-library/react';
import { MockResolver, mockInitialState } from '@data-client/test';
import ArticleList from 'components/ArticleList';
import results from './fixtures';
describe('<ArticleList />', () => {
it('renders', () => {
const tree = (
<DataProvider initialState={mockInitialState(results.full)}>
<ArticleList maxResults={10} />
</DataProvider>
);
const { findByText } = render(tree);
const content = findByText(results.full.result[0].content);
expect(content).toBeDefined();
});
it('suspends then resolves', async () => {
const tree = (
<DataProvider>
<MockResolver fixtures={results.full}>
<AsyncBoundary fallback="loading">
<ArticleList maxResults={10} />
</AsyncBoundary>
</MockResolver>
</DataProvider>
);
const { findByText } = render(tree);
expect(findByText('loading')).toBeDefined();
await waitFor(expect(findByText(results.full.result[0].content)).toBeDefined());
})
});