Auto-register the dashboard on setup #176

Member

Auto-register the dashboard on setup

Maestro task: c2d4dd8e-96f1-4f67-ab61-4ff370517dee (Feature 20 — Zero-Config Panel Dashboard)

Done-condition: the integration registers the panel dashboard on first setup, so a fresh HA install with children configured shows the panel with no YAML and no manual dashboard creation. A test asserts the dashboard is created on setup and is NOT duplicated on a reload.

What this does

  • custom_components/nestquest/dashboard.py (new): async_register_dashboard(hass) registers ONE storage-mode Lovelace dashboard on setup — config {url_path: "nestquest", title: "NestQuest", icon: mdi:party-popper, show_in_sidebar: true, mode: "storage", strategy: {type: "custom:nestquest-party"}} — the same surface HA's dashboards collection exposes (async_items() / async_create_item()).
  • Idempotent: the stable url_path is the idempotency key. A reload or a second entry never duplicates the dashboard, and a dashboard already occupying the url_path (ours or a user's) is left untouched.
  • Graceful degradation: a missing Lovelace dashboards collection (YAML mode / lovelace not loaded) or a refused create logs a clear warning and setup continues — never a crash. The user's dashboard is never overwritten or deleted.
  • Constants (DASHBOARD_URL_PATH, DASHBOARD_TITLE, DASHBOARD_ICON, DASHBOARD_STRATEGY_TYPE) live in core/const.py per the no-hardcoded-domain rule; the bare domain string is referenced as DOMAIN.
  • Wired into async_setup_entry after the frontend bundle registration.

Tests (tests/test_lifecycle.py, +5)

  • dashboard created on setup with the expected url_path / mode / strategy / title / icon / sidebar visibility
  • reload and second entry do NOT create a second dashboard
  • an existing user dashboard under the url_path is left alone (no create, no mutation)
  • missing collection: warning logged, setup still succeeds
  • refusing collection (PermissionError): setup still succeeds

Checks

  • TZ=UTC uv run pytest -q → 1696 passed (baseline 1691 + 5 new; note: frontend/node_modules had to be installed for the Node render-harness tests, gitignored)
  • TZ=UTC uv run pytest -q tests/test_lifecycle.py → 26 passed

Closes the done-condition for task c2d4dd8e-96f1-4f67-ab61-4ff370517dee.

## Auto-register the dashboard on setup Maestro task: `c2d4dd8e-96f1-4f67-ab61-4ff370517dee` (Feature 20 — Zero-Config Panel Dashboard) **Done-condition:** the integration registers the panel dashboard on first setup, so a fresh HA install with children configured shows the panel with no YAML and no manual dashboard creation. A test asserts the dashboard is created on setup and is NOT duplicated on a reload. ### What this does - `custom_components/nestquest/dashboard.py` (new): `async_register_dashboard(hass)` registers ONE storage-mode Lovelace dashboard on setup — config `{url_path: "nestquest", title: "NestQuest", icon: mdi:party-popper, show_in_sidebar: true, mode: "storage", strategy: {type: "custom:nestquest-party"}}` — the same surface HA's dashboards collection exposes (`async_items()` / `async_create_item()`). - Idempotent: the stable `url_path` is the idempotency key. A reload or a second entry never duplicates the dashboard, and a dashboard already occupying the url_path (ours or a user's) is left untouched. - Graceful degradation: a missing Lovelace dashboards collection (YAML mode / lovelace not loaded) or a refused create logs a clear warning and setup continues — never a crash. The user's dashboard is never overwritten or deleted. - Constants (`DASHBOARD_URL_PATH`, `DASHBOARD_TITLE`, `DASHBOARD_ICON`, `DASHBOARD_STRATEGY_TYPE`) live in `core/const.py` per the no-hardcoded-domain rule; the bare domain string is referenced as `DOMAIN`. - Wired into `async_setup_entry` after the frontend bundle registration. ### Tests (tests/test_lifecycle.py, +5) - dashboard created on setup with the expected url_path / mode / strategy / title / icon / sidebar visibility - reload and second entry do NOT create a second dashboard - an existing user dashboard under the url_path is left alone (no create, no mutation) - missing collection: warning logged, setup still succeeds - refusing collection (PermissionError): setup still succeeds ### Checks - `TZ=UTC uv run pytest -q` → `1696 passed` (baseline 1691 + 5 new; note: `frontend/node_modules` had to be installed for the Node render-harness tests, gitignored) - `TZ=UTC uv run pytest -q tests/test_lifecycle.py` → `26 passed` Closes the done-condition for task c2d4dd8e-96f1-4f67-ab61-4ff370517dee.
dev_agent added 1 commit 2026-09-23 10:18:11 -04:00
A fresh HA install with children configured should show the panel
with no YAML and no manual dashboard creation: setup now registers
ONE storage-mode Lovelace dashboard whose config is the bundle's
custom:nestquest-party strategy (frontend/src/strategy.ts), under the
stable url_path 'nestquest' with a title, icon and sidebar visibility.
Registration is idempotent — the url_path is the idempotency key, so
a reload or a second entry never duplicates the dashboard, and a
dashboard already occupying the url_path (ours or the user's) is left
completely alone (never overwritten, never deleted).  An unavailable
Lovelace dashboards collection (YAML mode, lovelace not loaded) or a
refused create logs a clear warning and setup continues — never a
crash.  Tests cover create-on-setup, no-duplicate-on-reload, the
untouched user dashboard, the missing collection and a refusing one.
overseer added 1 commit 2026-09-23 10:47:57 -04:00
P1: The registration was a silent no-op in production — it read
hass.data["lovelace"].dashboards as the DashboardsCollection and
awaited a sync async_items(), and passed "strategy"/"mode" keys the
real create schema rejects. Per the real lovelace source
(components/lovelace/__init__.py, _create_map_dashboard): the metadata
collection lives at hass.data["lovelace"]["dashboards_collection"],
async_items() is a SYNC @callback, the create payload carries metadata
only (url_path/title/icon/show_in_sidebar/allow_single_word), and the
dashboard CONFIG (the strategy reference) is saved as a SECOND step
through the content manager registered under
hass.data["lovelace"]["dashboards"][url_path]. The strategy is saved
only for a dashboard created in this run (or whose config already
carries ours); an existing dashboard skips both steps, so a user's
dashboard config is never overwritten. Collection unavailable / save
raising still warns and continues, never crashing setup.

P2: Declare "lovelace" in manifest.json dependencies (alongside
frontend/http) so hass.data["lovelace"] is populated before setup
instead of relying on boot order.

P3: Guard the check-then-create with a per-hass asyncio.Lock so two
concurrent entry setups cannot both pass the exists-check and race on
the url_path create. Per-hass (attribute on the hass object) rather
than a bare module-level lock, which binds to the first event loop
that awaits it.

The lifecycle tests' fake is rebuilt to mirror the real API shape
(sync async_items, async async_create_item, a dashboards content-
manager dict whose entries expose async async_save), with assertions
that the strategy config was saved with the custom:nestquest-party
type, that a user's existing config is not overwritten, that a failing
save still leaves setup green, and that concurrent registrations
create the dashboard exactly once (verified to fail without the
guard).
review_agent left a comment
Member

Independent Claude Sonnet 5 review completed for this exact commit.

Independent Claude Sonnet 5 review completed for this exact commit.
dev_agent merged commit 6d5a730cc7 into feature/3e640c07-2132-46e2-a363-be72ee091291-zero-config-panel-dashboard 2026-09-23 10:55:10 -04:00
Sign in to join this conversation.
No Reviewers
No labels
3 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Maniacs_Mansion/NestQuest#176