forked from cardosofelipe/fast-next-template
- Added grid and list view modes to AgentTypeList with user preference management. - Enhanced filtering with category selection alongside existing search and status filters. - Updated AgentTypeDetail with category badges and improved layout. - Added unit tests for grid/list views and category filtering in AgentTypeList. - Introduced `@radix-ui/react-toggle-group` for view mode toggle in AgentTypeList.
159 lines
5.8 KiB
TypeScript
159 lines
5.8 KiB
TypeScript
/**
|
|
* Tests for DynamicIcon Component
|
|
* Verifies dynamic icon rendering by name string
|
|
*/
|
|
|
|
import { render, screen } from '@testing-library/react';
|
|
import { DynamicIcon, getAvailableIconNames } from '@/components/ui/dynamic-icon';
|
|
|
|
describe('DynamicIcon', () => {
|
|
describe('Basic Rendering', () => {
|
|
it('renders an icon by name', () => {
|
|
render(<DynamicIcon name="bot" data-testid="icon" />);
|
|
const icon = screen.getByTestId('icon');
|
|
expect(icon).toBeInTheDocument();
|
|
expect(icon.tagName).toBe('svg');
|
|
});
|
|
|
|
it('renders different icons by name', () => {
|
|
const { rerender } = render(<DynamicIcon name="code" data-testid="icon" />);
|
|
expect(screen.getByTestId('icon')).toHaveClass('lucide-code');
|
|
|
|
rerender(<DynamicIcon name="brain" data-testid="icon" />);
|
|
expect(screen.getByTestId('icon')).toHaveClass('lucide-brain');
|
|
|
|
rerender(<DynamicIcon name="shield" data-testid="icon" />);
|
|
expect(screen.getByTestId('icon')).toHaveClass('lucide-shield');
|
|
});
|
|
|
|
it('renders kebab-case icon names correctly', () => {
|
|
render(<DynamicIcon name="clipboard-check" data-testid="icon" />);
|
|
expect(screen.getByTestId('icon')).toHaveClass('lucide-clipboard-check');
|
|
});
|
|
});
|
|
|
|
describe('Fallback Behavior', () => {
|
|
it('renders fallback icon when name is null', () => {
|
|
render(<DynamicIcon name={null} data-testid="icon" />);
|
|
expect(screen.getByTestId('icon')).toHaveClass('lucide-bot');
|
|
});
|
|
|
|
it('renders fallback icon when name is undefined', () => {
|
|
render(<DynamicIcon name={undefined} data-testid="icon" />);
|
|
expect(screen.getByTestId('icon')).toHaveClass('lucide-bot');
|
|
});
|
|
|
|
it('renders fallback icon when name is not found', () => {
|
|
render(<DynamicIcon name="nonexistent-icon" data-testid="icon" />);
|
|
expect(screen.getByTestId('icon')).toHaveClass('lucide-bot');
|
|
});
|
|
|
|
it('uses custom fallback when specified', () => {
|
|
render(<DynamicIcon name={null} fallback="code" data-testid="icon" />);
|
|
expect(screen.getByTestId('icon')).toHaveClass('lucide-code');
|
|
});
|
|
|
|
it('falls back to bot when custom fallback is also invalid', () => {
|
|
render(<DynamicIcon name="invalid" fallback="also-invalid" data-testid="icon" />);
|
|
expect(screen.getByTestId('icon')).toHaveClass('lucide-bot');
|
|
});
|
|
});
|
|
|
|
describe('Props Forwarding', () => {
|
|
it('forwards className to icon', () => {
|
|
render(<DynamicIcon name="bot" className="h-5 w-5 text-primary" data-testid="icon" />);
|
|
const icon = screen.getByTestId('icon');
|
|
expect(icon).toHaveClass('h-5');
|
|
expect(icon).toHaveClass('w-5');
|
|
expect(icon).toHaveClass('text-primary');
|
|
});
|
|
|
|
it('forwards style to icon', () => {
|
|
render(<DynamicIcon name="bot" style={{ color: 'red' }} data-testid="icon" />);
|
|
const icon = screen.getByTestId('icon');
|
|
expect(icon).toHaveStyle({ color: 'rgb(255, 0, 0)' });
|
|
});
|
|
|
|
it('forwards aria-hidden to icon', () => {
|
|
render(<DynamicIcon name="bot" aria-hidden="true" data-testid="icon" />);
|
|
const icon = screen.getByTestId('icon');
|
|
expect(icon).toHaveAttribute('aria-hidden', 'true');
|
|
});
|
|
});
|
|
|
|
describe('Available Icons', () => {
|
|
it('includes development icons', () => {
|
|
const icons = getAvailableIconNames();
|
|
expect(icons).toContain('clipboard-check');
|
|
expect(icons).toContain('briefcase');
|
|
expect(icons).toContain('code');
|
|
expect(icons).toContain('server');
|
|
});
|
|
|
|
it('includes design icons', () => {
|
|
const icons = getAvailableIconNames();
|
|
expect(icons).toContain('palette');
|
|
expect(icons).toContain('search');
|
|
});
|
|
|
|
it('includes quality icons', () => {
|
|
const icons = getAvailableIconNames();
|
|
expect(icons).toContain('shield');
|
|
expect(icons).toContain('shield-check');
|
|
});
|
|
|
|
it('includes ai_ml icons', () => {
|
|
const icons = getAvailableIconNames();
|
|
expect(icons).toContain('brain');
|
|
expect(icons).toContain('microscope');
|
|
expect(icons).toContain('eye');
|
|
});
|
|
|
|
it('includes data icons', () => {
|
|
const icons = getAvailableIconNames();
|
|
expect(icons).toContain('bar-chart');
|
|
expect(icons).toContain('database');
|
|
});
|
|
|
|
it('includes domain expert icons', () => {
|
|
const icons = getAvailableIconNames();
|
|
expect(icons).toContain('calculator');
|
|
expect(icons).toContain('heart-pulse');
|
|
expect(icons).toContain('flask-conical');
|
|
expect(icons).toContain('lightbulb');
|
|
expect(icons).toContain('book-open');
|
|
});
|
|
|
|
it('includes generic icons', () => {
|
|
const icons = getAvailableIconNames();
|
|
expect(icons).toContain('bot');
|
|
expect(icons).toContain('cpu');
|
|
});
|
|
});
|
|
|
|
describe('Icon Categories Coverage', () => {
|
|
const iconTestCases = [
|
|
// Development
|
|
{ name: 'clipboard-check', expectedClass: 'lucide-clipboard-check' },
|
|
{ name: 'briefcase', expectedClass: 'lucide-briefcase' },
|
|
{ name: 'file-text', expectedClass: 'lucide-file-text' },
|
|
{ name: 'git-branch', expectedClass: 'lucide-git-branch' },
|
|
{ name: 'layout', expectedClass: 'lucide-panels-top-left' },
|
|
{ name: 'smartphone', expectedClass: 'lucide-smartphone' },
|
|
// Operations
|
|
{ name: 'settings', expectedClass: 'lucide-settings' },
|
|
{ name: 'settings-2', expectedClass: 'lucide-settings-2' },
|
|
// AI/ML
|
|
{ name: 'message-square', expectedClass: 'lucide-message-square' },
|
|
// Leadership
|
|
{ name: 'users', expectedClass: 'lucide-users' },
|
|
{ name: 'target', expectedClass: 'lucide-target' },
|
|
];
|
|
|
|
it.each(iconTestCases)('renders $name icon correctly', ({ name, expectedClass }) => {
|
|
render(<DynamicIcon name={name} data-testid="icon" />);
|
|
expect(screen.getByTestId('icon')).toHaveClass(expectedClass);
|
|
});
|
|
});
|
|
});
|