Maps the fridge/dishwasher hrefs flagged by last session's coverage-gap Repairs issue: defrost delay (switch) + block status (diagnostic binary sensor), master ice-maker enable, self-check trigger/status, dishwasher diagnosis trigger/status, and last-operation-source. Adds fallback capabilities for /doors, /temperatures, and /icemaker/status that only bind when the richer per-instance hrefs they duplicate are absent, so simpler devices without those hrefs still get the data. Everything else in the original gap list moves to capabilities.ignored (Bixby audio feedback, inert DR/energy-planner resources, redundant metadata). Fixes discover() reporting a known href as an unregistered gap whenever its match_fn declined to bind for that device (e.g. a filter capability on hardware without that filter) — it's now only a gap when no capability is registered for the href at all. Device naming now uses x.com.samsung.da.modelNum (not the OCF /oic/p,d metadata, which produced inconsistent names like "[dishwasher] Samsung") to build "Samsung <Type> (<model>)".
60 lines
2.4 KiB
Python
60 lines
2.4 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()
|