Skip to content

Instantly share code, notes, and snippets.

@karlfus
Forked from mirague/CustomComponent-test.js
Last active May 23, 2019 11:30
Show Gist options
  • Save karlfus/f6827d862da7d51b539241d8e0ca70d4 to your computer and use it in GitHub Desktop.
Save karlfus/f6827d862da7d51b539241d8e0ca70d4 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. Extended for TypeScript to include generic type arguments for Mount and Shallow.

Extended mirague's React Intl Enzyme helper to work for Typescript's generic type arguments, which provide type checking and intellisense for the component props and state, thereby making tests easier to write.

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.
*/
/* eslint-disable import/no-extraneous-dependencies */
import * as React from 'react';
import { IntlProvider, intlShape, InjectedIntl } 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-us.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<P>(node) {
return React.cloneElement<P & { intl: InjectedIntl }, { intl: InjectedIntl }>(node, { intl });
}
export function shallowWithIntl<P, S>(node, contextObj?) {
return shallow<P, S>(
nodeWithIntlProp<P>(node),
{
context: Object.assign({}, contextObj ? contextObj.context : {}, { intl }),
}
);
}
// export function mountWithIntl(node, { context, childContextTypes }) {
export function mountWithIntl<P, S>(node, contextObj?) {
return mount<P, S>(
nodeWithIntlProp<P>(node),
{
context: Object.assign({}, contextObj ? contextObj.context : {}, { intl }),
childContextTypes: Object.assign({}, { intl: intlShape },
contextObj ? contextObj.childContextTypes : {})
}
);
}
@arumsey
Copy link

arumsey commented Nov 7, 2018

Typescript throws an error at: https://gist.github.com/karlfus/f6827d862da7d51b539241d8e0ca70d4#file-intl-enzyme-test-helper-js-L23

Type '{ intl: InjectedIntl; }' does not satisfy the constraint 'Component<P & { intl: InjectedIntl; }, any, any>'.
  Property 'setState' is missing in type '{ intl: InjectedIntl; }'.

@jacoob1406
Copy link

Does anyone have the intl-enzyme-test-helper ready to go written in TypeScript?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment