Files
localthings/tests/test_registry_ignored.py
T
Marc Billow e07d6ed706 Complete dryer coverage from issue #14 screenshots (DV90BB5245AES1)
Name the two remaining unidentified course codes (0x21 Hygiene Care,
0x4C Air Refresh) by matching the SmartThings app's course-list order
against editCourseList in the reporter's dump.

Also close three entity gaps the screenshots surfaced that v0.6.0
missed: dry level was read-only despite the app exposing a writable
Level 1/2/3 picker; the app's "AI pattern" toggle (AiOption_On/Off)
and "Auto cycle link" toggle (/cycleinterface/vs/0, previously
globally ignored as always-empty on washer dumps) were both unbound.
Scope that ignore to washer.py now that the dryer binds it for real.
2026-07-24 00:43:58 +00:00

86 lines
3.6 KiB
Python

"""Tests that known-noise hrefs don't show up as coverage gaps.
Each device-type registry folds in registry.capabilities.ignored.IGNORED so
that Bixby/voice/network/OTA housekeeping resources aren't reported as
unbound. This guards two things at once: that the ignored hrefs are
actually suppressed, and (via a plain import) that no ignored href
collides with a real capability declared elsewhere for the same family.
"""
import json
from pathlib import Path
from custom_components.localthings.registry.batch import parse_device0_batch
from custom_components.localthings.registry.by_type import dishwasher, refrigerator
from custom_components.localthings.registry.capabilities.ignored import IGNORED
FIXTURES = Path(__file__).resolve().parent / 'fixtures'
_IGNORED_HREFS = {cap.href for cap in IGNORED}
def _load(name: str) -> dict:
data = json.loads((FIXTURES / name).read_text())
return parse_device0_batch(data['device0'])
def _unbound_hrefs(resources, registry) -> list[str]:
unbound = []
from custom_components.localthings.registry.discovery import discover
discover(resources, registry.capabilities, registry.pattern_capabilities,
log=unbound.append)
return unbound
def test_ignored_hrefs_absent_from_dishwasher_gaps():
resources = _load('dishwasher_device.json')
unbound = _unbound_hrefs(resources, dishwasher.REGISTRY)
present_ignored = _IGNORED_HREFS & set(unbound)
assert not present_ignored, f"ignored hrefs leaked into gap report: {present_ignored}"
def test_ignored_hrefs_absent_from_refrigerator_gaps():
resources = _load('refrigerator_device.json')
unbound = _unbound_hrefs(resources, refrigerator.REGISTRY)
present_ignored = _IGNORED_HREFS & set(unbound)
assert not present_ignored, f"ignored hrefs leaked into gap report: {present_ignored}"
def test_dishwasher_fixture_has_no_remaining_gaps():
"""Sanity check that the gap mechanism isn't silencing everything.
Every href in the dishwasher fixture is now either mapped to a
capability or listed in capabilities.ignored — if this starts failing
because a genuinely new gap appeared, that's the interesting case to
look at (add the href to ignored.py or map it, don't just delete this
assertion).
"""
resources = _load('dishwasher_device.json')
unbound = set(_unbound_hrefs(resources, dishwasher.REGISTRY))
assert unbound == set()
class TestWasherIgnoredHrefs:
def test_washer_hrefs_are_ignored(self):
from custom_components.localthings.registry.capabilities.ignored import IGNORED
ignored_hrefs = {cap.href for cap in IGNORED}
for href in (
'/st/washercourse/vs/0',
'/wm/welcomemsg/vs/0',
'/wm/personalcourse/vs/0',
'/energy/consumption/0',
'/drlc/0',
'/operational/state/0',
):
assert href in ignored_hrefs, f"{href} should be in ignored.IGNORED"
def test_cycleinterface_is_scoped_to_washer_registry(self):
"""/cycleinterface/vs/0 is empty on every washer dump but real on the
dryer (issue #14's AUTO_CYCLE_LINK), so it's a washer-scoped ignore
(washer.CYCLE_INTERFACE_IGNORED) rather than a global one -- a global
entry would collide with the dryer's real capability."""
from custom_components.localthings.registry.by_type import washer as washer_registry
from custom_components.localthings.registry.capabilities.ignored import IGNORED
assert '/cycleinterface/vs/0' not in {cap.href for cap in IGNORED}
assert '/cycleinterface/vs/0' in washer_registry.REGISTRY.capabilities