Files
boardroom-map/orchestrator/tests/test_decks.py
T
Jonathan KirkwoodandClaude Fable 5 b1d7aed9f4 Implement BDEF v1.1 grading: scoring core, per-deck pipeline, ledger, dashboard, StartOS layer
- Deterministic scoring.py (quant 60 / qual 40 / flags -15, profitability heaviest)
- Per-company JSON ledger with forecast-target chaining deck N-1 -> N
- Single-shot sandbox agent with guided-JSON fallback ladder (no tool loop)
- Portfolio dashboard with sparklines, KPI hit rates, BDEF category bars
- 48 unit tests green; endpoints smoke-tested; npm check+build green

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 14:15:12 -05:00

119 lines
5.4 KiB
Python

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