All checks were successful
Lint & Test / test (push) Successful in 27s
- Add unfreeze_saves() to base_store.py and call it in e2e cleanup. The backup restore flow calls freeze_saves() which sets a module-level flag that silently disables all store _save() calls. Without reset, this poisoned all subsequent persistence tests (9 failures). - Fix os_listener toggle to use toggle-switch/toggle-slider CSS classes instead of nonexistent switch/slider classes (was showing plain checkbox). - Add mandatory test run to CLAUDE.md pre-commit checks. All 341 tests now pass.
78 lines
2.7 KiB
Python
78 lines
2.7 KiB
Python
"""Shared fixtures for end-to-end API tests.
|
|
|
|
Uses the real FastAPI app with a module-scoped TestClient to avoid
|
|
repeated lifespan startup/shutdown issues. Each test function gets
|
|
fresh, empty stores via the _clear_stores helper.
|
|
"""
|
|
|
|
import pytest
|
|
|
|
from wled_controller.config import get_config
|
|
|
|
|
|
# Resolve the API key from the real config (same key used in production tests)
|
|
_config = get_config()
|
|
API_KEY = next(iter(_config.auth.api_keys.values()), "")
|
|
AUTH_HEADERS = {"Authorization": f"Bearer {API_KEY}"}
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def _test_client():
|
|
"""Session-scoped TestClient to avoid lifespan re-entry issues.
|
|
|
|
The app's lifespan (MQTT, automation engine, health monitoring, etc.)
|
|
starts once for the entire e2e test session and shuts down after all
|
|
tests complete.
|
|
"""
|
|
from fastapi.testclient import TestClient
|
|
from wled_controller.main import app
|
|
|
|
with TestClient(app, raise_server_exceptions=False) as c:
|
|
yield c
|
|
|
|
|
|
@pytest.fixture
|
|
def client(_test_client):
|
|
"""Per-test client with auth headers and clean stores.
|
|
|
|
Clears all entity stores before each test so tests are independent.
|
|
"""
|
|
_clear_stores()
|
|
_test_client.headers["Authorization"] = f"Bearer {API_KEY}"
|
|
yield _test_client
|
|
# Clean up after test
|
|
_clear_stores()
|
|
|
|
|
|
def _clear_stores():
|
|
"""Remove all entities from all stores for test isolation."""
|
|
# Reset the saves-frozen flag that freeze_saves() sets during restore flows.
|
|
# Without this, subsequent tests can't persist data because _save() is a no-op.
|
|
from wled_controller.storage.base_store import unfreeze_saves
|
|
unfreeze_saves()
|
|
|
|
from wled_controller.api import dependencies as deps
|
|
|
|
store_clearers = [
|
|
(deps.get_device_store, "get_all_devices", "delete_device"),
|
|
(deps.get_output_target_store, "get_all_targets", "delete_target"),
|
|
(deps.get_color_strip_store, "get_all_sources", "delete_source"),
|
|
(deps.get_value_source_store, "get_all", "delete"),
|
|
(deps.get_sync_clock_store, "get_all", "delete"),
|
|
(deps.get_automation_store, "get_all", "delete"),
|
|
(deps.get_scene_preset_store, "get_all", "delete"),
|
|
]
|
|
for getter, list_method, delete_method in store_clearers:
|
|
try:
|
|
store = getter()
|
|
items = getattr(store, list_method)()
|
|
for item in items:
|
|
item_id = getattr(item, "id", getattr(item, "device_id", None))
|
|
if item_id:
|
|
try:
|
|
getattr(store, delete_method)(item_id)
|
|
except Exception:
|
|
pass
|
|
except RuntimeError:
|
|
pass # Store not initialized yet
|