gatsby-plugin-intl icon indicating copy to clipboard operation
gatsby-plugin-intl copied to clipboard

Testing components/pages using gatsby-plugin-intl

Open philschonholzer opened this issue 5 years ago • 7 comments

I'm trying to test a page/components using react-testing-library and injectIntl from gatsby-plugin-intl. I followed the guide on https://testing-library.com/docs/example-react-intl

I get the following error:

`TypeError: Cannot read property 'language' of undefined

  18 | 
  19 | const renderWithReactIntl = component => {
> 20 |   return render(<IntlProvider locale="en">{component}</IntlProvider>)
     |          ^
  21 | }
  22 | 
  23 | setupTests()

  at node_modules/gatsby-plugin-intl/link.js:27:41

`

Anybody have link to an working example or some docs how to test?

philschonholzer avatar Dec 16 '19 13:12 philschonholzer

gatsby-plugin-intl requires a provider wrapped around the component, similar to the react-intl example you referenced. Here's what I did...

Create a render helper method that can automatically wrap the proper provider around all your tests:

import React from 'react';
import { render } from '@testing-library/react';
import { IntlContextProvider } from 'gatsby-plugin-intl';

export const renderWithProviders = (component) => (
  render(
    <IntlContextProvider value={{ language: 'en-US', routed: true }}>
      {component}
    </IntlContextProvider>,
  )
);

Example test:

import React from 'react';
import { renderWithProviders } from './function-above';
import Component from './example-component';

describe('Component', () => {
  it('renders', () => {
    const { asFragment } = renderWithProviders(
      <Component />,
    );
    expect(asFragment()).toMatchSnapshot();
  });
});

ebello avatar Jan 23 '20 20:01 ebello

I ran into the same error. Tried implementing the suggestion from @ebello but it did not help as I still get this error below.

Screen Shot 2020-11-05 at 19 34 16

Do you have any clue where the problem could be? Tried using IntlContextProvider too bud did not help either.

sampittko avatar Nov 05 '20 18:11 sampittko

@sampittko It looks like you're passing props into the provider where value is expected, like this:

<IntlContextProvider value={{ language: 'en-US', routed: true }}>

ebello avatar Nov 05 '20 20:11 ebello

@ebello Tried it like you are suggesting too but it did not help either.

I also tried using RawIntlContext where I provided intl object that I created but the error was the same as mentioned above.

Screen Shot 2020-11-06 at 19 02 25

Do you have any ideas?

sampittko avatar Nov 06 '20 18:11 sampittko

I've encountered the same error and have not found a solution.

trevlar avatar Feb 11 '21 19:02 trevlar

I found a solution that works for me and resolves this issue. I had to wrap it with both the IntlContextProvider and the IntlProvider. Which included adding all of the relevant messages to the provider. We are using enzyme for generating the component.

I created the file src/test-utils/intl-setup.js with helper functions to use for this. Shallow rendering wasn't very helpful in this case though.

import React from 'react';
import { mount, shallow, render } from 'enzyme';
import { IntlContextProvider, IntlProvider } from 'gatsby-plugin-intl';

import messages from '../intl/es.json';

const es = messages;
const locales = ['en', 'es', 'fr'];
const intlConfig = {
    language: 'es',
    languages: locales,
    messages,
    originalPath: '/',
    redirect: true,
    routed: true,
};

export function shallowWithIntl(component) {
    return shallow(
        <IntlContextProvider value={intlConfig}>
            <IntlProvider locale="es" messages={es}>
                {component}
            </IntlProvider>
        </IntlContextProvider>,
    );
}

export function mountWithIntl(component) {
    return mount(
        <IntlContextProvider value={intlConfig}>
            <IntlProvider locale="es" messages={es}>
                {component}
            </IntlProvider>
        </IntlContextProvider>,
    );
}

export function renderWithIntl(component) {
    return render(
        <IntlContextProvider value={intlConfig}>
            <IntlProvider locale="es" messages={es}>
                {component}
            </IntlProvider>
        </IntlContextProvider>,
    );
}

trevlar avatar Feb 17 '21 01:02 trevlar

I found a solution that works for me and resolves this issue. I had to wrap it with both the IntlContextProvider and the IntlProvider. Which included adding all of the relevant messages to the provider. We are using enzyme for generating the component.

I created the file src/test-utils/intl-setup.js with helper functions to use for this. Shallow rendering wasn't very helpful in this case though.

import React from 'react';
import { mount, shallow, render } from 'enzyme';
import { IntlContextProvider, IntlProvider } from 'gatsby-plugin-intl';

import messages from '../intl/es.json';

const es = messages;
const locales = ['en', 'es', 'fr'];
const intlConfig = {
    language: 'es',
    languages: locales,
    messages,
    originalPath: '/',
    redirect: true,
    routed: true,
};

export function shallowWithIntl(component) {
    return shallow(
        <IntlContextProvider value={intlConfig}>
            <IntlProvider locale="es" messages={es}>
                {component}
            </IntlProvider>
        </IntlContextProvider>,
    );
}

export function mountWithIntl(component) {
    return mount(
        <IntlContextProvider value={intlConfig}>
            <IntlProvider locale="es" messages={es}>
                {component}
            </IntlProvider>
        </IntlContextProvider>,
    );
}

export function renderWithIntl(component) {
    return render(
        <IntlContextProvider value={intlConfig}>
            <IntlProvider locale="es" messages={es}>
                {component}
            </IntlProvider>
        </IntlContextProvider>,
    );
}

I did this setup but I take this error Screen Shot 2022-02-11 at 11 05 13

Wellers0n avatar Feb 11 '22 14:02 Wellers0n