import { render, screen } from '@testing-library/react'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { Theme } from '@/types/app'
import IconWithTooltip from './icon-with-tooltip'
// Mock Tooltip component
vi.mock('@/app/components/base/tooltip', () => ({
default: ({
children,
popupContent,
popupClassName,
}: {
children: React.ReactNode
popupContent?: string
popupClassName?: string
}) => (
{children}
),
}))
// Mock icon components
const MockLightIcon = ({ className }: { className?: string }) => (
Light Icon
)
const MockDarkIcon = ({ className }: { className?: string }) => (
Dark Icon
)
describe('IconWithTooltip', () => {
beforeEach(() => {
vi.clearAllMocks()
})
describe('Rendering', () => {
it('should render without crashing', () => {
render(
,
)
expect(screen.getByTestId('tooltip')).toBeInTheDocument()
})
it('should render Tooltip wrapper', () => {
render(
,
)
expect(screen.getByTestId('tooltip')).toHaveAttribute('data-popup-content', 'Test tooltip')
})
it('should apply correct popupClassName to Tooltip', () => {
render(
,
)
const tooltip = screen.getByTestId('tooltip')
expect(tooltip).toHaveAttribute('data-popup-classname')
expect(tooltip.getAttribute('data-popup-classname')).toContain('border-components-panel-border')
})
})
describe('Theme Handling', () => {
it('should render light icon when theme is light', () => {
render(
,
)
expect(screen.getByTestId('light-icon')).toBeInTheDocument()
expect(screen.queryByTestId('dark-icon')).not.toBeInTheDocument()
})
it('should render dark icon when theme is dark', () => {
render(
,
)
expect(screen.getByTestId('dark-icon')).toBeInTheDocument()
expect(screen.queryByTestId('light-icon')).not.toBeInTheDocument()
})
it('should render light icon when theme is system (not dark)', () => {
render(
,
)
// When theme is not 'dark', it should use light icon
expect(screen.getByTestId('light-icon')).toBeInTheDocument()
})
})
describe('Props', () => {
it('should apply custom className to icon', () => {
render(
,
)
const icon = screen.getByTestId('light-icon')
expect(icon).toHaveClass('custom-class')
})
it('should apply default h-5 w-5 class to icon', () => {
render(
,
)
const icon = screen.getByTestId('light-icon')
expect(icon).toHaveClass('h-5')
expect(icon).toHaveClass('w-5')
})
it('should merge custom className with default classes', () => {
render(
,
)
const icon = screen.getByTestId('light-icon')
expect(icon).toHaveClass('h-5')
expect(icon).toHaveClass('w-5')
expect(icon).toHaveClass('ml-2')
})
it('should pass popupContent to Tooltip', () => {
render(
,
)
expect(screen.getByTestId('tooltip')).toHaveAttribute(
'data-popup-content',
'Custom tooltip content',
)
})
it('should handle undefined popupContent', () => {
render(
,
)
expect(screen.getByTestId('tooltip')).toBeInTheDocument()
})
})
describe('Memoization', () => {
it('should be wrapped with React.memo', () => {
// The component is exported as React.memo(IconWithTooltip)
expect(IconWithTooltip).toBeDefined()
// Check if it's a memo component
expect(typeof IconWithTooltip).toBe('object')
})
})
describe('Container Structure', () => {
it('should render icon inside flex container', () => {
const { container } = render(
,
)
const flexContainer = container.querySelector('.flex.shrink-0.items-center.justify-center')
expect(flexContainer).toBeInTheDocument()
})
})
describe('Edge Cases', () => {
it('should handle empty className', () => {
render(
,
)
expect(screen.getByTestId('light-icon')).toBeInTheDocument()
})
it('should handle long popupContent', () => {
const longContent = 'A'.repeat(500)
render(
,
)
expect(screen.getByTestId('tooltip')).toHaveAttribute('data-popup-content', longContent)
})
it('should handle special characters in popupContent', () => {
const specialContent = ' & "quotes"'
render(
,
)
expect(screen.getByTestId('tooltip')).toHaveAttribute('data-popup-content', specialContent)
})
})
})