2

According to the enzyme documentation for find() for shallow rendering and full rendering (mount), one should be able to look up components using the value of props. This does not seem to work the same way for full and shallow rendering thought I the documentation doesn't seem to explain that there would be any difference expected.

Example component under test

import React, { Component } from 'react';

class Foo extends Component {
  render() {
    return (
      <div>
        <h1>Foo</h1>
        {this.props.children}
      </div>
    );
  }
}

class Bar extends Component {
  render() {
    return (<h1>Bar</h1>);
  }
}

class FindTest extends Component {
  render() {
    return (
      <div>
        <span spanProp="spanValue">Enzyme Find Test</span>
        <Foo fooProp="fooValue">
          <Bar barProp="barValue" />
        </Foo>
      </div>
    );
  }
}

export default FindTest;
export { Foo, Bar };

Example Test File

import React from 'react';
import { shallow, mount } from 'enzyme';
import { expect } from 'chai';

import FindTest, { Foo, Bar } from 'components/FindTest/FindTest.js';

describe('<FindTest />', () => {
  it('can find using props with shallow rendering', () => {
    const wrapper = shallow(<FindTest />);
    // Passes
    expect(wrapper.find({ spanProp: 'spanValue' })).to.have.length(1);
    // Passes
    expect(wrapper.find({ fooProp: 'fooValue' })).to.have.length(1);
    // Passes
    expect(wrapper.find({ barProp: 'barValue' })).to.have.length(1);
    // Passes
    expect(wrapper.find(Foo).find({ barProp: 'barValue' })).to.have.length(1);
  });

  it('can find using props with mount rendering', () => {
    const wrapper = mount(<FindTest />);
    //Passes
    expect(wrapper.find({ spanProp: 'spanValue' })).to.have.length(1);
    // Fails
    expect(wrapper.find({ fooProp: 'fooValue' })).to.have.length(1);
    // Fails
    expect(wrapper.find({ barProp: 'barValue' })).to.have.length(1);
    // Fails
    expect(wrapper.find(Foo).find({ barProp: 'barValue' })).to.have.length(1);
  });
});
zwalker
  • 346
  • 5
  • 9
  • 1
    Try doing a console log of the mounted wrapper to see if you have some idea why that is the case. Do `console.log(wrapper.debug());` inside the test for mount. – nbkhope Feb 23 '17 at 21:49
  • Looks like all of the expected props and values are there. This is the output of wrapper.debug() in the mount test case. `
    Enzyme Find Test

    Foo

    Bar

    `
    – zwalker Feb 23 '17 at 22:48
  • I tried looking into your example, but don't understand why it is failing. I'm not very familiar with the find by Props, so maybe you should post this in the Enzyme GitHub page? Maybe it could be a bug? Anyway, if you really need to test something for props, I would just find the component first, then check for the prop, like this: `expect(wrapper.find('Foo').prop('fooProp')).to.equal('fooValue')` – nbkhope Feb 23 '17 at 23:27
  • @nbkhope I agree that I could do what you have suggested in this example. However, if there is more that one Foo element, I would like to be able to select the one I want using `find({ prop: 'value'})` form which does not seem to work for mounted rendering. – zwalker Feb 24 '17 at 02:14

2 Answers2

1

in mount mode the test failed,because enzyme using react-addons-test-utils to render component into an visual dom in constructor,and react can't using dynamic properties in an element and the dynamic property will be striped.if you need you must using dynamic proeprty starts with data-,e.g:data-property-value.see:https://facebook.github.io/react/warnings/unknown-prop.html & https://github.com/holi-java/getstarted-react/blob/master/test/13.react-unknown-prop.test.js

renderWithOptions = (node, options) => {
   if (options.attachTo) {
      return React.render(node, options.attachTo);
    }
    return TestUtils.renderIntoDocument(node);
};
holi-java
  • 29,655
  • 7
  • 72
  • 83
  • The 'data-' prefix doesn't seem to change the behavior. I tried modifying the test code from the original post by changing 'fooProp' to 'data-fooProp' in both the component and the test with the same result. – zwalker Feb 23 '17 at 22:44
  • you change the element property name,thus you must modify find({prop:value}). copy this test and see you will know why? ` test('find element matching prop starts with data-* should be using the origin property name that defined in element', function () { let users = shallow(
    Jhon
    Mary
    ); expect(users.find({"data-userName": "jhon"}).text()).toEqual("Jhon"); }); `
    – holi-java Feb 24 '17 at 00:50
  • The "data-" prefix in your example has no impact on the outcome of the test. It pases with it or without it. This is the same as the `wrapper.find({ spanProp: 'spanValue' })` example in my original question which I agree works. It is the other examples that do not work. – zwalker Feb 24 '17 at 02:11
  • 1
    yes,you are right.the test was failed is not by unknown props.and I see depth in enzyme in mount mode find() will find element only by props,and in shallow it can find component & element both.you can see enzyme MountedTraversal.js if inst is a ReactComponent it return false directly `function instMatchesObjectProps(inst, props) { if (!(0, _reactCompat.isDOMComponent)(inst)) return false; var node = getNode(inst); return (0, _isSubset2['default'])((0, _Utils.propsOfNode)(node), props); }` – holi-java Feb 24 '17 at 11:38
0

As of Feb '17 it seems to be a bug.

As @holi-java mentioned in his comments above. The instMatchesObjectProps method for mounted traversal just doesn't return nodes if the node is a react component.

This existing bug was found on the Enzyme project https://github.com/airbnb/enzyme/issues/376 and this PR are out to fix the issues https://github.com/airbnb/enzyme/pull/377

zwalker
  • 346
  • 5
  • 9