# Test Report – T02: Vehicle Management + mobile.de Push + Vehicle UI **Date**: 2026-07-14 **Task**: T02 **Status**: PASSED ## Backend Tests **Command**: `cd backend && python -m pytest tests/test_vehicles.py tests/test_mobilede.py tests/test_vehicles_extra.py --cov=app.services.vehicle_service --cov=app.services.mobilede_service --cov=app.routers.vehicles --cov-report=term-missing -v` **Result**: 73 passed in 18.84s ### Coverage Report | Module | Stmts | Miss | Cover | |--------|-------|------|-------| | app/routers/vehicles.py | 63 | 25 | 60% | | app/services/mobilede_service.py | 122 | 24 | 80% | | app/services/vehicle_service.py | 86 | 1 | 99% | | **TOTAL** | **271** | **50** | **82%** | **Coverage target**: >= 80% → **MET** (82% total) ### Test Categories #### test_vehicles.py (27 tests) - TestVehicleList: 7 tests (pagination, filter by type/availability/price, sort, search, auth required) - TestVehicleCreate: 6 tests (201 on valid, 422 on missing make/fin/short fin, 409 on duplicate FIN, auto-compute power_hp) - TestVehicleDetail: 2 tests (200 on found, 404 on nonexistent) - TestVehicleUpdate: 3 tests (200 on update, 404 on nonexistent, 400 on no fields) - TestVehicleDelete: 4 tests (200 with deleted_at, 404 on nonexistent, not in list after delete, 404 on detail after delete) - TestMobileDePush: 2 tests (202 on push, 404 on nonexistent vehicle) - TestMobileDeStatus: 3 tests (200 with no listing, 200 with synced listing, 404 on nonexistent) #### test_mobilede.py (18 tests) - TestFieldMapping: 8 tests (LKW, Baumaschine, PKW, Stapler, Transporter, no optional fields, lkw_type with prefix, unknown lkw_type fallback) - TestPushListing: 3 tests (success, HTTP error, request error) - TestUpdateListing: 2 tests (success, no ad_id) - TestDeleteListing: 2 tests (success, no ad_id) - TestGetListingStatus: 2 tests (returns latest, returns none) - TestRetryFailedListing: 2 tests (succeeds within max retries, exceeds max retries) #### test_vehicles_extra.py (28 tests) - TestVehicleServiceDirect: 21 tests (list empty, pagination, sort asc, invalid sort, min/max price, search by fin/location, get by fin, create, duplicate fin, update, not found, duplicate fin update, same fin, soft delete, not found, get by id not found, excludes deleted) - TestRouterAdditionalPaths: 7 tests (all filters combined, verkaeufer allowed, fin duplicate 409, empty result, invalid UUID 422, push failure 202, status after failed push) ## Frontend Tests **Command**: `cd frontend && npx vitest run tests/vehicles.test.tsx` **Result**: 16 passed in 2.21s ### Test Categories #### VehicleList (5 tests) - Renders vehicle list with filters and table - Displays vehicles in table after loading - Shows pagination when total > page_size - Shows error message on API failure - Calls listVehicles with type filter when changed #### VehicleForm (4 tests) - Renders form with all required fields - Shows validation errors for empty required fields - Shows error for FIN not 17 characters - Calls createVehicle on submit with valid data #### VehicleDetail (3 tests) - Renders vehicle details after loading - Shows mobile.de status section - Shows error message on API failure #### MobileDeStatus (4 tests) - Renders with pending status when no listing exists - Shows synced status after successful push - Shows error log when sync failed - Calls pushToMobileDe when push button is clicked ## Smoke Test - Backend: All API endpoints tested via HTTPX ASGI transport with real PostgreSQL test DB - Frontend: All components tested with React Testing Library and mocked API calls - mobile.de: All HTTP calls mocked with httpx.AsyncClient patches, no real API calls made - Auth: All vehicle endpoints require JWT Bearer token (verified with 401 test) - Soft-delete: Verified deleted_at is set and vehicle excluded from subsequent queries ## Acceptance Criteria Verification | Criterion | Status | Evidence | |-----------|--------|----------| | GET /api/v1/vehicles → 200 + paginated list | ✅ | test_list_vehicles_returns_200_with_pagination | | GET /api/v1/vehicles?type=lkw&availability=available → 200 + filtered | ✅ | test_list_vehicles_filter_by_type, test_list_vehicles_filter_by_availability | | GET /api/v1/vehicles?sort=-created_at → 200 + sorted | ✅ | test_list_vehicles_sort_descending | | GET /api/v1/vehicles/:id → 200 + detail, nonexistent → 404 | ✅ | test_get_vehicle_returns_200, test_get_vehicle_nonexistent_returns_404 | | POST /api/v1/vehicles valid → 201, missing make → 422 | ✅ | test_create_vehicle_returns_201, test_create_vehicle_missing_make_returns_422 | | PUT /api/v1/vehicles/:id → 200 + updated | ✅ | test_update_vehicle_returns_200 | | DELETE /api/v1/vehicles/:id → 200 + deleted_at set | ✅ | test_delete_vehicle_returns_200_with_deleted_at | | POST /api/v1/vehicles/:id/mobile-de/push → 202 (async) | ✅ | test_push_returns_202 | | GET /api/v1/vehicles/:id/mobile-de/status → 200 + sync info | ✅ | test_status_returns_200_with_synced_listing | | mobile.de push sends correct Ad format (mocked) | ✅ | test_map_fields_basic_lkw, test_push_listing_success | | Frontend Vehicle List renders table with filter+pagination | ✅ | VehicleList test suite (5 tests) | | Frontend Vehicle Detail shows all fields + mobile.de status | ✅ | VehicleDetail test suite (3 tests) | | Frontend Create Form validates required fields | ✅ | VehicleForm test suite (4 tests) | | pytest coverage >= 80% vehicle module | ✅ | 82% total coverage |