172 lines
7.4 KiB
Python
172 lines
7.4 KiB
Python
"""Тесты для _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
|