Search code examples
reactjsjestjsmaterial-uiintegration-testingreact-testing-library

How to test Material-UI Popover close implementation


I would like to make sure that my implementation of a Popover element combined with a trigger button works as expected. I was unable to have a working test for asserting that the Popover gets closed after the user presses esc. I was able to make this test work with Modal, but I must use a Popover in my current project.

Component code:

import {
    Button, Popover,
} from '@mui/material';
import React from 'react';

export default function SimpleModal() {
    const [anchorEl, setAnchorEl] = React.useState<HTMLButtonElement | null>(null);

    const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
    setAnchorEl(event.currentTarget);
  };

  const handleClose = () => {
    setAnchorEl(null);
  };

  const open = Boolean(anchorEl);
  const id = open ? 'user-menu' : undefined;

    return (
        <>
            <Button
                aria-controls={id}
                aria-haspopup="true"
                onClick={handleClick}
            >
                Open Modal
            </Button>

            <Popover open={open} onClose={handleClose}>
                    <h1>Text in Modal</h1>
            </Popover>
        </>
    );
}

Test file code:

import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import SimpleModal from './SimpleModal';

test('should close when esc key is pressed', async () => {
    render(<SimpleModal />);
    userEvent.click(screen.getByText('Open Modal'));
    expect(screen.getByText('Text in Modal')).toBeInTheDocument();
    userEvent.keyboard('{esc}');
    await expect(screen.queryByText('Text in Modal')).not.toBeInTheDocument();
});

Solution

  • As suggested by @juliomalves, wrapping the last expect in a waitFor corrected the test:

    await waitFor(() => expect(...));