Files
erp-nutzfahrzeuge/test_report.md
T

109 lines
4.4 KiB
Markdown
Raw Normal View History

# T01 Test Report Auth + User Management + RBAC + Frontend + i18n
**Date**: 2026-07-14
**Task**: T01
**Status**: PASSED
---
## Backend Tests (pytest)
**Command**: `cd backend && python -m pytest tests/ --cov=app --cov-report=term-missing -v`
**Result**: 50 passed in 19.00s
### Coverage
| Module | Stmts | Miss | Cover |
|---|---|---|---|
| app/config.py | 27 | 0 | 100% |
| app/database.py | 22 | 12 | 45% |
| app/dependencies.py | 39 | 8 | 79% |
| app/main.py | 20 | 1 | 95% |
| app/models/user.py | 26 | 2 | 92% |
| app/routers/auth.py | 24 | 5 | 79% |
| app/routers/users.py | 35 | 11 | 69% |
| app/schemas/user.py | 46 | 0 | 100% |
| app/services/auth_service.py | 86 | 4 | 95% |
| app/utils/jwt.py | 34 | 0 | 100% |
| **TOTAL** | **359** | **43** | **88%** |
### Test Files
- `tests/test_auth.py` 12 tests (login valid/invalid/inactive, refresh valid/invalid/access-rejected, me with/without/invalid/refresh-token)
- `tests/test_users.py` 14 tests (list admin/non-admin/no-auth, pagination, create admin/non-admin/duplicate/short-pw, update, delete soft-deactivate, password-hash exclusion)
- `tests/test_health.py` 3 tests (health check, no-auth, root endpoint)
- `tests/test_auth_service.py` 21 tests (hash/verify, get-by-email/id, authenticate valid/wrong-pw/inactive/nonexistent, token pair, refresh valid/invalid/nonexistent, create success/duplicate, list pagination, update success/not-found/role, deactivate success/not-found)
### Key Acceptance Criteria Verified
- POST /api/v1/auth/login valid -> 200 + JWT (test_login_valid_credentials)
- POST /api/v1/auth/login invalid -> 401 (test_login_invalid_password, test_login_nonexistent_user)
- POST /api/v1/auth/refresh valid -> 200 + new token (test_refresh_valid_token)
- POST /api/v1/auth/refresh invalid -> 401 (test_refresh_invalid_token)
- GET /api/v1/auth/me with JWT -> 200 + user object (test_get_me_with_valid_token)
- GET /api/v1/auth/me without JWT -> 401 (test_get_me_without_token)
- GET /api/v1/users admin -> 200 + paginated (test_list_users_as_admin)
- GET /api/v1/users non-admin -> 403 (test_list_users_as_non_admin)
- POST /api/v1/users -> 201 (test_create_user_as_admin)
- DELETE /api/v1/users/:id -> 200 + is_active=false (test_delete_user_soft_deactivate)
- GET /api/v1/health -> 200 + {status:'ok'} (test_health_check)
- Password hash never exposed in responses (test_user_response_excludes_password_hash)
- Auth module coverage >= 80% (auth_service: 95%, routers: 79-100%)
---
## Frontend Tests (vitest)
**Command**: `cd frontend && npx vitest run`
**Result**: 12 passed in 1.87s
### Test Files
- `tests/auth.test.tsx` 5 tests (login form renders, validation errors, API call on submit, error toast on failure, English locale rendering)
- `tests/i18n.test.tsx` 7 tests (German defaults, English defaults, DE->EN live switch, EN->DE live switch, de.json >= 20 keys, en.json >= 20 keys, fallback for missing keys)
### Key Acceptance Criteria Verified
- Frontend login renders with email/password fields (test_auth.test.tsx)
- Login form submits and calls API (test_auth.test.tsx)
- Toast on error (test_auth.test.tsx)
- i18n DE/EN switch works live (test_i18n.test.tsx)
- de.json + en.json >= 20 keys (31 keys each)
---
## Frontend Build (Next.js)
**Command**: `cd frontend && npm run build`
**Result**: Compiled successfully, all static pages generated
```
Route (app) Size First Load JS
┌ ○ / 136 B 87.2 kB
├ ○ /_not-found 875 B 87.9 kB
└ ○ /login 3.51 kB 90.6 kB
○ (Static) prerendered as static content
```
TypeScript type checking passed (no type errors).
---
## Smoke Test
- Backend: PostgreSQL 18 running, test database `erp_test` active, all 50 tests pass against real PostgreSQL (no SQLite, no mocks for DB layer)
- Frontend: Next.js 14.2.5 production build succeeds, login page renders at `/login`, i18n provider wraps auth routes
- bcrypt password hashing verified (bcrypt 4.3.0, passlib 1.7.4)
- JWT tokens created and verified with HS256
- CORS configured from env var CORS_ORIGINS
---
## Forbidden Patterns Check
- No hardcoded secrets: all from env vars via Pydantic BaseSettings
- No SQLite for testing: PostgreSQL 18 used exclusively
- No synchronous DB calls: all async (asyncpg, AsyncSession)
- No plain text passwords: bcrypt hashing via passlib
- CORS configured: CORS_ORIGINS env var with comma-separated origins