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.
41 lines
1.5 KiB
Python
41 lines
1.5 KiB
Python
"""Tests for the /temperatures/vs/0 fallback helper in climate.py (PR #36).
|
|
|
|
`_temps_vs_item` is a pure module-level function (plain dict in, plain dict
|
|
out) with no coordinator/entity dependency, so -- like select.py's `_display`
|
|
in test_select_display.py -- it's testable directly even though the
|
|
LocalThingsClimate entity itself needs a coordinator/hass fixture to
|
|
exercise. This covers the actual fallback-selection logic that the
|
|
registry-level "no unbound hrefs" tests in test_airconditioner_capabilities.py
|
|
don't reach: TP1X-class firmware has no OCF-standard
|
|
/temperature/current+desired pair, so current_temperature/target_temperature
|
|
would silently be None without this fallback.
|
|
"""
|
|
|
|
from custom_components.localthings.climate import _temps_vs_item
|
|
|
|
|
|
def test_temps_vs_item_returns_first_item():
|
|
rep = {
|
|
"x.com.samsung.da.items": [
|
|
{"x.com.samsung.da.current": "17.0", "x.com.samsung.da.desired": "25.0"},
|
|
],
|
|
}
|
|
assert _temps_vs_item(rep) == {
|
|
"x.com.samsung.da.current": "17.0",
|
|
"x.com.samsung.da.desired": "25.0",
|
|
}
|
|
|
|
|
|
def test_temps_vs_item_empty_when_items_missing():
|
|
"""OCF-pair devices don't populate /temperatures/vs/0's items at all --
|
|
callers must fall through to the OCF hrefs cleanly, not raise."""
|
|
assert _temps_vs_item({}) == {}
|
|
|
|
|
|
def test_temps_vs_item_empty_when_items_is_empty_list():
|
|
assert _temps_vs_item({"x.com.samsung.da.items": []}) == {}
|
|
|
|
|
|
def test_temps_vs_item_empty_when_items_entry_is_not_a_dict():
|
|
assert _temps_vs_item({"x.com.samsung.da.items": ["not-a-dict"]}) == {}
|