UNPKG

reactstrap

Version:
849 lines (848 loc) 35 kB
/* eslint-disable jsx-a11y/no-noninteractive-tabindex */ import React from 'react'; import { render, screen } from '@testing-library/react'; import user from '@testing-library/user-event'; import '@testing-library/jest-dom'; import { Modal, ModalBody, ModalHeader, ModalFooter, Button } from '..'; describe('Modal', function () { var toggle = function toggle() {}; beforeEach(function () { jest.useFakeTimers(); }); afterEach(function () { jest.clearAllTimers(); // rtl doesn't clear attributes added to body, so manually clearing them document.body.removeAttribute('style'); document.body.removeAttribute('class'); }); it('should render modal portal into DOM', function () { render( /*#__PURE__*/React.createElement(Modal, { isOpen: true, toggle: toggle }, "Yo!")); expect(screen.getByText(/yo/i)).toBeInTheDocument(); }); it('should render with the class "modal-dialog"', function () { render( /*#__PURE__*/React.createElement(Modal, { isOpen: true, toggle: toggle }, "Yo!")); expect(screen.getByText(/yo/i).parentElement).toHaveClass('modal-dialog'); }); it('should render external content when present', function () { render( /*#__PURE__*/React.createElement(Modal, { isOpen: true, toggle: toggle, external: /*#__PURE__*/React.createElement("button", { className: "cool-close-button" }, "crazy button") }, "Yo!")); expect(screen.getByText(/crazy button/i)).toBeInTheDocument(); expect(screen.getByText(/crazy button/i).nextElementSibling.className.split(' ').indexOf('modal-dialog') > -1).toBe(true); }); it('should render with the backdrop with the class "modal-backdrop" by default', function () { render( /*#__PURE__*/React.createElement(Modal, { isOpen: true, toggle: toggle }, "Yo!")); expect(document.getElementsByClassName('modal-backdrop').length).toBe(1); }); it('should render with the backdrop with the class "modal-backdrop" when backdrop is "static"', function () { render( /*#__PURE__*/React.createElement(Modal, { isOpen: true, toggle: toggle, backdrop: "static" }, "Yo!")); expect(document.getElementsByClassName('modal-backdrop').length).toBe(1); }); it('should not render with the backdrop with the class "modal-backdrop" when backdrop is "false"', function () { render( /*#__PURE__*/React.createElement(Modal, { isOpen: true, toggle: toggle, backdrop: false }, "Yo!")); expect(document.getElementsByClassName('modal-dialog').length).toBe(1); expect(document.getElementsByClassName('modal-backdrop').length).toBe(0); }); it('should render with the class "modal-dialog-scrollable" when scrollable is "true"', function () { render( /*#__PURE__*/React.createElement(Modal, { isOpen: true, toggle: toggle, scrollable: true }, "Yo!")); expect(document.getElementsByClassName('modal-dialog-scrollable').length).toBe(1); }); it('should render with class "modal-dialog" and have custom class name if provided', function () { render( /*#__PURE__*/React.createElement(Modal, { isOpen: true, toggle: toggle, className: "my-custom-modal" }, "Yo!")); expect(document.getElementsByClassName('modal-dialog').length).toBe(1); expect(document.getElementsByClassName('my-custom-modal').length).toBe(1); }); it('should render with class "modal-dialog" w/o centered class if not provided', function () { render( /*#__PURE__*/React.createElement(Modal, { isOpen: true, toggle: toggle }, "Yo!")); jest.advanceTimersByTime(300); expect(document.getElementsByClassName('modal-dialog').length).toBe(1); expect(document.getElementsByClassName('modal-dialog-centered').length).toBe(0); }); it('should render with class "modal-dialog" and centered class if provided', function () { render( /*#__PURE__*/React.createElement(Modal, { isOpen: true, toggle: toggle, centered: true }, "Yo!")); expect(document.getElementsByClassName('modal-dialog').length).toBe(1); expect(document.getElementsByClassName('modal-dialog-centered').length).toBe(1); }); describe('fullscreen', function () { it('should render non fullscreen by default', function () { render( /*#__PURE__*/React.createElement(Modal, { isOpen: true, toggle: toggle }, "Yo!")); expect(document.getElementsByClassName('modal-dialog').length).toBe(1); expect(document.getElementsByClassName('modal-fullscreen').length).toBe(0); }); it('should always render fullscreen if true', function () { render( /*#__PURE__*/React.createElement(Modal, { isOpen: true, toggle: toggle, fullscreen: true }, "Yo!")); expect(document.getElementsByClassName('modal-dialog').length).toBe(1); expect(document.getElementsByClassName('modal-fullscreen').length).toBe(1); }); it('should render fullscreen below breakpoint if breakpoint is provided', function () { render( /*#__PURE__*/React.createElement(Modal, { isOpen: true, toggle: toggle, fullscreen: "lg" }, "Yo!")); expect(document.getElementsByClassName('modal-dialog').length).toBe(1); expect(document.getElementsByClassName('modal-fullscreen').length).toBe(0); expect(document.getElementsByClassName('modal-fullscreen-lg-down').length).toBe(1); }); }); it('should render with additional props if provided', function () { render( /*#__PURE__*/React.createElement(Modal, { isOpen: true, toggle: toggle, style: { maxWidth: '95%' } }, "Yo!")); expect(document.getElementsByClassName('modal-dialog').length).toBe(1); expect(document.getElementsByClassName('modal-dialog')[0].style.maxWidth).toBe('95%'); }); it('should render without fade transition if provided with fade={false}', function () { render( /*#__PURE__*/React.createElement(Modal, { isOpen: true, toggle: toggle, fade: false, modalClassName: "fadeless-modal" }, "Howdy!")); var matchedModals = document.getElementsByClassName('fadeless-modal'); var matchedModal = matchedModals[0]; expect(matchedModals.length).toBe(1); // Modal should not have the 'fade' class expect(matchedModal.className.split(' ').indexOf('fade') < 0).toBe(true); }); it('should render when expected when passed modalTransition and backdropTransition props', function () { render( /*#__PURE__*/React.createElement(Modal, { isOpen: true, toggle: toggle, modalTransition: { timeout: 2 }, backdropTransition: { timeout: 10 }, modalClassName: "custom-timeout-modal" }, "Hello, world!")); expect(document.getElementsByClassName('custom-timeout-modal').length).toBe(1); }); it('should render with class "modal" and have custom class name if provided with modalClassName', function () { render( /*#__PURE__*/React.createElement(Modal, { isOpen: true, toggle: toggle, modalClassName: "my-custom-modal" }, "Yo!")); expect(document.querySelectorAll('.modal.my-custom-modal').length).toBe(1); }); it('should render with custom class name if provided with wrapClassName', function () { render( /*#__PURE__*/React.createElement(Modal, { isOpen: true, toggle: toggle, wrapClassName: "my-custom-modal" }, "Yo!")); expect(document.getElementsByClassName('my-custom-modal').length).toBe(1); }); it('should render with class "modal-content" and have custom class name if provided with contentClassName', function () { render( /*#__PURE__*/React.createElement(Modal, { isOpen: true, toggle: toggle, contentClassName: "my-custom-modal" }, "Yo!")); expect(document.querySelectorAll('.modal-content.my-custom-modal').length).toBe(1); }); it('should render with class "modal-backdrop" and have custom class name if provided with backdropClassName', function () { render( /*#__PURE__*/React.createElement(Modal, { isOpen: true, toggle: toggle, backdropClassName: "my-custom-modal" }, "Yo!")); expect(document.querySelectorAll('.modal-backdrop.my-custom-modal').length).toBe(1); }); it('should render with the class "modal-${size}" when size is passed', function () { render( /*#__PURE__*/React.createElement(Modal, { isOpen: true, toggle: toggle, size: "crazy" }, "Yo!")); expect(document.getElementsByClassName('modal-dialog').length).toBe(1); expect(document.getElementsByClassName('modal-crazy').length).toBe(1); }); it('should render modal when isOpen is true', function () { render( /*#__PURE__*/React.createElement(Modal, { isOpen: true, toggle: toggle }, "Yo!")); expect(document.getElementsByClassName('modal').length).toBe(1); expect(document.getElementsByClassName('modal-backdrop').length).toBe(1); }); it('should render modal with default role of "dialog"', function () { render( /*#__PURE__*/React.createElement(Modal, { isOpen: true, toggle: toggle }, "Yo!")); expect(document.getElementsByClassName('modal')[0].getAttribute('role')).toBe('dialog'); }); it('should render modal with provided role', function () { render( /*#__PURE__*/React.createElement(Modal, { isOpen: true, toggle: toggle, role: "alert" }, "Yo!")); expect(document.getElementsByClassName('modal')[0].getAttribute('role')).toBe('alert'); }); it('should render modal with aria-labelledby provided labelledBy', function () { render( /*#__PURE__*/React.createElement(Modal, { isOpen: true, toggle: toggle, labelledBy: "myModalTitle" }, "Yo!")); expect(document.getElementsByClassName('modal')[0].getAttribute('aria-labelledby')).toBe('myModalTitle'); }); it('should not render modal when isOpen is false', function () { render( /*#__PURE__*/React.createElement(Modal, { isOpen: false, toggle: toggle }, "Yo!")); expect(document.getElementsByClassName('modal').length).toBe(0); expect(document.getElementsByClassName('modal-backdrop').length).toBe(0); }); it('should toggle modal', function () { var _render = render( /*#__PURE__*/React.createElement(Modal, { isOpen: false, toggle: toggle }, "Yo!")), rerender = _render.rerender; expect(document.getElementsByClassName('modal').length).toBe(0); expect(document.getElementsByClassName('modal-backdrop').length).toBe(0); rerender( /*#__PURE__*/React.createElement(Modal, { isOpen: true, toggle: toggle }, "Yo!")); expect(document.getElementsByClassName('modal').length).toBe(1); expect(document.getElementsByClassName('modal-backdrop').length).toBe(1); }); it('should call onClosed & onOpened', function () { var onOpened = jest.fn(); var onClosed = jest.fn(); var _render2 = render( /*#__PURE__*/React.createElement(Modal, { isOpen: false, onOpened: onOpened, onClosed: onClosed, toggle: toggle }, "Yo!")), rerender = _render2.rerender; expect(onOpened).not.toHaveBeenCalled(); expect(onClosed).not.toHaveBeenCalled(); rerender( /*#__PURE__*/React.createElement(Modal, { isOpen: true, onOpened: onOpened, onClosed: onClosed, toggle: toggle }, "Yo!")); jest.advanceTimersByTime(300); expect(onOpened).toHaveBeenCalledTimes(1); rerender( /*#__PURE__*/React.createElement(Modal, { isOpen: false, onOpened: onOpened, onClosed: onClosed, toggle: toggle }, "Yo!")); jest.advanceTimersByTime(300); expect(onOpened).toHaveBeenCalledTimes(1); expect(onClosed).toHaveBeenCalledTimes(1); }); it('should call onClosed & onOpened when fade={false}', function () { var onOpened = jest.fn(); var onClosed = jest.fn(); var _render3 = render( /*#__PURE__*/React.createElement(Modal, { isOpen: false, onOpened: onOpened, onClosed: onClosed, toggle: toggle, fade: false }, "Yo!")), rerender = _render3.rerender; expect(onOpened).not.toHaveBeenCalled(); expect(onClosed).not.toHaveBeenCalled(); rerender( /*#__PURE__*/React.createElement(Modal, { isOpen: true, onOpened: onOpened, onClosed: onClosed, toggle: toggle, fade: false }, "Yo!")); jest.advanceTimersByTime(1); expect(onOpened).toHaveBeenCalledTimes(1); expect(onClosed).not.toHaveBeenCalled(); rerender( /*#__PURE__*/React.createElement(Modal, { isOpen: false, onOpened: onOpened, onClosed: onClosed, toggle: toggle, fade: false }, "Yo!")); jest.advanceTimersByTime(1); expect(onClosed).toHaveBeenCalledTimes(1); expect(onOpened).toHaveBeenCalledTimes(1); }); it('should call toggle when escape key pressed and not for enter key', function () { var toggle = jest.fn(); render( /*#__PURE__*/React.createElement(Modal, { isOpen: true, toggle: toggle }, "Yo!")); user.keyboard('{enter}'); expect(toggle).not.toHaveBeenCalled(); user.keyboard('{esc}'); expect(toggle).toHaveBeenCalled(); }); it('should not call toggle when escape key pressed when keyboard is false', function () { var toggle = jest.fn(); render( /*#__PURE__*/React.createElement(Modal, { isOpen: true, toggle: toggle, keyboard: false }, "Yo!")); user.keyboard('{esc}'); expect(toggle).not.toHaveBeenCalled(); }); it('should call toggle when clicking backdrop', function () { var toggle = jest.fn(); render( /*#__PURE__*/React.createElement(Modal, { isOpen: true, toggle: toggle }, /*#__PURE__*/React.createElement("button", { id: "clicker" }, "Does Nothing"))); user.click(screen.getByText(/does nothing/i)); expect(toggle).not.toHaveBeenCalled(); user.click(document.body.getElementsByClassName('modal')[0]); expect(toggle).toHaveBeenCalled(); }); it('should not call toggle when clicking backdrop and backdrop is "static"', function () { var toggle = jest.fn(); render( /*#__PURE__*/React.createElement(Modal, { isOpen: true, toggle: toggle, backdrop: "static" }, /*#__PURE__*/React.createElement("button", { id: "clicker" }, "Does Nothing"))); user.click(document.getElementsByClassName('modal-backdrop')[0]); expect(toggle).not.toHaveBeenCalled(); }); it('should not call toggle when escape key pressed and backdrop is "static" and keyboard=false', function () { var toggle = jest.fn(); render( /*#__PURE__*/React.createElement(Modal, { isOpen: true, toggle: toggle, backdrop: "static", keyboard: false }, "Yo!")); user.keyboard('{esc}'); expect(toggle).not.toHaveBeenCalled(); }); it('should call toggle when escape key pressed and backdrop is "static" and keyboard=true', function () { var toggle = jest.fn(); render( /*#__PURE__*/React.createElement(Modal, { isOpen: true, toggle: toggle, backdrop: "static", keyboard: true }, /*#__PURE__*/React.createElement("button", { id: "clicker" }, "Does Nothing"))); user.keyboard('{esc}'); expect(toggle).toHaveBeenCalled(); }); it('should animate when backdrop is "static" and escape key pressed and keyboard=false', function () { render( /*#__PURE__*/React.createElement(Modal, { isOpen: true, toggle: toggle, backdrop: "static", keyboard: false, "data-testid": "mandalorian" }, /*#__PURE__*/React.createElement("button", { id: "clicker" }, "Does Nothing"))); user.keyboard('{esc}'); expect(screen.getByTestId('mandalorian').parentElement).toHaveClass('modal-static'); jest.advanceTimersByTime(300); expect(screen.getByTestId('mandalorian').parentElement).not.toHaveClass('modal-static'); }); it('should animate when backdrop is "static" and backdrop is clicked', function () { render( /*#__PURE__*/React.createElement(Modal, { isOpen: true, toggle: toggle, backdrop: "static", "data-testid": "mandalorian" }, /*#__PURE__*/React.createElement("button", { id: "clicker" }, "Does Nothing"))); user.click(document.getElementsByClassName('modal')[0]); expect(screen.getByTestId('mandalorian').parentElement).toHaveClass('modal-static'); jest.advanceTimersByTime(300); expect(screen.getByTestId('mandalorian').parentElement).not.toHaveClass('modal-static'); }); it('should not animate when backdrop is "static" and modal is clicked', function () { render( /*#__PURE__*/React.createElement(Modal, { isOpen: true, toggle: toggle, backdrop: "static", "data-testid": "mandalorian" }, /*#__PURE__*/React.createElement("button", { id: "clicker" }, "Does Nothing"))); user.click(document.getElementsByClassName('modal-dialog')[0]); expect(screen.getByTestId('mandalorian').parentElement).not.toHaveClass('modal-static'); }); it('should destroy this._element', function () { var _render4 = render( /*#__PURE__*/React.createElement(Modal, { isOpen: true, toggle: toggle, wrapClassName: "weird-class" }, /*#__PURE__*/React.createElement("button", { id: "clicker" }, "Does Nothing"))), rerender = _render4.rerender; var element = document.getElementsByClassName('weird-class')[0].parentElement; expect(element).toBeInTheDocument(); rerender( /*#__PURE__*/React.createElement(Modal, { isOpen: false, toggle: toggle, wrapClassName: "weird-class" }, /*#__PURE__*/React.createElement("button", { id: "clicker" }, "Does Nothing"))); jest.advanceTimersByTime(300); expect(element).not.toBeInTheDocument(); }); it('should destroy this._element when unmountOnClose prop set to true', function () { var _render5 = render( /*#__PURE__*/React.createElement(Modal, { isOpen: true, toggle: toggle, unmountOnClose: true, wrapClassName: "weird-class" }, /*#__PURE__*/React.createElement("button", { id: "clicker" }, "Does Nothing"))), rerender = _render5.rerender; var element = document.getElementsByClassName('weird-class')[0].parentElement; expect(element).toBeInTheDocument(); rerender( /*#__PURE__*/React.createElement(Modal, { isOpen: false, toggle: toggle, unmountOnClose: true, wrapClassName: "weird-class" }, /*#__PURE__*/React.createElement("button", { id: "clicker" }, "Does Nothing"))); jest.advanceTimersByTime(300); expect(element).not.toBeInTheDocument(); }); it('should not destroy this._element when unmountOnClose prop set to false', function () { var _render6 = render( /*#__PURE__*/React.createElement(Modal, { isOpen: true, toggle: toggle, unmountOnClose: false, wrapClassName: "weird-class" }, /*#__PURE__*/React.createElement("button", { id: "clicker" }, "Does Nothing"))), rerender = _render6.rerender; var element = document.getElementsByClassName('weird-class')[0].parentElement; expect(element).toBeInTheDocument(); rerender( /*#__PURE__*/React.createElement(Modal, { isOpen: false, toggle: toggle, unmountOnClose: false, wrapClassName: "weird-class" }, /*#__PURE__*/React.createElement("button", { id: "clicker" }, "Does Nothing"))); expect(element).toBeInTheDocument(); }); it('should destroy this._element on unmount', function () { var _render7 = render( /*#__PURE__*/React.createElement(Modal, { isOpen: true, toggle: toggle, wrapClassName: "weird-class" }, /*#__PURE__*/React.createElement("button", { id: "clicker" }, "Does Nothing"))), unmount = _render7.unmount; unmount(); jest.advanceTimersByTime(300); expect(document.getElementsByClassName('modal').length).toBe(0); }); it('should render nested modals', function () { var _render8 = render( /*#__PURE__*/React.createElement(Modal, { isOpen: true, toggle: toggle }, /*#__PURE__*/React.createElement(ModalBody, null, /*#__PURE__*/React.createElement(Modal, { isOpen: true, toggle: function toggle() {} }, "Yo!")))), unmount = _render8.unmount; expect(document.getElementsByClassName('modal-dialog').length).toBe(2); expect(document.body.className).toBe('modal-open'); unmount(); expect(document.getElementsByClassName('modal-dialog').length).toBe(0); }); it('should remove exactly modal-open class from body', function () { // set a body class which includes modal-open document.body.className = 'my-modal-opened'; var _render9 = render( /*#__PURE__*/React.createElement(Modal, { isOpen: false, toggle: toggle }, "Yo!")), rerender = _render9.rerender; expect(document.body.className).toBe('my-modal-opened'); rerender( /*#__PURE__*/React.createElement(Modal, { isOpen: true, toggle: toggle }, "Yo!")); expect(document.body.className).toBe('my-modal-opened modal-open'); // using this to test if replace will leave a space when removing modal-open document.body.className += ' modal-opened'; expect(document.body.className).toBe('my-modal-opened modal-open modal-opened'); rerender( /*#__PURE__*/React.createElement(Modal, { isOpen: false, toggle: toggle }, "Yo!")); jest.advanceTimersByTime(300); expect(document.body.className).toBe('my-modal-opened modal-opened'); }); it('should call onEnter & onExit props if provided', function () { var onEnter = jest.fn(); var onExit = jest.fn(); var _render10 = render( /*#__PURE__*/React.createElement(Modal, { isOpen: false, onEnter: onEnter, onExit: onExit, toggle: toggle }, "Yo!")), rerender = _render10.rerender, unmount = _render10.unmount; expect(onEnter).toHaveBeenCalled(); expect(onExit).not.toHaveBeenCalled(); onEnter.mockReset(); onExit.mockReset(); rerender( /*#__PURE__*/React.createElement(Modal, { isOpen: true, onEnter: onEnter, onExit: onExit, toggle: toggle }, "Yo!")); expect(onEnter).not.toHaveBeenCalled(); expect(onExit).not.toHaveBeenCalled(); onEnter.mockReset(); onExit.mockReset(); rerender( /*#__PURE__*/React.createElement(Modal, { isOpen: false, onEnter: onEnter, onExit: onExit, toggle: toggle }, "Yo!")); unmount(); expect(onEnter).not.toHaveBeenCalled(); expect(onExit).toHaveBeenCalled(); }); it('should update element z index when prop changes', function () { var _render11 = render( /*#__PURE__*/React.createElement(Modal, { isOpen: true, zIndex: 0, wrapClassName: "sandman" }, "Yo!")), rerender = _render11.rerender; expect(document.getElementsByClassName('sandman')[0].parentElement.style.zIndex).toBe('0'); rerender( /*#__PURE__*/React.createElement(Modal, { isOpen: true, zIndex: 1, wrapClassName: "sandman" }, "Yo!")); expect(document.getElementsByClassName('sandman')[0].parentElement.style.zIndex).toBe('1'); }); it('should allow focus on only focusable elements and tab through them', function () { render( /*#__PURE__*/React.createElement(Modal, { isOpen: true, toggle: toggle }, /*#__PURE__*/React.createElement(ModalHeader, { toggle: toggle }, "Modal title"), /*#__PURE__*/React.createElement(ModalBody, null, /*#__PURE__*/React.createElement("a", { alt: "test", href: "/" }, "First Test"), /*#__PURE__*/React.createElement("map", { name: "test" }, /*#__PURE__*/React.createElement("area", { alt: "test", href: "/", coords: "200,5,200,30" })), /*#__PURE__*/React.createElement("input", { type: "text", "aria-label": "test text input" }), /*#__PURE__*/React.createElement("input", { type: "hidden" }), /*#__PURE__*/React.createElement("input", { type: "text", disabled: true, value: "Test" }), /*#__PURE__*/React.createElement("select", { name: "test", id: "select_test" }, /*#__PURE__*/React.createElement("option", null, "Second item")), /*#__PURE__*/React.createElement("select", { name: "test", id: "select_test_disabled", disabled: true }, /*#__PURE__*/React.createElement("option", null, "Third item")), /*#__PURE__*/React.createElement("textarea", { name: "textarea_test", id: "textarea_test", cols: "30", rows: "10", "aria-label": "test text area" }), /*#__PURE__*/React.createElement("textarea", { name: "textarea_test_disabled", id: "textarea_test_disabled", cols: "30", rows: "10", disabled: true }), /*#__PURE__*/React.createElement("object", null, "Test"), /*#__PURE__*/React.createElement("span", { tabIndex: "0" }, "test tab index")), /*#__PURE__*/React.createElement(ModalFooter, null, /*#__PURE__*/React.createElement(Button, { disabled: true, color: "primary", onClick: toggle }, "Do Something"), ' ', /*#__PURE__*/React.createElement(Button, { color: "secondary", onClick: toggle }, "Cancel")))); user.tab(); expect(screen.getByLabelText(/close/i)).toHaveFocus(); user.tab(); expect(screen.getByText(/first test/i)).toHaveFocus(); user.tab(); expect(screen.getByLabelText(/test text input/i)).toHaveFocus(); user.tab(); expect(screen.getByText(/second item/i).parentElement).toHaveFocus(); user.tab(); expect(screen.getByLabelText(/test text area/i)).toHaveFocus(); user.tab(); expect(screen.getByText(/test tab index/i)).toHaveFocus(); user.tab(); expect(screen.getByText(/cancel/i)).toHaveFocus(); user.tab(); expect(screen.getByLabelText(/close/i)).toHaveFocus(); }); it('should return the focus to the last focused element before the modal has opened', function () { var _render12 = render( /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("button", { className: "focus" }, "Focused"), /*#__PURE__*/React.createElement(Modal, { isOpen: false }, /*#__PURE__*/React.createElement(ModalBody, null, "Whatever")))), rerender = _render12.rerender; user.tab(); expect(screen.getByText(/focused/i)).toHaveFocus(); rerender( /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("button", { className: "focus" }, "Focused"), /*#__PURE__*/React.createElement(Modal, { isOpen: true }, /*#__PURE__*/React.createElement(ModalBody, null, "Whatever")))); rerender( /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("button", { className: "focus" }, "Focused"), /*#__PURE__*/React.createElement(Modal, { isOpen: false }, /*#__PURE__*/React.createElement(ModalBody, null, "Whatever")))); jest.runAllTimers(); expect(screen.getByText(/focused/i)).toHaveFocus(); }); it('should not return the focus to the last focused element before the modal has opened when "returnFocusAfterClose" is false', function () { var _render13 = render( /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("button", { className: "focus" }, "Focused"), /*#__PURE__*/React.createElement(Modal, { returnFocusAfterClose: false, isOpen: false }, /*#__PURE__*/React.createElement(ModalBody, null, "Whatever")))), rerender = _render13.rerender; user.tab(); expect(screen.getByText(/focused/i)).toHaveFocus(); rerender( /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("button", { className: "focus" }, "Focused"), /*#__PURE__*/React.createElement(Modal, { returnFocusAfterClose: false, isOpen: true }, /*#__PURE__*/React.createElement(ModalBody, null, "Whatever")))); rerender( /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("button", { className: "focus" }, "Focused"), /*#__PURE__*/React.createElement(Modal, { returnFocusAfterClose: false, isOpen: false }, /*#__PURE__*/React.createElement(ModalBody, null, "Whatever")))); jest.runAllTimers(); expect(screen.getByText(/focused/i)).not.toHaveFocus(); }); it('should return the focus to the last focused element before the modal has opened when "unmountOnClose" is false', function () { var _render14 = render( /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("button", { className: "focus" }, "Focused"), /*#__PURE__*/React.createElement(Modal, { unmountOnClose: false, isOpen: false }, /*#__PURE__*/React.createElement(ModalBody, null, "Whatever")))), rerender = _render14.rerender; user.tab(); expect(screen.getByText(/focused/i)).toHaveFocus(); rerender( /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("button", { className: "focus" }, "Focused"), /*#__PURE__*/React.createElement(Modal, { unmountOnClose: false, isOpen: true }, /*#__PURE__*/React.createElement(ModalBody, null, "Whatever")))); rerender( /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("button", { className: "focus" }, "Focused"), /*#__PURE__*/React.createElement(Modal, { unmountOnClose: false, isOpen: false }, /*#__PURE__*/React.createElement(ModalBody, null, "Whatever")))); jest.runAllTimers(); expect(screen.getByText(/focused/i)).toHaveFocus(); }); it('should not return the focus to the last focused element before the modal has opened when "returnFocusAfterClose" is false and "unmountOnClose" is false', function () { var _render15 = render( /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("button", { className: "focus" }, "Focused"), /*#__PURE__*/React.createElement(Modal, { unmountOnClose: false, returnFocusAfterClose: false, isOpen: false }, /*#__PURE__*/React.createElement(ModalBody, null, "Whatever")))), rerender = _render15.rerender; user.tab(); expect(screen.getByText(/focused/i)).toHaveFocus(); rerender( /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("button", { className: "focus" }, "Focused"), /*#__PURE__*/React.createElement(Modal, { unmountOnClose: false, returnFocusAfterClose: false, isOpen: true }, /*#__PURE__*/React.createElement(ModalBody, null, "Whatever")))); rerender( /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("button", { className: "focus" }, "Focused"), /*#__PURE__*/React.createElement(Modal, { unmountOnClose: false, returnFocusAfterClose: false, isOpen: false }, /*#__PURE__*/React.createElement(ModalBody, null, "Whatever")))); jest.runAllTimers(); expect(screen.getByText(/focused/i)).not.toHaveFocus(); }); it('should attach/detach trapFocus for dialogs', function () { var addEventListener = jest.spyOn(document, 'addEventListener'); var removeEventListener = jest.spyOn(document, 'removeEventListener'); var _render16 = render( /*#__PURE__*/React.createElement(Modal, { isOpen: true }, /*#__PURE__*/React.createElement(ModalBody, null, /*#__PURE__*/React.createElement(Button, { className: "focus" }, "focusable element")))), unmount = _render16.unmount; expect(addEventListener).toHaveBeenCalledTimes(1); expect(addEventListener).toHaveBeenCalledWith('focus', expect.any(Function), true); unmount(); expect(removeEventListener).toHaveBeenCalledTimes(1); expect(removeEventListener).toHaveBeenCalledWith('focus', expect.any(Function), true); addEventListener.mockRestore(); removeEventListener.mockRestore(); }); it('should trap focus inside the open dialog', function () { var _render17 = render( /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Button, { className: "first" }, "Focused"), /*#__PURE__*/React.createElement(Modal, { isOpen: false, trapFocus: true }, /*#__PURE__*/React.createElement(ModalBody, null, "Something else to see", /*#__PURE__*/React.createElement(Button, { className: "focus" }, "focusable element"))))), rerender = _render17.rerender; screen.getByText(/focused/i).focus(); expect(screen.getByText(/focused/i)).toHaveFocus(); rerender( /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Button, { className: "first" }, "Focused"), /*#__PURE__*/React.createElement(Modal, { isOpen: true, trapFocus: true, "data-testid": "modal" }, /*#__PURE__*/React.createElement(ModalBody, null, "Something else to see", /*#__PURE__*/React.createElement(Button, { className: "focus" }, "focusable element"))))); jest.runAllTimers(); expect(screen.getByText(/focused/i)).not.toHaveFocus(); expect(screen.getByTestId('modal').parentElement).toHaveFocus(); // pressing tab shouldn't move focus outside the modal user.tab(); expect(screen.getByText(/focusable element/i)).toHaveFocus(); user.tab(); expect(screen.getByText(/focusable element/i)).toHaveFocus(); }); it('tab should focus on inside modal children for nested modal', function () { render( /*#__PURE__*/React.createElement(Modal, { isOpen: true, toggle: toggle }, /*#__PURE__*/React.createElement(ModalBody, null, /*#__PURE__*/React.createElement(Button, { className: "b0", onClick: toggle }, "Cancel"), /*#__PURE__*/React.createElement(Modal, { isOpen: true }, /*#__PURE__*/React.createElement(ModalBody, null, /*#__PURE__*/React.createElement(Button, { className: "b1" }, "Click 1")))))); user.tab(); expect(screen.getByText(/click 1/i)).toHaveFocus(); // pressing tab doesn't take focus out of inside modal user.tab(); expect(screen.getByText(/click 1/i)).toHaveFocus(); }); it('works with strict mode', function () { var spy = jest.spyOn(console, 'error'); render( /*#__PURE__*/React.createElement(React.StrictMode, null, /*#__PURE__*/React.createElement(Modal, { isOpen: true }, "Hello"))); expect(spy).not.toHaveBeenCalled(); }); });