Reputation: 551
I have a hard time making tests that are waiting for a new state from context. Here is a simple app that is showing a loader until user is fetched:
(I know all of the code isn't necessary in order to make the application do what it does, but it reflects more how I have an implementation in a real project)
export const Greeting: React.FC<{}> = () => {
const { loading, user } = useUserContext();
return (
<div>
{loading ? (
<CircularProgress />
) : (
<h1>
Hello {user.firstname} {user.lastname}
</h1>
)}
</div>
);
};
and here's the test:
import React from "react";
import Adapter from "enzyme-adapter-react-16";
import Enzyme, { mount } from "enzyme";
import { Greeting } from "./Greeting";
import { UserContextProvider } from "./UserContext";
Enzyme.configure({ adapter: new Adapter() });
describe("Test of <Greeting />", () => {
it(">>>> should show spinner on loading = true", () => {
const wrapper = mount(<Greeting />);
expect(wrapper.find("ForwardRef(CircularProgress)").exists()).toEqual(true);
});
it(">>>> should show greeting on loading = false", async () => {
const wrapper = mount(
<UserContextProvider>
<Greeting />
</UserContextProvider>
);
const promise = new Promise(resolve => {
setTimeout(() => {
resolve(wrapper);
}, 5000);
});
promise.then((res: Enzyme.ReactWrapper<any>) => {
console.log(res.debug());
expect(res.find("h1").text()).toEqual("Hello Bob Testman");
});
});
});
Link to codesandbox: https://codesandbox.io/embed/modern-sea-tx3ro?fontsize=14&hidenavigation=1&theme=dark
Any ideas on how to solve this?
Update Thanks to @Noix this works perfectly
it(">>>> should show greeting on loading = false", async () => {
const wrapper = mount(
<UserContextProvider>
<Greeting />
</UserContextProvider>
);
const promise = () => {
return new Promise(resolve => {
setTimeout(() => {
wrapper.update();
resolve(wrapper);
}, 3000);
});
};
return promise().then((res: Enzyme.ReactWrapper<any>) => {
console.log(res.debug());
expect(res.find("h1").text()).toEqual("Hello Bob Testman");
});
Upvotes: 0
Views: 3403
Reputation: 60
I believe you're having trouble because Jest ends the test before your promise is completed. Try adding the statement "return" before your "promise.then" so Jest will be able to wait for your promise to end before ending the test.
According to this :
https://jestjs.io/docs/en/asynchronous.html
Jest doesn't wait the callback return except if :
option 1 : you add done as argument to your function "it", so the test only resolve when you call the function done (in this case you need to use a try catch to be sure done is always called)
option 2 : you use a promise, it's the simpliest but never forget to return your promise :)
option 3 : you can use the statement "await" for your promise but THEN you have to use the keyword async on your "it" function
So in your case you can either put an await on your promise to wait for it to end, or just return your promise. I hope this helps.
Cheers :)
Upvotes: 1