Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
165 changes: 143 additions & 22 deletions frontend/__tests__/unit/components/Modal.test.tsx
Original file line number Diff line number Diff line change
@@ -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', () => {
Expand All @@ -21,6 +20,56 @@ jest.mock('components/ActionButton', () => ({ children, onClick }) => (
</button>
))

// Mock @heroui/modal components to avoid framer-motion issues
jest.mock('@heroui/modal', () => {
return {
Modal: ({ isOpen, children }: { isOpen: boolean; children: React.ReactNode }) =>
isOpen ? <dialog open>{children}</dialog> : null,
ModalContent: ({
children,
className,
...props
}: React.PropsWithChildren<{ className?: string } & Record<string, unknown>>) => (
<div className={className} {...props}>
{children}
</div>
),
ModalHeader: ({
children,
className,
...props
}: React.PropsWithChildren<{ className?: string } & Record<string, unknown>>) => (
<header className={className} {...props}>
{children}
</header>
),
ModalBody: ({ children, ...props }: React.PropsWithChildren<Record<string, unknown>>) => (
<div {...props}>{children}</div>
),
ModalFooter: ({
children,
className,
...props
}: React.PropsWithChildren<{ className?: string } & Record<string, unknown>>) => (
<footer className={className} {...props}>
{children}
</footer>
),
}
})

jest.mock('@heroui/button', () => ({
Button: ({
children,
onPress,
...props
}: React.PropsWithChildren<{ onPress?: () => void } & Record<string, unknown>>) => (
<button onClick={onPress} {...props}>
{children}
</button>
),
}))
Comment thread
coderabbitai[bot] marked this conversation as resolved.

describe('DialogComp', () => {
const mockOnClose = jest.fn()
const mockOnClick = jest.fn()
Expand All @@ -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(<DialogComp {...defaultProps} isOpen={false} />)

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(<DialogComp {...defaultProps} />)

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(<DialogComp {...defaultProps} />)
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(<DialogComp {...defaultProps} />)
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(<DialogComp {...defaultProps} hint={undefined} />)

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(
<DialogComp {...defaultProps}>
<div data-testid="child-content">Child Content</div>
</DialogComp>
)
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(<DialogComp {...defaultProps} />)
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(<DialogComp {...defaultProps} />)
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(<DialogComp {...minimalProps} />)
expect(screen.getByText('Minimal Title')).toBeInTheDocument()
expect(screen.getByText('Summary')).toBeInTheDocument()
expect(screen.getByText('Minimal Action')).toBeInTheDocument()
})

it('handles empty title, summary, description', () => {
render(<DialogComp {...defaultProps} title="" summary="" description="" />)
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(<DialogComp {...defaultProps} />)
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(<DialogComp {...defaultProps} />)
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(<DialogComp {...defaultProps} hint={null} />)
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(<DialogComp {...defaultProps} summary={markdownContent} hint={markdownContent} />)

const markdownElements = screen.getAllByTestId('markdown')
expect(markdownElements).toHaveLength(2)

markdownElements.forEach((element) => {
expect(element).toHaveClass('md-wrapper')
})
})
})