import unittest from scripts.match_payments import match_members MEMBERS = [ "Henrietta Ottová", "Tomáš Němeček (Tov)", "František Vrbík (Štrúdl)", "Jana Nováková", ] class TestMatchMembersExact(unittest.TestCase): def test_full_name_in_message_returns_only_that_member(self): # "tov" is a substring of "ottova" — the old code returned both members result = match_members("Henrietta Ottová (Heny): 04/2026", MEMBERS) names = [r[0] for r in result] self.assertEqual(names, ["Henrietta Ottová"]) self.assertTrue(all(conf == "auto" for _, conf in result)) def test_nickname_tov_not_matched_inside_ottova(self): # Bare nickname message should NOT match Tomáš via "tov" inside "ottova" result = match_members("platba ottova 04/2026", MEMBERS) names = [r[0] for r in result] self.assertNotIn("Tomáš Němeček (Tov)", names) def test_combined_payment_two_full_names(self): result = match_members("Henrietta Ottová a Tomáš Němeček 04/2026", MEMBERS) names = [r[0] for r in result] self.assertIn("Henrietta Ottová", names) self.assertIn("Tomáš Němeček (Tov)", names) self.assertTrue(all(conf == "auto" for _, conf in result)) def test_nickname_alone_still_matches_correctly(self): # "Tov" alone should still match Tomáš (as long as "ottova" is not in the text) result = match_members("Tov platba 04/2026", MEMBERS) names = [r[0] for r in result] self.assertIn("Tomáš Němeček (Tov)", names) def test_full_name_no_diacritics_still_matches(self): result = match_members("Henrietta Ottova 04/2026", MEMBERS) names = [r[0] for r in result] self.assertIn("Henrietta Ottová", names) self.assertNotIn("Tomáš Němeček (Tov)", names) def test_first_last_name_present_any_order(self): result = match_members("Platba od Nemeček Tomas 04/2026", MEMBERS) names = [r[0] for r in result] self.assertIn("Tomáš Němeček (Tov)", names) def test_shared_first_name_junior_in_roster_wins_exact(self): # Regression: two members share first name "Jáchym"; message has full name # of the junior-only member → exact match must win, no [?] on the adult. roster = ["Jáchym Hrušák (G)", "Jáchym Kubík"] result = match_members( "JIŘÍ KUBÍK Jáchym Kubík: 01/2026+03/2026+04/2026", roster ) self.assertEqual(result, [("Jáchym Kubík", "auto")]) def test_shared_first_name_without_junior_in_roster_falls_back(self): # Without Kubík in the roster (old behaviour), Hrušák wins via first-name # partial match — confirms the roster-expansion fix is the real solution. roster = ["Jáchym Hrušák (G)"] result = match_members( "JIŘÍ KUBÍK Jáchym Kubík: 01/2026+03/2026+04/2026", roster ) names = [r[0] for r in result] self.assertIn("Jáchym Hrušák (G)", names) if __name__ == "__main__": unittest.main()