I have a component that does some very basic fetching of data. Once this data is fetched, users can interact and click on the items in a list. When an item is clicked, it is displayed at the top of the component with a description as the "active item".
I'd like to test the click functionality by making sure that an item can be set to active, and also removed from being active. However, I am not sure how to do this, since it relies on data from an API. Any ideas?
Component Code
interface Item {
title: string;
description: string;
}
const Home: NextPage = () => {
const [items, setItems] = useState<Item[]>([]);
const [activeItem, setActiveItem] = useState<Item | null>(null);
const fetchItems = async () => {
try {
const res = await axios.get<Item[]>('http://localhost:3090/api/items');
setItems(res.data);
} catch (error) {
console.log(error);
}
};
const handleActiveItem = (item: Item) => {
if (activeItem?.title === item.title) {
setActiveItem(null);
} else {
setActiveItem(item);
}
};
useEffect(() => {
fetchItems();
}, []);
return (
<div>
{activeItem && (
<div data-testid="active-item">
<h1>{activeItem.title}</h1>
<p>{activeItem.description}</p>
</div>
)}
<ul>
{items.map((item: Item) => (
<li key={item.title} onClick={() => handleActiveItem(item)}>
{item.title}
</li>
))}
</ul>
</div>
);
};
Test Code
describe('Home', () => {
it('matches snapshot', () => {
const tree = renderer.create(<Home />).toJSON();
expect(tree).toMatchSnapshot();
});
render(<Home />);
it('Initially there is no active item', () => {
const activeItem = screen.queryByTestId('active-item');
expect(activeItem).not.toBeInTheDocument();
});
it('When an item is clicked in the list, it becomes the active item', () => {
//
});
it('If there is an active item and it is clicked in the list, active item is emptied', () => {
//
});
});