refactor: rename MERGE_CHECKLIST to ALL_TESTS + add per-service test files

- tests/MERGE_CHECKLIST.md → tests/ALL_TESTS.md (git rename, updated header + index of sub-files)
- tests/backend_tests.md — §1–9, §18 (auth, users, admin, groups, appearance, service health, plugins, AI/doc settings, infra/security)
- tests/frontend_tests.md — §19 (UI & routing)
- tests/doc-service_tests.md — §10–16 (upload/processing, list/filtering, slide-over, sharing, categories, bulk actions, watch directory)
- tests/ai-service_tests.md — §17 (AI queue & providers)
- CLAUDE.md: updated merge checklist section, file tree, and self-update checkpoint with mandatory test-file update rule
- settings.local.json: added docker inspect/ps, curl, lsof, git merge/branch/log/diff/status/config/mv permissions

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
curo1305
2026-04-19 02:19:51 +02:00
parent d345ace86d
commit 50d2348b36
7 changed files with 439 additions and 5 deletions
+157
View File
@@ -0,0 +1,157 @@
# Doc-Service Tests
Tests covering the PDF extraction microservice (`doc-service:8001`): document upload/processing, list/filtering, slide-over detail view, sharing, categories, bulk actions, and the file watcher.
Full combined suite: `tests/ALL_TESTS.md`
**Test environment:** Feature stack at `http://localhost:$PORT` (see CLAUDE.md §Feature branch workflow).
**Admin credentials:** any superuser account created during stack setup.
**Regular user credentials:** a second non-admin account for permission boundary tests.
---
## Legend
| Symbol | Meaning |
|--------|---------|
| ✅ | Pass |
| ❌ | Fail |
| — | N/A for this change |
---
## 10. Document Upload & Processing
| # | Test | Steps | Expected |
|---|------|-------|----------|
| 10.1 | Upload valid PDF | Drag-and-drop or file picker → select a PDF under the size limit | 202; document row appears with `status=pending`; transitions to `done` |
| 10.2 | Upload oversized PDF | Upload a PDF exceeding `max_pdf_bytes` | 413; error shown; no row created |
| 10.3 | Upload non-PDF | Upload a `.docx` or `.jpg` | 415; error shown |
| 10.4 | Multi-file upload | Select 3 PDFs at once | All 3 appear in upload queue panel; each processes independently |
| 10.5 | Upload queue panel | During upload → check bottom-right panel | Per-file status indicator; "Review →" link after each completes |
| 10.6 | Drag-and-drop overlay | Drag file over the documents page | Full-page overlay appears; drop uploads file |
| 10.7 | Processing status poll | Upload a large PDF | Table row auto-updates every 3s until status = `done` or `failed` |
| 10.8 | AI extraction result | Open slide-over for a `done` document | title, document_type, tags, extracted_data fields populated |
| 10.9 | Failed extraction | AI service down → upload PDF | Status = `failed`; error_message shown in slide-over |
| 10.10 | Re-analyse | Click "Re-analyse" in slide-over | 202; status resets to `pending`; re-processes through AI |
---
## 11. Document List & Filtering
| # | Test | Steps | Expected |
|---|------|-------|----------|
| 11.1 | Default list | Navigate to `/apps/documents` | Own documents shown, newest first, 20 per page |
| 11.2 | Search | Type in search box (debounced 400ms) | Results filtered by title / filename / tags / type |
| 11.3 | Filter by status | Add filter chip → Status → "done" | Only completed docs shown |
| 11.4 | Filter by type | Add filter chip → Document type → "invoice" | Only invoices shown |
| 11.5 | Filter by category | Add filter chip → Category → pick one | Only docs in that category shown |
| 11.6 | Remove filter chip | Click × on a chip | Filter removed; full list restored |
| 11.7 | Sort by column | Click "Date" column header | List re-ordered; chevron indicates direction; click again reverses |
| 11.8 | Pagination | Upload > 20 docs → scroll to bottom | Page controls appear; page 2 loads next 20 |
| 11.9 | "Mine" view | Click "Mine" in SourcePanel | Only own (uploaded) documents shown |
| 11.10 | "Shared with me" view | Click "Shared with me" | Docs shared by others via groups; own docs excluded |
| 11.11 | Category filter via SourcePanel | Click a category in the left tree | Table filtered to that category's documents |
| 11.12 | URL state preserved | Apply filters → copy URL → open in new tab | Same filters applied |
---
## 12. Document Detail — Slide-over
| # | Test | Steps | Expected |
|---|------|-------|----------|
| 12.1 | Open slide-over | Click any document row | 480px right panel slides in; metadata loaded |
| 12.2 | Inline title edit | Click pencil icon next to title → type new title → confirm | Title saved; updated in table row |
| 12.3 | Change document type | Click a type chip (Invoice, Receipt, etc.) | Type updated immediately |
| 12.4 | Edit tags | Click into tag area → type a tag → press Enter → remove a tag with × | Tags saved correctly |
| 12.5 | Assign category | Categories combobox → search → select | Category badge appears on document; table row updates |
| 12.6 | Remove category | Click × on an assigned category badge | Category removed from document |
| 12.7 | AI category suggestions | Slide-over shows "Suggested categories" | "Assign" and "Create & Assign" buttons present; clicking assigns |
| 12.8 | Confirm folder suggestion | "Confirm" button next to suggested_folder | Category created (if needed) and assigned; `suggested_folder` cleared |
| 12.9 | Reject folder suggestion | "Reject" button next to suggested_folder | `suggested_folder` cleared; no category created |
| 12.10 | Confirm filename suggestion | "Confirm" button next to suggested_filename | `title` updated to suggested value; `suggested_filename` cleared |
| 12.11 | Reject filename suggestion | "Reject" button next to suggested_filename | `suggested_filename` cleared; title unchanged |
| 12.12 | Extracted data section | Open slide-over on `done` doc | Key-value table of AI-extracted fields (vendor, amounts, dates, etc.) |
| 12.13 | Raw text section | Expand raw text collapse | First ~500k chars of extracted PDF text shown |
| 12.14 | Download | Click "Download" | Browser downloads the original PDF file |
| 12.15 | View in new tab | Click "View" | PDF opens in new browser tab; URL auto-revokes after 60s |
| 12.16 | Delete — owner | Click "Delete" → confirm dialog | Document and file removed; table row gone |
| 12.16b | Delete — admin | Admin opens any doc (not their own) → Delete → confirm | Document deleted; 204 returned |
| 12.16c | Delete — can_delete share | Group member whose share has `can_delete=true` → Delete | 204; document removed; `viewer_can_delete` was `true` in `DocumentOut` |
| 12.16d | Delete — group admin | User is group admin for a group the doc is shared with; no explicit `can_delete` flag → Delete | 204; group admin always has delete rights for docs shared with their group |
| 12.16e | Delete — watch document, admin only | Watch-ingested doc (`source=watch`); regular user → Delete | 403 (not owner); admin can delete it |
| 12.17 | Non-owner cannot edit | Recipient of shared doc opens slide-over (no can_delete, not group admin) | Edit controls (type, tags, title, delete) absent; download available |
---
## 13. Document Sharing
| # | Test | Steps | Expected |
|---|------|-------|----------|
| 13.1 | Share from slide-over | Owner opens sharing section → selects a group from combobox → shares | Group appears in shares list; `share_count` in table row increments |
| 13.2 | Only user's own groups shown | Open group picker in share section | Only groups the current user belongs to are listed |
| 13.3 | Recipient sees shared doc | Log in as group member → "Shared with me" view | Shared document appears with primary accent border |
| 13.4 | Recipient download | Recipient clicks Download on shared doc | PDF downloaded successfully |
| 13.4b | Non-owner calls `GET /documents/{id}/shares` | Regular user on a doc they don't own | 404 (doc-service hides existence, consistent with admin 404 semantics — not 403) |
| 13.5 | Recipient cannot delete | Recipient opens slide-over | Delete button absent |
| 13.6 | Recipient cannot re-share | Recipient opens sharing section | Share controls absent |
| 13.7 | Remove share | Owner clicks remove on a group share | Group removed; `share_count` decrements; recipient no longer sees doc |
| 13.8 | Bulk share | Select multiple rows → bulk share → pick group | All selected docs shared with that group |
| 13.9 | Share count indicator | Document shared with 2 groups | Users icon in table row shows "2" |
| 13.10 | Share with non-member group | `POST /api/documents/{id}/shares` with group not in X-User-Groups | 403 / validation error |
| 13.11 | Share with can_delete enabled | Owner opens sharing section → tick "Allow group members to delete" → share | `can_delete=true` stored; trash icon badge appears next to group name in shares list |
| 13.12 | Share without can_delete (default) | Owner shares without ticking delete checkbox | `can_delete=false`; recipient sees the doc but Delete button absent in slide-over |
| 13.13 | can_delete shown in shares list | Share with can_delete=true → inspect shares list in slide-over | Trash2 icon rendered beside the group name; tooltip "Group members can delete this document" |
| 13.14 | viewer_can_delete in document list | Share with can_delete=true; log in as group member → `GET /api/documents` | `viewer_can_delete=true` in the recipient's list response for that doc |
---
## 14. Categories
| # | Test | Steps | Expected |
|---|------|-------|----------|
| 14.1 | Create category | SourcePanel → "New category" form → submit | Category appears in tree |
| 14.2 | Rename category | Manage categories dialog → edit → save | New name reflected everywhere |
| 14.3 | Delete category | Delete category with documents assigned | 204; documents remain; category assignment removed |
| 14.4 | Category search | More than 4 categories → type in search field | Tree filtered in real time |
| 14.5 | Manage categories dialog | Click "Manage categories" | Modal shows categories grouped by scope (Personal / Group / System) with lock icons on group and system categories |
| 14.6 | New category triggers re-analysis | Create category with name similar to AI suggestion | Background re-analysis triggered (check backend logs) |
| 14.7 | Create personal category | SourcePanel → "New category" → no group selected → submit valid PascalCase name | Created with `scope=personal`; visible only to owner |
| 14.8 | Create group-scoped category | SourcePanel → "New category" → select a group → submit | Created with `scope=group`; visible to all members of that group |
| 14.9 | Group category visible to group members | Log in as another group member | Group category appears in their category list and SourcePanel |
| 14.10 | Non-member cannot see group category | Log in as user not in the group | Group category absent from list |
| 14.11 | Only group admin can rename group category | Regular group member → rename group category | 403; group admin can rename it successfully |
| 14.12 | Only group admin can delete group category | Regular group member → delete group category | 403; group admin can delete it |
| 14.13 | System categories read-only for non-admin | Regular user → Manage categories → rename/delete a system category | 403; lock icon shown; action blocked in UI |
| 14.14 | Admin can manage system categories | Superuser → rename or delete a system category | Succeeds; ManageCategoriesDialog shows edit/delete controls for system rows |
| 14.15 | PascalCase naming enforced — invalid | Create category named `my-invoices` or `Invoice Reports` | 422 with message explaining PascalCase-with-dashes format |
| 14.16 | PascalCase naming enforced — valid | Create category named `Vendor-Invoices` | 201; category created successfully |
| 14.17 | SourcePanel scope sections | Categories exist for all three scopes | SourcePanel tree shows "Mine", per-group, and "System" sections separately |
---
## 15. Bulk Actions
| # | Test | Steps | Expected |
|---|------|-------|----------|
| 15.1 | Select rows | Tick checkboxes on multiple rows | Floating bulk actions bar appears at bottom |
| 15.2 | Bulk share | Select docs → Share with group → confirm | All selected docs shared; confirmation |
| 15.3 | Bulk delete | Select docs → Delete → confirm dialog | All selected docs deleted; bar disappears |
| 15.4 | Clear selection | Click "Clear" in bulk bar | All checkboxes deselected; bar hides |
| 15.5 | Bulk bar — "Mine" view only | Switch to "Shared with me" view | Bulk actions bar not shown (no edit rights for shared docs) |
---
## 16. Watch Directory
| # | Test | Steps | Expected |
|---|------|-------|----------|
| 16.1 | Enable watch | Doc settings page → toggle `watch_enabled` on → save | File watcher starts; backend logs confirm |
| 16.2 | Ingest new file | Drop a PDF into the bind-mounted watch directory | Document appears in "All Documents" view with `source=watch` |
| 16.3 | Sub-folder to category | Place PDF in `watch/invoices/` | Document auto-assigned to "invoices" category |
| 16.4 | Startup scan | Restart doc-service with PDFs already in watch dir | Pre-existing PDFs ingested (idempotent — no duplicates) |
| 16.5 | AI folder suggestion | `ai_folder_suggestion` enabled → ingest file | `suggested_folder` populated; confirm/reject buttons visible in slide-over |
| 16.6 | AI rename suggestion | `ai_rename_suggestion` enabled → ingest file | `suggested_filename` populated; confirm/reject buttons visible |
| 16.7 | No-remove policy | Delete PDF from watch dir | Document record remains in DB |
| 16.8 | Disable watch | Toggle `watch_enabled` off → save | Watcher stops; new files dropped are not ingested |
| 16.9 | Watch docs visible to all users | Log in as any authenticated user | Watch-ingested docs (`user_id = "watch"`) appear in "All Documents" |