Testing React Intl components with Jest and Enzyme
There are two problems with testing components that use React Intl with Enzyme and Jest:
injectIntl
higher-order component will break shallow rendering because it will render a wrapper component instead of your component.- An
intl
prop will make snapshot testing useless because each snapshot will contain all your messages.
The solution is based on React Intl’s wiki:
- Add two new helper functions to your Jest setup file (setupFiles):
import { IntlProvider, intlShape } from 'react-intl';
// Create IntlProvider to retrieve React Intl context
const intlProvider = new IntlProvider(
{
locale: 'en',
messages: {
message1: 'Hello world'
}
},
{}
);
const { intl } = intlProvider.getChildContext();
// intl prop is required when using injectIntl HOC
const nodeWithIntlProp = node => React.cloneElement(node, { intl });
// shallow() with React Intl context
global.shallowWithIntl = (node, { context, ...options } = {}) => {
return shallow(nodeWithIntlProp(node), {
...options,
context: {
...context,
intl
}
});
};
// mount() with React Intl context
global.mountWithIntl = (
node,
{ context, childContextTypes, ...options } = {}
) => {
return mount(nodeWithIntlProp(node), {
...options,
context: {
...context,
intl
},
childContextTypes: {
intl: intlShape,
...childContextTypes
}
});
};
- Export your component with and without
injectIntl
:
import React from 'react';
import { injectIntl } from 'react-intl';
export function Pony() {
/* _ */
}
export default injectIntl(Pony);
- Write test cases almost as usual, using the
shallowWithIntl
andmountWithIntl
helpers:
import React from 'react';
import { Pony } from './Pony';
test('pink pony', () => {
const wrapper = shallowWithIntl(<Pony color="pink" />);
expect(wrapper).toMatchSnapshot();
expect(wrapper.find('.tail').prop('value')).toBe('pink');
});
P. S. You may also enjoy my more generic article on testing React components with Jest and Enzyme and Jest cheat sheet.