import json import unittest from typing import Any from uuid import UUID from B05_wf2_Route.B05_wf2_Route_Repository import ( confirm_route, create_route, create_route_statistics, get_latest_route, insert_route_points, ) class FakeCursor: def __init__(self, *, lastrowid: int = 0, row: tuple[Any, ...] | None = None) -> None: self.query = "" self.arguments: Any = () self.many_rows: list[tuple[Any, ...]] = [] self.lastrowid = lastrowid self._row = row async def __aenter__(self) -> "FakeCursor": return self async def __aexit__(self, *_exc: Any) -> None: return None async def execute(self, query: str, arguments: Any = None) -> None: self.query = query self.arguments = arguments or () async def executemany(self, query: str, rows: list[tuple[Any, ...]]) -> None: self.query = query self.many_rows = rows async def fetchone(self) -> tuple[Any, ...] | None: return self._row class FakeConnection: def __init__(self, cursor: FakeCursor) -> None: self._cursor = cursor def cursor(self) -> FakeCursor: return self._cursor PROJECT_ID = UUID("550e8400-e29b-41d4-a716-446655440000") class CreateRouteTest(unittest.IsolatedAsyncioTestCase): async def test_create(self) -> None: cursor = FakeCursor(lastrowid=7) route_id = await create_route( # type: ignore[arg-type] FakeConnection(cursor), project_id=PROJECT_ID, surface_model_id=22, total_length_m=100.0, start_chainage_m=0.0, end_chainage_m=100.0, grade_percent=[2.5, 1.8], constraints={"max_grade": 0.14}, algorithm_params={"weights": {"dist": 1.0}}, route_data_path="B05_wf2_Route/route/route_main.geojson", ) self.assertEqual(route_id, 7) self.assertIn("INSERT INTO routes", cursor.query) self.assertEqual(cursor.arguments[0], str(PROJECT_ID)) self.assertEqual(json.loads(cursor.arguments[6]), [2.5, 1.8]) async def test_rejects_path_outside_stage(self) -> None: with self.assertRaises(ValueError): await create_route( # type: ignore[arg-type] FakeConnection(FakeCursor(lastrowid=1)), project_id=PROJECT_ID, surface_model_id=None, total_length_m=None, start_chainage_m=None, end_chainage_m=None, grade_percent=None, constraints=None, algorithm_params=None, route_data_path="B04_wf1_Surface/x.geojson", ) class RoutePointsTest(unittest.IsolatedAsyncioTestCase): async def test_insert_many(self) -> None: cursor = FakeCursor() count = await insert_route_points( # type: ignore[arg-type] FakeConnection(cursor), 7, [ {"chainage_m": 0.0, "elevation_m": 5.0, "slope_percent": 0.0, "sequence_num": 0}, {"chainage_m": 10.0, "elevation_m": 5.3, "slope_percent": 3.0, "sequence_num": 1}, ], ) self.assertEqual(count, 2) self.assertEqual(len(cursor.many_rows), 2) self.assertEqual(cursor.many_rows[0][0], 7) async def test_insert_empty(self) -> None: count = await insert_route_points(FakeConnection(FakeCursor()), 7, []) # type: ignore[arg-type] self.assertEqual(count, 0) class RouteStatisticsTest(unittest.IsolatedAsyncioTestCase): async def test_create(self) -> None: cursor = FakeCursor(lastrowid=3) stat_id = await create_route_statistics( # type: ignore[arg-type] FakeConnection(cursor), route_id=7, min_slope=0.0, max_slope=7.0, mean_slope=3.5, cost_score=12.3, ) self.assertEqual(stat_id, 3) self.assertIn("INSERT INTO route_statistics", cursor.query) class LatestRouteTest(unittest.IsolatedAsyncioTestCase): async def test_found(self) -> None: import datetime row = ( 7, "CONFIRMED", 100.0, "B05_wf2_Route/route/route_main.geojson", datetime.datetime(2026, 7, 5, 12, 0, 0), ) result = await get_latest_route(FakeConnection(FakeCursor(row=row)), PROJECT_ID) # type: ignore[arg-type] self.assertEqual(result["id"], 7) self.assertEqual(result["status"], "CONFIRMED") async def test_none(self) -> None: result = await get_latest_route(FakeConnection(FakeCursor(row=None)), PROJECT_ID) # type: ignore[arg-type] self.assertIsNone(result) class ConfirmRouteTest(unittest.IsolatedAsyncioTestCase): async def test_confirm(self) -> None: cursor = FakeCursor() await confirm_route(FakeConnection(cursor), 7) # type: ignore[arg-type] self.assertIn("UPDATE routes SET status = 'CONFIRMED'", cursor.query) self.assertEqual(cursor.arguments[0], 7)