0
votes

I have a Modal window written in ReactJS with Material-ui library and I am creating a Enzyme (with Jest) unit test to make sure

  1. user can click a button to open Modal window
  2. content in the modal shall be 'something'
  3. user shall be able to close the Modal window by either clicking on backdrop or pressing ESC keystroke.

I can test 1 and 2 above but I am not sure how I am suppose to make the backdrop click event or send ESC keystroke.

My modal window code

import React from "react";
import { makeStyles } from "@material-ui/core/styles";
import Modal from "@material-ui/core/Modal";

function getModalStyle() {
  const top = 50;
  const left = 50;

  return {
    top: `${top}%`,
    left: `${left}%`,
    transform: `translate(-${top}%, -${left}%)`
  };
}

const useStyles = makeStyles(theme => ({
  paper: {
    position: "absolute",
    width: 400,
    backgroundColor: theme.palette.background.paper,
    border: "2px solid #000",
    boxShadow: theme.shadows[5],
    padding: theme.spacing(2, 4, 4),
    outline: "none"
  }
}));

export default function Modalwindow() {
  const classes = useStyles();
  // getModalStyle is not a pure function, we roll the style only on the first render
  const [modalStyle] = React.useState(getModalStyle);
  const [open, setOpen] = React.useState(false);

  const handleOpen = () => {
    setOpen(true);
  };

  const handleClose = () => {
    setOpen(false);
  };

  return (
    <div>
      <p>Click to get the full Modal experience!</p>
      <button
        type="button"
        id={"tacButton"}
        name={"tacButton"}
        onClick={handleOpen}
      >
        Open Modal
      </button>
      <Modal
        aria-labelledby="simple-modal-title"
        aria-describedby="simple-modal-description"
        id={"tacModalWindow"}
        name={"tacModalWindow"}
        open={open}
        onClose={handleClose}
      >
        <div style={modalStyle} className={classes.paper}>
          <h2 id="modal-title">Text in a modal</h2>
          <p id="simple-modal-description">
            Duis mollis, est non commodo luctus, nisi erat porttitor ligula.
          </p>
        </div>
      </Modal>
    </div>
  );
}

My unit test code

import { configure } from "enzyme/build";
import Adapter from "enzyme-adapter-react-16/build";
import { createMount } from "@material-ui/core/test-utils";
import { act } from "react-dom/test-utils";
import { Backdrop } from "@material-ui/core";
import { Modalwindow } from "./Modalwindow";

import React from "react";

configure({ adapter: new Adapter() });

describe("<Modalwindow />", () => {
  let componentMount = createMount();
  let component;
  act(() => {
    component = componentMount(<Modalwindow />);
  });

  it("should render modal window with TAC content", done => {
    act(() => {
      component.update();
    });
    // check the Modal is closed
    expect(component.find('#tacModalWindow').at(0).props().open).toBe(false);

    // check modal is open when user press a button
    act(() => {
      component.find('#tacButton').at(0).simulate('click', {
        currentTarget: {
          name: 'tacButton'
        }
      });
    });
    component.update();
    expect(component.find('#tacModalWindow').at(0).props().open).toBe(true);

    // Now how do I close here? *******************************
    // DO SOMETHING

    // check the modal is closed.
    expect(component.find('#tacModalWindow').at(0).props().open).toBe(false);


    done();
  });
});

I also uploaded the code to https://codesandbox.io/embed/stupefied-butterfly-t5bv5

(but for some reason, codesandbox doesn't work with enzyme for me.)

1

1 Answers

0
votes

I fixed with the following

import React from "react";
import { makeStyles } from "@material-ui/core/styles";
import Modal from "@material-ui/core/Modal";
import {Backdrop} from "@material-ui/core";


function getModalStyle() {
  const top = 50;
  const left = 50;

  return {
    top: `${top}%`,
    left: `${left}%`,
    transform: `translate(-${top}%, -${left}%)`
  };
}

const useStyles = makeStyles(theme => ({
  paper: {
    position: "absolute",
    width: 400,
    backgroundColor: theme.palette.background.paper,
    border: "2px solid #000",
    boxShadow: theme.shadows[5],
    padding: theme.spacing(2, 4, 4),
    outline: "none"
  }
}));

export default function Modalwindow() {
  const classes = useStyles();
  // getModalStyle is not a pure function, we roll the style only on the first render
  const [modalStyle] = React.useState(getModalStyle);
  const [open, setOpen] = React.useState(false);

  const handleOpen = () => {
    setOpen(true);
  };

  const handleClose = () => {
    setOpen(false);
  };

  return (
    <div>
      <p>Click to get the full Modal experience!</p>
      <button
        type="button"
        id={"tacButton"}
        name={"tacButton"}
        onClick={handleOpen}
      >
        Open Modal
      </button>
      <Modal
        aria-labelledby="simple-modal-title"
        aria-describedby="simple-modal-description"
        id={"tacModalWindow"}
        name={"tacModalWindow"}
        open={open}
        onClose={handleClose}
        BackdropComponent={Backdrop}
      >
        <div style={modalStyle} className={classes.paper}>
          <h2 id="modal-title">Text in a modal</h2>
          <p id="simple-modal-description">
            Duis mollis, est non commodo luctus, nisi erat porttitor ligula.
          </p>
        </div>
      </Modal>
    </div>
  );
}

And the test

import { configure } from "enzyme/build";
import Adapter from "enzyme-adapter-react-16/build";
import { createMount } from "@material-ui/core/test-utils";
import { act } from "react-dom/test-utils";
import { Backdrop } from "@material-ui/core";
import { Modalwindow } from "./Modalwindow";

import React from "react";

configure({ adapter: new Adapter() });

describe("<Modalwindow />", () => {
  let componentMount = createMount();
  let component;
  act(() => {
    component = componentMount(<Modalwindow />);
  });

  it("should render modal window with TAC content", done => {
    act(() => {
      component.update();
    });
    // check the Modal is closed
    expect(component.find('#tacModalWindow').at(0).props().open).toBe(false);

    // check modal is open when user press a button
    act(() => {
      component.find('#tacButton').at(0).simulate('click', {
        currentTarget: {
          name: 'tacButton'
        }
      });
    });
    component.update();
    expect(component.find('#tacModalWindow').at(0).props().open).toBe(true);

    // Now how do I close here? *******************************
    act(() => {
      component.find(Backdrop).simulate('click', {
        currentTarget: {
          name: 'tacButton'
        }
      });
    });
    component.update();

    // check the modal is closed.
    expect(component.find('#tacModalWindow').at(0).props().open).toBe(false);


    done();
  });
});

Summary :

I had to add BackdropComponent prop to the Modal.

I hope this helps.