import os import unittest from datetime import date from mileage_logger.ingest.semantic_reader import load_place_visits from mileage_logger.logic.detect_itinerary import SiteConfig, detect_itinerary FIXTURES_DIR = os.path.join(os.path.dirname(__file__), "fixtures", "semantic") CONFIG_PATH = os.path.join(os.path.dirname(__file__), "..", "config", "sites.yml") class TestItineraryDetection(unittest.TestCase): @classmethod def setUpClass(cls): cls.site_config = SiteConfig.from_yaml(CONFIG_PATH) def _load_visits(self, filename: str): path = os.path.join(FIXTURES_DIR, filename) return load_place_visits(path) def test_one_day_simple(self): visits = self._load_visits("2025-08-08.one_day_simple.json") hops = detect_itinerary(visits, self.site_config) canonical_pairs = [(h.origin, h.destination) for h in hops] expected = [ ("Home", "Lingwood Primary Academy"), ("Lingwood Primary Academy", "Heartsease Primary Academy"), ("Heartsease Primary Academy", "Home"), ] self.assertEqual(canonical_pairs, expected) def test_looping_multi_visit(self): visits = self._load_visits("2025-08-12.looping.json") hops = detect_itinerary(visits, self.site_config) canonical_pairs = [(h.origin, h.destination) for h in hops] expected = [ ("Home", "Lingwood Primary Academy"), ("Lingwood Primary Academy", "Valley Primary Academy"), ("Valley Primary Academy", "Lingwood Primary Academy"), ("Lingwood Primary Academy", "Home"), ] self.assertEqual(canonical_pairs, expected) def test_detours_ignored(self): visits = self._load_visits("day_with_detours.json") hops = detect_itinerary(visits, self.site_config) canonical_pairs = [(h.origin, h.destination) for h in hops] expected = [ ("Home", "Lingwood Primary Academy"), ("Lingwood Primary Academy", "Heartsease Primary Academy"), ("Heartsease Primary Academy", "Home"), ] self.assertEqual(canonical_pairs, expected) def test_no_home_start(self): visits = self._load_visits("no_home_start.json") hops = detect_itinerary(visits, self.site_config) canonical_pairs = [(h.origin, h.destination) for h in hops] expected = [ ("Unity SP", "Heartsease Primary Academy"), ("Heartsease Primary Academy", "Home"), ] self.assertEqual(canonical_pairs, expected) def test_cross_midnight_dates(self): visits = self._load_visits("cross_midnight.json") hops = detect_itinerary(visits, self.site_config) self.assertEqual(len(hops), 2) # Ensure canonical names self.assertEqual((hops[0].origin, hops[0].destination), ("Home", "Heartsease Primary Academy")) self.assertEqual((hops[1].origin, hops[1].destination), ("Heartsease Primary Academy", "Home")) # Check dates (local) across midnight self.assertEqual(hops[0].date, date(2025, 8, 8)) self.assertEqual(hops[1].date, date(2025, 8, 9)) if __name__ == '__main__': unittest.main()