mirror of
https://github.com/esphome/esphome.git
synced 2026-08-22 22:26:21 +00:00
80 lines
3.1 KiB
Python
80 lines
3.1 KiB
Python
"""Integration test for Home Assistant actions fired without a subscriber.
|
|
|
|
Home Assistant subscribes to device actions shortly after authenticating, while
|
|
on_client_connected (and similar triggers) fire right at authentication. Actions
|
|
fired before any client has subscribed cannot be delivered - they must produce a
|
|
warning in the log instead of vanishing silently.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import asyncio
|
|
|
|
from aioesphomeapi import ButtonInfo, HomeassistantServiceCall
|
|
import pytest
|
|
|
|
from .types import APIClientConnectedFactory, RunCompiledFunction
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_api_homeassistant_action_no_subscriber(
|
|
yaml_config: str,
|
|
run_compiled: RunCompiledFunction,
|
|
api_client_connected: APIClientConnectedFactory,
|
|
) -> None:
|
|
"""Undeliverable actions warn in the log; actions after subscribing arrive."""
|
|
loop = asyncio.get_running_loop()
|
|
|
|
boot_warning_future = loop.create_future()
|
|
connected_warning_future = loop.create_future()
|
|
button_action_future = loop.create_future()
|
|
|
|
def check_output(line: str) -> None:
|
|
if (
|
|
not boot_warning_future.done()
|
|
and "Home Assistant action 'test.boot_action' dropped; no client connected"
|
|
in line
|
|
):
|
|
boot_warning_future.set_result(True)
|
|
if (
|
|
not connected_warning_future.done()
|
|
and "Home Assistant action 'test.connected_action' dropped; "
|
|
"client has not subscribed to actions (yet)"
|
|
in line
|
|
):
|
|
connected_warning_future.set_result(True)
|
|
|
|
service_calls: list[HomeassistantServiceCall] = []
|
|
|
|
def on_service_call(service_call: HomeassistantServiceCall) -> None:
|
|
service_calls.append(service_call)
|
|
if (
|
|
service_call.service == "test.button_action"
|
|
and not button_action_future.done()
|
|
):
|
|
button_action_future.set_result(service_call)
|
|
|
|
async with run_compiled(yaml_config, line_callback=check_output):
|
|
# The on_boot action fires with no client connected at all.
|
|
await asyncio.wait_for(boot_warning_future, timeout=10.0)
|
|
|
|
async with api_client_connected() as client:
|
|
device_info = await client.device_info()
|
|
assert device_info.name == "test-ha-action-no-subscriber"
|
|
|
|
# on_client_connected fired at authentication, before this client
|
|
# subscribed to Home Assistant actions.
|
|
await asyncio.wait_for(connected_warning_future, timeout=5.0)
|
|
|
|
# After subscribing, actions must be delivered normally (and the
|
|
# dropped ones must not suddenly show up).
|
|
client.subscribe_service_calls(on_service_call)
|
|
|
|
entities, _ = await client.list_entities_services()
|
|
button = next(e for e in entities if isinstance(e, ButtonInfo))
|
|
client.button_command(button.key)
|
|
|
|
button_call = await asyncio.wait_for(button_action_future, timeout=5.0)
|
|
assert button_call.data == {"value": "subscribed"}
|
|
assert [call.service for call in service_calls] == ["test.button_action"]
|