/** * Tests for the Button component. */ import { describe, it, expect, vi } from 'vitest'; import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { Button } from '../../components/Button'; describe('Button', () => { it('renders children correctly', () => { render(); expect(screen.getByRole('button')).toHaveTextContent('Click me'); }); it('handles click events', async () => { const user = userEvent.setup(); const handleClick = vi.fn(); render(); await user.click(screen.getByRole('button')); expect(handleClick).toHaveBeenCalledTimes(1); }); it('can be disabled', async () => { const user = userEvent.setup(); const handleClick = vi.fn(); render( ); const button = screen.getByRole('button'); expect(button).toBeDisabled(); await user.click(button); expect(handleClick).not.toHaveBeenCalled(); }); // Variant tests describe('variants', () => { it('applies primary variant styles by default', () => { render(); const button = screen.getByRole('button'); expect(button.className).toContain('bg-bambu-green'); }); it('applies secondary variant styles', () => { render(); const button = screen.getByRole('button'); expect(button.className).toContain('bg-bambu-dark-tertiary'); }); it('applies danger variant styles', () => { render(); const button = screen.getByRole('button'); expect(button.className).toContain('bg-red-600'); }); it('applies ghost variant styles', () => { render(); const button = screen.getByRole('button'); expect(button.className).toContain('bg-transparent'); }); }); // Size tests describe('sizes', () => { it('applies medium size by default', () => { render(); const button = screen.getByRole('button'); expect(button.className).toContain('px-4'); expect(button.className).toContain('py-2'); }); it('applies small size styles', () => { render(); const button = screen.getByRole('button'); expect(button.className).toContain('px-3'); expect(button.className).toContain('py-1.5'); }); it('applies large size styles', () => { render(); const button = screen.getByRole('button'); expect(button.className).toContain('px-6'); expect(button.className).toContain('py-3'); }); }); // Accessibility tests describe('accessibility', () => { it('has correct button role', () => { render(); expect(screen.getByRole('button')).toBeInTheDocument(); }); it('supports custom aria-label', () => { render(); expect(screen.getByRole('button')).toHaveAttribute( 'aria-label', 'Custom label' ); }); it('supports type attribute', () => { render(); expect(screen.getByRole('button')).toHaveAttribute('type', 'submit'); }); }); // Custom className test it('merges custom className with default styles', () => { render(); const button = screen.getByRole('button'); expect(button.className).toContain('custom-class'); expect(button.className).toContain('bg-bambu-green'); // Still has default styles }); // Disabled styles test it('applies disabled styles when disabled', () => { render(); const button = screen.getByRole('button'); expect(button.className).toContain('disabled:opacity-50'); expect(button.className).toContain('disabled:cursor-not-allowed'); }); });