Some checks failed
Lint & Test / test (push) Failing after 1m33s
All store tests were passing file paths instead of Database objects after the JSON-to-SQLite migration. Updated fixtures to create temp Database instances, rewrote backup e2e tests for binary .db format, and fixed config tests for the simplified StorageConfig.
244 lines
6.9 KiB
Python
244 lines
6.9 KiB
Python
"""Pytest configuration and shared fixtures."""
|
|
|
|
from datetime import datetime, timezone
|
|
|
|
import pytest
|
|
|
|
from wled_controller.config import Config, StorageConfig, ServerConfig, AuthConfig
|
|
from wled_controller.storage.database import Database
|
|
from wled_controller.storage.device_store import Device, DeviceStore
|
|
from wled_controller.storage.sync_clock import SyncClock
|
|
from wled_controller.storage.sync_clock_store import SyncClockStore
|
|
from wled_controller.storage.output_target_store import OutputTargetStore
|
|
from wled_controller.storage.automation import (
|
|
Automation,
|
|
)
|
|
from wled_controller.storage.automation_store import AutomationStore
|
|
from wled_controller.storage.value_source_store import ValueSourceStore
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Directory / path fixtures
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@pytest.fixture
|
|
def test_data_dir(tmp_path):
|
|
"""Provide a temporary directory for test data."""
|
|
d = tmp_path / "data"
|
|
d.mkdir(parents=True, exist_ok=True)
|
|
return d
|
|
|
|
|
|
@pytest.fixture
|
|
def test_config_dir(tmp_path):
|
|
"""Provide a temporary directory for test configuration."""
|
|
return tmp_path / "config"
|
|
|
|
|
|
@pytest.fixture
|
|
def temp_store_dir(tmp_path):
|
|
"""Provide a temp directory for store files, cleaned up after tests."""
|
|
d = tmp_path / "stores"
|
|
d.mkdir(parents=True, exist_ok=True)
|
|
return d
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Database fixture
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@pytest.fixture
|
|
def tmp_db(tmp_path):
|
|
"""Provide a temporary SQLite Database instance."""
|
|
db = Database(tmp_path / "test.db")
|
|
yield db
|
|
db.close()
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Config fixtures
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@pytest.fixture
|
|
def test_config(tmp_path):
|
|
"""A Config instance with temp directories for all store files."""
|
|
data_dir = tmp_path / "data"
|
|
data_dir.mkdir(parents=True, exist_ok=True)
|
|
|
|
storage = StorageConfig(
|
|
database_file=str(data_dir / "test.db"),
|
|
)
|
|
|
|
return Config(
|
|
server=ServerConfig(host="127.0.0.1", port=9999),
|
|
auth=AuthConfig(api_keys={"test": "test-api-key-12345"}),
|
|
storage=storage,
|
|
)
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Store fixtures
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@pytest.fixture
|
|
def device_store(tmp_db):
|
|
"""Provide a DeviceStore backed by a temp database."""
|
|
return DeviceStore(tmp_db)
|
|
|
|
|
|
@pytest.fixture
|
|
def sync_clock_store(tmp_db):
|
|
"""Provide a SyncClockStore backed by a temp database."""
|
|
return SyncClockStore(tmp_db)
|
|
|
|
|
|
@pytest.fixture
|
|
def output_target_store(tmp_db):
|
|
"""Provide an OutputTargetStore backed by a temp database."""
|
|
return OutputTargetStore(tmp_db)
|
|
|
|
|
|
@pytest.fixture
|
|
def automation_store(tmp_db):
|
|
"""Provide an AutomationStore backed by a temp database."""
|
|
return AutomationStore(tmp_db)
|
|
|
|
|
|
@pytest.fixture
|
|
def value_source_store(tmp_db):
|
|
"""Provide a ValueSourceStore backed by a temp database."""
|
|
return ValueSourceStore(tmp_db)
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Sample entity factories
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@pytest.fixture
|
|
def sample_device():
|
|
"""Provide a sample device configuration dict."""
|
|
return {
|
|
"id": "test_device_001",
|
|
"name": "Test WLED Device",
|
|
"url": "http://192.168.1.100",
|
|
"led_count": 150,
|
|
"enabled": True,
|
|
"device_type": "wled",
|
|
}
|
|
|
|
|
|
@pytest.fixture
|
|
def make_device():
|
|
"""Factory fixture: call make_device(name=..., **overrides) to build a Device."""
|
|
_counter = 0
|
|
|
|
def _factory(name=None, **kwargs):
|
|
nonlocal _counter
|
|
_counter += 1
|
|
defaults = dict(
|
|
device_id=f"device_test_{_counter:04d}",
|
|
name=name or f"Device {_counter}",
|
|
url=f"http://192.168.1.{_counter}",
|
|
led_count=150,
|
|
)
|
|
defaults.update(kwargs)
|
|
return Device(**defaults)
|
|
|
|
return _factory
|
|
|
|
|
|
@pytest.fixture
|
|
def make_sync_clock():
|
|
"""Factory fixture: call make_sync_clock(name=..., **overrides)."""
|
|
_counter = 0
|
|
|
|
def _factory(name=None, **kwargs):
|
|
nonlocal _counter
|
|
_counter += 1
|
|
now = datetime.now(timezone.utc)
|
|
defaults = dict(
|
|
id=f"sc_test_{_counter:04d}",
|
|
name=name or f"Clock {_counter}",
|
|
speed=1.0,
|
|
created_at=now,
|
|
updated_at=now,
|
|
)
|
|
defaults.update(kwargs)
|
|
return SyncClock(**defaults)
|
|
|
|
return _factory
|
|
|
|
|
|
@pytest.fixture
|
|
def make_automation():
|
|
"""Factory fixture: call make_automation(name=..., **overrides)."""
|
|
_counter = 0
|
|
|
|
def _factory(name=None, **kwargs):
|
|
nonlocal _counter
|
|
_counter += 1
|
|
now = datetime.now(timezone.utc)
|
|
defaults = dict(
|
|
id=f"auto_test_{_counter:04d}",
|
|
name=name or f"Automation {_counter}",
|
|
enabled=True,
|
|
condition_logic="or",
|
|
conditions=[],
|
|
scene_preset_id=None,
|
|
deactivation_mode="none",
|
|
deactivation_scene_preset_id=None,
|
|
created_at=now,
|
|
updated_at=now,
|
|
)
|
|
defaults.update(kwargs)
|
|
return Automation(**defaults)
|
|
|
|
return _factory
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Authenticated test client
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@pytest.fixture
|
|
def authenticated_client(test_config, monkeypatch):
|
|
"""Provide a FastAPI TestClient with auth header pre-set.
|
|
|
|
Patches global config so the app uses temp storage paths.
|
|
"""
|
|
import wled_controller.config as config_mod
|
|
monkeypatch.setattr(config_mod, "config", test_config)
|
|
|
|
from fastapi.testclient import TestClient
|
|
from wled_controller.main import app
|
|
|
|
client = TestClient(app, raise_server_exceptions=False)
|
|
client.headers["Authorization"] = "Bearer test-api-key-12345"
|
|
return client
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Calibration sample (kept from original conftest)
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@pytest.fixture
|
|
def sample_calibration():
|
|
"""Provide a sample calibration configuration."""
|
|
return {
|
|
"layout": "clockwise",
|
|
"start_position": "bottom_left",
|
|
"segments": [
|
|
{"edge": "bottom", "led_start": 0, "led_count": 40, "reverse": False},
|
|
{"edge": "right", "led_start": 40, "led_count": 30, "reverse": False},
|
|
{"edge": "top", "led_start": 70, "led_count": 40, "reverse": True},
|
|
{"edge": "left", "led_start": 110, "led_count": 40, "reverse": True},
|
|
],
|
|
}
|