/**
* Tests for the Modal component
* @jest-environment jsdom
*/
import React from 'react';
import { render, screen, fireEvent } from '@testing-library/react';
import { Modal } from '@/components/ui/Modal';
describe('Modal', () => {
const mockOnClose = jest.fn();
beforeEach(() => {
jest.clearAllMocks();
});
it('should not render when isOpen is false', () => {
const { container } = render(
Modal content
);
expect(container.firstChild).toBeNull();
});
it('should render when isOpen is true', () => {
render(
Modal content
);
expect(screen.getByText('Modal content')).toBeInTheDocument();
});
it('should render title when provided', () => {
render(
Content
);
expect(screen.getByText('Test Title')).toBeInTheDocument();
});
it('should render close button by default', () => {
render(
Content
);
expect(screen.getByLabelText('Fermer')).toBeInTheDocument();
});
it('should not render close button when showCloseButton is false', () => {
render(
Content
);
expect(screen.queryByLabelText('Fermer')).not.toBeInTheDocument();
});
it('should call onClose when close button is clicked', () => {
render(
Content
);
fireEvent.click(screen.getByLabelText('Fermer'));
expect(mockOnClose).toHaveBeenCalledTimes(1);
});
it('should call onClose when backdrop is clicked', () => {
render(
Content
);
// The dialog role is on the backdrop element itself
const backdrop = screen.getByRole('dialog');
fireEvent.click(backdrop);
expect(mockOnClose).toHaveBeenCalledTimes(1);
});
it('should not call onClose when modal content is clicked', () => {
render(
Content
);
fireEvent.click(screen.getByText('Content'));
expect(mockOnClose).not.toHaveBeenCalled();
});
it('should call onClose when Escape key is pressed', () => {
render(
Content
);
fireEvent.keyDown(document, { key: 'Escape' });
expect(mockOnClose).toHaveBeenCalledTimes(1);
});
it('should have dialog role', () => {
render(
Content
);
expect(screen.getByRole('dialog')).toBeInTheDocument();
});
it('should have aria-modal attribute', () => {
render(
Content
);
expect(screen.getByRole('dialog')).toHaveAttribute('aria-modal', 'true');
});
it('should apply sm size class', () => {
const { container } = render(
Content
);
expect(container.querySelector('.max-w-md')).toBeInTheDocument();
});
it('should apply md size class by default', () => {
const { container } = render(
Content
);
expect(container.querySelector('.max-w-lg')).toBeInTheDocument();
});
it('should apply lg size class', () => {
const { container } = render(
Content
);
expect(container.querySelector('.max-w-2xl')).toBeInTheDocument();
});
it('should apply xl size class', () => {
const { container } = render(
Content
);
expect(container.querySelector('.max-w-4xl')).toBeInTheDocument();
});
it('should set body overflow to hidden when open', () => {
render(
Content
);
expect(document.body.style.overflow).toBe('hidden');
});
it('should reset body overflow when closed', () => {
const { rerender } = render(
Content
);
rerender(
Content
);
expect(document.body.style.overflow).toBe('unset');
});
it('should have aria-labelledby when title is provided', () => {
render(
Content
);
const dialog = screen.getByRole('dialog');
expect(dialog).toHaveAttribute('aria-labelledby', 'modal-title');
});
it('should not have aria-labelledby when title is not provided', () => {
render(
Content
);
const dialog = screen.getByRole('dialog');
expect(dialog).not.toHaveAttribute('aria-labelledby');
});
});