Prepare MQTT platorm tests part1 (#90051)

* Add help_custom_config

* Tests alarm_control_panel

* Tests binary_sensor

* Only use help_custom_config with iterable options
This commit is contained in:
Jan Bouwhuis 2023-03-22 10:23:08 +01:00 committed by GitHub
parent d25e394310
commit 214286acb9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 410 additions and 319 deletions

View File

@ -35,9 +35,9 @@ from homeassistant.const import (
Platform, Platform,
) )
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.setup import async_setup_component
from .test_common import ( from .test_common import (
help_custom_config,
help_test_availability_when_connection_lost, help_test_availability_when_connection_lost,
help_test_availability_without_topic, help_test_availability_without_topic,
help_test_custom_availability_payload, help_test_custom_availability_payload,
@ -204,17 +204,12 @@ async def test_update_state_via_state_topic(
assert hass.states.get(entity_id).state == state assert hass.states.get(entity_id).state == state
@pytest.mark.parametrize("hass_config", [DEFAULT_CONFIG])
async def test_ignore_update_state_if_unknown_via_state_topic( async def test_ignore_update_state_if_unknown_via_state_topic(
hass: HomeAssistant, mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator hass: HomeAssistant, mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator
) -> None: ) -> None:
"""Test ignoring updates via state topic.""" """Test ignoring updates via state topic."""
assert await async_setup_component( await mqtt_mock_entry_no_yaml_config()
hass,
mqtt.DOMAIN,
DEFAULT_CONFIG,
)
await hass.async_block_till_done()
await mqtt_mock_entry_with_yaml_config()
entity_id = "alarm_control_panel.test" entity_id = "alarm_control_panel.test"
@ -225,31 +220,25 @@ async def test_ignore_update_state_if_unknown_via_state_topic(
@pytest.mark.parametrize( @pytest.mark.parametrize(
("service", "payload"), ("hass_config", "service", "payload"),
[ [
(SERVICE_ALARM_ARM_HOME, "ARM_HOME"), (DEFAULT_CONFIG, SERVICE_ALARM_ARM_HOME, "ARM_HOME"),
(SERVICE_ALARM_ARM_AWAY, "ARM_AWAY"), (DEFAULT_CONFIG, SERVICE_ALARM_ARM_AWAY, "ARM_AWAY"),
(SERVICE_ALARM_ARM_NIGHT, "ARM_NIGHT"), (DEFAULT_CONFIG, SERVICE_ALARM_ARM_NIGHT, "ARM_NIGHT"),
(SERVICE_ALARM_ARM_VACATION, "ARM_VACATION"), (DEFAULT_CONFIG, SERVICE_ALARM_ARM_VACATION, "ARM_VACATION"),
(SERVICE_ALARM_ARM_CUSTOM_BYPASS, "ARM_CUSTOM_BYPASS"), (DEFAULT_CONFIG, SERVICE_ALARM_ARM_CUSTOM_BYPASS, "ARM_CUSTOM_BYPASS"),
(SERVICE_ALARM_DISARM, "DISARM"), (DEFAULT_CONFIG, SERVICE_ALARM_DISARM, "DISARM"),
(SERVICE_ALARM_TRIGGER, "TRIGGER"), (DEFAULT_CONFIG, SERVICE_ALARM_TRIGGER, "TRIGGER"),
], ],
) )
async def test_publish_mqtt_no_code( async def test_publish_mqtt_no_code(
hass: HomeAssistant, hass: HomeAssistant,
mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator, mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator,
service, service,
payload, payload,
) -> None: ) -> None:
"""Test publishing of MQTT messages when no code is configured.""" """Test publishing of MQTT messages when no code is configured."""
assert await async_setup_component( mqtt_mock = await mqtt_mock_entry_no_yaml_config()
hass,
mqtt.DOMAIN,
DEFAULT_CONFIG,
)
await hass.async_block_till_done()
mqtt_mock = await mqtt_mock_entry_with_yaml_config()
await hass.services.async_call( await hass.services.async_call(
alarm_control_panel.DOMAIN, alarm_control_panel.DOMAIN,
@ -262,31 +251,25 @@ async def test_publish_mqtt_no_code(
@pytest.mark.parametrize( @pytest.mark.parametrize(
("service", "payload"), ("hass_config", "service", "payload"),
[ [
(SERVICE_ALARM_ARM_HOME, "ARM_HOME"), (DEFAULT_CONFIG_CODE, SERVICE_ALARM_ARM_HOME, "ARM_HOME"),
(SERVICE_ALARM_ARM_AWAY, "ARM_AWAY"), (DEFAULT_CONFIG_CODE, SERVICE_ALARM_ARM_AWAY, "ARM_AWAY"),
(SERVICE_ALARM_ARM_NIGHT, "ARM_NIGHT"), (DEFAULT_CONFIG_CODE, SERVICE_ALARM_ARM_NIGHT, "ARM_NIGHT"),
(SERVICE_ALARM_ARM_VACATION, "ARM_VACATION"), (DEFAULT_CONFIG_CODE, SERVICE_ALARM_ARM_VACATION, "ARM_VACATION"),
(SERVICE_ALARM_ARM_CUSTOM_BYPASS, "ARM_CUSTOM_BYPASS"), (DEFAULT_CONFIG_CODE, SERVICE_ALARM_ARM_CUSTOM_BYPASS, "ARM_CUSTOM_BYPASS"),
(SERVICE_ALARM_DISARM, "DISARM"), (DEFAULT_CONFIG_CODE, SERVICE_ALARM_DISARM, "DISARM"),
(SERVICE_ALARM_TRIGGER, "TRIGGER"), (DEFAULT_CONFIG_CODE, SERVICE_ALARM_TRIGGER, "TRIGGER"),
], ],
) )
async def test_publish_mqtt_with_code( async def test_publish_mqtt_with_code(
hass: HomeAssistant, hass: HomeAssistant,
mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator, mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator,
service, service,
payload, payload,
) -> None: ) -> None:
"""Test publishing of MQTT messages when code is configured.""" """Test publishing of MQTT messages when code is configured."""
assert await async_setup_component( mqtt_mock = await mqtt_mock_entry_no_yaml_config()
hass,
mqtt.DOMAIN,
DEFAULT_CONFIG_CODE,
)
await hass.async_block_till_done()
mqtt_mock = await mqtt_mock_entry_with_yaml_config()
call_count = mqtt_mock.async_publish.call_count call_count = mqtt_mock.async_publish.call_count
# No code provided, should not publish # No code provided, should not publish
@ -318,31 +301,29 @@ async def test_publish_mqtt_with_code(
@pytest.mark.parametrize( @pytest.mark.parametrize(
("service", "payload"), ("hass_config", "service", "payload"),
[ [
(SERVICE_ALARM_ARM_HOME, "ARM_HOME"), (DEFAULT_CONFIG_REMOTE_CODE, SERVICE_ALARM_ARM_HOME, "ARM_HOME"),
(SERVICE_ALARM_ARM_AWAY, "ARM_AWAY"), (DEFAULT_CONFIG_REMOTE_CODE, SERVICE_ALARM_ARM_AWAY, "ARM_AWAY"),
(SERVICE_ALARM_ARM_NIGHT, "ARM_NIGHT"), (DEFAULT_CONFIG_REMOTE_CODE, SERVICE_ALARM_ARM_NIGHT, "ARM_NIGHT"),
(SERVICE_ALARM_ARM_VACATION, "ARM_VACATION"), (DEFAULT_CONFIG_REMOTE_CODE, SERVICE_ALARM_ARM_VACATION, "ARM_VACATION"),
(SERVICE_ALARM_ARM_CUSTOM_BYPASS, "ARM_CUSTOM_BYPASS"), (
(SERVICE_ALARM_DISARM, "DISARM"), DEFAULT_CONFIG_REMOTE_CODE,
(SERVICE_ALARM_TRIGGER, "TRIGGER"), SERVICE_ALARM_ARM_CUSTOM_BYPASS,
"ARM_CUSTOM_BYPASS",
),
(DEFAULT_CONFIG_REMOTE_CODE, SERVICE_ALARM_DISARM, "DISARM"),
(DEFAULT_CONFIG_REMOTE_CODE, SERVICE_ALARM_TRIGGER, "TRIGGER"),
], ],
) )
async def test_publish_mqtt_with_remote_code( async def test_publish_mqtt_with_remote_code(
hass: HomeAssistant, hass: HomeAssistant,
mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator, mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator,
service, service,
payload, payload,
) -> None: ) -> None:
"""Test publishing of MQTT messages when remode code is configured.""" """Test publishing of MQTT messages when remode code is configured."""
assert await async_setup_component( mqtt_mock = await mqtt_mock_entry_no_yaml_config()
hass,
mqtt.DOMAIN,
DEFAULT_CONFIG_REMOTE_CODE,
)
await hass.async_block_till_done()
mqtt_mock = await mqtt_mock_entry_with_yaml_config()
call_count = mqtt_mock.async_publish.call_count call_count = mqtt_mock.async_publish.call_count
# No code provided, should not publish # No code provided, should not publish
@ -365,31 +346,29 @@ async def test_publish_mqtt_with_remote_code(
@pytest.mark.parametrize( @pytest.mark.parametrize(
("service", "payload"), ("hass_config", "service", "payload"),
[ [
(SERVICE_ALARM_ARM_HOME, "ARM_HOME"), (DEFAULT_CONFIG_REMOTE_CODE_TEXT, SERVICE_ALARM_ARM_HOME, "ARM_HOME"),
(SERVICE_ALARM_ARM_AWAY, "ARM_AWAY"), (DEFAULT_CONFIG_REMOTE_CODE_TEXT, SERVICE_ALARM_ARM_AWAY, "ARM_AWAY"),
(SERVICE_ALARM_ARM_NIGHT, "ARM_NIGHT"), (DEFAULT_CONFIG_REMOTE_CODE_TEXT, SERVICE_ALARM_ARM_NIGHT, "ARM_NIGHT"),
(SERVICE_ALARM_ARM_VACATION, "ARM_VACATION"), (DEFAULT_CONFIG_REMOTE_CODE_TEXT, SERVICE_ALARM_ARM_VACATION, "ARM_VACATION"),
(SERVICE_ALARM_ARM_CUSTOM_BYPASS, "ARM_CUSTOM_BYPASS"), (
(SERVICE_ALARM_DISARM, "DISARM"), DEFAULT_CONFIG_REMOTE_CODE_TEXT,
(SERVICE_ALARM_TRIGGER, "TRIGGER"), SERVICE_ALARM_ARM_CUSTOM_BYPASS,
"ARM_CUSTOM_BYPASS",
),
(DEFAULT_CONFIG_REMOTE_CODE_TEXT, SERVICE_ALARM_DISARM, "DISARM"),
(DEFAULT_CONFIG_REMOTE_CODE_TEXT, SERVICE_ALARM_TRIGGER, "TRIGGER"),
], ],
) )
async def test_publish_mqtt_with_remote_code_text( async def test_publish_mqtt_with_remote_code_text(
hass: HomeAssistant, hass: HomeAssistant,
mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator, mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator,
service, service: str,
payload, payload: str,
) -> None: ) -> None:
"""Test publishing of MQTT messages when remote text code is configured.""" """Test publishing of MQTT messages when remote text code is configured."""
assert await async_setup_component( mqtt_mock = await mqtt_mock_entry_no_yaml_config()
hass,
mqtt.DOMAIN,
DEFAULT_CONFIG_REMOTE_CODE_TEXT,
)
await hass.async_block_till_done()
mqtt_mock = await mqtt_mock_entry_with_yaml_config()
call_count = mqtt_mock.async_publish.call_count call_count = mqtt_mock.async_publish.call_count
# No code provided, should not publish # No code provided, should not publish
@ -412,38 +391,85 @@ async def test_publish_mqtt_with_remote_code_text(
@pytest.mark.parametrize( @pytest.mark.parametrize(
("service", "payload", "disable_code"), ("hass_config", "service", "payload"),
[ [
(SERVICE_ALARM_ARM_HOME, "ARM_HOME", "code_arm_required"), (
(SERVICE_ALARM_ARM_AWAY, "ARM_AWAY", "code_arm_required"), help_custom_config(
(SERVICE_ALARM_ARM_NIGHT, "ARM_NIGHT", "code_arm_required"), alarm_control_panel.DOMAIN,
(SERVICE_ALARM_ARM_VACATION, "ARM_VACATION", "code_arm_required"), DEFAULT_CONFIG_CODE,
(SERVICE_ALARM_ARM_CUSTOM_BYPASS, "ARM_CUSTOM_BYPASS", "code_arm_required"), ({"code_arm_required": False},),
(SERVICE_ALARM_DISARM, "DISARM", "code_disarm_required"), ),
(SERVICE_ALARM_TRIGGER, "TRIGGER", "code_trigger_required"), SERVICE_ALARM_ARM_HOME,
"ARM_HOME",
),
(
help_custom_config(
alarm_control_panel.DOMAIN,
DEFAULT_CONFIG_CODE,
({"code_arm_required": False},),
),
SERVICE_ALARM_ARM_AWAY,
"ARM_AWAY",
),
(
help_custom_config(
alarm_control_panel.DOMAIN,
DEFAULT_CONFIG_CODE,
({"code_arm_required": False},),
),
SERVICE_ALARM_ARM_NIGHT,
"ARM_NIGHT",
),
(
help_custom_config(
alarm_control_panel.DOMAIN,
DEFAULT_CONFIG_CODE,
({"code_arm_required": False},),
),
SERVICE_ALARM_ARM_VACATION,
"ARM_VACATION",
),
(
help_custom_config(
alarm_control_panel.DOMAIN,
DEFAULT_CONFIG_CODE,
({"code_arm_required": False},),
),
SERVICE_ALARM_ARM_CUSTOM_BYPASS,
"ARM_CUSTOM_BYPASS",
),
(
help_custom_config(
alarm_control_panel.DOMAIN,
DEFAULT_CONFIG_CODE,
({"code_disarm_required": False},),
),
SERVICE_ALARM_DISARM,
"DISARM",
),
(
help_custom_config(
alarm_control_panel.DOMAIN,
DEFAULT_CONFIG_CODE,
({"code_trigger_required": False},),
),
SERVICE_ALARM_TRIGGER,
"TRIGGER",
),
], ],
) )
async def test_publish_mqtt_with_code_required_false( async def test_publish_mqtt_with_code_required_false(
hass: HomeAssistant, hass: HomeAssistant,
mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator, mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator,
service, service: str,
payload, payload: str,
disable_code,
) -> None: ) -> None:
"""Test publishing of MQTT messages when code is configured. """Test publishing of MQTT messages when code is configured.
code_arm_required = False / code_disarm_required = False / code_arm_required = False / code_disarm_required = False /
code_trigger_required = False code_trigger_required = False
""" """
config = copy.deepcopy(DEFAULT_CONFIG_CODE) mqtt_mock = await mqtt_mock_entry_no_yaml_config()
config[mqtt.DOMAIN][alarm_control_panel.DOMAIN][disable_code] = False
assert await async_setup_component(
hass,
mqtt.DOMAIN,
config,
)
await hass.async_block_till_done()
mqtt_mock = await mqtt_mock_entry_with_yaml_config()
# No code provided, should publish # No code provided, should publish
await hass.services.async_call( await hass.services.async_call(
@ -476,25 +502,29 @@ async def test_publish_mqtt_with_code_required_false(
mqtt_mock.reset_mock() mqtt_mock.reset_mock()
@pytest.mark.parametrize(
"hass_config",
[
help_custom_config(
alarm_control_panel.DOMAIN,
DEFAULT_CONFIG_CODE,
(
{
"code": "0123",
"command_template": '{"action":"{{ action }}","code":"{{ code }}"}',
},
),
)
],
)
async def test_disarm_publishes_mqtt_with_template( async def test_disarm_publishes_mqtt_with_template(
hass: HomeAssistant, mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator hass: HomeAssistant, mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator
) -> None: ) -> None:
"""Test publishing of MQTT messages while disarmed. """Test publishing of MQTT messages while disarmed.
When command_template set to output json When command_template set to output json
""" """
config = copy.deepcopy(DEFAULT_CONFIG_CODE) mqtt_mock = await mqtt_mock_entry_no_yaml_config()
config[mqtt.DOMAIN][alarm_control_panel.DOMAIN]["code"] = "0123"
config[mqtt.DOMAIN][alarm_control_panel.DOMAIN][
"command_template"
] = '{"action":"{{ action }}","code":"{{ code }}"}'
assert await async_setup_component(
hass,
mqtt.DOMAIN,
config,
)
await hass.async_block_till_done()
mqtt_mock = await mqtt_mock_entry_with_yaml_config()
await common.async_alarm_disarm(hass, "0123") await common.async_alarm_disarm(hass, "0123")
mqtt_mock.async_publish.assert_called_once_with( mqtt_mock.async_publish.assert_called_once_with(
@ -502,13 +532,9 @@ async def test_disarm_publishes_mqtt_with_template(
) )
async def test_update_state_via_state_topic_template( @pytest.mark.parametrize(
hass: HomeAssistant, mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator "hass_config",
) -> None: [
"""Test updating with template_value via state topic."""
assert await async_setup_component(
hass,
mqtt.DOMAIN,
{ {
mqtt.DOMAIN: { mqtt.DOMAIN: {
alarm_control_panel.DOMAIN: { alarm_control_panel.DOMAIN: {
@ -523,10 +549,14 @@ async def test_update_state_via_state_topic_template(
{% endif %}", {% endif %}",
} }
} }
}, }
],
) )
await hass.async_block_till_done() async def test_update_state_via_state_topic_template(
await mqtt_mock_entry_with_yaml_config() hass: HomeAssistant, mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator
) -> None:
"""Test updating with template_value via state topic."""
await mqtt_mock_entry_no_yaml_config()
state = hass.states.get("alarm_control_panel.test") state = hass.states.get("alarm_control_panel.test")
assert state.state == STATE_UNKNOWN assert state.state == STATE_UNKNOWN
@ -537,16 +567,19 @@ async def test_update_state_via_state_topic_template(
assert state.state == STATE_ALARM_ARMED_AWAY assert state.state == STATE_ALARM_ARMED_AWAY
@pytest.mark.parametrize(
"hass_config",
[
help_custom_config(
alarm_control_panel.DOMAIN, DEFAULT_CONFIG, ({"code": CODE_NUMBER},)
)
],
)
async def test_attributes_code_number( async def test_attributes_code_number(
hass: HomeAssistant, mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator hass: HomeAssistant, mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator
) -> None: ) -> None:
"""Test attributes which are not supported by the vacuum.""" """Test attributes which are not supported by the vacuum."""
config = copy.deepcopy(DEFAULT_CONFIG) await mqtt_mock_entry_no_yaml_config()
config[mqtt.DOMAIN][alarm_control_panel.DOMAIN]["code"] = CODE_NUMBER
assert await async_setup_component(hass, mqtt.DOMAIN, config)
await hass.async_block_till_done()
await mqtt_mock_entry_with_yaml_config()
state = hass.states.get("alarm_control_panel.test") state = hass.states.get("alarm_control_panel.test")
assert ( assert (
@ -555,16 +588,21 @@ async def test_attributes_code_number(
) )
@pytest.mark.parametrize(
"hass_config",
[
help_custom_config(
alarm_control_panel.DOMAIN,
DEFAULT_CONFIG_REMOTE_CODE,
({"code": "REMOTE_CODE"},),
)
],
)
async def test_attributes_remote_code_number( async def test_attributes_remote_code_number(
hass: HomeAssistant, mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator hass: HomeAssistant, mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator
) -> None: ) -> None:
"""Test attributes which are not supported by the vacuum.""" """Test attributes which are not supported by the vacuum."""
config = copy.deepcopy(DEFAULT_CONFIG_REMOTE_CODE) await mqtt_mock_entry_no_yaml_config()
config[mqtt.DOMAIN][alarm_control_panel.DOMAIN]["code"] = "REMOTE_CODE"
assert await async_setup_component(hass, mqtt.DOMAIN, config)
await hass.async_block_till_done()
await mqtt_mock_entry_with_yaml_config()
state = hass.states.get("alarm_control_panel.test") state = hass.states.get("alarm_control_panel.test")
assert ( assert (
@ -573,16 +611,19 @@ async def test_attributes_remote_code_number(
) )
@pytest.mark.parametrize(
"hass_config",
[
help_custom_config(
alarm_control_panel.DOMAIN, DEFAULT_CONFIG, ({"code": CODE_TEXT},)
)
],
)
async def test_attributes_code_text( async def test_attributes_code_text(
hass: HomeAssistant, mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator hass: HomeAssistant, mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator
) -> None: ) -> None:
"""Test attributes which are not supported by the vacuum.""" """Test attributes which are not supported by the vacuum."""
config = copy.deepcopy(DEFAULT_CONFIG) await mqtt_mock_entry_no_yaml_config()
config[mqtt.DOMAIN][alarm_control_panel.DOMAIN]["code"] = CODE_TEXT
assert await async_setup_component(hass, mqtt.DOMAIN, config)
await hass.async_block_till_done()
await mqtt_mock_entry_with_yaml_config()
state = hass.states.get("alarm_control_panel.test") state = hass.states.get("alarm_control_panel.test")
assert ( assert (

View File

@ -19,10 +19,11 @@ from homeassistant.const import (
Platform, Platform,
) )
from homeassistant.core import HomeAssistant, State, callback from homeassistant.core import HomeAssistant, State, callback
from homeassistant.setup import async_setup_component from homeassistant.helpers.typing import ConfigType
import homeassistant.util.dt as dt_util import homeassistant.util.dt as dt_util
from .test_common import ( from .test_common import (
help_custom_config,
help_test_availability_when_connection_lost, help_test_availability_when_connection_lost,
help_test_availability_without_topic, help_test_availability_without_topic,
help_test_custom_availability_payload, help_test_custom_availability_payload,
@ -74,15 +75,9 @@ def binary_sensor_platform_only():
yield yield
async def test_setting_sensor_value_expires_availability_topic( @pytest.mark.parametrize(
hass: HomeAssistant, "hass_config",
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,
{ {
mqtt.DOMAIN: { mqtt.DOMAIN: {
binary_sensor.DOMAIN: { binary_sensor.DOMAIN: {
@ -93,10 +88,16 @@ async def test_setting_sensor_value_expires_availability_topic(
"availability_topic": "availability-topic", "availability_topic": "availability-topic",
} }
} }
}, }
],
) )
await hass.async_block_till_done() async def test_setting_sensor_value_expires_availability_topic(
await mqtt_mock_entry_with_yaml_config() hass: HomeAssistant,
mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator,
caplog: pytest.LogCaptureFixture,
) -> None:
"""Test the expiration of the value."""
await mqtt_mock_entry_no_yaml_config()
state = hass.states.get("binary_sensor.test") state = hass.states.get("binary_sensor.test")
assert state.state == STATE_UNAVAILABLE assert state.state == STATE_UNAVAILABLE
@ -110,15 +111,9 @@ async def test_setting_sensor_value_expires_availability_topic(
await expires_helper(hass) await expires_helper(hass)
async def test_setting_sensor_value_expires( @pytest.mark.parametrize(
hass: HomeAssistant, "hass_config",
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,
{ {
mqtt.DOMAIN: { mqtt.DOMAIN: {
binary_sensor.DOMAIN: { binary_sensor.DOMAIN: {
@ -128,10 +123,16 @@ async def test_setting_sensor_value_expires(
"force_update": True, "force_update": True,
} }
} }
}, }
],
) )
await hass.async_block_till_done() async def test_setting_sensor_value_expires(
await mqtt_mock_entry_with_yaml_config() hass: HomeAssistant,
mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator,
caplog: pytest.LogCaptureFixture,
) -> 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 should be unavailable since expire_after is defined and > 0
state = hass.states.get("binary_sensor.test") state = hass.states.get("binary_sensor.test")
@ -274,13 +275,9 @@ async def test_expiration_on_discovery_and_discovery_update_of_binary_sensor(
assert state.state == STATE_UNAVAILABLE assert state.state == STATE_UNAVAILABLE
async def test_setting_sensor_value_via_mqtt_message( @pytest.mark.parametrize(
hass: HomeAssistant, mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator "hass_config",
) -> None: [
"""Test the setting of the value via MQTT."""
assert await async_setup_component(
hass,
mqtt.DOMAIN,
{ {
mqtt.DOMAIN: { mqtt.DOMAIN: {
binary_sensor.DOMAIN: { binary_sensor.DOMAIN: {
@ -290,10 +287,14 @@ async def test_setting_sensor_value_via_mqtt_message(
"payload_off": "OFF", "payload_off": "OFF",
} }
} }
}, }
],
) )
await hass.async_block_till_done() async def test_setting_sensor_value_via_mqtt_message(
await mqtt_mock_entry_with_yaml_config() 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()
state = hass.states.get("binary_sensor.test") state = hass.states.get("binary_sensor.test")
@ -312,15 +313,9 @@ async def test_setting_sensor_value_via_mqtt_message(
assert state.state == STATE_UNKNOWN assert state.state == STATE_UNKNOWN
async def test_invalid_sensor_value_via_mqtt_message( @pytest.mark.parametrize(
hass: HomeAssistant, "hass_config",
mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator, [
caplog: pytest.LogCaptureFixture,
) -> None:
"""Test the setting of the value via MQTT."""
assert await async_setup_component(
hass,
mqtt.DOMAIN,
{ {
mqtt.DOMAIN: { mqtt.DOMAIN: {
binary_sensor.DOMAIN: { binary_sensor.DOMAIN: {
@ -330,10 +325,16 @@ async def test_invalid_sensor_value_via_mqtt_message(
"payload_off": "OFF", "payload_off": "OFF",
} }
} }
}, }
],
) )
await hass.async_block_till_done() async def test_invalid_sensor_value_via_mqtt_message(
await mqtt_mock_entry_with_yaml_config() hass: HomeAssistant,
mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator,
caplog: pytest.LogCaptureFixture,
) -> None:
"""Test the setting of the value via MQTT."""
await mqtt_mock_entry_no_yaml_config()
state = hass.states.get("binary_sensor.test") state = hass.states.get("binary_sensor.test")
@ -356,13 +357,9 @@ async def test_invalid_sensor_value_via_mqtt_message(
assert "No matching payload found for entity" in caplog.text assert "No matching payload found for entity" in caplog.text
async def test_setting_sensor_value_via_mqtt_message_and_template( @pytest.mark.parametrize(
hass: HomeAssistant, mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator "hass_config",
) -> None: [
"""Test the setting of the value via MQTT."""
assert await async_setup_component(
hass,
mqtt.DOMAIN,
{ {
mqtt.DOMAIN: { mqtt.DOMAIN: {
binary_sensor.DOMAIN: { binary_sensor.DOMAIN: {
@ -374,10 +371,14 @@ async def test_setting_sensor_value_via_mqtt_message_and_template(
"{%-else-%}ON{%-endif%}", "{%-else-%}ON{%-endif%}",
} }
} }
}, }
],
) )
await hass.async_block_till_done() async def test_setting_sensor_value_via_mqtt_message_and_template(
await mqtt_mock_entry_with_yaml_config() 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()
state = hass.states.get("binary_sensor.test") state = hass.states.get("binary_sensor.test")
assert state.state == STATE_UNKNOWN assert state.state == STATE_UNKNOWN
@ -391,15 +392,9 @@ async def test_setting_sensor_value_via_mqtt_message_and_template(
assert state.state == STATE_OFF assert state.state == STATE_OFF
async def test_setting_sensor_value_via_mqtt_message_and_template2( @pytest.mark.parametrize(
hass: HomeAssistant, "hass_config",
mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator, [
caplog: pytest.LogCaptureFixture,
) -> None:
"""Test the setting of the value via MQTT."""
assert await async_setup_component(
hass,
mqtt.DOMAIN,
{ {
mqtt.DOMAIN: { mqtt.DOMAIN: {
binary_sensor.DOMAIN: { binary_sensor.DOMAIN: {
@ -411,9 +406,15 @@ async def test_setting_sensor_value_via_mqtt_message_and_template2(
} }
} }
}, },
],
) )
await hass.async_block_till_done() async def test_setting_sensor_value_via_mqtt_message_and_template2(
await mqtt_mock_entry_with_yaml_config() hass: HomeAssistant,
mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator,
caplog: pytest.LogCaptureFixture,
) -> None:
"""Test the setting of the value via MQTT."""
await mqtt_mock_entry_no_yaml_config()
state = hass.states.get("binary_sensor.test") state = hass.states.get("binary_sensor.test")
assert state.state == STATE_UNKNOWN assert state.state == STATE_UNKNOWN
@ -432,15 +433,9 @@ async def test_setting_sensor_value_via_mqtt_message_and_template2(
assert "template output: 'ILLEGAL'" in caplog.text assert "template output: 'ILLEGAL'" in caplog.text
async def test_setting_sensor_value_via_mqtt_message_and_template_and_raw_state_encoding( @pytest.mark.parametrize(
hass: HomeAssistant, "hass_config",
mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator, [
caplog: pytest.LogCaptureFixture,
) -> None:
"""Test processing a raw value via MQTT."""
assert await async_setup_component(
hass,
mqtt.DOMAIN,
{ {
mqtt.DOMAIN: { mqtt.DOMAIN: {
binary_sensor.DOMAIN: { binary_sensor.DOMAIN: {
@ -452,10 +447,16 @@ async def test_setting_sensor_value_via_mqtt_message_and_template_and_raw_state_
"value_template": "{%if value|unpack('b')-%}ON{%else%}OFF{%-endif-%}", "value_template": "{%if value|unpack('b')-%}ON{%else%}OFF{%-endif-%}",
} }
} }
}, }
],
) )
await hass.async_block_till_done() async def test_setting_sensor_value_via_mqtt_message_and_template_and_raw_state_encoding(
await mqtt_mock_entry_with_yaml_config() hass: HomeAssistant,
mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator,
caplog: pytest.LogCaptureFixture,
) -> None:
"""Test processing a raw value via MQTT."""
await mqtt_mock_entry_no_yaml_config()
state = hass.states.get("binary_sensor.test") state = hass.states.get("binary_sensor.test")
assert state.state == STATE_UNKNOWN assert state.state == STATE_UNKNOWN
@ -469,13 +470,9 @@ async def test_setting_sensor_value_via_mqtt_message_and_template_and_raw_state_
assert state.state == STATE_OFF assert state.state == STATE_OFF
async def test_setting_sensor_value_via_mqtt_message_empty_template( @pytest.mark.parametrize(
hass: HomeAssistant, mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator "hass_config",
) -> None: [
"""Test the setting of the value via MQTT."""
assert await async_setup_component(
hass,
mqtt.DOMAIN,
{ {
mqtt.DOMAIN: { mqtt.DOMAIN: {
binary_sensor.DOMAIN: { binary_sensor.DOMAIN: {
@ -486,10 +483,14 @@ async def test_setting_sensor_value_via_mqtt_message_empty_template(
"value_template": '{%if value == "ABC"%}ON{%endif%}', "value_template": '{%if value == "ABC"%}ON{%endif%}',
} }
} }
}, }
],
) )
await hass.async_block_till_done() async def test_setting_sensor_value_via_mqtt_message_empty_template(
await mqtt_mock_entry_with_yaml_config() 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()
state = hass.states.get("binary_sensor.test") state = hass.states.get("binary_sensor.test")
assert state.state == STATE_UNKNOWN assert state.state == STATE_UNKNOWN
@ -503,13 +504,9 @@ async def test_setting_sensor_value_via_mqtt_message_empty_template(
assert state.state == STATE_ON assert state.state == STATE_ON
async def test_valid_device_class( @pytest.mark.parametrize(
hass: HomeAssistant, mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator "hass_config",
) -> None: [
"""Test the setting of a valid sensor class."""
assert await async_setup_component(
hass,
mqtt.DOMAIN,
{ {
mqtt.DOMAIN: { mqtt.DOMAIN: {
binary_sensor.DOMAIN: { binary_sensor.DOMAIN: {
@ -518,22 +515,22 @@ async def test_valid_device_class(
"state_topic": "test-topic", "state_topic": "test-topic",
} }
} }
}, }
],
) )
await hass.async_block_till_done() async def test_valid_device_class(
await mqtt_mock_entry_with_yaml_config() hass: HomeAssistant, mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator
) -> None:
"""Test the setting of a valid sensor class."""
await mqtt_mock_entry_no_yaml_config()
state = hass.states.get("binary_sensor.test") state = hass.states.get("binary_sensor.test")
assert state.attributes.get("device_class") == "motion" assert state.attributes.get("device_class") == "motion"
async def test_invalid_device_class( @pytest.mark.parametrize(
hass: HomeAssistant, caplog: pytest.LogCaptureFixture "hass_config",
) -> None: [
"""Test the setting of an invalid sensor class."""
assert not await async_setup_component(
hass,
mqtt.DOMAIN,
{ {
mqtt.DOMAIN: { mqtt.DOMAIN: {
binary_sensor.DOMAIN: { binary_sensor.DOMAIN: {
@ -542,8 +539,17 @@ async def test_invalid_device_class(
"state_topic": "test-topic", "state_topic": "test-topic",
} }
} }
}, }
],
) )
async def test_invalid_device_class(
hass: HomeAssistant,
caplog: pytest.LogCaptureFixture,
mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator,
) -> None:
"""Test the setting of an invalid sensor class."""
with pytest.raises(AssertionError):
await mqtt_mock_entry_no_yaml_config()
assert "Invalid config for [mqtt]: expected BinarySensorDeviceClass" in caplog.text assert "Invalid config for [mqtt]: expected BinarySensorDeviceClass" in caplog.text
@ -585,13 +591,9 @@ async def test_custom_availability_payload(
) )
async def test_force_update_disabled( @pytest.mark.parametrize(
hass: HomeAssistant, mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator "hass_config",
) -> None: [
"""Test force update option."""
assert await async_setup_component(
hass,
mqtt.DOMAIN,
{ {
mqtt.DOMAIN: { mqtt.DOMAIN: {
binary_sensor.DOMAIN: { binary_sensor.DOMAIN: {
@ -601,10 +603,14 @@ async def test_force_update_disabled(
"payload_off": "OFF", "payload_off": "OFF",
} }
} }
}, }
],
) )
await hass.async_block_till_done() async def test_force_update_disabled(
await mqtt_mock_entry_with_yaml_config() hass: HomeAssistant, mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator
) -> None:
"""Test force update option."""
await mqtt_mock_entry_no_yaml_config()
events = [] events = []
@ -624,13 +630,9 @@ async def test_force_update_disabled(
assert len(events) == 1 assert len(events) == 1
async def test_force_update_enabled( @pytest.mark.parametrize(
hass: HomeAssistant, mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator "hass_config",
) -> None: [
"""Test force update option."""
assert await async_setup_component(
hass,
mqtt.DOMAIN,
{ {
mqtt.DOMAIN: { mqtt.DOMAIN: {
binary_sensor.DOMAIN: { binary_sensor.DOMAIN: {
@ -641,10 +643,14 @@ async def test_force_update_enabled(
"force_update": True, "force_update": True,
} }
} }
}, }
],
) )
await hass.async_block_till_done() async def test_force_update_enabled(
await mqtt_mock_entry_with_yaml_config() hass: HomeAssistant, mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator
) -> None:
"""Test force update option."""
await mqtt_mock_entry_no_yaml_config()
events = [] events = []
@ -664,13 +670,9 @@ async def test_force_update_enabled(
assert len(events) == 2 assert len(events) == 2
async def test_off_delay( @pytest.mark.parametrize(
hass: HomeAssistant, mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator "hass_config",
) -> None: [
"""Test off_delay option."""
assert await async_setup_component(
hass,
mqtt.DOMAIN,
{ {
mqtt.DOMAIN: { mqtt.DOMAIN: {
binary_sensor.DOMAIN: { binary_sensor.DOMAIN: {
@ -682,10 +684,14 @@ async def test_off_delay(
"force_update": True, "force_update": True,
} }
} }
}, }
],
) )
await hass.async_block_till_done() async def test_off_delay(
await mqtt_mock_entry_with_yaml_config() hass: HomeAssistant, mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator
) -> None:
"""Test off_delay option."""
await mqtt_mock_entry_no_yaml_config()
events = [] events = []
@ -1068,40 +1074,54 @@ async def test_reloadable(
@pytest.mark.parametrize( @pytest.mark.parametrize(
("payload1", "state1", "payload2", "state2"), ("hass_config", "payload1", "state1", "payload2", "state2"),
[("ON", "on", "OFF", "off"), ("OFF", "off", "ON", "on")], [
(
help_custom_config(
binary_sensor.DOMAIN,
DEFAULT_CONFIG,
(
{"name": "test1", "expire_after": 30, "state_topic": "test-topic1"},
{"name": "test2", "expire_after": 5, "state_topic": "test-topic2"},
),
),
"ON",
"on",
"OFF",
"off",
),
(
help_custom_config(
binary_sensor.DOMAIN,
DEFAULT_CONFIG,
(
{"name": "test1", "expire_after": 30, "state_topic": "test-topic1"},
{"name": "test2", "expire_after": 5, "state_topic": "test-topic2"},
),
),
"OFF",
"off",
"ON",
"on",
),
],
) )
async def test_cleanup_triggers_and_restoring_state( async def test_cleanup_triggers_and_restoring_state(
hass: HomeAssistant, hass: HomeAssistant,
mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator, mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator,
caplog: pytest.LogCaptureFixture, caplog: pytest.LogCaptureFixture,
tmp_path: Path, tmp_path: Path,
freezer: FrozenDateTimeFactory, freezer: FrozenDateTimeFactory,
hass_config: ConfigType,
payload1, payload1,
state1, state1,
payload2, payload2,
state2, state2,
) -> None: ) -> None:
"""Test cleanup old triggers at reloading and restoring the state.""" """Test cleanup old triggers at reloading and restoring the state."""
domain = binary_sensor.DOMAIN
config1 = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][domain])
config1["name"] = "test1"
config1["expire_after"] = 30
config1["state_topic"] = "test-topic1"
config2 = copy.deepcopy(DEFAULT_CONFIG[mqtt.DOMAIN][domain])
config2["name"] = "test2"
config2["expire_after"] = 5
config2["state_topic"] = "test-topic2"
freezer.move_to("2022-02-02 12:01:00+01:00") freezer.move_to("2022-02-02 12:01:00+01:00")
assert await async_setup_component( await mqtt_mock_entry_no_yaml_config()
hass,
mqtt.DOMAIN,
{mqtt.DOMAIN: {binary_sensor.DOMAIN: [config1, config2]}},
)
await hass.async_block_till_done()
await mqtt_mock_entry_with_yaml_config()
async_fire_mqtt_message(hass, "test-topic1", payload1) async_fire_mqtt_message(hass, "test-topic1", payload1)
state = hass.states.get("binary_sensor.test1") state = hass.states.get("binary_sensor.test1")
@ -1114,7 +1134,7 @@ async def test_cleanup_triggers_and_restoring_state(
freezer.move_to("2022-02-02 12:01:10+01:00") freezer.move_to("2022-02-02 12:01:10+01:00")
await help_test_reload_with_config( await help_test_reload_with_config(
hass, caplog, tmp_path, {mqtt.DOMAIN: {domain: [config1, config2]}} hass, caplog, tmp_path, {mqtt.DOMAIN: hass_config}
) )
state = hass.states.get("binary_sensor.test1") state = hass.states.get("binary_sensor.test1")
@ -1132,9 +1152,19 @@ async def test_cleanup_triggers_and_restoring_state(
assert state.state == state2 assert state.state == state2
@pytest.mark.parametrize(
"hass_config",
[
help_custom_config(
binary_sensor.DOMAIN,
DEFAULT_CONFIG,
({"name": "test3", "expire_after": 10, "state_topic": "test-topic3"},),
)
],
)
async def test_skip_restoring_state_with_over_due_expire_trigger( async def test_skip_restoring_state_with_over_due_expire_trigger(
hass: HomeAssistant, hass: HomeAssistant,
mqtt_mock_entry_with_yaml_config: MqttMockHAClientGenerator, mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator,
freezer: FrozenDateTimeFactory, freezer: FrozenDateTimeFactory,
) -> None: ) -> None:
"""Test restoring a state with over due expire timer.""" """Test restoring a state with over due expire timer."""
@ -1153,11 +1183,7 @@ async def test_skip_restoring_state_with_over_due_expire_trigger(
) )
mock_restore_cache(hass, (fake_state,)) mock_restore_cache(hass, (fake_state,))
assert await async_setup_component( await mqtt_mock_entry_no_yaml_config()
hass, mqtt.DOMAIN, {mqtt.DOMAIN: {domain: config3}}
)
await hass.async_block_till_done()
await mqtt_mock_entry_with_yaml_config()
state = hass.states.get("binary_sensor.test3") state = hass.states.get("binary_sensor.test3")
assert state.state == STATE_UNAVAILABLE assert state.state == STATE_UNAVAILABLE

View File

@ -1,4 +1,5 @@
"""Common test objects.""" """Common test objects."""
from collections.abc import Iterable
from contextlib import suppress from contextlib import suppress
import copy import copy
from datetime import datetime from datetime import datetime
@ -119,6 +120,29 @@ async def help_setup_component(
return mqtt_mock return mqtt_mock
def help_custom_config(
mqtt_entity_domain: str,
mqtt_base_config: ConfigType,
mqtt_entity_configs: Iterable[ConfigType,],
) -> ConfigType:
"""Tweak a default config for parametrization.
Returns a custom config to be used as parametrization for with hass_config,
based on the supplied mqtt_base_config and updated with mqtt_entity_configs.
For each item in mqtt_entity_configs an entity instance is added to the config.
"""
config: ConfigType = copy.deepcopy(mqtt_base_config)
entity_instances: list[ConfigType] = []
for instance in mqtt_entity_configs:
base: ConfigType = copy.deepcopy(
mqtt_base_config[mqtt.DOMAIN][mqtt_entity_domain]
)
base.update(instance)
entity_instances.append(base)
config[mqtt.DOMAIN][mqtt_entity_domain]: list[ConfigType] = entity_instances
return config
async def help_test_availability_when_connection_lost( async def help_test_availability_when_connection_lost(
hass: HomeAssistant, hass: HomeAssistant,
mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator, mqtt_mock_entry_no_yaml_config: MqttMockHAClientGenerator,