"""Тесты для _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 цеп."