import { render, screen, fireEvent } from '@testing-library/react' import { describe, it, expect, vi } from 'vitest' import userEvent from '@testing-library/user-event' import { Button } from '../button' describe('Button', () => { it('renders button with children', () => { render() expect(screen.getByRole('button')).toBeInTheDocument() expect(screen.getByText('Click me')).toBeInTheDocument() }) it('applies default variant classes', () => { render() const button = screen.getByRole('button') expect(button).toHaveClass('bg-primary', 'text-primary-fg', 'hover:bg-primary/90') }) it('applies destructive variant classes', () => { render() const button = screen.getByRole('button') expect(button).toHaveClass('bg-destructive', 'text-destructive-fg', 'hover:bg-destructive/90') }) it('applies link variant classes', () => { render() const button = screen.getByRole('button') expect(button).toHaveClass('underline-offset-4', 'hover:no-underline') }) it('applies default size classes', () => { render() const button = screen.getByRole('button') expect(button).toHaveClass('h-7', 'px-3', 'py-2') }) it('applies small size classes', () => { render() const button = screen.getByRole('button') expect(button).toHaveClass('h-6', 'px-2') }) it('applies large size classes', () => { render() const button = screen.getByRole('button') expect(button).toHaveClass('h-9', 'rounded-md', 'px-4') }) it('applies icon size classes', () => { render() const button = screen.getByRole('button') expect(button).toHaveClass('size-8') }) it('handles click events', async () => { const handleClick = vi.fn() const user = userEvent.setup() render() await user.click(screen.getByRole('button')) expect(handleClick).toHaveBeenCalledTimes(1) }) it('can be disabled', () => { render() const button = screen.getByRole('button') expect(button).toBeDisabled() expect(button).toHaveClass('disabled:pointer-events-none', 'disabled:opacity-50') }) it('does not trigger click when disabled', async () => { const handleClick = vi.fn() const user = userEvent.setup() render() await user.click(screen.getByRole('button')) expect(handleClick).not.toHaveBeenCalled() }) it('forwards ref correctly', () => { const ref = vi.fn() render() expect(ref).toHaveBeenCalledWith(expect.any(HTMLButtonElement)) }) it('accepts custom className', () => { render() const button = screen.getByRole('button') expect(button).toHaveClass('custom-class') }) it('accepts custom props', () => { render() const button = screen.getByTestId('custom-button') expect(button).toHaveAttribute('type', 'submit') }) it('renders as different element when asChild is true', () => { render( ) const link = screen.getByRole('link') expect(link).toHaveAttribute('href', '/test') expect(link).toHaveClass('bg-primary', 'text-primary-fg') // Should inherit button classes }) it('combines variant and size classes correctly', () => { render() const button = screen.getByRole('button') expect(button).toHaveClass('bg-destructive', 'text-destructive-fg') // destructive variant expect(button).toHaveClass('h-9', 'rounded-md', 'px-4') // large size }) it('handles keyboard events', () => { const handleKeyDown = vi.fn() render() const button = screen.getByRole('button') fireEvent.keyDown(button, { key: 'Enter' }) expect(handleKeyDown).toHaveBeenCalledWith(expect.objectContaining({ key: 'Enter' })) }) it('supports focus events', () => { const handleFocus = vi.fn() const handleBlur = vi.fn() render() const button = screen.getByRole('button') fireEvent.focus(button) fireEvent.blur(button) expect(handleFocus).toHaveBeenCalledTimes(1) expect(handleBlur).toHaveBeenCalledTimes(1) }) it('applies focus-visible styling', () => { render() const button = screen.getByRole('button') expect(button).toHaveClass('focus-visible:border-ring', 'focus-visible:ring-ring/50') }) })