milmal
milmal

Reputation: 551

Make jest/enzyme test wait for context

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

Answers (1)

Noix
Noix

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

Related Questions