jest.mock('../../../../src/renderer/lib/utils', () => ({
cn: (...classes: string[]) => classes.join(' '),
}));
jest.mock('@radix-ui/react-slot', () => ({
Slot: ({ children, ...props }: any) =>
React.createElement('div', { 'data-testid': 'slot', ...props }, children),
}));
jest.mock('class-variance-authority', () => ({
cva: jest.fn((base, options) => {
const mockFn = jest.fn((props: any) => {
const classes = [base];
if (options?.variants?.variant && props?.variant) {
classes.push(`variant-${props.variant}`);
}
return classes.join(' ');
});
return mockFn;
}),
}));
import React from 'react';
import { render, screen } from '@testing-library/react';
import '@testing-library/jest-dom';
import {
Badge,
badgeVariants,
} from '../../../../src/renderer/components/ui/badge';
describe('Badge Component', () => {
beforeEach(() => {
jest.clearAllMocks();
});
describe('Basic Rendering', () => {
test('renders with default variant', () => {
render(Default Badge);
const badge = screen.getByText('Default Badge');
expect(badge).toBeInTheDocument();
expect(badge.tagName).toBe('SPAN');
expect(badge).toHaveAttribute('data-slot', 'badge');
});
test('renders with custom content', () => {
render(Custom Content);
expect(screen.getByText('Custom Content')).toBeInTheDocument();
});
test('renders with emoji content', () => {
render(🚀);
expect(screen.getByText('🚀')).toBeInTheDocument();
});
test('renders with empty content', () => {
render();
const badge = screen.getByTestId('badge');
expect(badge).toBeInTheDocument();
});
});
describe('Variants', () => {
test('renders with secondary variant', () => {
render(Secondary Badge);
const badge = screen.getByText('Secondary Badge');
expect(badge).toBeInTheDocument();
expect(badge).toHaveClass('variant-secondary');
});
test('renders with destructive variant', () => {
render(Destructive Badge);
const badge = screen.getByText('Destructive Badge');
expect(badge).toBeInTheDocument();
expect(badge).toHaveClass('variant-destructive');
});
test('renders with outline variant', () => {
render(Outline Badge);
const badge = screen.getByText('Outline Badge');
expect(badge).toBeInTheDocument();
expect(badge).toHaveClass('variant-outline');
});
test('renders with default variant when no variant specified', () => {
render(Default Badge);
const badge = screen.getByText('Default Badge');
expect(badge).toBeInTheDocument();
expect(badge).toHaveClass('inline-flex');
});
});
describe('Styling and Classes', () => {
test('applies custom className', () => {
render(Custom Class Badge);
const badge = screen.getByText('Custom Class Badge');
expect(badge).toHaveClass('custom-class');
});
test('merges custom className with variant classes', () => {
render(
Merged Classes Badge
);
const badge = screen.getByText('Merged Classes Badge');
expect(badge).toHaveClass('variant-secondary');
expect(badge).toHaveClass('custom-class');
});
test('includes base classes', () => {
render(Base Classes Badge);
const badge = screen.getByText('Base Classes Badge');
expect(badge).toHaveClass('inline-flex');
expect(badge).toHaveClass('items-center');
expect(badge).toHaveClass('justify-center');
expect(badge).toHaveClass('rounded-lg');
});
test('includes responsive classes', () => {
render(Responsive Badge);
const badge = screen.getByText('Responsive Badge');
expect(badge).toHaveClass('px-2.5');
expect(badge).toHaveClass('py-1');
expect(badge).toHaveClass('text-xs');
});
});
describe('Slot Functionality', () => {
test('renders as span by default', () => {
render(Default Span);
const badge = screen.getByText('Default Span');
expect(badge.tagName).toBe('SPAN');
});
test('renders as Slot when asChild is true', () => {
render(Slot Content);
const slot = screen.getByTestId('slot');
expect(slot).toBeInTheDocument();
expect(slot).toHaveTextContent('Slot Content');
});
test('passes through props to Slot', () => {
render(
Slot Props
);
const slot = screen.getByTestId('slot');
expect(slot).toHaveAttribute('data-custom', 'test-value');
});
});
describe('Accessibility', () => {
test('has proper data attribute', () => {
render(Accessible Badge);
const badge = screen.getByText('Accessible Badge');
expect(badge).toHaveAttribute('data-slot', 'badge');
});
test('supports aria attributes', () => {
render(Status);
const badge = screen.getByLabelText('Status badge');
expect(badge).toBeInTheDocument();
});
test('supports role attribute', () => {
render(Status Badge);
const badge = screen.getByRole('status');
expect(badge).toBeInTheDocument();
});
});
describe('Content Types', () => {
test('renders with icon content', () => {
render(⭐ Star Badge);
expect(screen.getByText('⭐ Star Badge')).toBeInTheDocument();
});
test('renders with numeric content', () => {
render(42);
expect(screen.getByText('42')).toBeInTheDocument();
});
test('renders with special characters', () => {
render(Status: ✓);
expect(screen.getByText('Status: ✓')).toBeInTheDocument();
});
test('renders with HTML entities', () => {
render(& Badge);
expect(screen.getByText('& Badge')).toBeInTheDocument();
});
});
describe('Props Forwarding', () => {
test('forwards HTML span props', () => {
render(Tooltip Badge);
const badge = screen.getByTitle('Tooltip text');
expect(badge).toBeInTheDocument();
});
test('forwards id prop', () => {
render(ID Badge);
const badge = screen.getByTestId('badge');
expect(badge).toHaveAttribute('id', 'test-badge');
});
test('forwards data attributes', () => {
render(Data Attribute Badge);
expect(screen.getByTestId('custom-badge')).toBeInTheDocument();
});
});
describe('Edge Cases', () => {
test('handles undefined variant', () => {
render(Undefined Variant);
const badge = screen.getByText('Undefined Variant');
expect(badge).toBeInTheDocument();
expect(badge).toHaveClass('inline-flex');
});
test('handles null className', () => {
render(Null ClassName);
const badge = screen.getByText('Null ClassName');
expect(badge).toBeInTheDocument();
});
test('handles undefined className', () => {
render(Undefined ClassName);
const badge = screen.getByText('Undefined ClassName');
expect(badge).toBeInTheDocument();
});
});
describe('badgeVariants Function', () => {
test('badgeVariants is exported', () => {
expect(badgeVariants).toBeDefined();
expect(typeof badgeVariants).toBe('function');
});
test('badgeVariants returns class string', () => {
const result = badgeVariants({ variant: 'default' });
expect(typeof result).toBe('string');
expect(result.length).toBeGreaterThan(0);
});
test('badgeVariants handles different variants', () => {
const defaultResult = badgeVariants({ variant: 'default' });
const secondaryResult = badgeVariants({ variant: 'secondary' });
const destructiveResult = badgeVariants({ variant: 'destructive' });
const outlineResult = badgeVariants({ variant: 'outline' });
expect(defaultResult).not.toBe(secondaryResult);
expect(secondaryResult).not.toBe(destructiveResult);
expect(destructiveResult).not.toBe(outlineResult);
});
});
describe('Integration Scenarios', () => {
test('renders badge in complex layout', () => {
render(
);
expect(screen.getByText('New')).toBeInTheDocument();
expect(screen.getByText('Error')).toBeInTheDocument();
expect(screen.getByText('Title')).toBeInTheDocument();
expect(screen.getByText('Content')).toBeInTheDocument();
});
test('renders multiple badges with different variants', () => {
render(
Default
Secondary
Destructive
Outline
);
expect(screen.getByText('Default')).toBeInTheDocument();
expect(screen.getByText('Secondary')).toBeInTheDocument();
expect(screen.getByText('Destructive')).toBeInTheDocument();
expect(screen.getByText('Outline')).toBeInTheDocument();
});
test('badge with asChild renders children correctly', () => {
render(
);
const button = screen.getByRole('button');
expect(button).toBeInTheDocument();
expect(button).toHaveTextContent('Button Badge');
});
});
});