Prepare MQTT platform tests part7 (#90130)

* Tests select

* Tests sensor

* Deduplicate test code
pull/90219/head
Jan Bouwhuis 2023-03-24 08:42:00 +01:00 committed by GitHub
parent 0570405a3c
commit f2b4c95a04
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 521 additions and 435 deletions

View File

@ -1,4 +1,5 @@
"""The tests for mqtt select component."""
from collections.abc import Generator
import copy
import json
from typing import Any
@ -21,7 +22,7 @@ from homeassistant.const import (
Platform,
)
from homeassistant.core import HomeAssistant, State
from homeassistant.setup import async_setup_component
from homeassistant.helpers.typing import ConfigType
from .test_common import (
help_test_availability_when_connection_lost,
@ -74,27 +75,35 @@ def select_platform_only():
yield
async def test_run_select_setup(
hass: HomeAssistant, mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator
) -> None:
"""Test that it fetches the given payload."""
topic = "test/select"
await async_setup_component(
hass,
mqtt.DOMAIN,
def _test_run_select_setup_params(
topic: str,
) -> Generator[tuple[ConfigType, str], None]:
yield (
{
mqtt.DOMAIN: {
select.DOMAIN: {
"state_topic": topic,
"command_topic": topic,
"command_topic": "test/select_cmd",
"name": "Test Select",
"options": ["milk", "beer"],
}
}
},
topic,
)
await hass.async_block_till_done()
await mqtt_mock_entry_with_yaml_config()
@pytest.mark.parametrize(
("hass_config", "topic"),
_test_run_select_setup_params("test/select_stat"),
)
async def test_run_select_setup(
hass: HomeAssistant,
mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator,
topic: str,
) -> None:
"""Test that it fetches the given payload."""
await mqtt_mock_entry_no_yaml_config()
async_fire_mqtt_message(hass, topic, "milk")
@ -111,44 +120,43 @@ async def test_run_select_setup(
assert state.state == "beer"
async def test_value_template(
hass: HomeAssistant, mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator
) -> None:
"""Test that it fetches the given payload with a template."""
topic = "test/select"
await async_setup_component(
hass,
mqtt.DOMAIN,
@pytest.mark.parametrize(
"hass_config",
[
{
mqtt.DOMAIN: {
select.DOMAIN: {
"state_topic": topic,
"command_topic": topic,
"state_topic": "test/select_stat",
"command_topic": "test/select_cmd",
"name": "Test Select",
"options": ["milk", "beer"],
"value_template": "{{ value_json.val }}",
}
}
},
)
await hass.async_block_till_done()
await mqtt_mock_entry_with_yaml_config()
}
],
)
async def test_value_template(
hass: HomeAssistant, mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator
) -> None:
"""Test that it fetches the given payload with a template."""
await mqtt_mock_entry_no_yaml_config()
async_fire_mqtt_message(hass, topic, '{"val":"milk"}')
async_fire_mqtt_message(hass, "test/select_stat", '{"val":"milk"}')
await hass.async_block_till_done()
state = hass.states.get("select.test_select")
assert state.state == "milk"
async_fire_mqtt_message(hass, topic, '{"val":"beer"}')
async_fire_mqtt_message(hass, "test/select_stat", '{"val":"beer"}')
await hass.async_block_till_done()
state = hass.states.get("select.test_select")
assert state.state == "beer"
async_fire_mqtt_message(hass, topic, '{"val": null}')
async_fire_mqtt_message(hass, "test/select_stat", '{"val": null}')
await hass.async_block_till_done()
@ -156,30 +164,28 @@ async def test_value_template(
assert state.state == STATE_UNKNOWN
async def test_run_select_service_optimistic(
hass: HomeAssistant, mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator
) -> None:
"""Test that set_value service works in optimistic mode."""
topic = "test/select"
fake_state = State("select.test_select", "milk")
mock_restore_cache(hass, (fake_state,))
assert await async_setup_component(
hass,
mqtt.DOMAIN,
@pytest.mark.parametrize(
"hass_config",
[
{
mqtt.DOMAIN: {
select.DOMAIN: {
"command_topic": topic,
"command_topic": "test/select_cmd",
"name": "Test Select",
"options": ["milk", "beer"],
}
}
},
)
await hass.async_block_till_done()
mqtt_mock = await mqtt_mock_entry_with_yaml_config()
}
],
)
async def test_run_select_service_optimistic(
hass: HomeAssistant, mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator
) -> None:
"""Test that set_value service works in optimistic mode."""
fake_state = State("select.test_select", "milk")
mock_restore_cache(hass, (fake_state,))
mqtt_mock = await mqtt_mock_entry_no_yaml_config()
state = hass.states.get("select.test_select")
assert state.state == "milk"
@ -192,37 +198,35 @@ async def test_run_select_service_optimistic(
blocking=True,
)
mqtt_mock.async_publish.assert_called_once_with(topic, "beer", 0, False)
mqtt_mock.async_publish.assert_called_once_with("test/select_cmd", "beer", 0, False)
mqtt_mock.async_publish.reset_mock()
state = hass.states.get("select.test_select")
assert state.state == "beer"
async def test_run_select_service_optimistic_with_command_template(
hass: HomeAssistant, mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator
) -> None:
"""Test that set_value service works in optimistic mode and with a command_template."""
topic = "test/select"
fake_state = State("select.test_select", "milk")
mock_restore_cache(hass, (fake_state,))
assert await async_setup_component(
hass,
mqtt.DOMAIN,
@pytest.mark.parametrize(
"hass_config",
[
{
mqtt.DOMAIN: {
select.DOMAIN: {
"command_topic": topic,
"command_topic": "test/select_cmd",
"name": "Test Select",
"options": ["milk", "beer"],
"command_template": '{"option": "{{ value }}"}',
}
}
},
)
await hass.async_block_till_done()
mqtt_mock = await mqtt_mock_entry_with_yaml_config()
}
],
)
async def test_run_select_service_optimistic_with_command_template(
hass: HomeAssistant, mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator
) -> None:
"""Test that set_value service works in optimistic mode and with a command_template."""
fake_state = State("select.test_select", "milk")
mock_restore_cache(hass, (fake_state,))
mqtt_mock = await mqtt_mock_entry_no_yaml_config()
state = hass.states.get("select.test_select")
assert state.state == "milk"
@ -236,36 +240,36 @@ async def test_run_select_service_optimistic_with_command_template(
)
mqtt_mock.async_publish.assert_called_once_with(
topic, '{"option": "beer"}', 0, False
"test/select_cmd", '{"option": "beer"}', 0, False
)
mqtt_mock.async_publish.reset_mock()
state = hass.states.get("select.test_select")
assert state.state == "beer"
@pytest.mark.parametrize(
"hass_config",
[
{
mqtt.DOMAIN: {
select.DOMAIN: {
"command_topic": "test/select/set",
"state_topic": "test/select",
"name": "Test Select",
"options": ["milk", "beer"],
}
}
}
],
)
async def test_run_select_service(
hass: HomeAssistant, mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator
hass: HomeAssistant, mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator
) -> None:
"""Test that set_value service works in non optimistic mode."""
cmd_topic = "test/select/set"
state_topic = "test/select"
assert await async_setup_component(
hass,
mqtt.DOMAIN,
{
mqtt.DOMAIN: {
select.DOMAIN: {
"command_topic": cmd_topic,
"state_topic": state_topic,
"name": "Test Select",
"options": ["milk", "beer"],
}
}
},
)
await hass.async_block_till_done()
mqtt_mock = await mqtt_mock_entry_with_yaml_config()
mqtt_mock = await mqtt_mock_entry_no_yaml_config()
async_fire_mqtt_message(hass, state_topic, "beer")
state = hass.states.get("select.test_select")
@ -282,30 +286,30 @@ async def test_run_select_service(
assert state.state == "beer"
async def test_run_select_service_with_command_template(
hass: HomeAssistant, mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator
) -> None:
"""Test that set_value service works in non optimistic mode and with a command_template."""
cmd_topic = "test/select/set"
state_topic = "test/select"
assert await async_setup_component(
hass,
mqtt.DOMAIN,
@pytest.mark.parametrize(
"hass_config",
[
{
mqtt.DOMAIN: {
select.DOMAIN: {
"command_topic": cmd_topic,
"state_topic": state_topic,
"command_topic": "test/select/set",
"state_topic": "test/select",
"name": "Test Select",
"options": ["milk", "beer"],
"command_template": '{"option": "{{ value }}"}',
}
}
},
)
await hass.async_block_till_done()
mqtt_mock = await mqtt_mock_entry_with_yaml_config()
}
],
)
async def test_run_select_service_with_command_template(
hass: HomeAssistant, mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator
) -> None:
"""Test that set_value service works in non optimistic mode and with a command_template."""
cmd_topic = "test/select/set"
state_topic = "test/select"
mqtt_mock = await mqtt_mock_entry_no_yaml_config()
async_fire_mqtt_message(hass, state_topic, "beer")
state = hass.states.get("select.test_select")
@ -609,60 +613,65 @@ async def test_entity_debug_info_message(
)
@pytest.mark.parametrize("options", [["milk", "beer"], ["milk"], []])
def _test_options_attributes_options_config(
request: tuple[list[str]],
) -> Generator[tuple[ConfigType, list[str]], None]:
for option in request:
yield (
{
mqtt.DOMAIN: {
select.DOMAIN: {
"command_topic": "test/select/set",
"state_topic": "test/select",
"name": "Test select",
"options": option,
}
}
},
option,
)
@pytest.mark.parametrize(
("hass_config", "options"),
_test_options_attributes_options_config((["milk", "beer"], ["milk"], [])),
)
async def test_options_attributes(
hass: HomeAssistant,
mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator,
options,
mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator,
options: list[str],
) -> None:
"""Test options attribute."""
topic = "test/select"
await async_setup_component(
hass,
mqtt.DOMAIN,
{
mqtt.DOMAIN: {
select.DOMAIN: {
"state_topic": topic,
"command_topic": topic,
"name": "Test select",
"options": options,
}
}
},
)
await hass.async_block_till_done()
await mqtt_mock_entry_with_yaml_config()
await mqtt_mock_entry_no_yaml_config()
state = hass.states.get("select.test_select")
assert state.attributes.get(ATTR_OPTIONS) == options
async def test_mqtt_payload_not_an_option_warning(
hass: HomeAssistant,
caplog: pytest.LogCaptureFixture,
mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator,
) -> None:
"""Test warning for MQTT payload which is not a valid option."""
topic = "test/select"
await async_setup_component(
hass,
mqtt.DOMAIN,
@pytest.mark.parametrize(
"hass_config",
[
{
mqtt.DOMAIN: {
select.DOMAIN: {
"state_topic": topic,
"command_topic": topic,
"state_topic": "test/select_stat",
"command_topic": "test/select_cmd",
"name": "Test Select",
"options": ["milk", "beer"],
}
}
},
)
await hass.async_block_till_done()
await mqtt_mock_entry_with_yaml_config()
}
],
)
async def test_mqtt_payload_not_an_option_warning(
hass: HomeAssistant,
caplog: pytest.LogCaptureFixture,
mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator,
) -> None:
"""Test warning for MQTT payload which is not a valid option."""
await mqtt_mock_entry_no_yaml_config()
async_fire_mqtt_message(hass, topic, "öl")
async_fire_mqtt_message(hass, "test/select_stat", "öl")
await hass.async_block_till_done()

View File

@ -18,12 +18,13 @@ from homeassistant.const import (
Platform,
UnitOfTemperature,
)
from homeassistant.core import HomeAssistant, State, callback
from homeassistant.core import Event, HomeAssistant, State, callback
from homeassistant.helpers import device_registry as dr
from homeassistant.setup import async_setup_component
from homeassistant.helpers.typing import ConfigType
import homeassistant.util.dt as dt_util
from .test_common import (
help_custom_config,
help_test_availability_when_connection_lost,
help_test_availability_without_topic,
help_test_custom_availability_payload,
@ -82,13 +83,9 @@ def sensor_platform_only():
yield
async def test_setting_sensor_value_via_mqtt_message(
hass: HomeAssistant, mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator
) -> None:
"""Test the setting of the value via MQTT."""
assert await async_setup_component(
hass,
mqtt.DOMAIN,
@pytest.mark.parametrize(
"hass_config",
[
{
mqtt.DOMAIN: {
sensor.DOMAIN: {
@ -98,10 +95,14 @@ async def test_setting_sensor_value_via_mqtt_message(
"suggested_display_precision": 1,
}
}
},
)
await hass.async_block_till_done()
await mqtt_mock_entry_with_yaml_config()
}
],
)
async def test_setting_sensor_value_via_mqtt_message(
hass: HomeAssistant, mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator
) -> None:
"""Test the setting of the value via MQTT."""
await mqtt_mock_entry_no_yaml_config()
async_fire_mqtt_message(hass, "test-topic", "100.22")
state = hass.states.get("sensor.test")
@ -113,64 +114,118 @@ async def test_setting_sensor_value_via_mqtt_message(
@pytest.mark.parametrize(
("device_class", "native_value", "state_value", "log"),
("hass_config", "device_class", "native_value", "state_value", "log"),
[
(sensor.SensorDeviceClass.DATE, "2021-11-18", "2021-11-18", False),
(sensor.SensorDeviceClass.DATE, "invalid", STATE_UNKNOWN, True),
(
help_custom_config(
sensor.DOMAIN,
DEFAULT_CONFIG,
({"device_class": sensor.SensorDeviceClass.DATE},),
),
sensor.SensorDeviceClass.DATE,
"2021-11-18",
"2021-11-18",
False,
),
(
help_custom_config(
sensor.DOMAIN,
DEFAULT_CONFIG,
({"device_class": sensor.SensorDeviceClass.DATE},),
),
sensor.SensorDeviceClass.DATE,
"invalid",
STATE_UNKNOWN,
True,
),
(
help_custom_config(
sensor.DOMAIN,
DEFAULT_CONFIG,
({"device_class": sensor.SensorDeviceClass.TIMESTAMP},),
),
sensor.SensorDeviceClass.TIMESTAMP,
"2021-11-18T20:25:00+00:00",
"2021-11-18T20:25:00+00:00",
False,
),
(
help_custom_config(
sensor.DOMAIN,
DEFAULT_CONFIG,
({"device_class": sensor.SensorDeviceClass.TIMESTAMP},),
),
sensor.SensorDeviceClass.TIMESTAMP,
"2021-11-18 20:25:00+00:00",
"2021-11-18T20:25:00+00:00",
False,
),
(
help_custom_config(
sensor.DOMAIN,
DEFAULT_CONFIG,
({"device_class": sensor.SensorDeviceClass.TIMESTAMP},),
),
sensor.SensorDeviceClass.TIMESTAMP,
"2021-11-18 20:25:00+01:00",
"2021-11-18T19:25:00+00:00",
False,
),
(
help_custom_config(
sensor.DOMAIN,
DEFAULT_CONFIG,
({"device_class": sensor.SensorDeviceClass.TIMESTAMP},),
),
sensor.SensorDeviceClass.TIMESTAMP,
"2021-13-18T35:25:00+00:00",
STATE_UNKNOWN,
True,
),
(sensor.SensorDeviceClass.TIMESTAMP, "invalid", STATE_UNKNOWN, True),
(sensor.SensorDeviceClass.ENUM, "some_value", "some_value", False),
(None, "some_value", "some_value", False),
(
help_custom_config(
sensor.DOMAIN,
DEFAULT_CONFIG,
({"device_class": sensor.SensorDeviceClass.TIMESTAMP},),
),
sensor.SensorDeviceClass.TIMESTAMP,
"invalid",
STATE_UNKNOWN,
True,
),
(
help_custom_config(
sensor.DOMAIN,
DEFAULT_CONFIG,
({"device_class": sensor.SensorDeviceClass.ENUM},),
),
sensor.SensorDeviceClass.ENUM,
"some_value",
"some_value",
False,
),
(
help_custom_config(
sensor.DOMAIN, DEFAULT_CONFIG, ({"device_class": None},)
),
None,
"some_value",
"some_value",
False,
),
],
)
async def test_setting_sensor_native_value_handling_via_mqtt_message(
hass: HomeAssistant,
mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator,
mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator,
caplog: pytest.LogCaptureFixture,
device_class,
native_value,
state_value,
log,
device_class: sensor.SensorDeviceClass | None,
native_value: str,
state_value: str,
log: bool,
) -> None:
"""Test the setting of the value via MQTT."""
assert await async_setup_component(
hass,
mqtt.DOMAIN,
{
mqtt.DOMAIN: {
sensor.DOMAIN: {
"name": "test",
"state_topic": "test-topic",
"device_class": device_class,
}
}
},
)
await hass.async_block_till_done()
await mqtt_mock_entry_with_yaml_config()
await mqtt_mock_entry_no_yaml_config()
async_fire_mqtt_message(hass, "test-topic", native_value)
state = hass.states.get("sensor.test")
@ -180,14 +235,9 @@ async def test_setting_sensor_native_value_handling_via_mqtt_message(
assert log == ("Invalid state message" in caplog.text)
async def test_setting_numeric_sensor_native_value_handling_via_mqtt_message(
hass: HomeAssistant,
mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator,
) -> None:
"""Test the setting of a numeric sensor value via MQTT."""
assert await async_setup_component(
hass,
mqtt.DOMAIN,
@pytest.mark.parametrize(
"hass_config",
[
{
mqtt.DOMAIN: {
sensor.DOMAIN: {
@ -198,10 +248,16 @@ async def test_setting_numeric_sensor_native_value_handling_via_mqtt_message(
"unit_of_measurement": "W",
}
}
},
)
}
],
)
async def test_setting_numeric_sensor_native_value_handling_via_mqtt_message(
hass: HomeAssistant,
mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator,
) -> None:
"""Test the setting of a numeric sensor value via MQTT."""
await hass.async_block_till_done()
await mqtt_mock_entry_with_yaml_config()
await mqtt_mock_entry_no_yaml_config()
# float value
async_fire_mqtt_message(hass, "test-topic", '{ "power": 45.3, "current": 5.24 }')
@ -235,15 +291,9 @@ async def test_setting_numeric_sensor_native_value_handling_via_mqtt_message(
assert state.state == "21"
async def test_setting_sensor_value_expires_availability_topic(
hass: HomeAssistant,
mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator,
caplog: pytest.LogCaptureFixture,
) -> None:
"""Test the expiration of the value."""
assert await async_setup_component(
hass,
mqtt.DOMAIN,
@pytest.mark.parametrize(
"hass_config",
[
{
mqtt.DOMAIN: {
sensor.DOMAIN: {
@ -254,10 +304,14 @@ async def test_setting_sensor_value_expires_availability_topic(
"availability_topic": "availability-topic",
}
}
},
)
await hass.async_block_till_done()
await mqtt_mock_entry_with_yaml_config()
}
],
)
async def test_setting_sensor_value_expires_availability_topic(
hass: HomeAssistant, mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator
) -> None:
"""Test the expiration of the value."""
await mqtt_mock_entry_no_yaml_config()
state = hass.states.get("sensor.test")
assert state.state == STATE_UNAVAILABLE
@ -268,18 +322,12 @@ async def test_setting_sensor_value_expires_availability_topic(
state = hass.states.get("sensor.test")
assert state.state == STATE_UNAVAILABLE
await expires_helper(hass, caplog)
await expires_helper(hass)
async def test_setting_sensor_value_expires(
hass: HomeAssistant,
mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator,
caplog: pytest.LogCaptureFixture,
) -> None:
"""Test the expiration of the value."""
assert await async_setup_component(
hass,
mqtt.DOMAIN,
@pytest.mark.parametrize(
"hass_config",
[
{
mqtt.DOMAIN: {
sensor.DOMAIN: {
@ -290,19 +338,23 @@ async def test_setting_sensor_value_expires(
"force_update": True,
}
}
},
)
await hass.async_block_till_done()
await mqtt_mock_entry_with_yaml_config()
}
],
)
async def test_setting_sensor_value_expires(
hass: HomeAssistant, mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator
) -> None:
"""Test the expiration of the value."""
await mqtt_mock_entry_no_yaml_config()
# State should be unavailable since expire_after is defined and > 0
state = hass.states.get("sensor.test")
assert state.state == STATE_UNAVAILABLE
await expires_helper(hass, caplog)
await expires_helper(hass)
async def expires_helper(hass: HomeAssistant, caplog) -> None:
async def expires_helper(hass: HomeAssistant) -> None:
"""Run the basic expiry code."""
realnow = dt_util.utcnow()
now = datetime(realnow.year + 1, 1, 1, 1, tzinfo=dt_util.UTC)
@ -353,13 +405,9 @@ async def expires_helper(hass: HomeAssistant, caplog) -> None:
assert state.state == STATE_UNAVAILABLE
async def test_setting_sensor_value_via_mqtt_json_message(
hass: HomeAssistant, mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator
) -> None:
"""Test the setting of the value via MQTT with JSON payload."""
assert await async_setup_component(
hass,
mqtt.DOMAIN,
@pytest.mark.parametrize(
"hass_config",
[
{
mqtt.DOMAIN: {
sensor.DOMAIN: {
@ -368,10 +416,14 @@ async def test_setting_sensor_value_via_mqtt_json_message(
"value_template": "{{ value_json.val }}",
}
}
},
)
await hass.async_block_till_done()
await mqtt_mock_entry_with_yaml_config()
}
],
)
async def test_setting_sensor_value_via_mqtt_json_message(
hass: HomeAssistant, mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator
) -> None:
"""Test the setting of the value via MQTT with JSON payload."""
await mqtt_mock_entry_no_yaml_config()
async_fire_mqtt_message(hass, "test-topic", '{ "val": "100" }')
state = hass.states.get("sensor.test")
@ -385,13 +437,9 @@ async def test_setting_sensor_value_via_mqtt_json_message(
assert state.state == ""
async def test_setting_sensor_value_via_mqtt_json_message_and_default_current_state(
hass: HomeAssistant, mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator
) -> None:
"""Test the setting of the value via MQTT with fall back to current state."""
assert await async_setup_component(
hass,
mqtt.DOMAIN,
@pytest.mark.parametrize(
"hass_config",
[
{
mqtt.DOMAIN: {
sensor.DOMAIN: {
@ -400,10 +448,14 @@ async def test_setting_sensor_value_via_mqtt_json_message_and_default_current_st
"value_template": "{{ value_json.val | is_defined }}-{{ value_json.par }}",
}
}
},
)
await hass.async_block_till_done()
await mqtt_mock_entry_with_yaml_config()
}
],
)
async def test_setting_sensor_value_via_mqtt_json_message_and_default_current_state(
hass: HomeAssistant, mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator
) -> None:
"""Test the setting of the value via MQTT with fall back to current state."""
await mqtt_mock_entry_no_yaml_config()
async_fire_mqtt_message(
hass, "test-topic", '{ "val": "valcontent", "par": "parcontent" }'
@ -418,15 +470,9 @@ async def test_setting_sensor_value_via_mqtt_json_message_and_default_current_st
assert state.state == "valcontent-parcontent"
async def test_setting_sensor_last_reset_via_mqtt_message(
hass: HomeAssistant,
mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator,
caplog: pytest.LogCaptureFixture,
) -> None:
"""Test the setting of the last_reset property via MQTT."""
assert await async_setup_component(
hass,
mqtt.DOMAIN,
@pytest.mark.parametrize(
"hass_config",
[
{
mqtt.DOMAIN: {
sensor.DOMAIN: {
@ -437,10 +483,16 @@ async def test_setting_sensor_last_reset_via_mqtt_message(
"last_reset_topic": "last-reset-topic",
}
}
},
)
await hass.async_block_till_done()
await mqtt_mock_entry_with_yaml_config()
}
],
)
async def test_setting_sensor_last_reset_via_mqtt_message(
hass: HomeAssistant,
mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator,
caplog: pytest.LogCaptureFixture,
) -> None:
"""Test the setting of the last_reset property via MQTT."""
await mqtt_mock_entry_no_yaml_config()
async_fire_mqtt_message(hass, "last-reset-topic", "2020-01-02 08:11:00")
state = hass.states.get("sensor.test")
@ -452,17 +504,9 @@ async def test_setting_sensor_last_reset_via_mqtt_message(
)
@pytest.mark.parametrize("datestring", ["2020-21-02 08:11:00", "Hello there!"])
async def test_setting_sensor_bad_last_reset_via_mqtt_message(
hass: HomeAssistant,
caplog: pytest.LogCaptureFixture,
datestring,
mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator,
) -> None:
"""Test the setting of the last_reset property via MQTT."""
assert await async_setup_component(
hass,
mqtt.DOMAIN,
@pytest.mark.parametrize(
"hass_config",
[
{
mqtt.DOMAIN: {
sensor.DOMAIN: {
@ -473,10 +517,18 @@ async def test_setting_sensor_bad_last_reset_via_mqtt_message(
"last_reset_topic": "last-reset-topic",
}
}
},
)
await hass.async_block_till_done()
await mqtt_mock_entry_with_yaml_config()
}
],
)
@pytest.mark.parametrize("datestring", ["2020-21-02 08:11:00", "Hello there!"])
async def test_setting_sensor_bad_last_reset_via_mqtt_message(
hass: HomeAssistant,
caplog: pytest.LogCaptureFixture,
datestring,
mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator,
) -> None:
"""Test the setting of the last_reset property via MQTT."""
await mqtt_mock_entry_no_yaml_config()
async_fire_mqtt_message(hass, "last-reset-topic", datestring)
state = hass.states.get("sensor.test")
@ -484,13 +536,9 @@ async def test_setting_sensor_bad_last_reset_via_mqtt_message(
assert "Invalid last_reset message" in caplog.text
async def test_setting_sensor_empty_last_reset_via_mqtt_message(
hass: HomeAssistant, mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator
) -> None:
"""Test the setting of the last_reset property via MQTT."""
assert await async_setup_component(
hass,
mqtt.DOMAIN,
@pytest.mark.parametrize(
"hass_config",
[
{
mqtt.DOMAIN: {
sensor.DOMAIN: {
@ -501,23 +549,23 @@ async def test_setting_sensor_empty_last_reset_via_mqtt_message(
"last_reset_topic": "last-reset-topic",
}
}
},
)
await hass.async_block_till_done()
await mqtt_mock_entry_with_yaml_config()
}
],
)
async def test_setting_sensor_empty_last_reset_via_mqtt_message(
hass: HomeAssistant, mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator
) -> None:
"""Test the setting of the last_reset property via MQTT."""
await mqtt_mock_entry_no_yaml_config()
async_fire_mqtt_message(hass, "last-reset-topic", "")
state = hass.states.get("sensor.test")
assert state.attributes.get("last_reset") is None
async def test_setting_sensor_last_reset_via_mqtt_json_message(
hass: HomeAssistant, mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator
) -> None:
"""Test the setting of the value via MQTT with JSON payload."""
assert await async_setup_component(
hass,
mqtt.DOMAIN,
@pytest.mark.parametrize(
"hass_config",
[
{
mqtt.DOMAIN: {
sensor.DOMAIN: {
@ -529,10 +577,14 @@ async def test_setting_sensor_last_reset_via_mqtt_json_message(
"last_reset_value_template": "{{ value_json.last_reset }}",
}
}
},
)
await hass.async_block_till_done()
await mqtt_mock_entry_with_yaml_config()
}
],
)
async def test_setting_sensor_last_reset_via_mqtt_json_message(
hass: HomeAssistant, mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator
) -> None:
"""Test the setting of the value via MQTT with JSON payload."""
await mqtt_mock_entry_no_yaml_config()
async_fire_mqtt_message(
hass, "last-reset-topic", '{ "last_reset": "2020-01-02 08:11:00" }'
@ -541,35 +593,44 @@ async def test_setting_sensor_last_reset_via_mqtt_json_message(
assert state.attributes.get("last_reset") == "2020-01-02T08:11:00"
@pytest.mark.parametrize("extra", [{}, {"last_reset_topic": "test-topic"}])
async def test_setting_sensor_last_reset_via_mqtt_json_message_2(
hass: HomeAssistant,
mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator,
caplog: pytest.LogCaptureFixture,
extra,
) -> None:
"""Test the setting of the value via MQTT with JSON payload."""
assert await async_setup_component(
hass,
mqtt.DOMAIN,
@pytest.mark.parametrize(
"hass_config",
[
{
mqtt.DOMAIN: {
sensor.DOMAIN: {
**{
"name": "test",
"state_class": "total",
"state_topic": "test-topic",
"unit_of_measurement": "kWh",
"value_template": "{{ value_json.value | float / 60000 }}",
"last_reset_value_template": "{{ utcnow().fromtimestamp(value_json.time / 1000, tz=utcnow().tzinfo) }}",
},
**extra,
}
"name": "test",
"state_class": "total",
"state_topic": "test-topic",
"unit_of_measurement": "kWh",
"value_template": "{{ value_json.value | float / 60000 }}",
"last_reset_value_template": "{{ utcnow().fromtimestamp(value_json.time / 1000, tz=utcnow().tzinfo) }}",
},
}
},
)
{
mqtt.DOMAIN: {
sensor.DOMAIN: {
"name": "test",
"state_class": "total",
"state_topic": "test-topic",
"unit_of_measurement": "kWh",
"value_template": "{{ value_json.value | float / 60000 }}",
"last_reset_value_template": "{{ utcnow().fromtimestamp(value_json.time / 1000, tz=utcnow().tzinfo) }}",
"last_reset_topic": "test-topic",
},
}
},
],
)
async def test_setting_sensor_last_reset_via_mqtt_json_message_2(
hass: HomeAssistant,
mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator,
caplog: pytest.LogCaptureFixture,
) -> None:
"""Test the setting of the value via MQTT with JSON payload."""
await hass.async_block_till_done()
await mqtt_mock_entry_with_yaml_config()
await mqtt_mock_entry_no_yaml_config()
async_fire_mqtt_message(
hass,
@ -586,13 +647,9 @@ async def test_setting_sensor_last_reset_via_mqtt_json_message_2(
)
async def test_force_update_disabled(
hass: HomeAssistant, mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator
) -> None:
"""Test force update option."""
assert await async_setup_component(
hass,
mqtt.DOMAIN,
@pytest.mark.parametrize(
"hass_config",
[
{
mqtt.DOMAIN: {
sensor.DOMAIN: {
@ -601,15 +658,19 @@ async def test_force_update_disabled(
"unit_of_measurement": "fav unit",
}
}
},
)
await hass.async_block_till_done()
await mqtt_mock_entry_with_yaml_config()
}
],
)
async def test_force_update_disabled(
hass: HomeAssistant, mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator
) -> None:
"""Test force update option."""
await mqtt_mock_entry_no_yaml_config()
events = []
events: list[Event] = []
@callback
def test_callback(event) -> None:
def test_callback(event: Event) -> None:
events.append(event)
hass.bus.async_listen(EVENT_STATE_CHANGED, test_callback)
@ -623,13 +684,9 @@ async def test_force_update_disabled(
assert len(events) == 1
async def test_force_update_enabled(
hass: HomeAssistant, mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator
) -> None:
"""Test force update option."""
assert await async_setup_component(
hass,
mqtt.DOMAIN,
@pytest.mark.parametrize(
"hass_config",
[
{
mqtt.DOMAIN: {
sensor.DOMAIN: {
@ -639,15 +696,19 @@ async def test_force_update_enabled(
"force_update": True,
}
}
},
)
await hass.async_block_till_done()
await mqtt_mock_entry_with_yaml_config()
}
],
)
async def test_force_update_enabled(
hass: HomeAssistant, mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator
) -> None:
"""Test force update option."""
await mqtt_mock_entry_no_yaml_config()
events = []
events: list[Event] = []
@callback
def test_callback(event) -> None:
def test_callback(event: Event) -> None:
events.append(event)
hass.bus.async_listen(EVENT_STATE_CHANGED, test_callback)
@ -747,13 +808,9 @@ async def test_discovery_update_availability(
)
async def test_invalid_device_class(
hass: HomeAssistant, mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator
) -> None:
"""Test device_class option with invalid value."""
assert await async_setup_component(
hass,
sensor.DOMAIN,
@pytest.mark.parametrize(
"hass_config",
[
{
mqtt.DOMAIN: {
sensor.DOMAIN: {
@ -762,22 +819,25 @@ async def test_invalid_device_class(
"device_class": "foobarnotreal",
}
}
},
)
await hass.async_block_till_done()
await mqtt_mock_entry_no_yaml_config()
state = hass.states.get("sensor.test")
assert state is None
async def test_valid_device_class(
hass: HomeAssistant, mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator
}
],
)
async def test_invalid_device_class(
hass: HomeAssistant,
mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator,
caplog: pytest.LogCaptureFixture,
) -> None:
"""Test device_class option with valid values."""
assert await async_setup_component(
hass,
mqtt.DOMAIN,
"""Test device_class option with invalid value."""
with pytest.raises(AssertionError):
await mqtt_mock_entry_no_yaml_config()
assert (
"Invalid config for [mqtt]: expected SensorDeviceClass or one of" in caplog.text
)
@pytest.mark.parametrize(
"hass_config",
[
{
mqtt.DOMAIN: {
sensor.DOMAIN: [
@ -794,10 +854,14 @@ async def test_valid_device_class(
},
]
}
},
)
await hass.async_block_till_done()
await mqtt_mock_entry_with_yaml_config()
}
],
)
async def test_valid_device_class(
hass: HomeAssistant, mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator
) -> None:
"""Test device_class option with valid values."""
await mqtt_mock_entry_no_yaml_config()
state = hass.states.get("sensor.test_1")
assert state.attributes["device_class"] == "temperature"
@ -807,13 +871,9 @@ async def test_valid_device_class(
assert "device_class" not in state.attributes
async def test_invalid_state_class(
hass: HomeAssistant, mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator
) -> None:
"""Test state_class option with invalid value."""
assert await async_setup_component(
hass,
sensor.DOMAIN,
@pytest.mark.parametrize(
"hass_config",
[
{
mqtt.DOMAIN: {
sensor.DOMAIN: {
@ -822,22 +882,25 @@ async def test_invalid_state_class(
"state_class": "foobarnotreal",
}
}
},
)
await hass.async_block_till_done()
await mqtt_mock_entry_no_yaml_config()
state = hass.states.get("sensor.test")
assert state is None
async def test_valid_state_class(
hass: HomeAssistant, mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator
}
],
)
async def test_invalid_state_class(
hass: HomeAssistant,
mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator,
caplog: pytest.LogCaptureFixture,
) -> None:
"""Test state_class option with valid values."""
assert await async_setup_component(
hass,
mqtt.DOMAIN,
"""Test state_class option with invalid value."""
with pytest.raises(AssertionError):
await mqtt_mock_entry_no_yaml_config()
assert (
"Invalid config for [mqtt]: expected SensorStateClass or one of" in caplog.text
)
@pytest.mark.parametrize(
"hass_config",
[
{
mqtt.DOMAIN: {
sensor.DOMAIN: [
@ -854,10 +917,14 @@ async def test_valid_state_class(
},
]
}
},
)
await hass.async_block_till_done()
await mqtt_mock_entry_with_yaml_config()
}
],
)
async def test_valid_state_class(
hass: HomeAssistant, mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator
) -> None:
"""Test state_class option with valid values."""
await mqtt_mock_entry_no_yaml_config()
state = hass.states.get("sensor.test_1")
assert state.attributes["state_class"] == "measurement"
@ -1237,13 +1304,9 @@ async def test_entity_category(
)
async def test_value_template_with_entity_id(
hass: HomeAssistant, mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator
) -> None:
"""Test the access to attributes in value_template via the entity_id."""
assert await async_setup_component(
hass,
mqtt.DOMAIN,
@pytest.mark.parametrize(
"hass_config",
[
{
mqtt.DOMAIN: {
sensor.DOMAIN: {
@ -1258,10 +1321,14 @@ async def test_value_template_with_entity_id(
{% endif %}',
}
}
},
)
await hass.async_block_till_done()
await mqtt_mock_entry_with_yaml_config()
}
],
)
async def test_value_template_with_entity_id(
hass: HomeAssistant, mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator
) -> None:
"""Test the access to attributes in value_template via the entity_id."""
await mqtt_mock_entry_no_yaml_config()
async_fire_mqtt_message(hass, "test-topic", "100")
state = hass.states.get("sensor.test")
@ -1279,38 +1346,43 @@ async def test_reloadable(
await help_test_reloadable(hass, mqtt_client_mock, domain, config)
@pytest.mark.parametrize(
"hass_config",
[
help_custom_config(
sensor.DOMAIN,
DEFAULT_CONFIG,
(
{
"name": "test1",
"expire_after": 30,
"state_topic": "test-topic1",
"device_class": "temperature",
"unit_of_measurement": UnitOfTemperature.FAHRENHEIT.value,
},
{
"name": "test2",
"expire_after": 5,
"state_topic": "test-topic2",
"device_class": "temperature",
"unit_of_measurement": UnitOfTemperature.CELSIUS.value,
},
),
)
],
)
async def test_cleanup_triggers_and_restoring_state(
hass: HomeAssistant,
mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator,
mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator,
caplog: pytest.LogCaptureFixture,
tmp_path: Path,
freezer: FrozenDateTimeFactory,
hass_config: ConfigType,
) -> None:
"""Test cleanup old triggers at reloading and restoring the state."""
domain = sensor.DOMAIN
config1 = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][domain])
config1["name"] = "test1"
config1["expire_after"] = 30
config1["state_topic"] = "test-topic1"
config1["device_class"] = "temperature"
config1["unit_of_measurement"] = UnitOfTemperature.FAHRENHEIT.value
config2 = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][domain])
config2["name"] = "test2"
config2["expire_after"] = 5
config2["state_topic"] = "test-topic2"
config2["device_class"] = "temperature"
config2["unit_of_measurement"] = UnitOfTemperature.CELSIUS.value
freezer.move_to("2022-02-02 12:01:00+01:00")
assert await async_setup_component(
hass,
mqtt.DOMAIN,
{mqtt.DOMAIN: {domain: [config1, config2]}},
)
await hass.async_block_till_done()
await mqtt_mock_entry_with_yaml_config()
await mqtt_mock_entry_no_yaml_config()
async_fire_mqtt_message(hass, "test-topic1", "100")
state = hass.states.get("sensor.test1")
assert state.state == "38" # 100 °F -> 38 °C
@ -1321,9 +1393,7 @@ async def test_cleanup_triggers_and_restoring_state(
freezer.move_to("2022-02-02 12:01:10+01:00")
await help_test_reload_with_config(
hass, caplog, tmp_path, {mqtt.DOMAIN: {domain: [config1, config2]}}
)
await help_test_reload_with_config(hass, caplog, tmp_path, hass_config)
await hass.async_block_till_done()
state = hass.states.get("sensor.test1")
@ -1341,19 +1411,30 @@ async def test_cleanup_triggers_and_restoring_state(
assert state.state == "201"
@pytest.mark.parametrize(
"hass_config",
[
help_custom_config(
sensor.DOMAIN,
DEFAULT_CONFIG,
(
{
"name": "test3",
"expire_after": 10,
"state_topic": "test-topic3",
},
),
)
],
)
async def test_skip_restoring_state_with_over_due_expire_trigger(
hass: HomeAssistant,
mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator,
mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator,
freezer: FrozenDateTimeFactory,
) -> None:
"""Test restoring a state with over due expire timer."""
freezer.move_to("2022-02-02 12:02:00+01:00")
domain = sensor.DOMAIN
config3 = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][domain])
config3["name"] = "test3"
config3["expire_after"] = 10
config3["state_topic"] = "test-topic3"
fake_state = State(
"sensor.test3",
"300",
@ -1363,11 +1444,7 @@ async def test_skip_restoring_state_with_over_due_expire_trigger(
fake_extra_data = MagicMock()
mock_restore_cache_with_extra_data(hass, ((fake_state, fake_extra_data),))
assert await async_setup_component(
hass, mqtt.DOMAIN, {mqtt.DOMAIN: {domain: config3}}
)
await hass.async_block_till_done()
await mqtt_mock_entry_with_yaml_config()
await mqtt_mock_entry_no_yaml_config()
state = hass.states.get("sensor.test3")
assert state.state == STATE_UNAVAILABLE