gendesign/backend/tests/services/test_granddoc_lookup.py
bot-backend fe67e60d48
All checks were successful
Deploy / changes (push) Successful in 6s
Deploy / build-backend (push) Successful in 1m30s
Deploy / build-frontend (push) Has been skipped
Deploy / build-worker (push) Successful in 2m33s
Deploy / deploy (push) Successful in 1m9s
feat(sf): граддокументация (статус+ПАГЕ-реквизиты) из planning_projects в analyze (#1154)
Co-authored-by: bot-backend <bot-backend@gendsgn.local>
Co-committed-by: bot-backend <bot-backend@gendsgn.local>
2026-06-07 15:15:03 +00:00

181 lines
7 KiB
Python
Raw Permalink 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.

"""Тесты granddoc_lookup (#1061) — read-side lookup граддокументации из planning_projects."""
from __future__ import annotations
from datetime import date
from typing import Any
from sqlalchemy.exc import OperationalError, ProgrammingError
from app.services.site_finder.granddoc_lookup import parcel_granddoc
# ── Моки БД (аналог test_reservation_lookup.py) ────────────────────────────
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)
# ── Фикстура строк ────────────────────────────────────────────────────────────
_ROW_PAGA = {
"project_type": "ppt",
"doc_status_name": "Действующий",
"full_name": "ПАГЕ № 2792 от 16.12.2021\nРеконструкция ул. Декабристов",
"doc_full_name": "Проект планировки территории ул. Декабристов",
}
_ROW_NO_PAGA = {
"project_type": "pmt",
"doc_status_name": "Недействующий",
"full_name": "Проект межевания без реквизитов ПАГЕ",
"doc_full_name": "ПМТ квартал 24",
}
_ROW_INACTIVE = {
"project_type": "ppt",
"doc_status_name": "Недействующий",
"full_name": "ПАГЕ № 111 от 01.03.2015\nПрежний проект",
"doc_full_name": "Старый ППТ",
}
_ROW_ACTIVE_NEWER = {
"project_type": "ppt",
"doc_status_name": "Действующий",
"full_name": "ПАГЕ № 3500 от 20.06.2023\nНовый квартал",
"doc_full_name": "ППТ 2023",
}
# ── Тесты: парсинг ПАГЕ ───────────────────────────────────────────────────────
def test_paga_number_and_date_parsed() -> None:
"""full_name с «ПАГЕ № 2792 от 16.12.2021» → paga_number='2792', paga_date=date(2021,12,16)."""
result = parcel_granddoc(_FakeDB([_ROW_PAGA]), "POINT(60 56)")
assert len(result) == 1
row = result[0]
assert row["paga_number"] == "2792"
assert row["paga_date"] == date(2021, 12, 16)
def test_paga_subject_extracted() -> None:
"""Предмет (текст после реквизитов ПАГЕ) извлекается как subject."""
result = parcel_granddoc(_FakeDB([_ROW_PAGA]), "POINT(60 56)")
assert result[0]["subject"] == "Реконструкция ул. Декабристов"
def test_is_active_true_for_dejstvuyushiy() -> None:
"""doc_status_name='Действующий' → is_active=True."""
result = parcel_granddoc(_FakeDB([_ROW_PAGA]), "POINT(60 56)")
assert result[0]["is_active"] is True
def test_is_active_false_for_nedejstvuyushiy() -> None:
"""doc_status_name='Недействующий' → is_active=False."""
result = parcel_granddoc(_FakeDB([_ROW_INACTIVE]), "POINT(60 56)")
assert result[0]["is_active"] is False
def test_no_paga_in_full_name_returns_none_graceful() -> None:
"""full_name без «ПАГЕ № …» → paga_number=None, paga_date=None, subject=None (graceful)."""
result = parcel_granddoc(_FakeDB([_ROW_NO_PAGA]), "POINT(60 56)")
assert len(result) == 1
row = result[0]
assert row["paga_number"] is None
assert row["paga_date"] is None
assert row["subject"] is None
def test_all_expected_keys_present() -> None:
"""Каждый элемент содержит все ожидаемые ключи."""
result = parcel_granddoc(_FakeDB([_ROW_PAGA, _ROW_NO_PAGA]), "POINT(60 56)")
expected = {
"project_type",
"doc_status_name",
"is_active",
"paga_number",
"paga_date",
"subject",
"doc_full_name",
}
for item in result:
assert set(item.keys()) == expected
# ── Тесты: сортировка ────────────────────────────────────────────────────────
def test_active_first_sorting() -> None:
"""Действующие документы идут первыми независимо от порядка в БД."""
rows = [_ROW_INACTIVE, _ROW_PAGA] # inactive первый в БД
result = parcel_granddoc(_FakeDB(rows), "POINT(60 56)")
assert result[0]["is_active"] is True
assert result[1]["is_active"] is False
def test_active_sorted_by_date_desc() -> None:
"""Среди действующих: более новая дата идёт раньше (desc)."""
rows = [_ROW_PAGA, _ROW_ACTIVE_NEWER] # 2021 первый в БД, 2023 второй
result = parcel_granddoc(_FakeDB(rows), "POINT(60 56)")
# Оба active; 2023 > 2021 → 2023 должен быть первым
active_results = [r for r in result if r["is_active"]]
assert len(active_results) == 2
assert active_results[0]["paga_date"] == date(2023, 6, 20)
assert active_results[1]["paga_date"] == date(2021, 12, 16)
# ── Тесты: graceful ──────────────────────────────────────────────────────────
def test_empty_when_parcel_wkt_none() -> None:
"""parcel_wkt=None → пустой список, БД не вызывается."""
result = parcel_granddoc(_FakeDB([_ROW_PAGA]), None)
assert result == []
def test_empty_when_parcel_wkt_empty_string() -> None:
"""parcel_wkt='' → пустой список (falsy guard)."""
result = parcel_granddoc(_FakeDB([_ROW_PAGA]), "")
assert result == []
def test_empty_when_no_rows() -> None:
"""Нет пересечений в БД → пустой список."""
result = parcel_granddoc(_FakeDB([]), "POINT(60 56)")
assert result == []
def test_graceful_on_operational_error() -> None:
"""OperationalError (таблица не задеплоена) → [] без падения."""
db = _FakeDB(raise_exc=OperationalError("stmt", {}, Exception("no such table")))
result = parcel_granddoc(db, "POINT(60 56)")
assert result == []
def test_graceful_on_programming_error() -> None:
"""ProgrammingError → [] без падения."""
db = _FakeDB(raise_exc=ProgrammingError("stmt", {}, Exception("column not found")))
result = parcel_granddoc(db, "POINT(60 56)")
assert result == []