diff --git a/docs/test-plan-complete.md b/docs/test-plan-complete.md new file mode 100644 index 0000000..1e04958 --- /dev/null +++ b/docs/test-plan-complete.md @@ -0,0 +1,633 @@ +# 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**