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

Testing functional components using state hooks with Enzyme #71

Closed
dankreiger opened this issue Oct 27, 2018 · 20 comments
Closed

Testing functional components using state hooks with Enzyme #71

dankreiger opened this issue Oct 27, 2018 · 20 comments

Comments

@dankreiger
Copy link

describe('App', () => {
  test('renders one span element with the name as text', () => {
    const component = shallow(<App />); // Enzyme's shallow not working with React state hooks
    expect(component.find('span')).toBeTruthy();
    expect(component.find('span').text()).toBe('Dan');
  });
});

The error looks like this if I shallow render:

 FAIL  src/components/App/App.test.js
  App
    ✕ renders one span element with the name as text (16ms)

  ● App › renders one span element with the name as text

    Invariant Violation: Hooks can only be called inside the body of a function component.

       6 |
       7 | export default function App() {
    >  8 |   const [name, setName] = useState('Dan');
         |                           ^
       9 |   return (
      10 |     <span>{name}</span>
      11 |   );

      at invariant (node_modules/react/cjs/react.development.js:125:15)
      at resolveDispatcher (node_modules/react/cjs/react.development.js:1450:28)
      at useState (node_modules/react/cjs/react.development.js:1473:20)
      at App (src/components/App/App.js:8:27)
      at node_modules/enzyme-adapter-react-16/build/ReactSixteenAdapter.js:436:38
      at ReactShallowRenderer.render (node_modules/react-test-renderer/cjs/react-test-renderer-shallow.development.js:450:39)
      at node_modules/enzyme-adapter-react-16/build/ReactSixteenAdapter.js:440:37
      at withSetStateAllowed (node_modules/enzyme-adapter-utils/build/Utils.js:132:16)
      at Object.render (node_modules/enzyme-adapter-react-16/build/ReactSixteenAdapter.js:439:70)
      at new ShallowWrapper (node_modules/enzyme/build/ShallowWrapper.js:204:22)
      at shallow (node_modules/enzyme/build/shallow.js:21:10)
      at Object.test (src/components/App/App.test.js:7:23)

The component looks like this:

export default function App() {
  const [name, setName] = useState('Dan');
  return (
    <span>{name}</span>
  );
}

Is this an issue Enzyme will have to deal with or is there some other underlying issue?

The test passes with a mount render, but in a simple component test like this I would usually do a shallow render.

I know this might be outside of the scope of this thread, but at the same time I love using the Enzyme test utilities, and I thought I should bring this up.

Originally posted by @dankreiger in #68

@dankreiger dankreiger changed the title Issues using state hooks with Enzyme testing utilities Testing functional components using state hooks with Enzyme Oct 27, 2018
@ChibiBlasphem
Copy link

@dankreiger I had the same problem, and investigated a little;
The problem is that for using hook react need to have a "Dispatcher" which is not declared on shallow renderer (even for 'react-test-renderer/shallow' 16.7.0)

@milesj
Copy link

milesj commented Nov 5, 2018

Enzyme currently does not support hooks.

@koba04
Copy link
Member

koba04 commented Nov 7, 2018

In order to support Hooks in enzyme's shallow, we have to add Hooks support into ShallowRenderer(react-test-renderer/shallow).

@itaditya
Copy link

itaditya commented Dec 5, 2018

@milesj is this fixed now?

@milesj
Copy link

milesj commented Dec 5, 2018

@itaditya No. Just take a look at Enzyme itself. https://github.com/airbnb/enzyme/blob/master/CHANGELOG.md

@itaditya
Copy link

itaditya commented Dec 6, 2018

Wasn't able to find it in the changelog. Thanks for helping though. I tried to use enzyme yesterday, it said can't call hook outside component body.

@ChibiBlasphem
Copy link

ChibiBlasphem commented Dec 6, 2018

@itaditya that is normal. Nor React nor Enzyme did fix the bug yet. And that is not a bug, it's just not implemented yet :)

@danejordan
Copy link

danejordan commented Dec 18, 2018

For anyone here Kent Dodd's react-testing-library has got ya covered ( demo )

EDIT: As mentioned in the original issue mount works, just not shallow

@ChibiBlasphem
Copy link

@Dane456 nope it can't shallow render. Besides, kent created this lib because Hé don't really like the shallow approach. (render instead of shallow, and Enzyme can do it)

@danejordan
Copy link

@ChibiBlasphem yeah you're right, that was already mentioned in the original issue. Didn't see that. I wonder if there are any performance differences between enzyme's mount and react-testing-library's render

@danielcondemarin
Copy link

React now officially supports hooks as of today 🙂 https://reactjs.org/blog/2019/02/06/react-v16.8.0.html. Is there an eta when enzyme will support them? Thanks 🙏

@ChibiBlasphem
Copy link

ChibiBlasphem commented Feb 10, 2019

I hope it will. Enzyme is pretty known as a testing library for React but it misses support for some features (memo, lazy, hooks).

@Jessidhia
Copy link

Jessidhia commented Feb 10, 2019

Enzyme / shallow rendering wants information about things that not even React knows about unless the component is fully mounted. Perhaps it needs its own Babel plugin to add metadata to elements.

lugithub referenced this issue in lugithub/my-react-ts Feb 10, 2019
@geoffdavis92
Copy link

This is good to know. I've been sitting here trying to get useEffect to fire for like an hour. Guess I'll migrate to r-t-l until Enzyme catches up.

@milesj
Copy link

milesj commented Feb 18, 2019

@geoffdavis92 You don't need either lib. You can just use act() from react-dom.

@maciossek
Copy link

Workaround with react-test-renderer: enzymejs/enzyme#1938 (comment)

This is my final working test:

import React from 'react'
import { shallow } from 'enzyme'
import { OverlayComponent } from './../index'
import ShallowRenderer from 'react-test-renderer/shallow'

describe('<OverlayComponent />', () => {
  it("doesn't explode with a workaround", () => {
    const renderer = new ShallowRenderer()
    renderer.render(<OverlayComponent show closeFn={jest.fn()} t={key => key} />)
    const output = renderer.getRenderOutput()
    const wrapper = shallow(<div>{output}</div>) // Have to wrap it, otherwise you get: TypeError: ShallowWrapper can only wrap valid elements
    expect(wrapper).toMatchSnapshot()
  })
})

@vpicone
Copy link

vpicone commented Feb 27, 2019

@maciossek I haven't seen issues with rendering, it's mainly the hooks not doing anything at all. A simpler workaround might just be using mount and unmount instead of shallow.

@maciossek
Copy link

maciossek commented Feb 28, 2019

I might try it with the next test, but I got the same Invariant Violation: Hooks ... error: It didn't render at all.

@goncalobo
Copy link

I've managed to test a custom hook using @maciossek's workaround along with act().
https://gist.github.com/goncalobo/ace875af564d4fd585651abd86f65cd2

@gaearon
Copy link
Member

gaearon commented Mar 1, 2019

This thread is full of confusion because:

  • It references missing support for Hooks in shallow renderer which has been fixed in a stable release
  • There is however a bug that causes state to not update in shallow renderer which has not been fixed yet
  • There's a whole separate issue of which APIs are provided by enzyme

Ultimately this is a repository for proposing API changes and not for bug reports. This is why your messages don't receive a response, and why this thread is so confused with half-broken workarounds.

I will lock it to prevent further confusion. If something doesn't work in React please file an issue in the React repository instead. There we can discuss it and suggest the correct fix.

@gaearon gaearon pinned this issue Mar 1, 2019
@gaearon gaearon unpinned this issue Mar 1, 2019
@reactjs reactjs locked as off-topic and limited conversation to collaborators Mar 1, 2019
@gaearon gaearon closed this as completed Aug 24, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests