Skip to content

Instantly share code, notes, and snippets.

@rickarubio
Forked from mirague/CustomComponent-test.js
Created February 27, 2018 20:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rickarubio/ed25abb75c95e9279c476171e322ce5f to your computer and use it in GitHub Desktop.
Save rickarubio/ed25abb75c95e9279c476171e322ce5f to your computer and use it in GitHub Desktop.
Testing React-Intl components with Enzyme's mount() and shallow() methods. This is a helper function which wraps the `intl` context around your component tests in an easy and efficient way.

When using Enzyme and React-Intl you are likely run into the issues when testing components that use some of React-Intl's components or injected formatting functions. These helper functions (mountWithIntl and shallowWithIntl) aim to address some of the below errors:

Uncaught Invariant Violation: [React Intl] Could not find required ``intl`` object. <IntlProvider> needs to exist in the component ancestry.

TypeError: Cannot read property 'getInstance' of null

Error: ReactWrapper::state() can only be called on the root

Checkout this question at StackOverflow for a complete overview of the issues I ran into:

Injecting react-intl object into mounted Enzyme components for testing

import { mountWithIntl } from 'helpers/intl-enzyme-test-helper.js';
const wrapper = mountWithIntl(
<CustomComponent />
);
expect(wrapper.state('foo')).to.equal('bar'); // OK
expect(wrapper.text()).to.equal('Hello World!'); // OK
import React from 'react';
import { FormattedMessage } from 'react-intl';
class CustomComponent extends React.Component {
state = {
foo: 'bar'
}
render() {
return (
<div>
<FormattedMessage id="world.hello" defaultMessage="Hello World!" />
</div>
);
}
}
/**
* Components using the react-intl module require access to the intl context.
* This is not available when mounting single components in Enzyme.
* These helper functions aim to address that and wrap a valid,
* English-locale intl context around them.
*/
import React from 'react';
import { IntlProvider, intlShape } from 'react-intl';
import { mount, shallow } from 'enzyme';
// You can pass your messages to the IntlProvider. Optional: remove if unneeded.
const messages = require('../locales/en'); // en.json
// Create the IntlProvider to retrieve context for wrapping around.
const intlProvider = new IntlProvider({ locale: 'en', messages }, {});
const { intl } = intlProvider.getChildContext();
/**
* When using React-Intl `injectIntl` on components, props.intl is required.
*/
function nodeWithIntlProp(node) {
return React.cloneElement(node, { intl });
}
/**
* Export these methods.
*/
export function shallowWithIntl(node) {
return shallow(nodeWithIntlProp(node), { context: { intl } });
}
export function mountWithIntl(node) {
return mount(nodeWithIntlProp(node), {
context: { intl },
childContextTypes: { intl: intlShape }
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment