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.
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With