Reputation: 331
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?
Upvotes: 7
Views: 9021
Reputation: 4255
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(...);
});
Upvotes: 9
Reputation: 2803
If you want to test MyComponent, you should
const wrapper = mount(MyComponent);
Other things like Provider are not part of MyComponent so shouldn't be included in the unit test for it.
Upvotes: -1