I'm going to test lifecycle functions including componentWillReceiveProps using enzyme.
Before anything else, my component should be wrapped materialUi styles and be connected with redux. Otherwise, there will be bugs in render function because I use material-ui components including FlatButton.
const wrapper = mount(
<MuiThemeProvider muiTheme={muiTheme}>
<Provider store={store}>
<MemoryRouter>
<MyComponent />
</MemoryRouter>
</Provider>
</MuiThemeProvider>)
// absolutely fail
wrapper.find(MyComponent).setProps({ something })
expect(MyComponent.prototype.componentWillReceiveProps.calledOnce).toBe(true)
So the problem is that I can't use setProps() to MyComponent because enzyme doesn't allow applying non-root component. I'm not able to test componentWillReceiveProps or other necessary parts by changing props.
How can I set/change props of MyComponent so that I can test componentWillReceiveProps?
It is better to test your component in isolation. The problem is that material-ui
is passing down its props using React context
. You can specify the context of your component this way:
import React from 'react';
import { mount } from 'enzyme';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
const wrapper = mount(
<MyComponent />,
{
context: {
muiTheme: getMuiTheme(),
},
childContextTypes: {
muiTheme: React.PropTypes.object.isRequired,
}
}
);
Another thing you need to isolate your component is to remove <Provider>
. Instead of testing your connected component try to test component itself the way it is described in Redux
docs: Testing Connected Components
Shortly - export both component and connected component, then test component by passing props. Example of the component with exports:
import { connect } from 'react-redux'
// Use named export for unconnected component (for tests)
export class MyComponent extends Component { /* ... */ }
// Use default export for the connected component (for app)
export default connect(mapStateToProps)(MyComponent)
You can now import the undecorated component in your test file like this:
import { MyComponent } from './MyComponent';
And the final test could look this way:
import React from 'react';
import { mount } from 'enzyme';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
import { MyComponent } from './MyComponent';
test('test component', () => {
const wrapper = mount(
<MyComponent />,
{
context: {
muiTheme: getMuiTheme(),
},
childContextTypes: {
muiTheme: React.PropTypes.object.isRequired,
}
}
);
// Test something
const p = wrapper.find(...);
expect(...).toEqual(...);
// Change props
wrapper.setProps({foo: 1});
// test again
expect(...).toEqual(...);
});
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