I currently have this react component which displays a list of services which are retreived from an api(removed some code for simplicity) :
function Services(props) {
const [services, setServices] = useState([]);
const [page_nr, setPage_nr] = useState(0);
const [nameSearch, setNameSearch] = useState("");
const [domainSearch, setDomainSearch] = useState("");
let match = useRouteMatch();
let num_on_page = 20;
const get_services = () => {
let skip = page_nr*num_on_page;
fetch('https://myurl/api/services?limit={num_on_page}&skip={skip}', {
method: 'GET'
})
.then((res) => res.json())
.then((result) => setServices(result._embedded.serviceList))
.catch((err) => console.log('error'))
}
const listItems = services.map((service) =>
<li key={service.id}><Link to={`${match.url}/${service.id}`}>
<Service name={service.name} domain={service.domain} description={service.description} /></Link></li>
);
useEffect(() => {
if (nameSearch === "" || domainSearch === "") {
get_services();
}
});
return (
<Switch>
<Route path={`${match.path}/create`} component={ServiceCreate}/>
<Route path={`${match.path}/:id`} component={ServicePage}/>
<Route path={match.path}>
<div className="Services">
<h1>Diensten</h1>
<hr id="services_line"/>
<Link to={`${match.url}/create`}>
<button type="button" className="btn btn-primary">Nieuwe Dienst</button>
</Link>
<ul>{listItems}</ul>
<input type="button" value="Vorige" disabled={page_nr == 0} onClick={() => setPage_nr(page_nr-1)}/>
<input type="button" value="Volgende" disabled={services.length < num_on_page} onClick={() => setPage_nr(page_nr+1)}/>
</div>
</Route>
</Switch>
);
}
export default Services;
And I wrote the following test code, I want to mock the fetch function so that I can test that the rendered amount is correct and here I use Mock Service Worker:
import 'whatwg-fetch';
import { setupWorker, rest } from 'msw';
import { setupServer } from 'msw/node';
const fakeData = {
_embedded: {
serviceList: [{id: 100, name:"naam 1", description:"een omschrijving van de dienst", domain: "domein 1"},
{id: 101, name:"naam 1", description:"een omschrijving van de dienst", domain: "domein 1"},
{id: 102, name:"naam 1", description:"een omschrijving van de dienst", domain: "domein 1"},
{id: 104, name:"naam 1", description:"een omschrijving van de dienst", domain: "domein 1"},
{id: 105, name:"naam 1", description:"een omschrijving van de dienst", domain: "domein 1"},
{id: 106, name:"naam 1", description:"een omschrijving van de dienst", domain: "domein 1"},
{id: 107, name:"naam 1", description:"een omschrijving van de dienst", domain: "domein 1"},
{id: 108, name:"naam 1", description:"een omschrijving van de dienst", domain: "domein 1"}]
}
};
const server = setupServer(
rest.get("https://sel2-4.ugent.be/api/services", (req, res, ctx) => {
return res(ctx.status(200), ctx.json(fakeData))
}));
describe('Test Services', () => {
beforeAll(() => server.listen());
afterAll(() => server.close());
let wrapper = null;
const history = createMemoryHistory()
history.push('/services')
beforeEach(async () => {
await act(async () => {
wrapper = mount(<Router history={history}><Services/></Router>);
});
wrapper.update();
})
afterEach(() => {
wrapper = null;
server.resetHandlers()
})
it('should render correct fetched amount', async () => {
expect(wrapper.find(Service).length).toBe(8);
})
});
When I run the test it fails and it shows that the length is 0 (if I edit const [services, setServices] = useState([]); to have already items in the array, the length is different from 0). It seems like the fetch doesn't even get executed.
Now I have tried many options to mock the fetch function but none of them seemed to work. What am I doing wrong here and what should be the way to test react hooks that use fetch?