diff --git a/frontend/__tests__/unit/components/Modal.test.tsx b/frontend/__tests__/unit/components/Modal.test.tsx index 9b57dae1f7..fded18b0c4 100644 --- a/frontend/__tests__/unit/components/Modal.test.tsx +++ b/frontend/__tests__/unit/components/Modal.test.tsx @@ -1,8 +1,7 @@ import { faCheck } from '@fortawesome/free-solid-svg-icons' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' -import { fireEvent, screen, waitFor } from '@testing-library/react' -import { render } from 'wrappers/testUtil' -import '@testing-library/jest-dom' +import { render, screen, fireEvent } from '@testing-library/react' +import React from 'react' import DialogComp from 'components/Modal' jest.mock('@/components/MarkdownWrapper', () => { @@ -21,6 +20,56 @@ jest.mock('components/ActionButton', () => ({ children, onClick }) => ( )) +// Mock @heroui/modal components to avoid framer-motion issues +jest.mock('@heroui/modal', () => { + return { + Modal: ({ isOpen, children }: { isOpen: boolean; children: React.ReactNode }) => + isOpen ? {children} : null, + ModalContent: ({ + children, + className, + ...props + }: React.PropsWithChildren<{ className?: string } & Record>) => ( +
+ {children} +
+ ), + ModalHeader: ({ + children, + className, + ...props + }: React.PropsWithChildren<{ className?: string } & Record>) => ( +
+ {children} +
+ ), + ModalBody: ({ children, ...props }: React.PropsWithChildren>) => ( +
{children}
+ ), + ModalFooter: ({ + children, + className, + ...props + }: React.PropsWithChildren<{ className?: string } & Record>) => ( +
+ {children} +
+ ), + } +}) + +jest.mock('@heroui/button', () => ({ + Button: ({ + children, + onPress, + ...props + }: React.PropsWithChildren<{ onPress?: () => void } & Record>) => ( + + ), +})) + describe('DialogComp', () => { const mockOnClose = jest.fn() const mockOnClick = jest.fn() @@ -43,54 +92,126 @@ describe('DialogComp', () => { beforeEach(() => { jest.clearAllMocks() }) + afterEach(() => { jest.clearAllMocks() jest.restoreAllMocks() }) - test('does not render when isOpen is false', async () => { + it('does not render modal content when isOpen is false', () => { render() - - await waitFor(() => expect(screen.queryByText('Test Title')).not.toBeInTheDocument()) + expect(screen.queryByText('Test Title')).not.toBeInTheDocument() }) - test('renders summary section correctly', async () => { + it('renders modal with title and description correctly', () => { render() - - await waitFor(() => expect(screen.getByText('Summary')).toBeInTheDocument()) + expect(screen.getByText('Test Title')).toBeInTheDocument() + expect(screen.getByText('Test Description')).toBeInTheDocument() }) - test('renders hint section when hint prop is provided', async () => { + it('renders summary section correctly', () => { render() + expect(screen.getByText('Summary')).toBeInTheDocument() + const markdownElements = screen.getAllByTestId('markdown') + expect(markdownElements.length).toBeGreaterThan(0) + }) - await waitFor(() => expect(screen.getByText('How to tackle it')).toBeInTheDocument()) + it('renders hint section when hint prop is provided', () => { + render() + expect(screen.getByText('How to tackle it')).toBeInTheDocument() + const markdownElements = screen.getAllByTestId('markdown') + expect(markdownElements).toHaveLength(2) }) - test('does not render hint section when hint prop is not provided', async () => { + it('does not render hint section when hint prop is not provided', () => { render() - - await waitFor(() => expect(screen.queryByText('How to tackle it')).not.toBeInTheDocument()) + expect(screen.queryByText('How to tackle it')).not.toBeInTheDocument() + const markdownElements = screen.getAllByTestId('markdown') + expect(markdownElements).toHaveLength(1) }) - test('renders children content when provided', async () => { + it('renders children content when provided', () => { render(
Child Content
) + expect(screen.getByTestId('child-content')).toBeInTheDocument() + expect(screen.getByText('Child Content')).toBeInTheDocument() + }) - await waitFor(() => { - expect(screen.getByTestId('child-content')).toBeInTheDocument() - expect(screen.getByText('Child Content')).toBeInTheDocument() - }) + it('calls onClose when close button is clicked', () => { + render() + const closeButton = screen.getByRole('button', { name: /close/i }) + fireEvent.click(closeButton) + expect(mockOnClose).toHaveBeenCalledTimes(1) + }) + + it('renders action button when button prop is provided', () => { + render() + expect(screen.getByTestId('action-button')).toBeInTheDocument() + expect(screen.getByText('Action')).toBeInTheDocument() + }) + + it('renders with minimal required props', () => { + const minimalProps = { + title: 'Minimal Title', + summary: 'Minimal Summary', + isOpen: true, + onClose: mockOnClose, + description: '', + button: { + label: 'Minimal Action', + icon: null, + url: '', + onPress: mockOnClick, + }, + } + + render() + expect(screen.getByText('Minimal Title')).toBeInTheDocument() + expect(screen.getByText('Summary')).toBeInTheDocument() + expect(screen.getByText('Minimal Action')).toBeInTheDocument() + }) + + it('handles empty title, summary, description', () => { + render() + expect(screen.getByRole('dialog')).toBeInTheDocument() + expect(screen.getByText('Summary')).toBeInTheDocument() }) - test('calls onClose when close button is clicked', async () => { + it('has correct accessibility attributes', () => { render() + const modal = screen.getByRole('dialog') + expect(modal).toBeInTheDocument() const closeButton = screen.getByText('Close') - fireEvent.click(closeButton) + expect(closeButton).toHaveAttribute('aria-label', 'close-modal') + }) + + it('renders important classNames and DOM structure', () => { + render() + expect(document.querySelector('.animate-scaleIn')).toBeInTheDocument() + expect(document.querySelector('.font-bold')).toBeInTheDocument() + expect(document.querySelector('.flex.justify-end')).toBeInTheDocument() + }) + + it('handles null hint prop', () => { + render() + expect(screen.getByText('Summary')).toBeInTheDocument() + expect(screen.queryByText('How to tackle it')).not.toBeInTheDocument() + }) - await waitFor(() => expect(mockOnClose).toHaveBeenCalledTimes(1)) + it('renders markdown content correctly', () => { + const markdownContent = '**Bold text** and *italic text*' + + render() + + const markdownElements = screen.getAllByTestId('markdown') + expect(markdownElements).toHaveLength(2) + + markdownElements.forEach((element) => { + expect(element).toHaveClass('md-wrapper') + }) }) })