The problem:
<Child prop1={this.state.prop1}>What is the right way to go about testing that this process is happening as expected?
Here's some example code to make the problem clearer:
//App.js
import React, { Component } from 'react';
import Content from './Content';
class App extends Component {
constructor(props){
super(props)
this.state = {
page: 'home',
}
}
gotoAbout(){
this.setState({
page: 'about',
})
}
render() {
return(
<Content page={this.state.page} gotoAbout={this.gotoAbout.bind(this)} />
)
}
}
As you can see, the parent component App passes a prop, and a function that can change the value of that prop to its child component, Content.
The Content component would then do something like this:
//Content.js
import React, { Component } from 'react';
class Content extends Component {
constructor(props){
super(props)
}
gotoAbout() {
this.props.gotoAbout()
}
render(){
if(this.props.page = 'home'){
return(
<div>
<p>this is the home content</p>
<button onClick={this.gotoAbout}></button>
</div>
)
} else {
return(
<p>this is the about content</p>
)
}
}
}
The above is a simplified example, but I think it gets the point across. What would be the best way to write a test for this kind of component-prop flow?
I generally first start testing the components in isolation using shallow rendering with its expected functionality and then test components with composition.
e.g To test Content component
1.test whether it behaves correctly for props or state changes
2.test if it performs event's correctly such as button click or any other events through simulation
const wrapper
= shallow(
<Content
page={"home"}
gotoAbout={()=>{ console.log("fake goAbout")}}
/>
);
Now Check if rendered structure is matched as expected for prop page={"home"}
expect(wrapper.containsMatchingElement(
<div>
<p>this is the home content</p>
<button onClick={this.gotoAbout}></button>
</div>
)).to.equal(true);
Similarly test for other prop page={"about"} whether content renders correctly or not.
wrapper.setProps({ page: 'about' });
expect(wrapper.containsMatchingElement(
<p>this is the about content</p>
)).to.equal(true);
After that you can test for button click events
clickCount = 0;
const wrapper
= shallow(
<Content
page={"home"}
gotoAbout={()=>{ clickCount = clickCount + 1;}}
/>
);
Now you can check whether clickCount is greater than zero, after simulating the click event.
wrapper.find('button').simulate('click');
After that you may start testing the App component.
const wrapper = shallow(<App />);
const childWrapper = wrapper.find('Content');
After that you may create another Content component separately via shallow rendering and match those two for equal html structure, props, states etc.
const twrapper
= shallow(
<Content
page={"home"}
gotoAbout={()=>{ console.log("fake goAbout")}}
/>
);
expect(twrapper.html()).to.equal(childWrapper.html());
You can also check whether prop is passed correctly to rendered child elements -
expect(childWrapper.prop('page')).to.equal("home");
There may other better way available as well for testing the react components and these are just simple test examples. Enzyme provides lots of ways to test your components and there is no hard and fast rule I guess. But you should at least test the expected functionality and features of your component.
Also your test cases make sure that any new changes being made to the component don't break your test specification.