Enzyme: Enzyme 3 - Find Where does not work.

Created on 5 Oct 2017  Β·  20Comments  Β·  Source: enzymejs/enzyme

Hi, after update to v3, findWhere stopped working.

Following line throws ​​Method β€œprops” is only meant to be run on a single node. 0 found instead.​​

wrapper.findWhere(w => w.prop('content') === 'Register').simulate('click')

This is the wrapper.debug() - shortened

​​​​​<Segment inverted={true}>​​​​​
...
  <Button type="button" onClick={[Function]} color="green" labelPosition="left" content="Register" icon="sign in" as="button">​​​​​
      ​​​​​ <button type="button" className="ui green icon left labeled button" disabled={[undefined]} onClick={[Function]} role="button" tabIndex={[undefined]}>​​​​​
      ​​​​​     <Icon name="sign in" as="i">​​​​​
      ​​​​​          <i aria-hidden="true" className="sign in icon" />​​​​​
      ​​​​​     </Icon>​​​​​
      ​​​​​     Register​​​​​
      ​​​​​  </button>​​​​​
   </Button>​​​​​
 ...
​​​</Segment>​​​​​
mount Need To Reproduce package 16

Most helpful comment

Thanks for looking into it. Based on a suggestion above, I have gotten it working using

let convertSponsored = wrapper
        .find('Confirm')
        .filterWhere(n => n.contains('Convert to Sponsored'));

The code that creates the wrapper is here:

let wrapper = mount(
      <CustomerDetails params={{orgId: mockOrganization.slug}} />,
      TestStubs.routerContext([{user: mockUser}])
    );

The component I was trying to find is here: https://github.com/getsentry/sentry/blob/master/src/sentry/static/sentry/app/components/confirm.jsx

So, it seems to be working fine using a two step .find then .filterWhere rather than a straight .findWhere using a two-part boolean expression (n.type === 'Confirm' && n.contains('....')).

All 20 comments

What version of React? Shallow, or mount?

Getting the same thing, I'm using mount:

[email protected]
[email protected]

Jest setup file:

import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';

Enzyme.configure({ adapter: new Adapter() });

I believe this bug is the same bug we are discussing here:

https://github.com/airbnb/enzyme/issues/1201

@ljharb React 16, mount. Sorry for the lack of detail. Enzyme 3.0.1

I have the same issue with error, may findWhere does not work?

Error:
        Attempted to access ShallowWrapper::node, which was previously a private property on
        Enzyme ShallowWrapper instances, but is no longer and should not be relied upon.
        Consider using the getElement() method instead.
 Object.values(alarmTypes).forEach(type =>
        it(`should render correct icon for '${type}' alarm type `, () => {
            alarmConfigurationItem = shallow(
                <AlarmConfigurationItem
                    changeConfiguration={sinon.spy()}
                    changeBehavior={sinon.spy()}
                    intl={{formatMessage}}
                    configuration={{...configuration, alarmType: type}}
                />)

            alarmConfigurationItem.findWhere(t => t.node.type && t.node.type.displayName && t.node.type.displayName === alarmsConfiguration[type].icon.type.displayName).should.exist
        }))

I tried with, but not quite sure if it ok to check the React Element Type. Do we have another way to check the react element type with enzyme 3.x?
alarmConfigurationItem.findWhere(t => t.containsMatchingElement(alarmsConfiguration[type].icon)).should.exist

I ran into a similar problem with findWhere. I'd be happy to open a separate issue if necessary.

[email protected]
[email protected]
mount()

When iterating over a list of ReactWrappers, after the first valid ReactWrapper, the second element being passed to the predicate is the text of the previous ReactWrapper item in the list. This results in an invariant being thrown because it's not valid DOM.

Switching to filterWhere seems to be the workaround.

@wbeard could you open up a PR with a failing test for that?

@ljharb Yeah, I'll try to get one open for you soon. If you think it's cool, I'd like to dig in a bit and see if I can't provide a fix. Do you think this could be a good first PR?

Absolutely! Any level of contribution is welcome, even when PRs aren't accepted - although in this case it surely would be :-)

Happy to reopen this issue if needed.

@ljharb It appears I'm a day late to the party, but I'm getting the same error: Method β€œtype” is only meant to be run on a single node. 0 found instead. when trying to run

wrapper.findWhere(n => n.type() === 'MyComponent').

I'm running enzyme 3.3.0, enzyme-adapter-react-16: 1.1.1, react 16.3.2.

Has there been a fix for this?

@lobsterkatie thanks - could you provide your entire component code, and the code that creates wrapper? That should be sufficient for me to fix it.

Thanks for looking into it. Based on a suggestion above, I have gotten it working using

let convertSponsored = wrapper
        .find('Confirm')
        .filterWhere(n => n.contains('Convert to Sponsored'));

The code that creates the wrapper is here:

let wrapper = mount(
      <CustomerDetails params={{orgId: mockOrganization.slug}} />,
      TestStubs.routerContext([{user: mockUser}])
    );

The component I was trying to find is here: https://github.com/getsentry/sentry/blob/master/src/sentry/static/sentry/app/components/confirm.jsx

So, it seems to be working fine using a two step .find then .filterWhere rather than a straight .findWhere using a two-part boolean expression (n.type === 'Confirm' && n.contains('....')).

Hmm - so, I think that's probably because the find is filtering down such that the remaining results are guaranteed to be objects - if you try .findWhere(n => n && n.type === 'Confirm' && n.contains('Convert to Sponsored')), does it work?

Unfortunately, no. Nor does

wrapper.findWhere(n => n.key() === 'convert-to-sponsored').simulate('click');

(I get Method β€œkey” is only meant to be run on a single node. 0 found instead.) nor

wrapper.findWhere(n => n && n.key() === 'convert-to-sponsored').simulate('click');

(I get Method β€œsimulate” is only meant to be run on a single node. 0 found instead.)

It seems almost like findWhere isn't passing nodes to the predicate function correctly. (Knowing nothing about the implementation - just judging from the fact that .key() can't be run on any of the nodes.)

In the first place, that suggests that n is sometimes an empty node, so you'd want to filter like !n.isEmpty() && n.key() etc; for the second one, i'm surprised that you wouldn't get the same error.

If you console.log n inside the findWhere, do you see the node you're trying to locate?

Okay, I console.logged and the element was in fact there. I then tried !n.isEmpty() && n.key(), which I then changed to n.exists() && n.key() (since I got a bunch of warnings about isEmpty()), and now it's working. Yay! Thank you!

The part I don't understand is... how is n ever non-existent? If it doesn't exist, why/how is it even in the list to get checked?

@lobsterkatie I believe {null} can render something like that?

This seems answered. Happy to reopen if needed, and feel free to file a new issue if applicable.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

potapovDim picture potapovDim  Β·  3Comments

timhonders picture timhonders  Β·  3Comments

AdamYahid picture AdamYahid  Β·  3Comments

SandroMachado picture SandroMachado  Β·  3Comments

ivanbtrujillo picture ivanbtrujillo  Β·  3Comments