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