""" Sprint 0 — sanity: conversiones SI ↔ imperial round-trip y casos límite. """ from __future__ import annotations import pytest from arelec.core.units import ( AWG_TO_MM2, awg_to_mm2, ft_to_m, kg_to_lb, kw_to_hp, lb_to_kg, m_to_ft, mm2_to_awg, hp_to_kw, ) def test_length_roundtrip() -> None: assert m_to_ft(1.0) == pytest.approx(3.28084, rel=1e-4) assert ft_to_m(m_to_ft(42.0)) == pytest.approx(42.0) def test_mass_roundtrip() -> None: assert kg_to_lb(1.0) == pytest.approx(2.20462, rel=1e-4) assert lb_to_kg(kg_to_lb(100.0)) == pytest.approx(100.0) def test_power_roundtrip() -> None: assert hp_to_kw(1.0) == pytest.approx(0.7355) assert kw_to_hp(hp_to_kw(150.0)) == pytest.approx(150.0) def test_awg_lookup_known_values() -> None: # ABYC E-11 tabla VI — valores publicados estándar assert awg_to_mm2("10") == 5.26 assert awg_to_mm2("4/0") == 107.0 assert awg_to_mm2("14") == 2.08 def test_mm2_to_awg_picks_next_larger() -> None: # 5.0 mm² no es exactamente AWG 10 (5.26), pero AWG 10 cubre el cable. # Criterio conservador: elegir AWG cuya área es ≥ pedida. assert mm2_to_awg(5.0) == "10" assert mm2_to_awg(5.26) == "10" assert mm2_to_awg(2.0) == "14" # 2.08 assert mm2_to_awg(100.0) == "4/0" # 107 def test_mm2_to_awg_rejects_invalid() -> None: with pytest.raises(ValueError): mm2_to_awg(0) with pytest.raises(ValueError): mm2_to_awg(-1.0) with pytest.raises(ValueError): mm2_to_awg(500.0) # más grande que 4/0 def test_awg_table_monotonic() -> None: """La tabla AWG debe ir de menor a mayor área (asumido por mm2_to_awg).""" areas = list(AWG_TO_MM2.values()) assert areas == sorted(areas)