"""Тесты parcel_functional_zones (#1058) — read-side lookup функциональных зон генплана.""" from __future__ import annotations from typing import Any from sqlalchemy.exc import OperationalError, ProgrammingError from app.services.site_finder.functional_zone_lookup import parcel_functional_zones class _Result: def __init__(self, rows: list[dict[str, Any]]) -> None: self._rows = rows def mappings(self) -> _Result: return self def all(self) -> list[dict[str, Any]]: return self._rows class _FakeDB: def __init__( self, rows: list[dict[str, Any]] | None = None, raise_exc: Exception | None = None, ) -> None: self._rows = rows or [] self._raise = raise_exc def execute(self, sql: Any, params: dict[str, Any] | None = None) -> _Result: if self._raise is not None: raise self._raise return _Result(self._rows) _WKT = "POLYGON((60.5 56.8, 60.6 56.8, 60.6 56.9, 60.5 56.9, 60.5 56.8))" def test_returns_zones_for_parcel() -> None: """Обычный случай: строки из БД → список dict с нужными ключами.""" rows = [ { "zone_type": "Жилые зоны", "status": "Существующий", "area_ha": 15.3, "zone_class_code": "Ж", }, { "zone_type": "Общественные зоны", "status": "Планируемый", "area_ha": None, "zone_class_code": "О", }, ] result = parcel_functional_zones(_FakeDB(rows), _WKT) assert len(result) == 2 first = result[0] assert first["zone_type"] == "Жилые зоны" assert first["status"] == "Существующий" assert first["area_ha"] == 15.3 assert first["zone_class_code"] == "Ж" second = result[1] assert second["area_ha"] is None # NULL → None (не падает) def test_empty_when_no_wkt() -> None: """parcel_wkt=None → пустой список без запроса к БД.""" result = parcel_functional_zones(_FakeDB([{"zone_type": "Жилые зоны"}]), None) assert result == [] def test_empty_when_no_overlap() -> None: """БД вернула 0 строк → пустой список.""" result = parcel_functional_zones(_FakeDB([]), _WKT) assert result == [] def test_graceful_when_table_missing_operational_error() -> None: """OperationalError (таблица не задеплоена) → [] без падения.""" db = _FakeDB(raise_exc=OperationalError("stmt", {}, Exception("no such table"))) result = parcel_functional_zones(db, _WKT) assert result == [] def test_graceful_when_table_missing_programming_error() -> None: """ProgrammingError (e.g. relation не существует) → [] без падения.""" db = _FakeDB(raise_exc=ProgrammingError("stmt", {}, Exception("relation does not exist"))) result = parcel_functional_zones(db, _WKT) assert result == [] def test_empty_string_wkt_treated_as_falsy() -> None: """Пустая строка wkt → пустой список (falsy guard).""" result = parcel_functional_zones(_FakeDB([]), "") assert result == []