test(#357): Router-Test gefixt (QueryClientProvider+Mocks, 2/2 passed); Geister-Test ContactEditModal nach §10 gelöscht (Komponente weg seit db4701b)
This commit is contained in:
+2
-2
@@ -7,8 +7,8 @@
|
|||||||
**Offene Pakete (nach Größe, kleinste zuerst):**
|
**Offene Pakete (nach Größe, kleinste zuerst):**
|
||||||
|
|
||||||
1. **Saved-Filters 422-Test** — ✅ erledigt (d7b3c7c... der Fix wurde 2026-08-28 in `0d052ab` deployed)
|
1. **Saved-Filters 422-Test** — ✅ erledigt (d7b3c7c... der Fix wurde 2026-08-28 in `0d052ab` deployed)
|
||||||
2. **AppShell ×4 + Router ×2 Mock-Fixes** — useCurrentUser-Export fehlt im `@/api/hooks`-Mock (AppShell.test.tsx Zeile 14, ~10 Z.) + QueryClientProvider für Router-Tests (2,Z.); siehe #357
|
2. **AppShell ×4 + Router ×2 Mock-Fixes** — ✅ erledigt (2026-08-28): AppShell war bereits grün (useCurrentUser-Mock existierte in Zeile 9; Plan-Eintrag veraltet, bewiesen: Lauf 23:00 'Tests 2 failed (6)' = nur Router). Router.test.tsx gefixt: QueryClientProvider + Mocks useCurrentUser/useUserPermissions → **2/2 passed (2.03s)**
|
||||||
3. **ContactEditModal File-Level** — separate Ursache, braucht Mock-Diagnose
|
3. **ContactEditModal File-Level** — ✅ erledigt (2026-08-28): Geister-Test nach §10 gelöscht. Ursache bewiesen: ContactEditModal.tsx (349 Z.) wurde in db4701b (BUG-080/082) gelöscht, Test blieb → Vitest 'Failed to resolve import' (1 failed, no tests). Ersatz ContactEditForm.tsx lebt und wird von ContactsList/ContactDetailPage genutzt
|
||||||
4. **custom_field_definitions generisch machen** — ENTITY_PLUGIN_OWNERS-Muster wie W4b anwenden (app/routes/custom_field_definitions.py + app/services/entity_permission_service.py)
|
4. **custom_field_definitions generisch machen** — ENTITY_PLUGIN_OWNERS-Muster wie W4b anwenden (app/routes/custom_field_definitions.py + app/services/entity_permission_service.py)
|
||||||
5. **Sidebar /contacts statische Route entfernen** — routes/index.tsx Zeile 250; erst PluginRouteRenderer beweisen (Kritikpunkt 21: Production-Build + Reload-Test), dann entfernen
|
5. **Sidebar /contacts statische Route entfernen** — routes/index.tsx Zeile 250; erst PluginRouteRenderer beweisen (Kritikpunkt 21: Production-Build + Reload-Test), dann entfernen
|
||||||
6. **Kontakt-Model ins ContactsPlugin** — groß (~30 Import-Stellen, Alembic-Kette), bewusst zurückgestellt
|
6. **Kontakt-Model ins ContactsPlugin** — groß (~30 Import-Stellen, Alembic-Kette), bewusst zurückgestellt
|
||||||
|
|||||||
@@ -1,84 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import { describe, it, expect, vi } from 'vitest';
|
|
||||||
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
|
|
||||||
|
|
||||||
// ContactEditModal imports UI components that transitively load lucide-react.
|
|
||||||
// To avoid OOM in the vitest worker, we test via a stub that validates the
|
|
||||||
// component's interface contract (props, rendering, callbacks).
|
|
||||||
vi.mock('@/components/contacts/ContactEditModal', () => ({
|
|
||||||
ContactEditModal: ({ open, onClose, contact, onSaved }: any) => {
|
|
||||||
if (!open) return null;
|
|
||||||
const isEdit = !!contact;
|
|
||||||
return (
|
|
||||||
<div data-testid="modal-stub">
|
|
||||||
<h2>{isEdit ? 'Kontakt bearbeiten' : 'Kontakt erstellen'}</h2>
|
|
||||||
<select data-testid="contact-type-select" defaultValue="company">
|
|
||||||
<option value="company">Firmen</option>
|
|
||||||
<option value="person">Personen</option>
|
|
||||||
</select>
|
|
||||||
<input data-testid="contact-name-input" placeholder="Firmenname" />
|
|
||||||
<input data-testid="contact-first-name-input" placeholder="Vorname" style={{ display: 'none' }} />
|
|
||||||
<input data-testid="contact-last-name-input" placeholder="Nachname" style={{ display: 'none' }} />
|
|
||||||
<input data-testid="contact-submit-btn" type="submit" value={isEdit ? 'Speichern' : 'Erstellen'} />
|
|
||||||
<button onClick={onClose}>Abbrechen</button>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
|
|
||||||
import { ContactEditModal } from '@/components/contacts/ContactEditModal';
|
|
||||||
|
|
||||||
const defaultProps = {
|
|
||||||
open: true,
|
|
||||||
onClose: vi.fn(),
|
|
||||||
contact: null,
|
|
||||||
onSaved: vi.fn(),
|
|
||||||
};
|
|
||||||
|
|
||||||
describe('ContactEditModal', () => {
|
|
||||||
it('renders modal when open', () => {
|
|
||||||
render(<ContactEditModal {...defaultProps} />);
|
|
||||||
expect(screen.getByTestId('modal-stub')).toBeInTheDocument();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('does not render when closed', () => {
|
|
||||||
render(<ContactEditModal {...defaultProps} open={false} />);
|
|
||||||
expect(screen.queryByTestId('modal-stub')).not.toBeInTheDocument();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('renders type select', () => {
|
|
||||||
render(<ContactEditModal {...defaultProps} />);
|
|
||||||
expect(screen.getByTestId('contact-type-select')).toBeInTheDocument();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('renders name input for company type', () => {
|
|
||||||
render(<ContactEditModal {...defaultProps} />);
|
|
||||||
expect(screen.getByTestId('contact-name-input')).toBeInTheDocument();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('renders submit button', () => {
|
|
||||||
render(<ContactEditModal {...defaultProps} />);
|
|
||||||
expect(screen.getByTestId('contact-submit-btn')).toBeInTheDocument();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('renders cancel button', () => {
|
|
||||||
render(<ContactEditModal {...defaultProps} />);
|
|
||||||
expect(screen.getByText(/abbrechen/i)).toBeInTheDocument();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('calls onClose when cancel button clicked', () => {
|
|
||||||
render(<ContactEditModal {...defaultProps} />);
|
|
||||||
fireEvent.click(screen.getByText(/abbrechen/i));
|
|
||||||
expect(defaultProps.onClose).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('renders create title for new contact', () => {
|
|
||||||
render(<ContactEditModal {...defaultProps} />);
|
|
||||||
expect(screen.getByText('Kontakt erstellen')).toBeInTheDocument();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('renders edit title when editing existing contact', () => {
|
|
||||||
render(<ContactEditModal {...defaultProps} contact={{ id: 'c1', type: 'company' } as any} />);
|
|
||||||
expect(screen.getByText('Kontakt bearbeiten')).toBeInTheDocument();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,12 +1,30 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { describe, it, expect, vi } from 'vitest';
|
import { describe, it, expect, vi } from 'vitest';
|
||||||
import { render, screen, act } from '@testing-library/react';
|
import { render, screen } from '@testing-library/react';
|
||||||
import { MemoryRouter, Route, Routes, Navigate } from 'react-router-dom';
|
import { MemoryRouter, Route, Routes } from 'react-router-dom';
|
||||||
|
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
||||||
import { ProtectedRoute } from '@/routes/ProtectedRoute';
|
import { ProtectedRoute } from '@/routes/ProtectedRoute';
|
||||||
import { useAuthStore } from '@/store/authStore';
|
import { useAuthStore } from '@/store/authStore';
|
||||||
|
|
||||||
|
// Mock API hooks used by useAuth (ProtectedRoute → useAuth → useCurrentUser)
|
||||||
|
vi.mock('@/api/hooks', () => ({
|
||||||
|
useCurrentUser: () => ({ data: null, isLoading: false, isError: false, error: null }),
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Mock permissions fetch (useAuth → useUserPermissions → apiGet)
|
||||||
|
vi.mock('@/hooks/useUserPermissions', () => ({
|
||||||
|
useUserPermissions: () => ({}),
|
||||||
|
}));
|
||||||
|
|
||||||
function ProtectedTest() {
|
function ProtectedTest() {
|
||||||
|
const client = new QueryClient({
|
||||||
|
defaultOptions: {
|
||||||
|
queries: { retry: false, staleTime: 0, gcTime: 0 },
|
||||||
|
mutations: { retry: false },
|
||||||
|
},
|
||||||
|
});
|
||||||
return (
|
return (
|
||||||
|
<QueryClientProvider client={client}>
|
||||||
<MemoryRouter initialEntries={['/dashboard']}>
|
<MemoryRouter initialEntries={['/dashboard']}>
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route path="/login" element={<div data-testid="login-page">Login</div>} />
|
<Route path="/login" element={<div data-testid="login-page">Login</div>} />
|
||||||
@@ -17,6 +35,7 @@ function ProtectedTest() {
|
|||||||
} />
|
} />
|
||||||
</Routes>
|
</Routes>
|
||||||
</MemoryRouter>
|
</MemoryRouter>
|
||||||
|
</QueryClientProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user