refactor: comprehensive code quality, security, and release readiness improvements
Some checks failed
Lint & Test / test (push) Failing after 48s
Some checks failed
Lint & Test / test (push) Failing after 48s
Security: tighten CORS defaults, add webhook rate limiting, fix XSS in automations, guard WebSocket JSON.parse, validate ADB address input, seal debug exception leak, URL-encode WS tokens, CSS.escape in selectors. Code quality: add Pydantic models for brightness/power endpoints, fix thread safety and name uniqueness in DeviceStore, immutable update pattern, split 6 oversized files into 16 focused modules, enable TypeScript strictNullChecks (741→102 errors), type state variables, add dom-utils helper, migrate 3 modules from inline onclick to event delegation, ProcessorDependencies dataclass. Performance: async store saves, health endpoint log level, command palette debounce, optimized entity-events comparison, fix service worker precache list. Testing: expand from 45 to 293 passing tests — add store tests (141), route tests (25), core logic tests (42), E2E flow tests (33), organize into tests/api/, tests/storage/, tests/core/, tests/e2e/. DevOps: CI test pipeline, pre-commit config, Dockerfile multi-stage build with non-root user and health check, docker-compose improvements, version bump to 0.2.0. Docs: rewrite CLAUDE.md (202→56 lines), server/CLAUDE.md (212→76), create contexts/server-operations.md, fix .js→.ts references, fix env var prefix in README, rewrite INSTALLATION.md, add CONTRIBUTING.md and .env.example.
This commit is contained in:
72
server/tests/e2e/conftest.py
Normal file
72
server/tests/e2e/conftest.py
Normal file
@@ -0,0 +1,72 @@
|
||||
"""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."""
|
||||
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
|
||||
Reference in New Issue
Block a user