# LeoCRM — Kompletter Test-Plan > **Erstellt:** 2026-08-21 > **Prinzip:** Echte Tests gegen Produktion — keine Mocks > **Ziel:** 100% Abdeckung aller Module, Plugins, Verbindungen, Rechte, Security --- ## 1. Smoke Tests (Basis-Funktionalität) ### 1.1 System Health - [ ] `GET /api/v1/health` → 200, status=healthy - [ ] DB Verbindung → up - [ ] Redis Verbindung → up - [ ] Storage → up - [ ] Worker → up, queue_length=0 ### 1.2 Auth & Login - [ ] `POST /api/v1/auth/login` (admin) → 200, csrf_token - [ ] `POST /api/v1/auth/login` (falsches Passwort) → 401 - [ ] `POST /api/v1/auth/login` (nicht existierender User) → 401 - [ ] Session-Cookie ist HttpOnly - [ ] CSRF-Token wird zurückgegeben - [ ] `POST /api/v1/auth/logout` → 200 ### 1.3 Frontend laden - [ ] `GET /` → index.html mit JS-Referenzen - [ ] `GET /login` → Login-Seite rendert - [ ] `GET /assets/index-*.js` → 200 - [ ] Service Worker Kill-Switch aktiv auf /sw.js - [ ] Cache-Control: no-cache auf index.html ### 1.4 Plugins aktiv - [ ] `GET /api/v1/plugins` → 200, alle 25 Plugins aktiv - [ ] Jedes Plugin hat Routes registriert - [ ] Jedes Plugin hat Models in DB --- ## 2. Backend API Tests (alle 480+ Endpunkte) ### 2.1 Contacts - [ ] `GET /api/v1/contacts` → 200, PaginatedResponse - [ ] `GET /api/v1/contacts?page=1&page_size=25` → 200 - [ ] `GET /api/v1/contacts?search=test` → 200 - [ ] `GET /api/v1/contacts?type=company` → 200 - [ ] `GET /api/v1/contacts?type=person` → 200 - [ ] `GET /api/v1/contacts?folder_id={id}` → 200 - [ ] `GET /api/v1/contacts?sort_by=displayname&sort_order=asc` → 200 - [ ] `POST /api/v1/contacts` (person) → 201, id - [ ] `POST /api/v1/contacts` (company) → 201, id - [ ] `POST /api/v1/contacts` (missing required fields) → 422 - [ ] `GET /api/v1/contacts/{id}` → 200, contact detail - [ ] `GET /api/v1/contacts/{id}` (non-existent) → 404 - [ ] `PUT /api/v1/contacts/{id}` → 200, updated - [ ] `PUT /api/v1/contacts/{id}` (invalid data) → 422 - [ ] `DELETE /api/v1/contacts/{id}` → 204 - [ ] `DELETE /api/v1/contacts/{id}?hard=true` → 204 - [ ] `GET /api/v1/contacts/{id}/persons` → 200 - [ ] `POST /api/v1/contacts/{id}/persons` → 201 - [ ] `PUT /api/v1/contacts/{id}/persons/{pid}` → 200 - [ ] `DELETE /api/v1/contacts/{id}/persons/{pid}` → 204 ### 2.2 Contact Folders - [ ] `GET /api/v1/contact-folders` → 200 - [ ] `POST /api/v1/contact-folders` → 201 - [ ] `PUT /api/v1/contact-folders/{id}` → 200 - [ ] `DELETE /api/v1/contact-folders/{id}` → 204 - [ ] `PUT /api/v1/contact-folders/contacts/{cid}/move` → 200 - [ ] `GET /api/v1/contact-folders/{id}/permissions` → 200 - [ ] `POST /api/v1/contact-folders/{id}/permissions` → 201 - [ ] `PUT /api/v1/contact-folders/{id}/permissions/{pid}` → 200 - [ ] `DELETE /api/v1/contact-folders/{id}/permissions/{pid}` → 204 ### 2.3 Mail - [ ] `GET /api/v1/mail/accounts` → 200 - [ ] `POST /api/v1/mail/accounts` → 201 (IMAP account) - [ ] `PUT /api/v1/mail/accounts/{id}` → 200 - [ ] `DELETE /api/v1/mail/accounts/{id}` → 204 - [ ] `POST /api/v1/mail/accounts/{id}/sync` → 200, synced count - [ ] `GET /api/v1/mail/accounts/{id}/folders` → 200 - [ ] `GET /api/v1/mail/messages?account_id={id}` → 200 - [ ] `GET /api/v1/mail/messages/{id}` → 200 - [ ] `POST /api/v1/mail/messages` (send) → 201 - [ ] `PATCH /api/v1/mail/messages/{id}` (mark read/unread) → 200 - [ ] `DELETE /api/v1/mail/messages/{id}` → 204 - [ ] `POST /api/v1/mail/accounts/{id}/folders` (IMAP create) → 201 ### 2.4 Calendar - [ ] `GET /api/v1/calendars` → 200 - [ ] `POST /api/v1/calendars` → 201 - [ ] `PUT /api/v1/calendars/{id}` → 200 - [ ] `DELETE /api/v1/calendars/{id}` → 204 - [ ] `GET /api/v1/calendar/entries?start=...&end=...` → 200 - [ ] `POST /api/v1/calendar/entries` → 201 - [ ] `PUT /api/v1/calendar/entries/{id}` → 200 - [ ] `DELETE /api/v1/calendar/entries/{id}` → 204 - [ ] `GET /api/v1/calendar/entries?calendar_id={id}` → 200 ### 2.5 Tasks - [ ] `GET /api/v1/tasks?page=1&page_size=25` → 200 - [ ] `GET /api/v1/tasks?status=open` → 200 - [ ] `GET /api/v1/tasks?priority=high` → 200 - [ ] `POST /api/v1/tasks` → 201 - [ ] `GET /api/v1/tasks/{id}` → 200 - [ ] `PATCH /api/v1/tasks/{id}` → 200 - [ ] `DELETE /api/v1/tasks/{id}` → 204 - [ ] `PATCH /api/v1/tasks/{id}/status` → 200 ### 2.6 Wiki - [ ] `GET /api/v1/wiki/articles?page_size=100` → 200 - [ ] `GET /api/v1/wiki/articles?category_id={id}` → 200 - [ ] `GET /api/v1/wiki/articles?search=test` → 200 - [ ] `POST /api/v1/wiki/articles` (with slug) → 201 - [ ] `GET /api/v1/wiki/articles/{id}` → 200 - [ ] `PATCH /api/v1/wiki/articles/{id}` → 200 - [ ] `DELETE /api/v1/wiki/articles/{id}` → 204 - [ ] `GET /api/v1/wiki/articles/{id}/versions` → 200 - [ ] `POST /api/v1/wiki/articles/{id}/versions/{ver}/restore` → 200 - [ ] `GET /api/v1/wiki/categories` → 200 - [ ] `POST /api/v1/wiki/categories` → 201 ### 2.7 Tags - [ ] `GET /api/v1/tags` → 200 (with parent_id, applicable_to, icon) - [ ] `POST /api/v1/tags` (with new fields) → 201 - [ ] `PATCH /api/v1/tags/{id}` → 200 - [ ] `DELETE /api/v1/tags/{id}` → 204 - [ ] `POST /api/v1/tags/assign` → 201 - [ ] `DELETE /api/v1/tags/assign` → 204 - [ ] `POST /api/v1/tags/bulk-assign` → 200 - [ ] `GET /api/v1/tags/{id}/entities` → 200 ### 2.8 DMS - [ ] `GET /api/v1/dms/files?page=1&page_size=25` → 200 - [ ] `POST /api/v1/dms/files` (upload) → 201 - [ ] `GET /api/v1/dms/files/{id}` → 200 - [ ] `DELETE /api/v1/dms/files/{id}` → 204 - [ ] `GET /api/v1/dms/folders` → 200 - [ ] `POST /api/v1/dms/folders` → 201 - [ ] `GET /api/v1/dms/trash` → 200 ### 2.9 Reports - [ ] `GET /api/v1/reports/templates` → 200 - [ ] `POST /api/v1/reports/templates` → 201 - [ ] `PUT /api/v1/reports/templates/{id}` → 200 - [ ] `DELETE /api/v1/reports/templates/{id}` → 204 - [ ] `GET /api/v1/reports/presets` → 200 - [ ] `POST /api/v1/reports/generate` → 200 (blob) - [ ] `POST /api/v1/reports/presets/{key}/generate` → 200 (blob) ### 2.10 Kommunikation - [ ] `GET /api/v1/comm/conversations` → 200 - [ ] `POST /api/v1/comm/conversations` (with metadata) → 200 - [ ] `GET /api/v1/comm/conversations/{id}` → 200 - [ ] `PATCH /api/v1/comm/conversations/{id}` → 200 - [ ] `DELETE /api/v1/comm/conversations/{id}` → 200 - [ ] `GET /api/v1/comm/conversations/{id}/messages` → 200 - [ ] `POST /api/v1/comm/conversations/{id}/messages` → 200 - [ ] `POST /api/v1/comm/conversations/{id}/pin` → 200 - [ ] `POST /api/v1/comm/conversations/{id}/mark-read` → 200 - [ ] `GET /api/v1/comm/block-types` → 200 - [ ] `GET /api/v1/comm/miniapps` → 200 - [ ] WebSocket `/api/v1/comm/ws` → connect + receive messages ### 2.11 AI Assistant - [ ] `GET /api/v1/ai/providers` → 200 - [ ] `POST /api/v1/ai/providers` → 201 - [ ] `PUT /api/v1/ai/providers/{id}` → 200 - [ ] `DELETE /api/v1/ai/providers/{id}` → 200 - [ ] `GET /api/v1/ai/models` → 200 - [ ] `POST /api/v1/ai/models` → 201 - [ ] `PUT /api/v1/ai/models/{id}` → 200 - [ ] `DELETE /api/v1/ai/models/{id}` → 200 - [ ] `GET /api/v1/ai/presets` → 200 - [ ] `POST /api/v1/ai/presets` → 201 - [ ] `PUT /api/v1/ai/presets/{id}` → 200 - [ ] `DELETE /api/v1/ai/presets/{id}` → 200 - [ ] `GET /api/v1/ai/agents` → 200 - [ ] `POST /api/v1/ai/agents` → 201 - [ ] `PUT /api/v1/ai/agents/{id}` → 200 - [ ] `DELETE /api/v1/ai/agents/{id}` → 200 - [ ] `GET /api/v1/ai/tools` → 200 - [ ] `GET /api/v1/ai/folders` → 200 - [ ] `POST /api/v1/ai/folders` → 201 - [ ] `PUT /api/v1/ai/folders/{id}` → 200 - [ ] `DELETE /api/v1/ai/folders/{id}` → 200 - [ ] `POST /api/v1/ai/conversations/{id}/stream` → SSE stream with GLM 5.2 response - [ ] `GET /api/v1/ai/conversations/{id}/messages` → 200 - [ ] `GET /api/v1/ai/sessions` → 404 (removed in Phase 2) ### 2.12 Workflows - [ ] `GET /api/v1/workflows` → 200 - [ ] `POST /api/v1/workflows` → 201 - [ ] `GET /api/v1/workflows/{id}` → 200 - [ ] `PUT /api/v1/workflows/{id}` → 200 - [ ] `DELETE /api/v1/workflows/{id}` → 204 - [ ] `POST /api/v1/workflows/{id}/execute` → 200 - [ ] `GET /api/v1/workflows/{id}/instances` → 200 ### 2.13 Search - [ ] `GET /api/v1/search?q=test` → 200, results array - [ ] `GET /api/v1/search?q=test&entity_type=contact` → 200 - [ ] `GET /api/v1/search?q=test&entity_type=wiki` → 200 - [ ] `GET /api/v1/search?q=test&entity_type=ai_chat` → 200 (searches comm_messages) - [ ] `GET /api/v1/search/providers` → 200 ### 2.14 Notifications - [ ] `GET /api/v1/notifications` → 200 - [ ] `PATCH /api/v1/notifications/{id}` (mark read) → 200 - [ ] `DELETE /api/v1/notifications/{id}` → 204 - [ ] `GET /api/v1/notifications/types` → 200 ### 2.15 Audit Log - [ ] `GET /api/v1/audit-log?page=1&page_size=25` → 200 - [ ] `GET /api/v1/audit-log?entity_type=contact` → 200 - [ ] `GET /api/v1/audit-log?action=create` → 200 - [ ] Audit-Eintrag wird bei jeder Mutation erstellt ### 2.16 Users & Roles & Groups - [ ] `GET /api/v1/users` → 200 - [ ] `POST /api/v1/users` → 201 - [ ] `PATCH /api/v1/users/{id}` → 200 - [ ] `DELETE /api/v1/users/{id}` → 204 - [ ] `GET /api/v1/roles` → 200 - [ ] `POST /api/v1/roles` → 201 (with permissions dict) - [ ] `PUT /api/v1/roles/{id}` → 200 - [ ] `DELETE /api/v1/roles/{id}` → 204 - [ ] `GET /api/v1/groups` → 200 - [ ] `POST /api/v1/groups` → 201 - [ ] `PUT /api/v1/groups/{id}` → 200 - [ ] `DELETE /api/v1/groups/{id}` → 204 ### 2.17 Plugins - [ ] `GET /api/v1/plugins` → 200, 25 plugins - [ ] `GET /api/v1/plugins/{name}` → 200 - [ ] `POST /api/v1/plugins/{name}/activate` → 200 - [ ] `POST /api/v1/plugins/{name}/deactivate` → 200 ### 2.18 Settings - [ ] `GET /api/v1/system-settings` → 200 - [ ] `PUT /api/v1/system-settings` → 200 - [ ] `GET /api/v1/users/me/preferences` → 200 - [ ] `PUT /api/v1/users/me/preferences` → 200 ### 2.19 Entity Permissions - [ ] `GET /api/v1/entity-permissions?entity_type=contact` → 200 - [ ] `POST /api/v1/entity-permissions` → 201 - [ ] `DELETE /api/v1/entity-permissions/{id}` → 204 ### 2.20 Webhooks - [ ] `GET /api/v1/webhooks` → 200 - [ ] `POST /api/v1/webhooks` → 201 - [ ] `DELETE /api/v1/webhooks/{id}` → 204 - [ ] `POST /api/v1/webhooks/{id}/test` → 200 ### 2.21 Saved Views & Filters - [ ] `GET /api/v1/saved-views` → 200 - [ ] `POST /api/v1/saved-views` → 201 - [ ] `DELETE /api/v1/saved-views/{id}` → 204 - [ ] `GET /api/v1/saved-filters` → 200 - [ ] `POST /api/v1/saved-filters` → 201 ### 2.22 Custom Fields - [ ] `GET /api/v1/custom-field-definitions?entity=contact` → 200 - [ ] `POST /api/v1/custom-field-definitions` → 201 - [ ] `PUT /api/v1/custom-field-definitions/{id}` → 200 - [ ] `DELETE /api/v1/custom-field-definitions/{id}` → 204 - [ ] `GET /api/v1/contacts/{id}/custom-fields` → 200 - [ ] `PUT /api/v1/contacts/{id}/custom-fields` → 200 ### 2.23 Compliance - [ ] `GET /api/v1/compliance/incidents` → 200 - [ ] `POST /api/v1/compliance/incidents` → 201 ### 2.24 Attachments - [ ] `GET /api/v1/attachments` → 200 - [ ] `POST /api/v1/attachments` (upload) → 201 - [ ] `GET /api/v1/attachments/{id}` → 200 - [ ] `DELETE /api/v1/attachments/{id}` → 204 --- ## 3. Frontend Tests ### 3.1 TypeScript - [ ] `npx tsc --noEmit` → clean (0 errors) ### 3.2 Build - [ ] `npm run build` → successful ### 3.3 vitest Unit Tests - [ ] Alle `src/__tests__/` Dateien ausführen - [ ] DmsPage Tests → passed - [ ] Alle anderen Test-Dateien → passed ### 3.4 Playwright E2E Tests - [ ] Alle `e2e/` Dateien ausführen - [ ] Login Flow → passed - [ ] Navigation → passed - [ ] Contact CRUD → passed - [ ] Mail → passed ### 3.5 Browser UI Tests (live) - [ ] Login-Seite rendert mit Formular - [ ] Dashboard lädt nach Login - [ ] Contacts-Seite lädt mit 3-Spalten Layout - [ ] Mail-Seite lädt mit IMAP-Mails - [ ] Calendar-Seite lädt mit Kalender - [ ] Tasks-Seite lädt mit 3-Spalten Layout - [ ] Wiki-Seite lädt mit WYSIWYG Editor - [ ] Tags-Seite lädt (unter Settings) - [ ] Reports-Seite lädt - [ ] Communication-Seite lädt mit AI Chat - [ ] Settings-Seite lädt - [ ] System Dashboard lädt - [ ] Keine Console-Fehler auf irgendeiner Seite --- ## 4. Datenbank Tests ### 4.1 Schema - [ ] Alembic Version: 0140 - [ ] Alle Tabellen existieren (130+) - [ ] Alle Foreign Keys existieren (159+) - [ ] Alle Indexes existieren (590+) - [ ] Alle Unique Constraints existieren - [ ] JSONB Spalten: metadata, applicable_to, config - [ ] TSVECTOR Spalten: search_tsv - [ ] Vector Spalten: embedding (768) ### 4.2 RLS (Row Level Security) - [ ] 109 Tabellen mit RLS aktiviert - [ ] `app.current_tenant_id` wird von `set_tenant_context()` gesetzt - [ ] User sieht nur eigene Tenant-Daten - [ ] Cross-Tenant Query gibt leere Ergebnisse ### 4.3 Migrationen - [ ] Alle 140 Migrationen angewendet - [ ] Migration Hashes korrekt (migration_hashes.txt) - [ ] 0137: AI Chat Tables entfernt - [ ] 0138: Tags parent_id, applicable_to, icon - [ ] 0139: Report templates folder_id - [ ] 0140: Comm conversations folder_id ### 4.4 Daten-Integrität - [ ] AI Provider: Ollama Cloud (is_default=true) - [ ] AI Model: GLM 5.2 (is_active=true) - [ ] AI Preset: GLM 5.2 Default (is_active=true) - [ ] AI Agent: LeoCRM Assistant (is_default=true, is_active=true) - [ ] Mail Account: admin@media-on.de (is_active=true) - [ ] Sales Role: erstellt mit Berechtigungen - [ ] AI Chat Tables: entfernt (0 Einträge) - [ ] Comm Conversations mit conversation_type=ai: vorhanden - [ ] Mail Messages: synchronisiert (>0) --- ## 5. Rechte-System Tests ### 5.1 Admin User (volle Rechte) - [ ] Contacts: GET=200, POST=201, PUT=200, DELETE=204 - [ ] Mail: GET=200, POST=201 - [ ] Calendar: GET=200, POST=201 - [ ] Tasks: GET=200, POST=201 - [ ] Wiki: GET=200, POST=201 - [ ] Tags: GET=200, POST=201 - [ ] DMS: GET=200, POST=201 - [ ] Reports: GET=200, POST=201 - [ ] Comm: GET=200, POST=200 - [ ] AI Providers: GET=200, POST=201 - [ ] AI Agents: GET=200, POST=201 - [ ] Users: GET=200, POST=201 - [ ] Roles: GET=200, POST=201 - [ ] Groups: GET=200, POST=201 - [ ] Plugins: GET=200 - [ ] Workflows: GET=200, POST=201 - [ ] Settings: GET=200, PUT=200 - [ ] Audit: GET=200 - [ ] Webhooks: GET=200, POST=201 - [ ] Notifications: GET=200 - [ ] Search: GET=200 ### 5.2 Sales User (Sales-Rolle: contacts:read+write, mail:read, calendar:read, tags:read, tasks:read+write, wiki:read, communication:read+write, dms:read, reports:read) - [ ] Contacts: GET=200, POST=201 (write erlaubt) - [ ] Mail: GET=200 (read erlaubt) - [ ] Calendar: GET=200 (read erlaubt) - [ ] Tags: GET=200 (read erlaubt) - [ ] Tasks: GET=200, POST=201 (write erlaubt) - [ ] Wiki: GET=200 (read erlaubt) - [ ] Comm: GET=200, POST=200 (write erlaubt) - [ ] DMS: GET=200 (read erlaubt) - [ ] Reports: GET=200 (read erlaubt) - [ ] AI Providers: GET=403 (kein ai:config) - [ ] AI Agents: GET=403 (kein ai:agents) - [ ] Users: GET=403 (kein settings:read) - [ ] Roles: GET=403 (kein settings:read) - [ ] Plugins: GET=403 (kein settings:read) - [ ] Settings: GET=403 (kein settings:read) - [ ] Audit: GET=403 (kein audit:read) - [ ] Webhooks: GET=403 (kein settings:read) ### 5.3 Reader User (keine Berechtigungen) - [ ] Contacts: GET=403, POST=403 - [ ] Mail: GET=403 - [ ] Calendar: GET=403 - [ ] Tags: GET=403, POST=403 - [ ] Tasks: GET=403, POST=403 - [ ] Wiki: GET=403, POST=403 - [ ] AI Providers: GET=403 - [ ] Users: GET=403 ### 5.4 Field-Level Permissions - [ ] Feld `contacts.email_1` auf 'readonly' → User kann lesen aber nicht ändern - [ ] Feld `contacts.phone_1` auf 'hidden' → User kann nicht sehen ### 5.5 Entity-Permissions - [ ] User A hat 'read' auf Contact X → kann lesen - [ ] User B hat keine Permission auf Contact X → kann nicht lesen - [ ] User A hat 'write' auf Contact X → kann ändern ### 5.6 Gruppen-Permissions - [ ] Gruppe 'Sales' hat contacts:read → alle Gruppen-Mitglieder können Contacts lesen - [ ] User wird Gruppe hinzugefügt → bekommt Gruppen-Berechtigungen - [ ] User wird aus Gruppe entfernt → verliert Gruppen-Berechtigungen --- ## 6. Cross-Tenant Security Tests - [ ] Tenant A User fragt Contacts ab → sieht nur Tenant A Contacts - [ ] Tenant A User fragt Contact ID aus Tenant B ab → 404 - [ ] Tenant A User versucht Contact aus Tenant B zu ändern → 404 - [ ] Tenant A User versucht Contact aus Tenant B zu löschen → 404 - [ ] RLS Policy aktiv auf allen 109 Tabellen - [ ] `set_tenant_context()` wird bei jedem Request aufgerufen --- ## 7. Plugin-Verbindungen Tests ### 7.1 AI ↔ Kommunikation - [ ] AI Chat erstellt comm_conversation mit metadata.conversation_type=ai - [ ] AI Streaming schreibt Messages in comm_messages - [ ] AI Messages werden in Kommunikation angezeigt - [ ] categorizeConversation erkennt AI Chats an metadata ### 7.2 AI ↔ Search (Unified Search) - [ ] AI Chat Provider sucht in comm_messages (nicht ai_chat_messages) - [ ] Search Results zeigen AI Chat Messages - [ ] Search filtert nach conversation_type=ai ### 7.3 Tags ↔ Contacts - [ ] Tag wird Contact zugewiesen (POST /tags/assign) - [ ] Contact hat Tag in tags Feld - [ ] Contact kann nach Tag gefiltert werden - [ ] Tag wird von Contact entfernt (DELETE /tags/assign) ### 7.4 Tags ↔ andere Module - [ ] Tags mit applicable_to=['contact'] → nur für Contacts verfügbar - [ ] Tags mit applicable_to=['file'] → nur für DMS verfügbar - [ ] Tags mit applicable_to=['calendar_entry'] → nur für Calendar verfügbar ### 7.5 Wiki ↔ Search - [ ] Wiki Artikel erscheint in Unified Search - [ ] Search nach Wiki Artikel Titel → gefunden - [ ] Search nach Wiki Artikel Content → gefunden ### 7.6 DMS ↔ Contacts - [ ] Datei wird mit Contact verknüpft (entity_link) - [ ] Contact Detail zeigt verknüpfte Dateien - [ ] Datei wird von Contact entknüpft ### 7.7 Mail ↔ Contacts - [ ] E-Mail wird mit Contact verknüpft - [ ] Contact Detail zeigt verknüpfte E-Mails ### 7.8 Calendar ↔ Tasks - [ ] Task mit due_date erscheint im Calendar - [ ] Calendar Entry kann mit Task verknüpft werden ### 7.9 Permissions ↔ alle Plugins - [ ] Jedes Plugin nutzt require_permission Dependency - [ ] Plugin Route ohne Berechtigung → 403 - [ ] Plugin Route mit Berechtigung → 200 ### 7.10 Notifications ↔ alle Plugins - [ ] Contact erstellt → Notification generiert - [ ] Task erstellt → Notification generiert - [ ] Mail empfangen → Notification generiert - [ ] AI Chat Message → Notification generiert ### 7.11 Audit ↔ alle Plugins - [ ] Contact Create → Audit Log Eintrag - [ ] Contact Update → Audit Log Eintrag - [ ] Contact Delete → Audit Log Eintrag - [ ] Tag Create → Audit Log Eintrag - [ ] Task Create → Audit Log Eintrag - [ ] Wiki Create → Audit Log Eintrag - [ ] Mail Send → Audit Log Eintrag ### 7.12 Workflows ↔ Plugins - [ ] Workflow kann Contact erstellen (Step Handler) - [ ] Workflow kann Task erstellen (Step Handler) - [ ] Workflow kann Notification senden (Step Handler) ### 7.13 AI ↔ CRM API Tool - [ ] AI Agent kann call_crm_api Tool verwenden - [ ] AI Agent ruft Contacts API auf → bekommt Ergebnisse - [ ] AI Agent erstellt Contact über Tool → Contact existiert ### 7.14 Search ↔ alle Provider - [ ] Contact Search Provider → findet Contacts - [ ] DMS Search Provider → findet Dateien - [ ] Wiki Search Provider → findet Artikel - [ ] AI Chat Search Provider → findet AI Chat Messages - [ ] Tag Search Provider → findet Tags - [ ] Mail Search Provider → findet E-Mails - [ ] Calendar Search Provider → findet Termine - [ ] Task Search Provider → findet Tasks --- ## 8. Code-Logik Tests ### 8.1 Python Imports - [ ] `from app.main import app` → OK - [ ] `from app.models import *` → OK (keine AIChatSession/AIChatMessage) - [ ] Alle Plugin Routes importierbar - [ ] Alle Services importierbar - [ ] Keine ImportError in irgend einem Modul ### 8.2 Model Validierung - [ ] Tag Model hat parent_id, applicable_to, icon - [ ] CommConversation Model hat folder_id - [ ] ReportTemplate Model hat folder_id - [ ] AIChatSession/AIChatMessage/AIChatAttachment entfernt - [ ] AIConversation/AIMessage entfernt ### 8.3 Schema Validierung - [ ] TagCreate akzeptiert parent_id, applicable_to, icon - [ ] TagUpdate akzeptiert parent_id, applicable_to, icon - [ ] ConversationCreate akzeptiert metadata - [ ] WikiArticleCreate benötigt slug ### 8.4 Service Logik - [ ] create_conversation speichert metadata - [ ] stream_chat_comm schreibt in comm_messages - [ ] get_comm_messages liest aus comm_messages - [ ] AI Chat Search Provider sucht in comm_messages --- ## 9. Performance Tests - [ ] `GET /api/v1/contacts?page=1&page_size=25` → < 200ms - [ ] `GET /api/v1/search?q=test` → < 500ms - [ ] `GET /api/v1/health` → < 50ms - [ ] Frontend Load Time → < 3s - [ ] DB Query für Contacts mit RLS → < 100ms --- ## 10. Security Tests ### 10.1 CSRF - [ ] POST ohne X-CSRF-Token → 403 - [ ] POST mit gültigem X-CSRF-Token → 200/201 - [ ] POST mit falschem X-CSRF-Token → 403 ### 10.2 Auth - [ ] GET ohne Session-Cookie → 401 - [ ] GET mit abgelaufener Session → 401 - [ ] Session-Cookie ist HttpOnly - [ ] Session-Cookie ist Secure (HTTPS) ### 10.3 Input Validation - [ ] POST mit invalid JSON → 422 - [ ] POST mit SQL Injection (`'; DROP TABLE--`) → 422 oder safe - [ ] POST mit XSS (``) → sanitized - [ ] GET mit Path Traversal (`../../../etc/passwd`) → 404 ### 10.4 Rate Limiting - [ ] AI Chat Streaming hat Rate Limit - [ ] Login hat Rate Limit - [ ] API hat General Rate Limit --- ## 11. Cleanup Tests - [ ] Test-User (sales@test.com, reader@test.com) werden nach Tests gelöscht - [ ] Test-Daten (Contacts, Tags, Tasks, Wiki Articles) werden nach Tests gelöscht - [ ] Test-Role (Sales) wird nach Tests gelöscht - [ ] Keine Test-Daten bleiben in Produktion --- ## Ausführungs-Reihenfolge 1. Smoke Tests (1.) — schnell, prüft ob System läuft 2. Code-Logik Tests (8.) — prüft Imports und Models 3. Datenbank Tests (4.) — prüft Schema und Daten 4. Backend API Tests (2.) — alle Endpunkte durchtesten 5. Rechte-System Tests (5.) — mit verschiedenen Usern 6. Cross-Tenant Security Tests (6.) — Tenant-Isolation 7. Plugin-Verbindungen Tests (7.) — alle Plugin-Interaktionen 8. Frontend Tests (3.) — vitest, Playwright, Browser 9. Performance Tests (9.) — Response Times 10. Security Tests (10.) — CSRF, XSS, Rate Limiting 11. Cleanup Tests (11.) — Test-Daten entfernen --- ## Test-User | User | Email | Rolle | Berechtigungen | |------|-------|-------|----------------| | Admin | admin@media-on.de | admin | *:* (volle Rechte) | | Sales | sales@test.com | Sales | contacts:read+write, mail:read, calendar:read, tags:read, tasks:read+write, wiki:read, communication:read+write, dms:read, reports:read | | Reader | reader@test.com | viewer | keine | --- ## Prinzipien - **Echte Tests gegen Produktion** — keine Mocks - **Jeder Test wird mit curl/HTTP gegen https://crm.media-on.de ausgeführt** - **Datenbank-Tests via SSH → psql auf Produktions-DB** - **Frontend-Tests mit vitest + Playwright + Browser** - **Test-Daten werden nach Tests gelöscht** - **Jeder Bug wird sofort gefixt und deployt** - **Ergebnisse werden dokumentiert**