Closed dclowd9901 closed 8 years ago
That is what shallow rendering does:
https://facebook.github.io/react/docs/test-utils.html#shallow-rendering
Shallow rendering is an experimental feature that lets you render a component "one level deep" and assert facts about what its render method returns, without worrying about the behavior of child components, which are not instantiated or rendered. This does not require a DOM
If you want to assert on the fully rendered DOM, you can use mount
.
Sorry, I think I didn't make myself clear:
class Component extends React.Component {
inline() {
return (<div id="i-am-inline"></div>);
}
render() {
return (<div id="i-am-the-parent">{this.inline()}</div>);
}
}
var wrapper = Enzyme.shallow(<Component />);
console.log(wrapper.html());
// outputs
// <div id="i-am-the-parent"><div id="i-am-inline"></div></div>
console.log(wrapper.find('#i-am-inline').length);
// outputs 0
If I perform wrapper.find('#i-am-inline')
it won't be found, despite the fact that it is apparently being rendered according to .html()
.
@dclowd9901 I'll reopen this for now until I can reproduce and clarify what the expected behavior here should be.
Thanks; it may just be my misunderstanding of shallow render. My understanding was always that it will render an entire component (depth notwithstanding), just not other components that might inhabit it.
the find method seems to be working only against the nodes that are compiled via shallow, or mount, and in the case of shallow only the root node will be found. The html() method will render the full html but the find method is not finding against the html output. Ran into this issue earlier today and just using mount fixed the problem.
That's intentional - html()
just does a full render
, but .find
operates on the shallow tree.
@ljharb yeah i agree with you. I think this issue can be closed.
Then I will close this out again 😄
@dclowd9901 your example was bugging me (as in everything looked right) so I threw this in enzyme's test suite and both assertions pass. Just a heads up.
it.only('test', () => {
class Component extends React.Component {
inline() {
return (<div id="i-am-inline"></div>);
}
render() {
return (<div id="i-am-the-parent">{this.inline()}</div>);
}
}
var wrapper = shallow(<Component />);
expect(wrapper.find('#i-am-inline').length).to.equal(1);
var count = 0;
wrapper.findWhere(w => count++);
expect(count).to.equal(2);
});
@dclowd9901 I know this is pretty old, but I just ran across this symptom, and I thought I would share my experience.
I hit this point in my testing where I would shallow render a component, but I couldn't find()
any child within the node. It would always return an empty result set. Well, I had failed to notice that I was actually wrapping the component in a higher order component just before exporting. In my case it was a react-intl
wrapper.
So in this instance, I was shallow rendering the react-intl
component and stopping short of rendering the component I was actually trying to test. Obviously this isn't a problem with Enzyme. It's more of a gotcha to be aware of. Hope this is helpful to someone.
@conlanpatrek for that use case, try .dive()
@ljharb Oooh, I've never noticed .dive()
before. Thanks for that.
@ljharb awesome .... thanks for that
@ljharb .. If I have this structure . How should I use dive() to get the value of the input field in wrapper3.jsx when I shallow render one.jsx? What's the right way to do this ?
I tried : comp.find('Wrapper2').dive('.abc') comp.find('Wrapper2').find('Wrapper3').dive('.abc') .. but the wrapper3 lenght is always 0.
``
**one.jsx**
<Wrapper1>
<Wrapper2 />
</Wrapper1>
**two.jsx**
<Wrapper3/>
**wrapper3.jsx**
<input class='abc'/>
dive does not take a selector - it only works when there is a single custom component. You want shallow(<Wrapper1 />).dive().dive().find('input')
.
hi @ljharb thanks for replying. The above doesn't work. shallow(
It always says dive() can only be called on components.
@smoholkar if it doesn't render another Component, then it's not just a wrapper, conceptually, so you'd need to use .find
and then .shallow
.
@ljharb cool thanks for the prompt response 👍 . I ended up using mount & then .find() ==> that also worked.
@ljharb I have one more question, might be unrelated to this thread. Apologies if I've put it in wrong thread. I can open up a new one if necessary but :
I'm trying to check if onChange handler was called on keyDown simulation.
``
**one.jsx**
<Wrapper1>
<Wrapper2 handleKeyDown={this.handleKeyDown}/>
</Wrapper1>
**two.jsx**
<Wrapper3 handleKeyDown={props.handleKeyDown}/>
**wrapper3.jsx**
<input class='abc' onKeyDown={props.handleKeyDown}/>
I'm trying to check if onChange handler was called on keyDown simulation. The simulate seems to be fired but the onChange doesn't seem to be called. Is there another way to test this behavior using enzyme?
test:
const component = mount(<One {...properties} />);
const instance = component.instance();
instance.onChangeHandler = jest.fn();
const input = component.find('input');
input.simulate('keydown', { key: 's', keyCode: 83 });
expect(instance.onChangeHandler).toBeCalled();
All you need to assert is that the input
has onKeyDown
. You don't need to (and shouldn't) be testing React's event wiring itself.
@ljharb yes I agree but for certain keys I am prevent the event. Which is why I was trying to test if onChange fired when I pressed that particular key. How would I test that?
Directly call the function with different faked event objects, and see what happens?
onChangeHandler = jest.fn();
changes your local variable, it doesn't change anything about the instance.
I was facing the same issue, and using shallow(
I'm finding that even though I can output all content with wrapper.html(), when I try to dig through a rendered shallow component with .find and .findWhere, they stop at the top level.
In this example:
for instance, only runs once, even for a component with deeply nested inline elements.