amplegest / tests /test_verdict.py
Viney's picture
fix: keep fail-closed per fact but stop zero-verified synthesis from emptying the whole brief
b419b7b
Raw
History Blame Contribute Delete
5.68 kB
"""Pure helper tests for the PM Flash decision screen."""
from __future__ import annotations
from datetime import date
from dashboard.provenance import filing_staleness
from dashboard.verdict import (
_collect_source_types,
_evidence_coverage_label,
_normalize_watch_items,
_select_swing_factor,
)
from dashboard.signals_view import _sentiment_display_allowed
from dashboard.i18n import STRINGS, t
from dashboard.nav import NAV_ITEMS, VALID_KEYS
def test_collect_source_types_is_recursive_deduplicated_and_ordered():
brief = {
"bull_points": [{"source": "transcript, 10-Q"}],
"risks_categorized": [{"evidence": {"source": "10-K"}}],
"management_commentary": [{"source": "news"}, {"source": "10-Q"}],
"ignored": {"source": "yfinance"},
}
assert _collect_source_types(brief) == ["10-K", "10-Q", "Transcript", "News"]
def test_evidence_coverage_uses_verified_counts_with_legacy_source_fallback():
brief = {
"evidence_coverage": {
"status": "INCOMPLETE",
"verified": 7,
"unverified": 2,
"failed": 1,
"total": 10,
},
"bull_points": [{"source": "10-Q"}],
}
assert _evidence_coverage_label(brief) == "Incomplete 路 7/10 verified 路 10-Q"
assert _evidence_coverage_label(
{"bull_points": [{"source": "transcript"}]}
) == "Legacy / unverified 路 Transcript"
assert _evidence_coverage_label({
"evidence_coverage": {"status": "VERIFIED", "verified": 2, "total": 3}
}).startswith("Incomplete")
assert _evidence_coverage_label({
"evidence_coverage": {"status": "VERIFIED", "verified": 3, "total": 3}
}) == "Verified 路 3/3 verified"
def test_normalize_watch_items_supports_legacy_and_structured_values():
result = _normalize_watch_items([
"Q2 gross margin",
{
"label": "Data-center growth",
"metric": "Revenue growth",
"trigger": "below 30%",
"event_date": "Q2 FY27",
"source": "10-Q",
"status": "open",
},
{},
None,
])
assert result[0] == {
"text": "Q2 gross margin",
"metric": "",
"threshold": "",
"period": "",
"source": "",
"status": "",
}
assert result[1]["text"] == "Data-center growth"
assert result[1]["threshold"] == "below 30%"
assert result[1]["period"] == "Q2 FY27"
assert len(result) == 2
def test_select_swing_factor_prefers_material_tension_stably():
brief = {
"analytical_tensions": [
{"headline": "Watch first", "weight": "watch"},
{"headline": "Material first", "weight": "material"},
{"headline": "Material second", "weight": "material"},
]
}
factor = _select_swing_factor(brief)
assert factor is not None
assert factor["kind"] == "tension"
assert factor["headline"] == "Material first"
def test_select_swing_factor_falls_back_to_top_tell():
brief = {
"between_the_lines": [{
"observation": "Management stopped quantifying backlog",
"reading": "Visibility may be weakening",
"implication": "Watch conversion next quarter",
"signal_type": "omission",
"evidence": {
"source": "transcript",
"reliability": "MEDIUM",
"impact": "HIGH",
"evidence_snippet": "Backlog was not discussed.",
},
}]
}
factor = _select_swing_factor(brief)
assert factor is not None
assert factor["kind"] == "tell"
assert factor["headline"] == "Management stopped quantifying backlog"
assert factor["implication"] == "Watch conversion next quarter"
def test_select_swing_factor_returns_none_without_interpretive_data():
assert _select_swing_factor({}) is None
def test_sentiment_display_policy_fails_closed():
assert _sentiment_display_allowed({}) is False
assert _sentiment_display_allowed({"display_policy": {"sentiment_calibrated": "true"}}) is False
assert _sentiment_display_allowed({"display_policy": {"sentiment_calibrated": True}}) is True
def test_nav_order_is_analyst_flow():
assert VALID_KEYS == {"company", "verdict", "signals", "financials", "chat"}
assert [item["key"] for item in NAV_ITEMS] == [
"company", "verdict", "signals", "financials", "chat"
]
assert not any(item.get("secondary") for item in NAV_ITEMS)
def test_nav_items_have_no_hardcoded_display_label():
assert not any("display_label" in item for item in NAV_ITEMS)
def test_nav_i18n_labels_complete():
for item in NAV_ITEMS:
labels = STRINGS[item["i18n_key"]]
assert set(labels) == {"en", "fr", "es", "de"}
assert t("nav_company") == "Company Overview"
def test_filing_staleness_flags_old_filings():
assert filing_staleness(
"2026-07-29", today=date(2026, 8, 2)
) == {"days_old": 4, "likely_newer_filing": False}
assert filing_staleness(
"2026-07-29", today=date(2026, 12, 15)
) == {"days_old": 139, "likely_newer_filing": True}
assert filing_staleness("", today=date(2026, 8, 2)) == {
"days_old": None,
"likely_newer_filing": False,
}
assert filing_staleness("garbage", today=date(2026, 8, 2)) == {
"days_old": None,
"likely_newer_filing": False,
}
def test_partial_notice_strings_exist_in_all_languages():
for key in (
"freshness_stale_note",
"partial_brief_notice_zero",
"data_through_label",
):
assert set(STRINGS[key]) == {"en", "fr", "es", "de"}