-1

For abstraction purpose, the app I work on has a custom provider that wraps a couple of other providers (like IntlProvider and CookiesProvider). The version of react-intl we use in our app is still v2 (react-intl@2.8.0). A simplified version of my App.js is:

App.js

return (
      <Provider
        value={{
          localeData,
          env,
          data
        }}>
          <IntlProvider locale={language} key={language} messages={allMessages}>
             {props.children}
          </IntlProvider>
      </Provider>
  )

I have setup a custom render to test components in my app. My custom render looks exactly as it is specified in the react-intl-docs. I have followed the official setup guides from react-testing-library.

import React from "react";
import {render} from "@testing-library/react";

import {MyProvider} from "MyProvider";

const MyTestProvider = ({children}) => {
  return <MyProvider>{children}</MyProvider>;
};

const myTestRender = (ui, options) => render(ui, {wrapper: MyTestProvider, ...options});

export * from "@testing-library/react";
export {myTestRender as render};

I then render my component under test as follows:

import {render as renderSC} from "test-utils";
import MyComponentUnderTest from 'MyComponentUnderTest';

test("does my component render", () => {
  const {getByText} = renderSC(<MyComponentUnderTest />);
});

I get an error from react-intl which indicates it is warning, but the component that is rendered in test is empty.

console.error
    Warning: IntlProvider.shouldComponentUpdate(): Returned undefined instead of a boolean value. Make sure to return true or false.

This is what my component renders in test:

    <body>
      <div />
    </body>

Is anyone able to advise what I might be doing wrong?

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
Ali Bhagat
  • 475
  • 1
  • 6
  • 15

2 Answers2

0

I think your exports make this problem, try these instead:

import React from "react";
import {render} from "@testing-library/react";

import {MyProvider} from "MyProvider";

const MyTestProvider = ({children}) => {
  return <MyProvider>{children}</MyProvider>;
};

const myTestRender = (ui, options) => render(ui, {wrapper: MyTestProvider, ...options});

export default myTestRender;

and then use your custom renderer this way:

import renderSC from "test-utils";
import MyComponentUnderTest from 'MyComponentUnderTest';

test("does my component render", () => {
  const {getByText} = renderSC(<MyComponentUnderTest />);
});
Taghi Khavari
  • 6,272
  • 3
  • 15
  • 32
  • Thanks so much Taghi for suggesting an answer. I would have been very surprised if the solution you suggested was indeed the answer. As far as the export matches the way I import it should not be a problem if I make it a default export or not. Is there any specific reason you think this would work different with a default export? I did try the change you suggested to confirm and the problem is still the same. – Ali Bhagat Dec 31 '20 at 14:21
  • I thought maybe this line `export * from "@testing-library/react";` is creating the problem. it's not necessary because you're getting all you need from `render` method of `myTestRender` function. – Taghi Khavari Dec 31 '20 at 16:54
  • So did you add `console.error` section after I answered or before it? because I think I didn't see it. – Taghi Khavari Dec 31 '20 at 16:55
  • Based on what `console.error` says the problem is from `MyProvider` Component. Could you show some code from it. – Taghi Khavari Dec 31 '20 at 16:56
0

So I was able to confirm that nothing was wrong with testing-library or with react-intl. The problem was the app I work on had a module mock that mocked out the functionality of react-intl. This was done for convenience when working with unit tests with Enzyme. However this module mock was stripping out all functionality I needed for IntlProvider and that was the reason I was seeing an empty div when I render the testing-library test with a wrapper.

Ali Bhagat
  • 475
  • 1
  • 6
  • 15