Files
ai-contract-platform/backend/tests/test_operation_kpis_api.py
T

138 lines
5.8 KiB
Python

import unittest
from fastapi import HTTPException
from fastapi.testclient import TestClient
from app.api.operation_kpis import get_operation_kpi_service, require_current_user
from app.main import app
class StubOperationKpiService:
def get_dashboard(self, current_user):
if current_user["role"] != "admin":
raise HTTPException(status_code=403, detail="forbidden")
return {
"scope": {
"tenant_id": current_user["tenant_id"],
"usage_scope": "current_tenant",
"plan_distribution_scope": "platform_counts",
"timezone": "UTC",
},
"generated_at": "2026-05-21T00:00:00+00:00",
"periods": [
{
"key": "monthly",
"label": "本月",
"start_at": "2026-05-01T00:00:00+00:00",
"end_at": "2026-05-21T00:00:00+00:00",
"metrics": {
"ai_usage_count": 7,
"review_count": 2,
"generation_count": 2,
"chat_message_count": 1,
"report_download_count": 1,
"clause_recommendation_count": 2,
"clause_action_total": 3,
"clause_action_applied": 2,
"clause_action_ignored": 1,
"clause_action_adoption_rate_percent": 66.67,
"clause_recommendation_shown_count": 4,
"clause_recommendation_applied_count": 1,
"clause_recommendation_modified_count": 1,
"clause_recommendation_ignored_count": 1,
"clause_recommendation_adoption_rate_percent": 50.0,
"clause_recommendation_action_rate_percent": 75.0,
"quality_eval_run_count": 3,
"quality_eval_passed_count": 2,
"quality_eval_failed_count": 1,
"quality_eval_running_count": 0,
"quality_eval_pass_rate_percent": 66.67,
"quality_eval_average_score_percent": 91.5,
"legal_reference_count": 3,
"legal_reference_verified_rate_percent": 100,
},
}
],
"top_templates": [{"template_id": "tpl-1", "template_name": "采购合同模板", "usage_count": 2, "last_used_at": None}],
"clause_action_summary": {"total": 3, "applied_count": 2, "ignored_count": 1, "adoption_rate_percent": 66.67},
"risk_action_top_items": [],
"clause_recommendation_funnel": {
"total": 4,
"shown_only_count": 1,
"applied_count": 1,
"modified_count": 1,
"ignored_count": 1,
"adopted_count": 2,
"acted_count": 3,
"adoption_rate_percent": 50.0,
"action_rate_percent": 75.0,
},
"clause_recommendation_top_items": [
{
"clause_title": "验收标准与流程",
"clause_key": "acceptance",
"recommendation_kind": "missing_clause",
"action_status": "shown",
"action_count": 1,
}
],
"quality_eval_summary": {
"total_runs": 3,
"passed_runs": 2,
"failed_runs": 1,
"running_runs": 0,
"pass_rate_percent": 66.67,
"average_score_percent": 91.5,
"total_samples": 24,
"passed_samples": 21,
"sample_pass_rate_percent": 87.5,
"latest_run_id": "qualityeval-123",
"latest_subject_name": "合同文书生成默认 Prompt",
"latest_eval_domain": "prompt",
"latest_status": "passed",
"latest_finished_at": "2026-05-21T00:00:01+00:00",
},
"legal_citation_summary": {"total_reference_count": 3, "verified_reference_rate_percent": 100},
"conversion_funnel": {"trial_or_free_tenants": 1, "active_paid_tenants": 1, "plan_distribution": []},
"overage_conversion": {"current_exceeded_count": 2, "pending_overage_order_count": 1},
}
class OperationKpisApiTestCase(unittest.TestCase):
def setUp(self):
app.dependency_overrides[get_operation_kpi_service] = lambda: StubOperationKpiService()
self.client = TestClient(app)
def tearDown(self):
app.dependency_overrides.clear()
def test_admin_can_get_operation_kpi_dashboard(self):
app.dependency_overrides[require_current_user] = lambda: {
"id": "user-admin",
"tenant_id": "tenant-demo-001",
"role": "admin",
}
response = self.client.get("/api/v1/operation-kpis/dashboard")
self.assertEqual(response.status_code, 200)
self.assertEqual(response.json()["data"]["periods"][0]["metrics"]["ai_usage_count"], 7)
self.assertEqual(response.json()["data"]["quality_eval_summary"]["total_runs"], 3)
self.assertEqual(response.json()["data"]["top_templates"][0]["template_id"], "tpl-1")
def test_member_cannot_get_operation_kpi_dashboard(self):
app.dependency_overrides[require_current_user] = lambda: {
"id": "user-member",
"tenant_id": "tenant-demo-001",
"role": "member",
}
response = self.client.get("/api/v1/operation-kpis/dashboard")
self.assertEqual(response.status_code, 403)
self.assertEqual(response.json()["message"], "forbidden")
if __name__ == "__main__":
unittest.main()