gendesign/backend/tests/services/test_utility_characteristics.py
bot-backend 99ee09e230
All checks were successful
Deploy / changes (push) Successful in 21s
Deploy / build-frontend (push) Has been skipped
Deploy / build-backend (push) Successful in 1m53s
Deploy / build-worker (push) Successful in 3m11s
Deploy / deploy (push) Successful in 1m34s
feat(site-finder): теплотрассы из OSM в слой инженерной инфраструктуры (Фаза C1) (#2280)
2026-07-03 08:05:44 +00:00

172 lines
7.4 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.

"""Тесты для _utility_characteristics (#2111 §3 «Сети и точки подключения»).
Покрывает гуманизацию OSM tags инженерных сетей в одну RU-строку для попапов:
напряжение (multi/кВ/В), оператор, диаметр трубопровода, материал, цепи, фильтр
junk-значений. Хелпер module-private — импортируем напрямую.
"""
from __future__ import annotations
from app.services.site_finder.utility_infrastructure_loader import (
_format_diameter,
_format_voltage,
_utility_characteristics,
)
# ── _format_voltage ───────────────────────────────────────────────────────────
def test_format_voltage_kv_single() -> None:
assert _format_voltage("110000") == "110 кВ"
def test_format_voltage_volts_below_1000() -> None:
assert _format_voltage("400") == "400 В"
def test_format_voltage_multi_mixed() -> None:
# «110000;10000» → оба ≥1000 → кВ, join через «/».
assert _format_voltage("110000;10000") == "110 кВ/10 кВ"
def test_format_voltage_multi_kv_and_volts() -> None:
assert _format_voltage("10000;400") == "10 кВ/400 В"
def test_format_voltage_fractional_kv() -> None:
# 400 В → «400 В»; 6600 → «6.6 кВ» (без хвостового нуля).
assert _format_voltage("6600") == "6.6 кВ"
def test_format_voltage_skips_non_numeric() -> None:
assert _format_voltage("110000;junk;10000") == "110 кВ/10 кВ"
def test_format_voltage_all_junk_returns_none() -> None:
assert _format_voltage("abc;;def") is None
# ── _format_diameter ──────────────────────────────────────────────────────────
def test_format_diameter_plain_digits() -> None:
assert _format_diameter("500") == "⌀ 500 мм"
def test_format_diameter_strips_mm_suffix() -> None:
assert _format_diameter("500mm") == "⌀ 500 мм"
assert _format_diameter("300 мм") == "⌀ 300 мм"
def test_format_diameter_no_digits_returns_none() -> None:
assert _format_diameter("large") is None
def test_format_diameter_multidim_takes_first_run() -> None:
# «500x300» (прямоугольный короб) → берём первый числовой run, не склеиваем.
assert _format_diameter("500x300") == "⌀ 500 мм"
assert _format_diameter("DN500") == "⌀ 500 мм"
# ── _utility_characteristics ──────────────────────────────────────────────────
def test_characteristics_power_voltage_and_operator() -> None:
out = _utility_characteristics("power", {"voltage": "110000;10000", "operator": "МРСК Урала"})
assert out == "110 кВ/10 кВ · МРСК Урала"
def test_characteristics_pipeline_diameter_and_material() -> None:
# material переводится на RU («человеческим языком»): steel → сталь.
out = _utility_characteristics("gas", {"diameter": "500mm", "material": "steel"})
assert out == "⌀ 500 мм · сталь"
def test_characteristics_material_ru_and_unknown_passthrough() -> None:
# known → RU; неизвестный материал остаётся сырым (лучше сырое, чем потерять).
assert _utility_characteristics("power", {"material": "metal"}) == "металл"
assert _utility_characteristics("power", {"material": "Concrete"}) == "бетон"
assert _utility_characteristics("gas", {"material": "unobtanium"}) == "unobtanium"
def test_characteristics_single_voltage_volts() -> None:
assert _utility_characteristics("power", {"voltage": "400"}) == "400 В"
def test_characteristics_circuits_when_numeric() -> None:
out = _utility_characteristics("power", {"voltage": "10000", "circuits": "2"})
assert out == "10 кВ · 2 цеп."
def test_characteristics_cables_fallback_for_circuits() -> None:
out = _utility_characteristics("power", {"cables": "3"})
assert out == "3 цеп."
def test_characteristics_non_numeric_circuits_skipped() -> None:
# circuits=«single» не число → пропускаем; остаётся только напряжение.
assert _utility_characteristics("power", {"voltage": "400", "circuits": "single"}) == "400 В"
def test_characteristics_junk_voltage_filtered() -> None:
# voltage=yes (junk) → пропуск; ничего больше → None.
assert _utility_characteristics("power", {"voltage": "yes"}) is None
def test_characteristics_filters_empty_and_no() -> None:
assert _utility_characteristics("water", {"operator": " ", "material": "no"}) is None
def test_characteristics_none_tags_returns_none() -> None:
assert _utility_characteristics("power", None) is None
def test_characteristics_empty_dict_returns_none() -> None:
assert _utility_characteristics("power", {}) is None
def test_characteristics_not_a_dict_returns_none() -> None:
# Защитный guard: tags из БД мог прийти не dict (broken JSONB) → None, не падаем.
assert _utility_characteristics("power", "not-a-dict") is None # type: ignore[arg-type]
def test_characteristics_full_order() -> None:
# Порядок частей: напряжение · оператор · диаметр · материал · цепи.
out = _utility_characteristics(
"power",
{
"voltage": "10000",
"operator": "Облкоммунэнерго",
"diameter": "200",
"material": "медь",
"circuits": "2",
},
)
assert out == "10 кВ · Облкоммунэнерго · ⌀ 200 мм · медь · 2 цеп."
# ── теплотрассы (kind=heat, #2119) ────────────────────────────────────────────
def test_characteristics_heat_hot_water_substance() -> None:
# Теплоноситель — первым: «горячая вода», затем диаметр.
out = _utility_characteristics("heat", {"substance": "hot_water", "diameter": "200"})
assert out == "горячая вода · ⌀ 200 мм"
def test_characteristics_heat_steam_substance() -> None:
out = _utility_characteristics("heat", {"substance": "steam"})
assert out == "пар"
def test_characteristics_heat_generic_substance_no_label() -> None:
# substance=heat (обобщённо) не уточняем — фронт и так покажет «Теплотрасса».
# Диаметр остаётся, теплоноситель-подписи нет.
assert _utility_characteristics("heat", {"substance": "heat", "diameter": "300"}) == "⌀ 300 мм"
# heat без каких-либо характеристик → None (одного вида довольно для попапа).
assert _utility_characteristics("heat", {"substance": "heat"}) is None
def test_characteristics_heat_substance_only_on_heat_kind() -> None:
# substance-подпись только для kind=heat; для gas/water теплоноситель не лезет.
assert _utility_characteristics("gas", {"substance": "hot_water"}) is None