Files
Charon/frontend/src/components/ui/__tests__/Alert.test.tsx
GitHub Actions 3169b05156 fix: skip incomplete system log viewer tests
- Marked 12 tests as skip pending feature implementation
- Features tracked in GitHub issue #686 (system log viewer feature completion)
- Tests cover sorting by timestamp/level/method/URI/status, pagination controls, filtering by text/level, download functionality
- Unblocks Phase 2 at 91.7% pass rate to proceed to Phase 3 security enforcement validation
- TODO comments in code reference GitHub #686 for feature completion tracking
- Tests skipped: Pagination (3), Search/Filter (2), Download (2), Sorting (1), Log Display (4)
2026-02-09 21:55:55 +00:00

182 lines
5.5 KiB
TypeScript

import '@testing-library/jest-dom/vitest'
import { render, screen, fireEvent } from '@testing-library/react'
import { describe, it, expect, vi } from 'vitest'
import { AlertCircle } from 'lucide-react'
import { Alert, AlertTitle, AlertDescription } from '../Alert'
describe('Alert', () => {
it('renders with default variant', () => {
render(<Alert>Default alert content</Alert>)
const alert = screen.getByRole('alert')
expect(alert).toBeInTheDocument()
expect(alert).toHaveClass('bg-surface-subtle')
expect(screen.getByText('Default alert content')).toBeInTheDocument()
})
it('renders with info variant', () => {
render(<Alert variant="info">Info message</Alert>)
const alert = screen.getByRole('alert')
expect(alert).toHaveClass('bg-info-muted')
expect(alert).toHaveClass('border-info/30')
})
it('renders with success variant', () => {
render(<Alert variant="success">Success message</Alert>)
const alert = screen.getByRole('alert')
expect(alert).toHaveClass('bg-success-muted')
expect(alert).toHaveClass('border-success/30')
})
it('renders with warning variant', () => {
render(<Alert variant="warning">Warning message</Alert>)
const alert = screen.getByRole('alert')
expect(alert).toHaveClass('bg-warning-muted')
expect(alert).toHaveClass('border-warning/30')
})
it('renders with error variant', () => {
render(<Alert variant="error">Error message</Alert>)
const alert = screen.getByRole('alert')
expect(alert).toHaveClass('bg-error-muted')
expect(alert).toHaveClass('border-error/30')
})
it('renders with title', () => {
render(<Alert title="Alert Title">Alert content</Alert>)
expect(screen.getByText('Alert Title')).toBeInTheDocument()
expect(screen.getByText('Alert content')).toBeInTheDocument()
})
it('renders dismissible alert with dismiss button', () => {
const onDismiss = vi.fn()
render(
<Alert dismissible onDismiss={onDismiss}>
Dismissible alert
</Alert>
)
const dismissButton = screen.getByRole('button', { name: /dismiss alert/i })
expect(dismissButton).toBeInTheDocument()
})
it('calls onDismiss and hides alert when dismiss button is clicked', () => {
const onDismiss = vi.fn()
render(
<Alert dismissible onDismiss={onDismiss}>
Dismissible alert
</Alert>
)
const dismissButton = screen.getByRole('button', { name: /dismiss alert/i })
fireEvent.click(dismissButton)
expect(onDismiss).toHaveBeenCalledTimes(1)
expect(screen.queryByRole('alert')).not.toBeInTheDocument()
})
it('hides alert on dismiss without onDismiss callback', () => {
render(
<Alert dismissible>
Dismissible alert
</Alert>
)
const dismissButton = screen.getByRole('button', { name: /dismiss alert/i })
fireEvent.click(dismissButton)
expect(screen.queryByRole('alert')).not.toBeInTheDocument()
})
it('renders with custom icon', () => {
render(
<Alert icon={AlertCircle} data-testid="alert-with-icon">
Alert with custom icon
</Alert>
)
const alert = screen.getByTestId('alert-with-icon')
// Custom icon should be rendered (AlertCircle)
const iconContainer = alert.querySelector('svg')
expect(iconContainer).toBeInTheDocument()
})
it('renders default icon based on variant', () => {
render(<Alert variant="error">Error alert</Alert>)
const alert = screen.getByRole('alert')
// Error variant uses XCircle icon
const icon = alert.querySelector('svg')
expect(icon).toBeInTheDocument()
expect(icon).toHaveClass('text-error')
})
it('applies custom className', () => {
render(<Alert className="custom-class">Alert content</Alert>)
const alert = screen.getByRole('alert')
expect(alert).toHaveClass('custom-class')
})
it('does not render dismiss button when not dismissible', () => {
render(<Alert>Non-dismissible alert</Alert>)
expect(screen.queryByRole('button', { name: /dismiss/i })).not.toBeInTheDocument()
})
})
describe('AlertTitle', () => {
it('renders correctly', () => {
render(<AlertTitle>Test Title</AlertTitle>)
const title = screen.getByText('Test Title')
expect(title).toBeInTheDocument()
expect(title.tagName).toBe('H5')
expect(title).toHaveClass('font-semibold')
})
it('applies custom className', () => {
render(<AlertTitle className="custom-class">Title</AlertTitle>)
const title = screen.getByText('Title')
expect(title).toHaveClass('custom-class')
})
})
describe('AlertDescription', () => {
it('renders correctly', () => {
render(<AlertDescription>Test Description</AlertDescription>)
const description = screen.getByText('Test Description')
expect(description).toBeInTheDocument()
expect(description.tagName).toBe('P')
expect(description).toHaveClass('text-sm')
})
it('applies custom className', () => {
render(<AlertDescription className="custom-class">Description</AlertDescription>)
const description = screen.getByText('Description')
expect(description).toHaveClass('custom-class')
})
})
describe('Alert composition', () => {
it('works with AlertTitle and AlertDescription subcomponents', () => {
render(
<Alert>
<AlertTitle>Composed Title</AlertTitle>
<AlertDescription>Composed description text</AlertDescription>
</Alert>
)
expect(screen.getByText('Composed Title')).toBeInTheDocument()
expect(screen.getByText('Composed description text')).toBeInTheDocument()
})
})