fix(api): keep operator read-model gaps from breaking ai loop UI
Some checks failed
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Failing after 2m5s
CD Pipeline / build-and-deploy (push) Has been skipped
CD Pipeline / post-deploy-checks (push) Has been skipped
Some checks failed
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Failing after 2m5s
CD Pipeline / build-and-deploy (push) Has been skipped
CD Pipeline / post-deploy-checks (push) Has been skipped
This commit is contained in:
81
apps/api/tests/test_platform_read_model_fallbacks.py
Normal file
81
apps/api/tests/test_platform_read_model_fallbacks.py
Normal file
@@ -0,0 +1,81 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
|
||||
from src.api.v1.platform import events, operator_runs, truth_chain
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_quality_summary_returns_source_unavailable_when_read_model_fails(monkeypatch):
|
||||
async def broken_fetch(**kwargs):
|
||||
raise RuntimeError("quality read model unavailable")
|
||||
|
||||
observations: list[dict] = []
|
||||
|
||||
monkeypatch.setattr(truth_chain, "fetch_automation_quality_summary", broken_fetch)
|
||||
monkeypatch.setattr(
|
||||
truth_chain,
|
||||
"record_quality_summary_observation",
|
||||
lambda **kwargs: observations.append(kwargs),
|
||||
)
|
||||
|
||||
response = await truth_chain.get_automation_quality_summary(
|
||||
project_id="awoooi",
|
||||
hours=24,
|
||||
limit=30,
|
||||
)
|
||||
|
||||
assert response["source_status"] == "source_unavailable"
|
||||
assert response["evaluated_total"] == 0
|
||||
assert response["verified_auto_repair_total"] == 0
|
||||
assert response["production_claim"]["can_claim_full_auto_repair"] is False
|
||||
assert observations[0]["success"] is False
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_recurrence_endpoint_returns_empty_summary_when_read_model_fails(monkeypatch):
|
||||
async def broken_fetch(**kwargs):
|
||||
raise RuntimeError("recurrence read model unavailable")
|
||||
|
||||
monkeypatch.setattr(events, "fetch_channel_event_dossier_recurrence", broken_fetch)
|
||||
|
||||
response = await events.get_event_dossier_recurrence(
|
||||
project_id="awoooi",
|
||||
provider=None,
|
||||
limit=100,
|
||||
)
|
||||
|
||||
assert response["source_status"] == "source_unavailable"
|
||||
assert response["project_id"] == "awoooi"
|
||||
assert response["items"] == []
|
||||
assert response["summary"]["source_event_total"] == 0
|
||||
assert response["summary"]["open_work_item_group_total"] == 0
|
||||
validated = events.ChannelEventRecurrenceResponse.model_validate(response)
|
||||
assert validated.summary.source_event_total == 0
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_callback_replies_endpoint_returns_empty_page_when_read_model_fails(monkeypatch):
|
||||
async def broken_fetch(**kwargs):
|
||||
raise RuntimeError("callback reply read model unavailable")
|
||||
|
||||
monkeypatch.setattr(operator_runs, "list_callback_replies_svc", broken_fetch)
|
||||
|
||||
response = await operator_runs.list_callback_replies(
|
||||
project_id="awoooi",
|
||||
callback_reply_status=None,
|
||||
action=None,
|
||||
incident_id=None,
|
||||
page=1,
|
||||
per_page=100,
|
||||
refresh=False,
|
||||
)
|
||||
|
||||
assert response["source_status"] == "source_unavailable"
|
||||
assert response["items"] == []
|
||||
assert response["total"] == 0
|
||||
assert response["page"] == 1
|
||||
assert response["per_page"] == 100
|
||||
assert response["summary"] is None
|
||||
validated = operator_runs.ListCallbackRepliesResponse.model_validate(response)
|
||||
assert validated.total == 0
|
||||
Reference in New Issue
Block a user