from backend.red_flags import ( evaluate_red_flags, compute_risk_score, overall_confidence, get_value, FLAG_SEVERITY, ) class FakeGraph: def __init__(self, data): self._data = data def get_company_metrics(self, company): return self._data.get(company, {}) FAKE_DATA = { "HDFC Bank": { "2023": { "deposits": {"value": 1_900_000_00_00_000, "confidence": "high"}, "gross_npa_pct": 1.3, "net_npa_pct": 0.4, "casa_ratio": 44.0, "capital_adequacy": 18.9, }, "2024": { "profit_after_tax": {"value": 608_120_00_00_000, "confidence": "high"}, "deposits": {"value": 1_500_000_00_00_000, "confidence": "high"}, "gross_npa_pct": 6.2, "net_npa_pct": 0.33, "casa_ratio": 28.0, "capital_adequacy": 19.3, }, }, "Infosys": { "2023": {"revenue": {"value": 1_500_000_000_000, "confidence": "high"}}, "2024": { "revenue": {"value": 1_300_000_000_000, "confidence": "high"}, "net_income": {"value": -50_000_000, "confidence": "medium"}, "attrition": 27.5, }, }, } def test_get_value_normalizes_both_shapes(): assert get_value({"value": 5.0, "confidence": "high"}) == (5.0, "high") assert get_value(3.2) == (3.2, "medium") assert get_value(None) == (None, None) def test_bank_flags_trigger(): result = evaluate_red_flags(FakeGraph(FAKE_DATA), "HDFC Bank", "2024", sector="BANK") flag_names = {f["flag"] for f in result["flags_triggered"]} assert "HIGH_GROSS_NPA" in flag_names # 6.2 > 5 assert "LOW_CASA" in flag_names # 28 < 30 assert "DEPOSIT_DECLINE_YOY" in flag_names # 1.9e15 -> 1.5e15 is >10% assert result["risk_score"] > 0 def test_it_flags_trigger(): result = evaluate_red_flags(FakeGraph(FAKE_DATA), "Infosys", "2024", sector="IT") flag_names = {f["flag"] for f in result["flags_triggered"]} assert "HIGH_ATTRITION" in flag_names # 27.5 > 25 assert "REVENUE_DECLINE_YOY" in flag_names # >5% decline assert "NEGATIVE_NET_INCOME" in flag_names def test_missing_filing_returns_error_not_crash(): result = evaluate_red_flags(FakeGraph(FAKE_DATA), "Nobody", "2024", sector="BANK") assert result["risk_score"] is None assert "error" in result def test_risk_score_capped_at_100(): flags = [{"flag": "HIGH_GROSS_NPA"}] * 10 assert compute_risk_score(flags) == 100 def test_overall_confidence_is_weakest_link(): flags = [ {"flag": "A", "confidence": "high"}, {"flag": "B", "confidence": "low"}, ] assert overall_confidence(flags) == "low" assert overall_confidence([]) == "high" def test_severity_table_has_entries_for_core_flags(): for flag in ("HIGH_GROSS_NPA", "NEGATIVE_PAT", "HIGH_ATTRITION", "HIGH_DEBT_EQUITY"): assert flag in FLAG_SEVERITY