Files
fuj-management/legacy/tests/test_match_members.py
T
kacerrandClaude Opus 5.5 022facc957
Deploy to K8s / deploy (push) Successful in 20s
refactor: move Python implementation to legacy/, make Go primary
Go (go/) becomes the primary implementation. The original Python
version moves to legacy/ and is kept runnable; new features are still
built in both (see the Dual implementation rule in CLAUDE.md).

- git mv app.py, scripts/, templates/, tests/, pyproject.toml, uv.lock
  and build/ into legacy/
- Makefile: Python targets point at legacy/, venv in legacy/.venv,
  CREDENTIALS_PATH exported for the root .secret/ file
- CI and make image build the Python image with legacy/ as context;
  the Makefile is no longer copied into the image
- legacy/.dockerignore moved to the context root so it takes effect
- CLAUDE.md, docs/README.md, Go comments, fixture README, capture
  script and VS Code launch config updated to the new layout

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 11:33:57 +02:00

73 lines
3.0 KiB
Python

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()