2026-07-14 11:51:32 +02:00
|
|
|
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
|
|
|
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
|
2026-07-14 20:16:15 +02:00
|
|
|
import { ToastProvider, useToast } from '@/components/ui/Toast';
|
|
|
|
|
import { I18nProvider, useI18n } from '@/lib/i18n';
|
|
|
|
|
import { Button } from '@/components/ui/Button';
|
|
|
|
|
import { Input } from '@/components/ui/Input';
|
|
|
|
|
import { Card } from '@/components/ui/Card';
|
|
|
|
|
|
|
|
|
|
// Test Button component
|
|
|
|
|
describe('Button', () => {
|
|
|
|
|
it('renders children', () => {
|
|
|
|
|
render(<Button>Click me</Button>);
|
|
|
|
|
expect(screen.getByText('Click me')).toBeInTheDocument();
|
|
|
|
|
});
|
2026-07-14 11:51:32 +02:00
|
|
|
|
2026-07-14 20:16:15 +02:00
|
|
|
it('shows loading spinner', () => {
|
|
|
|
|
render(<Button loading>Submit</Button>);
|
|
|
|
|
expect(screen.getByText('Submit')).toBeInTheDocument();
|
|
|
|
|
expect(screen.getByRole('button')).toBeDisabled();
|
|
|
|
|
});
|
2026-07-14 11:51:32 +02:00
|
|
|
|
2026-07-14 20:16:15 +02:00
|
|
|
it('handles click events', () => {
|
|
|
|
|
const onClick = vi.fn();
|
|
|
|
|
render(<Button onClick={onClick}>Click</Button>);
|
|
|
|
|
fireEvent.click(screen.getByText('Click'));
|
|
|
|
|
expect(onClick).toHaveBeenCalledTimes(1);
|
|
|
|
|
});
|
|
|
|
|
});
|
2026-07-14 11:51:32 +02:00
|
|
|
|
2026-07-14 20:16:15 +02:00
|
|
|
// Test Input component
|
|
|
|
|
describe('Input', () => {
|
|
|
|
|
it('renders label and input', () => {
|
|
|
|
|
render(<Input label="Email" placeholder="test@test.com" />);
|
|
|
|
|
expect(screen.getByText('Email')).toBeInTheDocument();
|
|
|
|
|
expect(screen.getByPlaceholderText('test@test.com')).toBeInTheDocument();
|
2026-07-14 11:51:32 +02:00
|
|
|
});
|
|
|
|
|
|
2026-07-14 20:16:15 +02:00
|
|
|
it('shows error message', () => {
|
|
|
|
|
render(<Input label="Email" error="Invalid email" />);
|
|
|
|
|
expect(screen.getByText('Invalid email')).toBeInTheDocument();
|
|
|
|
|
});
|
|
|
|
|
});
|
2026-07-14 11:51:32 +02:00
|
|
|
|
2026-07-14 20:16:15 +02:00
|
|
|
// Test Card component
|
|
|
|
|
describe('Card', () => {
|
|
|
|
|
it('renders title and children', () => {
|
|
|
|
|
render(<Card title="Test Title"><p>Card content</p></Card>);
|
|
|
|
|
expect(screen.getByText('Test Title')).toBeInTheDocument();
|
|
|
|
|
expect(screen.getByText('Card content')).toBeInTheDocument();
|
2026-07-14 11:51:32 +02:00
|
|
|
});
|
2026-07-14 20:16:15 +02:00
|
|
|
});
|
2026-07-14 11:51:32 +02:00
|
|
|
|
2026-07-14 20:16:15 +02:00
|
|
|
// Test Toast
|
|
|
|
|
describe('Toast', () => {
|
|
|
|
|
it('shows toast on action', async () => {
|
|
|
|
|
function TestComponent() {
|
|
|
|
|
const { showToast } = useToast();
|
|
|
|
|
return (
|
|
|
|
|
<button onClick={() => showToast('Test message', 'success')} data-testid="trigger">
|
|
|
|
|
Show Toast
|
|
|
|
|
</button>
|
|
|
|
|
);
|
|
|
|
|
}
|
2026-07-14 11:51:32 +02:00
|
|
|
render(
|
2026-07-14 20:16:15 +02:00
|
|
|
<ToastProvider>
|
|
|
|
|
<TestComponent />
|
|
|
|
|
</ToastProvider>
|
2026-07-14 11:51:32 +02:00
|
|
|
);
|
2026-07-14 20:16:15 +02:00
|
|
|
fireEvent.click(screen.getByTestId('trigger'));
|
2026-07-14 11:51:32 +02:00
|
|
|
await waitFor(() => {
|
2026-07-14 20:16:15 +02:00
|
|
|
expect(screen.getByText('Test message')).toBeInTheDocument();
|
2026-07-14 11:51:32 +02:00
|
|
|
});
|
|
|
|
|
});
|
2026-07-14 20:16:15 +02:00
|
|
|
});
|
2026-07-14 11:51:32 +02:00
|
|
|
|
2026-07-14 20:16:15 +02:00
|
|
|
// Test i18n
|
|
|
|
|
describe('i18n', () => {
|
|
|
|
|
it('translates keys in German', () => {
|
|
|
|
|
function TestComponent() {
|
|
|
|
|
const { t } = useI18n();
|
|
|
|
|
return <span data-testid="translated">{t('login.title')}</span>;
|
|
|
|
|
}
|
2026-07-14 11:51:32 +02:00
|
|
|
render(
|
|
|
|
|
<I18nProvider initialLocale="de">
|
2026-07-14 20:16:15 +02:00
|
|
|
<TestComponent />
|
2026-07-14 11:51:32 +02:00
|
|
|
</I18nProvider>
|
|
|
|
|
);
|
2026-07-14 20:16:15 +02:00
|
|
|
expect(screen.getByTestId('translated').textContent).toBe('Anmelden');
|
2026-07-14 11:51:32 +02:00
|
|
|
});
|
|
|
|
|
|
2026-07-14 20:16:15 +02:00
|
|
|
it('translates keys in English', () => {
|
|
|
|
|
function TestComponent() {
|
|
|
|
|
const { t } = useI18n();
|
|
|
|
|
return <span data-testid="translated">{t('login.title')}</span>;
|
|
|
|
|
}
|
2026-07-14 11:51:32 +02:00
|
|
|
render(
|
2026-07-14 20:16:15 +02:00
|
|
|
<I18nProvider initialLocale="en">
|
|
|
|
|
<TestComponent />
|
2026-07-14 11:51:32 +02:00
|
|
|
</I18nProvider>
|
|
|
|
|
);
|
2026-07-14 20:16:15 +02:00
|
|
|
expect(screen.getByTestId('translated').textContent).toBe('Sign In');
|
2026-07-14 11:51:32 +02:00
|
|
|
});
|
|
|
|
|
|
2026-07-14 20:16:15 +02:00
|
|
|
it('switches locale live', () => {
|
|
|
|
|
function TestComponent() {
|
|
|
|
|
const { t, locale, setLocale } = useI18n();
|
|
|
|
|
return (
|
|
|
|
|
<div>
|
|
|
|
|
<span data-testid="translated">{t('login.submit')}</span>
|
|
|
|
|
<button data-testid="switch" onClick={() => setLocale(locale === 'de' ? 'en' : 'de')}>
|
|
|
|
|
Switch
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
2026-07-14 11:51:32 +02:00
|
|
|
render(
|
2026-07-14 20:16:15 +02:00
|
|
|
<I18nProvider initialLocale="de">
|
|
|
|
|
<TestComponent />
|
2026-07-14 11:51:32 +02:00
|
|
|
</I18nProvider>
|
|
|
|
|
);
|
2026-07-14 20:16:15 +02:00
|
|
|
expect(screen.getByTestId('translated').textContent).toBe('Anmelden');
|
|
|
|
|
fireEvent.click(screen.getByTestId('switch'));
|
|
|
|
|
expect(screen.getByTestId('translated').textContent).toBe('Sign In');
|
2026-07-14 11:51:32 +02:00
|
|
|
});
|
|
|
|
|
});
|