How to test a click event with enzyme in a React component's dangerouslySetInnerHTML content

Viewed 585

I have a component that just renders customer entered HTML. This HTML can contain links. The click events are intercepted. How can I test this in Enzyme?

class Html extends React.Component {
  componentDidMount() {
    this.htmlContainer.addEventListener('click', this.handleTap, true);
  }

  componentWillUnmount() {
    this.htmlContainer.removeEventListener('click', this.handleTap, true);
  }

  handleTap = (event) => {
    // do stuff ...
  }

  render() {
    return (
      <div
        dangerouslySetInnerHTML={{ __html: this.props.html }}
        ref={(domElm) => { this.htmlContainer = domElm; }}
      />
    );
  }
}
1 Answers

I was able to solve it by attaching the mount to the DOM.

// The Component

function CustomHtml({ html, trackInteraction }) {
    const ref = useRef<?HTMLDivElement>();

    const trackClick = useCallback(() => {
        trackInteraction();
    }, [trackInteraction]);

    useEffect(() => {
        const elements = ref.current?.querySelectorAll('[data-click-track]') || [];

        elements.forEach(element => {
            element.addEventListener('click', trackClick);
        });

        return () => {
            elements.forEach(element => {
                element.removeEventListener('click', trackClick);
            });
        };
    }, [trackClick]);

    return <div ref={ref} dangerouslySetInnerHTML={{ __html: html }} />;
}

// The Test

it('should call mock on click on inner html', () => {

    const trackInteractionMock = jest.fn();

    const body = document.querySelector('body');
    body.appendChild(document.createElement('div'));

    const wrapper = mount(
        <CustomHtml html="<span data-click-track>click me</span>" trackInteraction={trackInteractionMock} />,
        { attachTo: body.firstChild }
    );

    const span = document.querySelector('[data-click-track]');
    const event = new Event('click');
    span.dispatchEvent(event);

    expect(trackInteractionMock).toHaveBeenCalledWith();

});
Related