'Mock Service Worker returns empty
I'm new to react testing library. I am trying to test a simple component that call some apis
and then it fills inputs with the data of these apis. But when I run npm test
it keeps showing me this : the recieved value is empty
Expected the element to have value: 100 Received:
7 | it('displays returned client info on successful fetch', async () => {
8 | render(<Client />);
> 9 | expect(await screen.findByLabelText('IFU')).toHaveValue('100');
| ^
10 | });
11 |
12 | it('displays error message when fetching tasks raises error', async () => {
at Object.<anonymous> (src/unit-tests/Client.test.js:9:51)
here is my test
import { render, screen } from '@testing-library/react';
import Client from './../components/Client';
import { mswServer } from './api-mocks/msw-server';
import { clientHandlerException } from './api-mocks/handlers';
describe('Component: Client', () => {
it('displays returned client info on successful fetch', async () => {
render(<Client />);
expect(await screen.findByLabelText('IFU')).toHaveValue('100');
});
it('displays error message when fetching tasks raises error', async () => {
mswServer.use(clientHandlerException);
render(<Client />);
});
});
handlers.js
import { rest } from 'msw';
const importateur = {numeroRc: "1000", description: "desc one", ifu: "100", ice: "789", company: "mycom", city: "paris"}
export const clientHandler = rest.get("http://localhost:8080/api/informationsClient", async (req, res, ctx) => {
// res(ctx.json(mockClientInfo))
return res(
ctx.status(200),
ctx.json(importateur)
)
});
export const clientHandlerException = rest.get("http://localhost:8080/api/informationsClient", async (req, res, ctx) =>
res(ctx.status(500), ctx.json({ message: 'Deliberately broken request' }))
);
export const handlers = [clientHandler];
msw-server.js
import { setupServer } from 'msw/node';
import { handlers } from './handlers';
export const mswServer = setupServer(...handlers);
setupTests.js
import '@testing-library/jest-dom';
import { mswServer } from './msw-server';
beforeAll(() => mswServer.listen());
afterEach(() => mswServer.resetHandlers());
afterAll(() => mswServer.close());
My component
export interface IClient {
numeroRc: string,
description: string,
ifu: string,
ice: string
}
const Client = (props: ClientProps) => {
const [clientData, setClientData] = React.useState<IClient>(
{numeroRc: "",
description: "",
ifu: "",
ice: ""}
);
//other useEffect s that call other apis
React.useEffect(() => {
(async () => {
const response = await getClientInfo();
setClientData(response as IClient);
})();
}, [])
return(
<Stack direction="row" spacing={3} className='client' >
<TextField id="numro-rc" label="Numero RC" variant="outlined" value={clientData.numeroRc}/>
<TextField id="client" label="Client" variant="outlined" value={clientData.description}/>
<TextField id="ifu" label="IFU" variant="outlined" value={clientData.ifu} />
<TextField title='ice' id="ice" label="ICE" variant="outlined" value={clientData.ice} />
</Stack>
);
}
UPDATE
getClientInfo is a method that call my api using axios ( I put all my apis calls inside a file api.tsx)
axios.defaults.baseURL = 'http://localhost:8080/api'
...
export const getClientInfo = async () => {
try {
const response = await axios.get(`/informationsClient`);
return response.data;
} catch(e) {
console.log(e);
return 0;
}
}
please what it could be the issue ?
Solution 1:[1]
The problem is that you're not awaiting for the value but the element, and the element is there when the component is mounted with a value of ""
, hence your assertion fails.
So, you need to await
for the value, you can use waitFor
for the same.
import { render, screen, waitFor } from "@testing-library/react";
describe("Component: Client", () => {
it("displays returned client info on successful fetch", async () => {
render(<Client />);
const element = screen.getByLabelText("IFU");
await waitFor(() => {
expect(element).toHaveValue("100");
});
});
});
You can also do it using findByDisplayValue
:
import { render, screen, waitFor } from "@testing-library/react";
describe("Component: Client", () => {
it("displays returned client info on successful fetch", async () => {
render(<Client />);
const element = await screen.findByDisplayValue("100");
expect(element).toBeInTheDocument();
});
});
UPDATE:
Once you've made the following two changes, both the above methods of testing would work fine.
You've created a
setupTests.ts
file insideapi-mocks
which has no effect because CRA doesn't consider anysetupTest.ts
file but only the one that is there insidesrc
. You would notice there's already asetupTest.ts
file insidesrc
, just move all your setup code into this file.The mock server returns an array but your
clientData
state expects an object, so do either of the following:Update the mock server to return an object instead of an array (in
handlers.js
)js const client = { numeroRc: "1000", description: "desc one", ifu: "100", ice: "789", company: "mycom", city: "paris" };
Or extract the object from the array before setting the state (in
Client.tsx
).const response = await getClientInfo(); setClientData(response[0]);
You also need to give an onChange
handler to all your inputs to get rid of the warnings.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |