import { describe, it, expect, vi } from 'vitest'; import { render, screen, fireEvent } from '@testing-library/react'; import { Button } from '../button'; describe('Button', () => { describe('rendering', () => { it('should render with default variant and size', () => { render(); const button = screen.getByRole('button', { name: /click me/i }); expect(button).toBeInTheDocument(); expect(button).toHaveClass('bg-primary'); expect(button).toHaveClass('h-10', 'px-4', 'py-2'); }); it('should render with children text', () => { render(); expect(screen.getByText('Submit Form')).toBeInTheDocument(); }); }); describe('variants', () => { it('should render destructive variant', () => { render(); const button = screen.getByRole('button'); expect(button).toHaveClass('bg-destructive'); }); it('should render outline variant', () => { render(); const button = screen.getByRole('button'); expect(button).toHaveClass('border', 'border-input'); }); it('should render secondary variant', () => { render(); const button = screen.getByRole('button'); expect(button).toHaveClass('bg-secondary'); }); it('should render ghost variant', () => { render(); const button = screen.getByRole('button'); expect(button).toHaveClass('hover:bg-accent'); }); it('should render link variant', () => { render(); const button = screen.getByRole('button'); expect(button).toHaveClass('underline-offset-4'); }); }); describe('sizes', () => { it('should render small size', () => { render(); const button = screen.getByRole('button'); expect(button).toHaveClass('h-9', 'px-3'); }); it('should render large size', () => { render(); const button = screen.getByRole('button'); expect(button).toHaveClass('h-11', 'px-8'); }); it('should render icon size', () => { render(); const button = screen.getByRole('button'); expect(button).toHaveClass('h-10', 'w-10'); }); }); describe('states', () => { it('should be disabled when disabled prop is passed', () => { render(); const button = screen.getByRole('button'); expect(button).toBeDisabled(); expect(button).toHaveClass('disabled:opacity-50'); }); it('should handle click events', () => { const handleClick = vi.fn(); render(); const button = screen.getByRole('button'); fireEvent.click(button); expect(handleClick).toHaveBeenCalledTimes(1); }); it('should not fire click when disabled', () => { const handleClick = vi.fn(); render(); const button = screen.getByRole('button'); fireEvent.click(button); expect(handleClick).not.toHaveBeenCalled(); }); }); describe('asChild prop', () => { it('should render as child element when asChild is true', () => { render( ); const link = screen.getByRole('link'); expect(link).toBeInTheDocument(); expect(link).toHaveAttribute('href', '/test'); expect(link).toHaveClass('bg-primary'); }); }); describe('custom className', () => { it('should apply custom className', () => { render(); const button = screen.getByRole('button'); expect(button).toHaveClass('custom-class'); }); }); describe('type attribute', () => { it('should have type button by default', () => { render(); const button = screen.getByRole('button'); // Default type in React is undefined (browser defaults to submit in forms) expect(button).not.toHaveAttribute('type', 'submit'); }); it('should accept submit type', () => { render(); const button = screen.getByRole('button'); expect(button).toHaveAttribute('type', 'submit'); }); }); });