diff --git a/test_report.md b/test_report.md index 931083f..a7dfa3f 100644 --- a/test_report.md +++ b/test_report.md @@ -1,92 +1,78 @@ -# T10 Test Report — Monitoring, Performance, Documentation & Environment Config - -**Date**: 2026-07-01 -**Task**: T10 -**Status**: ✅ ALL TESTS PASS - +IyBUMTAgVGVzdCBSZXBvcnQg4oCUIE1vbml0b3JpbmcsIFBlcmZvcm1hbmNlLCBEb2N1bWVudGF0aW9uICYgRW52aXJvbm1lbnQgQ29uZmlnCgoqKkRhdGUqKjogMjAyNi0wNy0wMQoqKlRhc2sqKjogVDEwCioqU3RhdHVzKio6IOKchSBBTEwgVEVTVFMgUEFTUwoKLS0tCgojIyBUZXN0IFJ1bgoKYGBgCmNkIC9hMC91c3Ivd29ya2Rpci9kZXYtcHJvamVjdHMvbGVvY3JtICYmIHB5dGhvbiAtbSBweXRlc3QgdGVzdHMvdGVzdF9tb25pdG9yaW5nLnB5IHRlc3RzL3Rlc3RfcGVyZm9ybWFuY2UucHkgdGVzdHMvdGVzdF9oZWFsdGgucHkgLXYgLS10Yj1zaG9ydApgYGAKCioqUmVzdWx0Kio6IDM4IHBhc3NlZCwgMiB3YXJuaW5ncyBpbiAyNC4yNHMKCiMjIyBBbGwgMzggVGVzdHMgUGFzc2VkOgoKIyMjIyB0ZXN0X21vbml0b3JpbmcucHkgKDE3IHRlc3RzKSDigJQgQUMxLTYKLSDinIUgdGVzdF9oZWFsdGhfcmV0dXJuc18yMDBfd2l0aF9jaGVja3Nfc3RydWN0dXJlIChBQzEpCi0g4pyFIHRlc3RfaGVhbHRoX2RiX2Rvd25fcmV0dXJuc19kZWdyYWRlZCAoQUMyKQotIOKchSB0ZXN0X2hlYWx0aF9ub19hdXRoX3JlcXVpcmVkCi0g4pyFIHRlc3RfY2hlY2tfZGF0YWJhc2VfcmV0dXJuc19kaWN0Ci0g4pyFIHRlc3RfY2hlY2tfcmVkaXNfcmV0dXJuc19kaWN0Ci0g4pyFIHRlc3RfY2hlY2tfc3RvcmFnZV9yZXR1cm5zX2RpY3QKLSDinIUgdGVzdF9jaGVja193b3JrZXJfcmV0dXJuc19kaWN0Ci0g4pyFIHRlc3RfbWV0cmljc19hZG1pbl9yZXR1cm5zXzIwMF90ZXh0X3BsYWluIChBQzMpCi0g4pyFIHRlc3RfbWV0cmljc19ub25fYWRtaW5fcmV0dXJuc180MDMgKEFDMykKLSDinIUgdGVzdF9tZXRyaWNzX3VuYXV0aGVudGljYXRlZF9yZXR1cm5zXzQwMQotIOKchSB0ZXN0X21ldHJpY3NfaW5jbHVkZV9yZXF1aXJlZF9tZXRyaWNfbmFtZXMgKEFDNCkKLSDinIUgdGVzdF9nZW5lcmF0ZV9tZXRyaWNzX3JldHVybnNfYnl0ZXMKLSDinIUgdGVzdF9yZWNvcmRfcmVxdWVzdF9pbmNyZW1lbnRzX2NvdW50ZXIgKEFDNSkKLSDinIUgdGVzdF9yZWNvcmRfcmVxdWVzdF9sb2dfaGFzX3JlcXVpcmVkX2ZpZWxkcyAoQUM1KQotIOKchSB0ZXN0X3JlY29yZF9lcnJvcl9sb2dzX3N0YWNrdHJhY2VfYW5kX2NvbnRleHQgKEFDNikKLSDinIUgdGVzdF9yZWNvcmRfZXJyb3Jfd2l0aG91dF90cmFjZWJhY2sKLSDinIUgdGVzdF9yZWNvcmRfYXJxX2pvYl9pbmNyZW1lbnRzX2NvdW50ZXIKCiMjIyMgdGVzdF9wZXJmb3JtYW5jZS5weSAoMTUgdGVzdHMpIOKAlCBBQzctMTIKLSDinIUgdGVzdF9saXN0X2NvbnRhY3RzX3Jlc3BvbnNlX3RpbWVfdW5kZXJfNTAwbXMgKEFDOCkKLSDinIUgdGVzdF9zZWFyY2hfY29udGFjdHNfcmVzcG9uc2VfdGltZV91bmRlcl81MDBtcyAoQUM5KQotIOKchSB0ZXN0X2xpc3RfY29udGFjdHNfcmV0dXJuc19jb3JyZWN0X3BhZ2luYXRpb24KLSDinIUgdGVzdF9wYWdlX3NpemVfb3Zlcl8xMDBfcmV0dXJuc180MjIgKEFDMTApCi0g4pyFIHRlc3RfcGFnZV9zaXplXzEwMF9hY2NlcHRlZAotIOKchSB0ZXN0X3BhZ2Vfc2l6ZV8wX3JldHVybnNfNDIyCi0g4pyFIHRlc3RfY29tcGFuaWVzX3BhZ2Vfc2l6ZV9vdmVyXzEwMF9yZXR1cm5zXzQyMgotIOKchSB0ZXN0X2Nzdl9leHBvcnRfc3RyZWFtc19jb250ZW50IChBQzEyKQotIOKchSB0ZXN0X2Nzdl9leHBvcnRfZW1wdHlfdGVuYW50Ci0g4pyFIHRlc3RfY3N2X2V4cG9ydF93aXRoX3NlYXJjaF9maWx0ZXIKLSDinIUgdGVzdF9jc3ZfZXhwb3J0X2NvbXBhbmllc19zdHJlYW1pbmcKLSDinIUgdGVzdF9jc3ZfZXhwb3J0X3JlcXVpcmVzX2F1dGgKLSDinIUgdGVzdF9zZWVkX3NjcmlwdF9leGlzdHMgKEFDNykKLSDinIUgdGVzdF9zZWVkX3NjcmlwdF9oYXNfY291bnRfYXJnCi0g4pyFIHRlc3RfY2hlY2tfaW5kZXhlc19zY3JpcHRfZXhpc3RzCgojIyMjIHRlc3RfaGVhbHRoLnB5ICg2IHRlc3RzKSDigJQgQUMxCi0g4pyFIHRlc3RfaGVhbHRoX3JldHVybnNfMjAwX3dpdGhvdXRfYXV0aAotIOKchSB0ZXN0X2hlYWx0aF9oYXNfZGF0YWJhc2VfY2hlY2sKLSDinIUgdGVzdF9oZWFsdGhfaGFzX3JlZGlzX2NoZWNrCi0g4pyFIHRlc3RfaGVhbHRoX2hhc19zdG9yYWdlX2NoZWNrCi0g4pyFIHRlc3RfaGVhbHRoX2hhc193b3JrZXJfY2hlY2sKLSDinIUgdGVzdF9oZWFsdGhfc3RhdHVzX2lzX3ZhbGlkX3ZhbHVlCgotLS0KCiMjIFJ1ZmYgQ2hlY2sKCmBgYApweXRob24gLW0gcnVmZiBjaGVjayBhcHAvY29yZS9tb25pdG9yaW5nLnB5IGFwcC9yb3V0ZXMvbWV0cmljcy5weSBhcHAvcm91dGVzL2hlYWx0aC5weSB0ZXN0cy90ZXN0X21vbml0b3JpbmcucHkgdGVzdHMvdGVzdF9wZXJmb3JtYW5jZS5weQpgYGAKCioqUmVzdWx0Kio6IEFsbCBjaGVja3MgcGFzc2VkIQoKLS0tCgojIyBEb2NzIENoZWNrCgpgYGAKdGVzdCAtZiBSRUFETUUubWQgJiYgdGVzdCAtZiBkb2NzL2FkbWluLWd1aWRlLm1kICYmIHRlc3QgLWYgZG9jcy9hcGktb3ZlcnZpZXcubWQgJiYgZWNobyAnRG9jcyBPSycKYGBgCgoqKlJlc3VsdCoqOiBEb2NzIE9LCgotLS0KCiMjIFNtb2tlIFRlc3QKCi0gQXBwIGltcG9ydHMgc3VjY2Vzc2Z1bGx5OiBgZnJvbSBhcHAubWFpbiBpbXBvcnQgY3JlYXRlX2FwcGAg4oaSIE9LCi0gSGVhbHRoIGVuZHBvaW50IHJldHVybnMgMjAwIHdpdGggYWxsIGNoZWNrcyAoZGF0YWJhc2UsIHJlZGlzLCBzdG9yYWdlLCB3b3JrZXIpOiB2ZXJpZmllZCB2aWEgZGlyZWN0IEFTR0kgY2xpZW50IHRlc3QKLSBQcm9tZXRoZXVzIG1ldHJpY3MgZW5kcG9pbnQgcmV0dXJucyB0ZXh0L3BsYWluIHdpdGggcmVxdWlyZWQgbWV0cmljIG5hbWVzIChsZW9jcm1faHR0cF9yZXF1ZXN0c190b3RhbCwgbGVvY3JtX2RiX3Bvb2xfY29ubmVjdGlvbnMsIGxlb2NybV9hcnFfam9ic190b3RhbCk6IHZlcmlmaWVkCi0gU3RydWN0dXJlZCBKU09OIGxvZ2dpbmcgcHJvZHVjZXMgZW50cmllcyB3aXRoIHRpbWVzdGFtcCwgbGV2ZWwsIGV2ZW50LCBtZXRob2QsIHBhdGgsIHN0YXR1cywgZHVyYXRpb25fbXMsIHRlbmFudF9pZDogdmVyaWZpZWQKLSBDU1YgZXhwb3J0IHVzZXMgU3RyZWFtaW5nUmVzcG9uc2Ugd2l0aCBvd24gREIgc2Vzc2lvbiAobm90IGJ1ZmZlcmVkKTogdmVyaWZpZWQKLSBwYWdlX3NpemUgPiAxMDAgcmV0dXJucyA0MjIgZm9yIGJvdGggY29udGFjdHMgYW5kIGNvbXBhbmllczogdmVyaWZpZWQK --- -## Test Run +# Settings Plugins & Roles API — Frontend Implementation -``` -cd /a0/usr/workdir/dev-projects/leocrm && python -m pytest tests/test_monitoring.py tests/test_performance.py tests/test_health.py -v --tb=short -``` +**Date**: 2026-07-03 +**Task**: SettingsPlugins.tsx (new), SettingsRoles.tsx (rewrite to API), Settings.tsx nav update, routes/index.tsx update +**Status**: ✅ ALL FILES COMMITTED -**Result**: 38 passed, 2 warnings in 24.24s +## Files Changed (7 files, 7 commits on main) -### All 38 Tests Passed: +1. **frontend/src/pages/SettingsPlugins.tsx** (NEW, 9482 bytes, 255 lines) + - Plugin management page with install/activate/deactivate/uninstall actions + - Uses usePlugins, useInstallPlugin, useActivatePlugin, useDeactivatePlugin, useUninstallPlugin hooks + - Loading skeleton, error state with refetch, empty state + - ConfirmDialog for uninstall with remove-data checkbox option + - Status badges: discovered/installed/active/inactive -#### test_monitoring.py (17 tests) — AC1-6 -- ✅ test_health_returns_200_with_checks_structure (AC1) -- ✅ test_health_db_down_returns_degraded (AC2) -- ✅ test_health_no_auth_required -- ✅ test_check_database_returns_dict -- ✅ test_check_redis_returns_dict -- ✅ test_check_storage_returns_dict -- ✅ test_check_worker_returns_dict -- ✅ test_metrics_admin_returns_200_text_plain (AC3) -- ✅ test_metrics_non_admin_returns_403 (AC3) -- ✅ test_metrics_unauthenticated_returns_401 -- ✅ test_metrics_include_required_metric_names (AC4) -- ✅ test_generate_metrics_returns_bytes -- ✅ test_record_request_increments_counter (AC5) -- ✅ test_record_request_log_has_required_fields (AC5) -- ✅ test_record_error_logs_stacktrace_and_context (AC6) -- ✅ test_record_error_without_traceback -- ✅ test_record_arq_job_increments_counter +2. **frontend/src/pages/SettingsRoles.tsx** (REWRITE, 311 lines) + - Replaced hardcoded mock data with API hooks: useRoles, useCreateRole, useUpdateRole, useDeleteRole + - Loading skeleton, error state with refetch + - Added delete role with ConfirmDialog + - Permission handling adapted to dict-based permissions (backend uses dict[str, Any]) + - Helper functions: isPermissionGranted, togglePermission, getGrantedPermissionKeys -#### test_performance.py (15 tests) — AC7-12 -- ✅ test_list_contacts_response_time_under_500ms (AC8) -- ✅ test_search_contacts_response_time_under_500ms (AC9) -- ✅ test_list_contacts_returns_correct_pagination -- ✅ test_page_size_over_100_returns_422 (AC10) -- ✅ test_page_size_100_accepted -- ✅ test_page_size_0_returns_422 -- ✅ test_companies_page_size_over_100_returns_422 -- ✅ test_csv_export_streams_content (AC12) -- ✅ test_csv_export_empty_tenant -- ✅ test_csv_export_with_search_filter -- ✅ test_csv_export_companies_streaming -- ✅ test_csv_export_requires_auth -- ✅ test_seed_script_exists (AC7) -- ✅ test_seed_script_has_count_arg -- ✅ test_check_indexes_script_exists +3. **frontend/src/pages/Settings.tsx** (UPDATE, 45 lines) + - Added plugins nav item: { to: '/settings/plugins', label: t('settings.plugins'), icon: '🧩' } -#### test_health.py (6 tests) — AC1 -- ✅ test_health_returns_200_without_auth -- ✅ test_health_has_database_check -- ✅ test_health_has_redis_check -- ✅ test_health_has_storage_check -- ✅ test_health_has_worker_check -- ✅ test_health_status_is_valid_value +4. **frontend/src/routes/index.tsx** (UPDATE, 83 lines) + - Added import: SettingsPluginsPage from '@/pages/SettingsPlugins' + - Added route: { path: 'plugins', element: } under /settings children ---- +5. **frontend/src/api/hooks.ts** (UPDATE, 535 lines) + - Added Role and Plugin TypeScript interfaces + - Added useRoles() — GET /api/v1/roles + - Added useCreateRole() — POST /api/v1/roles with cache invalidation + - Added useUpdateRole() — PATCH /api/v1/roles/:id with cache invalidation + - Added useDeleteRole() — DELETE /api/v1/roles/:id with cache invalidation + - Updated usePlugins() — improved return type handling + - Added useInstallPlugin() — POST /api/v1/plugins/:name/install + - Added useActivatePlugin() — POST /api/v1/plugins/:name/activate + - Added useDeactivatePlugin() — POST /api/v1/plugins/:name/deactivate + - Added useUninstallPlugin() — DELETE /api/v1/plugins/:name?remove_data=bool -## Ruff Check +6. **frontend/src/i18n/locales/de.json** (UPDATE) + - Added 17 new translation keys: plugins, noPlugins, pluginInstall, pluginActivate, pluginDeactivate, pluginUninstall, pluginInstalled, pluginActive, pluginInactive, pluginDiscovered, pluginInstalledSuccess, pluginActivatedSuccess, pluginDeactivatedSuccess, pluginUninstalledSuccess, pluginUninstallConfirm, pluginRemoveData, roleDeleted -``` -python -m ruff check app/core/monitoring.py app/routes/metrics.py app/routes/health.py tests/test_monitoring.py tests/test_performance.py -``` +7. **frontend/src/i18n/locales/en.json** (UPDATE) + - Same 17 new translation keys in English -**Result**: All checks passed! +## Commits (Forgejo API, branch: main) ---- +- d26efa5bb736 — fix: SettingsPlugins.tsx with actual content +- 1aa6d1ffa953 — refactor: SettingsRoles.tsx use API hooks +- ce4d41c1b8be — feat: add plugins nav item to Settings +- eb0420d726c1 — feat: add SettingsPluginsPage route +- 502cddd68cfa — feat: add role and plugin hooks to hooks.ts +- dda972187a74 — feat: add plugin translation keys to de.json +- 962ac66f7233 — feat: add plugin translation keys to en.json -## Docs Check +## Verification -``` -test -f README.md && test -f docs/admin-guide.md && test -f docs/api-overview.md && echo 'Docs OK' -``` +- ✅ SettingsPlugins.tsx content verified via Forgejo files_get (9482 bytes, correct content) +- ✅ All 7 files committed with HTTP 200/201 from Forgejo API +- ⚠️ Build verification (npm run build / tsc --noEmit) not run — no Node.js environment available in this container +- ⚠️ Smoke test not run — requires running frontend dev server with backend API -**Result**: Docs OK +## Backend API Endpoints Used ---- - -## Smoke Test - -- App imports successfully: `from app.main import create_app` → OK -- Health endpoint returns 200 with all checks (database, redis, storage, worker): verified via direct ASGI client test -- Prometheus metrics endpoint returns text/plain with required metric names (leocrm_http_requests_total, leocrm_db_pool_connections, leocrm_arq_jobs_total): verified -- Structured JSON logging produces entries with timestamp, level, event, method, path, status, duration_ms, tenant_id: verified -- CSV export uses StreamingResponse with own DB session (not buffered): verified -- page_size > 100 returns 422 for both contacts and companies: verified +- GET /api/v1/roles → { items: [{ id, name, permissions, field_permissions }] } +- POST /api/v1/roles → 201 with created role +- PATCH /api/v1/roles/:id → updated role +- DELETE /api/v1/roles/:id → 204 +- GET /api/v1/plugins → { plugins: [...], total: N } +- POST /api/v1/plugins/:name/install +- POST /api/v1/plugins/:name/activate +- POST /api/v1/plugins/:name/deactivate +- DELETE /api/v1/plugins/:name?remove_data=bool