Hi. I'm trying to use snapshot testing for components that use React-Intl (https://github.com/yahoo/react-intl). I tried following a similar approach to how we'd set it up using Enzyme (https://github.com/yahoo/react-intl/wiki/Testing-with-React-Intl#enzyme):
import React from 'react';
jest.mock('react-dom');
import renderer from 'react-test-renderer';
import { IntlProvider } from 'react-intl';
const messages = require('../../build/lang/en-US.json');
const intlProvider = new IntlProvider({ locale: 'en', messages }, {});
const { intl } = intlProvider.getChildContext();
function nodeWithIntlProp(node) {
return React.cloneElement(node, { intl });
}
const rendererWithIntl = (node) => {
return renderer.create(nodeWithIntlProp(node), { context: { intl } });
};
export {
rendererWithIntl,
};
and then my tests:
import React from 'react';
jest.mock('react-dom');
import { rendererWithIntl } from 'utils/tests';
import Item from './Item';
describe('<Item /> - snapshot', () => {
it('renders the default Item', () => {
const component = rendererWithIntl(
<Item
items={ [{ id: '1', text: '123' }] }
selectItem={ () => {} }
/>
);
const tree = component.toJSON();
expect(tree).toMatchSnapshot();
});
});
it keeps throwing an error saying Invariant Violation: [React Intl] Could not find requiredintlobject. <IntlProvider> needs to exist in the component ancestry.. So it looks like I'm not defining the intl context properly using renderer.create. Wondering if you have any tips for how to create the intl context using react-test-renderer's renderer?
@dmitriiabramov
Just to confirm, so you're suggesting to use getRenderedOutput to do snapshot testing?
I currently got the below to work, but I'm not sure how I feel about it:
import React from 'react';
jest.mock('react-dom');
import { createRenderer } from 'react-addons-test-utils';
import { IntlProvider } from 'react-intl';
const messages = require('../../build/lang/en-US.json');
const intlProvider = new IntlProvider({ locale: 'en', messages }, {});
const { intl } = intlProvider.getChildContext();
import Item from './Item';
describe('<Item /> - snapshot', () => {
const renderer = createRenderer();
it('renders the default Item', () => {
const component = renderer.render(
<Item.WrappedComponent
items={ [{ id: '1', text: '123' }] }
selectItem={ () => {} }
intl={ intl }
/>
);
const tree = renderer.getRenderOutput();
expect(tree).toMatchSnapshot();
});
});
_…sorry for the delay, just realized I was pinged on this._
@iam-peekay I looked at react-test-renderer and it doesn't support passing context as @dmitriiabramov said. The reason for the example I wrote up in the docs about manually creating an IntlProvider and calling its getChildContext() method was to get the context.intl without adding another level to tree — which doesn't work out for shallow renderer. But react-test-renderer supports rending deep trees, so it's actually simpler. You should be able to update this code:
const rendererWithIntl = (node) => {
return renderer.create(nodeWithIntlProp(node), { context: { intl } });
};
…to this:
const rendererWithIntl = (node) => {
return renderer.create(<IntlProvider locale='en' messages={messages}>{node}</IntlProvider>);
};
@ericf thank you!! This works :)
Most helpful comment
_…sorry for the delay, just realized I was pinged on this._
@iam-peekay I looked at
react-test-rendererand it doesn't support passingcontextas @dmitriiabramov said. The reason for the example I wrote up in the docs about manually creating anIntlProviderand calling itsgetChildContext()method was to get thecontext.intlwithout adding another level to tree — which doesn't work out for shallow renderer. Butreact-test-renderersupports rending deep trees, so it's actually simpler. You should be able to update this code:…to this: