Unit testing react-helmet code

Viewed 5364

I am using react-helmet to add elements to head element.

<Helmet>
     <title>title</title>
     <meta name="description" content="description" />
     <meta name="keywords" content="keywords" />
</Helmet>

And I am trying to write unit test like this:

it('should render metadata', () => {
    const wrapper = mount(<Metadata/>);
    // this is not working.
    expect(document.title).to.equal("title");
});
4 Answers

I was in a similar situation with react testing library and JSDOM, but I didn't want to make the test specific to the Helmet implementation because that's against the guiding principle of react testing library. I found that doing the obvious thing:

render(<App />)
await waitFor(...some DOM element)
expect(document.title).toEqual("title")

does not work even if the DOM element you're awaiting is rendered in the same render as the <Helmet>

However, this does work:

await waitFor(...some DOM element)
await waitFor( () => expect(document.title).toEqual("title"))

I presume that between React and Helmet there's some timing thing going on which means there's a delay between the rest of the DOM being rendered and the title being set in JSDOM.

Today i tested adding simply <HelmetProvider> in the return of the react function. Before that, i had errors like

TypeError: Cannot read properties of undefined (reading 'add')

when coming to the render command in the test. After adding the <HelmetProvider> tests are passed without error.

If you want to test helmet with only jest and no furhter modules like enzyme etc. you can do the following:

add:

jest.mock('react-helmet', () => {
    const React = require('react');
    const plugin = jest.requireActual('react-helmet');
    const mockHelmet = ({children, ...props}) =>
        React.createElement('div', {
            ...props,
            className: 'mock-helmet',
        }, children);
    return {
        ...plugin,
        Helmet: jest.fn().mockImplementation(mockHelmet),
    };
});

to your setupFiles in the jest config.

Now it will render a <div className="mock-helmet"> that you can use for snapshot tests or inspect further and check if a certain <meta> tag is present inside.

Related