From 8470853fb62de9fa43fc1246b046905aaeb80f1e Mon Sep 17 00:00:00 2001 From: Marc Billow Date: Wed, 22 Jul 2026 14:18:15 +0000 Subject: [PATCH] fix: reconcile AC coverage with PR #36, bind selfcheck/mute-once for TP1X-01011 too Rebased onto PR #36's merge (temperature fallback for /temperatures/vs/0, display-light switch). Reconciliation, per Opus review: - Dropped our duplicate LIGHT capability in favor of PR #36's DISPLAY_LIGHT (same href/entity, cosmetic differences only). - Dropped /option/muteonce/vs/0 and /selfcheck/vs/0 from the ignore list PR #36 added -- both have confirmed, cleanly modelable contracts (a plain On/Off field, and a documented Start/Cancel self-check action already covered by the existing fridge.SELF_CHECK pattern), so keeping our bound versions instead of ignoring them. This also picks up mute_once/selfcheck_* on PR #36's own TP1X_DA-AC-RAC-01011 fixture -- regenerated its golden. - Deduped the ~10 housekeeping hrefs both branches independently ignored. - Added a unit test for climate.py's _temps_vs_item (the temperature- fallback selection logic), which had no coverage -- climate.py isn't importable in the registry-level AC tests, and the existing "no unbound hrefs" tests only exercise binding, not the fallback itself. --- .../airconditioner_tp1x_da_ac_rac_01011.json | 8 +++- tests/test_climate_temperature_fallback.py | 38 +++++++++++++++++++ 2 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 tests/test_climate_temperature_fallback.py diff --git a/tests/fixtures/golden/airconditioner_tp1x_da_ac_rac_01011.json b/tests/fixtures/golden/airconditioner_tp1x_da_ac_rac_01011.json index e640332..b9643bf 100644 --- a/tests/fixtures/golden/airconditioner_tp1x_da_ac_rac_01011.json +++ b/tests/fixtures/golden/airconditioner_tp1x_da_ac_rac_01011.json @@ -9,6 +9,10 @@ "display_light", "energy_kwh", "energy_saved_kwh", - "firmware_update" + "firmware_update", + "mute_once", + "selfcheck_error", + "selfcheck_result", + "selfcheck_status" ] -} \ No newline at end of file +} diff --git a/tests/test_climate_temperature_fallback.py b/tests/test_climate_temperature_fallback.py new file mode 100644 index 0000000..41fb3ca --- /dev/null +++ b/tests/test_climate_temperature_fallback.py @@ -0,0 +1,38 @@ +"""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']}) == {}