| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173 |
- from __future__ import annotations
- class FakeGovernanceMetricsService:
- def __init__(self):
- self.calls = []
- def summary(self, access):
- self.calls.append(("summary", access))
- return {
- "scope": {
- "global_access": access.global_access,
- "business_domain_uids": list(access.business_domain_uids),
- },
- "metrics": [
- {
- "code": "asset_completeness",
- "name": "台账完整率",
- "definition": "固定口径",
- "numerator": 2,
- "denominator": 3,
- "rate": 0.666667,
- "status": "available",
- "states": ["complete", "incomplete"],
- }
- ],
- }
- def details(self, access, **filters):
- self.calls.append(("details", access, filters))
- return {
- "metric": {
- "code": filters["metric"],
- "name": "台账完整率",
- "definition": "固定口径",
- },
- "state": filters["state"],
- "records": [{"asset_uid": "asset-1", "asset_name": "循环泵"}],
- "page": int(filters["page"]),
- "page_size": int(filters["page_size"]),
- "total": 1,
- }
- def _client(monkeypatch, *, role="viewer"):
- from app import create_app
- from app.api.data_development import routes
- from app.core.data_research.governance_metrics import GovernanceMetricAccess
- service = FakeGovernanceMetricsService()
- monkeypatch.setattr(
- "app.core.system.permissions.authenticate_request",
- lambda: {
- "id": "00000000-0000-7000-8000-000000000111",
- "roles": [role],
- },
- )
- monkeypatch.setattr(
- routes,
- "get_governance_metrics_service",
- lambda: service,
- raising=False,
- )
- monkeypatch.setattr(
- routes,
- "_governance_metric_access",
- lambda: GovernanceMetricAccess(
- global_access=role == "admin",
- business_domain_uids=(
- () if role == "admin" else ("domain-a",)
- ),
- ),
- raising=False,
- )
- app = create_app()
- app.config.update(TESTING=True)
- return app.test_client(), service
- def test_viewer_reads_summary_with_server_derived_scope(monkeypatch):
- http, service = _client(monkeypatch)
- response = http.get(
- "/api/development/v1/governance-metrics/summary"
- )
- assert response.status_code == 200
- data = response.get_json()["data"]
- assert data["scope"] == {
- "global_access": False,
- "business_domain_uids": ["domain-a"],
- }
- assert data["metrics"][0]["rate"] == 0.666667
- assert service.calls[0][0] == "summary"
- def test_viewer_traces_metric_to_bounded_details(monkeypatch):
- http, service = _client(monkeypatch)
- response = http.get(
- "/api/development/v1/governance-metrics/details"
- "?metric=asset_completeness&state=incomplete&page=2&page_size=25"
- )
- assert response.status_code == 200
- data = response.get_json()["data"]
- assert data["records"] == [
- {"asset_uid": "asset-1", "asset_name": "循环泵"}
- ]
- assert service.calls[-1][2] == {
- "metric": "asset_completeness",
- "state": "incomplete",
- "page": "2",
- "page_size": "25",
- }
- def test_invalid_metric_returns_safe_400_contract(monkeypatch):
- from app.core.data_research.errors import GovernanceMetricInvalid
- http, service = _client(monkeypatch)
- def invalid(*_args, **_kwargs):
- raise GovernanceMetricInvalid("unsupported metric")
- service.details = invalid
- response = http.get(
- "/api/development/v1/governance-metrics/details"
- "?metric=ranking&state=top"
- )
- assert response.status_code == 400
- assert response.get_json()["error"]["code"] == (
- "GOVERNANCE_METRIC_INVALID"
- )
- def test_unexpected_repository_failure_uses_existing_safe_error(monkeypatch):
- http, service = _client(monkeypatch)
- def unavailable(*_args, **_kwargs):
- raise RuntimeError("database secret")
- service.summary = unavailable
- response = http.get(
- "/api/development/v1/governance-metrics/summary"
- )
- assert response.status_code == 500
- payload = response.get_json()
- assert payload["message"] == "数据采集任务处理失败"
- assert "database secret" not in repr(payload)
- def test_admin_scope_is_global_and_anonymous_is_denied(monkeypatch):
- admin_http, service = _client(monkeypatch, role="admin")
- admin_response = admin_http.get(
- "/api/development/v1/governance-metrics/summary"
- )
- assert admin_response.status_code == 200
- assert service.calls[0][1].global_access is True
- monkeypatch.setattr(
- "app.core.system.permissions.authenticate_request",
- lambda: None,
- )
- from app import create_app
- anonymous_response = create_app().test_client().get(
- "/api/development/v1/governance-metrics/summary"
- )
- assert anonymous_response.status_code == 401
|