diff --git a/web/package-lock.json b/web/package-lock.json index 0bd993942..678a75720 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -3786,6 +3786,15 @@ "@testing-library/dom": "^7.16.2" } }, + "@testing-library/user-event": { + "version": "12.7.1", + "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-12.7.1.tgz", + "integrity": "sha512-COfCkYgcxc+P9+pEAIGlmBuIDjO91Chf9GOBHI8AhIiMyaoOrKVPQny1uf0HIAYNoHKL5slhkqOPP2ZyNaVQGw==", + "dev": true, + "requires": { + "@babel/runtime": "^7.12.5" + } + }, "@ts-morph/common": { "version": "0.7.3", "resolved": "https://registry.npmjs.org/@ts-morph/common/-/common-0.7.3.tgz", diff --git a/web/package.json b/web/package.json index 07fc1bd6b..6e855a701 100644 --- a/web/package.json +++ b/web/package.json @@ -24,6 +24,7 @@ "@snowpack/plugin-postcss": "^1.1.0", "@testing-library/jest-dom": "^5.11.9", "@testing-library/preact": "^2.0.1", + "@testing-library/user-event": "^12.7.1", "autoprefixer": "^10.2.1", "cross-env": "^7.0.3", "eslint": "^7.19.0", diff --git a/web/src/components/RelativeModal.jsx b/web/src/components/RelativeModal.jsx index a8094b90a..644a0b875 100644 --- a/web/src/components/RelativeModal.jsx +++ b/web/src/components/RelativeModal.jsx @@ -41,10 +41,11 @@ export default function RelativeModal({ if (event.key === 'Escape') { setShow(false); + handleDismiss(); return; } }, - [ref] + [ref, handleDismiss] ); useLayoutEffect(() => { @@ -96,7 +97,7 @@ export default function RelativeModal({ const menu = ( -
+
{ + test('keeps tab focus', async () => { + const ref = createRef(); + render( +
+ + +
+ + + + +
+ ); + + const inputs = screen.queryAllByTestId(/modal-input/); + expect(document.activeElement).toBe(inputs[0]); + userEvent.tab(); + expect(document.activeElement).toBe(inputs[1]); + userEvent.tab(); + expect(document.activeElement).toBe(inputs[0]); + }); + + test('pressing ESC dismisses', async () => { + const handleDismiss = jest.fn(); + const ref = createRef(); + render( +
+
+ + + +
+ ); + + const dialog = screen.queryByRole('dialog'); + expect(dialog).toBeInTheDocument(); + + fireEvent.keyDown(document.activeElement, { key: 'Escape', code: 'Escape' }); + expect(handleDismiss).toHaveBeenCalled(); + }); + + test('clicking a scrim dismisses', async () => { + const handleDismiss = jest.fn(); + const ref = createRef(); + render( +
+
+ + + +
+ ); + + fireEvent.click(screen.queryByTestId('scrim')); + expect(handleDismiss).toHaveBeenCalled(); + }); +});