"""Tests for decks.py: slugify, period parsing/sorting, inbox discovery.""" import os import sys import tempfile import unittest sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) import decks class TestSlugify(unittest.TestCase): def test_basic(self): self.assertEqual(decks.slugify("Acme Robotics"), "acme-robotics") self.assertEqual(decks.slugify(" Acme, Inc. (US) "), "acme-inc-us") self.assertEqual(decks.slugify("ALLCAPS"), "allcaps") self.assertEqual(decks.slugify(""), "company") self.assertEqual(decks.slugify("---"), "company") class TestParsePeriod(unittest.TestCase): def test_quarters(self): self.assertEqual(decks.parse_period_from_name("acme_2026-Q2_board.pdf"), "2026-Q2") self.assertEqual(decks.parse_period_from_name("2026Q4 deck.pptx"), "2026-Q4") self.assertEqual(decks.parse_period_from_name("Q3 2025 update.pptx"), "2025-Q3") self.assertEqual(decks.parse_period_from_name("q1_2024_board.docx"), "2024-Q1") def test_halves(self): self.assertEqual(decks.parse_period_from_name("board-2026-H1.docx"), "2026-H1") self.assertEqual(decks.parse_period_from_name("2025H2-review.pdf"), "2025-H2") def test_months(self): self.assertEqual(decks.parse_period_from_name("acme 2026-05 board.pdf"), "2026-05") self.assertEqual(decks.parse_period_from_name("2026_12_flash.txt"), "2026-12") self.assertIsNone(decks.parse_period_from_name("2026-13 notes.pdf")) self.assertIsNone(decks.parse_period_from_name("2026-00 notes.pdf")) def test_fiscal_year(self): self.assertEqual(decks.parse_period_from_name("FY2025 review.pdf"), "FY2025") self.assertEqual(decks.parse_period_from_name("fy-2024 plan.txt"), "FY2024") self.assertEqual(decks.parse_period_from_name("FY 2026 budget.docx"), "FY2026") def test_no_period(self): self.assertIsNone(decks.parse_period_from_name("notes.txt")) self.assertIsNone(decks.parse_period_from_name("budget_2027.xlsx")) self.assertIsNone(decks.parse_period_from_name("Q5 2026.pdf")) def test_quarter_wins_over_month(self): # "2026-Q2" must not be misread; Q pattern is checked before YYYY-MM. self.assertEqual(decks.parse_period_from_name("2026-Q2 and 2026-05.pdf"), "2026-Q2") def test_not_inside_digit_runs(self): self.assertIsNone(decks.parse_period_from_name("doc-20261-05.pdf")) class TestPeriodSortKey(unittest.TestCase): def test_ordering_mixed_granularities(self): ordered = ["FY2025", "2025-Q4", "2026-H1", "2026-Q1", "2026-01", "2026-Q2", "2026-05", "2026-H2", "2026-Q4"] self.assertEqual(sorted(ordered, key=decks.period_sort_key), ordered) def test_start_months(self): self.assertEqual(decks.period_sort_key("2026-Q2")[:2], (2026, 4)) self.assertEqual(decks.period_sort_key("2026-H2")[:2], (2026, 7)) self.assertEqual(decks.period_sort_key("2026-11")[:2], (2026, 11)) self.assertEqual(decks.period_sort_key("FY2026")[:2], (2026, 1)) def test_unknown_sorts_last(self): keys = [decks.period_sort_key(p) for p in ("2026-Q4", None, "garbage", "FY2026")] self.assertEqual(max(keys), decks.period_sort_key(None)) self.assertEqual(decks.period_sort_key(None), decks.period_sort_key("garbage")) self.assertGreater(decks.period_sort_key(None), decks.period_sort_key("2099-Q4")) class TestDiscover(unittest.TestCase): def _touch(self, *parts): path = os.path.join(*parts) os.makedirs(os.path.dirname(path), exist_ok=True) with open(path, "w") as f: f.write("x") def test_discover(self): with tempfile.TemporaryDirectory() as tmp: inbox = os.path.join(tmp, "inbox") self._touch(inbox, "Acme Robotics", "acme-2026-Q1.pdf") self._touch(inbox, "Acme Robotics", "acme-2026-Q1-appendix.txt") self._touch(inbox, "Acme Robotics", "acme-2026-Q2.pptx") self._touch(inbox, "Acme Robotics", "chart-2026-Q2.png") self._touch(inbox, "Acme Robotics", "notes.txt") self._touch(inbox, "Acme Robotics", ".DS_Store") self._touch(inbox, "beta-corp", "deck 2026-H1.docx") self._touch(inbox, "stray.pdf") out = decks.discover(inbox) self.assertEqual(out["skipped"], ["stray.pdf"]) units = out["units"] keys = [(u["company_slug"], u["period"], u["period_source"]) for u in units] self.assertEqual(keys, [ ("acme-robotics", "2026-Q1", "filename"), ("acme-robotics", "2026-Q2", "filename"), ("acme-robotics", None, "unknown"), ("beta-corp", "2026-H1", "filename"), ]) q1 = units[0] self.assertEqual([os.path.basename(f) for f in q1["files"]], ["acme-2026-Q1-appendix.txt", "acme-2026-Q1.pdf"]) self.assertTrue(all(os.path.isabs(f) for f in q1["files"])) q2 = units[1] self.assertEqual([os.path.basename(f) for f in q2["files"]], ["acme-2026-Q2.pptx"]) self.assertEqual(q2["ignored"], ["chart-2026-Q2.png"]) self.assertEqual([os.path.basename(f) for f in units[2]["files"]], ["notes.txt"]) def test_missing_inbox(self): self.assertEqual(decks.discover("/nonexistent/inbox"), {"units": [], "skipped": []}) if __name__ == "__main__": unittest.main()