- Add Color Strip Processing Template (CSPT) entity: reusable filter chains for 1D LED strip postprocessing (backend, storage, API, frontend CRUD) - Add "processed" color strip source type that wraps another CSS source and applies a CSPT filter chain (dataclass, stream, schema, modal, cards) - Add Reverse filter for strip LED order reversal - Add CSPT and processed CSS nodes/edges to visual graph editor - Add CSPT test preview WS endpoint with input source selection - Add device settings CSPT template selector (add + edit modals with hints) - Use icon grids for palette quantization preset selector in filter lists - Use EntitySelect for template references and test modal source selectors - Fix filters.css_filter_template.desc missing localization - Fix icon grid cell height inequality (grid-auto-rows: 1fr) - Rename "Processed" subtab to "Processing Templates" - Localize all new strings (en/ru/zh) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
269 lines
7.0 KiB
Python
269 lines
7.0 KiB
Python
"""Tests for device storage."""
|
|
|
|
import pytest
|
|
from pathlib import Path
|
|
|
|
from wled_controller.storage.device_store import Device, DeviceStore
|
|
|
|
|
|
@pytest.fixture
|
|
def temp_storage(tmp_path):
|
|
"""Provide temporary storage file."""
|
|
return tmp_path / "devices.json"
|
|
|
|
|
|
@pytest.fixture
|
|
def device_store(temp_storage):
|
|
"""Provide device store instance."""
|
|
return DeviceStore(temp_storage)
|
|
|
|
|
|
def test_device_creation():
|
|
"""Test creating a device."""
|
|
device = Device(
|
|
device_id="test_001",
|
|
name="Test Device",
|
|
url="http://192.168.1.100",
|
|
led_count=150,
|
|
)
|
|
|
|
assert device.id == "test_001"
|
|
assert device.name == "Test Device"
|
|
assert device.url == "http://192.168.1.100"
|
|
assert device.led_count == 150
|
|
assert device.enabled is True
|
|
|
|
|
|
def test_device_to_dict():
|
|
"""Test converting device to dictionary."""
|
|
device = Device(
|
|
device_id="test_001",
|
|
name="Test Device",
|
|
url="http://192.168.1.100",
|
|
led_count=150,
|
|
)
|
|
|
|
data = device.to_dict()
|
|
|
|
assert data["id"] == "test_001"
|
|
assert data["name"] == "Test Device"
|
|
assert data["url"] == "http://192.168.1.100"
|
|
assert data["led_count"] == 150
|
|
|
|
|
|
def test_device_from_dict():
|
|
"""Test creating device from dictionary."""
|
|
data = {
|
|
"id": "test_001",
|
|
"name": "Test Device",
|
|
"url": "http://192.168.1.100",
|
|
"led_count": 150,
|
|
"enabled": True,
|
|
}
|
|
|
|
device = Device.from_dict(data)
|
|
|
|
assert device.id == "test_001"
|
|
assert device.name == "Test Device"
|
|
assert device.led_count == 150
|
|
|
|
|
|
def test_device_round_trip():
|
|
"""Test converting device to dict and back."""
|
|
original = Device(
|
|
device_id="test_001",
|
|
name="Test Device",
|
|
url="http://192.168.1.100",
|
|
led_count=150,
|
|
)
|
|
|
|
data = original.to_dict()
|
|
restored = Device.from_dict(data)
|
|
|
|
assert restored.id == original.id
|
|
assert restored.name == original.name
|
|
assert restored.url == original.url
|
|
assert restored.led_count == original.led_count
|
|
|
|
|
|
def test_device_store_init(device_store):
|
|
"""Test device store initialization."""
|
|
assert device_store is not None
|
|
assert device_store.count() == 0
|
|
|
|
|
|
def test_create_device(device_store):
|
|
"""Test creating a device in store."""
|
|
device = device_store.create_device(
|
|
name="Test WLED",
|
|
url="http://192.168.1.100",
|
|
led_count=150,
|
|
)
|
|
|
|
assert device.id is not None
|
|
assert device.name == "Test WLED"
|
|
assert device_store.count() == 1
|
|
|
|
|
|
def test_get_device(device_store):
|
|
"""Test retrieving a device."""
|
|
created = device_store.create_device(
|
|
name="Test WLED",
|
|
url="http://192.168.1.100",
|
|
led_count=150,
|
|
)
|
|
|
|
retrieved = device_store.get_device(created.id)
|
|
|
|
assert retrieved is not None
|
|
assert retrieved.id == created.id
|
|
assert retrieved.name == "Test WLED"
|
|
|
|
|
|
def test_get_device_not_found(device_store):
|
|
"""Test retrieving non-existent device raises ValueError."""
|
|
with pytest.raises(ValueError, match="not found"):
|
|
device_store.get_device("nonexistent")
|
|
|
|
|
|
def test_get_all_devices(device_store):
|
|
"""Test getting all devices."""
|
|
device_store.create_device("Device 1", "http://192.168.1.100", 150)
|
|
device_store.create_device("Device 2", "http://192.168.1.101", 200)
|
|
|
|
devices = device_store.get_all_devices()
|
|
|
|
assert len(devices) == 2
|
|
assert any(d.name == "Device 1" for d in devices)
|
|
assert any(d.name == "Device 2" for d in devices)
|
|
|
|
|
|
def test_update_device(device_store):
|
|
"""Test updating a device."""
|
|
device = device_store.create_device(
|
|
name="Test WLED",
|
|
url="http://192.168.1.100",
|
|
led_count=150,
|
|
)
|
|
|
|
updated = device_store.update_device(
|
|
device.id,
|
|
name="Updated WLED",
|
|
enabled=False,
|
|
)
|
|
|
|
assert updated.name == "Updated WLED"
|
|
assert updated.enabled is False
|
|
|
|
|
|
def test_update_device_led_count(device_store):
|
|
"""Test updating device LED count."""
|
|
device = device_store.create_device(
|
|
name="Test WLED",
|
|
url="http://192.168.1.100",
|
|
led_count=150,
|
|
)
|
|
|
|
updated = device_store.update_device(device.id, led_count=200)
|
|
|
|
assert updated.led_count == 200
|
|
|
|
|
|
def test_update_device_not_found(device_store):
|
|
"""Test updating non-existent device."""
|
|
with pytest.raises(ValueError, match="not found"):
|
|
device_store.update_device("nonexistent", name="New Name")
|
|
|
|
|
|
def test_delete_device(device_store):
|
|
"""Test deleting a device."""
|
|
device = device_store.create_device(
|
|
name="Test WLED",
|
|
url="http://192.168.1.100",
|
|
led_count=150,
|
|
)
|
|
|
|
device_store.delete_device(device.id)
|
|
|
|
assert device_store.count() == 0
|
|
with pytest.raises(ValueError, match="not found"):
|
|
device_store.get_device(device.id)
|
|
|
|
|
|
def test_delete_device_not_found(device_store):
|
|
"""Test deleting non-existent device."""
|
|
with pytest.raises(ValueError, match="not found"):
|
|
device_store.delete_device("nonexistent")
|
|
|
|
|
|
def test_device_exists(device_store):
|
|
"""Test checking if device exists."""
|
|
device = device_store.create_device(
|
|
name="Test WLED",
|
|
url="http://192.168.1.100",
|
|
led_count=150,
|
|
)
|
|
|
|
assert device_store.device_exists(device.id) is True
|
|
assert device_store.device_exists("nonexistent") is False
|
|
|
|
|
|
def test_persistence(temp_storage):
|
|
"""Test device persistence across store instances."""
|
|
# Create store and add device
|
|
store1 = DeviceStore(temp_storage)
|
|
device = store1.create_device(
|
|
name="Test WLED",
|
|
url="http://192.168.1.100",
|
|
led_count=150,
|
|
)
|
|
device_id = device.id
|
|
|
|
# Create new store instance (loads from file)
|
|
store2 = DeviceStore(temp_storage)
|
|
|
|
# Verify device persisted
|
|
loaded_device = store2.get_device(device_id)
|
|
assert loaded_device is not None
|
|
assert loaded_device.name == "Test WLED"
|
|
assert loaded_device.led_count == 150
|
|
|
|
|
|
def test_clear(device_store):
|
|
"""Test clearing all devices."""
|
|
device_store.create_device("Device 1", "http://192.168.1.100", 150)
|
|
device_store.create_device("Device 2", "http://192.168.1.101", 200)
|
|
|
|
assert device_store.count() == 2
|
|
|
|
device_store.clear()
|
|
|
|
assert device_store.count() == 0
|
|
|
|
|
|
def test_update_device_ignores_none_values(device_store):
|
|
"""Test that update_device ignores None kwargs."""
|
|
device = device_store.create_device(
|
|
name="Test WLED",
|
|
url="http://192.168.1.100",
|
|
led_count=150,
|
|
)
|
|
|
|
updated = device_store.update_device(device.id, name=None, led_count=200)
|
|
|
|
assert updated.name == "Test WLED" # unchanged
|
|
assert updated.led_count == 200
|
|
|
|
|
|
def test_update_device_ignores_unknown_fields(device_store):
|
|
"""Test that update_device silently ignores unknown kwargs."""
|
|
device = device_store.create_device(
|
|
name="Test WLED",
|
|
url="http://192.168.1.100",
|
|
led_count=150,
|
|
)
|
|
|
|
# Should not raise even with an unknown kwarg
|
|
updated = device_store.update_device(device.id, nonexistent_field="foo")
|
|
assert updated.name == "Test WLED"
|