import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import React from 'react';
import { describe, expect, it, vi } from 'vitest';
import { MdModal } from '../MdModal';
describe('MdModal', () => {
describe('rendering', () => {
it('renders when open is true', () => {
render(
Modal content
,
);
expect(screen.getByText('Test Modal')).toBeInTheDocument();
expect(screen.getByText('Modal content')).toBeInTheDocument();
});
it('does not render when open is false', () => {
render(
Modal content
,
);
expect(screen.queryByText('Test Modal')).not.toBeInTheDocument();
});
it('renders heading', () => {
render(
Content
,
);
expect(screen.getByText('My Heading')).toBeInTheDocument();
});
it('renders heading icon', () => {
render(
}>
Content
,
);
expect(screen.getByTestId('heading-icon')).toBeInTheDocument();
});
it('renders children', () => {
render(
Child content
,
);
expect(screen.getByTestId('child-content')).toBeInTheDocument();
});
it('renders footer', () => {
render(
Save}>
Content
,
);
expect(screen.getByRole('button', { name: 'Save' })).toBeInTheDocument();
});
it('renders close button', () => {
render(
Content
,
);
// Close button is the dismiss button within the modal
expect(screen.getByRole('button')).toBeInTheDocument();
});
});
describe('states', () => {
it('applies error class when error is true', () => {
const { baseElement } = render(
Content
,
);
expect(baseElement.querySelector('.md-modal--error')).toBeInTheDocument();
});
});
describe('dividers', () => {
it('renders header divider when headingDivider is true', () => {
const { baseElement } = render(
Content
,
);
expect(baseElement.querySelector('.md-modal__header-divider')).toBeInTheDocument();
});
it('renders footer divider when footerDivider is true', () => {
const { baseElement } = render(
OK} footerDivider>
Content
,
);
expect(baseElement.querySelector('.md-modal__footer-divider')).toBeInTheDocument();
});
});
describe('interactions', () => {
it('calls onClose when close button is clicked', async () => {
const user = userEvent.setup();
const onClose = vi.fn();
render(
Content
,
);
// Click the close button (the dismiss button)
const closeButton = screen.getByRole('button');
await user.click(closeButton);
expect(onClose).toHaveBeenCalled();
});
it('calls onClose when pressing Escape', async () => {
const user = userEvent.setup();
const onClose = vi.fn();
render(
Content
,
);
await user.keyboard('{Escape}');
expect(onClose).toHaveBeenCalled();
});
});
describe('props forwarding', () => {
it('applies custom className', () => {
const { baseElement } = render(
Content
,
);
expect(baseElement.querySelector('.md-modal')).toHaveClass('custom-modal');
});
it('applies contentClassName to content div', () => {
const { baseElement } = render(
Content
,
);
expect(baseElement.querySelector('.md-modal__content')).toHaveClass('custom-content');
});
it('forwards data-* attributes', () => {
render(
Content
,
);
expect(screen.getByTestId('my-modal')).toBeInTheDocument();
});
});
describe('accessibility', () => {
it('is a dialog role', () => {
render(
Content
,
);
expect(screen.getByRole('dialog')).toBeInTheDocument();
});
it('is modal by default', () => {
render(
Content
,
);
// ariakit Dialog uses modal prop which ensures proper modal behavior
// The aria-modal attribute may not be explicitly set but modal behavior is enforced
expect(screen.getByRole('dialog')).toBeInTheDocument();
});
});
});