Admin routes: children CRUD over the core business layer
Task e4845baa (feature 16, NestQuest API service): the admin PWA needs to manage the children registry, but the only removal path the domain allows is deactivation and the name/NULL/bool/permutation policies all live in core.children — so the plane gets thin adapters that forward each request to ONE core call and never re-implement a rule. WHY: create/edit/set_active/reorder (+ a thin GET list) hang off the router's ONE require_admin dependency; edit forwards only the fields the request supplied (exclude_unset) so an omitted field stays unchanged while an explicit null is rejected by the core rather than silently ignored. Core ValueErrors map to 404 (non-existent child) or 422 (invalid input, same class Pydantic reports) and are documented in the module docstring; the core rejects before any write, so neither status can leave a half-applied change. The admin JWT test harness (local RSA keys, stubbed JWKS, token minting, app runner) is factored into tests/admin_jwt_harness.py so the children route tests reuse it instead of duplicating it; the auth tests import the same harness with unchanged test bodies, and the shared temp_db_path/admin_client fixtures now live in conftest.py. TZ=UTC uv run pytest -q: 1669 passed (baseline 1652 + 17 new).
This commit is contained in:
+25
-1
@@ -33,8 +33,11 @@ from pathlib import Path
|
||||
from types import SimpleNamespace
|
||||
from unittest.mock import AsyncMock, MagicMock
|
||||
|
||||
import httpx
|
||||
import pytest
|
||||
|
||||
from tests.admin_jwt_harness import ADMIN_KEY, KID, AdminRunner, jwks_for
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Homeassistant module provisioning (explicitly mock-only).
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -953,4 +956,25 @@ def freeze_nestquest_clock(
|
||||
date=datetime.date,
|
||||
)
|
||||
monkeypatch.setattr(nestquest, "datetime", fake_module)
|
||||
return frozen, requested
|
||||
return frozen, requested
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Admin-plane API fixtures (shared by the admin-plane test modules).
|
||||
#
|
||||
# The local-key/stubbed-JWKS harness itself lives in
|
||||
# :mod:`tests.admin_jwt_harness` (imported by name, the same pattern as
|
||||
# tests.blueprint_helpers); these fixtures hand its runner to every test
|
||||
# module in tests/ without re-declaring it.
|
||||
# ---------------------------------------------------------------------------
|
||||
@pytest.fixture
|
||||
def temp_db_path(tmp_path: Path) -> str:
|
||||
"""A fresh per-test SQLite path under pytest's tmp_path."""
|
||||
return str(tmp_path / "nestquest.db")
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def admin_client(temp_db_path: str) -> httpx.AsyncClient:
|
||||
"""An app client whose provider publishes the admin test key."""
|
||||
async with AdminRunner(temp_db_path, jwks_for(ADMIN_KEY, KID)) as client:
|
||||
yield client
|
||||
Reference in New Issue
Block a user