diff --git a/README.md b/README.md index 2288c4f..df7cada 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Async-first, high-level Python client for Home Assistant with REST and WebSocket ## Features - Async context manager with automatic WebSocket connection and state priming -- Typed domain accessors: light, switch, climate, cover, sensor, binary sensor, media player, scene, timer +- Typed domain accessors: air quality, binary sensor, climate, cover, event, fan, humidifier, light, lock, media player, scene, sensor, switch, timer, vacuum, valve - Intent-specific methods over raw service calls (e.g. `light.set_brightness(200)` instead of `light.turn_on(brightness=200)`) - Real-time state change listeners with granular attribute and state-transition filtering - Synchronous blocking wrapper for scripts, REPL, and Jupyter diff --git a/docs/index.md b/docs/index.md index cd583c7..2d4105e 100644 --- a/docs/index.md +++ b/docs/index.md @@ -11,8 +11,10 @@ WebSocket support. ship via the `haclient.domains` entry-point group. - Async context manager with automatic WebSocket connect, race-free state priming, and reconnect-aware refresh. -- Typed domain accessors: `light`, `switch`, `climate`, `cover`, - `sensor`, `binary_sensor`, `media_player`, `scene`, `timer`. +- Typed domain accessors: `air_quality`, `binary_sensor`, `climate`, + `cover`, `event`, `fan`, `humidifier`, `light`, `lock`, + `media_player`, `scene`, `sensor`, `switch`, `timer`, `vacuum`, + `valve`. - Real-time state-change listeners with attribute and transition filtering. - Synchronous blocking wrapper for scripts, REPL, and Jupyter. diff --git a/docs/reference/domains/air_quality.md b/docs/reference/domains/air_quality.md new file mode 100644 index 0000000..278a024 --- /dev/null +++ b/docs/reference/domains/air_quality.md @@ -0,0 +1,3 @@ +# Air Quality + +::: haclient.domains.air_quality diff --git a/docs/reference/domains/event.md b/docs/reference/domains/event.md new file mode 100644 index 0000000..67bd2d7 --- /dev/null +++ b/docs/reference/domains/event.md @@ -0,0 +1,3 @@ +# Event + +::: haclient.domains.event diff --git a/docs/reference/domains/fan.md b/docs/reference/domains/fan.md new file mode 100644 index 0000000..f8b5fcb --- /dev/null +++ b/docs/reference/domains/fan.md @@ -0,0 +1,3 @@ +# Fan + +::: haclient.domains.fan diff --git a/docs/reference/domains/humidifier.md b/docs/reference/domains/humidifier.md new file mode 100644 index 0000000..e381c6e --- /dev/null +++ b/docs/reference/domains/humidifier.md @@ -0,0 +1,3 @@ +# Humidifier + +::: haclient.domains.humidifier diff --git a/docs/reference/domains/lock.md b/docs/reference/domains/lock.md new file mode 100644 index 0000000..dc70fc1 --- /dev/null +++ b/docs/reference/domains/lock.md @@ -0,0 +1,3 @@ +# Lock + +::: haclient.domains.lock diff --git a/docs/reference/domains/vacuum.md b/docs/reference/domains/vacuum.md new file mode 100644 index 0000000..e78f7e3 --- /dev/null +++ b/docs/reference/domains/vacuum.md @@ -0,0 +1,3 @@ +# Vacuum + +::: haclient.domains.vacuum diff --git a/docs/reference/domains/valve.md b/docs/reference/domains/valve.md new file mode 100644 index 0000000..bc28b0f --- /dev/null +++ b/docs/reference/domains/valve.md @@ -0,0 +1,3 @@ +# Valve + +::: haclient.domains.valve diff --git a/mkdocs.yml b/mkdocs.yml index 2e55555..9414806 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -40,15 +40,22 @@ nav: - REST adapter: reference/infra/rest_aiohttp.md - WebSocket adapter: reference/infra/ws_aiohttp.md - Domains: - - Light: reference/domains/light.md - - Switch: reference/domains/switch.md + - Air Quality: reference/domains/air_quality.md + - Binary Sensor: reference/domains/binary_sensor.md - Climate: reference/domains/climate.md - Cover: reference/domains/cover.md - - Sensor: reference/domains/sensor.md - - Binary Sensor: reference/domains/binary_sensor.md + - Event: reference/domains/event.md + - Fan: reference/domains/fan.md + - Humidifier: reference/domains/humidifier.md + - Light: reference/domains/light.md + - Lock: reference/domains/lock.md - Media Player: reference/domains/media_player.md - Scene: reference/domains/scene.md + - Sensor: reference/domains/sensor.md + - Switch: reference/domains/switch.md - Timer: reference/domains/timer.md + - Vacuum: reference/domains/vacuum.md + - Valve: reference/domains/valve.md hooks: - tools/mkdocs_hooks.py diff --git a/tests/test_docs_completeness.py b/tests/test_docs_completeness.py new file mode 100644 index 0000000..a022914 --- /dev/null +++ b/tests/test_docs_completeness.py @@ -0,0 +1,43 @@ +"""Documentation completeness tests. + +Guards against drift between registered built-in domains and the +documentation surface (MkDocs nav and reference pages). See issue #90. +""" + +from __future__ import annotations + +from pathlib import Path + +import haclient.domains # noqa: F401 -- registers built-in domains +from haclient.core.plugins import DomainRegistry + +REPO_ROOT = Path(__file__).resolve().parents[1] +DOMAINS_DIR = REPO_ROOT / "docs" / "reference" / "domains" +MKDOCS_YML = REPO_ROOT / "mkdocs.yml" + + +def _registered_builtin_domains() -> set[str]: + """Return the set of built-in domain names registered at import time. + + Returns + ------- + set of str + Names registered via ``haclient.domains.__init__`` imports. + """ + return set(DomainRegistry.shared().names()) + + +def test_every_builtin_domain_has_reference_page() -> None: + """Every registered built-in domain must have a Markdown reference page.""" + expected = _registered_builtin_domains() + existing = {p.stem for p in DOMAINS_DIR.glob("*.md")} + missing = expected - existing + assert not missing, f"Missing domain reference pages: {sorted(missing)}" + + +def test_every_builtin_domain_listed_in_mkdocs_nav() -> None: + """Every registered built-in domain must appear in the MkDocs nav.""" + nav_text = MKDOCS_YML.read_text(encoding="utf-8") + expected = _registered_builtin_domains() + missing = {name for name in expected if f"reference/domains/{name}.md" not in nav_text} + assert not missing, f"Domains missing from mkdocs.yml nav: {sorted(missing)}"