I assume I missed some bit from documentation, but so far my searches didn't achieve anything.
Let's say I have a very simple setup of component, which looks like this, and I want to test it:
import React, { Component } from 'react';
import Button from 'components/Button';
class MyComponent extends Component {
render() {
const { shouldRenderButton } = this.props;
return (<div>
<h1>My Amazing Title<h1>
{shouldRenderButton && this.renderButton()}
</div>);
}
renderButton() {
return (<Button
outlined={true}
amazing={'dinosaur'}
/>);
}
}
The common approach to test in react is to invoke the shallow render on the root of the component, and then start testing internals. In this particular case, this will work nice, but if your application grows, writing tests like this will become cumbersome and you will start splitting your components into additional subrenders.
The way how I want to test my component in this case, is I want to test both render and renderButton methods separately (stubbing where necessary), while still using enzyme. The reasons for doing this is a separate topic, but basically to achieve better tests, which are less fragile to other changes.
And here I'm stuck, because when invoking this code, I have no idea how to use enzyme anymore:
const wrapper = shallow(<MyComponent shouldRenderButton />;
const resultOfSubrender = wrapper.instance().renderButton();
// How to use enzyme API on the resultOfSubrender
Here's how assertion, which I want to write looks like:
describe('renderButton', () => {
it('should have an amazing prop of dinosaur', () => {
const wrapper = shallow(<MyComponent shouldRenderButton />);
const renderedButton = wrapper.instance.renderButton();
let buttonShallowWrapper;
// Here I do some magick with renderedButton to convert it into shallow wrapper
// Assuming I use chai-enzyme
// https://github.com/producthunt/chai-enzyme#propkey-val
expect(buttonShallowWrapper).to.have.prop('amazing', 'dinosaur');
})
})
My question is how can I convert the instance of rendered react component into a shallow wrapper, after it happened, and whether it's even possible to do this. So far I've been relying on react-dom/test-utils and just direct assertions agains the properties of the instance, but it would be nice to be able to use enzyme.
If I wrap the resultOfSubrender into shallow, the returned wrapper root is actually the result of the render method of Button component, which is tested separately, and useless for my assertions agains the props I pass inside this component. Of course I could wrap my button in additional <div> and then use selector based find to get my button, but this will make me modify my markup structure just to write test, which I would prefer to avoid.
Ok, so I looked into search code, and seems like this helper does the trick:
https://github.com/airbnb/enzyme/blob/master/src/ReactWrapper.jsx#L927
The result assertion will look like this:
describe('renderButton', () => {
it('should have an amazing prop of dinosaur', () => {
const wrapper = shallow(<MyComponent shouldRenderButton />);
const renderedButton = wrapper.instance.renderButton();
const buttonShallowWrapper = wrapper.wrap(renderedButton);
expect(buttonShallowWrapper).to.have.prop('amazing', 'dinosaur');
});
});
Feel free to close the issue, but this helper is clearly missing from the official documentation.
I would like to write a pull request to docs, but currently it's not very straightforward to understand how do you guys generate them :)
renderButton should be an SFC instead - renderFoo methods are an antipattern.
I introduced the simplest possible example, real code is obviously not that simple, includes conditions and other stuff, which I do not want to test in scope of single render method.
I don't see how any amount of complexity would make a renderFoo method any less bad of an approach.
MyComponent should render a MyButton; MyComponent's tests should assert on the prop values passed to MyButton; MyButton's tests should cover all the combinations of props it can take.
I don't really want to go into this argument tbh, I've explained enough reasoning behind the usecase I needed, and if you disagree, sure, I don't have anything against opinions.
The point was to discover the lack of wrap utility helper in the documentation, and help open-source software with providing PR to fix it. Hope we both agree, that this is a good thing.
this is an old post but just wanted to say that maybe having the helper documented is not a bad idea. it would be very useful when dealing with things like Portals on React 16
This doesn't seem to work anymore in enzyme 3.
After wrapping the instance with ReactWrapper (or calling the wrap utility helper) and calling .debug() on it, the children and display name of the component is lost.
@Blasz can you provide a test case?
Closing; please file a new issue if needed.
Most helpful comment
Ok, so I looked into search code, and seems like this helper does the trick:
https://github.com/airbnb/enzyme/blob/master/src/ReactWrapper.jsx#L927
The result assertion will look like this: