Files
esphome/tests/integration/test_sensor_raw_state.py
T

109 lines
3.7 KiB
Python

"""Integration tests for Sensor::get_raw_state().
Raw state storage only exists when filters are compiled in (USE_SENSOR_FILTER).
Without it, get_raw_state() returns state, so both build configurations are covered:
one fixture with a filtered sensor and one with no filters at all.
"""
from __future__ import annotations
import asyncio
import re
from aioesphomeapi import APIClient, EntityInfo
import pytest
from .types import APIClientConnectedFactory, RunCompiledFunction
NO_FILTER_PATTERN = re.compile(r"NO_FILTER: state=([\d.]+) raw_state=([\d.]+)")
WITH_FILTER_PATTERN = re.compile(r"WITH_FILTER: state=([\d.]+) raw_state=([\d.]+)")
async def _press_and_read(
client: APIClient,
entities: list[EntityInfo],
button_object_id: str,
future: asyncio.Future[tuple[float, float]],
label: str,
) -> tuple[float, float]:
button = next(
(e for e in entities if button_object_id in e.object_id.lower()), None
)
assert button is not None, f"{button_object_id} not found"
client.button_command(button.key)
try:
return await asyncio.wait_for(future, timeout=5.0)
except TimeoutError:
pytest.fail(f"Timeout waiting for {label} log message")
@pytest.mark.asyncio
async def test_sensor_raw_state(
yaml_config: str,
run_compiled: RunCompiledFunction,
api_client_connected: APIClientConnectedFactory,
) -> None:
"""With filters compiled in, raw state is stored separately from state."""
loop = asyncio.get_running_loop()
no_filter_future: asyncio.Future[tuple[float, float]] = loop.create_future()
with_filter_future: asyncio.Future[tuple[float, float]] = loop.create_future()
def check_output(line: str) -> None:
if not no_filter_future.done() and (match := NO_FILTER_PATTERN.search(line)):
no_filter_future.set_result((float(match.group(1)), float(match.group(2))))
if not with_filter_future.done() and (
match := WITH_FILTER_PATTERN.search(line)
):
with_filter_future.set_result(
(float(match.group(1)), float(match.group(2)))
)
async with (
run_compiled(yaml_config, line_callback=check_output),
api_client_connected() as client,
):
entities, _ = await client.list_entities_services()
state, raw_state = await _press_and_read(
client, entities, "test_no_filter_button", no_filter_future, "NO_FILTER"
)
assert state == 21.5
assert raw_state == 21.5
state, raw_state = await _press_and_read(
client,
entities,
"test_with_filter_button",
with_filter_future,
"WITH_FILTER",
)
assert state == 43.0
assert raw_state == 21.5
@pytest.mark.asyncio
async def test_sensor_raw_state_no_filter(
yaml_config: str,
run_compiled: RunCompiledFunction,
api_client_connected: APIClientConnectedFactory,
) -> None:
"""Without filters compiled in, get_raw_state() returns state."""
loop = asyncio.get_running_loop()
no_filter_future: asyncio.Future[tuple[float, float]] = loop.create_future()
def check_output(line: str) -> None:
if not no_filter_future.done() and (match := NO_FILTER_PATTERN.search(line)):
no_filter_future.set_result((float(match.group(1)), float(match.group(2))))
async with (
run_compiled(yaml_config, line_callback=check_output),
api_client_connected() as client,
):
entities, _ = await client.list_entities_services()
state, raw_state = await _press_and_read(
client, entities, "test_no_filter_button", no_filter_future, "NO_FILTER"
)
assert state == 21.5
assert raw_state == 21.5