From 938beccb6e4e9ec95fec8d4f1f2bc2ec7ffb4e0b Mon Sep 17 00:00:00 2001 From: Will Hunt Date: Thu, 7 Nov 2024 17:06:49 +0000 Subject: [PATCH] Add tests for Modal (#2731) * Add Modal tests. * fix type * apply review feedback * lint * remove act --- src/Modal.test.tsx | 73 ++++++++++++++++++++++++++ src/Modal.tsx | 12 +++-- src/__snapshots__/Modal.test.tsx.snap | 75 +++++++++++++++++++++++++++ src/useMediaQuery.ts | 2 +- 4 files changed, 158 insertions(+), 4 deletions(-) create mode 100644 src/Modal.test.tsx create mode 100644 src/__snapshots__/Modal.test.tsx.snap diff --git a/src/Modal.test.tsx b/src/Modal.test.tsx new file mode 100644 index 000000000..41bd7bbec --- /dev/null +++ b/src/Modal.test.tsx @@ -0,0 +1,73 @@ +/* +Copyright 2024 New Vector Ltd. + +SPDX-License-Identifier: AGPL-3.0-only +Please see LICENSE in the repository root for full details. +*/ + +import { expect, test } from "vitest"; +import { render } from "@testing-library/react"; +import { ReactNode, useState } from "react"; +import { afterEach } from "node:test"; +import userEvent from "@testing-library/user-event"; + +import { Modal } from "./Modal"; + +const originalMatchMedia = window.matchMedia; +afterEach(() => { + window.matchMedia = originalMatchMedia; +}); + +test("that nothing is rendered when the modal is closed", () => { + const { queryByRole } = render( + +

This is the content.

+
, + ); + expect(queryByRole("dialog")).toBeNull(); +}); + +test("the content is rendered when the modal is open", () => { + const { queryByRole } = render( + +

This is the content.

+
, + ); + expect(queryByRole("dialog")).toMatchSnapshot(); +}); + +test("the modal can be closed by clicking the close button", async () => { + function ModalFn(): ReactNode { + const [isOpen, setOpen] = useState(true); + return ( + setOpen(false)}> +

This is the content.

+
+ ); + } + const user = userEvent.setup(); + const { queryByRole, getByRole } = render(); + await user.click(getByRole("button", { name: "action.close" })); + expect(queryByRole("dialog")).toBeNull(); +}); + +test("the modal renders as a drawer in mobile viewports", () => { + window.matchMedia = function (query): MediaQueryList { + return { + matches: query.includes("hover: none"), + addEventListener(): MediaQueryList { + return this as MediaQueryList; + }, + removeEventListener(): MediaQueryList { + return this as MediaQueryList; + }, + } as unknown as MediaQueryList; + }; + + const { queryByRole } = render( + +

This is the content.

+
, + ); + expect(queryByRole("dialog")).toMatchSnapshot(); +}); diff --git a/src/Modal.tsx b/src/Modal.tsx index deef76355..6e9de90bb 100644 --- a/src/Modal.tsx +++ b/src/Modal.tsx @@ -89,6 +89,7 @@ export const Modal: FC = ({ styles.drawer, { [styles.tabbed]: tabbed }, )} + role="dialog" // Suppress the warning about there being no description; the modal // has an accessible title aria-describedby={undefined} @@ -114,9 +115,14 @@ export const Modal: FC = ({ - {/* Suppress the warning about there being no description; the modal - has an accessible title */} - + +
+
+

+ My modal +

+
+
+

+ This is the content. +

+
+
+ +`; + +exports[`the modal renders as a drawer in mobile viewports 1`] = ` +