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,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