reactstrap
Version:
React Bootstrap components
849 lines (848 loc) • 35 kB
JavaScript
/* 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();
});
});