InsuranceBot / tests /test_bug4143_fixes.py
rohitsar567's picture
#41 + #43: fix family-history re-ask + unverifiable-UIN warning
ba47227
Raw
History Blame Contribute Delete
4.42 kB
"""Regression tests for #41 + #43 (2026-05-21).
#41 β€” the post-recap pricing bundle re-asked family medical history even
after the user answered "no family history". Root cause: an explicit
negative answer coerces to [] and save_profile_field dropped it as
"normalized_empty" β†’ the slot stayed unset β†’ the gate re-asked it.
Fix: save_profile_field records an explicit-none family-history answer on
profile.asked, and _unresolved_pricing_bundle treats an answered (asked)
slot as resolved even when its value is empty.
#43 β€” a comparison reply citing a genuine catalogue UIN (not echoed in
this turn's retrieved chunks) was wrongly flagged "could not be verified
against our records". _verify_prose_grounding now treats a real
catalogue UIN as verified-by-definition.
"""
import unittest
from backend import single_brain
from backend.brain_tools import save_profile_field, _unresolved_pricing_bundle
from backend.session_state import SessionState
from backend.main import _catalogue_uin_index
class TestBug41FamilyHistoryNoneResolved(unittest.TestCase):
def test_explicit_none_answer_is_recorded_as_asked(self):
for neg in ("none", "no", "no family history",
"no family medical history"):
s = SessionState(session_id="b41a_" + neg[:4])
r = save_profile_field(s, "family_medical_history", neg)
self.assertTrue(r.get("saved"),
f"#41: explicit-none {neg!r} not accepted: {r}")
self.assertIn("family_medical_history", s.profile.asked,
f"#41: {neg!r} not recorded on profile.asked")
def test_bundle_gate_does_not_reask_an_answered_none(self):
s = SessionState(session_id="b41b")
save_profile_field(s, "desired_sum_insured_inr", "1000000")
save_profile_field(s, "budget_band", "15k_30k")
save_profile_field(s, "copay_pct", "0")
save_profile_field(s, "smoker", "no")
# before answering family history β†’ it IS in the re-ask set
self.assertIn("family_medical_history",
_unresolved_pricing_bundle(s.profile, s))
# user answers "no family history" β†’ must become RESOLVED
save_profile_field(s, "family_medical_history", "none")
self.assertNotIn("family_medical_history",
_unresolved_pricing_bundle(s.profile, s),
"#41: family history re-asked after it was answered")
def test_affirmative_family_history_still_saved_normally(self):
s = SessionState(session_id="b41c")
r = save_profile_field(s, "family_medical_history", "diabetes")
self.assertTrue(r.get("saved"))
self.assertTrue(s.profile.family_medical_history) # non-empty value
self.assertNotIn("family_medical_history",
_unresolved_pricing_bundle(s.profile, s))
def test_garbage_empty_still_dropped(self):
# a None/garbage save must still be rejected (KI-091/094 β€” never
# overwrite a captured slot with an empty extraction)
s = SessionState(session_id="b41d")
r = save_profile_field(s, "family_medical_history", None)
self.assertFalse(r.get("saved"))
self.assertNotIn("family_medical_history", s.profile.asked)
class TestBug43CatalogueUinIsVerified(unittest.TestCase):
def test_real_catalogue_uin_in_prose_is_not_flagged(self):
uin = next(iter(_catalogue_uin_index())) # a genuine catalogue UIN
ok, reasons = single_brain._verify_prose_grounding(
f"Comparison table. Policy A [Source: ..., {uin}] is strong.",
[], # no retrieved chunks this turn
)
self.assertTrue(ok, f"#43: catalogue UIN {uin} wrongly flagged: {reasons}")
self.assertEqual(reasons, [])
def test_fabricated_uin_is_still_flagged(self):
ok, reasons = single_brain._verify_prose_grounding(
"Policy X [Source: Bogus, ZZZHLIP99999V999999] is great.", [])
self.assertFalse(ok, "#43: a fabricated UIN must still be flagged")
self.assertTrue(reasons)
def test_uin_grounded_in_a_retrieved_chunk_passes(self):
ok, _ = single_brain._verify_prose_grounding(
"Policy [Source: P, ZZZHLIP99999V999999].",
[{"uin_code": "ZZZHLIP99999V999999", "chunk_text": ""}])
self.assertTrue(ok)
if __name__ == "__main__":
unittest.main()