import * as React from 'react'; import Dialog from './Dialog'; import DialogCloseButton from './DialogCloseButton'; import { render, fireEvent, waitForElementToBeRemoved, screen, } from '@testing-library/react'; import {waitFor} from '@storybook/testing-library'; import userEvent from '@testing-library/user-event'; import {testA11y} from '../../axe'; import DialogBody from './DialogBody'; import DialogHeader from './DialogHeader'; window.scrollTo = jest.fn(); describe('', () => { it('renders children', () => { const wrapper = render(content text); expect(wrapper.getByText('content text')).toBeTruthy(); }); it('fires onDismiss callback on Escape key', () => { const onDismiss = jest.fn(); const wrapper = render( content text ); // @ts-ignore TS2345 fireEvent.keyUp(wrapper.container.firstChild, { key: 'Escape', }); expect(onDismiss).toHaveBeenCalledTimes(1); }); it('fires onDismiss callback on Overlay click', () => { const onDismiss = jest.fn(); const wrapper = render( content text ); // @ts-ignore TS2345 fireEvent.click(wrapper.container.firstChild); expect(onDismiss).toHaveBeenCalledTimes(1); }); it('fires onEntryTransitionEnd callback on entry', () => { const onEntryTransitionEnd = jest.fn(); render( content text ); expect(onEntryTransitionEnd).toHaveBeenCalledTimes(1); }); it('fires onExitTransitionEnd callback on exit', () => { const onExitTransitionEnd = jest.fn(); const {rerender} = render( content text ); rerender( content text ); expect(onExitTransitionEnd).toHaveBeenCalledTimes(1); }); it('does not fire onEntryTransitionEnd callback before open', () => { const onEntryTransitionEnd = jest.fn(); render( content text ); expect(onEntryTransitionEnd).toHaveBeenCalledTimes(0); }); it('does not fire onExitTransitionEnd callback before open', () => { const onExitTransitionEnd = jest.fn(); render( content text ); expect(onExitTransitionEnd).toHaveBeenCalledTimes(0); }); it('returns null after exit transition', async () => { const dialog = render(content text); expect(dialog.container.firstElementChild).not.toBe(null); dialog.rerender(content text); await waitFor(() => expect(dialog.container.firstElementChild).toBe(null)); }); it('sets given zIndex', () => { const dialog = render( content text ); expect( (dialog.container.firstElementChild as HTMLElement).style.zIndex ).toEqual('10'); }); it('sets given data-testid to dialog', () => { const dialog = render( content text ); expect(dialog.getByTestId('test_id')).toBeTruthy(); }); it('sets given data-testid to dialog close button', () => { const dialog = render( ); expect(dialog.getByTestId('test_id')).toBeTruthy(); }); it('forces no-scroll class removal before onExitTransitionEnd callback', () => { const onExitTransitionEnd = () => { expect( document.body.classList.contains('sg-dialog-no-scroll') ).toBeFalsy(); }; const dialog = render( content text ); dialog.rerender( content text ); }); it('does not force no-scroll class removal before onEntryTransitionEnd callback', () => { const onEntryTransitionEnd = () => { expect( document.body.classList.contains('sg-dialog-no-scroll') ).toBeTruthy(); }; const dialog = render( content text ); dialog.rerender( content text ); }); it('has "dialog" role and aria-modal', async () => { const label = 'Dialog label'; const dialog = render( content text ); expect( dialog .getByRole('dialog', { name: label, }) .getAttribute('aria-modal') ).toBeTruthy(); }); it('is described by ', async () => { const descId = 'desc-id'; const dialog = render( {/*@ts-ignore to be fixed, dialog body doesn't expose id*/} Information you provide to us directly. ); await testA11y(dialog.container); expect(dialog.getByRole('dialog').getAttribute('aria-describedby')).toEqual( descId ); }); it('moves focus to first tabbable element when opens', async () => { const buttonText = 'button'; const dialog = render( ); expect(dialog.getByText(buttonText)).toEqual(document.activeElement); }); it('has focus when it opens and there are no children', async () => { const dialog = render( content text ); expect(dialog.getByRole('dialog')).toEqual(document.activeElement); }); it('closes on Esc key', () => { const dialog = render(content text); userEvent.keyboard('{esc}'); waitForElementToBeRemoved(dialog.queryByRole('dialog')); }); it('blocks user interaction outside dialog and closes dialog on click outside', () => { const buttonText = 'label'; const dialog = render(
content text
); userEvent.click(dialog.getByText(buttonText)); waitForElementToBeRemoved(dialog.queryByRole('dialog')); }); it('handles escape key for nested Dialogs', () => { // TODO: improve this test to adhere to react-testing-library standards // so to check modal visibility instead of onDismiss callback const onDismissOuter = jest.fn(); const onDismissInner = jest.fn(); render( Inner content ); screen.getByText('Inner content').focus(); userEvent.keyboard('{esc}'); expect(onDismissInner).toBeCalled(); expect(onDismissOuter).not.toBeCalled(); }); describe('a11y', () => { it('renders with , and ', async () => { const headerId = 'header-id'; const onDismiss = jest.fn(); await testA11y( Header Information you provide to us directly. ); }); }); });