Model/backend/app/db/functions/tests/test_magic_plan_functions.py

131 lines
4.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import json
from pathlib import Path
from unittest.mock import MagicMock
import pytest
from sqlalchemy.dialects import postgresql
from datatypes.magicplan.api.response import MagicPlan
from datatypes.magicplan.domain.mapper import map_plan
from datatypes.magicplan.domain.models import Plan
from backend.app.db.functions.magic_plan_functions import save_plan
FIXTURE_DIR = Path(__file__).parents[4] / "magic_plan"
PLAN_UID = "a7285ed1-878d-47eb-8aa6-85ef9e187516"
# fixture 1: 2 floors, 14 rooms total, 13 windows, 27 doors
@pytest.fixture(scope="module")
def domain_plan() -> Plan:
data = json.loads((FIXTURE_DIR / "magicplan_api_plan_response_example.json").read_text())
return map_plan(MagicPlan.model_validate(data["data"]))
def _compiled(stmt: object) -> str:
return str(stmt.compile( # type: ignore[union-attr]
dialect=postgresql.dialect(),
compile_kwargs={"literal_binds": True},
))
@pytest.fixture()
def mock_session() -> MagicMock:
session = MagicMock()
plan_result = MagicMock()
plan_result.scalar_one.return_value = 1
floor_result = MagicMock()
floor_result.scalars.return_value.all.return_value = [10, 20]
room_result = MagicMock()
room_result.scalars.return_value.all.return_value = list(range(100, 114))
session.execute.side_effect = [
plan_result, # upsert plan
None, # delete windows
None, # delete doors
None, # delete rooms
None, # delete floors
floor_result, # insert floors
room_result, # insert rooms
None, # insert windows
None, # insert doors
]
return session
# --- save_plan orchestration ---
def test_save_plan_does_not_raise(mock_session: MagicMock, domain_plan: Plan) -> None:
# Act
save_plan(mock_session, domain_plan)
def test_save_plan_upserts_plan_table_first(mock_session: MagicMock, domain_plan: Plan) -> None:
# Act
save_plan(mock_session, domain_plan)
# Assert
first_stmt = mock_session.execute.call_args_list[0][0][0]
sql = _compiled(first_stmt)
assert "magic_plan_plan" in sql
assert "INSERT" in sql.upper()
def test_save_plan_upsert_contains_plan_uid(mock_session: MagicMock, domain_plan: Plan) -> None:
# Act
save_plan(mock_session, domain_plan)
# Assert
first_stmt = mock_session.execute.call_args_list[0][0][0]
assert PLAN_UID in _compiled(first_stmt)
def test_save_plan_upsert_contains_plan_name(mock_session: MagicMock, domain_plan: Plan) -> None:
# Act
save_plan(mock_session, domain_plan)
# Assert
first_stmt = mock_session.execute.call_args_list[0][0][0]
assert domain_plan.name in _compiled(first_stmt)
def test_save_plan_deletes_floors_before_inserting(mock_session: MagicMock, domain_plan: Plan) -> None:
# Act
save_plan(mock_session, domain_plan)
# Assert — find delete and insert stmts targeting magic_plan_floor
stmts = [_compiled(c[0][0]) for c in mock_session.execute.call_args_list]
floor_delete_idx = next(i for i, s in enumerate(stmts) if "DELETE" in s.upper() and "magic_plan_floor" in s)
floor_insert_idx = next(i for i, s in enumerate(stmts) if "INSERT" in s.upper() and "magic_plan_floor" in s)
assert floor_delete_idx < floor_insert_idx
def test_save_plan_floor_insert_contains_all_levels(mock_session: MagicMock, domain_plan: Plan) -> None:
# Act
save_plan(mock_session, domain_plan)
# Assert — each floor's level value appears in the INSERT
stmts = [_compiled(c[0][0]) for c in mock_session.execute.call_args_list]
floor_insert = next(s for s in stmts if "INSERT" in s.upper() and "magic_plan_floor" in s)
for floor in domain_plan.floors:
if floor.level is not None:
assert str(floor.level) in floor_insert
def test_save_plan_room_insert_uses_all_floor_ids(mock_session: MagicMock, domain_plan: Plan) -> None:
# Act
save_plan(mock_session, domain_plan)
# Assert — both mocked floor ids (10, 20) appear in the room INSERT
stmts = [_compiled(c[0][0]) for c in mock_session.execute.call_args_list]
room_insert = next(s for s in stmts if "INSERT" in s.upper() and "magic_plan_room" in s)
assert "10" in room_insert
assert "20" in room_insert
def test_save_plan_windows_use_room_ids_from_insert(mock_session: MagicMock, domain_plan: Plan) -> None:
# Act
save_plan(mock_session, domain_plan)
# Assert — window INSERT references one of the mocked room ids (100113)
stmts = [_compiled(c[0][0]) for c in mock_session.execute.call_args_list]
window_insert = next(s for s in stmts if "INSERT" in s.upper() and "magic_plan_window" in s)
assert any(str(rid) in window_insert for rid in range(100, 114))