mirror of
https://github.com/esphome/esphome.git
synced 2026-09-28 15:30:21 +00:00
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
148 lines
6.2 KiB
Python
148 lines
6.2 KiB
Python
"""Integration test verifying light effect restore on/off cycles.
|
|
|
|
Tests that when resume_effect is enabled, the previously active effect
|
|
is restored when the light is turned back on without explicit effect/color
|
|
parameters.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import asyncio
|
|
from typing import Any
|
|
|
|
from aioesphomeapi import ColorMode, EntityState, LightInfo, LightState
|
|
import pytest
|
|
|
|
from .state_utils import InitialStateHelper
|
|
from .types import APIClientConnectedFactory, RunCompiledFunction
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_light_resume_effect(
|
|
yaml_config: str,
|
|
run_compiled: RunCompiledFunction,
|
|
api_client_connected: APIClientConnectedFactory,
|
|
) -> None:
|
|
"""When resume_effect is enabled, effect persists after off/on cycle."""
|
|
async with (
|
|
run_compiled(yaml_config),
|
|
api_client_connected() as client,
|
|
):
|
|
entities, _ = await client.list_entities_services()
|
|
light_resume = next(e for e in entities if e.object_id == "test_light_resume")
|
|
light_no_resume = next(
|
|
e for e in entities if e.object_id == "test_light_no_resume"
|
|
)
|
|
|
|
state_futures: dict[int, asyncio.Future[LightState]] = {}
|
|
|
|
def on_state(state: EntityState) -> None:
|
|
if isinstance(state, LightState) and state.key in state_futures:
|
|
future = state_futures[state.key]
|
|
if not future.done():
|
|
future.set_result(state)
|
|
|
|
# Drain initial state burst
|
|
initial_state_helper = InitialStateHelper(entities)
|
|
client.subscribe_states(initial_state_helper.on_state_wrapper(on_state))
|
|
await initial_state_helper.wait_for_initial_states()
|
|
|
|
async def send_and_wait(
|
|
light: LightInfo, timeout: float = 5.0, **kwargs: Any
|
|
) -> LightState:
|
|
"""Send a light command and wait for the matching state response."""
|
|
state_futures[light.key] = asyncio.get_running_loop().create_future()
|
|
client.light_command(key=light.key, **kwargs)
|
|
return await asyncio.wait_for(state_futures[light.key], timeout=timeout)
|
|
|
|
# Test 1: Start with Pulse effect
|
|
state = await send_and_wait(light_resume, state=True, effect="Pulse Effect")
|
|
assert state.state is True
|
|
assert state.effect == "Pulse Effect"
|
|
|
|
# Test 2: Turn off
|
|
state = await send_and_wait(light_resume, state=False)
|
|
assert state.state is False
|
|
|
|
# Test 3: Turn on without specifying effect — should restore Pulse Effect
|
|
state = await send_and_wait(light_resume, state=True)
|
|
assert state.state is True
|
|
assert state.effect == "Pulse Effect", (
|
|
"Effect should be restored when turning on without explicit effect parameter"
|
|
)
|
|
|
|
# Test 4: Switch to Strobe effect
|
|
state = await send_and_wait(light_resume, effect="Strobe Effect")
|
|
assert state.effect == "Strobe Effect"
|
|
|
|
# Test 5: Turn off
|
|
state = await send_and_wait(light_resume, state=False)
|
|
assert state.state is False
|
|
|
|
# Test 6: Turn on without effect — should restore Strobe Effect
|
|
state = await send_and_wait(light_resume, state=True)
|
|
assert state.state is True
|
|
assert state.effect == "Strobe Effect", (
|
|
"Effect should be restored to Strobe after turning on"
|
|
)
|
|
|
|
# Test 7: Explicitly set effect to None while turning on — should not restore
|
|
state = await send_and_wait(light_resume, state=False)
|
|
assert state.state is False
|
|
|
|
state = await send_and_wait(light_resume, state=True, effect="None")
|
|
assert state.state is True
|
|
assert state.effect == "None", (
|
|
"Explicit effect=None should override restoration"
|
|
)
|
|
|
|
# Test 8: Turn off, then on with explicit effect — should use explicit effect
|
|
state = await send_and_wait(light_resume, state=False)
|
|
state = await send_and_wait(light_resume, state=True, effect="Pulse Effect")
|
|
assert state.effect == "Pulse Effect"
|
|
|
|
# Test 9: a turn-on that asks for something specific does not restore, and the
|
|
# effect it replaced must not come back on a later plain off/on
|
|
state = await send_and_wait(light_resume, state=False)
|
|
assert state.state is False
|
|
state = await send_and_wait(light_resume, state=True, brightness=0.5)
|
|
assert state.effect == "None", "A turn-on with brightness should not restore"
|
|
state = await send_and_wait(light_resume, state=False)
|
|
state = await send_and_wait(light_resume, state=True)
|
|
assert state.effect == "None", (
|
|
"An effect dropped on an earlier cycle must not return"
|
|
)
|
|
|
|
# Test 10: a plain turn-on sent to a light that is already on never starts the
|
|
# remembered effect
|
|
state = await send_and_wait(light_resume, state=True, effect="Pulse Effect")
|
|
state = await send_and_wait(light_resume, state=False)
|
|
state = await send_and_wait(light_resume, state=True, brightness=0.5)
|
|
assert state.effect == "None"
|
|
state = await send_and_wait(light_resume, state=True)
|
|
assert state.effect == "None", (
|
|
"A lit light must not pick up the remembered effect"
|
|
)
|
|
|
|
# Test 11: a turn-on that names a color mode is not plain, so it does not restore
|
|
state = await send_and_wait(light_resume, state=True, effect="Pulse Effect")
|
|
state = await send_and_wait(light_resume, state=False)
|
|
state = await send_and_wait(
|
|
light_resume, state=True, color_mode=ColorMode.BRIGHTNESS
|
|
)
|
|
assert state.effect == "None", "A turn-on with a color mode should not restore"
|
|
|
|
# Test 12: Turn on effect, then off, then on without effect — should not restore Pulse Effect
|
|
state = await send_and_wait(light_no_resume, state=True, effect="Pulse Effect")
|
|
assert state.state is True
|
|
assert state.effect == "Pulse Effect"
|
|
|
|
state = await send_and_wait(light_no_resume, state=False)
|
|
assert state.state is False
|
|
|
|
state = await send_and_wait(light_no_resume, state=True)
|
|
assert state.state is True
|
|
assert state.effect == "None", (
|
|
"Effect should NOT be restored when resume_effect=false"
|
|
)
|