Files
houseplan-card/tests_backend/test_virtual_lights.py
T
2026-08-14 03:32:53 +03:00

72 lines
2.4 KiB
Python

"""Pure operational-store rules independent of the HA WebSocket harness."""
import pytest
from custom_components.houseplan.virtual_lights import (
async_reconcile_virtual_lights,
async_toggle_virtual_light,
async_virtual_light_snapshot,
eligible_virtual_light_ids,
)
class FakeStore:
def __init__(self, data=None):
self.data = data
self.writes = []
async def async_load(self):
return self.data
async def async_save(self, data):
self.data = data
self.writes.append(data)
def _config(*markers):
return {"spaces": [], "markers": list(markers), "settings": {}}
def _manual(marker_id, **extra):
return {
"id": marker_id, "binding": "virtual", "is_light": True,
"tap_action": "toggle", **extra,
}
def test_eligibility_is_the_exact_triple_and_hidden_is_not_lifecycle():
config = _config(
_manual("eligible", hidden=True),
_manual("wrong-action", tap_action="info"),
_manual("wrong-role", is_light=False),
_manual("removed", removed=True),
{"id": "ha", "binding": "entity:light.lamp", "is_light": True, "tap_action": "toggle"},
)
assert eligible_virtual_light_ids(config) == {"eligible"}
@pytest.mark.asyncio
async def test_revision_gap_fails_safe_on_and_known_transition_preserves_only_eligible():
store = FakeStore({"rev": 5, "config_rev": 2, "off": ["keep", "drop"]})
gap = await async_virtual_light_snapshot(store, _config(_manual("keep")), 4)
assert gap == {"rev": 6, "config_rev": 4, "off": []}
store = FakeStore({"rev": 8, "config_rev": 4, "off": ["keep", "drop"]})
carried = await async_reconcile_virtual_lights(
store,
_config(_manual("keep", hidden=True), _manual("drop", is_light=False)),
5,
previous_config_rev=4,
)
assert carried == {"rev": 9, "config_rev": 5, "off": ["keep"]}
@pytest.mark.asyncio
async def test_toggle_accepts_only_an_id_and_inverts_server_current_state():
store = FakeStore()
config = _config(_manual("lamp"))
first = await async_toggle_virtual_light(store, config, 1, "lamp")
second = await async_toggle_virtual_light(store, config, 1, "lamp")
assert first == {"marker_id": "lamp", "on": False, "rev": 1}
assert second == {"marker_id": "lamp", "on": True, "rev": 2}
assert await async_toggle_virtual_light(store, config, 1, "missing") is None