import { render, screen, fireEvent } from '../../../tests/helpers/render';
import userEvent from '@testing-library/user-event';
import Modal from './Modal';
import { lockBodyScroll, resetBodyScrollLock } from '../../utils/bodyScrollLock';
describe('Modal', () => {
const onClose = vi.fn();
beforeEach(() => {
onClose.mockClear();
resetBodyScrollLock();
document.body.style.overflow = '';
});
it('FE-COMP-MODAL-001: does not render when isOpen is false', () => {
render(content
);
expect(screen.queryByText('content')).toBeNull();
});
it('FE-COMP-MODAL-002: renders overlay when isOpen is true', () => {
render(content
);
expect(screen.getByText('content')).toBeTruthy();
});
it('FE-COMP-MODAL-003: renders the title prop', () => {
render();
expect(screen.getByText('My Modal Title')).toBeTruthy();
});
it('FE-COMP-MODAL-004: renders children content', () => {
render(Hello World
);
expect(screen.getByText('Hello World')).toBeTruthy();
});
it('FE-COMP-MODAL-005: renders footer prop', () => {
render(
Save}>
body
);
expect(screen.getByRole('button', { name: 'Save' })).toBeTruthy();
});
it('FE-COMP-MODAL-006: close button calls onClose', async () => {
const user = userEvent.setup();
render();
// The X button is the only button rendered by Modal itself
const closeBtn = document.querySelector('button');
await user.click(closeBtn!);
expect(onClose).toHaveBeenCalledOnce();
});
it('FE-COMP-MODAL-007: Escape key calls onClose', () => {
render();
fireEvent.keyDown(document, { key: 'Escape' });
expect(onClose).toHaveBeenCalledOnce();
});
it('FE-COMP-MODAL-008: clicking the backdrop calls onClose', () => {
render(inner
);
const backdrop = document.querySelector('.trek-modal-backdrop') as HTMLElement;
// Simulate mousedown then click on the backdrop itself
fireEvent.mouseDown(backdrop, { target: backdrop });
fireEvent.click(backdrop);
expect(onClose).toHaveBeenCalledOnce();
});
it('FE-COMP-MODAL-009: clicking inside modal content does NOT call onClose', async () => {
const user = userEvent.setup();
render(inner content
);
await user.click(screen.getByText('inner content'));
expect(onClose).not.toHaveBeenCalled();
});
it('FE-COMP-MODAL-010: close button is hidden when hideCloseButton is true', () => {
render();
// No button should be present in the modal header
expect(document.querySelector('button')).toBeNull();
});
it('FE-COMP-MODAL-011: sets document.body overflow to hidden when open', () => {
render();
expect(document.body.style.overflow).toBe('hidden');
});
// #1809: the document is the scroller on a phone, so closing this modal must
// not unlock the page while another overlay is still holding the lock.
it('FE-COMP-MODAL-012: unmounting keeps a lock another overlay still holds', () => {
const otherOverlay = lockBodyScroll();
const { unmount } = render();
expect(document.body.style.overflow).toBe('hidden');
unmount();
expect(document.body.style.overflow).toBe('hidden');
otherOverlay();
expect(document.body.style.overflow).toBe('');
});
});