Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Testing functional components with renderIntoDocument

I am learning to test React stateless components using the ReactTestUtils library. This is my simple component:

import React from 'react';

const Greeter = ({name,place}) => (
  <h1>Hello,{name}. Welcome to the {place}.</h1>
);

export default Greeter;

This is my test spec, to get the renderIntoDocument working, I wrapped my Greeter component in a div as suggested here:

import {expect} from 'chai';
import React from 'react';
import ReactTestUtils from 'react-addons-test-utils';
import Greeter from '../Greeter';

describe('Greeter Components',() => {
  it('renders correctly',() => {
    var component = ReactTestUtils.renderIntoDocument(<div>
        <Greeter name="Vamsi" place="Hotel California"/>
    </div>);

    var hasH1 = ReactTestUtils.findRenderedDOMComponentWithTag(component,'h1');
expect(hasH1).to.be.ok;
  });
});

I get the error

findAllInRenderedTree(...): instance must be a composite component.

I am providing my code as jsbin here.

like image 302
vamsiampolu Avatar asked Apr 17 '16 21:04

vamsiampolu


People also ask

Can a functional component have a render method?

Functional Component There is no render method used in functional components. With functional components there are fewer lines of code another positive to this is that the fewer lines of code a developer has to read and write, the faster and easier their code is to comprehend.

Which is better enzyme or react testing library?

Enzyme allows you to access the internal workings of your components. You can read and set the state, and you can mock children to make tests run faster. On the other hand, react-testing-library doesn't give you any access to the implementation details.

How can you simulate clicking on an element using react testing utilities?

Simulate a Click Event The onClick should pass through to the component's underlying <button /> element because we're spreading ( {... props} ) that props through to it. In the test, we create a ref so that we can pass it to the rendered Button and later to the Simulate. click call.


1 Answers

Since function components don't have an instance associated with them, you can't use them directly with render or renderIntoDocument. Attempting to wrap the function component is a good idea, unfortunately using a div doesn't work for a similar reason. DOM components also don't return a component instance, instead they return the underlying DOM node.

Which is all to say that you can't use the test utils function or native components as the "root" component you are rendering. Instead you will want to wrap your function components in a wrapper component that uses createClass or extends React.Component.

class Wrapper extends React.Component {
  render() { 
    return this.props.children
  }
}

let component = renderIntoDocument(<Wrapper><Greeter /></wrapper>

Gotcha's like this may be reason enough to make use of a third-party testing library like the popular enzyme, or my own take: teaspoon. Both abstract over issues like this by seamlessly wrapping and unwrapping function components for you, so you don't need to worry about what type of component you are trying to render.

like image 139
monastic-panic Avatar answered Oct 11 '22 01:10

monastic-panic