gendesign/tradein-mvp/backend/tests/test_suggest_fias_contract.py
bot-backend 67a852caf1
All checks were successful
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI / changes (pull_request) Successful in 10s
feat(tradein/matching): fias_exact tier + estimate fias persist + suggest fias_id contract
2026-07-02 20:49:04 +03:00

123 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.

"""Тесты контракта suggest→ФИАС (feat/tradein-fias-tier-matching).
Покрывают:
1. geocoder._dadata_suggest — fias_id прокидывается ТОЛЬКО у house-level
кандидата (DaData kind='house' ⇔ fias_level 8/9); у street/city/plot None.
2. SuggestItem — сериализует fias_id (house-тир) и None у не-DaData тиров.
3. TradeInEstimateInput — принимает target_fias_id и дефолтит None при отсутствии.
"""
import os
# Settings требует DATABASE_URL на импорте — ставим dummy DSN до app-импортов.
os.environ.setdefault("DATABASE_URL", "postgresql+psycopg://test:test@localhost:5432/test")
from unittest.mock import AsyncMock, patch
from app.api.v1.geocode import SuggestItem
from app.schemas.trade_in import TradeInEstimateInput
from app.services.dadata import DadataSuggestion
from app.services.geocoder import GeocodeSuggestion, _dadata_suggest
def _sugg(kind: str, fias_id: str | None) -> DadataSuggestion:
return DadataSuggestion(
value=f"тест {kind}",
unrestricted_value=f"г Екатеринбург, тест {kind}",
lat=56.84,
lon=60.60,
fias_id=fias_id,
house="1" if kind == "house" else None,
street="Тестовая",
city="Екатеринбург",
kind=kind,
)
# ── 1. _dadata_suggest: fias_id только у house-тира ──────────────────────────
async def test_dadata_suggest_fias_only_for_house_kind():
raw = [
_sugg("house", "0a1b2c3d-0000-4000-8000-00000000aaaa"),
_sugg("street", "0a1b2c3d-0000-4000-8000-00000000bbbb"),
_sugg("city", "0a1b2c3d-0000-4000-8000-00000000cccc"),
_sugg("plot", "0a1b2c3d-0000-4000-8000-00000000dddd"),
]
with patch(
"app.services.geocoder.dadata.suggest_addresses",
new=AsyncMock(return_value=raw),
):
out = await _dadata_suggest("тест", limit=8)
assert len(out) == 4
house = next(s for s in out if s.kind == "house")
assert house.fias_id == "0a1b2c3d-0000-4000-8000-00000000aaaa"
# У всех НЕ-house тиров fias_id обнулён, даже если DaData его прислал.
for s in out:
if s.kind != "house":
assert s.fias_id is None
async def test_dadata_suggest_house_without_fias_stays_none():
"""house-кандидат без fias у DaData → fias_id None (не падаем)."""
with patch(
"app.services.geocoder.dadata.suggest_addresses",
new=AsyncMock(return_value=[_sugg("house", None)]),
):
out = await _dadata_suggest("тест", limit=8)
assert len(out) == 1
assert out[0].fias_id is None
# ── 2. SuggestItem сериализация ──────────────────────────────────────────────
def test_suggest_item_serializes_fias_id():
item = SuggestItem(
label="ул Малышева, д 30",
full_address="г Екатеринбург, ул Малышева, д 30",
lat=56.84,
lon=60.60,
kind="house",
fias_id="0a1b2c3d-0000-4000-8000-00000000aaaa",
)
dumped = item.model_dump()
assert dumped["fias_id"] == "0a1b2c3d-0000-4000-8000-00000000aaaa"
def test_suggest_item_fias_id_defaults_none_for_non_dadata_tier():
"""Не-DaData тир (Yandex/Nominatim/cadastral) не передаёт fias_id → None."""
gs = GeocodeSuggestion(
label="Малышева 30",
full_address="г Екатеринбург, ул Малышева, д 30",
lat=56.84,
lon=60.60,
kind="house",
)
assert gs.fias_id is None
item = SuggestItem(
label=gs.label,
full_address=gs.full_address,
lat=gs.lat,
lon=gs.lon,
kind=gs.kind,
fias_id=gs.fias_id,
)
assert item.model_dump()["fias_id"] is None
# ── 3. TradeInEstimateInput.target_fias_id ───────────────────────────────────
def test_estimate_input_accepts_target_fias_id():
payload = TradeInEstimateInput(
address="ул Малышева 30, Екатеринбург",
area_m2=50.0,
rooms=2,
target_fias_id="0a1b2c3d-0000-4000-8000-00000000aaaa",
)
assert payload.target_fias_id == "0a1b2c3d-0000-4000-8000-00000000aaaa"
def test_estimate_input_target_fias_id_defaults_none():
payload = TradeInEstimateInput(
address="ул Малышева 30, Екатеринбург",
area_m2=50.0,
rooms=2,
)
assert payload.target_fias_id is None