If I create a custom theme and test a component that is leveraging a custom object from that theme, tests fail because that custom field is undefined, is there a documented way to test components with custom themes?
Create a custom theme:
customTheme = {
"direction": "ltr",
"palette": {
"customObject": {
"customField1": "#FF0000"
},
......
}
Shallow render custom component with a custom theme.
shallow(
<MuiThemeProvider theme={customTheme} >
<ComponentThatUsesCustomField1 />
</MuiThemeProvider
).dive()
Will throw an undefined error at customObject.
First thing, the createMuiTheme is doing the job correctly.

Second thing, the shallow function of enzyme doesn't propagate the context create by a component. You need to use the mount API.
Second thing, the shallow function of enzyme doesn't propagate the context create by a component. You need to use the mount API.
I tried using mount but enzyme still complains if I have custom variables in the theme. What is the best way to do this? Is there a cleaner way to do the below?
const JobWithTheme = props => (
<MuiThemeProvider theme={theme}>
<Job {...props} />
</MuiThemeProvider>
);
const wrapper = shallow(<JobWithTheme match={{params: {id: '1'}}} />);
Even then, I am running into this enzyme issue reported here where it's hard to setState of the nested component (the example uses MuiThemeProvider): https://github.com/airbnb/enzyme/issues/1289
Any pointers would be greatly appreciated.
I worked around this by manually adding the custom theme in to the context like so:
import {CHANNEL} from '@material-ui/core/styles/themeListener';
import createBroadcast from 'brcast';
const broadcast = createBroadcast();
broadcast.setState(customTheme);
const wrapper = shallow(<ComponentThatUsesCustomField1 />, {
context: {
[CHANNEL]: broadcast,
},
});
You can use the above logic to wrap createShallow or make it cleaner in any number of ways.
@stocky37 Thank you so much! I've spent all evening trying to provide a custom theme via a context and this worked fine. The only thing I needed to do was to add childContextTypes:
const wrapper = shallow(<ComponentThatUsesCustomField1 />, {
context: {
[CHANNEL]: broadcast
},
childContextTypes: {
[CHANNEL]: PropTypes.object
}
});
You should not rely on implementation details about the theme context. Once we switch to the stable context API this will be obsolete. Use MuiThemeProvider instead.
But then you can鈥檛 use shallow in your unit tests, right?
I don't think so. Enzyme is currently lacking test methods for the new context API anyway and some people would argue that you should never test with shallow rendering anyway which is at least true for this particular test case in my opinion
@eps1lon The reason that I wasn't using MuiThemeProvider in the tests is that a lot of the existing tests manipulate (set state, set props, check props) on the top-level component, so wrapping components in MuiThemeProvider breaks all of these tests.
We are currently having similar issues when switching from the legacy context api to the component based API and the issue is that our tests were to brittle to begin with. You can work around setProps and setState with helper methods although setState should only be used on rare occasions. Anything else should not rely on the actual component tree but the rendered dom tree.
Hello,
I'm experiencing a similar issue. I've wrapped a TextField in a MuiThemeProvider, so when using jest tests fail:
createMuiTheme -> createPalette -> augmentColor ()
It seems that it's unable to get the palette in the tests, even though it's working perfectly in the rest of scenarios (no browser console logs complaining when NODE_ENV='development', so our palette is well defined).
Is there any workaround to include this context for our tests (with shallow)? Maybe the augmentColor should not be raising an error if NODE_ENV='test' ?
Thank you very much for your help.
@JavierLight This is a fundamental issue with enzyme and shallow rendering. You could use either use shallow with dive or mount. Some additional ressources: https://blog.kentcdodds.com/why-i-never-use-shallow-rendering-c08851a68bb7
@eps1lon
You should not rely on implementation details about the theme context. Once we switch to the stable
context API this will be obsolete. UseMuiThemeProviderinstead.
I am trying to test my component which is wrapped by theme provider.The problem is that i can not use setProps method in the instance of wrapped component.
Here is my test case:
it('Renders valid no data text', () => {
let wrapper = mount(
<ThemeProvider>
<ResponsiveTable
noDataText="no data"
loadingError={false}
isLoading={false} data={[]}/>
</ThemeProvider>
)
expect(wrapper.contains(<div>no data</div>)).toBeTruthy()
wrapper.find('ResponsiveTable').instance().setProps({isLoading:'true'}) // this doesnt work due to lack of setProps method
expect(wrapper.contains(<div>no data</div>)).toBeFalsy()
})
I have some logic in the componentDidUpdate which i would like tot test, but i can't when i wrap my component in ThemeProvider.
I'am in dead end.What say you?
Cheers!
Most helpful comment
Hello,
I'm experiencing a similar issue. I've wrapped a
TextFieldin aMuiThemeProvider, so when usingjesttests fail:createMuiTheme -> createPalette -> augmentColor ()It seems that it's unable to get the palette in the tests, even though it's working perfectly in the rest of scenarios (no browser console logs complaining when
NODE_ENV='development', so our palette is well defined).Is there any workaround to include this context for our tests (with
shallow)? Maybe theaugmentColorshould not be raising an error ifNODE_ENV='test'?Thank you very much for your help.