Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mounted wrapper was not wrapped in act(...) warning still showing #2153

Closed
2 of 13 tasks
nryoung opened this issue Jun 4, 2019 · 4 comments
Closed
2 of 13 tasks

Mounted wrapper was not wrapped in act(...) warning still showing #2153

nryoung opened this issue Jun 4, 2019 · 4 comments

Comments

@nryoung
Copy link

nryoung commented Jun 4, 2019

Current behavior

I have a component that makes use of the useEffect hook to make an asynchronous call an api (or in the test case a mock of a call to an api) and then call the setState hook with the result.

I've written tests that assert on the outcome of the effect (ie content being returned from the api). I'm using v1.14.0 of the adapter for react-16 my tests pass, snapshots are created and everything appears to be working well, however, a warning is repeatedly logged out from react-dom.

Here's the test in question:

import { mount } from 'enzyme';

import { flushPromises, renderHook, HOOK_WRAPPER_ID } from 'utils/tests';
import useData from './use-data';

const mockURL = 'https://example.com';
const mockConfig = {
  data: ':dataHere',
};

describe('useData', () => {
  it('fetches data config', async () => {
    fetch.mockResponseOnce(JSON.stringify(mockConfig));
    const wrapper = mount(renderHook(() => useData(mockURL)));

    await flushPromises();
    wrapper.update();

    const dataConfig = wrapper.find(`#${HOOK_WRAPPER_ID}`).props().hook;
    expect(dataConfig).toEqual(mockConfig);
  });
});

Here's the warning:

 PASS  src/hooks/use-data.test.js
  ● Console

    console.error node_modules/react-dom/cjs/react-dom.development.js:506
      Warning: An update to TestHookWrapper inside a test was not wrapped in act(...).

      When testing, code that causes React state updates should be wrapped into act(...):

      act(() => {
        /* fire events that update state */
      });
      /* assert on the output */

      This ensures that you're testing the behavior the user would see in the browser. Learn more at https://fb.me/react-wrap-tests-with-act
          in TestHookWrapper (created by WrapperComponent)
          in WrapperComponent

#2073 claims to have fixed this, but even after upgrading both enzyme and enzyme-adapter-react-16 I still encounter this warning.

Expected behavior

For no warning to be issued.

API

  • shallow
  • mount
  • render

Version

library version
enzyme v3.10.0
react v16.8.6
react-dom v16.8.6
react-test-renderer n/a
adapter (below) v1.14.0

Adapter

  • enzyme-adapter-react-16
  • enzyme-adapter-react-16.3
  • enzyme-adapter-react-16.2
  • enzyme-adapter-react-16.1
  • enzyme-adapter-react-15
  • enzyme-adapter-react-15.4
  • enzyme-adapter-react-14
  • enzyme-adapter-react-13
  • enzyme-adapter-react-helper
  • others ( )
@ljharb
Copy link
Member

ljharb commented Jun 5, 2019

enzyme now wraps the things it knows about in act, but if your test is updating it (like in flushPromises) you have to manually wrap that in act.

@nryoung
Copy link
Author

nryoung commented Jun 5, 2019

I am testing a custom hook above that uses useEffect and my custom hook is async... how do you wrap that in act? I can't simply await on act because it doesn't return anything...
I am trying this:

    await act(async () => {
      await flushPromises();
    });

but I get this error:

  console.error node_modules/react-dom/cjs/react-dom-test-utils.development.js:100
    Warning: The callback passed to ReactTestUtils.act(...) function must not return anything.

    It looks like you wrote ReactTestUtils.act(async () => ...), or returned a Promise from the callback passed to it. Putting asynchronous logic inside ReactTestUtils.act(...) is not supported.


  console.error node_modules/react-dom/cjs/react-dom-test-utils.development.js:100
    Warning: Do not await the result of calling ReactTestUtils.act(...), it is not a Promise.

  console.error node_modules/react-dom/cjs/react-dom.development.js:506
    Warning: An update to TestHookWrapper inside a test was not wrapped in act(...).

    When testing, code that causes React state updates should be wrapped into act(...):

    act(() => {
      /* fire events that update state */
    });
    /* assert on the output */

    This ensures that you're testing the behavior the user would see in the browser. Learn more at https://fb.me/react-wrap-tests-with-act
        in TestHookWrapper (created by WrapperComponent)
        in WrapperComponent

@ljharb
Copy link
Member

ljharb commented Jun 5, 2019

indeed, act is synchronous.

Can you share the code of renderHook?

@nryoung
Copy link
Author

nryoung commented Jun 5, 2019

This issue is actually due to async/await support not being present in the act testing util provided by react-dom/test-utils. You can see more about the issue here: facebook/react#14769

The solution that worked for me was upgrading both react and react-dom to v16.9.0-alpha.0. Then I modified my test above to look like:

import { mount } from 'enzyme';
import { act } from 'react-dom/test-utils';


import { flushPromises, renderHook, HOOK_WRAPPER_ID } from 'utils/tests';
import useData from './use-data';

const mockURL = 'https://example.com';
const mockConfig = {
  data: ':dataHere',
};

describe('useData', () => {
  it('fetches data config', async () => {
    fetch.mockResponseOnce(JSON.stringify(mockConfig));
    const wrapper = mount(renderHook(() => useData(mockURL)));

    // now act supports async/await syntax
    await act(async () => {
      await flushPromises();
    });

    wrapper.update();

    const dataConfig = wrapper.find(`#${HOOK_WRAPPER_ID}`).props().hook;
    expect(dataConfig).toEqual(mockConfig);
  });
});

@ljharb Thanks for your help and patience troubleshooting this 😃

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants