enzyme: Mount find() Does Not Find Rendered Marker

This one is pretty frustrating. I mount this container. It does hit the code I expect that contains my css feature marker (ft-playback-error). But in the end I end up with not found.

screencast of this issue: https://youtu.be/kh-UJTig3Qg

   it.only('renders a coordinates message in the player when no coordinates exist', () => {
      const store = createStore(reducers, {}),

        liveScreen = mount(
          <Provider store={createStore(reducers, {})}>
            <Live
              breakpoint="site-web"
              coordinates={null}
              renderInfoInDetail={() => {}}
              setOverlay={() => {}}
              store={store}
              AccessEnablerUrl=""
              getUseUtagGlobal={() => {}}
              pageViewEvent={() => {}}
            />
          </Provider>),
        message = liveScreen.find('.ft-playback-error');

      expect(message).to.have.length(1);
    });

message.nodes ends up being 0 (or aka not found). Why? screen shot 2017-10-05 at 10 54 05 am

I assumed when you mounted, it runs every child’s render() (every child that’s being hit down the codepath of container…obviously depending on whatever logic is in its render will determine which children are being rendered) method of this container.

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Comments: 58 (14 by maintainers)

Commits related to this issue

Most upvoted comments

@StefanoSega I had a similar problem. I have a component written in pure JS that inserts html inside React component. After component mount, I’m using render method before find and it works as expected. Example:

const wrapper = mount(<Provider store={store}><Units /></Provider>);
const nodes = wrapper.render().find('.unit'));

@dmccown1500 I also had a similar issue, seems like redux and enzyme not working properly. .html() was giving proper markup but .find('selector') wasn’t working (enzyme v3.1.0)

wrapper.update() after modifying the redux state fixed wrapper.find('.deep-nested-component') returning an empty set 👍

I’m having this issue. Enzyme 3.3.0 with MobX. HTML is correct but find() doesn’t work. The update() trick didn’t help

WORK AROUND FOUND: So at least for us this was an issue where Redux (or maybe Redux-Saga/Thunk?) and Enzyme are not playing well together. Enzyme does not auto-update the wrapper when some of the external updates are happening. They talk about in the migration guide but I guess I just missed it? In any case you can call .update() on the root component.

Using .render().find() did the trick for me, as in @d-e-p’s example. Thanks @d-e-p

Can confirm with versions:

+-- enzyme@3.3.0
+-- enzyme-adapter-react-16@1.1.1

when the component being tested must be wrapped by a redux Provider:

wrapper = mount(
  React.createElement(Provider, {store},
    React.createElement(MyComponent, props)
  )
);

then wrapper.html() always shows the child nodes, but wrapper.find(...) will not find them UNLESS wrapper.update() is called first

Using .render().find() doesn’t allow me to simulate a click for a button. This is still happening.

meet with the same problem. html() is right but find couldn’t find the dom. update() doesn’t help.

@sadu thanks for the tip. Had similar issue - wrapper.html() returned correct tree but when I was doing wrapper.find(...) it seemed like it was searching in the tree of the previous state. wrapper.update() helped

@aweary I’m using "enzyme": "^3.1.0" and adapter is "enzyme-adapter-react-16": "^1.0.1" and I have the same problem

I’ve just tried upgrading a small project to Enzyme 3 and think I’m running into the same (or similar-looking) issue – using React 15.6.1 with enzyme-adapter-react-15 1.0.2 and enzyme 3.1.0.

It appears that Enzyme isn’t updating it’s internal understanding of the state of the vdom, even though the actual host nodes are updated as expected.

In this test, I’m using react-apollo and a mocked API render a component which goes from a loading state to a loaded state after a 0ms sleep. In enzyme 2, everything works. In enzyme 3, I get inconsistent results between page.html() and page.debug(). (And my test fails in the same way that debug is wrong.)

