T08c: Frontend Mail UI + Global Search UI — 44 tests, tsc clean, vite build pass
- Mail page: 3-pane layout (folder tree + mail list + reading pane) - Compose modal: rich text editor (bold/italic/link), template picker, reply/forward pre-fill - Mail settings: accounts, signatures, rules, labels, vacation, PGP (6 tabs) - Shared mailbox selector: switch between personal + shared accounts - Mail search bar + attachment download + create-event-from-mail - Global search: tabs for companies/contacts/mails/files/events - Search autocomplete in TopBar (existing SearchDropdown) - API client: mail.ts (all endpoints) - Routes: /mail, /mail/settings - i18n: de.json + en.json mail + search translations - 44 new tests (4 test files), full regression 318/318 pass - tsc --noEmit: 0 errors, vite build: 267 modules
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
import React from 'react';
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
|
||||
vi.mock('@/api/mail', () => ({
|
||||
fetchTemplates: vi.fn().mockResolvedValue([
|
||||
{ id: 't1', name: 'Welcome', subject: 'Welcome!', body: '<p>Welcome {{name}}</p>', variables: ['name'] },
|
||||
]),
|
||||
substituteTemplate: vi.fn().mockResolvedValue({ subject: 'Welcome!', body: '<p>Welcome John</p>' }),
|
||||
}));
|
||||
|
||||
vi.mock('@/components/ui/Toast', () => ({
|
||||
useToast: () => ({ success: vi.fn(), error: vi.fn(), info: vi.fn(), warning: vi.fn() }),
|
||||
}));
|
||||
|
||||
import { ComposeModal } from '@/components/mail/ComposeModal';
|
||||
|
||||
function renderModal(props: Partial<React.ComponentProps<typeof ComposeModal>> = {}) {
|
||||
const defaultProps = {
|
||||
open: true,
|
||||
mode: 'new' as const,
|
||||
accountId: 'acc1',
|
||||
replyToMail: null,
|
||||
forwardMail: null,
|
||||
signatures: [],
|
||||
onSend: vi.fn().mockResolvedValue(undefined),
|
||||
onClose: vi.fn(),
|
||||
};
|
||||
return render(<MemoryRouter><ComposeModal {...defaultProps} {...props} /></MemoryRouter>);
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('ComposeModal', () => {
|
||||
it('renders compose modal when open', () => {
|
||||
renderModal();
|
||||
expect(screen.getByTestId('compose-modal')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders compose toolbar with bold button', () => {
|
||||
renderModal();
|
||||
expect(screen.getByTestId('compose-toolbar')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders recipient input field', () => {
|
||||
renderModal();
|
||||
expect(screen.getByTestId('compose-to')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders subject input field', () => {
|
||||
renderModal();
|
||||
expect(screen.getByTestId('compose-subject')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders editor', () => {
|
||||
renderModal();
|
||||
expect(screen.getByTestId('compose-editor')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders send button', () => {
|
||||
renderModal();
|
||||
expect(screen.getByTestId('compose-send')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders template picker toggle button', () => {
|
||||
renderModal();
|
||||
expect(screen.getByTestId('template-picker-toggle')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('shows template picker when template button is clicked', async () => {
|
||||
renderModal();
|
||||
fireEvent.click(screen.getByTestId('template-picker-toggle'));
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('template-picker')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it('pre-fills reply fields when mode is reply', async () => {
|
||||
renderModal({
|
||||
mode: 'reply',
|
||||
replyToMail: {
|
||||
id: 'm1', folder_id: 'f1', account_id: 'acc1', from_address: 'sender@example.com', from_name: 'Sender',
|
||||
to_addresses: ['test@example.com'], cc_addresses: [], bcc_addresses: [],
|
||||
subject: 'Original Subject', body_text: 'Original body', body_html: null, sanitized_html: null,
|
||||
date: '2026-01-01T10:00:00Z', is_seen: true, is_flagged: false, is_answered: false, has_attachments: false,
|
||||
} as any,
|
||||
});
|
||||
await waitFor(() => {
|
||||
const toInput = screen.getByTestId('compose-to');
|
||||
expect(toInput).toHaveValue('sender@example.com');
|
||||
});
|
||||
});
|
||||
|
||||
it('pre-fills forward fields when mode is forward', async () => {
|
||||
renderModal({
|
||||
mode: 'forward',
|
||||
forwardMail: {
|
||||
id: 'm1', folder_id: 'f1', account_id: 'acc1', from_address: 'sender@example.com', from_name: 'Sender',
|
||||
to_addresses: ['test@example.com'], cc_addresses: [], bcc_addresses: [],
|
||||
subject: 'Original Subject', body_text: 'Original body', body_html: null, sanitized_html: null,
|
||||
date: '2026-01-01T10:00:00Z', is_seen: true, is_flagged: false, is_answered: false, has_attachments: false,
|
||||
} as any,
|
||||
});
|
||||
await waitFor(() => {
|
||||
const subjectInput = screen.getByTestId('compose-subject');
|
||||
expect(subjectInput).toHaveValue('Fwd: Original Subject');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,162 @@
|
||||
import React from 'react';
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
|
||||
vi.mock('@/api/mail', () => ({
|
||||
fetchAccounts: vi.fn().mockResolvedValue([
|
||||
{ id: 'acc1', email: 'test@example.com', display_name: 'Test User', is_shared: false, is_active: true, imap_host: '', imap_port: 993, smtp_host: '', smtp_port: 587 },
|
||||
]),
|
||||
fetchFolders: vi.fn().mockResolvedValue([
|
||||
{ id: 'f1', account_id: 'acc1', name: 'INBOX', parent_id: null, unread_count: 2, total_count: 5, children: [] },
|
||||
{ id: 'f2', account_id: 'acc1', name: 'Sent', parent_id: null, unread_count: 0, total_count: 10, children: [] },
|
||||
]),
|
||||
fetchMails: vi.fn().mockResolvedValue({
|
||||
mails: [
|
||||
{ id: 'm1', folder_id: 'f1', account_id: 'acc1', from_address: 'sender@example.com', from_name: 'Sender', to_addresses: ['test@example.com'], cc_addresses: [], bcc_addresses: [], subject: 'Test Subject', body_text: 'Hello', body_html: null, sanitized_html: '<p>Hello</p>', date: '2026-01-01T10:00:00Z', is_seen: false, is_flagged: false, is_answered: false, has_attachments: false, labels: [] },
|
||||
{ id: 'm2', folder_id: 'f1', account_id: 'acc1', from_address: 'sender2@example.com', from_name: 'Sender 2', to_addresses: ['test@example.com'], cc_addresses: [], bcc_addresses: [], subject: 'Another Subject', body_text: 'World', body_html: null, sanitized_html: '<p>World</p>', date: '2026-01-01T11:00:00Z', is_seen: true, is_flagged: true, is_answered: false, has_attachments: true, labels: [] },
|
||||
],
|
||||
total: 2,
|
||||
page: 1,
|
||||
page_size: 25,
|
||||
}),
|
||||
getMail: vi.fn().mockResolvedValue({
|
||||
id: 'm1', folder_id: 'f1', account_id: 'acc1', from_address: 'sender@example.com', from_name: 'Sender', to_addresses: ['test@example.com'], cc_addresses: [], bcc_addresses: [], subject: 'Test Subject', body_text: 'Hello', body_html: '<p>Hello</p>', sanitized_html: '<p>Hello</p>', date: '2026-01-01T10:00:00Z', is_seen: false, is_flagged: false, is_answered: false, has_attachments: false, attachments: [], labels: [],
|
||||
}),
|
||||
sendMail: vi.fn().mockResolvedValue({ id: 'm3', success: true }),
|
||||
replyMail: vi.fn().mockResolvedValue({ id: 'm3', success: true }),
|
||||
forwardMail: vi.fn().mockResolvedValue({ id: 'm3', success: true }),
|
||||
updateFlags: vi.fn().mockResolvedValue(undefined),
|
||||
createEventFromMail: vi.fn().mockResolvedValue({ id: 'e1', success: true }),
|
||||
downloadAttachment: vi.fn().mockResolvedValue(new Blob(['test'])),
|
||||
fetchSignatures: vi.fn().mockResolvedValue([]),
|
||||
searchMails: vi.fn().mockResolvedValue({ mails: [], total: 0, page: 1, page_size: 25 }),
|
||||
}));
|
||||
|
||||
vi.mock('@/components/ui/Toast', () => ({
|
||||
useToast: () => ({ success: vi.fn(), error: vi.fn(), info: vi.fn(), warning: vi.fn() }),
|
||||
}));
|
||||
|
||||
import { MailPage } from '@/pages/Mail';
|
||||
|
||||
function renderWithRouter() {
|
||||
return render(<MemoryRouter><MailPage /></MemoryRouter>);
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('MailPage', () => {
|
||||
it('renders mail page after loading', async () => {
|
||||
renderWithRouter();
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('mail-page')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it('renders folder tree pane', async () => {
|
||||
renderWithRouter();
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('mail-folder-pane')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it('renders mail list pane', async () => {
|
||||
renderWithRouter();
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('mail-list-pane')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it('renders mail detail pane', async () => {
|
||||
renderWithRouter();
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('mail-detail-pane')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it('renders compose button', async () => {
|
||||
renderWithRouter();
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('compose-btn')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it('renders shared mailbox selector', async () => {
|
||||
renderWithRouter();
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('shared-mailbox-selector')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it('renders mail search bar', async () => {
|
||||
renderWithRouter();
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('mail-search-bar')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it('renders folders after loading', async () => {
|
||||
renderWithRouter();
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('INBOX')).toBeInTheDocument();
|
||||
expect(screen.getByText('Sent')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it('renders mails after loading', async () => {
|
||||
renderWithRouter();
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('Test Subject')).toBeInTheDocument();
|
||||
expect(screen.getByText('Another Subject')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it('shows compose modal when compose button is clicked', async () => {
|
||||
renderWithRouter();
|
||||
await waitFor(() => {
|
||||
const btn = screen.getByTestId('compose-btn');
|
||||
fireEvent.click(btn);
|
||||
expect(screen.getByTestId('compose-modal')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it('shows compose toolbar with bold and italic buttons', async () => {
|
||||
renderWithRouter();
|
||||
await waitFor(() => {
|
||||
const btn = screen.getByTestId('compose-btn');
|
||||
fireEvent.click(btn);
|
||||
expect(screen.getByTestId('compose-toolbar')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it('renders mail detail empty state initially', async () => {
|
||||
renderWithRouter();
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('mail-detail-empty')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it('renders mail detail when mail is clicked', async () => {
|
||||
renderWithRouter();
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('Test Subject')).toBeInTheDocument();
|
||||
});
|
||||
fireEvent.click(screen.getByText('Test Subject'));
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('mail-detail')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it('shows reply and forward buttons in mail detail', async () => {
|
||||
renderWithRouter();
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('Test Subject')).toBeInTheDocument();
|
||||
});
|
||||
fireEvent.click(screen.getByText('Test Subject'));
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('mail-detail-toolbar')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,146 @@
|
||||
import React from 'react';
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
|
||||
vi.mock('@/api/mail', () => ({
|
||||
fetchAccounts: vi.fn().mockResolvedValue([
|
||||
{ id: 'acc1', email: 'test@example.com', display_name: 'Test User', is_shared: false, is_active: true, imap_host: '', imap_port: 993, smtp_host: '', smtp_port: 587 },
|
||||
]),
|
||||
createAccount: vi.fn().mockResolvedValue({ id: 'acc2', email: 'new@example.com', display_name: 'New User', is_shared: false, is_active: true, imap_host: '', imap_port: 993, smtp_host: '', smtp_port: 587 }),
|
||||
testConnection: vi.fn().mockResolvedValue({ success: true, message: 'OK' }),
|
||||
triggerSync: vi.fn().mockResolvedValue({ success: true, synced_count: 5 }),
|
||||
fetchSignatures: vi.fn().mockResolvedValue([]),
|
||||
createSignature: vi.fn().mockResolvedValue({ id: 's1', name: 'Test', body_html: '<p>Test</p>', is_default: false }),
|
||||
updateSignature: vi.fn().mockResolvedValue({ id: 's1', name: 'Test', body_html: '<p>Test</p>', is_default: false }),
|
||||
deleteSignature: vi.fn().mockResolvedValue(undefined),
|
||||
fetchRules: vi.fn().mockResolvedValue([]),
|
||||
createRule: vi.fn().mockResolvedValue({ id: 'r1', name: 'Rule 1', account_id: 'acc1', priority: 1, is_active: true, conditions: [], actions: [] }),
|
||||
deleteRule: vi.fn().mockResolvedValue(undefined),
|
||||
fetchLabels: vi.fn().mockResolvedValue([]),
|
||||
createLabel: vi.fn().mockResolvedValue({ id: 'l1', name: 'Important', color: '#ef4444' }),
|
||||
deleteLabel: vi.fn().mockResolvedValue(undefined),
|
||||
configureVacation: vi.fn().mockResolvedValue({ success: true }),
|
||||
testVacationDedup: vi.fn().mockResolvedValue({ dedup_count: 0 }),
|
||||
importPgpKey: vi.fn().mockResolvedValue({ id: 'k1', key_id: 'ABC', fingerprint: 'DEF', user_id: 'test', is_private: true, expires_at: null }),
|
||||
fetchPgpKeys: vi.fn().mockResolvedValue([]),
|
||||
fetchContactPgpKeys: vi.fn().mockResolvedValue([]),
|
||||
storeContactPgpKey: vi.fn().mockResolvedValue(undefined),
|
||||
fetchTemplates: vi.fn().mockResolvedValue([]),
|
||||
substituteTemplate: vi.fn().mockResolvedValue({ subject: '', body: '' }),
|
||||
}));
|
||||
|
||||
vi.mock('@/components/ui/Toast', () => ({
|
||||
useToast: () => ({ success: vi.fn(), error: vi.fn(), info: vi.fn(), warning: vi.fn() }),
|
||||
}));
|
||||
|
||||
import { MailSettingsPage } from '@/pages/MailSettings';
|
||||
|
||||
function renderWithRouter() {
|
||||
return render(<MemoryRouter><MailSettingsPage /></MemoryRouter>);
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('MailSettingsPage', () => {
|
||||
it('renders settings page', async () => {
|
||||
renderWithRouter();
|
||||
expect(screen.getByTestId('mail-settings-page')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders accounts tab content', async () => {
|
||||
renderWithRouter();
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('tab-accounts')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it('renders add account button', async () => {
|
||||
renderWithRouter();
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('add-account-btn')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it('shows add account form when button is clicked', async () => {
|
||||
renderWithRouter();
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('add-account-btn')).toBeInTheDocument();
|
||||
});
|
||||
fireEvent.click(screen.getByTestId('add-account-btn'));
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('add-account-form')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it('renders signature manager in signatures tab', async () => {
|
||||
renderWithRouter();
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('mail-settings-page')).toBeInTheDocument();
|
||||
});
|
||||
// Click on signatures tab
|
||||
const sigTab = screen.getByRole('tab', { name: /Signaturen/i });
|
||||
fireEvent.click(sigTab);
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('signature-manager')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it('renders rule editor in rules tab', async () => {
|
||||
renderWithRouter();
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('mail-settings-page')).toBeInTheDocument();
|
||||
});
|
||||
const rulesTab = screen.getByRole('tab', { name: /Regeln/i });
|
||||
fireEvent.click(rulesTab);
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('rule-editor')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it('renders label manager in labels tab', async () => {
|
||||
renderWithRouter();
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('mail-settings-page')).toBeInTheDocument();
|
||||
});
|
||||
const labelsTab = screen.getByRole('tab', { name: /Labels/i });
|
||||
fireEvent.click(labelsTab);
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('label-manager')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it('renders vacation responder in vacation tab', async () => {
|
||||
renderWithRouter();
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('mail-settings-page')).toBeInTheDocument();
|
||||
});
|
||||
const vacationTab = screen.getByRole('tab', { name: /Abwesenheit/i });
|
||||
fireEvent.click(vacationTab);
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('vacation-responder')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it('renders PGP settings in PGP tab', async () => {
|
||||
renderWithRouter();
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('mail-settings-page')).toBeInTheDocument();
|
||||
});
|
||||
const pgpTab = screen.getByRole('tab', { name: /PGP/i });
|
||||
fireEvent.click(pgpTab);
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('pgp-settings')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it('renders account list with test connection button', async () => {
|
||||
renderWithRouter();
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('account-list')).toBeInTheDocument();
|
||||
});
|
||||
expect(screen.getByTestId('test-conn-acc1')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,73 @@
|
||||
import React from 'react';
|
||||
import { describe, it, expect, vi } from 'vitest';
|
||||
import { render, screen, waitFor } from '@testing-library/react';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
|
||||
vi.mock('@/api/hooks', () => ({
|
||||
useGlobalSearch: () => ({
|
||||
data: [
|
||||
{ id: '1', type: 'company', name: 'TestCorp GmbH', description: 'IT company', url: '/companies/1' },
|
||||
{ id: '2', type: 'contact', name: 'Max Mustermann', description: 'CEO', url: '/contacts/2' },
|
||||
{ id: '3', type: 'mail', name: 'Test Email', description: 'Subject: Hello', url: '/mail/3' },
|
||||
{ id: '4', type: 'file', name: 'Document.pdf', description: 'PDF file', url: '/dms/4' },
|
||||
{ id: '5', type: 'event', name: 'Meeting', description: 'Team sync', url: '/calendar/5' },
|
||||
],
|
||||
isLoading: false,
|
||||
}),
|
||||
}));
|
||||
|
||||
import { GlobalSearchResultsPage } from '@/pages/GlobalSearchResults';
|
||||
|
||||
describe('GlobalSearchResultsPage with tabs', () => {
|
||||
it('renders search page', () => {
|
||||
render(<MemoryRouter initialEntries={['/search?q=test']}><GlobalSearchResultsPage /></MemoryRouter>);
|
||||
expect(screen.getByTestId('global-search-page')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders search input field', () => {
|
||||
render(<MemoryRouter initialEntries={['/search?q=test']}><GlobalSearchResultsPage /></MemoryRouter>);
|
||||
expect(screen.getByTestId('search-input')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders search tabs after results load', async () => {
|
||||
render(<MemoryRouter initialEntries={['/search?q=test']}><GlobalSearchResultsPage /></MemoryRouter>);
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('search-tabs')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it('renders all results in the all tab', async () => {
|
||||
render(<MemoryRouter initialEntries={['/search?q=test']}><GlobalSearchResultsPage /></MemoryRouter>);
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('search-results-all')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it('renders company results', async () => {
|
||||
render(<MemoryRouter initialEntries={['/search?q=test']}><GlobalSearchResultsPage /></MemoryRouter>);
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('search-results-all')).toBeInTheDocument();
|
||||
});
|
||||
const companyTab = screen.getByRole('tab', { name: /Firmen/i });
|
||||
expect(companyTab).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders all 5 result types in the all tab', async () => {
|
||||
render(<MemoryRouter initialEntries={['/search?q=test']}><GlobalSearchResultsPage /></MemoryRouter>);
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText((content, element) => content.includes('Max Mustermann'))).toBeInTheDocument();
|
||||
});
|
||||
expect(screen.getByText((content, element) => content.includes('Document.pdf'))).toBeInTheDocument();
|
||||
expect(screen.getByText((content, element) => content.includes('Meeting'))).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders search submit button', () => {
|
||||
render(<MemoryRouter initialEntries={['/search?q=test']}><GlobalSearchResultsPage /></MemoryRouter>);
|
||||
expect(screen.getByTestId('search-submit-btn')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('shows query display', async () => {
|
||||
render(<MemoryRouter initialEntries={['/search?q=test']}><GlobalSearchResultsPage /></MemoryRouter>);
|
||||
expect(screen.getByTestId('search-query-display')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user