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');
});
});
});