import React from 'react'
import { render, screen, fireEvent } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import {
Toast,
ToastProvider,
ToastTitle,
ToastDescription,
ToastAction,
ToastClose,
useToast,
Toaster
} from '../toast'
// Mock icons for testing
jest.mock('lucide-react', () => ({
X: (props: React.ComponentProps<'div'>) =>
,
}))
// Test wrapper component for useToast hook
const TestToastWrapper = ({ children }: { children: React.ReactNode }) => (
{children}
)
describe('Toast Components', () => {
describe('Toast Component', () => {
describe('Basic Rendering', () => {
it('renders correctly with default props', () => {
render(
)
const toast = screen.getByRole('button', { name: /kapat/i })
expect(toast).toBeInTheDocument()
})
it('renders with title', () => {
render(
)
expect(screen.getByText('Test Title')).toBeInTheDocument()
})
it('renders with description', () => {
render(
)
expect(screen.getByText('Test Description')).toBeInTheDocument()
})
it('applies custom className', () => {
const { container } = render(
)
expect(container.querySelector('.custom-toast')).toBeInTheDocument()
})
it('has correct displayName', () => {
expect((Toast as any).displayName || 'Toast').toBe('Toast')
})
})
describe('Variants', () => {
it('renders primary variant correctly', () => {
const { container } = render(
)
expect(container.querySelector('[class*="bg-primary"]')).toBeInTheDocument()
})
it('renders secondary variant correctly', () => {
const { container } = render(
)
expect(container.querySelector('[class*="bg-secondary"]')).toBeInTheDocument()
})
it('renders success variant correctly', () => {
const { container } = render(
)
expect(container.querySelector('[class*="bg-success"]')).toBeInTheDocument()
})
it('renders caution variant correctly', () => {
const { container } = render(
)
expect(container.querySelector('[class*="bg-warning"]')).toBeInTheDocument()
})
it('renders destructive variant correctly', () => {
const { container } = render(
)
expect(container.querySelector('[class*="bg-destructive"]')).toBeInTheDocument()
})
it('renders info variant correctly', () => {
const { container } = render(
)
expect(container.querySelector('[class*="bg-info"]')).toBeInTheDocument()
})
})
describe('Actions', () => {
it('renders action element', () => {
const action = Action
render(
)
expect(screen.getByTestId('toast-action')).toBeInTheDocument()
})
it('handles close button click', async () => {
const onClose = jest.fn()
const user = userEvent.setup()
render(
)
const closeButton = screen.getByRole('button', { name: /kapat/i })
await user.click(closeButton)
expect(onClose).toHaveBeenCalled()
})
})
describe('HTML Attributes', () => {
it('passes through HTML attributes', () => {
const { container } = render(
)
const toast = container.querySelector('[data-testid="toast"]')
expect(toast).toHaveAttribute('aria-label', 'Custom toast')
})
})
})
describe('ToastProvider Component', () => {
describe('Basic Rendering', () => {
it('renders children correctly', () => {
render(
Child Content
)
expect(screen.getByTestId('child')).toBeInTheDocument()
})
it('renders toast container', () => {
const { container } = render(
Content
)
const toastContainer = container.querySelector('[aria-label="Bildirimler"]')
expect(toastContainer).toBeInTheDocument()
})
})
describe('Toast Management', () => {
it('renders toasts in provider', () => {
render(
)
expect(screen.getByText('Test Toast')).toBeInTheDocument()
})
it('renders multiple toasts', () => {
render(
)
expect(screen.getByText('Toast 1')).toBeInTheDocument()
expect(screen.getByText('Toast 2')).toBeInTheDocument()
})
})
})
describe('ToastTitle Component', () => {
describe('Basic Rendering', () => {
it('renders correctly with default props', () => {
render(Title Content )
expect(screen.getByText('Title Content')).toBeInTheDocument()
})
it('applies custom className', () => {
render(Title )
expect(screen.getByText('Title')).toHaveClass('custom-title')
})
it('passes through HTML attributes', () => {
render(Title )
expect(screen.getByTestId('toast-title')).toBeInTheDocument()
})
})
})
describe('ToastDescription Component', () => {
describe('Basic Rendering', () => {
it('renders correctly with default props', () => {
render(Description Content )
expect(screen.getByText('Description Content')).toBeInTheDocument()
})
it('applies custom className', () => {
render(Description )
expect(screen.getByText('Description')).toHaveClass('custom-desc')
})
it('passes through HTML attributes', () => {
render(Description )
expect(screen.getByTestId('toast-desc')).toBeInTheDocument()
})
})
})
describe('ToastAction Component', () => {
describe('Basic Rendering', () => {
it('renders correctly with default props', () => {
render(Action )
expect(screen.getByRole('button', { name: 'Action' })).toBeInTheDocument()
})
it('applies custom className', () => {
render(Action )
expect(screen.getByRole('button')).toHaveClass('custom-action')
})
it('handles click events', async () => {
const onClick = jest.fn()
render(Action )
fireEvent.click(screen.getByRole('button'))
expect(onClick).toHaveBeenCalled()
})
it('passes through HTML attributes', () => {
render(Action )
expect(screen.getByTestId('toast-action')).toBeInTheDocument()
})
})
})
describe('ToastClose Component', () => {
describe('Basic Rendering', () => {
it('renders correctly with default props', () => {
render( )
expect(screen.getByRole('button', { name: /kapat/i })).toBeInTheDocument()
expect(screen.getByTestId('x-icon')).toBeInTheDocument()
})
it('applies custom className', () => {
render( )
expect(screen.getByRole('button')).toHaveClass('custom-close')
})
it('handles click events', async () => {
const onClick = jest.fn()
render( )
fireEvent.click(screen.getByRole('button'))
expect(onClick).toHaveBeenCalled()
})
it('passes through HTML attributes', () => {
render( )
expect(screen.getByTestId('toast-close')).toBeInTheDocument()
})
})
})
describe('useToast Hook', () => {
describe('Context Usage', () => {
it('works correctly within ToastProvider', () => {
const TestComponent = () => {
const { toasts } = useToast()
return {toasts.length}
}
render(
)
expect(screen.getByTestId('toast-count')).toHaveTextContent('0')
})
})
})
describe('Toaster Component', () => {
it('renders Toaster component', () => {
render(Test content
)
// Toaster should render without errors
expect(document.body).toBeInTheDocument()
})
})
describe('Complex Combinations', () => {
it('renders complete toast with all components', () => {
render(
Retry}
/>
)
expect(screen.getByText('Complete Toast')).toBeInTheDocument()
expect(screen.getByText('This is a complete toast')).toBeInTheDocument()
expect(screen.getByRole('button', { name: 'Retry' })).toBeInTheDocument()
expect(screen.getByRole('button', { name: /kapat/i })).toBeInTheDocument()
})
it('handles multiple toasts', () => {
render(
)
expect(screen.getByText('Toast 1')).toBeInTheDocument()
expect(screen.getByText('Toast 2')).toBeInTheDocument()
expect(screen.getByText('Toast 3')).toBeInTheDocument()
})
})
describe('Edge Cases', () => {
it('handles toast without id', () => {
render(
)
expect(screen.getByText('No ID Toast')).toBeInTheDocument()
})
it('handles empty toast content', () => {
render(
)
expect(screen.getByRole('button', { name: /kapat/i })).toBeInTheDocument()
})
it('handles null/undefined props', () => {
render(
)
expect(screen.getByRole('button', { name: /kapat/i })).toBeInTheDocument()
})
it('handles complex nested content', () => {
render(
Complex Title }
description={Complex Description
}
/>
)
expect(screen.getAllByText('Complex')).toHaveLength(2)
expect(screen.getByText('Title')).toBeInTheDocument()
expect(screen.getByText('Description')).toBeInTheDocument()
})
it('passes through HTML attributes for all components', () => {
render(
Title
Description
Action
)
expect(screen.getByTestId('title')).toHaveAttribute('aria-label', 'Title')
expect(screen.getByTestId('desc')).toHaveAttribute('aria-label', 'Description')
expect(screen.getByTestId('action')).toHaveAttribute('aria-label', 'Action')
expect(screen.getByTestId('close')).toHaveAttribute('aria-label', 'Close')
})
})
})