Enzyme thinks the page is still in a loading state, even though the html() call returns the loaded state. (I also instrumented the test and see render being called with the ‘loaded’ props).

  it("Shows the snacks in a list", async () => {
    const Provider = mockProvider({
      mocks: {
        Query: () => ({
          allSnacks: () => {
            console.log("In allSnacks");
            return [
              { id: 1, name: "Foo", voteCount: 1 },
              { id: 2, name: "Bar", voteCount: 2 }
            ];
          }
        })
      }
    });

    const page = mount(
      <Provider>
        <HomePage />
      </Provider>
    );

    await sleep(0);

    console.log(page.html());
    console.log(page.debug());

Output

Expecting to see"Foo" and “Bar” listed in both the html and debug output, but only seeing them in the html. debug still returns the loading state.

html output

 console.log modules/client/pages/home/__tests__/home-page.test.tsx:101
    <div class="home-page"><h2>Snacks</h2><ul><li><!-- react-text: 18 -->Foo<!-- /react-text --><!-- react-text: 19 -->&nbsp; (popularity: <!-- /react-text --><!-- react-text: 20 -->50%<!-- /react-text --><!-- react-text: 21 -->)&nbsp;<!-- /react-text --><a>Vote</a></li><li><!-- react-text: 24 -->Bar<!-- /react-text --><!-- react-text: 25 -->&nbsp; (popularity: <!-- /react-text --><!-- react-text: 26 -->100%<!-- /react-text --><!-- react-text: 27 -->)&nbsp;<!-- /react-text --><a>Vote</a></li></ul><div class="home-page-pop-mode-toggle"><h4>Show popularity as:</h4><div><label for="home-page-percentage"><input type="radio" id="home-page-percentage"><!-- react-text: 10 --> <!-- /react-text --><!-- react-text: 11 -->Percentage<!-- /react-text --></label></div><div><label for="home-page-vote-count"><input type="radio" id="home-page-vote-count"><!-- react-text: 15 --> <!-- /react-text --><!-- react-text: 16 -->Vote Count<!-- /react-text --></label></div></div></div>

debug output:

  console.log modules/client/pages/home/__tests__/home-page.test.tsx:102
    <MockProvider>
      <MemoryRouter>
        <Router history={{...}}>
          <ApolloProvider client={{...}} store={{...}}>
            <QueryRecyclerProvider>
              <withApollo(Connect(Apollo(Component)))>
                <Connect(Apollo(Component)) client={{...}}>
                  <Apollo(Component) client={{...}} popularityMode="PERCENTAGE" onVote={[Function]} onPopularityModeChange={[Function]}>
                    <Component client={{...}} popularityMode="PERCENTAGE" onVote={[Function]} onPopularityModeChange={[Function]} snacks={{...}}>
                      <div className="home-page">
                        <h2>
                          Snacks
                        </h2>
                        <Component snacks={{...}} onVote={[Function]} popularityMode="PERCENTAGE">
                          <ul>
                            <li>
                              Loading
                            </li>
                          </ul>
                        </Component>
                        <Component selected="PERCENTAGE" onChange={[Function]}>
                          <div className="home-page-pop-mode-toggle">
                            <h4>
                              Show popularity as:
                            </h4>
                            <div>
                              <label htmlFor="home-page-percentage">
                                <input id="home-page-percentage" type="radio" checked={true} onChange={[Function]} />

                                Percentage
                              </label>
                            </div>
                            <div>
                              <label htmlFor="home-page-vote-count">
                                <input id="home-page-vote-count" type="radio" checked={false} onChange={[Function]} />

                                Vote Count
                              </label>
                            </div>
                          </div>
                        </Component>
                      </div>
                    </Component>
                  </Apollo(Component)>
                </Connect(Apollo(Component))>
              </withApollo(Connect(Apollo(Component)))>
            </QueryRecyclerProvider>
          </ApolloProvider>
        </Router>
      </MemoryRouter>
    </MockProvider>

I just encountered this issue with redux and enzyme 3.3.0, the .update() workaround does work.

after upgrading to enzyme 3 this problem went way. It’s either that or my component wasn’t rendering what I thought it was and the marker wasn’t there. Closing this.

if noone if seeing the same results from wrapper.debug() and wrapper.html() after calling update, use wrapper = wrapper.update(). In enzyme 3, the wrapper is immutable.

@kaiyoma find finding more than it used to is an expected change; use .hostNodes() if you want to filter it down to DOM elements.

If you stick with React 15, and upgrade to v3, and follow the migration guide, you should be fine.

I did this today and I’m also running into the issues mentioned in this thread. Tests that were previously passing are now failing. The tests in question fail because they either:

  • search for an element by classname a couple layers deep in the DOM
  • search for a classname that is not listed first in the classname list for an element

Usually the test fails because find fails to find anything, but sometimes find finds more than it should! Something is not working right here.

@EvgenyW3 see #1213; fragments aren’t currently supported.

For me the problem with .find() was because of wrapping a component with <React.Fragment>. Changed it back to <div> and that did the trick. Seems like Enzyme 3.3.0 doesn’t like React.Fragment

@dmccown1500 The update works great!

Confirmed again:

"enzyme": "^3.3.0",
"enzyme-adapter-react-16": "^1.1.1",

I’m not using Redux. wrapper.html() was correct but wrapper.find() couldn’t find anything. Added a wrapper.update() before the find and it worked.

Just tried with Enzyme 3. This is no longer an issue. Thank you!

@3axap4eHko which, shallow? The entire point of shallow rendering is to never traverse subcomponents.

@ljharb .feature__cover is parsed correctly, so I don’t think so, but it could be related to the traversal logic. @dschinkel @3axap4eHko if you use findWhere does it work?

element.findWhere(node => node.hasClass('.feature__cover'))

If it doesn’t, can you verify if findWhere traverses the node you’re targeting? A reduced example that we could reproduce the issue with would be useful, it’s hard to say whats going on with a 800+ line example that imports from other unknown files.

the same for me:

console.log(element.html());
expect(element.find('.feature__media').length).toEqual(1);

I’m getting

expect(received).toEqual(expected)

    Expected value to equal:
      1
    Received:
      0

<div class="feature"><div class="feature__cover"><div class="feature__media">Episode</div></div><div class="feature__details"><h3 class="feature__type">episode</h3><div class="feature__title"></div></div></div>

but .feature__cover found well