useEffect usually use Promises for update state.
This updates cause long warning in jest: Warning: An update to null inside a test was not wrapped in act(...).
How correctly write Jest Test for such case?
live example, Reproducible Example:
https://codesandbox.io/s/jest-test-for-useeffect-with-promises-spieq?file=/index.test.js
index.test.js
import React from "react";
import Hello from "./Hello";
import { create, act } from "react-test-renderer";
it("works", () => {
let root;
act(() => {
root = create(<Hello />);
});
// console.log("From test:", );
let repr = JSON.stringify(root.toJSON());
expect(repr).toBe('{"type":"span","props":{},"children":["Hello! "]}');
});
Hello.js
import React, { useState, useEffect } from "react";
export default () => {
const [count, setCount] = useState();
useEffect(() => {
Promise.resolve({}).then(() => setCount(4));
}, []);
return <span>Hello! {count}</span>;
};
Upd 1:
the same result for one of propasal:
I would like to suggest you to use testing-library/react which could be use smoothly with jest and provide async methods
Your test would become something like:
import React from "react";
import Hello from "./Hello";
import { render } from '@testing-library/react';
it("works", () => {
const { baseElement } = render(<Hello />);
expect(baseElement).toBeTruthy();
});
EDIT: For sake of completeness, in your example you're trying to test whether or not an update in your component happened after an effect which is using a promise.
In order to waitFor something async you can use the method findBy (findBy methods are a combination of getBy queries and waitFor.)
import React from "react";
import Hello from "./Hello";
import { render, findByText } from "@testing-library/react";
import "@testing-library/jest-dom";
it("works", async () => {
const { baseElement } = render(<Hello />);
expect(await findByText(baseElement, "Hello! 4")).toBeVisible();
});
Let's me explain, import "@testing-library/jest-dom"
allows you to use the the method toBeVisible
So, this test is rendering a component Hello and then it's waiting (with default value, 1000ms) inside the baseElement (which is the component itself) looking for the text "Hello! 4", then if found it will return the found element, which we are going to test whether is it visibile or not.