Вот решение для модульного тестирования:
itemList.tsx
:
import React, { useState, useEffect } from 'react';
import { fetchItems } from './api';
import { addToSelectList } from './listModule';
import Item from './item';
export default function ItemList() {
const [page, setPage] = useState(1);
const [items, setItems] = useState([]);
useEffect(() => {
fetchItems().then((res) => {
setItems(res.data.items);
});
}, [page]);
function onClickItem(item) {
addToSelectList(item);
}
return (
<ul>
{items.map((item: any, index) => (
<li key={index}>
<Item
name={item.name}
onClick={() => {
onClickItem(item);
}}
/>
</li>
))}
</ul>
);
}
api.ts
:
export const fetchItems = async () => {
return { data: { items: [] } } as any;
};
item.tsx
:
import React from 'react';
export default function Item(props) {
return (
<div>
<div
onClick={() => {
props.onClick();
}}
>
{props.name}
</div>
</div>
);
}
listModule.ts
:
export const addToSelectList = (item) => {
console.log(item);
};
itemList.test.tsx
:
import React from 'react';
import ItemList from './itemList';
import { mount } from 'enzyme';
import { fetchItems } from './api';
import { act } from 'react-dom/test-utils';
import Item from './item';
import { addToSelectList } from './listModule';
jest.mock('./api', () => {
return { fetchItems: jest.fn() };
});
jest.mock('./listModule', () => {
return { addToSelectList: jest.fn() };
});
describe('59853199', () => {
it('should pass', async () => {
const mFetchItemsResponse = { data: { items: [{ name: 'a' }, { name: 'b' }] } };
(fetchItems as jest.MockedFunction<typeof fetchItems>).mockResolvedValueOnce(mFetchItemsResponse);
const wrapper = mount(<ItemList />);
expect(wrapper.find(Item).length).toBe(0);
// when useEffect stable
await act(async () => {
await new Promise((resolve) => setTimeout(resolve));
});
wrapper.update();
expect(wrapper.find(Item).length).toBeGreaterThan(0);
wrapper
.find(Item)
.at(0)
.prop('onClick')();
expect(addToSelectList).toBeCalledWith(mFetchItemsResponse.data.items[0]);
});
});
Результаты модульного теста с отчетом о покрытии:
PASS src/stackoverflow/59853199/itemList.test.tsx
59853199
✓ should pass (98ms)
--------------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
--------------|----------|----------|----------|----------|-------------------|
All files | 94.44 | 100 | 87.5 | 94.44 | |
item.tsx | 75 | 100 | 50 | 75 | 8 |
itemList.tsx | 100 | 100 | 100 | 100 | |
--------------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 4.18s, estimated 10s
Исходный код: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/59853199