1

Thats my component

class Foo extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            ...
        };

        this.input = React.createRef();
    }

    componentDidMount() {
        const id = 'bar';
        let element = document.getElementById(id);
        element.addEventListener('transitionend', () => {
            this.setState({ ... });
        }, false);
    }

    ...

When I set up my test like so

import React from 'react';
import { mount } from 'enzyme';
import 'jsdom-global/register';

import Foo from './';

it('renders the component correctly', () => {
    const component = mount(
        <Foo />
    );

    component
        .unmount();
});

I get

console.error node_modules/react-dom/cjs/react-dom.development.js:16647 The above error occurred in the component: in Foo (created by WrapperComponent) in WrapperComponent

Consider adding an error boundary to your tree to customize error handling behavior. ● renders the component correctly TypeError: Cannot read property 'addEventListener' of null

I tried

ReactDOM.render(<Foo />, document.body);

or adding this

const map = {};
Window.addEventListener = jest.genMockFn().mockImpl((event, cb) => {
  map[event] = cb;
});

as well as this

const map = {};
    document.addEventListener = jest.fn((event, cb) => {
      map[event] = cb;
    })

before mounting <Foo /> in the test. But it all comes back with the same error. Why is that?

four-eyes
  • 10,740
  • 29
  • 111
  • 220
  • 1
    Possible duplicate of [jest + enzyme, using mount(), document.getElementById() returns null on component which appear after \_method call](https://stackoverflow.com/questions/43694975/jest-enzyme-using-mount-document-getelementbyid-returns-null-on-componen) – Agney Feb 12 '19 at 11:29

1 Answers1

4

One of reasons why direct DOM access is discouraged in React is because it makes testing more complicated and unpredictable.

DOM can be mocked entirely before mounting a component:

const elementMock = { addEventListener: jest.fn() };
jest.spyOn(document, 'getElementById').mockImplementation(() => elementMock);

A stub can be tested that is was called correctly:

expect(elementMock.addEventListener).toBeCalledWith('transitionend', expect.any(Function), false);

And event listener can be tested that it changes the state as expected:

const handler = elementMock.mock.calls[0][1];
handler();
...
Estus Flask
  • 206,104
  • 70
  • 425
  • 565
  • Thanks. I referred to this comment from alechill in the answer from Dmytro Zhytomyrsky https://stackoverflow.com/questions/43694975/jest-enzyme-using-mount-document-getelementbyid-returns-null-on-componen?answertab=votes#tab-top and changed my code accordingly. Now I do not have any problems. – four-eyes Feb 13 '19 at 08:48