Test exception - unstable_flushDiscreteUpdates

Viewed 2509

I have a test that uses Jest and react-testing-library with a .tsx test file (TypeScript):

import React from "react";
import { Provider } from 'react-redux';
import { render, screen } from "@testing-library/react";
import Home from "./Home";
describe('Home', () => {
    test("renders Programs without crashing", async () => {
        const storeFake = (state: any) => ({
            default: () => { },
            subscribe: () => { },
            dispatch: () => { },
            getState: () => ({ ...state })
        });
        const store = storeFake({}) as any;
        const { getByAltText } = render(<Provider store={store}>
                                            <Home />
                                        </Provider>);
        // render should show the title
        expect(getByAltText(/Great State/)).toBeInTheDocument();
    });

The test passes but an exception is thrown:

console.error node_modules/react-dom/cjs/react-dom.development.js:88
  Warning: unstable_flushDiscreteUpdates: Cannot flush updates when React is already rendering.
      in video (at Home.tsx:10)
      in div (at Home.tsx:9)
      in Home (created by ConnectFunction)
      in ConnectFunction (at Home.test.tsx:15)
      in Provider (at Home.test.tsx:14)

First, does anyone know how to resovle the exception. Second, I know this is a warning but it seems pretty serious, shouldn't the test fail?

2 Answers

As the error message describes it's a React warning and not related with React Testing Library. It's actually a React issue according to this thread https://github.com/facebook/react/issues/10389 . You may encounter this warning when you're using a <video /> element with muted property.

You can try the below code within the beforeAll block or before the test cases are executed.

   Object.defineProperty(HTMLMediaElement.prototype, "muted", {
       set: jest.fn(),
   });

It should work assuming that you're using <video /> tag inside your component like below.

<video src={videoPath} muted />

Property vs Attribute

This bug arises since React sets the muted property instead of correctly passing the attribute to the element: the first reflects the current value, while the latter reflects the initial state of the component. Setting muted as a prop is therefore incorrectly triggering an event.

Solution: you can also just set the 'muted' property in a useEffect hook.

function VideoComponent() {
    const videoRef = createRef<HTMLVideoElement>()
    const source = '/path/to.mp4'

    useEffect(() => {
        const { current: video } = videoRef
        video && (video.muted = true)
    }, [])

    return (
        <video 
            ref={videoRef} 
            src={source}
            autoPlay loop playsInline  
            />
    )

}
Related