using enzyme.mount().setProps with a react-redux Provider
You should only be calling setProps
on the wrapped component or parent.
A good rule of thumb is your test should only be testing a single component (the parent), so setting props on children is not permitted with enzyme.
https://github.com/airbnb/enzyme/blob/master/docs/api/ShallowWrapper/setProps.md#setpropsnextprops--self
If you have child components further down that we need to satisfy store dependencies for (via Provider and context), then that is fine, but those child components should really have their own isolated tests.
That is where you'd be encouraged to write a test for a change on setProps
.
If you find yourself writing tests for a container or connector, you would really only want to verify that the child component is receiving the correct props and or state. For example:
import { createMockStore } from 'mocks'
import { shallwo } from 'enzyme'
// this component exports the redux connection
import Container from '../container'
const state = { foo: 'bar' }
let wrapper
let wrapped
let store
beforeEach(() => {
store = createMockStore(state)
wrapper = shallow(<Container store={store} />)
wrapped = wrapper.find('MyChildComponent')
})
it('props.foo', () => {
const expected = 'bar'
const actual = wrapped.prop('foo')
expect(expected).toEqual(actual)
})
One other tip is that it helps to understand the difference between shallow and mount so you aren't needlessly mocking dependencies for children in a test, the top answer here is a good read:
When should you use render and shallow in Enzyme / React tests?
Another approach will be to use wrappingComponent
.
For example, let say this is your provider
const ExampleProvider = ({ children }) => (
<Provider store={store}>
{children}
</Provider>
);
and then initialize wrapper
as follows
wrapper = mount(<Component />, { wrappingComponent: ExampleProvider});
And then in test cases, you should be able to call wrapper.setProps
directly.
Here's an approach using the setProps
import { Provider } from 'react-redux';
const renderComponent = properties => mount(
React.createElement(
props => (
<Provider store={store}>
<IntlProvider locale="en" defaultLocale="en" messages={messages}>
<Router>
<MyComponent {...props} />
</Router>
</Provider>
),
properties))
Then in your test
it('should set some props', () => {
const renderedComponent = renderComponent(props);
renderedComponent.setProps({ /* some props */ } });
expect(true).toBe(true);
})
I had the same issue after wrapping my component in a Provider. What I did is, I used setProps on children instead of a component itself.
This is the example of my component in test suite:
let component, connectedComponent;
component = () => {
store = configureMockStore()(myStore);
connectedComponent = mount(
<Provider >
<MyComponent store={store} params={{xyz: 123}} />
</Provider>);};
But in the test itself, I did this:
connectedComponent.setProps({children: <MyComponent params={{}} />});