react-testing-libraryreact-modal

Testing for existence of react-modal using React Testing Library with findByRole


I am trying to test for the existence of my modal using React Testing Library with findByRole. I keep getting an error saying: Unable to find role="dialog" even though I can see clearly see it printed out in the console of the test.

Here is my test:

import React from "react";
import {
    render,
    screen,
    within,
    fireEvent, cleanup, waitFor
} from '@testing-library/react';
import '@testing-library/jest-dom';
import "@testing-library/react/dont-cleanup-after-each";
import Modal from 'react-modal';

import PackagerModal from './PackagerModal';

const mockedEmptyFn = jest.fn();

const mockBaseProps = {
    openPackager: true,
    setOpenPackager: mockedEmptyFn,
    activeOrder: {
        // ... // lots of irrelevant properties here
        ]
    },
    setOrders: mockedEmptyFn,
    customStyles: {
        content: {
            backgroundColor: "var(--color-primary)",
            border: "1px solid #ccc",
            boxShadow: "-2rem 2rem 2rem rgba(0, 0, 0, 0.5)",
            color: "rgba(var(--RGB-text), 0.8)",
            filter: "blur(0)",
            fontSize: "1.1em",
            fontWeight: "bold",
            margin: "50px auto",
            opacity: 1,
            outline: 0,
            position: "relative",
            visibility: "visible",
            width: "500px"
        },
        overlay: {
            backgroundColor: "rgba(255, 255, 255, 0.9)"
        }
    },
    readOnly: false,
    setReadOnly: mockedEmptyFn,
};

Modal.setAppElement('body');


const Component = (props) =>    <PackagerModal {...mockBaseProps} {...props} />

describe('Packager Modal tests with editable inputs', () => {
    afterAll(() => {
        cleanup();
    });


    test('Should show packager modal', async () => {
        render(
            <Component/>
        );
        // screen.debug();
        const modalWindow = await screen.findByRole('dialog');
        expect(modalWindow).toBeInTheDocument();
    });
});

And here is my modal:

import ReactModal from 'react-modal';
import React, { useEffect, useRef, useState } from 'react';
import CloseButton from './CloseButton';
import PropTypes from 'prop-types';

const PackagerModal = (props) => {
    const {
        openPackager,
        setOpenPackager,
        activeOrder,
        setOrders,
        customStyles,
        readOnly,
        setReadOnly,
    } = props;

    const cleanUpModal = () => {
        setReadOnly(false);
        setUserInput(initialState);
    };

    return (
        <ReactModal
            isOpen={openPackager}
            style={customStyles}
            className={'order-details-modal'}
            closeTimeoutMS={1000}
            onAfterClose={cleanUpModal}
        >
            <CloseButton setOpenModal={setOpenPackager} />
            <h2 className={'title'}>Packager Order Checklist</h2>
        </ReactModal>
    );
};

PackagerModal.propTypes = {
    openPackager: PropTypes.bool.isRequired,
    setOpenPackager: PropTypes.func.isRequired,
    customStyles: PropTypes.object.isRequired,
    activeOrder: PropTypes.object.isRequired,
    setOrders: PropTypes.func.isRequired,
    readOnly: PropTypes.bool.isRequired,
    setReadOnly: PropTypes.func.isRequired,
};

export default PackagerModal;

And finally, here is some of the output I see in the console from the test:

 ● Packager Modal tests with editable inputs › Should show packager modal

    Unable to find role="dialog"

    Ignored nodes: comments, script, style
    <body
      aria-hidden="true"
      class="ReactModal__Body--open"
    >
      <div
        data-react-modal-body-trap=""
        style="position: absolute; opacity: 0;"
        tabindex="0"
      />
      <div />
      <div
        data-react-modal-body-trap=""
        style="position: absolute; opacity: 0;"
        tabindex="0"
      />
      <div
        class="ReactModalPortal"
      >
        <div
          class="ReactModal__Overlay ReactModal__Overlay--after-open"
          style="position: fixed; top: 0px; left: 0px; right: 0px; bottom: 0px; background-color: rgba(255, 255, 255, 0.9);"
        >
          <div
            aria-modal="true"
            class="ReactModal__Content ReactModal__Content--after-open order-details-modal"
            role="dialog"
            style="border: 1px solid #ccc; box-shadow: -2rem 2rem 2rem rgba(0, 0, 0, 0.5); filter: blur(0); font-size: 1.1em; font-weight: bold; margin: 50px auto; opacity: 1; outline: 0; position: relative; visibility: visible; width: 500px;"
            tabindex="-1"
          >
          ...

Solution

  • Looks like the body of your test is set to hidden - aria-hidden="true" (not sure why as I'm not familiar with the package). React Testing Library is heavily accessibility oriented, so by default it ignores any elements that are not accessible.

    Try querying your element with the { hidden: true } option

    const myModal = getByRole('dialog', { hidden: true });