Jest: Testing with React-Intl

Created on 11 Aug 2016  Â·  4Comments  Â·  Source: facebook/jest

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?

Most helpful comment

_…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>);
};

All 4 comments

i don't think react-test-renderer can accept the context argument.
i think for the snapshot testing it's better to look at this or this example.

hey @ericf can you look at this?

we should write a doc for jest if we can get a working example :)

@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 :)

Was this page helpful?
0 / 5 - 0 ratings