"""Tests for fridge-specific capabilities.""" from collections.abc import Callable from typing import ClassVar, cast from custom_components.localthings.coordinator import LocalThingsCoordinator from custom_components.localthings.registry.capabilities import fridge from custom_components.localthings.registry.entities import ( NumberDesc, SelectDesc, SensorDesc, ) class TestTempCurrentGeneric: """Issue #7: unit must be read live from the device, not assumed to be Fahrenheit -- a TP1X_REF_21K fridge (RL38C6B0CWW/EG) reports the same resource in Celsius.""" def test_unit_reads_celsius(self): desc = next(e for e in fridge.TEMP_CURRENT_GENERIC.entities if isinstance(e, SensorDesc)) assert desc.unit_fn is not None assert desc.unit_fn({"temperature": 3.0, "units": "C"}) == "°C" def test_unit_reads_fahrenheit(self): desc = next(e for e in fridge.TEMP_CURRENT_GENERIC.entities if isinstance(e, SensorDesc)) assert desc.unit_fn is not None assert desc.unit_fn({"temperature": 5.0, "units": "F"}) == "°F" def test_unit_defaults_to_fahrenheit_when_missing(self): desc = next(e for e in fridge.TEMP_CURRENT_GENERIC.entities if isinstance(e, SensorDesc)) assert desc.unit_fn is not None assert desc.unit_fn({"temperature": 5.0}) == "°F" class TestDoorGeneric: """Issues #77/#83: DOOR_GENERIC used to read only the bare `openState` field. Most /door/* resources use that, but the ARTIK051_DONGLE_REF family's /door/onedoorfreezer/vs/0 reports the vendor-prefixed `x.com.samsung.da.openState` instead -- the pattern capability still bound the href either way, but the entity's value was always None.""" def test_reads_bare_open_state(self): desc = fridge.DOOR_GENERIC.entities[0] assert desc.rep_fn is not None assert desc.rep_fn({"openState": "Open"}) is True assert desc.rep_fn({"openState": "Close"}) is False def test_reads_vendor_prefixed_open_state(self): desc = fridge.DOOR_GENERIC.entities[0] assert desc.rep_fn is not None assert desc.rep_fn({"x.com.samsung.da.openState": "Open"}) is True assert desc.rep_fn({"x.com.samsung.da.openState": "Close"}) is False def test_prefers_bare_field_when_both_present(self): desc = fridge.DOOR_GENERIC.entities[0] assert desc.rep_fn is not None rep = {"openState": "Open", "x.com.samsung.da.openState": "Close"} assert desc.rep_fn(rep) is True class TestTempSetpointGeneric: def test_unit_reads_celsius(self): desc = next(e for e in fridge.TEMP_SETPOINT.entities if isinstance(e, NumberDesc)) assert desc.unit_fn is not None assert desc.unit_fn({"temperature": -19.0, "units": "C"}) == "°C" class TestTemperaturesFallback: """Aggregate /temperatures/vs/0 -- per-item unit from x.com.samsung.da.unit ('Celsius'/'Fahrenheit').""" def test_freezer_unit_celsius(self): desc = next( e for e in fridge.TEMPERATURES_FALLBACK.entities if e.key == "freezer_temperature" and isinstance(e, SensorDesc) ) assert desc.unit_fn is not None rep = { "x.com.samsung.da.items": [ { "x.com.samsung.da.description": "Freezer", "x.com.samsung.da.current": "-19", "x.com.samsung.da.unit": "Celsius", }, { "x.com.samsung.da.description": "Fridge", "x.com.samsung.da.current": "3", "x.com.samsung.da.unit": "Celsius", }, ] } assert desc.unit_fn(rep) == "°C" assert desc.value_fn(rep["x.com.samsung.da.items"]) == -19 def test_fridge_unit_fahrenheit(self): desc = next( e for e in fridge.TEMPERATURES_FALLBACK.entities if e.key == "fridge_temperature" and isinstance(e, SensorDesc) ) assert desc.unit_fn is not None rep = { "x.com.samsung.da.items": [ { "x.com.samsung.da.description": "Fridge", "x.com.samsung.da.current": "37", "x.com.samsung.da.unit": "Fahrenheit", }, ] } assert desc.unit_fn(rep) == "°F" def test_unit_defaults_to_fahrenheit_when_item_missing(self): desc = next( e for e in fridge.TEMPERATURES_FALLBACK.entities if e.key == "freezer_temperature" and isinstance(e, SensorDesc) ) assert desc.unit_fn is not None assert desc.unit_fn({"x.com.samsung.da.items": []}) == "°F" class TestDefrostBlockStatus: """DEFROST_BLOCK_ON means the defrost cycle is actively running, not that defrost is being withheld -- confirmed against live dumps showing it ON while defrost_delay is off.""" def test_key_and_name_reflect_active_defrosting(self): desc = fridge.DEFROST_BLOCK_STATUS.entities[0] assert desc.key == "defrost_active" def test_value_fn(self): desc = fridge.DEFROST_BLOCK_STATUS.entities[0] assert desc.value_fn(["DEFROST_BLOCK_ON"]) is True assert desc.value_fn(["DEFROST_BLOCK_OFF"]) is False class TestRefrigerationFallback: """/refrigeration/0 duplicates two of REFRIGERATION's (/refrigeration/vs/0) fields under different names (rapidFreeze/rapidCool vs rapidFreezing/rapidFridge) but also carries one genuinely new field (defrost) that has no vs-href equivalent.""" def test_href(self): assert fridge.REFRIGERATION_FALLBACK.href == "/refrigeration/0" def test_defrost_active_is_fallback_of_defrost_block_status(self): # Duplicates DEFROST_BLOCK_STATUS's defrost_active # (/defrost/block/vs/0) -- only a true fallback when that richer # href is absent (issue #7's device: /refrigeration/0 only). desc = next(e for e in fridge.REFRIGERATION_FALLBACK.entities if e.key == "defrost_active") assert desc.value_fn(True) is True assert desc.value_fn(False) is False assert desc.exists_fn is not None assert desc.exists_fn({}, {"/refrigeration/0": {}}) is True assert desc.exists_fn({}, {"/refrigeration/0": {}, "/defrost/block/vs/0": {}}) is False def test_rapid_switches_hidden_when_vs_href_present(self): for key in ("rapid_fridge", "rapid_freezing"): desc = next(e for e in fridge.REFRIGERATION_FALLBACK.entities if e.key == key) assert desc.exists_fn is not None assert desc.exists_fn({}, {"/refrigeration/vs/0": {}, "/refrigeration/0": {}}) is False def test_rapid_switches_shown_when_vs_href_absent(self): for key in ("rapid_fridge", "rapid_freezing"): desc = next(e for e in fridge.REFRIGERATION_FALLBACK.entities if e.key == key) assert desc.exists_fn is not None assert desc.exists_fn({}, {"/refrigeration/0": {}}) is True class TestFlexZone: """Issue #32 (surfaced by #26/#27's TP2X/Bespoke dumps): the flex-zone entry's prefix varies by fridge family (CV_TTYPE_RF9000A_ on RF9000-class, CV_FDR_ on TP1X/Bespoke-class). The old hardcoded-prefix match left CV_FDR_-family fridges with an always-unknown select, and a write would have appended a duplicate flag instead of replacing the existing one.""" def test_reads_rf9000_prefix(self): rep = { "x.com.samsung.da.modes": ["CV_TTYPE_RF9000A_BEVERAGE", "WATERFILTER_DISABLE"], "x.com.samsung.da.supportedOptions": [ "CV_TTYPE_RF9000A_FREEZE", "CV_TTYPE_RF9000A_BEVERAGE", ], } assert fridge._flex_zone_current(rep) == "CV_TTYPE_RF9000A_BEVERAGE" def test_reads_cv_fdr_prefix(self): rep = { "x.com.samsung.da.modes": ["CVN_CONVERTIBLE_ZONE", "CV_FDR_MEAT", "WATERFILTER_ENABLE"], "x.com.samsung.da.supportedOptions": [ "CV_FDR_WINE", "CV_FDR_DELI", "CV_FDR_BEVERAGE", "CV_FDR_MEAT", ], } assert fridge._flex_zone_current(rep) == "CV_FDR_MEAT" def test_write_replaces_rather_than_duplicates(self): rep = { "x.com.samsung.da.modes": ["CVN_CONVERTIBLE_ZONE", "CV_FDR_MEAT", "WATERFILTER_ENABLE"], "x.com.samsung.da.supportedOptions": [ "CV_FDR_WINE", "CV_FDR_DELI", "CV_FDR_BEVERAGE", "CV_FDR_MEAT", ], } path, payload = fridge._flex_zone_write("CV_FDR_WINE", rep) assert path == ["mode", "vs", "0"] modes = payload["x.com.samsung.da.modes"] assert modes.count("CV_FDR_WINE") == 1 assert "CV_FDR_MEAT" not in modes assert "CVN_CONVERTIBLE_ZONE" in modes and "WATERFILTER_ENABLE" in modes def test_exists_only_when_a_current_value_resolves(self): """Issue #26's kimchi-refrigerator family also populates /mode/vs/0's modes/supportedOptions, but its supportedOptions tokens carry a "_[n]:[n]" suffix modes never repeats, so no item ever overlaps -- the entity used to bind anyway (supportedOptions is nonempty) and get stuck on "unknown" forever.""" no_overlap_rep = { "x.com.samsung.da.modes": ["KIMCHIT_STORAGE_FREEZER_NORMAL"], "x.com.samsung.da.supportedOptions": ["KIMCHIT_STORAGE_FREEZER_NORMAL_[0]:[0]"], } desc = fridge.FLEX_ZONE.entities[0] assert desc.exists_fn is not None assert desc.exists_fn(no_overlap_rep, {}) is False overlap_rep = { "x.com.samsung.da.modes": ["CV_FDR_MEAT"], "x.com.samsung.da.supportedOptions": ["CV_FDR_WINE", "CV_FDR_MEAT"], } assert desc.exists_fn(overlap_rep, {}) is True class TestTp1xNativeDuplicateResources: """The US TP1X_REF_21K publishes two native mirrors in addition to the richer vendor resources. They must count as covered without producing duplicate entities or guessing unverified write contracts.""" def test_duplicate_capabilities_have_no_entities(self): assert fridge.DEFROST_DELAY_NATIVE_DUPLICATE.entities == () assert fridge.ICEMAKER_STATUS_NATIVE_DUPLICATE.entities == () def test_us_fixture_has_complete_coverage(self): from custom_components.localthings.registry.adapter import flatten from custom_components.localthings.registry.by_type import refrigerator from custom_components.localthings.registry.discovery import discover from tests.conftest import _load_device resources = _load_device("refrigerator_tp1x_ref_21k_us") unbound = [] bound = discover( resources, refrigerator.REGISTRY.capabilities, refrigerator.REGISTRY.pattern_capabilities, log=unbound.append, ) assert unbound == [] state = flatten(bound, resources) assert state["defrost_delay"] is False assert "ice_maker_enabled" not in state assert state["icemaker_one_enabled"] is True assert state["icemaker_two_enabled"] is True assert state["selfcheck_error"] == "DA_ERROR_NONE" class TestPantryZone: """Cool Select Zone pantry compartment on ARTIK051_REF_17K -- issue #20.""" def test_href(self): assert fridge.PANTRY_ZONE.href == "/status/pantry/one/vs/0" def test_write(self): desc = next(e for e in fridge.PANTRY_ZONE.entities if isinstance(e, SelectDesc)) assert desc.write_fn is not None result = desc.write_fn("FDR_WINE", {}) assert result is not None path, body = result assert path == ["status", "pantry", "one", "vs", "0"] assert body == {"x.com.samsung.da.mode": "FDR_WINE"} class TestDefiniteTemperatureCooler: """Discrete cooler setpoint (RT42DG6630B1FZ, issue #186) -- a single-door fridge whose /temperature/definite/cooler/vs/0 falls outside both TEMP_CURRENT_GENERIC and TEMP_SETPOINT's href prefixes, so temperature control was entirely unbound before this capability was added.""" def test_href(self): assert fridge.DEFINITE_TEMPERATURE_COOLER.href == "/temperature/definite/cooler/vs/0" def test_write(self): desc = next( e for e in fridge.DEFINITE_TEMPERATURE_COOLER.entities if isinstance(e, SelectDesc) ) assert desc.write_fn is not None result = desc.write_fn("3", {}) assert result is not None path, body = result assert path == ["temperature", "definite", "cooler", "vs", "0"] assert body == {"x.com.samsung.da.definite.desired": "3"} def test_no_unbound_hrefs_and_discrete_options(self): from custom_components.localthings.registry.adapter import flatten from custom_components.localthings.registry.by_type import refrigerator from custom_components.localthings.registry.discovery import discover from tests.conftest import _load_device resources = _load_device("refrigerator_definite_cooler") unbound = [] bound = discover( resources, refrigerator.REGISTRY.capabilities, refrigerator.REGISTRY.pattern_capabilities, log=unbound.append, ) assert unbound == [] state = flatten(bound, resources) assert state["cooler_temperature_setpoint"] == "2" rep = resources["/temperature/definite/cooler/vs/0"] assert rep["x.com.samsung.da.definite.supportedList"] == ["1", "2", "3", "4", "7"] class TestDefiniteTemperatureFreezer: """Discrete freezer setpoint (TP1X_REF_21K, issue #229) -- the same definite-setpoint pattern as DEFINITE_TEMPERATURE_COOLER above, on a fridge/freezer combo that reports it for *both* compartments. Identical field shape, just negative supportedList values.""" def test_href(self): assert fridge.DEFINITE_TEMPERATURE_FREEZER.href == "/temperature/definite/freezer/vs/0" def test_write(self): desc = next( e for e in fridge.DEFINITE_TEMPERATURE_FREEZER.entities if isinstance(e, SelectDesc) ) assert desc.write_fn is not None result = desc.write_fn("-19", {}) assert result is not None path, body = result assert path == ["temperature", "definite", "freezer", "vs", "0"] assert body == {"x.com.samsung.da.definite.desired": "-19"} def test_no_unbound_hrefs_and_discrete_options(self): from custom_components.localthings.registry.adapter import flatten from custom_components.localthings.registry.by_type import refrigerator from custom_components.localthings.registry.discovery import discover from tests.conftest import _load_device resources = _load_device("refrigerator_tp1x_ref_21k_definite") unbound = [] bound = discover( resources, refrigerator.REGISTRY.capabilities, refrigerator.REGISTRY.pattern_capabilities, log=unbound.append, ) assert unbound == [] state = flatten(bound, resources) assert state["cooler_temperature_setpoint"] == "4" assert state["freezer_temperature_setpoint"] == "-19" rep = resources["/temperature/definite/freezer/vs/0"] assert rep["x.com.samsung.da.definite.supportedList"] == [ "-23", "-21", "-19", "-17", "-15", ] class TestKimchiZone: """Kimchi-refrigerator compartments (TP2X_REF_20K-class, issue #26) -- top/middle/bottom each report an identically-shaped currentMode/ supportMode resource under /status/kimchi//vs/0.""" def test_href_prefix(self): assert fridge.KIMCHI_ZONE.href_prefix == "/status/kimchi/" assert fridge.KIMCHI_DOOR_GENERIC.href_prefix == "/kimchidoors/" def test_write_derives_path_from_href(self): desc = next(e for e in fridge.KIMCHI_ZONE.entities if isinstance(e, SelectDesc)) assert desc.write_fn is not None write_fn = cast("Callable[..., tuple[list[str], dict] | None]", desc.write_fn) rep = {"x.com.samsung.da.supportMode": ["KIMCHI_STORAGE_COLD"]} result = write_fn("KIMCHI_STORAGE_COLD", rep, href="/status/kimchi/middle/vs/0") assert result is not None path, body = result assert path == ["status", "kimchi", "middle", "vs", "0"] assert body == {"x.com.samsung.da.currentMode": "KIMCHI_STORAGE_COLD"} def test_write_without_href_is_rejected(self): desc = next(e for e in fridge.KIMCHI_ZONE.entities if isinstance(e, SelectDesc)) assert desc.write_fn is not None rep = {"x.com.samsung.da.supportMode": ["KIMCHI_STORAGE_COLD"]} assert desc.write_fn("KIMCHI_STORAGE_COLD", rep) is None def test_write_rejects_value_outside_supportmode(self): """A value the compartment never advertised is rejected rather than written blind -- this write path is unconfirmed against real hardware (module docstring above KIMCHI_ZONE), so a bad value here is a food-safety-adjacent outcome, not just a cosmetic one.""" desc = next(e for e in fridge.KIMCHI_ZONE.entities if isinstance(e, SelectDesc)) assert desc.write_fn is not None write_fn = cast("Callable[..., tuple[list[str], dict] | None]", desc.write_fn) rep = {"x.com.samsung.da.supportMode": ["KIMCHI_STORAGE_COLD"]} assert ( write_fn( "KIMCHI_STORAGE_WARM", rep, href="/status/kimchi/middle/vs/0", ) is None ) def test_ripening_status_passes_through_device_value(self): """No device_class='enum' catalog entry exists for this sensor, so lowercasing it would only make the raw device token un-translatable by HA -- pass the device's own casing straight through instead.""" desc = next(e for e in fridge.KIMCHI_ZONE.entities if e.key == "ripening_status") assert desc.value_fn("Off") == "Off" def test_door_reuses_open_state_helper(self): desc = fridge.KIMCHI_DOOR_GENERIC.entities[0] assert desc.rep_fn is not None assert desc.rep_fn({"x.com.samsung.da.openState": "Open"}) is True assert desc.rep_fn({"x.com.samsung.da.openState": "Close"}) is False async def test_zone_mode_select_round_trips_through_display_casing(self): """kimchi_zone_mode's displayed value (lowercase, catalog-translated) and the raw device code it writes back can silently drift apart -- this is the one place that casing conversion could break. Runs through the real discovery/select pipeline against the tp2x_ref_20k kimchi fixture rather than a hand-built descriptor, so it also catches use_instance_name key derivation going wrong.""" from custom_components.localthings.registry.adapter import flatten from custom_components.localthings.registry.by_type import refrigerator from custom_components.localthings.registry.discovery import discover from custom_components.localthings.registry.entities import SelectDesc from custom_components.localthings.select import LocalThingsSelect from tests.conftest import _load_device resources = _load_device("refrigerator_tp2x_ref_20k_kimchi") bound = discover( resources, refrigerator.REGISTRY.capabilities, refrigerator.REGISTRY.pattern_capabilities, ) mode_bound = next( b for b in bound if isinstance(b.desc, SelectDesc) and b.href == "/status/kimchi/middle/vs/0" ) class _FakeCoordinator: device_key = "TEST-SERIAL" def __init__(self, resources, data): self.last_resources = resources self.data = data self.commands = [] async def async_send_command(self, bound, value): self.commands.append(value) coordinator = _FakeCoordinator(resources, flatten(bound, resources)) entity = LocalThingsSelect(cast(LocalThingsCoordinator, coordinator), mode_bound) assert entity.current_option == "kimchi_storage_normal" assert "kimchi_storage_cold" in entity.options await entity.async_select_option("kimchi_storage_cold") assert coordinator.commands == ["KIMCHI_STORAGE_COLD"] class TestArtik051AndTp2xFixturesHaveCompleteCoverage: """issue #20 (ARTIK051_REF_17K) and #26 (TP2X_REF_20K) both triggered the incomplete-capability-coverage repair; both must resolve to zero unbound hrefs now that /diagnosis/vs/0 (dishwasher.DIAGNOSIS, reused for fridges), /status/pantry/one/vs/0 (PANTRY_ZONE), and the OCF-native defrost/icemaker mirrors are covered.""" def test_artik051_ref_17k(self): from custom_components.localthings.registry.adapter import flatten from custom_components.localthings.registry.by_type import refrigerator from custom_components.localthings.registry.discovery import discover from tests.conftest import _load_device resources = _load_device("refrigerator_artik051_ref_17k") unbound = [] bound = discover( resources, refrigerator.REGISTRY.capabilities, refrigerator.REGISTRY.pattern_capabilities, log=unbound.append, ) assert unbound == [] state = flatten(bound, resources) assert state["pantry_zone_mode"] == "FDR_DRINKS" def test_tp2x_ref_20k(self): from custom_components.localthings.registry.adapter import flatten from custom_components.localthings.registry.by_type import refrigerator from custom_components.localthings.registry.discovery import discover from tests.conftest import _load_device resources = _load_device("refrigerator_tp2x_ref_20k") unbound = [] bound = discover( resources, refrigerator.REGISTRY.capabilities, refrigerator.REGISTRY.pattern_capabilities, log=unbound.append, ) assert unbound == [] state = flatten(bound, resources) assert state["flex_zone_mode"] == "CV_FDR_BEVERAGE" def test_tp2x_ref_20k_kimchi(self): """A different physical unit sharing the same modelNum string (issue #26, second reporter) -- a 3-compartment kimchi refrigerator instead of the flex-zone fridge above. /kimchidoors/top/vs/0 and /status/kimchi/{top,middle,bottom}/vs/0 were previously unbound.""" from custom_components.localthings.registry.adapter import flatten from custom_components.localthings.registry.by_type import refrigerator from custom_components.localthings.registry.discovery import discover from tests.conftest import _load_device resources = _load_device("refrigerator_tp2x_ref_20k_kimchi") unbound = [] bound = discover( resources, refrigerator.REGISTRY.capabilities, refrigerator.REGISTRY.pattern_capabilities, log=unbound.append, ) assert unbound == [] state = flatten(bound, resources) assert state["top_mode"] == "STORAGE_FREEZER_NORMAL" assert state["middle_mode"] == "KIMCHI_STORAGE_NORMAL" assert state["bottom_mode"] == "KIMCHI_STORAGE_NORMAL" assert state["top_open"] is False assert "middle_open" not in state # no /kimchidoors/middle/vs/0 reported assert "flex_zone_mode" not in state # no resolvable overlap on this family class TestArtik051DongleRefFixtureCoverage: """Issues #77/#83: the ARTIK051_DONGLE_REF standalone freezer resolves to the refrigerator registry (segment-based modelNum detection) with zero unbound hrefs, and its door/temperature entities -- which only bind through pattern capabilities the 'unknown' fallback never tried -- now carry real values.""" def test_no_unbound_hrefs_and_expected_entities(self): from custom_components.localthings.registry.adapter import flatten from custom_components.localthings.registry.by_type import ( for_device_by_model, refrigerator, ) from custom_components.localthings.registry.discovery import discover from tests.conftest import _load_device resources = _load_device("refrigerator_artik051_dongle_ref") info = resources["/information/vs/0"] reg = for_device_by_model( info["x.com.samsung.da.modelNum"], info["x.com.samsung.da.description"] ) assert reg is not None and reg.name == "refrigerator" unbound = [] bound = discover( resources, refrigerator.REGISTRY.capabilities, refrigerator.REGISTRY.pattern_capabilities, log=unbound.append, ) assert unbound == [] state = flatten(bound, resources) assert state["door_onedoorfreezer_open"] is False # rep reports 'Close' assert state["freezer_temperature"] == -20.0 assert state["freezer_setpoint"] == -20.0 class TestArtik051DongleRefCoolerFixtureCoverage: """Issue #78: RR40M7165WW, the fridge half of the same household ARTIK051_DONGLE_REF dongle setup as issue #77's freezer. Notably reports *two* door hrefs (/door/cooler/0 and /door/onedoorfreezer/vs/0) despite being a single-door fridge, not a fridge/freezer combo -- apparently shared firmware naming across the product line, not a real second compartment. Both must still resolve to zero unbound hrefs and real values with the same fix as #77.""" def test_no_unbound_hrefs_and_expected_entities(self): from custom_components.localthings.registry.adapter import flatten from custom_components.localthings.registry.by_type import ( for_device_by_model, refrigerator, ) from custom_components.localthings.registry.discovery import discover from tests.conftest import _load_device resources = _load_device("refrigerator_artik051_dongle_ref_cooler") info = resources["/information/vs/0"] reg = for_device_by_model( info["x.com.samsung.da.modelNum"], info["x.com.samsung.da.description"] ) assert reg is not None and reg.name == "refrigerator" unbound = [] bound = discover( resources, refrigerator.REGISTRY.capabilities, refrigerator.REGISTRY.pattern_capabilities, log=unbound.append, ) assert unbound == [] state = flatten(bound, resources) assert state["door_cooler_open"] is False assert state["door_onedoorfreezer_open"] is False assert state["cooler_temperature"] == 3.0 assert state["cooler_setpoint"] == 3.0 class TestRefrigeratorAiEnergyLevelFixtureCoverage: """AI energy-saving level (common.AI_ENERGY_LEVEL, see test_common_capabilities.py) is exercised end-to-end here against the refrigerator fixture/registry. refrigerator_device.json's supportedAiLevel was extended to two entries (['1', '2']) specifically to exercise the select branch -- the real captured TP1X_REF_21K_US dump only ever reports one entry (switch branch), so the select is synthetic-fixture-only for now.""" def test_synthetic_fixture_has_complete_coverage(self): from custom_components.localthings.registry.adapter import flatten from custom_components.localthings.registry.by_type import refrigerator from custom_components.localthings.registry.discovery import discover from tests.conftest import _load_device resources = _load_device("refrigerator") unbound = [] bound = discover( resources, refrigerator.REGISTRY.capabilities, refrigerator.REGISTRY.pattern_capabilities, log=unbound.append, ) assert unbound == [] state = flatten(bound, resources) assert state["ai_energy_level"] == "1" class TestSwitchOffIsNotInverted: """Regression: several fridge SwitchDesc write_fns used ``'On' if p else 'Off'``. The switch platform passes the literal string ``'Off'`` on turn-off (and ``'On'`` on turn-on). ``'Off'`` is a non-empty, truthy string, so ``'On' if p else 'Off'`` always evaluated to ``'On'`` — turning the switch OFF silently re-sent ``On`` and the switch could never be turned off. The guard must compare ``p == 'On'`` (as the other capability files already do). """ # (switch descriptor, payload key it writes) CASES: ClassVar[list] = [ (fridge.ICEMAKER_NIGHTTIME.entities[0], "ice.night.status"), (fridge.STATUS_LOCK.entities[0], "x.com.samsung.da.ado.devicecontrol"), (fridge.STATUS_LOCK.entities[1], "x.com.samsung.da.device.sound"), (fridge.DEFROST_DELAY.entities[0], "x.com.samsung.da.delayDefrost"), (fridge.WELCOME_LIGHTING.entities[0], "status"), (fridge.CABINET_LIGHT.entities[1], "light.dimming.status"), (fridge.ICEMAKER_STATUS_FALLBACK.entities[0], "x.com.samsung.da.iceMaker"), ] def test_turning_off_sends_off(self): for desc, key in self.CASES: _segs, payload = desc.write_fn("Off", {}) assert payload[key] == "Off", ( f"{desc.key}: OFF must send 'Off', got {payload[key]!r} (inverted)" ) def test_turning_on_sends_on(self): for desc, key in self.CASES: _segs, payload = desc.write_fn("On", {}) assert payload[key] == "On", f"{desc.key}: ON must send 'On', got {payload[key]!r}"