175 lines
5.1 KiB
TypeScript
175 lines
5.1 KiB
TypeScript
|
|
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||
|
|
import { render, screen, fireEvent } from '@testing-library/react';
|
||
|
|
import { BrowserRouter } from 'react-router-dom';
|
||
|
|
// import { useTranslation } from '@/hooks/useTranslation'
|
||
|
|
import { Button } from '@/components/ui/button';
|
||
|
|
import { Input } from '@/components/ui/input';
|
||
|
|
import { FocusTrap } from '@/components/ui/focus-trap';
|
||
|
|
|
||
|
|
// Mock useTranslation
|
||
|
|
vi.mock('@/hooks/useTranslation', () => ({
|
||
|
|
useTranslation: vi.fn(() => ({
|
||
|
|
t: (key: string) => key,
|
||
|
|
i18n: { changeLanguage: vi.fn() },
|
||
|
|
language: 'en',
|
||
|
|
changeLanguage: vi.fn(),
|
||
|
|
isReady: true,
|
||
|
|
})),
|
||
|
|
}));
|
||
|
|
|
||
|
|
// Mock i18n
|
||
|
|
vi.mock('@/lib/i18n', () => ({
|
||
|
|
default: {
|
||
|
|
changeLanguage: vi.fn(),
|
||
|
|
isInitialized: true,
|
||
|
|
},
|
||
|
|
}));
|
||
|
|
|
||
|
|
const TestWrapper = ({ children }: { children: React.ReactNode }) => (
|
||
|
|
<BrowserRouter>{children}</BrowserRouter>
|
||
|
|
);
|
||
|
|
|
||
|
|
describe('UI Components', () => {
|
||
|
|
beforeEach(() => {
|
||
|
|
vi.clearAllMocks();
|
||
|
|
});
|
||
|
|
|
||
|
|
describe('Button', () => {
|
||
|
|
it('should render with default props', () => {
|
||
|
|
render(<Button>Test Button</Button>);
|
||
|
|
expect(
|
||
|
|
screen.getByRole('button', { name: 'Test Button' })
|
||
|
|
).toBeInTheDocument();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should render with different variants', () => {
|
||
|
|
render(<Button variant='destructive'>Delete</Button>);
|
||
|
|
const button = screen.getByRole('button', { name: 'Delete' });
|
||
|
|
expect(button).toBeInTheDocument();
|
||
|
|
expect(button).toHaveClass('bg-destructive');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should handle click events', () => {
|
||
|
|
const handleClick = vi.fn();
|
||
|
|
render(<Button onClick={handleClick}>Click me</Button>);
|
||
|
|
|
||
|
|
fireEvent.click(screen.getByRole('button'));
|
||
|
|
expect(handleClick).toHaveBeenCalledTimes(1);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should be disabled when disabled prop is true', () => {
|
||
|
|
render(<Button disabled>Disabled Button</Button>);
|
||
|
|
const button = screen.getByRole('button', { name: 'Disabled Button' });
|
||
|
|
expect(button).toBeDisabled();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should render as child when asChild is true', () => {
|
||
|
|
render(
|
||
|
|
<Button asChild>
|
||
|
|
<a href='/test'>Link Button</a>
|
||
|
|
</Button>
|
||
|
|
);
|
||
|
|
expect(
|
||
|
|
screen.getByRole('link', { name: 'Link Button' })
|
||
|
|
).toBeInTheDocument();
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
describe('Input', () => {
|
||
|
|
it('should render with default props', () => {
|
||
|
|
render(<Input placeholder='Enter text' />);
|
||
|
|
expect(screen.getByPlaceholderText('Enter text')).toBeInTheDocument();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should handle value changes', () => {
|
||
|
|
const handleChange = vi.fn();
|
||
|
|
render(<Input onChange={handleChange} />);
|
||
|
|
|
||
|
|
const input = screen.getByRole('textbox');
|
||
|
|
fireEvent.change(input, { target: { value: 'test input' } });
|
||
|
|
|
||
|
|
expect(handleChange).toHaveBeenCalled();
|
||
|
|
expect(input).toHaveValue('test input');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should support different input types', () => {
|
||
|
|
render(<Input type='email' placeholder='Enter email' />);
|
||
|
|
const input = screen.getByPlaceholderText('Enter email');
|
||
|
|
expect(input).toHaveAttribute('type', 'email');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should be disabled when disabled prop is true', () => {
|
||
|
|
render(<Input disabled placeholder='Disabled input' />);
|
||
|
|
const input = screen.getByPlaceholderText('Disabled input');
|
||
|
|
expect(input).toBeDisabled();
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
describe('FocusTrap', () => {
|
||
|
|
it('should render children when active', () => {
|
||
|
|
render(
|
||
|
|
<FocusTrap active={true}>
|
||
|
|
<div>Test content</div>
|
||
|
|
</FocusTrap>
|
||
|
|
);
|
||
|
|
expect(screen.getByText('Test content')).toBeInTheDocument();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should not render children when inactive', () => {
|
||
|
|
render(
|
||
|
|
<FocusTrap active={false}>
|
||
|
|
<div>Test content</div>
|
||
|
|
</FocusTrap>
|
||
|
|
);
|
||
|
|
expect(screen.getByText('Test content')).toBeInTheDocument();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should call onEscape when Escape key is pressed', () => {
|
||
|
|
const onEscape = vi.fn();
|
||
|
|
render(
|
||
|
|
<FocusTrap active={true} onEscape={onEscape}>
|
||
|
|
<div>Test content</div>
|
||
|
|
</FocusTrap>
|
||
|
|
);
|
||
|
|
|
||
|
|
fireEvent.keyDown(document, { key: 'Escape' });
|
||
|
|
expect(onEscape).toHaveBeenCalledTimes(1);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
describe('Integration Tests', () => {
|
||
|
|
it('should work with React Router', () => {
|
||
|
|
render(
|
||
|
|
<TestWrapper>
|
||
|
|
<Button asChild>
|
||
|
|
<a href='/dashboard'>Go to Dashboard</a>
|
||
|
|
</Button>
|
||
|
|
</TestWrapper>
|
||
|
|
);
|
||
|
|
|
||
|
|
const link = screen.getByRole('link', { name: 'Go to Dashboard' });
|
||
|
|
expect(link).toBeInTheDocument();
|
||
|
|
expect(link).toHaveAttribute('href', '/dashboard');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should handle form interactions', async () => {
|
||
|
|
const handleSubmit = vi.fn(e => e.preventDefault());
|
||
|
|
|
||
|
|
render(
|
||
|
|
<form onSubmit={handleSubmit}>
|
||
|
|
<Input name='username' placeholder='Username' />
|
||
|
|
<Button type='submit'>Submit</Button>
|
||
|
|
</form>
|
||
|
|
);
|
||
|
|
|
||
|
|
const input = screen.getByPlaceholderText('Username');
|
||
|
|
const button = screen.getByRole('button', { name: 'Submit' });
|
||
|
|
|
||
|
|
fireEvent.change(input, { target: { value: 'testuser' } });
|
||
|
|
fireEvent.click(button);
|
||
|
|
|
||
|
|
expect(handleSubmit).toHaveBeenCalledTimes(1);
|
||
|
|
});
|
||
|
|
});
|