test: add Vitest setup with 115 tests (backend + frontend)

This commit is contained in:
2026-06-26 14:19:50 +02:00
parent 19884b7b5d
commit f853372c90
11 changed files with 2062 additions and 42 deletions
+154 -42
View File
@@ -1,58 +1,170 @@
# Test Report: Yjs CRDT Binding with Canvas Local State
# Test Report Phase 21: Vitest Test-Setup für web-cad-neu
**Date:** 2026-06-26
**Task:** Wire Yjs CRDT binding with Canvas local state
**Datum:** 2026-06-26
**Status:** ✅ Alle Tests grün
## Build Verification
## Backend Tests (31 Tests, 3 Files)
### Test-Command
```
cd /a0/usr/workdir/web-cad-neu/frontend && npm run build
cd /a0/usr/workdir/web-cad-neu/backend && npm test
```
**Result:** ✅ PASS — 0 TypeScript errors
### Ergebnis
```
> tsc && vite build
vite v5.4.21 building for production...
transforming...
✓ 334 modules transformed.
rendering chunks...
computing gzip size...
dist/index.html 0.37 kB │ gzip: 0.27 kB
dist/assets/index-BnXa05r8.css 36.38 kB │ gzip: 6.91 kB
dist/assets/index-CjnWSOJb.js 897.00 kB │ gzip: 311.12 kB
✓ built in 3.58s
Test Files 3 passed (3)
Tests 31 passed (31)
Duration 2.92s
```
## Smoke Test
### Test-Dateien
### Step 1: App loads
- Browser opened at `http://localhost:5173/`
- Login page → Dashboard with project list rendered correctly
- Project 'Test Collab CRDT test project' visible
#### tests/health.test.ts (2 Tests)
- ✅ GET /api/health should return ok status
- ✅ GET /api/health should return valid ISO timestamp
### Step 2: CAD Editor opens
- Clicked project card → CAD editor loaded
- Topbar shows 'web-cad | Test Collab gespeichert'
- All UI panels rendered: Ribbon, LeftSidebar, CanvasArea, RightSidebar, CommandLine, StatusBar
- No console errors
#### tests/auth.test.ts (18 Tests)
- ✅ POST /api/auth/register (3 tests)
- Register new user with 201
- Reject duplicate registration with 409
- Reject missing fields with 400
- ✅ POST /api/auth/login (4 tests)
- Login with correct credentials
- Reject wrong password with 401
- Reject non-existent email with 401
- Reject missing fields with 400
- ✅ GET /api/auth/me (3 tests)
- Return current user profile with valid token
- Reject without token with 401
- Reject invalid token with 401
- ✅ PATCH /api/auth/password (6 tests)
- Change password with correct old password
- Allow login with new password
- Reject old password after change
- Reject password change with wrong old password
- Reject password change without auth
- Reject missing password fields
- ✅ POST /api/auth/logout (2 tests)
- Logout and invalidate token
- Return 204 even without token
### Step 3: Collaboration status active
- Status bar shows: 'Online · 1 weiterer' — Yjs collaboration is connected
- Connection status: connected
#### tests/projects.test.ts (11 Tests)
- ✅ POST /api/projects (3 tests)
- Create project with 201
- Reject without name with 400
- Create with default values
- ✅ GET /api/projects (1 test)
- List all projects
- ✅ GET /api/projects/:id (2 tests)
- Get single project
- Return 404 for non-existent
- ✅ PATCH /api/projects/:id (3 tests)
- Update project name
- Update project description
- Return 404 for non-existent update
- ✅ DELETE /api/projects/:id (2 tests)
- Delete a project
- Return 404 for non-existent delete
## Changes Made
## Frontend Tests (84 Tests, 3 Files)
### Files Modified
1. **`frontend/src/types/ui.types.ts`** — Added `UserCursor` import and `remoteCursors?: UserCursor[]` prop to `CanvasAreaProps`
2. **`frontend/src/App.tsx`** — 4 changes:
- Push initial data to Yjs after load (`collab.loadFromState` after `setDataLoaded`)
- Remote→local sync effect (watches `collab.elements/layers/blocks`, updates local state when different)
- Push local→Yjs in handlers (`collab.setElement` in created/modified, `collab.deleteElement` in deleted)
- Cursor tracking (`collab.setCursor` in `handleCursorMoved`, `remoteCursors={collab.cursors}` prop to CanvasArea)
3. **`frontend/src/components/CanvasArea.tsx`** — Added `remoteCursors` prop, cursor screen position computation, and remote cursor overlay rendering (colored circles with user names)
### Test-Command
```
cd /a0/usr/workdir/web-cad-neu/frontend && npm test
```
## Multi-Tab Sync Test
### Ergebnis
```
Test Files 3 passed (3)
Tests 84 passed (84)
Duration 2.40s
```
Manual verification recommended: Open two browser tabs, create an element in tab A, verify it appears in tab B via Yjs sync. The status bar 'Online · 1 weiterer' confirms the WebSocket connection is active.
### Test-Dateien
#### tests/SpatialIndex.test.ts (13 Tests)
- ✅ insert & search (4 tests)
- Find inserted element within bounding box
- Not find element outside viewport
- Find multiple elements within viewport
- Handle elements at origin
- ✅ bulkInsert (2 tests)
- Bulk insert and find all elements
- Work with empty array
- ✅ remove (2 tests)
- Remove element so it's no longer found
- Remove only specified element
- ✅ clear (1 test)
- Clear all elements from index
- ✅ edge cases (4 tests)
- Handle overlapping bounding boxes
- Handle zero-size elements
- Handle negative coordinates
- Search with large viewport
#### tests/LayerManager.test.ts (39 Tests)
- ✅ addLayer & getLayer (4 tests)
- ✅ removeLayer (3 tests)
- ✅ getLayers (2 tests)
- ✅ getVisibleLayers (1 test)
- ✅ setActiveLayer & getActiveLayer (2 tests)
- ✅ toggleVisibility (1 test)
- ✅ toggleLock (1 test)
- ✅ clear (1 test)
- ✅ renameLayer (2 tests)
- ✅ updateLayer (1 test)
- ✅ setParent (3 tests)
- ✅ getChildLayers & getLayerTree (3 tests)
- ✅ moveLayer (1 test)
- ✅ duplicateLayer (2 tests)
- ✅ filterLayers (5 tests)
- ✅ getDescendantIds (2 tests)
- ✅ isLocked (3 tests)
- ✅ getLayerColor (2 tests)
#### tests/HistoryManager.test.ts (32 Tests)
- ✅ initialize (2 tests)
- ✅ pushSnapshot (3 tests)
- ✅ undo (4 tests)
- ✅ redo (4 tests)
- ✅ canUndo & canRedo (4 tests)
- ✅ getHistory (3 tests)
- ✅ jumpTo (4 tests)
- ✅ clear (1 test)
- ✅ subscribe (2 tests)
- ✅ maxStackSize (2 tests)
- ✅ getUndoCount & getRedoCount (1 test)
- ✅ snapshot data integrity (2 tests)
## Smoke-Test Beschreibung
### Backend
- In-memory SQLite (`:memory:`) wird via `SqliteAdapter` initialisiert
- Fastify `app.inject()` simuliert HTTP-Requests ohne echte Netzwerkverbindung
- Auth-Flow vollständig getestet: Register → Login → Me → Password Change → Logout
- Project CRUD vollständig getestet: Create → List → Get → Update → Delete
- Health Endpoint gibt `{ status: 'ok', timestamp: ISO-String }` zurück
### Frontend
- SpatialIndex: rbush-basierte räumliche Suche mit insert/search/remove/clear/bulkInsert
- LayerManager: Layer-Verwaltung mit add/remove/toggle/tree/filter/duplicate
- HistoryManager: Undo/Redo-Stack mit initialize/push/undo/redo/jumpTo/subscribe/maxStackSize
- jsdom environment für DOM-abhängige Tests aktiviert
## Coverage
### Backend
- Auth CRUD: Register, Login, Logout, Me, Password-Change → alle Endpoints getestet
- Project CRUD: List, Get, Create, Update, Delete → alle Endpoints getestet
- Health: GET /api/health → getestet
### Frontend
- SpatialIndex: insert, bulkInsert, search, remove, clear → alle öffentlichen Methoden
- LayerManager: alle 18 öffentlichen Methoden getestet
- HistoryManager: initialize, pushSnapshot, undo, redo, canUndo, canRedo, getHistory, jumpTo, clear, subscribe, getUndoCount, getRedoCount → alle öffentlichen Methoden
## Verbotene Patterns Check
- ❌ Keine echten Netzwerk-Verbindungen → ✅ Nur `app.inject()`
- ❌ Keine echten WebSocket-Verbindungen → ✅ Keine WebSocket-Tests
- ❌ Keine Datei-Schreiboperationen auf echte DB-Files → ✅ Nur `:memory:`
- ❌ Keine Mock-Libraries außer vitest built-in `vi` → ✅ Nur vitest built-ins