Search code examples
reactjsjestjsreact-hooksreact-intl

FormattedTime component throwing error when mounted in unit test


I am working on implementing a unit test for a custom React hook that utilizes the react-intl component FormattedTime. Unfortunately, I am having trouble getting past the following error when mounted:

[Error: FormattedTime(...): Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null.]

The portion of the hook that is using FormattedTime:

{ timeIncrements.map((time, key) => (
  <DropdownItem value={ format(convertTime(time, date), "yyyy-MM-dd'T'HH:mm:'00'") } key={ key }>
    <FormattedTime
      value={ convertTime(time, date) }
      timeZone={ timezone }
      timeZoneName='short'
      hour='numeric'
      minute='numeric'
      hour12={ true }
    />
  </DropdownItem>
)) }

I have confirmed that the convertTime function is returning a value to pass to the component.

There isn't much to the unit test yet, but here it is:

it('mounts component', () => {
  const Component = injectIntl(Settings);
  const wrapper = mount(<Component />);

  expect(wrapper.find(Schedule)).toHaveLength(1);

  wrapper.unmount();
});

Is there a way to spyOn/mock that FormattedTime component? I have done similar spyOn for FormattedMessage errors, but can't seem to find a way to implement similar for FormattedTime. I think this will be an easy question for someone, but it is giving me fits so asking for help.


Update based on answer from @diedu...here is the output from wrapper.debug():

<IntlProvider locale="en-US" messages={{...}} formats={{...}} timeZone={[undefined]} textComponent={[symbol]} defaultLocale="en" defaultFormats={{...}} onError={[Function: mockConstructor] { _isMockFunction: true, getMockImplementation: [Function (anonymous)], mock: Object [Object: null prototype] { calls: [], instances: [], invocationCallOrder: [], results: [] }, mockClear: [Function (anonymous)], mockReset: [Function (anonymous)], mockRestore: [Function (anonymous)], mockReturnValueOnce: [Function (anonymous)], mockResolvedValueOnce: [Function (anonymous)], mockRejectedValueOnce: [Function (anonymous)], mockReturnValue: [Function (anonymous)], mockResolvedValue: [Function (anonymous)], mockRejectedValue: [Function (anonymous)], mockImplementationOnce: [Function (anonymous)], mockImplementation: [Function (anonymous)], mockReturnThis: [Function (anonymous)], mockName: [Function (anonymous)], getMockName: [Function (anonymous)] }} />

Solution

  • react-intl needs an I18n Context to work, you need to wrap the component you're testing with all the providers 3rd party libs need when mounting.

      it("mounts component", () => {
        const Component = injectIntl(Settings);
        const wrapper = mount(
          <IntlProvider locale={usersLocale} messages={translationsForUsersLocale}>
            <Component />
          </IntlProvider>
        );
    
        expect(wrapper.find(Schedule)).toHaveLength(1);
    
        wrapper.unmount();
      });