Reputation: 2310
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 ?
Upvotes: 0
Views: 4815
Reputation: 8188
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 inside api-mocks
which has no effect because CRA doesn't consider any setupTest.ts
file but only the one that is there inside src
. You would notice there's already a setupTest.ts
file inside src
, 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.
Upvotes: 2