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>βββββ
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:
@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.
Most helpful comment
Thanks for looking into it. Based on a suggestion above, I have gotten it working using
The code that creates the wrapper is here:
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
.findthen.filterWhererather than a straight.findWhereusing a two-part boolean expression (n.type === 'Confirm' && n.contains('....')).