You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
fithia2/tests/integration/test_review_queue_integrati...

119 lines
3.5 KiB
Python

"""Integration test: merger output → review queue creation."""
from __future__ import annotations
import copy
from unittest.mock import AsyncMock, MagicMock
import pytest
pytestmark = pytest.mark.integration
_RULE_OUTPUT = {
"schema_version": "1.0.0",
"document_id": "DOC::test",
"parser_kind": "rule",
"event_type": "earnings_release",
"event_direction": "unknown", # low confidence
"event_date": "2026-01-01",
"filing_time_bucket": "post_market",
"headline": "",
"summary": "Earnings results.",
"guidance": {"status": "unclear", "scope": "unknown", "notes": ""},
"signals": {
"demand_strength": "unknown",
"pricing_power": "unknown",
"backlog_or_bookings": "unknown",
"customer_expansion": "unknown",
"margin_quality": "unknown",
},
"risk_flags": {
"oneoff_item": True,
"tax_benefit": False,
"valuation_gain": False,
"non_gaap_heavy": True,
"financing_related": False,
"legal_or_regulatory_overhang": False,
},
"evidence": [],
"confidence": {
"overall": 0.40, # low
"event_type": 0.60,
"event_direction": 0.30,
"guidance": 0.40,
"risk_flags": 0.70,
},
"warnings": [],
}
def _make_mock_session_with_no_existing() -> AsyncMock:
session = AsyncMock()
mock_result = MagicMock()
mock_result.scalar_one_or_none.return_value = None
session.execute = AsyncMock(return_value=mock_result)
session.add = MagicMock()
session.flush = AsyncMock()
return session
@pytest.mark.asyncio
async def test_low_confidence_merge_creates_review_item() -> None:
"""A low-confidence merged record triggers review item creation."""
from libs.parser.merger import merge, should_queue_for_review
from libs.review.queue import create_review_item
merged = merge(_RULE_OUTPUT, None) # No LLM
should_queue, reason_codes = should_queue_for_review(merged)
assert should_queue is True
assert "low_confidence" in reason_codes
# Mock session for review item creation
session = _make_mock_session_with_no_existing()
await create_review_item(
session=session,
entity_type="parser_event",
entity_id=merged["document_id"],
priority="P1",
reason_codes=reason_codes,
snapshot_refs={"document_id": merged["document_id"]},
)
session.add.assert_called_once()
@pytest.mark.asyncio
async def test_conflict_merge_creates_p0_review_item() -> None:
"""A rule/LLM conflict triggers P0 review item."""
from libs.parser.merger import merge, should_queue_for_review
from libs.review.queue import create_review_item
llm_conflict = copy.deepcopy(_RULE_OUTPUT)
llm_conflict["parser_kind"] = "llm"
llm_conflict["event_type"] = "guidance_update" # Conflict
llm_conflict["confidence"]["overall"] = 0.80
llm_conflict["confidence"]["event_type"] = 0.85
rule_high = copy.deepcopy(_RULE_OUTPUT)
rule_high["confidence"]["overall"] = 0.80
rule_high["confidence"]["event_type"] = 0.90
merged = merge(rule_high, llm_conflict)
should_queue, reason_codes = should_queue_for_review(merged)
assert should_queue is True
session = _make_mock_session_with_no_existing()
await create_review_item(
session=session,
entity_type="parser_event",
entity_id=merged["document_id"],
priority="P0",
reason_codes=reason_codes,
snapshot_refs={"document_id": merged["document_id"]},
)
session.add.assert_called_once()