Adds [tool.ruff] and [tool.ty] config to pyproject.toml with a curated ruff rule set (E, F, W, I, UP, B, C4, SIM, RUF, ASYNC, LOG, G, PIE, RET, PERF, N), pins ruff/ty in requirements-dev.txt, reformats the whole tree with `ruff format`, and fixes the pre-existing lint and type-check debt those tools surfaced so both run clean. Production-code type fixes include: HA's ConfigFlowResult vs. the generic FlowResult in config_flow.py, narrowing BoundEntity.desc to its platform-specific subclass (SelectDesc/NumberDesc/SensorDesc/etc.) via cast() instead of an unchecked annotation, converting HA device_class strings to their proper enum types, a resolve_registry callback typed as `object` instead of `DeviceRegistry | None`, and a couple of other narrow correctness fixes (CA key type validation, an index-out-of-bounds false positive from an empty-tuple fallback, a bool/dict argument swap). Test-file fixes are mechanical: narrowing SamsungEntityDescription to the correct subclass via isinstance()/cast() before accessing subclass-only fields, and asserting Optional write_fn/unit_fn fields are set before calling them.
49 lines
1.9 KiB
Python
49 lines
1.9 KiB
Python
"""Tests for select-option display casing (custom_components/localthings/select.py)."""
|
|
|
|
from custom_components.localthings.select import _display
|
|
|
|
_UNTRANSLATED = None
|
|
_TRANSLATED = "ice_type"
|
|
|
|
|
|
def test_display_titlecases_a_fully_lowercase_device_native_token():
|
|
"""Samsung's sound-mode field is genuinely lowercase on the wire
|
|
('voice'/'tone'/'mute') -- these have no other casing signal to key
|
|
off, so title-case them for display."""
|
|
assert _display("voice", _UNTRANSLATED) == "Voice"
|
|
assert _display("mute", _UNTRANSLATED) == "Mute"
|
|
|
|
|
|
def test_display_inserts_a_space_at_a_camelcase_boundary():
|
|
"""'ExtraHigh' (from supportedHeatedDry) should read as two words."""
|
|
assert _display("ExtraHigh", _UNTRANSLATED) == "Extra High"
|
|
|
|
|
|
def test_display_passes_through_an_already_human_friendly_value():
|
|
"""'AI Wash' etc. (dishwasher cycle names) already read fine and
|
|
have no camelCase boundary or all-lowercase pattern -- must not be
|
|
mangled."""
|
|
assert _display("AI Wash", _UNTRANSLATED) == "AI Wash"
|
|
assert _display("Low", _UNTRANSLATED) == "Low"
|
|
assert _display("Off", _UNTRANSLATED) == "Off"
|
|
|
|
|
|
def test_display_lowercases_for_translation_key_lookup():
|
|
"""An entity with a translation_key must match the catalog's
|
|
lowercase keys exactly -- unlike the untranslated cases above, this
|
|
is not a cosmetic transform."""
|
|
assert _display("Whiskey_IceBall_3", _TRANSLATED) == "whiskey_iceball_3"
|
|
|
|
|
|
def test_unknown_translated_vendor_value_keeps_readable_fallback():
|
|
"""A firmware-added value must remain readable instead of being mangled."""
|
|
assert _display("FutureVendorMode", _TRANSLATED) == "Future Vendor Mode"
|
|
|
|
|
|
def test_known_camel_case_state_uses_snake_case_translation_key():
|
|
assert _display("ExtraHigh", "heated_dry") == "extra_high"
|
|
|
|
|
|
def test_display_passes_through_non_string_values():
|
|
assert _display(None, _UNTRANSLATED) is None
|