Deduplicate MQTT mixin tests (#32563)

* Deduplicate MQTT mixin tests

* Remove test of not yet merged function
This commit is contained in:
Erik Montnemery 2020-03-09 17:40:00 +01:00 committed by GitHub
parent 743833e5f3
commit 4bb9f1800d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 1499 additions and 2956 deletions

View File

@ -266,7 +266,9 @@ class MqttVacuum(
async def async_will_remove_from_hass(self): async def async_will_remove_from_hass(self):
"""Unsubscribe when removed.""" """Unsubscribe when removed."""
await subscription.async_unsubscribe_topics(self.hass, self._sub_state) self._sub_state = await subscription.async_unsubscribe_topics(
self.hass, self._sub_state
)
await MqttAttributes.async_will_remove_from_hass(self) await MqttAttributes.async_will_remove_from_hass(self)
await MqttAvailability.async_will_remove_from_hass(self) await MqttAvailability.async_will_remove_from_hass(self)
await MqttDiscoveryUpdate.async_will_remove_from_hass(self) await MqttDiscoveryUpdate.async_will_remove_from_hass(self)

View File

@ -231,7 +231,9 @@ class MqttStateVacuum(
async def async_will_remove_from_hass(self): async def async_will_remove_from_hass(self):
"""Unsubscribe when removed.""" """Unsubscribe when removed."""
await subscription.async_unsubscribe_topics(self.hass, self._sub_state) self._sub_state = await subscription.async_unsubscribe_topics(
self.hass, self._sub_state
)
await MqttAttributes.async_will_remove_from_hass(self) await MqttAttributes.async_will_remove_from_hass(self)
await MqttAvailability.async_will_remove_from_hass(self) await MqttAvailability.async_will_remove_from_hass(self)
await MqttDiscoveryUpdate.async_will_remove_from_hass(self) await MqttDiscoveryUpdate.async_will_remove_from_hass(self)

View File

@ -0,0 +1,221 @@
"""Common test objects."""
import json
from unittest.mock import ANY
from homeassistant.components import mqtt
from homeassistant.components.mqtt.discovery import async_start
from tests.common import (
MockConfigEntry,
async_fire_mqtt_message,
async_mock_mqtt_component,
async_setup_component,
mock_registry,
)
async def help_test_setting_attribute_via_mqtt_json_message(
hass, mqtt_mock, domain, config
):
"""Test the setting of attribute via MQTT with JSON payload."""
assert await async_setup_component(hass, domain, config,)
async_fire_mqtt_message(hass, "attr-topic", '{ "val": "100" }')
state = hass.states.get(f"{domain}.test")
assert state.attributes.get("val") == "100"
async def help_test_update_with_json_attrs_not_dict(
hass, mqtt_mock, caplog, domain, config
):
"""Test attributes get extracted from a JSON result."""
assert await async_setup_component(hass, domain, config,)
async_fire_mqtt_message(hass, "attr-topic", '[ "list", "of", "things"]')
state = hass.states.get(f"{domain}.test")
assert state.attributes.get("val") is None
assert "JSON result was not a dictionary" in caplog.text
async def help_test_update_with_json_attrs_bad_JSON(
hass, mqtt_mock, caplog, domain, config
):
"""Test attributes get extracted from a JSON result."""
assert await async_setup_component(hass, domain, config,)
async_fire_mqtt_message(hass, "attr-topic", "This is not JSON")
state = hass.states.get(f"{domain}.test")
assert state.attributes.get("val") is None
assert "Erroneous JSON: This is not JSON" in caplog.text
async def help_test_discovery_update_attr(
hass, mqtt_mock, caplog, domain, data1, data2
):
"""Test update of discovered MQTTAttributes."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
await async_start(hass, "homeassistant", {}, entry)
async_fire_mqtt_message(hass, f"homeassistant/{domain}/bla/config", data1)
await hass.async_block_till_done()
async_fire_mqtt_message(hass, "attr-topic1", '{ "val": "100" }')
state = hass.states.get(f"{domain}.beer")
assert state.attributes.get("val") == "100"
# Change json_attributes_topic
async_fire_mqtt_message(hass, f"homeassistant/{domain}/bla/config", data2)
await hass.async_block_till_done()
# Verify we are no longer subscribing to the old topic
async_fire_mqtt_message(hass, "attr-topic1", '{ "val": "50" }')
state = hass.states.get(f"{domain}.beer")
assert state.attributes.get("val") == "100"
# Verify we are subscribing to the new topic
async_fire_mqtt_message(hass, "attr-topic2", '{ "val": "75" }')
state = hass.states.get(f"{domain}.beer")
assert state.attributes.get("val") == "75"
async def help_test_unique_id(hass, domain, config):
"""Test unique id option only creates one alarm per unique_id."""
await async_mock_mqtt_component(hass)
assert await async_setup_component(hass, domain, config,)
async_fire_mqtt_message(hass, "test-topic", "payload")
assert len(hass.states.async_entity_ids(domain)) == 1
async def help_test_discovery_removal(hass, mqtt_mock, caplog, domain, data):
"""Test removal of discovered component."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
await async_start(hass, "homeassistant", {}, entry)
async_fire_mqtt_message(hass, f"homeassistant/{domain}/bla/config", data)
await hass.async_block_till_done()
state = hass.states.get(f"{domain}.beer")
assert state is not None
assert state.name == "Beer"
async_fire_mqtt_message(hass, f"homeassistant/{domain}/bla/config", "")
await hass.async_block_till_done()
state = hass.states.get(f"{domain}.beer")
assert state is None
async def help_test_discovery_update(hass, mqtt_mock, caplog, domain, data1, data2):
"""Test update of discovered component."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
await async_start(hass, "homeassistant", {}, entry)
async_fire_mqtt_message(hass, f"homeassistant/{domain}/bla/config", data1)
await hass.async_block_till_done()
state = hass.states.get(f"{domain}.beer")
assert state is not None
assert state.name == "Beer"
async_fire_mqtt_message(hass, f"homeassistant/{domain}/bla/config", data2)
await hass.async_block_till_done()
state = hass.states.get(f"{domain}.beer")
assert state is not None
assert state.name == "Milk"
state = hass.states.get(f"{domain}.milk")
assert state is None
async def help_test_discovery_broken(hass, mqtt_mock, caplog, domain, data1, data2):
"""Test handling of bad discovery message."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
await async_start(hass, "homeassistant", {}, entry)
async_fire_mqtt_message(hass, f"homeassistant/{domain}/bla/config", data1)
await hass.async_block_till_done()
state = hass.states.get(f"{domain}.beer")
assert state is None
async_fire_mqtt_message(hass, f"homeassistant/{domain}/bla/config", data2)
await hass.async_block_till_done()
state = hass.states.get(f"{domain}.milk")
assert state is not None
assert state.name == "Milk"
state = hass.states.get(f"{domain}.beer")
assert state is None
async def help_test_entity_device_info_with_identifier(hass, mqtt_mock, domain, data):
"""Test MQTT alarm control panel device registry integration."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
entry.add_to_hass(hass)
await async_start(hass, "homeassistant", {}, entry)
registry = await hass.helpers.device_registry.async_get_registry()
async_fire_mqtt_message(hass, f"homeassistant/{domain}/bla/config", data)
await hass.async_block_till_done()
device = registry.async_get_device({("mqtt", "helloworld")}, set())
assert device is not None
assert device.identifiers == {("mqtt", "helloworld")}
assert device.connections == {("mac", "02:5b:26:a8:dc:12")}
assert device.manufacturer == "Whatever"
assert device.name == "Beer"
assert device.model == "Glass"
assert device.sw_version == "0.1-beta"
async def help_test_entity_device_info_update(hass, mqtt_mock, domain, config):
"""Test device registry update."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
entry.add_to_hass(hass)
await async_start(hass, "homeassistant", {}, entry)
registry = await hass.helpers.device_registry.async_get_registry()
data = json.dumps(config)
async_fire_mqtt_message(hass, f"homeassistant/{domain}/bla/config", data)
await hass.async_block_till_done()
device = registry.async_get_device({("mqtt", "helloworld")}, set())
assert device is not None
assert device.name == "Beer"
config["device"]["name"] = "Milk"
data = json.dumps(config)
async_fire_mqtt_message(hass, f"homeassistant/{domain}/bla/config", data)
await hass.async_block_till_done()
device = registry.async_get_device({("mqtt", "helloworld")}, set())
assert device is not None
assert device.name == "Milk"
async def help_test_entity_id_update(hass, mqtt_mock, domain, config):
"""Test MQTT subscriptions are managed when entity_id is updated."""
registry = mock_registry(hass, {})
mock_mqtt = await async_mock_mqtt_component(hass)
assert await async_setup_component(hass, domain, config,)
state = hass.states.get(f"{domain}.beer")
assert state is not None
assert mock_mqtt.async_subscribe.call_count == 2
mock_mqtt.async_subscribe.assert_any_call("test-topic", ANY, 0, "utf-8")
mock_mqtt.async_subscribe.assert_any_call("avty-topic", ANY, 0, "utf-8")
mock_mqtt.async_subscribe.reset_mock()
registry.async_update_entity(f"{domain}.beer", new_entity_id=f"{domain}.milk")
await hass.async_block_till_done()
state = hass.states.get(f"{domain}.beer")
assert state is None
state = hass.states.get(f"{domain}.milk")
assert state is not None
assert mock_mqtt.async_subscribe.call_count == 2
mock_mqtt.async_subscribe.assert_any_call("test-topic", ANY, 0, "utf-8")
mock_mqtt.async_subscribe.assert_any_call("avty-topic", ANY, 0, "utf-8")

View File

@ -1,9 +1,7 @@
"""The tests the MQTT alarm control panel component.""" """The tests the MQTT alarm control panel component."""
import json import json
from unittest.mock import ANY
from homeassistant.components import alarm_control_panel, mqtt from homeassistant.components import alarm_control_panel
from homeassistant.components.mqtt.discovery import async_start
from homeassistant.const import ( from homeassistant.const import (
STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_AWAY,
STATE_ALARM_ARMED_HOME, STATE_ALARM_ARMED_HOME,
@ -15,13 +13,24 @@ from homeassistant.const import (
STATE_UNKNOWN, STATE_UNKNOWN,
) )
from .common import (
help_test_discovery_broken,
help_test_discovery_removal,
help_test_discovery_update,
help_test_discovery_update_attr,
help_test_entity_device_info_update,
help_test_entity_device_info_with_identifier,
help_test_entity_id_update,
help_test_setting_attribute_via_mqtt_json_message,
help_test_unique_id,
help_test_update_with_json_attrs_bad_JSON,
help_test_update_with_json_attrs_not_dict,
)
from tests.common import ( from tests.common import (
MockConfigEntry,
assert_setup_component, assert_setup_component,
async_fire_mqtt_message, async_fire_mqtt_message,
async_mock_mqtt_component,
async_setup_component, async_setup_component,
mock_registry,
) )
from tests.components.alarm_control_panel import common from tests.components.alarm_control_panel import common
@ -489,10 +498,7 @@ async def test_custom_availability_payload(hass, mqtt_mock):
async def test_setting_attribute_via_mqtt_json_message(hass, mqtt_mock): async def test_setting_attribute_via_mqtt_json_message(hass, mqtt_mock):
"""Test the setting of attribute via MQTT with JSON payload.""" """Test the setting of attribute via MQTT with JSON payload."""
assert await async_setup_component( config = {
hass,
alarm_control_panel.DOMAIN,
{
alarm_control_panel.DOMAIN: { alarm_control_panel.DOMAIN: {
"platform": "mqtt", "platform": "mqtt",
"name": "test", "name": "test",
@ -500,14 +506,11 @@ async def test_setting_attribute_via_mqtt_json_message(hass, mqtt_mock):
"state_topic": "test-topic", "state_topic": "test-topic",
"json_attributes_topic": "attr-topic", "json_attributes_topic": "attr-topic",
} }
}, }
await help_test_setting_attribute_via_mqtt_json_message(
hass, mqtt_mock, alarm_control_panel.DOMAIN, config
) )
async_fire_mqtt_message(hass, "attr-topic", '{ "val": "100" }')
state = hass.states.get("alarm_control_panel.test")
assert state.attributes.get("val") == "100"
async def test_update_state_via_state_topic_template(hass, mqtt_mock): async def test_update_state_via_state_topic_template(hass, mqtt_mock):
"""Test updating with template_value via state topic.""" """Test updating with template_value via state topic."""
@ -541,10 +544,7 @@ async def test_update_state_via_state_topic_template(hass, mqtt_mock):
async def test_update_with_json_attrs_not_dict(hass, mqtt_mock, caplog): async def test_update_with_json_attrs_not_dict(hass, mqtt_mock, caplog):
"""Test attributes get extracted from a JSON result.""" """Test attributes get extracted from a JSON result."""
assert await async_setup_component( config = {
hass,
alarm_control_panel.DOMAIN,
{
alarm_control_panel.DOMAIN: { alarm_control_panel.DOMAIN: {
"platform": "mqtt", "platform": "mqtt",
"name": "test", "name": "test",
@ -552,22 +552,15 @@ async def test_update_with_json_attrs_not_dict(hass, mqtt_mock, caplog):
"state_topic": "test-topic", "state_topic": "test-topic",
"json_attributes_topic": "attr-topic", "json_attributes_topic": "attr-topic",
} }
}, }
await help_test_update_with_json_attrs_not_dict(
hass, mqtt_mock, caplog, alarm_control_panel.DOMAIN, config
) )
async_fire_mqtt_message(hass, "attr-topic", '[ "list", "of", "things"]')
state = hass.states.get("alarm_control_panel.test")
assert state.attributes.get("val") is None
assert "JSON result was not a dictionary" in caplog.text
async def test_update_with_json_attrs_bad_JSON(hass, mqtt_mock, caplog): async def test_update_with_json_attrs_bad_JSON(hass, mqtt_mock, caplog):
"""Test attributes get extracted from a JSON result.""" """Test attributes get extracted from a JSON result."""
assert await async_setup_component( config = {
hass,
alarm_control_panel.DOMAIN,
{
alarm_control_panel.DOMAIN: { alarm_control_panel.DOMAIN: {
"platform": "mqtt", "platform": "mqtt",
"name": "test", "name": "test",
@ -575,20 +568,14 @@ async def test_update_with_json_attrs_bad_JSON(hass, mqtt_mock, caplog):
"state_topic": "test-topic", "state_topic": "test-topic",
"json_attributes_topic": "attr-topic", "json_attributes_topic": "attr-topic",
} }
}, }
await help_test_update_with_json_attrs_bad_JSON(
hass, mqtt_mock, caplog, alarm_control_panel.DOMAIN, config
) )
async_fire_mqtt_message(hass, "attr-topic", "This is not JSON")
state = hass.states.get("alarm_control_panel.test")
assert state.attributes.get("val") is None
assert "Erroneous JSON: This is not JSON" in caplog.text
async def test_discovery_update_attr(hass, mqtt_mock, caplog): async def test_discovery_update_attr(hass, mqtt_mock, caplog):
"""Test update of discovered MQTTAttributes.""" """Test update of discovered MQTTAttributes."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
await async_start(hass, "homeassistant", {}, entry)
data1 = ( data1 = (
'{ "name": "Beer",' '{ "name": "Beer",'
' "command_topic": "test_topic",' ' "command_topic": "test_topic",'
@ -599,86 +586,48 @@ async def test_discovery_update_attr(hass, mqtt_mock, caplog):
' "command_topic": "test_topic",' ' "command_topic": "test_topic",'
' "json_attributes_topic": "attr-topic2" }' ' "json_attributes_topic": "attr-topic2" }'
) )
async_fire_mqtt_message(hass, "homeassistant/alarm_control_panel/bla/config", data1) await help_test_discovery_update_attr(
await hass.async_block_till_done() hass, mqtt_mock, caplog, alarm_control_panel.DOMAIN, data1, data2
async_fire_mqtt_message(hass, "attr-topic1", '{ "val": "100" }') )
state = hass.states.get("alarm_control_panel.beer")
assert state.attributes.get("val") == "100"
# Change json_attributes_topic
async_fire_mqtt_message(hass, "homeassistant/alarm_control_panel/bla/config", data2)
await hass.async_block_till_done()
# Verify we are no longer subscribing to the old topic
async_fire_mqtt_message(hass, "attr-topic1", '{ "val": "50" }')
state = hass.states.get("alarm_control_panel.beer")
assert state.attributes.get("val") == "100"
# Verify we are subscribing to the new topic
async_fire_mqtt_message(hass, "attr-topic2", '{ "val": "75" }')
state = hass.states.get("alarm_control_panel.beer")
assert state.attributes.get("val") == "75"
async def test_unique_id(hass): async def test_unique_id(hass):
"""Test unique id option only creates one alarm per unique_id.""" """Test unique id option only creates one alarm per unique_id."""
await async_mock_mqtt_component(hass) config = {
assert await async_setup_component(
hass,
alarm_control_panel.DOMAIN,
{
alarm_control_panel.DOMAIN: [ alarm_control_panel.DOMAIN: [
{ {
"platform": "mqtt", "platform": "mqtt",
"name": "Test 1", "name": "Test 1",
"state_topic": "test-topic", "state_topic": "test-topic",
"command_topic": "test_topic", "command_topic": "command-topic",
"unique_id": "TOTALLY_UNIQUE", "unique_id": "TOTALLY_UNIQUE",
}, },
{ {
"platform": "mqtt", "platform": "mqtt",
"name": "Test 2", "name": "Test 2",
"state_topic": "test-topic", "state_topic": "test-topic",
"command_topic": "test_topic", "command_topic": "command-topic",
"unique_id": "TOTALLY_UNIQUE", "unique_id": "TOTALLY_UNIQUE",
}, },
] ]
}, }
) await help_test_unique_id(hass, alarm_control_panel.DOMAIN, config)
async_fire_mqtt_message(hass, "test-topic", "payload")
assert len(hass.states.async_entity_ids(alarm_control_panel.DOMAIN)) == 1
async def test_discovery_removal_alarm(hass, mqtt_mock, caplog): async def test_discovery_removal_alarm(hass, mqtt_mock, caplog):
"""Test removal of discovered alarm_control_panel.""" """Test removal of discovered alarm_control_panel."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
await async_start(hass, "homeassistant", {}, entry)
data = ( data = (
'{ "name": "Beer",' '{ "name": "Beer",'
' "state_topic": "test_topic",' ' "state_topic": "test_topic",'
' "command_topic": "test_topic" }' ' "command_topic": "test_topic" }'
) )
await help_test_discovery_removal(
async_fire_mqtt_message(hass, "homeassistant/alarm_control_panel/bla/config", data) hass, mqtt_mock, caplog, alarm_control_panel.DOMAIN, data
await hass.async_block_till_done() )
state = hass.states.get("alarm_control_panel.beer")
assert state is not None
assert state.name == "Beer"
async_fire_mqtt_message(hass, "homeassistant/alarm_control_panel/bla/config", "")
await hass.async_block_till_done()
state = hass.states.get("alarm_control_panel.beer")
assert state is None
async def test_discovery_update_alarm(hass, mqtt_mock, caplog): async def test_discovery_update_alarm(hass, mqtt_mock, caplog):
"""Test update of discovered alarm_control_panel.""" """Test update of discovered alarm_control_panel."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
await async_start(hass, "homeassistant", {}, entry)
data1 = ( data1 = (
'{ "name": "Beer",' '{ "name": "Beer",'
' "state_topic": "test_topic",' ' "state_topic": "test_topic",'
@ -689,66 +638,32 @@ async def test_discovery_update_alarm(hass, mqtt_mock, caplog):
' "state_topic": "test_topic",' ' "state_topic": "test_topic",'
' "command_topic": "test_topic" }' ' "command_topic": "test_topic" }'
) )
await help_test_discovery_update(
async_fire_mqtt_message(hass, "homeassistant/alarm_control_panel/bla/config", data1) hass, mqtt_mock, caplog, alarm_control_panel.DOMAIN, data1, data2
await hass.async_block_till_done() )
state = hass.states.get("alarm_control_panel.beer")
assert state is not None
assert state.name == "Beer"
async_fire_mqtt_message(hass, "homeassistant/alarm_control_panel/bla/config", data2)
await hass.async_block_till_done()
state = hass.states.get("alarm_control_panel.beer")
assert state is not None
assert state.name == "Milk"
state = hass.states.get("alarm_control_panel.milk")
assert state is None
async def test_discovery_broken(hass, mqtt_mock, caplog): async def test_discovery_broken(hass, mqtt_mock, caplog):
"""Test handling of bad discovery message.""" """Test handling of bad discovery message."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
await async_start(hass, "homeassistant", {}, entry)
data1 = '{ "name": "Beer" }' data1 = '{ "name": "Beer" }'
data2 = ( data2 = (
'{ "name": "Milk",' '{ "name": "Milk",'
' "state_topic": "test_topic",' ' "state_topic": "test_topic",'
' "command_topic": "test_topic" }' ' "command_topic": "test_topic" }'
) )
await help_test_discovery_broken(
async_fire_mqtt_message(hass, "homeassistant/alarm_control_panel/bla/config", data1) hass, mqtt_mock, caplog, alarm_control_panel.DOMAIN, data1, data2
await hass.async_block_till_done() )
state = hass.states.get("alarm_control_panel.beer")
assert state is None
async_fire_mqtt_message(hass, "homeassistant/alarm_control_panel/bla/config", data2)
await hass.async_block_till_done()
state = hass.states.get("alarm_control_panel.milk")
assert state is not None
assert state.name == "Milk"
state = hass.states.get("alarm_control_panel.beer")
assert state is None
async def test_entity_device_info_with_identifier(hass, mqtt_mock): async def test_entity_device_info_with_identifier(hass, mqtt_mock):
"""Test MQTT alarm control panel device registry integration.""" """Test MQTT alarm control panel device registry integration."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
entry.add_to_hass(hass)
await async_start(hass, "homeassistant", {}, entry)
registry = await hass.helpers.device_registry.async_get_registry()
data = json.dumps( data = json.dumps(
{ {
"platform": "mqtt", "platform": "mqtt",
"name": "Test 1", "name": "Test 1",
"state_topic": "test-topic", "state_topic": "test-topic",
"command_topic": "test-topic", "command_topic": "test-command-topic",
"device": { "device": {
"identifiers": ["helloworld"], "identifiers": ["helloworld"],
"connections": [["mac", "02:5b:26:a8:dc:12"]], "connections": [["mac", "02:5b:26:a8:dc:12"]],
@ -760,26 +675,13 @@ async def test_entity_device_info_with_identifier(hass, mqtt_mock):
"unique_id": "veryunique", "unique_id": "veryunique",
} }
) )
async_fire_mqtt_message(hass, "homeassistant/alarm_control_panel/bla/config", data) await help_test_entity_device_info_with_identifier(
await hass.async_block_till_done() hass, mqtt_mock, alarm_control_panel.DOMAIN, data
)
device = registry.async_get_device({("mqtt", "helloworld")}, set())
assert device is not None
assert device.identifiers == {("mqtt", "helloworld")}
assert device.connections == {("mac", "02:5b:26:a8:dc:12")}
assert device.manufacturer == "Whatever"
assert device.name == "Beer"
assert device.model == "Glass"
assert device.sw_version == "0.1-beta"
async def test_entity_device_info_update(hass, mqtt_mock): async def test_entity_device_info_update(hass, mqtt_mock):
"""Test device registry update.""" """Test device registry update."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
entry.add_to_hass(hass)
await async_start(hass, "homeassistant", {}, entry)
registry = await hass.helpers.device_registry.async_get_registry()
config = { config = {
"platform": "mqtt", "platform": "mqtt",
"name": "Test 1", "name": "Test 1",
@ -795,33 +697,14 @@ async def test_entity_device_info_update(hass, mqtt_mock):
}, },
"unique_id": "veryunique", "unique_id": "veryunique",
} }
await help_test_entity_device_info_update(
data = json.dumps(config) hass, mqtt_mock, alarm_control_panel.DOMAIN, config
async_fire_mqtt_message(hass, "homeassistant/alarm_control_panel/bla/config", data) )
await hass.async_block_till_done()
device = registry.async_get_device({("mqtt", "helloworld")}, set())
assert device is not None
assert device.name == "Beer"
config["device"]["name"] = "Milk"
data = json.dumps(config)
async_fire_mqtt_message(hass, "homeassistant/alarm_control_panel/bla/config", data)
await hass.async_block_till_done()
device = registry.async_get_device({("mqtt", "helloworld")}, set())
assert device is not None
assert device.name == "Milk"
async def test_entity_id_update(hass, mqtt_mock): async def test_entity_id_update(hass, mqtt_mock):
"""Test MQTT subscriptions are managed when entity_id is updated.""" """Test MQTT subscriptions are managed when entity_id is updated."""
registry = mock_registry(hass, {}) config = {
mock_mqtt = await async_mock_mqtt_component(hass)
assert await async_setup_component(
hass,
alarm_control_panel.DOMAIN,
{
alarm_control_panel.DOMAIN: [ alarm_control_panel.DOMAIN: [
{ {
"platform": "mqtt", "platform": "mqtt",
@ -832,26 +715,7 @@ async def test_entity_id_update(hass, mqtt_mock):
"unique_id": "TOTALLY_UNIQUE", "unique_id": "TOTALLY_UNIQUE",
} }
] ]
}, }
await help_test_entity_id_update(
hass, mqtt_mock, alarm_control_panel.DOMAIN, config
) )
state = hass.states.get("alarm_control_panel.beer")
assert state is not None
assert mock_mqtt.async_subscribe.call_count == 2
mock_mqtt.async_subscribe.assert_any_call("test-topic", ANY, 0, "utf-8")
mock_mqtt.async_subscribe.assert_any_call("avty-topic", ANY, 0, "utf-8")
mock_mqtt.async_subscribe.reset_mock()
registry.async_update_entity(
"alarm_control_panel.beer", new_entity_id="alarm_control_panel.milk"
)
await hass.async_block_till_done()
state = hass.states.get("alarm_control_panel.beer")
assert state is None
state = hass.states.get("alarm_control_panel.milk")
assert state is not None
assert mock_mqtt.async_subscribe.call_count == 2
mock_mqtt.async_subscribe.assert_any_call("test-topic", ANY, 0, "utf-8")
mock_mqtt.async_subscribe.assert_any_call("avty-topic", ANY, 0, "utf-8")

View File

@ -1,10 +1,9 @@
"""The tests for the MQTT binary sensor platform.""" """The tests for the MQTT binary sensor platform."""
from datetime import datetime, timedelta from datetime import datetime, timedelta
import json import json
from unittest.mock import ANY, patch from unittest.mock import patch
from homeassistant.components import binary_sensor, mqtt from homeassistant.components import binary_sensor
from homeassistant.components.mqtt.discovery import async_start
from homeassistant.const import ( from homeassistant.const import (
EVENT_STATE_CHANGED, EVENT_STATE_CHANGED,
STATE_OFF, STATE_OFF,
@ -15,14 +14,22 @@ import homeassistant.core as ha
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
import homeassistant.util.dt as dt_util import homeassistant.util.dt as dt_util
from tests.common import ( from .common import (
MockConfigEntry, help_test_discovery_broken,
async_fire_mqtt_message, help_test_discovery_removal,
async_fire_time_changed, help_test_discovery_update,
async_mock_mqtt_component, help_test_discovery_update_attr,
mock_registry, help_test_entity_device_info_update,
help_test_entity_device_info_with_identifier,
help_test_entity_id_update,
help_test_setting_attribute_via_mqtt_json_message,
help_test_unique_id,
help_test_update_with_json_attrs_bad_JSON,
help_test_update_with_json_attrs_not_dict,
) )
from tests.common import async_fire_mqtt_message, async_fire_time_changed
async def test_setting_sensor_value_expires_availability_topic(hass, mqtt_mock, caplog): async def test_setting_sensor_value_expires_availability_topic(hass, mqtt_mock, caplog):
"""Test the expiration of the value.""" """Test the expiration of the value."""
@ -417,73 +424,51 @@ async def test_off_delay(hass, mqtt_mock):
async def test_setting_attribute_via_mqtt_json_message(hass, mqtt_mock): async def test_setting_attribute_via_mqtt_json_message(hass, mqtt_mock):
"""Test the setting of attribute via MQTT with JSON payload.""" """Test the setting of attribute via MQTT with JSON payload."""
assert await async_setup_component( config = {
hass,
binary_sensor.DOMAIN,
{
binary_sensor.DOMAIN: { binary_sensor.DOMAIN: {
"platform": "mqtt", "platform": "mqtt",
"name": "test", "name": "test",
"state_topic": "test-topic", "state_topic": "test-topic",
"json_attributes_topic": "attr-topic", "json_attributes_topic": "attr-topic",
} }
}, }
await help_test_setting_attribute_via_mqtt_json_message(
hass, mqtt_mock, binary_sensor.DOMAIN, config
) )
async_fire_mqtt_message(hass, "attr-topic", '{ "val": "100" }')
state = hass.states.get("binary_sensor.test")
assert state.attributes.get("val") == "100"
async def test_update_with_json_attrs_not_dict(hass, mqtt_mock, caplog): async def test_update_with_json_attrs_not_dict(hass, mqtt_mock, caplog):
"""Test attributes get extracted from a JSON result.""" """Test attributes get extracted from a JSON result."""
assert await async_setup_component( config = {
hass,
binary_sensor.DOMAIN,
{
binary_sensor.DOMAIN: { binary_sensor.DOMAIN: {
"platform": "mqtt", "platform": "mqtt",
"name": "test", "name": "test",
"state_topic": "test-topic", "state_topic": "test-topic",
"json_attributes_topic": "attr-topic", "json_attributes_topic": "attr-topic",
} }
}, }
await help_test_update_with_json_attrs_not_dict(
hass, mqtt_mock, caplog, binary_sensor.DOMAIN, config
) )
async_fire_mqtt_message(hass, "attr-topic", '[ "list", "of", "things"]')
state = hass.states.get("binary_sensor.test")
assert state.attributes.get("val") is None
assert "JSON result was not a dictionary" in caplog.text
async def test_update_with_json_attrs_bad_JSON(hass, mqtt_mock, caplog): async def test_update_with_json_attrs_bad_JSON(hass, mqtt_mock, caplog):
"""Test attributes get extracted from a JSON result.""" """Test attributes get extracted from a JSON result."""
assert await async_setup_component( config = {
hass,
binary_sensor.DOMAIN,
{
binary_sensor.DOMAIN: { binary_sensor.DOMAIN: {
"platform": "mqtt", "platform": "mqtt",
"name": "test", "name": "test",
"state_topic": "test-topic", "state_topic": "test-topic",
"json_attributes_topic": "attr-topic", "json_attributes_topic": "attr-topic",
} }
}, }
await help_test_update_with_json_attrs_bad_JSON(
hass, mqtt_mock, caplog, binary_sensor.DOMAIN, config
) )
async_fire_mqtt_message(hass, "attr-topic", "This is not JSON")
state = hass.states.get("binary_sensor.test")
assert state.attributes.get("val") is None
assert "Erroneous JSON: This is not JSON" in caplog.text
async def test_discovery_update_attr(hass, mqtt_mock, caplog): async def test_discovery_update_attr(hass, mqtt_mock, caplog):
"""Test update of discovered MQTTAttributes.""" """Test update of discovered MQTTAttributes."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
await async_start(hass, "homeassistant", {}, entry)
data1 = ( data1 = (
'{ "name": "Beer",' '{ "name": "Beer",'
' "state_topic": "test_topic",' ' "state_topic": "test_topic",'
@ -494,34 +479,14 @@ async def test_discovery_update_attr(hass, mqtt_mock, caplog):
' "state_topic": "test_topic",' ' "state_topic": "test_topic",'
' "json_attributes_topic": "attr-topic2" }' ' "json_attributes_topic": "attr-topic2" }'
) )
async_fire_mqtt_message(hass, "homeassistant/binary_sensor/bla/config", data1) await help_test_discovery_update_attr(
await hass.async_block_till_done() hass, mqtt_mock, caplog, binary_sensor.DOMAIN, data1, data2
async_fire_mqtt_message(hass, "attr-topic1", '{ "val": "100" }') )
state = hass.states.get("binary_sensor.beer")
assert state.attributes.get("val") == "100"
# Change json_attributes_topic
async_fire_mqtt_message(hass, "homeassistant/binary_sensor/bla/config", data2)
await hass.async_block_till_done()
# Verify we are no longer subscribing to the old topic
async_fire_mqtt_message(hass, "attr-topic1", '{ "val": "50" }')
state = hass.states.get("binary_sensor.beer")
assert state.attributes.get("val") == "100"
# Verify we are subscribing to the new topic
async_fire_mqtt_message(hass, "attr-topic2", '{ "val": "75" }')
state = hass.states.get("binary_sensor.beer")
assert state.attributes.get("val") == "75"
async def test_unique_id(hass): async def test_unique_id(hass):
"""Test unique id option only creates one sensor per unique_id.""" """Test unique id option only creates one sensor per unique_id."""
await async_mock_mqtt_component(hass) config = {
assert await async_setup_component(
hass,
binary_sensor.DOMAIN,
{
binary_sensor.DOMAIN: [ binary_sensor.DOMAIN: [
{ {
"platform": "mqtt", "platform": "mqtt",
@ -536,36 +501,24 @@ async def test_unique_id(hass):
"unique_id": "TOTALLY_UNIQUE", "unique_id": "TOTALLY_UNIQUE",
}, },
] ]
}, }
) await help_test_unique_id(hass, binary_sensor.DOMAIN, config)
async_fire_mqtt_message(hass, "test-topic", "payload")
assert len(hass.states.async_all()) == 1
async def test_discovery_removal_binary_sensor(hass, mqtt_mock, caplog): async def test_discovery_removal_binary_sensor(hass, mqtt_mock, caplog):
"""Test removal of discovered binary_sensor.""" """Test removal of discovered binary_sensor."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
await async_start(hass, "homeassistant", {}, entry)
data = ( data = (
'{ "name": "Beer",' '{ "name": "Beer",'
' "state_topic": "test_topic",' ' "state_topic": "test_topic",'
' "availability_topic": "availability_topic" }' ' "availability_topic": "availability_topic" }'
) )
async_fire_mqtt_message(hass, "homeassistant/binary_sensor/bla/config", data) await help_test_discovery_removal(
await hass.async_block_till_done() hass, mqtt_mock, caplog, binary_sensor.DOMAIN, data
state = hass.states.get("binary_sensor.beer") )
assert state is not None
assert state.name == "Beer"
async_fire_mqtt_message(hass, "homeassistant/binary_sensor/bla/config", "")
await hass.async_block_till_done()
state = hass.states.get("binary_sensor.beer")
assert state is None
async def test_discovery_update_binary_sensor(hass, mqtt_mock, caplog): async def test_discovery_update_binary_sensor(hass, mqtt_mock, caplog):
"""Test update of discovered binary_sensor.""" """Test update of discovered binary_sensor."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
await async_start(hass, "homeassistant", {}, entry)
data1 = ( data1 = (
'{ "name": "Beer",' '{ "name": "Beer",'
' "state_topic": "test_topic",' ' "state_topic": "test_topic",'
@ -576,52 +529,22 @@ async def test_discovery_update_binary_sensor(hass, mqtt_mock, caplog):
' "state_topic": "test_topic2",' ' "state_topic": "test_topic2",'
' "availability_topic": "availability_topic2" }' ' "availability_topic": "availability_topic2" }'
) )
async_fire_mqtt_message(hass, "homeassistant/binary_sensor/bla/config", data1) await help_test_discovery_update(
await hass.async_block_till_done() hass, mqtt_mock, caplog, binary_sensor.DOMAIN, data1, data2
state = hass.states.get("binary_sensor.beer") )
assert state is not None
assert state.name == "Beer"
async_fire_mqtt_message(hass, "homeassistant/binary_sensor/bla/config", data2)
await hass.async_block_till_done()
state = hass.states.get("binary_sensor.beer")
assert state is not None
assert state.name == "Milk"
state = hass.states.get("binary_sensor.milk")
assert state is None
async def test_discovery_broken(hass, mqtt_mock, caplog): async def test_discovery_broken(hass, mqtt_mock, caplog):
"""Test handling of bad discovery message.""" """Test handling of bad discovery message."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
await async_start(hass, "homeassistant", {}, entry)
data1 = '{ "name": "Beer",' ' "off_delay": -1 }' data1 = '{ "name": "Beer",' ' "off_delay": -1 }'
data2 = '{ "name": "Milk",' ' "state_topic": "test_topic" }' data2 = '{ "name": "Milk",' ' "state_topic": "test_topic" }'
await help_test_discovery_broken(
async_fire_mqtt_message(hass, "homeassistant/binary_sensor/bla/config", data1) hass, mqtt_mock, caplog, binary_sensor.DOMAIN, data1, data2
await hass.async_block_till_done() )
state = hass.states.get("binary_sensor.beer")
assert state is None
async_fire_mqtt_message(hass, "homeassistant/binary_sensor/bla/config", data2)
await hass.async_block_till_done()
state = hass.states.get("binary_sensor.milk")
assert state is not None
assert state.name == "Milk"
state = hass.states.get("binary_sensor.beer")
assert state is None
async def test_entity_device_info_with_identifier(hass, mqtt_mock): async def test_entity_device_info_with_identifier(hass, mqtt_mock):
"""Test MQTT binary sensor device registry integration.""" """Test MQTT binary sensor device registry integration."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
entry.add_to_hass(hass)
await async_start(hass, "homeassistant", {}, entry)
registry = await hass.helpers.device_registry.async_get_registry()
data = json.dumps( data = json.dumps(
{ {
"platform": "mqtt", "platform": "mqtt",
@ -638,26 +561,13 @@ async def test_entity_device_info_with_identifier(hass, mqtt_mock):
"unique_id": "veryunique", "unique_id": "veryunique",
} }
) )
async_fire_mqtt_message(hass, "homeassistant/binary_sensor/bla/config", data) await help_test_entity_device_info_with_identifier(
await hass.async_block_till_done() hass, mqtt_mock, binary_sensor.DOMAIN, data
)
device = registry.async_get_device({("mqtt", "helloworld")}, set())
assert device is not None
assert device.identifiers == {("mqtt", "helloworld")}
assert device.connections == {("mac", "02:5b:26:a8:dc:12")}
assert device.manufacturer == "Whatever"
assert device.name == "Beer"
assert device.model == "Glass"
assert device.sw_version == "0.1-beta"
async def test_entity_device_info_update(hass, mqtt_mock): async def test_entity_device_info_update(hass, mqtt_mock):
"""Test device registry update.""" """Test device registry update."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
entry.add_to_hass(hass)
await async_start(hass, "homeassistant", {}, entry)
registry = await hass.helpers.device_registry.async_get_registry()
config = { config = {
"platform": "mqtt", "platform": "mqtt",
"name": "Test 1", "name": "Test 1",
@ -672,33 +582,14 @@ async def test_entity_device_info_update(hass, mqtt_mock):
}, },
"unique_id": "veryunique", "unique_id": "veryunique",
} }
await help_test_entity_device_info_update(
data = json.dumps(config) hass, mqtt_mock, binary_sensor.DOMAIN, config
async_fire_mqtt_message(hass, "homeassistant/binary_sensor/bla/config", data) )
await hass.async_block_till_done()
device = registry.async_get_device({("mqtt", "helloworld")}, set())
assert device is not None
assert device.name == "Beer"
config["device"]["name"] = "Milk"
data = json.dumps(config)
async_fire_mqtt_message(hass, "homeassistant/binary_sensor/bla/config", data)
await hass.async_block_till_done()
device = registry.async_get_device({("mqtt", "helloworld")}, set())
assert device is not None
assert device.name == "Milk"
async def test_entity_id_update(hass, mqtt_mock): async def test_entity_id_update(hass, mqtt_mock):
"""Test MQTT subscriptions are managed when entity_id is updated.""" """Test MQTT subscriptions are managed when entity_id is updated."""
registry = mock_registry(hass, {}) config = {
mock_mqtt = await async_mock_mqtt_component(hass)
assert await async_setup_component(
hass,
binary_sensor.DOMAIN,
{
binary_sensor.DOMAIN: [ binary_sensor.DOMAIN: [
{ {
"platform": "mqtt", "platform": "mqtt",
@ -708,26 +599,5 @@ async def test_entity_id_update(hass, mqtt_mock):
"unique_id": "TOTALLY_UNIQUE", "unique_id": "TOTALLY_UNIQUE",
} }
] ]
}, }
) await help_test_entity_id_update(hass, mqtt_mock, binary_sensor.DOMAIN, config)
state = hass.states.get("binary_sensor.beer")
assert state is not None
assert mock_mqtt.async_subscribe.call_count == 2
mock_mqtt.async_subscribe.assert_any_call("test-topic", ANY, 0, "utf-8")
mock_mqtt.async_subscribe.assert_any_call("avty-topic", ANY, 0, "utf-8")
mock_mqtt.async_subscribe.reset_mock()
registry.async_update_entity(
"binary_sensor.beer", new_entity_id="binary_sensor.milk"
)
await hass.async_block_till_done()
state = hass.states.get("binary_sensor.beer")
assert state is None
state = hass.states.get("binary_sensor.milk")
assert state is not None
assert mock_mqtt.async_subscribe.call_count == 2
mock_mqtt.async_subscribe.assert_any_call("test-topic", ANY, 0, "utf-8")
mock_mqtt.async_subscribe.assert_any_call("avty-topic", ANY, 0, "utf-8")

View File

@ -2,12 +2,10 @@
import copy import copy
import json import json
import unittest import unittest
from unittest.mock import ANY
import pytest import pytest
import voluptuous as vol import voluptuous as vol
from homeassistant.components import mqtt
from homeassistant.components.climate import DEFAULT_MAX_TEMP, DEFAULT_MIN_TEMP from homeassistant.components.climate import DEFAULT_MAX_TEMP, DEFAULT_MIN_TEMP
from homeassistant.components.climate.const import ( from homeassistant.components.climate.const import (
DOMAIN as CLIMATE_DOMAIN, DOMAIN as CLIMATE_DOMAIN,
@ -25,16 +23,23 @@ from homeassistant.components.climate.const import (
SUPPORT_TARGET_TEMPERATURE, SUPPORT_TARGET_TEMPERATURE,
SUPPORT_TARGET_TEMPERATURE_RANGE, SUPPORT_TARGET_TEMPERATURE_RANGE,
) )
from homeassistant.components.mqtt.discovery import async_start
from homeassistant.const import STATE_OFF, STATE_UNAVAILABLE from homeassistant.const import STATE_OFF, STATE_UNAVAILABLE
from tests.common import ( from .common import (
MockConfigEntry, help_test_discovery_broken,
async_fire_mqtt_message, help_test_discovery_removal,
async_mock_mqtt_component, help_test_discovery_update,
async_setup_component, help_test_discovery_update_attr,
mock_registry, help_test_entity_device_info_update,
help_test_entity_device_info_with_identifier,
help_test_entity_id_update,
help_test_setting_attribute_via_mqtt_json_message,
help_test_unique_id,
help_test_update_with_json_attrs_bad_JSON,
help_test_update_with_json_attrs_not_dict,
) )
from tests.common import async_fire_mqtt_message, async_setup_component
from tests.components.climate import common from tests.components.climate import common
ENTITY_CLIMATE = "climate.test" ENTITY_CLIMATE = "climate.test"
@ -768,10 +773,7 @@ async def test_temp_step_custom(hass, mqtt_mock):
async def test_setting_attribute_via_mqtt_json_message(hass, mqtt_mock): async def test_setting_attribute_via_mqtt_json_message(hass, mqtt_mock):
"""Test the setting of attribute via MQTT with JSON payload.""" """Test the setting of attribute via MQTT with JSON payload."""
assert await async_setup_component( config = {
hass,
CLIMATE_DOMAIN,
{
CLIMATE_DOMAIN: { CLIMATE_DOMAIN: {
"platform": "mqtt", "platform": "mqtt",
"name": "test", "name": "test",
@ -779,21 +781,15 @@ async def test_setting_attribute_via_mqtt_json_message(hass, mqtt_mock):
"power_command_topic": "test_topic", "power_command_topic": "test_topic",
"json_attributes_topic": "attr-topic", "json_attributes_topic": "attr-topic",
} }
}, }
await help_test_setting_attribute_via_mqtt_json_message(
hass, mqtt_mock, CLIMATE_DOMAIN, config
) )
async_fire_mqtt_message(hass, "attr-topic", '{ "val": "100" }')
state = hass.states.get("climate.test")
assert state.attributes.get("val") == "100"
async def test_update_with_json_attrs_not_dict(hass, mqtt_mock, caplog): async def test_update_with_json_attrs_not_dict(hass, mqtt_mock, caplog):
"""Test attributes get extracted from a JSON result.""" """Test attributes get extracted from a JSON result."""
assert await async_setup_component( config = {
hass,
CLIMATE_DOMAIN,
{
CLIMATE_DOMAIN: { CLIMATE_DOMAIN: {
"platform": "mqtt", "platform": "mqtt",
"name": "test", "name": "test",
@ -801,22 +797,15 @@ async def test_update_with_json_attrs_not_dict(hass, mqtt_mock, caplog):
"power_command_topic": "test_topic", "power_command_topic": "test_topic",
"json_attributes_topic": "attr-topic", "json_attributes_topic": "attr-topic",
} }
}, }
await help_test_update_with_json_attrs_not_dict(
hass, mqtt_mock, caplog, CLIMATE_DOMAIN, config
) )
async_fire_mqtt_message(hass, "attr-topic", '[ "list", "of", "things"]')
state = hass.states.get("climate.test")
assert state.attributes.get("val") is None
assert "JSON result was not a dictionary" in caplog.text
async def test_update_with_json_attrs_bad_JSON(hass, mqtt_mock, caplog): async def test_update_with_json_attrs_bad_JSON(hass, mqtt_mock, caplog):
"""Test attributes get extracted from a JSON result.""" """Test attributes get extracted from a JSON result."""
assert await async_setup_component( config = {
hass,
CLIMATE_DOMAIN,
{
CLIMATE_DOMAIN: { CLIMATE_DOMAIN: {
"platform": "mqtt", "platform": "mqtt",
"name": "test", "name": "test",
@ -824,20 +813,14 @@ async def test_update_with_json_attrs_bad_JSON(hass, mqtt_mock, caplog):
"power_command_topic": "test_topic", "power_command_topic": "test_topic",
"json_attributes_topic": "attr-topic", "json_attributes_topic": "attr-topic",
} }
}, }
await help_test_update_with_json_attrs_bad_JSON(
hass, mqtt_mock, caplog, CLIMATE_DOMAIN, config
) )
async_fire_mqtt_message(hass, "attr-topic", "This is not JSON")
state = hass.states.get("climate.test")
assert state.attributes.get("val") is None
assert "Erroneous JSON: This is not JSON" in caplog.text
async def test_discovery_update_attr(hass, mqtt_mock, caplog): async def test_discovery_update_attr(hass, mqtt_mock, caplog):
"""Test update of discovered MQTTAttributes.""" """Test update of discovered MQTTAttributes."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
await async_start(hass, "homeassistant", {}, entry)
data1 = ( data1 = (
'{ "name": "Beer",' '{ "name": "Beer",'
' "power_state_topic": "test-topic",' ' "power_state_topic": "test-topic",'
@ -850,34 +833,14 @@ async def test_discovery_update_attr(hass, mqtt_mock, caplog):
' "power_command_topic": "test_topic",' ' "power_command_topic": "test_topic",'
' "json_attributes_topic": "attr-topic2" }' ' "json_attributes_topic": "attr-topic2" }'
) )
async_fire_mqtt_message(hass, "homeassistant/climate/bla/config", data1) await help_test_discovery_update_attr(
await hass.async_block_till_done() hass, mqtt_mock, caplog, CLIMATE_DOMAIN, data1, data2
async_fire_mqtt_message(hass, "attr-topic1", '{ "val": "100" }') )
state = hass.states.get("climate.beer")
assert state.attributes.get("val") == "100"
# Change json_attributes_topic
async_fire_mqtt_message(hass, "homeassistant/climate/bla/config", data2)
await hass.async_block_till_done()
# Verify we are no longer subscribing to the old topic
async_fire_mqtt_message(hass, "attr-topic1", '{ "val": "50" }')
state = hass.states.get("climate.beer")
assert state.attributes.get("val") == "100"
# Verify we are subscribing to the new topic
async_fire_mqtt_message(hass, "attr-topic2", '{ "val": "75" }')
state = hass.states.get("climate.beer")
assert state.attributes.get("val") == "75"
async def test_unique_id(hass): async def test_unique_id(hass):
"""Test unique id option only creates one climate per unique_id.""" """Test unique id option only creates one climate per unique_id."""
await async_mock_mqtt_component(hass) config = {
assert await async_setup_component(
hass,
CLIMATE_DOMAIN,
{
CLIMATE_DOMAIN: [ CLIMATE_DOMAIN: [
{ {
"platform": "mqtt", "platform": "mqtt",
@ -894,83 +857,36 @@ async def test_unique_id(hass):
"unique_id": "TOTALLY_UNIQUE", "unique_id": "TOTALLY_UNIQUE",
}, },
] ]
}, }
) await help_test_unique_id(hass, CLIMATE_DOMAIN, config)
async_fire_mqtt_message(hass, "test-topic", "payload")
assert len(hass.states.async_entity_ids(CLIMATE_DOMAIN)) == 1
async def test_discovery_removal_climate(hass, mqtt_mock, caplog): async def test_discovery_removal_climate(hass, mqtt_mock, caplog):
"""Test removal of discovered climate.""" """Test removal of discovered climate."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
await async_start(hass, "homeassistant", {}, entry)
data = '{ "name": "Beer" }' data = '{ "name": "Beer" }'
async_fire_mqtt_message(hass, "homeassistant/climate/bla/config", data) await help_test_discovery_removal(hass, mqtt_mock, caplog, CLIMATE_DOMAIN, data)
await hass.async_block_till_done()
state = hass.states.get("climate.beer")
assert state is not None
assert state.name == "Beer"
async_fire_mqtt_message(hass, "homeassistant/climate/bla/config", "")
await hass.async_block_till_done()
state = hass.states.get("climate.beer")
assert state is None
async def test_discovery_update_climate(hass, mqtt_mock, caplog): async def test_discovery_update_climate(hass, mqtt_mock, caplog):
"""Test update of discovered climate.""" """Test update of discovered climate."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
await async_start(hass, "homeassistant", {}, entry)
data1 = '{ "name": "Beer" }' data1 = '{ "name": "Beer" }'
data2 = '{ "name": "Milk" }' data2 = '{ "name": "Milk" }'
async_fire_mqtt_message(hass, "homeassistant/climate/bla/config", data1) await help_test_discovery_update(
await hass.async_block_till_done() hass, mqtt_mock, caplog, CLIMATE_DOMAIN, data1, data2
)
state = hass.states.get("climate.beer")
assert state is not None
assert state.name == "Beer"
async_fire_mqtt_message(hass, "homeassistant/climate/bla/config", data2)
await hass.async_block_till_done()
state = hass.states.get("climate.beer")
assert state is not None
assert state.name == "Milk"
state = hass.states.get("climate.milk")
assert state is None
async def test_discovery_broken(hass, mqtt_mock, caplog): async def test_discovery_broken(hass, mqtt_mock, caplog):
"""Test handling of bad discovery message.""" """Test handling of bad discovery message."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
await async_start(hass, "homeassistant", {}, entry)
data1 = '{ "name": "Beer",' ' "power_command_topic": "test_topic#" }' data1 = '{ "name": "Beer",' ' "power_command_topic": "test_topic#" }'
data2 = '{ "name": "Milk", ' ' "power_command_topic": "test_topic" }' data2 = '{ "name": "Milk", ' ' "power_command_topic": "test_topic" }'
await help_test_discovery_broken(
async_fire_mqtt_message(hass, "homeassistant/climate/bla/config", data1) hass, mqtt_mock, caplog, CLIMATE_DOMAIN, data1, data2
await hass.async_block_till_done() )
state = hass.states.get("climate.beer")
assert state is None
async_fire_mqtt_message(hass, "homeassistant/climate/bla/config", data2)
await hass.async_block_till_done()
state = hass.states.get("climate.milk")
assert state is not None
assert state.name == "Milk"
state = hass.states.get("climate.beer")
assert state is None
async def test_entity_device_info_with_identifier(hass, mqtt_mock): async def test_entity_device_info_with_identifier(hass, mqtt_mock):
"""Test MQTT climate device registry integration.""" """Test MQTT climate device registry integration."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
entry.add_to_hass(hass)
await async_start(hass, "homeassistant", {}, entry)
registry = await hass.helpers.device_registry.async_get_registry()
data = json.dumps( data = json.dumps(
{ {
"platform": "mqtt", "platform": "mqtt",
@ -986,26 +902,13 @@ async def test_entity_device_info_with_identifier(hass, mqtt_mock):
"unique_id": "veryunique", "unique_id": "veryunique",
} }
) )
async_fire_mqtt_message(hass, "homeassistant/climate/bla/config", data) await help_test_entity_device_info_with_identifier(
await hass.async_block_till_done() hass, mqtt_mock, CLIMATE_DOMAIN, data
)
device = registry.async_get_device({("mqtt", "helloworld")}, set())
assert device is not None
assert device.identifiers == {("mqtt", "helloworld")}
assert device.connections == {("mac", "02:5b:26:a8:dc:12")}
assert device.manufacturer == "Whatever"
assert device.name == "Beer"
assert device.model == "Glass"
assert device.sw_version == "0.1-beta"
async def test_entity_device_info_update(hass, mqtt_mock): async def test_entity_device_info_update(hass, mqtt_mock):
"""Test device registry update.""" """Test device registry update."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
entry.add_to_hass(hass)
await async_start(hass, "homeassistant", {}, entry)
registry = await hass.helpers.device_registry.async_get_registry()
config = { config = {
"platform": "mqtt", "platform": "mqtt",
"name": "Test 1", "name": "Test 1",
@ -1021,33 +924,12 @@ async def test_entity_device_info_update(hass, mqtt_mock):
}, },
"unique_id": "veryunique", "unique_id": "veryunique",
} }
await help_test_entity_device_info_update(hass, mqtt_mock, CLIMATE_DOMAIN, config)
data = json.dumps(config)
async_fire_mqtt_message(hass, "homeassistant/climate/bla/config", data)
await hass.async_block_till_done()
device = registry.async_get_device({("mqtt", "helloworld")}, set())
assert device is not None
assert device.name == "Beer"
config["device"]["name"] = "Milk"
data = json.dumps(config)
async_fire_mqtt_message(hass, "homeassistant/climate/bla/config", data)
await hass.async_block_till_done()
device = registry.async_get_device({("mqtt", "helloworld")}, set())
assert device is not None
assert device.name == "Milk"
async def test_entity_id_update(hass, mqtt_mock): async def test_entity_id_update(hass, mqtt_mock):
"""Test MQTT subscriptions are managed when entity_id is updated.""" """Test MQTT subscriptions are managed when entity_id is updated."""
registry = mock_registry(hass, {}) config = {
mock_mqtt = await async_mock_mqtt_component(hass)
assert await async_setup_component(
hass,
CLIMATE_DOMAIN,
{
CLIMATE_DOMAIN: [ CLIMATE_DOMAIN: [
{ {
"platform": "mqtt", "platform": "mqtt",
@ -1057,27 +939,8 @@ async def test_entity_id_update(hass, mqtt_mock):
"unique_id": "TOTALLY_UNIQUE", "unique_id": "TOTALLY_UNIQUE",
} }
] ]
}, }
) await help_test_entity_id_update(hass, mqtt_mock, CLIMATE_DOMAIN, config)
state = hass.states.get("climate.beer")
assert state is not None
assert mock_mqtt.async_subscribe.call_count == 2
mock_mqtt.async_subscribe.assert_any_call("test-topic", ANY, 0, "utf-8")
mock_mqtt.async_subscribe.assert_any_call("avty-topic", ANY, 0, "utf-8")
mock_mqtt.async_subscribe.reset_mock()
registry.async_update_entity("climate.beer", new_entity_id="climate.milk")
await hass.async_block_till_done()
state = hass.states.get("climate.beer")
assert state is None
state = hass.states.get("climate.milk")
assert state is not None
assert mock_mqtt.async_subscribe.call_count == 2
mock_mqtt.async_subscribe.assert_any_call("test-topic", ANY, 0, "utf-8")
mock_mqtt.async_subscribe.assert_any_call("avty-topic", ANY, 0, "utf-8")
async def test_precision_default(hass, mqtt_mock): async def test_precision_default(hass, mqtt_mock):

View File

@ -1,11 +1,9 @@
"""The tests for the MQTT cover platform.""" """The tests for the MQTT cover platform."""
import json import json
from unittest.mock import ANY
from homeassistant.components import cover, mqtt from homeassistant.components import cover
from homeassistant.components.cover import ATTR_POSITION, ATTR_TILT_POSITION from homeassistant.components.cover import ATTR_POSITION, ATTR_TILT_POSITION
from homeassistant.components.mqtt.cover import MqttCover from homeassistant.components.mqtt.cover import MqttCover
from homeassistant.components.mqtt.discovery import async_start
from homeassistant.const import ( from homeassistant.const import (
ATTR_ASSUMED_STATE, ATTR_ASSUMED_STATE,
ATTR_ENTITY_ID, ATTR_ENTITY_ID,
@ -27,13 +25,22 @@ from homeassistant.const import (
) )
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
from tests.common import ( from .common import (
MockConfigEntry, help_test_discovery_broken,
async_fire_mqtt_message, help_test_discovery_removal,
async_mock_mqtt_component, help_test_discovery_update,
mock_registry, help_test_discovery_update_attr,
help_test_entity_device_info_update,
help_test_entity_device_info_with_identifier,
help_test_entity_id_update,
help_test_setting_attribute_via_mqtt_json_message,
help_test_unique_id,
help_test_update_with_json_attrs_bad_JSON,
help_test_update_with_json_attrs_not_dict,
) )
from tests.common import async_fire_mqtt_message
async def test_state_via_state_topic(hass, mqtt_mock): async def test_state_via_state_topic(hass, mqtt_mock):
"""Test the controlling state via topic.""" """Test the controlling state via topic."""
@ -1693,73 +1700,51 @@ async def test_invalid_device_class(hass, mqtt_mock):
async def test_setting_attribute_via_mqtt_json_message(hass, mqtt_mock): async def test_setting_attribute_via_mqtt_json_message(hass, mqtt_mock):
"""Test the setting of attribute via MQTT with JSON payload.""" """Test the setting of attribute via MQTT with JSON payload."""
assert await async_setup_component( config = {
hass,
cover.DOMAIN,
{
cover.DOMAIN: { cover.DOMAIN: {
"platform": "mqtt", "platform": "mqtt",
"name": "test", "name": "test",
"state_topic": "test-topic", "state_topic": "test-topic",
"json_attributes_topic": "attr-topic", "json_attributes_topic": "attr-topic",
} }
}, }
await help_test_setting_attribute_via_mqtt_json_message(
hass, mqtt_mock, cover.DOMAIN, config
) )
async_fire_mqtt_message(hass, "attr-topic", '{ "val": "100" }')
state = hass.states.get("cover.test")
assert state.attributes.get("val") == "100"
async def test_update_with_json_attrs_not_dict(hass, mqtt_mock, caplog): async def test_update_with_json_attrs_not_dict(hass, mqtt_mock, caplog):
"""Test attributes get extracted from a JSON result.""" """Test attributes get extracted from a JSON result."""
assert await async_setup_component( config = {
hass,
cover.DOMAIN,
{
cover.DOMAIN: { cover.DOMAIN: {
"platform": "mqtt", "platform": "mqtt",
"name": "test", "name": "test",
"state_topic": "test-topic", "state_topic": "test-topic",
"json_attributes_topic": "attr-topic", "json_attributes_topic": "attr-topic",
} }
}, }
await help_test_update_with_json_attrs_not_dict(
hass, mqtt_mock, caplog, cover.DOMAIN, config
) )
async_fire_mqtt_message(hass, "attr-topic", '[ "list", "of", "things"]')
state = hass.states.get("cover.test")
assert state.attributes.get("val") is None
assert "JSON result was not a dictionary" in caplog.text
async def test_update_with_json_attrs_bad_JSON(hass, mqtt_mock, caplog): async def test_update_with_json_attrs_bad_JSON(hass, mqtt_mock, caplog):
"""Test attributes get extracted from a JSON result.""" """Test attributes get extracted from a JSON result."""
assert await async_setup_component( config = {
hass,
cover.DOMAIN,
{
cover.DOMAIN: { cover.DOMAIN: {
"platform": "mqtt", "platform": "mqtt",
"name": "test", "name": "test",
"state_topic": "test-topic", "state_topic": "test-topic",
"json_attributes_topic": "attr-topic", "json_attributes_topic": "attr-topic",
} }
}, }
await help_test_update_with_json_attrs_bad_JSON(
hass, mqtt_mock, caplog, cover.DOMAIN, config
) )
async_fire_mqtt_message(hass, "attr-topic", "This is not JSON")
state = hass.states.get("cover.test")
assert state.attributes.get("val") is None
assert "Erroneous JSON: This is not JSON" in caplog.text
async def test_discovery_update_attr(hass, mqtt_mock, caplog): async def test_discovery_update_attr(hass, mqtt_mock, caplog):
"""Test update of discovered MQTTAttributes.""" """Test update of discovered MQTTAttributes."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
await async_start(hass, "homeassistant", {}, entry)
data1 = ( data1 = (
'{ "name": "Beer",' '{ "name": "Beer",'
' "command_topic": "test_topic",' ' "command_topic": "test_topic",'
@ -1770,97 +1755,14 @@ async def test_discovery_update_attr(hass, mqtt_mock, caplog):
' "command_topic": "test_topic",' ' "command_topic": "test_topic",'
' "json_attributes_topic": "attr-topic2" }' ' "json_attributes_topic": "attr-topic2" }'
) )
async_fire_mqtt_message(hass, "homeassistant/cover/bla/config", data1) await help_test_discovery_update_attr(
await hass.async_block_till_done() hass, mqtt_mock, caplog, cover.DOMAIN, data1, data2
async_fire_mqtt_message(hass, "attr-topic1", '{ "val": "100" }') )
state = hass.states.get("cover.beer")
assert state.attributes.get("val") == "100"
# Change json_attributes_topic
async_fire_mqtt_message(hass, "homeassistant/cover/bla/config", data2)
await hass.async_block_till_done()
# Verify we are no longer subscribing to the old topic
async_fire_mqtt_message(hass, "attr-topic1", '{ "val": "50" }')
state = hass.states.get("cover.beer")
assert state.attributes.get("val") == "100"
# Verify we are subscribing to the new topic
async_fire_mqtt_message(hass, "attr-topic2", '{ "val": "75" }')
state = hass.states.get("cover.beer")
assert state.attributes.get("val") == "75"
async def test_discovery_removal_cover(hass, mqtt_mock, caplog):
"""Test removal of discovered cover."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
await async_start(hass, "homeassistant", {}, entry)
data = '{ "name": "Beer",' ' "command_topic": "test_topic" }'
async_fire_mqtt_message(hass, "homeassistant/cover/bla/config", data)
await hass.async_block_till_done()
state = hass.states.get("cover.beer")
assert state is not None
assert state.name == "Beer"
async_fire_mqtt_message(hass, "homeassistant/cover/bla/config", "")
await hass.async_block_till_done()
state = hass.states.get("cover.beer")
assert state is None
async def test_discovery_update_cover(hass, mqtt_mock, caplog):
"""Test update of discovered cover."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
await async_start(hass, "homeassistant", {}, entry)
data1 = '{ "name": "Beer",' ' "command_topic": "test_topic" }'
data2 = '{ "name": "Milk",' ' "command_topic": "test_topic" }'
async_fire_mqtt_message(hass, "homeassistant/cover/bla/config", data1)
await hass.async_block_till_done()
state = hass.states.get("cover.beer")
assert state is not None
assert state.name == "Beer"
async_fire_mqtt_message(hass, "homeassistant/cover/bla/config", data2)
await hass.async_block_till_done()
state = hass.states.get("cover.beer")
assert state is not None
assert state.name == "Milk"
state = hass.states.get("cover.milk")
assert state is None
async def test_discovery_broken(hass, mqtt_mock, caplog):
"""Test handling of bad discovery message."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
await async_start(hass, "homeassistant", {}, entry)
data1 = '{ "name": "Beer",' ' "command_topic": "test_topic#" }'
data2 = '{ "name": "Milk",' ' "command_topic": "test_topic" }'
async_fire_mqtt_message(hass, "homeassistant/cover/bla/config", data1)
await hass.async_block_till_done()
state = hass.states.get("cover.beer")
assert state is None
async_fire_mqtt_message(hass, "homeassistant/cover/bla/config", data2)
await hass.async_block_till_done()
state = hass.states.get("cover.milk")
assert state is not None
assert state.name == "Milk"
state = hass.states.get("cover.beer")
assert state is None
async def test_unique_id(hass): async def test_unique_id(hass):
"""Test unique_id option only creates one cover per id.""" """Test unique_id option only creates one cover per id."""
await async_mock_mqtt_component(hass) config = {
assert await async_setup_component(
hass,
cover.DOMAIN,
{
cover.DOMAIN: [ cover.DOMAIN: [
{ {
"platform": "mqtt", "platform": "mqtt",
@ -1875,21 +1777,36 @@ async def test_unique_id(hass):
"unique_id": "TOTALLY_UNIQUE", "unique_id": "TOTALLY_UNIQUE",
}, },
] ]
}, }
await help_test_unique_id(hass, cover.DOMAIN, config)
async def test_discovery_removal_cover(hass, mqtt_mock, caplog):
"""Test removal of discovered cover."""
data = '{ "name": "Beer",' ' "command_topic": "test_topic" }'
await help_test_discovery_removal(hass, mqtt_mock, caplog, cover.DOMAIN, data)
async def test_discovery_update_cover(hass, mqtt_mock, caplog):
"""Test update of discovered cover."""
data1 = '{ "name": "Beer",' ' "command_topic": "test_topic" }'
data2 = '{ "name": "Milk",' ' "command_topic": "test_topic" }'
await help_test_discovery_update(
hass, mqtt_mock, caplog, cover.DOMAIN, data1, data2
) )
async_fire_mqtt_message(hass, "test-topic", "payload")
assert len(hass.states.async_entity_ids(cover.DOMAIN)) == 1 async def test_discovery_broken(hass, mqtt_mock, caplog):
"""Test handling of bad discovery message."""
data1 = '{ "name": "Beer",' ' "command_topic": "test_topic#" }'
data2 = '{ "name": "Milk",' ' "command_topic": "test_topic" }'
await help_test_discovery_broken(
hass, mqtt_mock, caplog, cover.DOMAIN, data1, data2
)
async def test_entity_device_info_with_identifier(hass, mqtt_mock): async def test_entity_device_info_with_identifier(hass, mqtt_mock):
"""Test MQTT cover device registry integration.""" """Test MQTT cover device registry integration."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
entry.add_to_hass(hass)
await async_start(hass, "homeassistant", {}, entry)
registry = await hass.helpers.device_registry.async_get_registry()
data = json.dumps( data = json.dumps(
{ {
"platform": "mqtt", "platform": "mqtt",
@ -1907,26 +1824,13 @@ async def test_entity_device_info_with_identifier(hass, mqtt_mock):
"unique_id": "veryunique", "unique_id": "veryunique",
} }
) )
async_fire_mqtt_message(hass, "homeassistant/cover/bla/config", data) await help_test_entity_device_info_with_identifier(
await hass.async_block_till_done() hass, mqtt_mock, cover.DOMAIN, data
)
device = registry.async_get_device({("mqtt", "helloworld")}, set())
assert device is not None
assert device.identifiers == {("mqtt", "helloworld")}
assert device.connections == {("mac", "02:5b:26:a8:dc:12")}
assert device.manufacturer == "Whatever"
assert device.name == "Beer"
assert device.model == "Glass"
assert device.sw_version == "0.1-beta"
async def test_entity_device_info_update(hass, mqtt_mock): async def test_entity_device_info_update(hass, mqtt_mock):
"""Test device registry update.""" """Test device registry update."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
entry.add_to_hass(hass)
await async_start(hass, "homeassistant", {}, entry)
registry = await hass.helpers.device_registry.async_get_registry()
config = { config = {
"platform": "mqtt", "platform": "mqtt",
"name": "Test 1", "name": "Test 1",
@ -1942,33 +1846,12 @@ async def test_entity_device_info_update(hass, mqtt_mock):
}, },
"unique_id": "veryunique", "unique_id": "veryunique",
} }
await help_test_entity_device_info_update(hass, mqtt_mock, cover.DOMAIN, config)
data = json.dumps(config)
async_fire_mqtt_message(hass, "homeassistant/cover/bla/config", data)
await hass.async_block_till_done()
device = registry.async_get_device({("mqtt", "helloworld")}, set())
assert device is not None
assert device.name == "Beer"
config["device"]["name"] = "Milk"
data = json.dumps(config)
async_fire_mqtt_message(hass, "homeassistant/cover/bla/config", data)
await hass.async_block_till_done()
device = registry.async_get_device({("mqtt", "helloworld")}, set())
assert device is not None
assert device.name == "Milk"
async def test_entity_id_update(hass, mqtt_mock): async def test_entity_id_update(hass, mqtt_mock):
"""Test MQTT subscriptions are managed when entity_id is updated.""" """Test MQTT subscriptions are managed when entity_id is updated."""
registry = mock_registry(hass, {}) config = {
mock_mqtt = await async_mock_mqtt_component(hass)
assert await async_setup_component(
hass,
cover.DOMAIN,
{
cover.DOMAIN: [ cover.DOMAIN: [
{ {
"platform": "mqtt", "platform": "mqtt",
@ -1978,24 +1861,5 @@ async def test_entity_id_update(hass, mqtt_mock):
"unique_id": "TOTALLY_UNIQUE", "unique_id": "TOTALLY_UNIQUE",
} }
] ]
}, }
) await help_test_entity_id_update(hass, mqtt_mock, cover.DOMAIN, config)
state = hass.states.get("cover.beer")
assert state is not None
assert mock_mqtt.async_subscribe.call_count == 2
mock_mqtt.async_subscribe.assert_any_call("test-topic", ANY, 0, "utf-8")
mock_mqtt.async_subscribe.assert_any_call("avty-topic", ANY, 0, "utf-8")
mock_mqtt.async_subscribe.reset_mock()
registry.async_update_entity("cover.beer", new_entity_id="cover.milk")
await hass.async_block_till_done()
state = hass.states.get("cover.beer")
assert state is None
state = hass.states.get("cover.milk")
assert state is not None
assert mock_mqtt.async_subscribe.call_count == 2
mock_mqtt.async_subscribe.assert_any_call("test-topic", ANY, 0, "utf-8")
mock_mqtt.async_subscribe.assert_any_call("avty-topic", ANY, 0, "utf-8")

View File

@ -1,9 +1,7 @@
"""Test MQTT fans.""" """Test MQTT fans."""
import json import json
from unittest.mock import ANY
from homeassistant.components import fan, mqtt from homeassistant.components import fan
from homeassistant.components.mqtt.discovery import async_start
from homeassistant.const import ( from homeassistant.const import (
ATTR_ASSUMED_STATE, ATTR_ASSUMED_STATE,
STATE_OFF, STATE_OFF,
@ -12,12 +10,21 @@ from homeassistant.const import (
) )
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
from tests.common import ( from .common import (
MockConfigEntry, help_test_discovery_broken,
async_fire_mqtt_message, help_test_discovery_removal,
async_mock_mqtt_component, help_test_discovery_update,
mock_registry, help_test_discovery_update_attr,
help_test_entity_device_info_update,
help_test_entity_device_info_with_identifier,
help_test_entity_id_update,
help_test_setting_attribute_via_mqtt_json_message,
help_test_unique_id,
help_test_update_with_json_attrs_bad_JSON,
help_test_update_with_json_attrs_not_dict,
) )
from tests.common import async_fire_mqtt_message
from tests.components.fan import common from tests.components.fan import common
@ -438,138 +445,53 @@ async def test_custom_availability_payload(hass, mqtt_mock):
assert state.state is not STATE_UNAVAILABLE assert state.state is not STATE_UNAVAILABLE
async def test_discovery_removal_fan(hass, mqtt_mock, caplog):
"""Test removal of discovered fan."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
await async_start(hass, "homeassistant", {}, entry)
data = '{ "name": "Beer",' ' "command_topic": "test_topic" }'
async_fire_mqtt_message(hass, "homeassistant/fan/bla/config", data)
await hass.async_block_till_done()
state = hass.states.get("fan.beer")
assert state is not None
assert state.name == "Beer"
async_fire_mqtt_message(hass, "homeassistant/fan/bla/config", "")
await hass.async_block_till_done()
state = hass.states.get("fan.beer")
assert state is None
async def test_discovery_update_fan(hass, mqtt_mock, caplog):
"""Test update of discovered fan."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
await async_start(hass, "homeassistant", {}, entry)
data1 = '{ "name": "Beer",' ' "command_topic": "test_topic" }'
data2 = '{ "name": "Milk",' ' "command_topic": "test_topic" }'
async_fire_mqtt_message(hass, "homeassistant/fan/bla/config", data1)
await hass.async_block_till_done()
state = hass.states.get("fan.beer")
assert state is not None
assert state.name == "Beer"
async_fire_mqtt_message(hass, "homeassistant/fan/bla/config", data2)
await hass.async_block_till_done()
state = hass.states.get("fan.beer")
assert state is not None
assert state.name == "Milk"
state = hass.states.get("fan.milk")
assert state is None
async def test_discovery_broken(hass, mqtt_mock, caplog):
"""Test handling of bad discovery message."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
await async_start(hass, "homeassistant", {}, entry)
data1 = '{ "name": "Beer" }'
data2 = '{ "name": "Milk",' ' "command_topic": "test_topic" }'
async_fire_mqtt_message(hass, "homeassistant/fan/bla/config", data1)
await hass.async_block_till_done()
state = hass.states.get("fan.beer")
assert state is None
async_fire_mqtt_message(hass, "homeassistant/fan/bla/config", data2)
await hass.async_block_till_done()
state = hass.states.get("fan.milk")
assert state is not None
assert state.name == "Milk"
state = hass.states.get("fan.beer")
assert state is None
async def test_setting_attribute_via_mqtt_json_message(hass, mqtt_mock): async def test_setting_attribute_via_mqtt_json_message(hass, mqtt_mock):
"""Test the setting of attribute via MQTT with JSON payload.""" """Test the setting of attribute via MQTT with JSON payload."""
assert await async_setup_component( config = {
hass,
fan.DOMAIN,
{
fan.DOMAIN: { fan.DOMAIN: {
"platform": "mqtt", "platform": "mqtt",
"name": "test", "name": "test",
"command_topic": "test-topic", "command_topic": "test-topic",
"json_attributes_topic": "attr-topic", "json_attributes_topic": "attr-topic",
} }
}, }
await help_test_setting_attribute_via_mqtt_json_message(
hass, mqtt_mock, fan.DOMAIN, config
) )
async_fire_mqtt_message(hass, "attr-topic", '{ "val": "100" }')
state = hass.states.get("fan.test")
assert state.attributes.get("val") == "100"
async def test_update_with_json_attrs_not_dict(hass, mqtt_mock, caplog): async def test_update_with_json_attrs_not_dict(hass, mqtt_mock, caplog):
"""Test attributes get extracted from a JSON result.""" """Test attributes get extracted from a JSON result."""
assert await async_setup_component( config = {
hass,
fan.DOMAIN,
{
fan.DOMAIN: { fan.DOMAIN: {
"platform": "mqtt", "platform": "mqtt",
"name": "test", "name": "test",
"command_topic": "test-topic", "command_topic": "test-topic",
"json_attributes_topic": "attr-topic", "json_attributes_topic": "attr-topic",
} }
}, }
await help_test_update_with_json_attrs_not_dict(
hass, mqtt_mock, caplog, fan.DOMAIN, config
) )
async_fire_mqtt_message(hass, "attr-topic", '[ "list", "of", "things"]')
state = hass.states.get("fan.test")
assert state.attributes.get("val") is None
assert "JSON result was not a dictionary" in caplog.text
async def test_update_with_json_attrs_bad_JSON(hass, mqtt_mock, caplog): async def test_update_with_json_attrs_bad_JSON(hass, mqtt_mock, caplog):
"""Test attributes get extracted from a JSON result.""" """Test attributes get extracted from a JSON result."""
assert await async_setup_component( config = {
hass,
fan.DOMAIN,
{
fan.DOMAIN: { fan.DOMAIN: {
"platform": "mqtt", "platform": "mqtt",
"name": "test", "name": "test",
"command_topic": "test-topic", "command_topic": "test-topic",
"json_attributes_topic": "attr-topic", "json_attributes_topic": "attr-topic",
} }
}, }
await help_test_update_with_json_attrs_bad_JSON(
hass, mqtt_mock, caplog, fan.DOMAIN, config
) )
async_fire_mqtt_message(hass, "attr-topic", "This is not JSON")
state = hass.states.get("fan.test")
assert state.attributes.get("val") is None
assert "Erroneous JSON: This is not JSON" in caplog.text
async def test_discovery_update_attr(hass, mqtt_mock, caplog): async def test_discovery_update_attr(hass, mqtt_mock, caplog):
"""Test update of discovered MQTTAttributes.""" """Test update of discovered MQTTAttributes."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
await async_start(hass, "homeassistant", {}, entry)
data1 = ( data1 = (
'{ "name": "Beer",' '{ "name": "Beer",'
' "command_topic": "test_topic",' ' "command_topic": "test_topic",'
@ -580,65 +502,56 @@ async def test_discovery_update_attr(hass, mqtt_mock, caplog):
' "command_topic": "test_topic",' ' "command_topic": "test_topic",'
' "json_attributes_topic": "attr-topic2" }' ' "json_attributes_topic": "attr-topic2" }'
) )
async_fire_mqtt_message(hass, "homeassistant/fan/bla/config", data1) await help_test_discovery_update_attr(
await hass.async_block_till_done() hass, mqtt_mock, caplog, fan.DOMAIN, data1, data2
async_fire_mqtt_message(hass, "attr-topic1", '{ "val": "100" }') )
state = hass.states.get("fan.beer")
assert state.attributes.get("val") == "100"
# Change json_attributes_topic
async_fire_mqtt_message(hass, "homeassistant/fan/bla/config", data2)
await hass.async_block_till_done()
# Verify we are no longer subscribing to the old topic
async_fire_mqtt_message(hass, "attr-topic1", '{ "val": "50" }')
state = hass.states.get("fan.beer")
assert state.attributes.get("val") == "100"
# Verify we are subscribing to the new topic
async_fire_mqtt_message(hass, "attr-topic2", '{ "val": "75" }')
state = hass.states.get("fan.beer")
assert state.attributes.get("val") == "75"
async def test_unique_id(hass): async def test_unique_id(hass):
"""Test unique_id option only creates one fan per id.""" """Test unique_id option only creates one fan per id."""
await async_mock_mqtt_component(hass) config = {
assert await async_setup_component(
hass,
fan.DOMAIN,
{
fan.DOMAIN: [ fan.DOMAIN: [
{ {
"platform": "mqtt", "platform": "mqtt",
"name": "Test 1", "name": "Test 1",
"state_topic": "test-topic", "state_topic": "test-topic",
"command_topic": "test-topic", "command_topic": "test_topic",
"unique_id": "TOTALLY_UNIQUE", "unique_id": "TOTALLY_UNIQUE",
}, },
{ {
"platform": "mqtt", "platform": "mqtt",
"name": "Test 2", "name": "Test 2",
"state_topic": "test-topic", "state_topic": "test-topic",
"command_topic": "test-topic", "command_topic": "test_topic",
"unique_id": "TOTALLY_UNIQUE", "unique_id": "TOTALLY_UNIQUE",
}, },
] ]
}, }
) await help_test_unique_id(hass, fan.DOMAIN, config)
async_fire_mqtt_message(hass, "test-topic", "payload")
assert len(hass.states.async_entity_ids(fan.DOMAIN)) == 1 async def test_discovery_removal_fan(hass, mqtt_mock, caplog):
"""Test removal of discovered fan."""
data = '{ "name": "Beer",' ' "command_topic": "test_topic" }'
await help_test_discovery_removal(hass, mqtt_mock, caplog, fan.DOMAIN, data)
async def test_discovery_update_fan(hass, mqtt_mock, caplog):
"""Test update of discovered fan."""
data1 = '{ "name": "Beer",' ' "command_topic": "test_topic" }'
data2 = '{ "name": "Milk",' ' "command_topic": "test_topic" }'
await help_test_discovery_update(hass, mqtt_mock, caplog, fan.DOMAIN, data1, data2)
async def test_discovery_broken(hass, mqtt_mock, caplog):
"""Test handling of bad discovery message."""
data1 = '{ "name": "Beer" }'
data2 = '{ "name": "Milk",' ' "command_topic": "test_topic" }'
await help_test_discovery_broken(hass, mqtt_mock, caplog, fan.DOMAIN, data1, data2)
async def test_entity_device_info_with_identifier(hass, mqtt_mock): async def test_entity_device_info_with_identifier(hass, mqtt_mock):
"""Test MQTT fan device registry integration.""" """Test MQTT fan device registry integration."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
entry.add_to_hass(hass)
await async_start(hass, "homeassistant", {}, entry)
registry = await hass.helpers.device_registry.async_get_registry()
data = json.dumps( data = json.dumps(
{ {
"platform": "mqtt", "platform": "mqtt",
@ -656,26 +569,13 @@ async def test_entity_device_info_with_identifier(hass, mqtt_mock):
"unique_id": "veryunique", "unique_id": "veryunique",
} }
) )
async_fire_mqtt_message(hass, "homeassistant/fan/bla/config", data) await help_test_entity_device_info_with_identifier(
await hass.async_block_till_done() hass, mqtt_mock, fan.DOMAIN, data
)
device = registry.async_get_device({("mqtt", "helloworld")}, set())
assert device is not None
assert device.identifiers == {("mqtt", "helloworld")}
assert device.connections == {("mac", "02:5b:26:a8:dc:12")}
assert device.manufacturer == "Whatever"
assert device.name == "Beer"
assert device.model == "Glass"
assert device.sw_version == "0.1-beta"
async def test_entity_device_info_update(hass, mqtt_mock): async def test_entity_device_info_update(hass, mqtt_mock):
"""Test device registry update.""" """Test device registry update."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
entry.add_to_hass(hass)
await async_start(hass, "homeassistant", {}, entry)
registry = await hass.helpers.device_registry.async_get_registry()
config = { config = {
"platform": "mqtt", "platform": "mqtt",
"name": "Test 1", "name": "Test 1",
@ -691,33 +591,12 @@ async def test_entity_device_info_update(hass, mqtt_mock):
}, },
"unique_id": "veryunique", "unique_id": "veryunique",
} }
await help_test_entity_device_info_update(hass, mqtt_mock, fan.DOMAIN, config)
data = json.dumps(config)
async_fire_mqtt_message(hass, "homeassistant/fan/bla/config", data)
await hass.async_block_till_done()
device = registry.async_get_device({("mqtt", "helloworld")}, set())
assert device is not None
assert device.name == "Beer"
config["device"]["name"] = "Milk"
data = json.dumps(config)
async_fire_mqtt_message(hass, "homeassistant/fan/bla/config", data)
await hass.async_block_till_done()
device = registry.async_get_device({("mqtt", "helloworld")}, set())
assert device is not None
assert device.name == "Milk"
async def test_entity_id_update(hass, mqtt_mock): async def test_entity_id_update(hass, mqtt_mock):
"""Test MQTT subscriptions are managed when entity_id is updated.""" """Test MQTT subscriptions are managed when entity_id is updated."""
registry = mock_registry(hass, {}) config = {
mock_mqtt = await async_mock_mqtt_component(hass)
assert await async_setup_component(
hass,
fan.DOMAIN,
{
fan.DOMAIN: [ fan.DOMAIN: [
{ {
"platform": "mqtt", "platform": "mqtt",
@ -728,24 +607,5 @@ async def test_entity_id_update(hass, mqtt_mock):
"unique_id": "TOTALLY_UNIQUE", "unique_id": "TOTALLY_UNIQUE",
} }
] ]
}, }
) await help_test_entity_id_update(hass, mqtt_mock, fan.DOMAIN, config)
state = hass.states.get("fan.beer")
assert state is not None
assert mock_mqtt.async_subscribe.call_count == 2
mock_mqtt.async_subscribe.assert_any_call("test-topic", ANY, 0, "utf-8")
mock_mqtt.async_subscribe.assert_any_call("avty-topic", ANY, 0, "utf-8")
mock_mqtt.async_subscribe.reset_mock()
registry.async_update_entity("fan.beer", new_entity_id="fan.milk")
await hass.async_block_till_done()
state = hass.states.get("fan.beer")
assert state is None
state = hass.states.get("fan.milk")
assert state is not None
assert mock_mqtt.async_subscribe.call_count == 2
mock_mqtt.async_subscribe.assert_any_call("test-topic", ANY, 0, "utf-8")
mock_mqtt.async_subscribe.assert_any_call("avty-topic", ANY, 0, "utf-8")

View File

@ -2,9 +2,8 @@
from copy import deepcopy from copy import deepcopy
import json import json
from homeassistant.components import mqtt, vacuum from homeassistant.components import vacuum
from homeassistant.components.mqtt import CONF_COMMAND_TOPIC from homeassistant.components.mqtt import CONF_COMMAND_TOPIC
from homeassistant.components.mqtt.discovery import async_start
from homeassistant.components.mqtt.vacuum import schema_legacy as mqttvacuum from homeassistant.components.mqtt.vacuum import schema_legacy as mqttvacuum
from homeassistant.components.mqtt.vacuum.schema import services_to_strings from homeassistant.components.mqtt.vacuum.schema import services_to_strings
from homeassistant.components.mqtt.vacuum.schema_legacy import ( from homeassistant.components.mqtt.vacuum.schema_legacy import (
@ -26,11 +25,21 @@ from homeassistant.const import (
) )
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
from tests.common import ( from .common import (
MockConfigEntry, help_test_discovery_broken,
async_fire_mqtt_message, help_test_discovery_removal,
async_mock_mqtt_component, help_test_discovery_update,
help_test_discovery_update_attr,
help_test_entity_device_info_update,
help_test_entity_device_info_with_identifier,
help_test_entity_id_update,
help_test_setting_attribute_via_mqtt_json_message,
help_test_unique_id,
help_test_update_with_json_attrs_bad_JSON,
help_test_update_with_json_attrs_not_dict,
) )
from tests.common import async_fire_mqtt_message
from tests.components.vacuum import common from tests.components.vacuum import common
DEFAULT_CONFIG = { DEFAULT_CONFIG = {
@ -514,142 +523,50 @@ async def test_custom_availability_payload(hass, mqtt_mock):
assert state.state == STATE_UNAVAILABLE assert state.state == STATE_UNAVAILABLE
async def test_discovery_removal_vacuum(hass, mqtt_mock):
"""Test removal of discovered vacuum."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
await async_start(hass, "homeassistant", {}, entry)
data = '{ "name": "Beer",' ' "command_topic": "test_topic" }'
async_fire_mqtt_message(hass, "homeassistant/vacuum/bla/config", data)
await hass.async_block_till_done()
state = hass.states.get("vacuum.beer")
assert state is not None
assert state.name == "Beer"
async_fire_mqtt_message(hass, "homeassistant/vacuum/bla/config", "")
await hass.async_block_till_done()
state = hass.states.get("vacuum.beer")
assert state is None
async def test_discovery_broken(hass, mqtt_mock, caplog):
"""Test handling of bad discovery message."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
await async_start(hass, "homeassistant", {}, entry)
data1 = '{ "name": "Beer",' ' "command_topic": "test_topic#" }'
data2 = '{ "name": "Milk",' ' "command_topic": "test_topic" }'
async_fire_mqtt_message(hass, "homeassistant/vacuum/bla/config", data1)
await hass.async_block_till_done()
state = hass.states.get("vacuum.beer")
assert state is None
async_fire_mqtt_message(hass, "homeassistant/vacuum/bla/config", data2)
await hass.async_block_till_done()
state = hass.states.get("vacuum.milk")
assert state is not None
assert state.name == "Milk"
state = hass.states.get("vacuum.beer")
assert state is None
async def test_discovery_update_vacuum(hass, mqtt_mock):
"""Test update of discovered vacuum."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
await async_start(hass, "homeassistant", {}, entry)
data1 = '{ "name": "Beer",' ' "command_topic": "test_topic" }'
data2 = '{ "name": "Milk",' ' "command_topic": "test_topic" }'
async_fire_mqtt_message(hass, "homeassistant/vacuum/bla/config", data1)
await hass.async_block_till_done()
state = hass.states.get("vacuum.beer")
assert state is not None
assert state.name == "Beer"
async_fire_mqtt_message(hass, "homeassistant/vacuum/bla/config", data2)
await hass.async_block_till_done()
state = hass.states.get("vacuum.beer")
assert state is not None
assert state.name == "Milk"
state = hass.states.get("vacuum.milk")
assert state is None
async def test_setting_attribute_via_mqtt_json_message(hass, mqtt_mock): async def test_setting_attribute_via_mqtt_json_message(hass, mqtt_mock):
"""Test the setting of attribute via MQTT with JSON payload.""" """Test the setting of attribute via MQTT with JSON payload."""
assert await async_setup_component( config = {
hass,
vacuum.DOMAIN,
{
vacuum.DOMAIN: { vacuum.DOMAIN: {
"platform": "mqtt", "platform": "mqtt",
"name": "test", "name": "test",
"json_attributes_topic": "attr-topic", "json_attributes_topic": "attr-topic",
} }
}, }
await help_test_setting_attribute_via_mqtt_json_message(
hass, mqtt_mock, vacuum.DOMAIN, config
) )
async_fire_mqtt_message(hass, "attr-topic", '{ "val": "100" }')
state = hass.states.get("vacuum.test")
assert state.attributes.get("val") == "100"
async def test_update_with_json_attrs_not_dict(hass, mqtt_mock, caplog): async def test_update_with_json_attrs_not_dict(hass, mqtt_mock, caplog):
"""Test attributes get extracted from a JSON result.""" """Test attributes get extracted from a JSON result."""
assert await async_setup_component( config = {
hass,
vacuum.DOMAIN,
{
vacuum.DOMAIN: { vacuum.DOMAIN: {
"platform": "mqtt", "platform": "mqtt",
"name": "test", "name": "test",
"json_attributes_topic": "attr-topic", "json_attributes_topic": "attr-topic",
} }
}, }
await help_test_update_with_json_attrs_not_dict(
hass, mqtt_mock, caplog, vacuum.DOMAIN, config
) )
async_fire_mqtt_message(hass, "attr-topic", '[ "list", "of", "things"]')
state = hass.states.get("vacuum.test")
assert state.attributes.get("val") is None async def test_update_with_json_attrs_bad_JSON(hass, mqtt_mock, caplog):
assert "JSON result was not a dictionary" in caplog.text
async def test_update_with_json_attrs_bad_json(hass, mqtt_mock, caplog):
"""Test attributes get extracted from a JSON result.""" """Test attributes get extracted from a JSON result."""
assert await async_setup_component( config = {
hass,
vacuum.DOMAIN,
{
vacuum.DOMAIN: { vacuum.DOMAIN: {
"platform": "mqtt", "platform": "mqtt",
"name": "test", "name": "test",
"json_attributes_topic": "attr-topic", "json_attributes_topic": "attr-topic",
} }
}, }
await help_test_update_with_json_attrs_bad_JSON(
hass, mqtt_mock, caplog, vacuum.DOMAIN, config
) )
async_fire_mqtt_message(hass, "attr-topic", "This is not JSON")
state = hass.states.get("vacuum.test")
assert state.attributes.get("val") is None
assert "Erroneous JSON: This is not JSON" in caplog.text
async def test_discovery_update_attr(hass, mqtt_mock, caplog): async def test_discovery_update_attr(hass, mqtt_mock, caplog):
"""Test update of discovered MQTTAttributes.""" """Test update of discovered MQTTAttributes."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
await async_start(hass, "homeassistant", {}, entry)
data1 = ( data1 = (
'{ "name": "Beer",' '{ "name": "Beer",'
' "command_topic": "test_topic",' ' "command_topic": "test_topic",'
@ -660,63 +577,58 @@ async def test_discovery_update_attr(hass, mqtt_mock, caplog):
' "command_topic": "test_topic",' ' "command_topic": "test_topic",'
' "json_attributes_topic": "attr-topic2" }' ' "json_attributes_topic": "attr-topic2" }'
) )
async_fire_mqtt_message(hass, "homeassistant/vacuum/bla/config", data1) await help_test_discovery_update_attr(
await hass.async_block_till_done() hass, mqtt_mock, caplog, vacuum.DOMAIN, data1, data2
async_fire_mqtt_message(hass, "attr-topic1", '{ "val": "100" }') )
state = hass.states.get("vacuum.beer")
assert state.attributes.get("val") == "100"
# Change json_attributes_topic
async_fire_mqtt_message(hass, "homeassistant/vacuum/bla/config", data2)
await hass.async_block_till_done()
# Verify we are no longer subscribing to the old topic
async_fire_mqtt_message(hass, "attr-topic1", '{ "val": "50" }')
state = hass.states.get("vacuum.beer")
assert state.attributes.get("val") == "100"
# Verify we are subscribing to the new topic
async_fire_mqtt_message(hass, "attr-topic2", '{ "val": "75" }')
state = hass.states.get("vacuum.beer")
assert state.attributes.get("val") == "75"
async def test_unique_id(hass, mqtt_mock): async def test_unique_id(hass, mqtt_mock):
"""Test unique id option only creates one vacuum per unique_id.""" """Test unique id option only creates one vacuum per unique_id."""
await async_mock_mqtt_component(hass) config = {
assert await async_setup_component(
hass,
vacuum.DOMAIN,
{
vacuum.DOMAIN: [ vacuum.DOMAIN: [
{ {
"platform": "mqtt", "platform": "mqtt",
"name": "Test 1", "name": "Test 1",
"command_topic": "command-topic", "command_topic": "test_topic",
"unique_id": "TOTALLY_UNIQUE", "unique_id": "TOTALLY_UNIQUE",
}, },
{ {
"platform": "mqtt", "platform": "mqtt",
"name": "Test 2", "name": "Test 2",
"command_topic": "command-topic", "command_topic": "test_topic",
"unique_id": "TOTALLY_UNIQUE", "unique_id": "TOTALLY_UNIQUE",
}, },
] ]
}, }
await help_test_unique_id(hass, vacuum.DOMAIN, config)
async def test_discovery_removal_vacuum(hass, mqtt_mock, caplog):
"""Test removal of discovered vacuum."""
data = '{ "name": "Beer",' ' "command_topic": "test_topic" }'
await help_test_discovery_removal(hass, mqtt_mock, caplog, vacuum.DOMAIN, data)
async def test_discovery_update_vacuum(hass, mqtt_mock, caplog):
"""Test update of discovered vacuum."""
data1 = '{ "name": "Beer",' ' "command_topic": "test_topic" }'
data2 = '{ "name": "Milk",' ' "command_topic": "test_topic" }'
await help_test_discovery_update(
hass, mqtt_mock, caplog, vacuum.DOMAIN, data1, data2
) )
async_fire_mqtt_message(hass, "test-topic", "payload")
assert len(hass.states.async_entity_ids()) == 1 async def test_discovery_broken(hass, mqtt_mock, caplog):
"""Test handling of bad discovery message."""
data1 = '{ "name": "Beer",' ' "command_topic": "test_topic#" }'
data2 = '{ "name": "Milk",' ' "command_topic": "test_topic" }'
await help_test_discovery_broken(
hass, mqtt_mock, caplog, vacuum.DOMAIN, data1, data2
)
async def test_entity_device_info_with_identifier(hass, mqtt_mock): async def test_entity_device_info_with_identifier(hass, mqtt_mock):
"""Test MQTT vacuum device registry integration.""" """Test MQTT vacuum device registry integration."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
entry.add_to_hass(hass)
await async_start(hass, "homeassistant", {}, entry)
registry = await hass.helpers.device_registry.async_get_registry()
data = json.dumps( data = json.dumps(
{ {
"platform": "mqtt", "platform": "mqtt",
@ -733,26 +645,13 @@ async def test_entity_device_info_with_identifier(hass, mqtt_mock):
"unique_id": "veryunique", "unique_id": "veryunique",
} }
) )
async_fire_mqtt_message(hass, "homeassistant/vacuum/bla/config", data) await help_test_entity_device_info_with_identifier(
await hass.async_block_till_done() hass, mqtt_mock, vacuum.DOMAIN, data
)
device = registry.async_get_device({("mqtt", "helloworld")}, set())
assert device is not None
assert device.identifiers == {("mqtt", "helloworld")}
assert device.connections == {("mac", "02:5b:26:a8:dc:12")}
assert device.manufacturer == "Whatever"
assert device.name == "Beer"
assert device.model == "Glass"
assert device.sw_version == "0.1-beta"
async def test_entity_device_info_update(hass, mqtt_mock): async def test_entity_device_info_update(hass, mqtt_mock):
"""Test device registry update.""" """Test device registry update."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
entry.add_to_hass(hass)
await async_start(hass, "homeassistant", {}, entry)
registry = await hass.helpers.device_registry.async_get_registry()
config = { config = {
"platform": "mqtt", "platform": "mqtt",
"name": "Test 1", "name": "Test 1",
@ -767,20 +666,22 @@ async def test_entity_device_info_update(hass, mqtt_mock):
}, },
"unique_id": "veryunique", "unique_id": "veryunique",
} }
await help_test_entity_device_info_update(hass, mqtt_mock, vacuum.DOMAIN, config)
data = json.dumps(config)
async_fire_mqtt_message(hass, "homeassistant/vacuum/bla/config", data)
await hass.async_block_till_done()
device = registry.async_get_device({("mqtt", "helloworld")}, set()) async def test_entity_id_update(hass, mqtt_mock):
assert device is not None """Test MQTT subscriptions are managed when entity_id is updated."""
assert device.name == "Beer" config = {
vacuum.DOMAIN: [
config["device"]["name"] = "Milk" {
data = json.dumps(config) "platform": "mqtt",
async_fire_mqtt_message(hass, "homeassistant/vacuum/bla/config", data) "name": "beer",
await hass.async_block_till_done() "battery_level_topic": "test-topic",
"battery_level_template": "{{ value_json.battery_level }}",
device = registry.async_get_device({("mqtt", "helloworld")}, set()) "command_topic": "command-topic",
assert device is not None "availability_topic": "avty-topic",
assert device.name == "Milk" "unique_id": "TOTALLY_UNIQUE",
}
]
}
await help_test_entity_id_update(hass, mqtt_mock, vacuum.DOMAIN, config)

View File

@ -155,7 +155,7 @@ light:
""" """
import json import json
from unittest import mock from unittest import mock
from unittest.mock import ANY, patch from unittest.mock import patch
from homeassistant.components import light, mqtt from homeassistant.components import light, mqtt
from homeassistant.components.mqtt.discovery import async_start from homeassistant.components.mqtt.discovery import async_start
@ -168,13 +168,25 @@ from homeassistant.const import (
import homeassistant.core as ha import homeassistant.core as ha
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
from .common import (
help_test_discovery_broken,
help_test_discovery_removal,
help_test_discovery_update,
help_test_discovery_update_attr,
help_test_entity_device_info_update,
help_test_entity_device_info_with_identifier,
help_test_entity_id_update,
help_test_setting_attribute_via_mqtt_json_message,
help_test_unique_id,
help_test_update_with_json_attrs_bad_JSON,
help_test_update_with_json_attrs_not_dict,
)
from tests.common import ( from tests.common import (
MockConfigEntry, MockConfigEntry,
assert_setup_component, assert_setup_component,
async_fire_mqtt_message, async_fire_mqtt_message,
async_mock_mqtt_component,
mock_coro, mock_coro,
mock_registry,
) )
from tests.components.light import common from tests.components.light import common
@ -1063,73 +1075,51 @@ async def test_custom_availability_payload(hass, mqtt_mock):
async def test_setting_attribute_via_mqtt_json_message(hass, mqtt_mock): async def test_setting_attribute_via_mqtt_json_message(hass, mqtt_mock):
"""Test the setting of attribute via MQTT with JSON payload.""" """Test the setting of attribute via MQTT with JSON payload."""
assert await async_setup_component( config = {
hass,
light.DOMAIN,
{
light.DOMAIN: { light.DOMAIN: {
"platform": "mqtt", "platform": "mqtt",
"name": "test", "name": "test",
"command_topic": "test-topic", "command_topic": "test-topic",
"json_attributes_topic": "attr-topic", "json_attributes_topic": "attr-topic",
} }
}, }
await help_test_setting_attribute_via_mqtt_json_message(
hass, mqtt_mock, light.DOMAIN, config
) )
async_fire_mqtt_message(hass, "attr-topic", '{ "val": "100" }')
state = hass.states.get("light.test")
assert state.attributes.get("val") == "100"
async def test_update_with_json_attrs_not_dict(hass, mqtt_mock, caplog): async def test_update_with_json_attrs_not_dict(hass, mqtt_mock, caplog):
"""Test attributes get extracted from a JSON result.""" """Test attributes get extracted from a JSON result."""
assert await async_setup_component( config = {
hass,
light.DOMAIN,
{
light.DOMAIN: { light.DOMAIN: {
"platform": "mqtt", "platform": "mqtt",
"name": "test", "name": "test",
"command_topic": "test-topic", "command_topic": "test-topic",
"json_attributes_topic": "attr-topic", "json_attributes_topic": "attr-topic",
} }
}, }
await help_test_update_with_json_attrs_not_dict(
hass, mqtt_mock, caplog, light.DOMAIN, config
) )
async_fire_mqtt_message(hass, "attr-topic", '[ "list", "of", "things"]')
state = hass.states.get("light.test")
assert state.attributes.get("val") is None
assert "JSON result was not a dictionary" in caplog.text
async def test_update_with_json_attrs_bad_JSON(hass, mqtt_mock, caplog): async def test_update_with_json_attrs_bad_JSON(hass, mqtt_mock, caplog):
"""Test attributes get extracted from a JSON result.""" """Test attributes get extracted from a JSON result."""
assert await async_setup_component( config = {
hass,
light.DOMAIN,
{
light.DOMAIN: { light.DOMAIN: {
"platform": "mqtt", "platform": "mqtt",
"name": "test", "name": "test",
"command_topic": "test-topic", "command_topic": "test-topic",
"json_attributes_topic": "attr-topic", "json_attributes_topic": "attr-topic",
} }
}, }
await help_test_update_with_json_attrs_bad_JSON(
hass, mqtt_mock, caplog, light.DOMAIN, config
) )
async_fire_mqtt_message(hass, "attr-topic", "This is not JSON")
state = hass.states.get("light.test")
assert state.attributes.get("val") is None
assert "Erroneous JSON: This is not JSON" in caplog.text
async def test_discovery_update_attr(hass, mqtt_mock, caplog): async def test_discovery_update_attr(hass, mqtt_mock, caplog):
"""Test update of discovered MQTTAttributes.""" """Test update of discovered MQTTAttributes."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
await async_start(hass, "homeassistant", {}, entry)
data1 = ( data1 = (
'{ "name": "Beer",' '{ "name": "Beer",'
' "command_topic": "test_topic",' ' "command_topic": "test_topic",'
@ -1140,34 +1130,14 @@ async def test_discovery_update_attr(hass, mqtt_mock, caplog):
' "command_topic": "test_topic",' ' "command_topic": "test_topic",'
' "json_attributes_topic": "attr-topic2" }' ' "json_attributes_topic": "attr-topic2" }'
) )
async_fire_mqtt_message(hass, "homeassistant/light/bla/config", data1) await help_test_discovery_update_attr(
await hass.async_block_till_done() hass, mqtt_mock, caplog, light.DOMAIN, data1, data2
async_fire_mqtt_message(hass, "attr-topic1", '{ "val": "100" }') )
state = hass.states.get("light.beer")
assert state.attributes.get("val") == "100"
# Change json_attributes_topic
async_fire_mqtt_message(hass, "homeassistant/light/bla/config", data2)
await hass.async_block_till_done()
# Verify we are no longer subscribing to the old topic
async_fire_mqtt_message(hass, "attr-topic1", '{ "val": "50" }')
state = hass.states.get("light.beer")
assert state.attributes.get("val") == "100"
# Verify we are subscribing to the new topic
async_fire_mqtt_message(hass, "attr-topic2", '{ "val": "75" }')
state = hass.states.get("light.beer")
assert state.attributes.get("val") == "75"
async def test_unique_id(hass): async def test_unique_id(hass):
"""Test unique id option only creates one light per unique_id.""" """Test unique id option only creates one light per unique_id."""
await async_mock_mqtt_component(hass) config = {
assert await async_setup_component(
hass,
light.DOMAIN,
{
light.DOMAIN: [ light.DOMAIN: [
{ {
"platform": "mqtt", "platform": "mqtt",
@ -1184,35 +1154,18 @@ async def test_unique_id(hass):
"unique_id": "TOTALLY_UNIQUE", "unique_id": "TOTALLY_UNIQUE",
}, },
] ]
}, }
) await help_test_unique_id(hass, light.DOMAIN, config)
async_fire_mqtt_message(hass, "test-topic", "payload")
assert len(hass.states.async_entity_ids(light.DOMAIN)) == 1
async def test_discovery_removal_light(hass, mqtt_mock, caplog): async def test_discovery_removal_light(hass, mqtt_mock, caplog):
"""Test removal of discovered light.""" """Test removal of discovered light."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
await async_start(hass, "homeassistant", {}, entry)
data = ( data = (
'{ "name": "Beer",' '{ "name": "Beer",'
' "state_topic": "test_topic",' ' "state_topic": "test_topic",'
' "command_topic": "test_topic" }' ' "command_topic": "test_topic" }'
) )
await help_test_discovery_removal(hass, mqtt_mock, caplog, light.DOMAIN, data)
async_fire_mqtt_message(hass, "homeassistant/light/bla/config", data)
await hass.async_block_till_done()
state = hass.states.get("light.beer")
assert state is not None
assert state.name == "Beer"
async_fire_mqtt_message(hass, "homeassistant/light/bla/config", "")
await hass.async_block_till_done()
state = hass.states.get("light.beer")
assert state is None
async def test_discovery_deprecated(hass, mqtt_mock, caplog): async def test_discovery_deprecated(hass, mqtt_mock, caplog):
@ -1231,9 +1184,6 @@ async def test_discovery_deprecated(hass, mqtt_mock, caplog):
async def test_discovery_update_light(hass, mqtt_mock, caplog): async def test_discovery_update_light(hass, mqtt_mock, caplog):
"""Test update of discovered light.""" """Test update of discovered light."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
await async_start(hass, "homeassistant", {}, entry)
data1 = ( data1 = (
'{ "name": "Beer",' '{ "name": "Beer",'
' "state_topic": "test_topic",' ' "state_topic": "test_topic",'
@ -1244,59 +1194,26 @@ async def test_discovery_update_light(hass, mqtt_mock, caplog):
' "state_topic": "test_topic",' ' "state_topic": "test_topic",'
' "command_topic": "test_topic" }' ' "command_topic": "test_topic" }'
) )
await help_test_discovery_update(
async_fire_mqtt_message(hass, "homeassistant/light/bla/config", data1) hass, mqtt_mock, caplog, light.DOMAIN, data1, data2
await hass.async_block_till_done() )
state = hass.states.get("light.beer")
assert state is not None
assert state.name == "Beer"
async_fire_mqtt_message(hass, "homeassistant/light/bla/config", data2)
await hass.async_block_till_done()
state = hass.states.get("light.beer")
assert state is not None
assert state.name == "Milk"
state = hass.states.get("light.milk")
assert state is None
async def test_discovery_broken(hass, mqtt_mock, caplog): async def test_discovery_broken(hass, mqtt_mock, caplog):
"""Test handling of bad discovery message.""" """Test handling of bad discovery message."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
await async_start(hass, "homeassistant", {}, entry)
data1 = '{ "name": "Beer" }' data1 = '{ "name": "Beer" }'
data2 = ( data2 = (
'{ "name": "Milk",' '{ "name": "Milk",'
' "state_topic": "test_topic",' ' "state_topic": "test_topic",'
' "command_topic": "test_topic" }' ' "command_topic": "test_topic" }'
) )
await help_test_discovery_broken(
async_fire_mqtt_message(hass, "homeassistant/light/bla/config", data1) hass, mqtt_mock, caplog, light.DOMAIN, data1, data2
await hass.async_block_till_done() )
state = hass.states.get("light.beer")
assert state is None
async_fire_mqtt_message(hass, "homeassistant/light/bla/config", data2)
await hass.async_block_till_done()
state = hass.states.get("light.milk")
assert state is not None
assert state.name == "Milk"
state = hass.states.get("light.beer")
assert state is None
async def test_entity_device_info_with_identifier(hass, mqtt_mock): async def test_entity_device_info_with_identifier(hass, mqtt_mock):
"""Test MQTT light device registry integration.""" """Test MQTT light device registry integration."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
entry.add_to_hass(hass)
await async_start(hass, "homeassistant", {}, entry)
registry = await hass.helpers.device_registry.async_get_registry()
data = json.dumps( data = json.dumps(
{ {
"platform": "mqtt", "platform": "mqtt",
@ -1314,26 +1231,13 @@ async def test_entity_device_info_with_identifier(hass, mqtt_mock):
"unique_id": "veryunique", "unique_id": "veryunique",
} }
) )
async_fire_mqtt_message(hass, "homeassistant/light/bla/config", data) await help_test_entity_device_info_with_identifier(
await hass.async_block_till_done() hass, mqtt_mock, light.DOMAIN, data
)
device = registry.async_get_device({("mqtt", "helloworld")}, set())
assert device is not None
assert device.identifiers == {("mqtt", "helloworld")}
assert device.connections == {("mac", "02:5b:26:a8:dc:12")}
assert device.manufacturer == "Whatever"
assert device.name == "Beer"
assert device.model == "Glass"
assert device.sw_version == "0.1-beta"
async def test_entity_device_info_update(hass, mqtt_mock): async def test_entity_device_info_update(hass, mqtt_mock):
"""Test device registry update.""" """Test device registry update."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
entry.add_to_hass(hass)
await async_start(hass, "homeassistant", {}, entry)
registry = await hass.helpers.device_registry.async_get_registry()
config = { config = {
"platform": "mqtt", "platform": "mqtt",
"name": "Test 1", "name": "Test 1",
@ -1349,33 +1253,12 @@ async def test_entity_device_info_update(hass, mqtt_mock):
}, },
"unique_id": "veryunique", "unique_id": "veryunique",
} }
await help_test_entity_device_info_update(hass, mqtt_mock, light.DOMAIN, config)
data = json.dumps(config)
async_fire_mqtt_message(hass, "homeassistant/light/bla/config", data)
await hass.async_block_till_done()
device = registry.async_get_device({("mqtt", "helloworld")}, set())
assert device is not None
assert device.name == "Beer"
config["device"]["name"] = "Milk"
data = json.dumps(config)
async_fire_mqtt_message(hass, "homeassistant/light/bla/config", data)
await hass.async_block_till_done()
device = registry.async_get_device({("mqtt", "helloworld")}, set())
assert device is not None
assert device.name == "Milk"
async def test_entity_id_update(hass, mqtt_mock): async def test_entity_id_update(hass, mqtt_mock):
"""Test MQTT subscriptions are managed when entity_id is updated.""" """Test MQTT subscriptions are managed when entity_id is updated."""
registry = mock_registry(hass, {}) config = {
mock_mqtt = await async_mock_mqtt_component(hass)
assert await async_setup_component(
hass,
light.DOMAIN,
{
light.DOMAIN: [ light.DOMAIN: [
{ {
"platform": "mqtt", "platform": "mqtt",
@ -1386,24 +1269,5 @@ async def test_entity_id_update(hass, mqtt_mock):
"unique_id": "TOTALLY_UNIQUE", "unique_id": "TOTALLY_UNIQUE",
} }
] ]
}, }
) await help_test_entity_id_update(hass, mqtt_mock, light.DOMAIN, config)
state = hass.states.get("light.beer")
assert state is not None
assert mock_mqtt.async_subscribe.call_count == 2
mock_mqtt.async_subscribe.assert_any_call("test-topic", ANY, 0, "utf-8")
mock_mqtt.async_subscribe.assert_any_call("avty-topic", ANY, 0, "utf-8")
mock_mqtt.async_subscribe.reset_mock()
registry.async_update_entity("light.beer", new_entity_id="light.milk")
await hass.async_block_till_done()
state = hass.states.get("light.beer")
assert state is None
state = hass.states.get("light.milk")
assert state is not None
assert mock_mqtt.async_subscribe.call_count == 2
mock_mqtt.async_subscribe.assert_any_call("test-topic", ANY, 0, "utf-8")
mock_mqtt.async_subscribe.assert_any_call("avty-topic", ANY, 0, "utf-8")

View File

@ -89,7 +89,7 @@ light:
""" """
import json import json
from unittest import mock from unittest import mock
from unittest.mock import ANY, patch from unittest.mock import patch
from homeassistant.components import light, mqtt from homeassistant.components import light, mqtt
from homeassistant.components.mqtt.discovery import async_start from homeassistant.components.mqtt.discovery import async_start
@ -103,13 +103,21 @@ from homeassistant.const import (
import homeassistant.core as ha import homeassistant.core as ha
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
from tests.common import ( from .common import (
MockConfigEntry, help_test_discovery_broken,
async_fire_mqtt_message, help_test_discovery_removal,
async_mock_mqtt_component, help_test_discovery_update,
mock_coro, help_test_discovery_update_attr,
mock_registry, help_test_entity_device_info_update,
help_test_entity_device_info_with_identifier,
help_test_entity_id_update,
help_test_setting_attribute_via_mqtt_json_message,
help_test_unique_id,
help_test_update_with_json_attrs_bad_JSON,
help_test_update_with_json_attrs_not_dict,
) )
from tests.common import MockConfigEntry, async_fire_mqtt_message, mock_coro
from tests.components.light import common from tests.components.light import common
@ -913,10 +921,7 @@ async def test_custom_availability_payload(hass, mqtt_mock):
async def test_setting_attribute_via_mqtt_json_message(hass, mqtt_mock): async def test_setting_attribute_via_mqtt_json_message(hass, mqtt_mock):
"""Test the setting of attribute via MQTT with JSON payload.""" """Test the setting of attribute via MQTT with JSON payload."""
assert await async_setup_component( config = {
hass,
light.DOMAIN,
{
light.DOMAIN: { light.DOMAIN: {
"platform": "mqtt", "platform": "mqtt",
"schema": "json", "schema": "json",
@ -924,21 +929,15 @@ async def test_setting_attribute_via_mqtt_json_message(hass, mqtt_mock):
"command_topic": "test-topic", "command_topic": "test-topic",
"json_attributes_topic": "attr-topic", "json_attributes_topic": "attr-topic",
} }
}, }
await help_test_setting_attribute_via_mqtt_json_message(
hass, mqtt_mock, light.DOMAIN, config
) )
async_fire_mqtt_message(hass, "attr-topic", '{ "val": "100" }')
state = hass.states.get("light.test")
assert state.attributes.get("val") == "100"
async def test_update_with_json_attrs_not_dict(hass, mqtt_mock, caplog): async def test_update_with_json_attrs_not_dict(hass, mqtt_mock, caplog):
"""Test attributes get extracted from a JSON result.""" """Test attributes get extracted from a JSON result."""
assert await async_setup_component( config = {
hass,
light.DOMAIN,
{
light.DOMAIN: { light.DOMAIN: {
"platform": "mqtt", "platform": "mqtt",
"schema": "json", "schema": "json",
@ -946,22 +945,15 @@ async def test_update_with_json_attrs_not_dict(hass, mqtt_mock, caplog):
"command_topic": "test-topic", "command_topic": "test-topic",
"json_attributes_topic": "attr-topic", "json_attributes_topic": "attr-topic",
} }
}, }
await help_test_update_with_json_attrs_not_dict(
hass, mqtt_mock, caplog, light.DOMAIN, config
) )
async_fire_mqtt_message(hass, "attr-topic", '[ "list", "of", "things"]')
state = hass.states.get("light.test")
assert state.attributes.get("val") is None
assert "JSON result was not a dictionary" in caplog.text
async def test_update_with_json_attrs_bad_JSON(hass, mqtt_mock, caplog): async def test_update_with_json_attrs_bad_JSON(hass, mqtt_mock, caplog):
"""Test attributes get extracted from a JSON result.""" """Test attributes get extracted from a JSON result."""
assert await async_setup_component( config = {
hass,
light.DOMAIN,
{
light.DOMAIN: { light.DOMAIN: {
"platform": "mqtt", "platform": "mqtt",
"schema": "json", "schema": "json",
@ -969,20 +961,14 @@ async def test_update_with_json_attrs_bad_JSON(hass, mqtt_mock, caplog):
"command_topic": "test-topic", "command_topic": "test-topic",
"json_attributes_topic": "attr-topic", "json_attributes_topic": "attr-topic",
} }
}, }
await help_test_update_with_json_attrs_bad_JSON(
hass, mqtt_mock, caplog, light.DOMAIN, config
) )
async_fire_mqtt_message(hass, "attr-topic", "This is not JSON")
state = hass.states.get("light.test")
assert state.attributes.get("val") is None
assert "Erroneous JSON: This is not JSON" in caplog.text
async def test_discovery_update_attr(hass, mqtt_mock, caplog): async def test_discovery_update_attr(hass, mqtt_mock, caplog):
"""Test update of discovered MQTTAttributes.""" """Test update of discovered MQTTAttributes."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
await async_start(hass, "homeassistant", {}, entry)
data1 = ( data1 = (
'{ "name": "Beer",' '{ "name": "Beer",'
' "schema": "json",' ' "schema": "json",'
@ -995,34 +981,14 @@ async def test_discovery_update_attr(hass, mqtt_mock, caplog):
' "command_topic": "test_topic",' ' "command_topic": "test_topic",'
' "json_attributes_topic": "attr-topic2" }' ' "json_attributes_topic": "attr-topic2" }'
) )
async_fire_mqtt_message(hass, "homeassistant/light/bla/config", data1) await help_test_discovery_update_attr(
await hass.async_block_till_done() hass, mqtt_mock, caplog, light.DOMAIN, data1, data2
async_fire_mqtt_message(hass, "attr-topic1", '{ "val": "100" }') )
state = hass.states.get("light.beer")
assert state.attributes.get("val") == "100"
# Change json_attributes_topic
async_fire_mqtt_message(hass, "homeassistant/light/bla/config", data2)
await hass.async_block_till_done()
# Verify we are no longer subscribing to the old topic
async_fire_mqtt_message(hass, "attr-topic1", '{ "val": "50" }')
state = hass.states.get("light.beer")
assert state.attributes.get("val") == "100"
# Verify we are subscribing to the new topic
async_fire_mqtt_message(hass, "attr-topic2", '{ "val": "75" }')
state = hass.states.get("light.beer")
assert state.attributes.get("val") == "75"
async def test_unique_id(hass): async def test_unique_id(hass):
"""Test unique id option only creates one light per unique_id.""" """Test unique id option only creates one light per unique_id."""
await async_mock_mqtt_component(hass) config = {
assert await async_setup_component(
hass,
light.DOMAIN,
{
light.DOMAIN: [ light.DOMAIN: [
{ {
"platform": "mqtt", "platform": "mqtt",
@ -1041,26 +1007,14 @@ async def test_unique_id(hass):
"unique_id": "TOTALLY_UNIQUE", "unique_id": "TOTALLY_UNIQUE",
}, },
] ]
}, }
) await help_test_unique_id(hass, light.DOMAIN, config)
async_fire_mqtt_message(hass, "test-topic", "payload")
assert len(hass.states.async_entity_ids(light.DOMAIN)) == 1
async def test_discovery_removal(hass, mqtt_mock, caplog): async def test_discovery_removal(hass, mqtt_mock, caplog):
"""Test removal of discovered mqtt_json lights.""" """Test removal of discovered mqtt_json lights."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
await async_start(hass, "homeassistant", {"mqtt": {}}, entry)
data = '{ "name": "Beer",' ' "schema": "json",' ' "command_topic": "test_topic" }' data = '{ "name": "Beer",' ' "schema": "json",' ' "command_topic": "test_topic" }'
async_fire_mqtt_message(hass, "homeassistant/light/bla/config", data) await help_test_discovery_removal(hass, mqtt_mock, caplog, light.DOMAIN, data)
await hass.async_block_till_done()
state = hass.states.get("light.beer")
assert state is not None
assert state.name == "Beer"
async_fire_mqtt_message(hass, "homeassistant/light/bla/config", "")
await hass.async_block_till_done()
state = hass.states.get("light.beer")
assert state is None
async def test_discovery_deprecated(hass, mqtt_mock, caplog): async def test_discovery_deprecated(hass, mqtt_mock, caplog):
@ -1081,9 +1035,6 @@ async def test_discovery_deprecated(hass, mqtt_mock, caplog):
async def test_discovery_update_light(hass, mqtt_mock, caplog): async def test_discovery_update_light(hass, mqtt_mock, caplog):
"""Test update of discovered light.""" """Test update of discovered light."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
await async_start(hass, "homeassistant", {}, entry)
data1 = ( data1 = (
'{ "name": "Beer",' '{ "name": "Beer",'
' "schema": "json",' ' "schema": "json",'
@ -1096,29 +1047,13 @@ async def test_discovery_update_light(hass, mqtt_mock, caplog):
' "state_topic": "test_topic",' ' "state_topic": "test_topic",'
' "command_topic": "test_topic" }' ' "command_topic": "test_topic" }'
) )
await help_test_discovery_update(
async_fire_mqtt_message(hass, "homeassistant/light/bla/config", data1) hass, mqtt_mock, caplog, light.DOMAIN, data1, data2
await hass.async_block_till_done() )
state = hass.states.get("light.beer")
assert state is not None
assert state.name == "Beer"
async_fire_mqtt_message(hass, "homeassistant/light/bla/config", data2)
await hass.async_block_till_done()
state = hass.states.get("light.beer")
assert state is not None
assert state.name == "Milk"
state = hass.states.get("light.milk")
assert state is None
async def test_discovery_broken(hass, mqtt_mock, caplog): async def test_discovery_broken(hass, mqtt_mock, caplog):
"""Test handling of bad discovery message.""" """Test handling of bad discovery message."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
await async_start(hass, "homeassistant", {}, entry)
data1 = '{ "name": "Beer" }' data1 = '{ "name": "Beer" }'
data2 = ( data2 = (
'{ "name": "Milk",' '{ "name": "Milk",'
@ -1126,30 +1061,13 @@ async def test_discovery_broken(hass, mqtt_mock, caplog):
' "state_topic": "test_topic",' ' "state_topic": "test_topic",'
' "command_topic": "test_topic" }' ' "command_topic": "test_topic" }'
) )
await help_test_discovery_broken(
async_fire_mqtt_message(hass, "homeassistant/light/bla/config", data1) hass, mqtt_mock, caplog, light.DOMAIN, data1, data2
await hass.async_block_till_done() )
state = hass.states.get("light.beer")
assert state is None
async_fire_mqtt_message(hass, "homeassistant/light/bla/config", data2)
await hass.async_block_till_done()
state = hass.states.get("light.milk")
assert state is not None
assert state.name == "Milk"
state = hass.states.get("light.beer")
assert state is None
async def test_entity_device_info_with_identifier(hass, mqtt_mock): async def test_entity_device_info_with_identifier(hass, mqtt_mock):
"""Test MQTT light device registry integration.""" """Test MQTT light device registry integration."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
entry.add_to_hass(hass)
await async_start(hass, "homeassistant", {}, entry)
registry = await hass.helpers.device_registry.async_get_registry()
data = json.dumps( data = json.dumps(
{ {
"platform": "mqtt", "platform": "mqtt",
@ -1168,26 +1086,13 @@ async def test_entity_device_info_with_identifier(hass, mqtt_mock):
"unique_id": "veryunique", "unique_id": "veryunique",
} }
) )
async_fire_mqtt_message(hass, "homeassistant/light/bla/config", data) await help_test_entity_device_info_with_identifier(
await hass.async_block_till_done() hass, mqtt_mock, light.DOMAIN, data
)
device = registry.async_get_device({("mqtt", "helloworld")}, set())
assert device is not None
assert device.identifiers == {("mqtt", "helloworld")}
assert device.connections == {("mac", "02:5b:26:a8:dc:12")}
assert device.manufacturer == "Whatever"
assert device.name == "Beer"
assert device.model == "Glass"
assert device.sw_version == "0.1-beta"
async def test_entity_device_info_update(hass, mqtt_mock): async def test_entity_device_info_update(hass, mqtt_mock):
"""Test device registry update.""" """Test device registry update."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
entry.add_to_hass(hass)
await async_start(hass, "homeassistant", {}, entry)
registry = await hass.helpers.device_registry.async_get_registry()
config = { config = {
"platform": "mqtt", "platform": "mqtt",
"name": "Test 1", "name": "Test 1",
@ -1204,33 +1109,12 @@ async def test_entity_device_info_update(hass, mqtt_mock):
}, },
"unique_id": "veryunique", "unique_id": "veryunique",
} }
await help_test_entity_device_info_update(hass, mqtt_mock, light.DOMAIN, config)
data = json.dumps(config)
async_fire_mqtt_message(hass, "homeassistant/light/bla/config", data)
await hass.async_block_till_done()
device = registry.async_get_device({("mqtt", "helloworld")}, set())
assert device is not None
assert device.name == "Beer"
config["device"]["name"] = "Milk"
data = json.dumps(config)
async_fire_mqtt_message(hass, "homeassistant/light/bla/config", data)
await hass.async_block_till_done()
device = registry.async_get_device({("mqtt", "helloworld")}, set())
assert device is not None
assert device.name == "Milk"
async def test_entity_id_update(hass, mqtt_mock): async def test_entity_id_update(hass, mqtt_mock):
"""Test MQTT subscriptions are managed when entity_id is updated.""" """Test MQTT subscriptions are managed when entity_id is updated."""
registry = mock_registry(hass, {}) config = {
mock_mqtt = await async_mock_mqtt_component(hass)
assert await async_setup_component(
hass,
light.DOMAIN,
{
light.DOMAIN: [ light.DOMAIN: [
{ {
"platform": "mqtt", "platform": "mqtt",
@ -1242,24 +1126,5 @@ async def test_entity_id_update(hass, mqtt_mock):
"unique_id": "TOTALLY_UNIQUE", "unique_id": "TOTALLY_UNIQUE",
} }
] ]
}, }
) await help_test_entity_id_update(hass, mqtt_mock, light.DOMAIN, config)
state = hass.states.get("light.beer")
assert state is not None
assert mock_mqtt.async_subscribe.call_count == 2
mock_mqtt.async_subscribe.assert_any_call("test-topic", ANY, 0, "utf-8")
mock_mqtt.async_subscribe.assert_any_call("avty-topic", ANY, 0, "utf-8")
mock_mqtt.async_subscribe.reset_mock()
registry.async_update_entity("light.beer", new_entity_id="light.milk")
await hass.async_block_till_done()
state = hass.states.get("light.beer")
assert state is None
state = hass.states.get("light.milk")
assert state is not None
assert mock_mqtt.async_subscribe.call_count == 2
mock_mqtt.async_subscribe.assert_any_call("test-topic", ANY, 0, "utf-8")
mock_mqtt.async_subscribe.assert_any_call("avty-topic", ANY, 0, "utf-8")

View File

@ -27,7 +27,7 @@ If your light doesn't support white value feature, omit `white_value_template`.
If your light doesn't support RGB feature, omit `(red|green|blue)_template`. If your light doesn't support RGB feature, omit `(red|green|blue)_template`.
""" """
import json import json
from unittest.mock import ANY, patch from unittest.mock import patch
from homeassistant.components import light, mqtt from homeassistant.components import light, mqtt
from homeassistant.components.mqtt.discovery import async_start from homeassistant.components.mqtt.discovery import async_start
@ -40,13 +40,25 @@ from homeassistant.const import (
import homeassistant.core as ha import homeassistant.core as ha
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
from .common import (
help_test_discovery_broken,
help_test_discovery_removal,
help_test_discovery_update,
help_test_discovery_update_attr,
help_test_entity_device_info_update,
help_test_entity_device_info_with_identifier,
help_test_entity_id_update,
help_test_setting_attribute_via_mqtt_json_message,
help_test_unique_id,
help_test_update_with_json_attrs_bad_JSON,
help_test_update_with_json_attrs_not_dict,
)
from tests.common import ( from tests.common import (
MockConfigEntry, MockConfigEntry,
assert_setup_component, assert_setup_component,
async_fire_mqtt_message, async_fire_mqtt_message,
async_mock_mqtt_component,
mock_coro, mock_coro,
mock_registry,
) )
@ -510,10 +522,7 @@ async def test_custom_availability_payload(hass, mqtt_mock):
async def test_setting_attribute_via_mqtt_json_message(hass, mqtt_mock): async def test_setting_attribute_via_mqtt_json_message(hass, mqtt_mock):
"""Test the setting of attribute via MQTT with JSON payload.""" """Test the setting of attribute via MQTT with JSON payload."""
assert await async_setup_component( config = {
hass,
light.DOMAIN,
{
light.DOMAIN: { light.DOMAIN: {
"platform": "mqtt", "platform": "mqtt",
"schema": "template", "schema": "template",
@ -523,21 +532,15 @@ async def test_setting_attribute_via_mqtt_json_message(hass, mqtt_mock):
"command_off_template": "off,{{ transition|d }}", "command_off_template": "off,{{ transition|d }}",
"json_attributes_topic": "attr-topic", "json_attributes_topic": "attr-topic",
} }
}, }
await help_test_setting_attribute_via_mqtt_json_message(
hass, mqtt_mock, light.DOMAIN, config
) )
async_fire_mqtt_message(hass, "attr-topic", '{ "val": "100" }')
state = hass.states.get("light.test")
assert state.attributes.get("val") == "100"
async def test_update_with_json_attrs_not_dict(hass, mqtt_mock, caplog): async def test_update_with_json_attrs_not_dict(hass, mqtt_mock, caplog):
"""Test attributes get extracted from a JSON result.""" """Test attributes get extracted from a JSON result."""
assert await async_setup_component( config = {
hass,
light.DOMAIN,
{
light.DOMAIN: { light.DOMAIN: {
"platform": "mqtt", "platform": "mqtt",
"schema": "template", "schema": "template",
@ -547,22 +550,15 @@ async def test_update_with_json_attrs_not_dict(hass, mqtt_mock, caplog):
"command_off_template": "off,{{ transition|d }}", "command_off_template": "off,{{ transition|d }}",
"json_attributes_topic": "attr-topic", "json_attributes_topic": "attr-topic",
} }
}, }
await help_test_update_with_json_attrs_not_dict(
hass, mqtt_mock, caplog, light.DOMAIN, config
) )
async_fire_mqtt_message(hass, "attr-topic", '[ "list", "of", "things"]')
state = hass.states.get("light.test")
assert state.attributes.get("val") is None
assert "JSON result was not a dictionary" in caplog.text
async def test_update_with_json_attrs_bad_JSON(hass, mqtt_mock, caplog): async def test_update_with_json_attrs_bad_JSON(hass, mqtt_mock, caplog):
"""Test attributes get extracted from a JSON result.""" """Test attributes get extracted from a JSON result."""
assert await async_setup_component( config = {
hass,
light.DOMAIN,
{
light.DOMAIN: { light.DOMAIN: {
"platform": "mqtt", "platform": "mqtt",
"schema": "template", "schema": "template",
@ -572,20 +568,14 @@ async def test_update_with_json_attrs_bad_JSON(hass, mqtt_mock, caplog):
"command_off_template": "off,{{ transition|d }}", "command_off_template": "off,{{ transition|d }}",
"json_attributes_topic": "attr-topic", "json_attributes_topic": "attr-topic",
} }
}, }
await help_test_update_with_json_attrs_bad_JSON(
hass, mqtt_mock, caplog, light.DOMAIN, config
) )
async_fire_mqtt_message(hass, "attr-topic", "This is not JSON")
state = hass.states.get("light.test")
assert state.attributes.get("val") is None
assert "Erroneous JSON: This is not JSON" in caplog.text
async def test_discovery_update_attr(hass, mqtt_mock, caplog): async def test_discovery_update_attr(hass, mqtt_mock, caplog):
"""Test update of discovered MQTTAttributes.""" """Test update of discovered MQTTAttributes."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
await async_start(hass, "homeassistant", {}, entry)
data1 = ( data1 = (
'{ "name": "Beer",' '{ "name": "Beer",'
' "schema": "template",' ' "schema": "template",'
@ -602,34 +592,14 @@ async def test_discovery_update_attr(hass, mqtt_mock, caplog):
' "command_off_template": "off",' ' "command_off_template": "off",'
' "json_attributes_topic": "attr-topic2" }' ' "json_attributes_topic": "attr-topic2" }'
) )
async_fire_mqtt_message(hass, "homeassistant/light/bla/config", data1) await help_test_discovery_update_attr(
await hass.async_block_till_done() hass, mqtt_mock, caplog, light.DOMAIN, data1, data2
async_fire_mqtt_message(hass, "attr-topic1", '{ "val": "100" }') )
state = hass.states.get("light.beer")
assert state.attributes.get("val") == "100"
# Change json_attributes_topic
async_fire_mqtt_message(hass, "homeassistant/light/bla/config", data2)
await hass.async_block_till_done()
# Verify we are no longer subscribing to the old topic
async_fire_mqtt_message(hass, "attr-topic1", '{ "val": "50" }')
state = hass.states.get("light.beer")
assert state.attributes.get("val") == "100"
# Verify we are subscribing to the new topic
async_fire_mqtt_message(hass, "attr-topic2", '{ "val": "75" }')
state = hass.states.get("light.beer")
assert state.attributes.get("val") == "75"
async def test_unique_id(hass): async def test_unique_id(hass):
"""Test unique id option only creates one light per unique_id.""" """Test unique id option only creates one light per unique_id."""
await async_mock_mqtt_component(hass) config = {
assert await async_setup_component(
hass,
light.DOMAIN,
{
light.DOMAIN: [ light.DOMAIN: [
{ {
"platform": "mqtt", "platform": "mqtt",
@ -650,16 +620,12 @@ async def test_unique_id(hass):
"unique_id": "TOTALLY_UNIQUE", "unique_id": "TOTALLY_UNIQUE",
}, },
] ]
}, }
) await help_test_unique_id(hass, light.DOMAIN, config)
async_fire_mqtt_message(hass, "test-topic", "payload")
assert len(hass.states.async_entity_ids(light.DOMAIN)) == 1
async def test_discovery_removal(hass, mqtt_mock, caplog): async def test_discovery_removal(hass, mqtt_mock, caplog):
"""Test removal of discovered mqtt_json lights.""" """Test removal of discovered mqtt_json lights."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
await async_start(hass, "homeassistant", {"mqtt": {}}, entry)
data = ( data = (
'{ "name": "Beer",' '{ "name": "Beer",'
' "schema": "template",' ' "schema": "template",'
@ -667,15 +633,7 @@ async def test_discovery_removal(hass, mqtt_mock, caplog):
' "command_on_template": "on",' ' "command_on_template": "on",'
' "command_off_template": "off"}' ' "command_off_template": "off"}'
) )
async_fire_mqtt_message(hass, "homeassistant/light/bla/config", data) await help_test_discovery_removal(hass, mqtt_mock, caplog, light.DOMAIN, data)
await hass.async_block_till_done()
state = hass.states.get("light.beer")
assert state is not None
assert state.name == "Beer"
async_fire_mqtt_message(hass, "homeassistant/light/bla/config", "")
await hass.async_block_till_done()
state = hass.states.get("light.beer")
assert state is None
async def test_discovery_deprecated(hass, mqtt_mock, caplog): async def test_discovery_deprecated(hass, mqtt_mock, caplog):
@ -698,9 +656,6 @@ async def test_discovery_deprecated(hass, mqtt_mock, caplog):
async def test_discovery_update_light(hass, mqtt_mock, caplog): async def test_discovery_update_light(hass, mqtt_mock, caplog):
"""Test update of discovered light.""" """Test update of discovered light."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
await async_start(hass, "homeassistant", {}, entry)
data1 = ( data1 = (
'{ "name": "Beer",' '{ "name": "Beer",'
' "schema": "template",' ' "schema": "template",'
@ -717,29 +672,13 @@ async def test_discovery_update_light(hass, mqtt_mock, caplog):
' "command_on_template": "on",' ' "command_on_template": "on",'
' "command_off_template": "off"}' ' "command_off_template": "off"}'
) )
await help_test_discovery_update(
async_fire_mqtt_message(hass, "homeassistant/light/bla/config", data1) hass, mqtt_mock, caplog, light.DOMAIN, data1, data2
await hass.async_block_till_done() )
state = hass.states.get("light.beer")
assert state is not None
assert state.name == "Beer"
async_fire_mqtt_message(hass, "homeassistant/light/bla/config", data2)
await hass.async_block_till_done()
state = hass.states.get("light.beer")
assert state is not None
assert state.name == "Milk"
state = hass.states.get("light.milk")
assert state is None
async def test_discovery_broken(hass, mqtt_mock, caplog): async def test_discovery_broken(hass, mqtt_mock, caplog):
"""Test handling of bad discovery message.""" """Test handling of bad discovery message."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
await async_start(hass, "homeassistant", {}, entry)
data1 = '{ "name": "Beer" }' data1 = '{ "name": "Beer" }'
data2 = ( data2 = (
'{ "name": "Milk",' '{ "name": "Milk",'
@ -749,30 +688,13 @@ async def test_discovery_broken(hass, mqtt_mock, caplog):
' "command_on_template": "on",' ' "command_on_template": "on",'
' "command_off_template": "off"}' ' "command_off_template": "off"}'
) )
await help_test_discovery_broken(
async_fire_mqtt_message(hass, "homeassistant/light/bla/config", data1) hass, mqtt_mock, caplog, light.DOMAIN, data1, data2
await hass.async_block_till_done() )
state = hass.states.get("light.beer")
assert state is None
async_fire_mqtt_message(hass, "homeassistant/light/bla/config", data2)
await hass.async_block_till_done()
state = hass.states.get("light.milk")
assert state is not None
assert state.name == "Milk"
state = hass.states.get("light.beer")
assert state is None
async def test_entity_device_info_with_identifier(hass, mqtt_mock): async def test_entity_device_info_with_identifier(hass, mqtt_mock):
"""Test MQTT light device registry integration.""" """Test MQTT light device registry integration."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
entry.add_to_hass(hass)
await async_start(hass, "homeassistant", {}, entry)
registry = await hass.helpers.device_registry.async_get_registry()
data = json.dumps( data = json.dumps(
{ {
"platform": "mqtt", "platform": "mqtt",
@ -793,26 +715,13 @@ async def test_entity_device_info_with_identifier(hass, mqtt_mock):
"unique_id": "veryunique", "unique_id": "veryunique",
} }
) )
async_fire_mqtt_message(hass, "homeassistant/light/bla/config", data) await help_test_entity_device_info_with_identifier(
await hass.async_block_till_done() hass, mqtt_mock, light.DOMAIN, data
)
device = registry.async_get_device({("mqtt", "helloworld")}, set())
assert device is not None
assert device.identifiers == {("mqtt", "helloworld")}
assert device.connections == {("mac", "02:5b:26:a8:dc:12")}
assert device.manufacturer == "Whatever"
assert device.name == "Beer"
assert device.model == "Glass"
assert device.sw_version == "0.1-beta"
async def test_entity_device_info_update(hass, mqtt_mock): async def test_entity_device_info_update(hass, mqtt_mock):
"""Test device registry update.""" """Test device registry update."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
entry.add_to_hass(hass)
await async_start(hass, "homeassistant", {}, entry)
registry = await hass.helpers.device_registry.async_get_registry()
config = { config = {
"platform": "mqtt", "platform": "mqtt",
"name": "Test 1", "name": "Test 1",
@ -831,33 +740,12 @@ async def test_entity_device_info_update(hass, mqtt_mock):
}, },
"unique_id": "veryunique", "unique_id": "veryunique",
} }
await help_test_entity_device_info_update(hass, mqtt_mock, light.DOMAIN, config)
data = json.dumps(config)
async_fire_mqtt_message(hass, "homeassistant/light/bla/config", data)
await hass.async_block_till_done()
device = registry.async_get_device({("mqtt", "helloworld")}, set())
assert device is not None
assert device.name == "Beer"
config["device"]["name"] = "Milk"
data = json.dumps(config)
async_fire_mqtt_message(hass, "homeassistant/light/bla/config", data)
await hass.async_block_till_done()
device = registry.async_get_device({("mqtt", "helloworld")}, set())
assert device is not None
assert device.name == "Milk"
async def test_entity_id_update(hass, mqtt_mock): async def test_entity_id_update(hass, mqtt_mock):
"""Test MQTT subscriptions are managed when entity_id is updated.""" """Test MQTT subscriptions are managed when entity_id is updated."""
registry = mock_registry(hass, {}) config = {
mock_mqtt = await async_mock_mqtt_component(hass)
assert await async_setup_component(
hass,
light.DOMAIN,
{
light.DOMAIN: [ light.DOMAIN: [
{ {
"platform": "mqtt", "platform": "mqtt",
@ -871,24 +759,5 @@ async def test_entity_id_update(hass, mqtt_mock):
"unique_id": "TOTALLY_UNIQUE", "unique_id": "TOTALLY_UNIQUE",
} }
] ]
}, }
) await help_test_entity_id_update(hass, mqtt_mock, light.DOMAIN, config)
state = hass.states.get("light.beer")
assert state is not None
assert mock_mqtt.async_subscribe.call_count == 2
mock_mqtt.async_subscribe.assert_any_call("test-topic", ANY, 0, "utf-8")
mock_mqtt.async_subscribe.assert_any_call("avty-topic", ANY, 0, "utf-8")
mock_mqtt.async_subscribe.reset_mock()
registry.async_update_entity("light.beer", new_entity_id="light.milk")
await hass.async_block_till_done()
state = hass.states.get("light.beer")
assert state is None
state = hass.states.get("light.milk")
assert state is not None
assert mock_mqtt.async_subscribe.call_count == 2
mock_mqtt.async_subscribe.assert_any_call("test-topic", ANY, 0, "utf-8")
mock_mqtt.async_subscribe.assert_any_call("avty-topic", ANY, 0, "utf-8")

View File

@ -1,9 +1,7 @@
"""The tests for the MQTT lock platform.""" """The tests for the MQTT lock platform."""
import json import json
from unittest.mock import ANY
from homeassistant.components import lock, mqtt from homeassistant.components import lock
from homeassistant.components.mqtt.discovery import async_start
from homeassistant.const import ( from homeassistant.const import (
ATTR_ASSUMED_STATE, ATTR_ASSUMED_STATE,
STATE_LOCKED, STATE_LOCKED,
@ -12,12 +10,21 @@ from homeassistant.const import (
) )
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
from tests.common import ( from .common import (
MockConfigEntry, help_test_discovery_broken,
async_fire_mqtt_message, help_test_discovery_removal,
async_mock_mqtt_component, help_test_discovery_update,
mock_registry, help_test_discovery_update_attr,
help_test_entity_device_info_update,
help_test_entity_device_info_with_identifier,
help_test_entity_id_update,
help_test_setting_attribute_via_mqtt_json_message,
help_test_unique_id,
help_test_update_with_json_attrs_bad_JSON,
help_test_update_with_json_attrs_not_dict,
) )
from tests.common import async_fire_mqtt_message
from tests.components.lock import common from tests.components.lock import common
@ -309,73 +316,51 @@ async def test_custom_availability_payload(hass, mqtt_mock):
async def test_setting_attribute_via_mqtt_json_message(hass, mqtt_mock): async def test_setting_attribute_via_mqtt_json_message(hass, mqtt_mock):
"""Test the setting of attribute via MQTT with JSON payload.""" """Test the setting of attribute via MQTT with JSON payload."""
assert await async_setup_component( config = {
hass,
lock.DOMAIN,
{
lock.DOMAIN: { lock.DOMAIN: {
"platform": "mqtt", "platform": "mqtt",
"name": "test", "name": "test",
"command_topic": "test-topic", "command_topic": "test-topic",
"json_attributes_topic": "attr-topic", "json_attributes_topic": "attr-topic",
} }
}, }
await help_test_setting_attribute_via_mqtt_json_message(
hass, mqtt_mock, lock.DOMAIN, config
) )
async_fire_mqtt_message(hass, "attr-topic", '{ "val": "100" }')
state = hass.states.get("lock.test")
assert state.attributes.get("val") == "100"
async def test_update_with_json_attrs_not_dict(hass, mqtt_mock, caplog): async def test_update_with_json_attrs_not_dict(hass, mqtt_mock, caplog):
"""Test attributes get extracted from a JSON result.""" """Test attributes get extracted from a JSON result."""
assert await async_setup_component( config = {
hass,
lock.DOMAIN,
{
lock.DOMAIN: { lock.DOMAIN: {
"platform": "mqtt", "platform": "mqtt",
"name": "test", "name": "test",
"command_topic": "test-topic", "command_topic": "test-topic",
"json_attributes_topic": "attr-topic", "json_attributes_topic": "attr-topic",
} }
}, }
await help_test_update_with_json_attrs_not_dict(
hass, mqtt_mock, caplog, lock.DOMAIN, config
) )
async_fire_mqtt_message(hass, "attr-topic", '[ "list", "of", "things"]')
state = hass.states.get("lock.test")
assert state.attributes.get("val") is None
assert "JSON result was not a dictionary" in caplog.text
async def test_update_with_json_attrs_bad_JSON(hass, mqtt_mock, caplog): async def test_update_with_json_attrs_bad_JSON(hass, mqtt_mock, caplog):
"""Test attributes get extracted from a JSON result.""" """Test attributes get extracted from a JSON result."""
assert await async_setup_component( config = {
hass,
lock.DOMAIN,
{
lock.DOMAIN: { lock.DOMAIN: {
"platform": "mqtt", "platform": "mqtt",
"name": "test", "name": "test",
"command_topic": "test-topic", "command_topic": "test-topic",
"json_attributes_topic": "attr-topic", "json_attributes_topic": "attr-topic",
} }
}, }
await help_test_update_with_json_attrs_bad_JSON(
hass, mqtt_mock, caplog, lock.DOMAIN, config
) )
async_fire_mqtt_message(hass, "attr-topic", "This is not JSON")
state = hass.states.get("lock.test")
assert state.attributes.get("val") is None
assert "Erroneous JSON: This is not JSON" in caplog.text
async def test_discovery_update_attr(hass, mqtt_mock, caplog): async def test_discovery_update_attr(hass, mqtt_mock, caplog):
"""Test update of discovered MQTTAttributes.""" """Test update of discovered MQTTAttributes."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
await async_start(hass, "homeassistant", {}, entry)
data1 = ( data1 = (
'{ "name": "Beer",' '{ "name": "Beer",'
' "command_topic": "test_topic",' ' "command_topic": "test_topic",'
@ -386,34 +371,14 @@ async def test_discovery_update_attr(hass, mqtt_mock, caplog):
' "command_topic": "test_topic",' ' "command_topic": "test_topic",'
' "json_attributes_topic": "attr-topic2" }' ' "json_attributes_topic": "attr-topic2" }'
) )
async_fire_mqtt_message(hass, "homeassistant/lock/bla/config", data1) await help_test_discovery_update_attr(
await hass.async_block_till_done() hass, mqtt_mock, caplog, lock.DOMAIN, data1, data2
async_fire_mqtt_message(hass, "attr-topic1", '{ "val": "100" }') )
state = hass.states.get("lock.beer")
assert state.attributes.get("val") == "100"
# Change json_attributes_topic
async_fire_mqtt_message(hass, "homeassistant/lock/bla/config", data2)
await hass.async_block_till_done()
# Verify we are no longer subscribing to the old topic
async_fire_mqtt_message(hass, "attr-topic1", '{ "val": "50" }')
state = hass.states.get("lock.beer")
assert state.attributes.get("val") == "100"
# Verify we are subscribing to the new topic
async_fire_mqtt_message(hass, "attr-topic2", '{ "val": "75" }')
state = hass.states.get("lock.beer")
assert state.attributes.get("val") == "75"
async def test_unique_id(hass): async def test_unique_id(hass):
"""Test unique id option only creates one light per unique_id.""" """Test unique id option only creates one lock per unique_id."""
await async_mock_mqtt_component(hass) config = {
assert await async_setup_component(
hass,
lock.DOMAIN,
{
lock.DOMAIN: [ lock.DOMAIN: [
{ {
"platform": "mqtt", "platform": "mqtt",
@ -430,56 +395,18 @@ async def test_unique_id(hass):
"unique_id": "TOTALLY_UNIQUE", "unique_id": "TOTALLY_UNIQUE",
}, },
] ]
}, }
) await help_test_unique_id(hass, lock.DOMAIN, config)
async_fire_mqtt_message(hass, "test-topic", "payload")
assert len(hass.states.async_entity_ids(lock.DOMAIN)) == 1
async def test_discovery_removal_lock(hass, mqtt_mock, caplog): async def test_discovery_removal_lock(hass, mqtt_mock, caplog):
"""Test removal of discovered lock.""" """Test removal of discovered lock."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
await async_start(hass, "homeassistant", {}, entry)
data = '{ "name": "Beer",' ' "command_topic": "test_topic" }' data = '{ "name": "Beer",' ' "command_topic": "test_topic" }'
async_fire_mqtt_message(hass, "homeassistant/lock/bla/config", data) await help_test_discovery_removal(hass, mqtt_mock, caplog, lock.DOMAIN, data)
await hass.async_block_till_done()
state = hass.states.get("lock.beer")
assert state is not None
assert state.name == "Beer"
async_fire_mqtt_message(hass, "homeassistant/lock/bla/config", "")
await hass.async_block_till_done()
state = hass.states.get("lock.beer")
assert state is None
async def test_discovery_broken(hass, mqtt_mock, caplog):
"""Test handling of bad discovery message."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
await async_start(hass, "homeassistant", {}, entry)
data1 = '{ "name": "Beer" }'
data2 = '{ "name": "Milk",' ' "command_topic": "test_topic" }'
async_fire_mqtt_message(hass, "homeassistant/lock/bla/config", data1)
await hass.async_block_till_done()
state = hass.states.get("lock.beer")
assert state is None
async_fire_mqtt_message(hass, "homeassistant/lock/bla/config", data2)
await hass.async_block_till_done()
state = hass.states.get("lock.milk")
assert state is not None
assert state.name == "Milk"
state = hass.states.get("lock.beer")
assert state is None
async def test_discovery_update_lock(hass, mqtt_mock, caplog): async def test_discovery_update_lock(hass, mqtt_mock, caplog):
"""Test update of discovered lock.""" """Test update of discovered lock."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
await async_start(hass, "homeassistant", {}, entry)
data1 = ( data1 = (
'{ "name": "Beer",' '{ "name": "Beer",'
' "state_topic": "test_topic",' ' "state_topic": "test_topic",'
@ -492,28 +419,18 @@ async def test_discovery_update_lock(hass, mqtt_mock, caplog):
' "command_topic": "command_topic",' ' "command_topic": "command_topic",'
' "availability_topic": "availability_topic2" }' ' "availability_topic": "availability_topic2" }'
) )
async_fire_mqtt_message(hass, "homeassistant/lock/bla/config", data1) await help_test_discovery_update(hass, mqtt_mock, caplog, lock.DOMAIN, data1, data2)
await hass.async_block_till_done()
state = hass.states.get("lock.beer")
assert state is not None
assert state.name == "Beer"
async_fire_mqtt_message(hass, "homeassistant/lock/bla/config", data2)
await hass.async_block_till_done()
state = hass.states.get("lock.beer")
assert state is not None
assert state.name == "Milk"
state = hass.states.get("lock.milk")
assert state is None async def test_discovery_broken(hass, mqtt_mock, caplog):
"""Test handling of bad discovery message."""
data1 = '{ "name": "Beer" }'
data2 = '{ "name": "Milk",' ' "command_topic": "test_topic" }'
await help_test_discovery_broken(hass, mqtt_mock, caplog, lock.DOMAIN, data1, data2)
async def test_entity_device_info_with_identifier(hass, mqtt_mock): async def test_entity_device_info_with_identifier(hass, mqtt_mock):
"""Test MQTT lock device registry integration.""" """Test MQTT lock device registry integration."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
entry.add_to_hass(hass)
await async_start(hass, "homeassistant", {}, entry)
registry = await hass.helpers.device_registry.async_get_registry()
data = json.dumps( data = json.dumps(
{ {
"platform": "mqtt", "platform": "mqtt",
@ -531,26 +448,13 @@ async def test_entity_device_info_with_identifier(hass, mqtt_mock):
"unique_id": "veryunique", "unique_id": "veryunique",
} }
) )
async_fire_mqtt_message(hass, "homeassistant/lock/bla/config", data) await help_test_entity_device_info_with_identifier(
await hass.async_block_till_done() hass, mqtt_mock, lock.DOMAIN, data
)
device = registry.async_get_device({("mqtt", "helloworld")}, set())
assert device is not None
assert device.identifiers == {("mqtt", "helloworld")}
assert device.connections == {("mac", "02:5b:26:a8:dc:12")}
assert device.manufacturer == "Whatever"
assert device.name == "Beer"
assert device.model == "Glass"
assert device.sw_version == "0.1-beta"
async def test_entity_device_info_update(hass, mqtt_mock): async def test_entity_device_info_update(hass, mqtt_mock):
"""Test device registry update.""" """Test device registry update."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
entry.add_to_hass(hass)
await async_start(hass, "homeassistant", {}, entry)
registry = await hass.helpers.device_registry.async_get_registry()
config = { config = {
"platform": "mqtt", "platform": "mqtt",
"name": "Test 1", "name": "Test 1",
@ -566,61 +470,21 @@ async def test_entity_device_info_update(hass, mqtt_mock):
}, },
"unique_id": "veryunique", "unique_id": "veryunique",
} }
await help_test_entity_device_info_update(hass, mqtt_mock, lock.DOMAIN, config)
data = json.dumps(config)
async_fire_mqtt_message(hass, "homeassistant/lock/bla/config", data)
await hass.async_block_till_done()
device = registry.async_get_device({("mqtt", "helloworld")}, set())
assert device is not None
assert device.name == "Beer"
config["device"]["name"] = "Milk"
data = json.dumps(config)
async_fire_mqtt_message(hass, "homeassistant/lock/bla/config", data)
await hass.async_block_till_done()
device = registry.async_get_device({("mqtt", "helloworld")}, set())
assert device is not None
assert device.name == "Milk"
async def test_entity_id_update(hass, mqtt_mock): async def test_entity_id_update(hass, mqtt_mock):
"""Test MQTT subscriptions are managed when entity_id is updated.""" """Test MQTT subscriptions are managed when entity_id is updated."""
registry = mock_registry(hass, {}) config = {
mock_mqtt = await async_mock_mqtt_component(hass)
assert await async_setup_component(
hass,
lock.DOMAIN,
{
lock.DOMAIN: [ lock.DOMAIN: [
{ {
"platform": "mqtt", "platform": "mqtt",
"name": "beer", "name": "beer",
"state_topic": "test-topic", "state_topic": "test-topic",
"command_topic": "test-topic", "command_topic": "command-topic",
"availability_topic": "avty-topic", "availability_topic": "avty-topic",
"unique_id": "TOTALLY_UNIQUE", "unique_id": "TOTALLY_UNIQUE",
} }
] ]
}, }
) await help_test_entity_id_update(hass, mqtt_mock, lock.DOMAIN, config)
state = hass.states.get("lock.beer")
assert state is not None
assert mock_mqtt.async_subscribe.call_count == 2
mock_mqtt.async_subscribe.assert_any_call("test-topic", ANY, 0, "utf-8")
mock_mqtt.async_subscribe.assert_any_call("avty-topic", ANY, 0, "utf-8")
mock_mqtt.async_subscribe.reset_mock()
registry.async_update_entity("lock.beer", new_entity_id="lock.milk")
await hass.async_block_till_done()
state = hass.states.get("lock.beer")
assert state is None
state = hass.states.get("lock.milk")
assert state is not None
assert mock_mqtt.async_subscribe.call_count == 2
mock_mqtt.async_subscribe.assert_any_call("test-topic", ANY, 0, "utf-8")
mock_mqtt.async_subscribe.assert_any_call("avty-topic", ANY, 0, "utf-8")

View File

@ -1,7 +1,7 @@
"""The tests for the MQTT sensor platform.""" """The tests for the MQTT sensor platform."""
from datetime import datetime, timedelta from datetime import datetime, timedelta
import json import json
from unittest.mock import ANY, patch from unittest.mock import patch
from homeassistant.components import mqtt from homeassistant.components import mqtt
from homeassistant.components.mqtt.discovery import async_start from homeassistant.components.mqtt.discovery import async_start
@ -11,12 +11,24 @@ import homeassistant.core as ha
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
import homeassistant.util.dt as dt_util import homeassistant.util.dt as dt_util
from .common import (
help_test_discovery_broken,
help_test_discovery_removal,
help_test_discovery_update,
help_test_discovery_update_attr,
help_test_entity_device_info_update,
help_test_entity_device_info_with_identifier,
help_test_entity_id_update,
help_test_setting_attribute_via_mqtt_json_message,
help_test_unique_id,
help_test_update_with_json_attrs_bad_JSON,
help_test_update_with_json_attrs_not_dict,
)
from tests.common import ( from tests.common import (
MockConfigEntry, MockConfigEntry,
async_fire_mqtt_message, async_fire_mqtt_message,
async_fire_time_changed, async_fire_time_changed,
async_mock_mqtt_component,
mock_registry,
) )
@ -395,24 +407,18 @@ async def test_valid_device_class(hass, mqtt_mock):
async def test_setting_attribute_via_mqtt_json_message(hass, mqtt_mock): async def test_setting_attribute_via_mqtt_json_message(hass, mqtt_mock):
"""Test the setting of attribute via MQTT with JSON payload.""" """Test the setting of attribute via MQTT with JSON payload."""
assert await async_setup_component( config = {
hass,
sensor.DOMAIN,
{
sensor.DOMAIN: { sensor.DOMAIN: {
"platform": "mqtt", "platform": "mqtt",
"name": "test", "name": "test",
"state_topic": "test-topic", "state_topic": "test-topic",
"json_attributes_topic": "attr-topic", "json_attributes_topic": "attr-topic",
} }
}, }
await help_test_setting_attribute_via_mqtt_json_message(
hass, mqtt_mock, sensor.DOMAIN, config
) )
async_fire_mqtt_message(hass, "attr-topic", '{ "val": "100" }')
state = hass.states.get("sensor.test")
assert state.attributes.get("val") == "100"
async def test_setting_attribute_with_template(hass, mqtt_mock): async def test_setting_attribute_with_template(hass, mqtt_mock):
"""Test the setting of attribute via MQTT with JSON payload.""" """Test the setting of attribute via MQTT with JSON payload."""
@ -441,52 +447,36 @@ async def test_setting_attribute_with_template(hass, mqtt_mock):
async def test_update_with_json_attrs_not_dict(hass, mqtt_mock, caplog): async def test_update_with_json_attrs_not_dict(hass, mqtt_mock, caplog):
"""Test attributes get extracted from a JSON result.""" """Test attributes get extracted from a JSON result."""
assert await async_setup_component( config = {
hass,
sensor.DOMAIN,
{
sensor.DOMAIN: { sensor.DOMAIN: {
"platform": "mqtt", "platform": "mqtt",
"name": "test", "name": "test",
"state_topic": "test-topic", "state_topic": "test-topic",
"json_attributes_topic": "attr-topic", "json_attributes_topic": "attr-topic",
} }
}, }
await help_test_update_with_json_attrs_not_dict(
hass, mqtt_mock, caplog, sensor.DOMAIN, config
) )
async_fire_mqtt_message(hass, "attr-topic", '[ "list", "of", "things"]')
state = hass.states.get("sensor.test")
assert state.attributes.get("val") is None
assert "JSON result was not a dictionary" in caplog.text
async def test_update_with_json_attrs_bad_JSON(hass, mqtt_mock, caplog): async def test_update_with_json_attrs_bad_JSON(hass, mqtt_mock, caplog):
"""Test attributes get extracted from a JSON result.""" """Test attributes get extracted from a JSON result."""
assert await async_setup_component( config = {
hass,
sensor.DOMAIN,
{
sensor.DOMAIN: { sensor.DOMAIN: {
"platform": "mqtt", "platform": "mqtt",
"name": "test", "name": "test",
"state_topic": "test-topic", "state_topic": "test-topic",
"json_attributes_topic": "attr-topic", "json_attributes_topic": "attr-topic",
} }
}, }
await help_test_update_with_json_attrs_bad_JSON(
hass, mqtt_mock, caplog, sensor.DOMAIN, config
) )
async_fire_mqtt_message(hass, "attr-topic", "This is not JSON")
state = hass.states.get("sensor.test")
assert state.attributes.get("val") is None
assert "Erroneous JSON: This is not JSON" in caplog.text
async def test_discovery_update_attr(hass, mqtt_mock, caplog): async def test_discovery_update_attr(hass, mqtt_mock, caplog):
"""Test update of discovered MQTTAttributes.""" """Test update of discovered MQTTAttributes."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
await async_start(hass, "homeassistant", {}, entry)
data1 = ( data1 = (
'{ "name": "Beer",' '{ "name": "Beer",'
' "state_topic": "test_topic",' ' "state_topic": "test_topic",'
@ -497,34 +487,14 @@ async def test_discovery_update_attr(hass, mqtt_mock, caplog):
' "state_topic": "test_topic",' ' "state_topic": "test_topic",'
' "json_attributes_topic": "attr-topic2" }' ' "json_attributes_topic": "attr-topic2" }'
) )
async_fire_mqtt_message(hass, "homeassistant/sensor/bla/config", data1) await help_test_discovery_update_attr(
await hass.async_block_till_done() hass, mqtt_mock, caplog, sensor.DOMAIN, data1, data2
async_fire_mqtt_message(hass, "attr-topic1", '{ "val": "100" }') )
state = hass.states.get("sensor.beer")
assert state.attributes.get("val") == "100"
# Change json_attributes_topic
async_fire_mqtt_message(hass, "homeassistant/sensor/bla/config", data2)
await hass.async_block_till_done()
# Verify we are no longer subscribing to the old topic
async_fire_mqtt_message(hass, "attr-topic1", '{ "val": "50" }')
state = hass.states.get("sensor.beer")
assert state.attributes.get("val") == "100"
# Verify we are subscribing to the new topic
async_fire_mqtt_message(hass, "attr-topic2", '{ "val": "75" }')
state = hass.states.get("sensor.beer")
assert state.attributes.get("val") == "75"
async def test_unique_id(hass): async def test_unique_id(hass):
"""Test unique id option only creates one sensor per unique_id.""" """Test unique id option only creates one sensor per unique_id."""
await async_mock_mqtt_component(hass) config = {
assert await async_setup_component(
hass,
sensor.DOMAIN,
{
sensor.DOMAIN: [ sensor.DOMAIN: [
{ {
"platform": "mqtt", "platform": "mqtt",
@ -539,85 +509,36 @@ async def test_unique_id(hass):
"unique_id": "TOTALLY_UNIQUE", "unique_id": "TOTALLY_UNIQUE",
}, },
] ]
}, }
) await help_test_unique_id(hass, sensor.DOMAIN, config)
async_fire_mqtt_message(hass, "test-topic", "payload")
assert len(hass.states.async_all()) == 1
async def test_discovery_removal_sensor(hass, mqtt_mock, caplog): async def test_discovery_removal_sensor(hass, mqtt_mock, caplog):
"""Test removal of discovered sensor.""" """Test removal of discovered sensor."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
await async_start(hass, "homeassistant", {}, entry)
data = '{ "name": "Beer",' ' "state_topic": "test_topic" }' data = '{ "name": "Beer",' ' "state_topic": "test_topic" }'
async_fire_mqtt_message(hass, "homeassistant/sensor/bla/config", data) await help_test_discovery_removal(hass, mqtt_mock, caplog, sensor.DOMAIN, data)
await hass.async_block_till_done()
state = hass.states.get("sensor.beer")
assert state is not None
assert state.name == "Beer"
async_fire_mqtt_message(hass, "homeassistant/sensor/bla/config", "")
await hass.async_block_till_done()
state = hass.states.get("sensor.beer")
assert state is None
async def test_discovery_update_sensor(hass, mqtt_mock, caplog): async def test_discovery_update_sensor(hass, mqtt_mock, caplog):
"""Test update of discovered sensor.""" """Test update of discovered sensor."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
await async_start(hass, "homeassistant", {}, entry)
data1 = '{ "name": "Beer",' ' "state_topic": "test_topic" }' data1 = '{ "name": "Beer",' ' "state_topic": "test_topic" }'
data2 = '{ "name": "Milk",' ' "state_topic": "test_topic" }' data2 = '{ "name": "Milk",' ' "state_topic": "test_topic" }'
async_fire_mqtt_message(hass, "homeassistant/sensor/bla/config", data1) await help_test_discovery_update(
await hass.async_block_till_done() hass, mqtt_mock, caplog, sensor.DOMAIN, data1, data2
)
state = hass.states.get("sensor.beer")
assert state is not None
assert state.name == "Beer"
async_fire_mqtt_message(hass, "homeassistant/sensor/bla/config", data2)
await hass.async_block_till_done()
state = hass.states.get("sensor.beer")
assert state is not None
assert state.name == "Milk"
state = hass.states.get("sensor.milk")
assert state is None
async def test_discovery_broken(hass, mqtt_mock, caplog): async def test_discovery_broken(hass, mqtt_mock, caplog):
"""Test handling of bad discovery message.""" """Test handling of bad discovery message."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
await async_start(hass, "homeassistant", {}, entry)
data1 = '{ "name": "Beer",' ' "state_topic": "test_topic#" }' data1 = '{ "name": "Beer",' ' "state_topic": "test_topic#" }'
data2 = '{ "name": "Milk",' ' "state_topic": "test_topic" }' data2 = '{ "name": "Milk",' ' "state_topic": "test_topic" }'
await help_test_discovery_broken(
async_fire_mqtt_message(hass, "homeassistant/sensor/bla/config", data1) hass, mqtt_mock, caplog, sensor.DOMAIN, data1, data2
await hass.async_block_till_done() )
state = hass.states.get("sensor.beer")
assert state is None
async_fire_mqtt_message(hass, "homeassistant/sensor/bla/config", data2)
await hass.async_block_till_done()
state = hass.states.get("sensor.milk")
assert state is not None
assert state.name == "Milk"
state = hass.states.get("sensor.beer")
assert state is None
async def test_entity_device_info_with_identifier(hass, mqtt_mock): async def test_entity_device_info_with_identifier(hass, mqtt_mock):
"""Test MQTT sensor device registry integration.""" """Test MQTT sensor device registry integration."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
entry.add_to_hass(hass)
await async_start(hass, "homeassistant", {}, entry)
registry = await hass.helpers.device_registry.async_get_registry()
data = json.dumps( data = json.dumps(
{ {
"platform": "mqtt", "platform": "mqtt",
@ -634,26 +555,13 @@ async def test_entity_device_info_with_identifier(hass, mqtt_mock):
"unique_id": "veryunique", "unique_id": "veryunique",
} }
) )
async_fire_mqtt_message(hass, "homeassistant/sensor/bla/config", data) await help_test_entity_device_info_with_identifier(
await hass.async_block_till_done() hass, mqtt_mock, sensor.DOMAIN, data
)
device = registry.async_get_device({("mqtt", "helloworld")}, set())
assert device is not None
assert device.identifiers == {("mqtt", "helloworld")}
assert device.connections == {("mac", "02:5b:26:a8:dc:12")}
assert device.manufacturer == "Whatever"
assert device.name == "Beer"
assert device.model == "Glass"
assert device.sw_version == "0.1-beta"
async def test_entity_device_info_update(hass, mqtt_mock): async def test_entity_device_info_update(hass, mqtt_mock):
"""Test device registry update.""" """Test device registry update."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
entry.add_to_hass(hass)
await async_start(hass, "homeassistant", {}, entry)
registry = await hass.helpers.device_registry.async_get_registry()
config = { config = {
"platform": "mqtt", "platform": "mqtt",
"name": "Test 1", "name": "Test 1",
@ -668,33 +576,12 @@ async def test_entity_device_info_update(hass, mqtt_mock):
}, },
"unique_id": "veryunique", "unique_id": "veryunique",
} }
await help_test_entity_device_info_update(hass, mqtt_mock, sensor.DOMAIN, config)
data = json.dumps(config)
async_fire_mqtt_message(hass, "homeassistant/sensor/bla/config", data)
await hass.async_block_till_done()
device = registry.async_get_device({("mqtt", "helloworld")}, set())
assert device is not None
assert device.name == "Beer"
config["device"]["name"] = "Milk"
data = json.dumps(config)
async_fire_mqtt_message(hass, "homeassistant/sensor/bla/config", data)
await hass.async_block_till_done()
device = registry.async_get_device({("mqtt", "helloworld")}, set())
assert device is not None
assert device.name == "Milk"
async def test_entity_id_update(hass, mqtt_mock): async def test_entity_id_update(hass, mqtt_mock):
"""Test MQTT subscriptions are managed when entity_id is updated.""" """Test MQTT subscriptions are managed when entity_id is updated."""
registry = mock_registry(hass, {}) config = {
mock_mqtt = await async_mock_mqtt_component(hass)
assert await async_setup_component(
hass,
sensor.DOMAIN,
{
sensor.DOMAIN: [ sensor.DOMAIN: [
{ {
"platform": "mqtt", "platform": "mqtt",
@ -704,27 +591,8 @@ async def test_entity_id_update(hass, mqtt_mock):
"unique_id": "TOTALLY_UNIQUE", "unique_id": "TOTALLY_UNIQUE",
} }
] ]
}, }
) await help_test_entity_id_update(hass, mqtt_mock, sensor.DOMAIN, config)
state = hass.states.get("sensor.beer")
assert state is not None
assert mock_mqtt.async_subscribe.call_count == 2
mock_mqtt.async_subscribe.assert_any_call("test-topic", ANY, 0, "utf-8")
mock_mqtt.async_subscribe.assert_any_call("avty-topic", ANY, 0, "utf-8")
mock_mqtt.async_subscribe.reset_mock()
registry.async_update_entity("sensor.beer", new_entity_id="sensor.milk")
await hass.async_block_till_done()
state = hass.states.get("sensor.beer")
assert state is None
state = hass.states.get("sensor.milk")
assert state is not None
assert mock_mqtt.async_subscribe.call_count == 2
mock_mqtt.async_subscribe.assert_any_call("test-topic", ANY, 0, "utf-8")
mock_mqtt.async_subscribe.assert_any_call("avty-topic", ANY, 0, "utf-8")
async def test_entity_device_info_with_hub(hass, mqtt_mock): async def test_entity_device_info_with_hub(hass, mqtt_mock):

View File

@ -2,9 +2,8 @@
from copy import deepcopy from copy import deepcopy
import json import json
from homeassistant.components import mqtt, vacuum from homeassistant.components import vacuum
from homeassistant.components.mqtt import CONF_COMMAND_TOPIC, CONF_STATE_TOPIC from homeassistant.components.mqtt import CONF_COMMAND_TOPIC, CONF_STATE_TOPIC
from homeassistant.components.mqtt.discovery import async_start
from homeassistant.components.mqtt.vacuum import CONF_SCHEMA, schema_state as mqttvacuum from homeassistant.components.mqtt.vacuum import CONF_SCHEMA, schema_state as mqttvacuum
from homeassistant.components.mqtt.vacuum.schema import services_to_strings from homeassistant.components.mqtt.vacuum.schema import services_to_strings
from homeassistant.components.mqtt.vacuum.schema_state import SERVICE_TO_STRING from homeassistant.components.mqtt.vacuum.schema_state import SERVICE_TO_STRING
@ -32,11 +31,21 @@ from homeassistant.const import (
) )
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
from tests.common import ( from .common import (
MockConfigEntry, help_test_discovery_broken,
async_fire_mqtt_message, help_test_discovery_removal,
async_mock_mqtt_component, help_test_discovery_update,
help_test_discovery_update_attr,
help_test_entity_device_info_update,
help_test_entity_device_info_with_identifier,
help_test_entity_id_update,
help_test_setting_attribute_via_mqtt_json_message,
help_test_unique_id,
help_test_update_with_json_attrs_bad_JSON,
help_test_update_with_json_attrs_not_dict,
) )
from tests.common import async_fire_mqtt_message
from tests.components.vacuum import common from tests.components.vacuum import common
COMMAND_TOPIC = "vacuum/command" COMMAND_TOPIC = "vacuum/command"
@ -340,212 +349,123 @@ async def test_custom_availability_payload(hass, mqtt_mock):
assert state.state == STATE_UNAVAILABLE assert state.state == STATE_UNAVAILABLE
async def test_discovery_removal_vacuum(hass, mqtt_mock):
"""Test removal of discovered vacuum."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
await async_start(hass, "homeassistant", {}, entry)
data = '{ "name": "Beer",' ' "command_topic": "test_topic"}'
async_fire_mqtt_message(hass, "homeassistant/vacuum/bla/config", data)
await hass.async_block_till_done()
state = hass.states.get("vacuum.beer")
assert state is not None
assert state.name == "Beer"
async_fire_mqtt_message(hass, "homeassistant/vacuum/bla/config", "")
await hass.async_block_till_done()
state = hass.states.get("vacuum.beer")
assert state is None
async def test_discovery_broken(hass, mqtt_mock, caplog):
"""Test handling of bad discovery message."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
await async_start(hass, "homeassistant", {}, entry)
data1 = '{ "name": "Beer",' ' "command_topic": "test_topic#"}'
data2 = '{ "name": "Milk",' ' "command_topic": "test_topic"}'
async_fire_mqtt_message(hass, "homeassistant/vacuum/bla/config", data1)
await hass.async_block_till_done()
state = hass.states.get("vacuum.beer")
assert state is None
async_fire_mqtt_message(hass, "homeassistant/vacuum/bla/config", data2)
await hass.async_block_till_done()
state = hass.states.get("vacuum.milk")
assert state is not None
assert state.name == "Milk"
state = hass.states.get("vacuum.beer")
assert state is None
async def test_discovery_update_vacuum(hass, mqtt_mock):
"""Test update of discovered vacuum."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
await async_start(hass, "homeassistant", {}, entry)
data1 = '{ "name": "Beer",' ' "command_topic": "test_topic"}'
data2 = '{ "name": "Milk",' ' "command_topic": "test_topic"}'
async_fire_mqtt_message(hass, "homeassistant/vacuum/bla/config", data1)
await hass.async_block_till_done()
state = hass.states.get("vacuum.beer")
assert state is not None
assert state.name == "Beer"
async_fire_mqtt_message(hass, "homeassistant/vacuum/bla/config", data2)
await hass.async_block_till_done()
state = hass.states.get("vacuum.beer")
assert state is not None
assert state.name == "Milk"
state = hass.states.get("vacuum.milk")
assert state is None
async def test_setting_attribute_via_mqtt_json_message(hass, mqtt_mock): async def test_setting_attribute_via_mqtt_json_message(hass, mqtt_mock):
"""Test the setting of attribute via MQTT with JSON payload.""" """Test the setting of attribute via MQTT with JSON payload."""
assert await async_setup_component( config = {
hass,
vacuum.DOMAIN,
{
vacuum.DOMAIN: { vacuum.DOMAIN: {
"platform": "mqtt", "platform": "mqtt",
"schema": "state",
"name": "test", "name": "test",
"json_attributes_topic": "attr-topic", "json_attributes_topic": "attr-topic",
} }
}, }
await help_test_setting_attribute_via_mqtt_json_message(
hass, mqtt_mock, vacuum.DOMAIN, config
) )
async_fire_mqtt_message(hass, "attr-topic", '{ "val": "100" }')
state = hass.states.get("vacuum.test")
assert state.attributes.get("val") == "100"
async def test_update_with_json_attrs_not_dict(hass, mqtt_mock, caplog): async def test_update_with_json_attrs_not_dict(hass, mqtt_mock, caplog):
"""Test attributes get extracted from a JSON result.""" """Test attributes get extracted from a JSON result."""
assert await async_setup_component( config = {
hass,
vacuum.DOMAIN,
{
vacuum.DOMAIN: { vacuum.DOMAIN: {
"platform": "mqtt", "platform": "mqtt",
"schema": "state",
"name": "test", "name": "test",
"json_attributes_topic": "attr-topic", "json_attributes_topic": "attr-topic",
} }
}, }
await help_test_update_with_json_attrs_not_dict(
hass, mqtt_mock, caplog, vacuum.DOMAIN, config
) )
async_fire_mqtt_message(hass, "attr-topic", '[ "list", "of", "things"]')
state = hass.states.get("vacuum.test")
assert state.attributes.get("val") is None
assert "JSON result was not a dictionary" in caplog.text
async def test_update_with_json_attrs_bad_json(hass, mqtt_mock, caplog): async def test_update_with_json_attrs_bad_json(hass, mqtt_mock, caplog):
"""Test attributes get extracted from a JSON result.""" """Test attributes get extracted from a JSON result."""
assert await async_setup_component( config = {
hass,
vacuum.DOMAIN,
{
vacuum.DOMAIN: { vacuum.DOMAIN: {
"platform": "mqtt", "platform": "mqtt",
"schema": "state",
"name": "test", "name": "test",
"json_attributes_topic": "attr-topic", "json_attributes_topic": "attr-topic",
} }
}, }
await help_test_update_with_json_attrs_bad_JSON(
hass, mqtt_mock, caplog, vacuum.DOMAIN, config
) )
async_fire_mqtt_message(hass, "attr-topic", "This is not JSON")
state = hass.states.get("vacuum.test")
assert state.attributes.get("val") is None
assert "Erroneous JSON: This is not JSON" in caplog.text
async def test_discovery_update_attr(hass, mqtt_mock, caplog): async def test_discovery_update_attr(hass, mqtt_mock, caplog):
"""Test update of discovered MQTTAttributes.""" """Test update of discovered MQTTAttributes."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
await async_start(hass, "homeassistant", {}, entry)
data1 = ( data1 = (
'{ "name": "Beer",' '{ "name": "Beer",'
' "schema": "state",'
' "command_topic": "test_topic",' ' "command_topic": "test_topic",'
' "json_attributes_topic": "attr-topic1" }' ' "json_attributes_topic": "attr-topic1" }'
) )
data2 = ( data2 = (
'{ "name": "Beer",' '{ "name": "Beer",'
' "schema": "state",'
' "command_topic": "test_topic",' ' "command_topic": "test_topic",'
' "json_attributes_topic": "attr-topic2" }' ' "json_attributes_topic": "attr-topic2" }'
) )
async_fire_mqtt_message(hass, "homeassistant/vacuum/bla/config", data1) await help_test_discovery_update_attr(
await hass.async_block_till_done() hass, mqtt_mock, caplog, vacuum.DOMAIN, data1, data2
async_fire_mqtt_message(hass, "attr-topic1", '{ "val": "100" }') )
state = hass.states.get("vacuum.beer")
assert state.attributes.get("val") == "100"
# Change json_attributes_topic
async_fire_mqtt_message(hass, "homeassistant/vacuum/bla/config", data2)
await hass.async_block_till_done()
# Verify we are no longer subscribing to the old topic
async_fire_mqtt_message(hass, "attr-topic1", '{ "val": "50" }')
state = hass.states.get("vacuum.beer")
assert state.attributes.get("val") == "100"
# Verify we are subscribing to the new topic
async_fire_mqtt_message(hass, "attr-topic2", '{ "val": "75" }')
state = hass.states.get("vacuum.beer")
assert state.attributes.get("val") == "75"
async def test_unique_id(hass, mqtt_mock): async def test_unique_id(hass, mqtt_mock):
"""Test unique id option only creates one vacuum per unique_id.""" """Test unique id option only creates one vacuum per unique_id."""
await async_mock_mqtt_component(hass) config = {
assert await async_setup_component(
hass,
vacuum.DOMAIN,
{
vacuum.DOMAIN: [ vacuum.DOMAIN: [
{ {
"platform": "mqtt", "platform": "mqtt",
"schema": "state",
"name": "Test 1", "name": "Test 1",
"command_topic": "command-topic", "command_topic": "command-topic",
"unique_id": "TOTALLY_UNIQUE", "unique_id": "TOTALLY_UNIQUE",
}, },
{ {
"platform": "mqtt", "platform": "mqtt",
"schema": "state",
"name": "Test 2", "name": "Test 2",
"command_topic": "command-topic", "command_topic": "command-topic",
"unique_id": "TOTALLY_UNIQUE", "unique_id": "TOTALLY_UNIQUE",
}, },
] ]
}, }
await help_test_unique_id(hass, vacuum.DOMAIN, config)
async def test_discovery_removal_vacuum(hass, mqtt_mock, caplog):
"""Test removal of discovered vacuum."""
data = '{ "schema": "state", "name": "Beer",' ' "command_topic": "test_topic"}'
await help_test_discovery_removal(hass, mqtt_mock, caplog, vacuum.DOMAIN, data)
async def test_discovery_update_vacuum(hass, mqtt_mock, caplog):
"""Test update of discovered vacuum."""
data1 = '{ "schema": "state", "name": "Beer",' ' "command_topic": "test_topic"}'
data2 = '{ "schema": "state", "name": "Milk",' ' "command_topic": "test_topic"}'
await help_test_discovery_update(
hass, mqtt_mock, caplog, vacuum.DOMAIN, data1, data2
) )
async_fire_mqtt_message(hass, "test-topic", "payload")
assert len(hass.states.async_entity_ids()) == 1 async def test_discovery_broken(hass, mqtt_mock, caplog):
"""Test handling of bad discovery message."""
data1 = '{ "schema": "state", "name": "Beer",' ' "command_topic": "test_topic#"}'
data2 = '{ "schema": "state", "name": "Milk",' ' "command_topic": "test_topic"}'
await help_test_discovery_broken(
hass, mqtt_mock, caplog, vacuum.DOMAIN, data1, data2
)
async def test_entity_device_info_with_identifier(hass, mqtt_mock): async def test_entity_device_info_with_identifier(hass, mqtt_mock):
"""Test MQTT vacuum device registry integration.""" """Test MQTT vacuum device registry integration."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
entry.add_to_hass(hass)
await async_start(hass, "homeassistant", {}, entry)
registry = await hass.helpers.device_registry.async_get_registry()
data = json.dumps( data = json.dumps(
{ {
"platform": "mqtt", "platform": "mqtt",
"schema": "state",
"name": "Test 1", "name": "Test 1",
"command_topic": "test-command-topic", "command_topic": "test-command-topic",
"device": { "device": {
@ -559,28 +479,16 @@ async def test_entity_device_info_with_identifier(hass, mqtt_mock):
"unique_id": "veryunique", "unique_id": "veryunique",
} }
) )
async_fire_mqtt_message(hass, "homeassistant/vacuum/bla/config", data) await help_test_entity_device_info_with_identifier(
await hass.async_block_till_done() hass, mqtt_mock, vacuum.DOMAIN, data
)
device = registry.async_get_device({("mqtt", "helloworld")}, set())
assert device is not None
assert device.identifiers == {("mqtt", "helloworld")}
assert device.connections == {("mac", "02:5b:26:a8:dc:12")}
assert device.manufacturer == "Whatever"
assert device.name == "Beer"
assert device.model == "Glass"
assert device.sw_version == "0.1-beta"
async def test_entity_device_info_update(hass, mqtt_mock): async def test_entity_device_info_update(hass, mqtt_mock):
"""Test device registry update.""" """Test device registry update."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
entry.add_to_hass(hass)
await async_start(hass, "homeassistant", {}, entry)
registry = await hass.helpers.device_registry.async_get_registry()
config = { config = {
"platform": "mqtt", "platform": "mqtt",
"schema": "state",
"name": "Test 1", "name": "Test 1",
"command_topic": "test-command-topic", "command_topic": "test-command-topic",
"device": { "device": {
@ -593,20 +501,22 @@ async def test_entity_device_info_update(hass, mqtt_mock):
}, },
"unique_id": "veryunique", "unique_id": "veryunique",
} }
await help_test_entity_device_info_update(hass, mqtt_mock, vacuum.DOMAIN, config)
data = json.dumps(config)
async_fire_mqtt_message(hass, "homeassistant/vacuum/bla/config", data)
await hass.async_block_till_done()
device = registry.async_get_device({("mqtt", "helloworld")}, set()) async def test_entity_id_update(hass, mqtt_mock):
assert device is not None """Test MQTT subscriptions are managed when entity_id is updated."""
assert device.name == "Beer" config = {
vacuum.DOMAIN: [
config["device"]["name"] = "Milk" {
data = json.dumps(config) "platform": "mqtt",
async_fire_mqtt_message(hass, "homeassistant/vacuum/bla/config", data) "schema": "state",
await hass.async_block_till_done() "name": "beer",
"state_topic": "test-topic",
device = registry.async_get_device({("mqtt", "helloworld")}, set()) "command_topic": "command-topic",
assert device is not None "availability_topic": "avty-topic",
assert device.name == "Milk" "unique_id": "TOTALLY_UNIQUE",
}
]
}
await help_test_entity_id_update(hass, mqtt_mock, vacuum.DOMAIN, config)

View File

@ -1,12 +1,10 @@
"""The tests for the MQTT switch platform.""" """The tests for the MQTT switch platform."""
import json import json
from unittest.mock import ANY
from asynctest import patch from asynctest import patch
import pytest import pytest
from homeassistant.components import mqtt, switch from homeassistant.components import switch
from homeassistant.components.mqtt.discovery import async_start
from homeassistant.const import ( from homeassistant.const import (
ATTR_ASSUMED_STATE, ATTR_ASSUMED_STATE,
STATE_OFF, STATE_OFF,
@ -16,13 +14,21 @@ from homeassistant.const import (
import homeassistant.core as ha import homeassistant.core as ha
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
from tests.common import ( from .common import (
MockConfigEntry, help_test_discovery_broken,
async_fire_mqtt_message, help_test_discovery_removal,
async_mock_mqtt_component, help_test_discovery_update,
mock_coro, help_test_discovery_update_attr,
mock_registry, help_test_entity_device_info_update,
help_test_entity_device_info_with_identifier,
help_test_entity_id_update,
help_test_setting_attribute_via_mqtt_json_message,
help_test_unique_id,
help_test_update_with_json_attrs_bad_JSON,
help_test_update_with_json_attrs_not_dict,
) )
from tests.common import async_fire_mqtt_message, async_mock_mqtt_component, mock_coro
from tests.components.switch import common from tests.components.switch import common
@ -265,73 +271,51 @@ async def test_custom_state_payload(hass, mock_publish):
async def test_setting_attribute_via_mqtt_json_message(hass, mqtt_mock): async def test_setting_attribute_via_mqtt_json_message(hass, mqtt_mock):
"""Test the setting of attribute via MQTT with JSON payload.""" """Test the setting of attribute via MQTT with JSON payload."""
assert await async_setup_component( config = {
hass,
switch.DOMAIN,
{
switch.DOMAIN: { switch.DOMAIN: {
"platform": "mqtt", "platform": "mqtt",
"name": "test", "name": "test",
"command_topic": "test-topic", "command_topic": "test-topic",
"json_attributes_topic": "attr-topic", "json_attributes_topic": "attr-topic",
} }
}, }
await help_test_setting_attribute_via_mqtt_json_message(
hass, mqtt_mock, switch.DOMAIN, config
) )
async_fire_mqtt_message(hass, "attr-topic", '{ "val": "100" }')
state = hass.states.get("switch.test")
assert state.attributes.get("val") == "100"
async def test_update_with_json_attrs_not_dict(hass, mqtt_mock, caplog): async def test_update_with_json_attrs_not_dict(hass, mqtt_mock, caplog):
"""Test attributes get extracted from a JSON result.""" """Test attributes get extracted from a JSON result."""
assert await async_setup_component( config = {
hass,
switch.DOMAIN,
{
switch.DOMAIN: { switch.DOMAIN: {
"platform": "mqtt", "platform": "mqtt",
"name": "test", "name": "test",
"command_topic": "test-topic", "command_topic": "test-topic",
"json_attributes_topic": "attr-topic", "json_attributes_topic": "attr-topic",
} }
}, }
await help_test_update_with_json_attrs_not_dict(
hass, mqtt_mock, caplog, switch.DOMAIN, config
) )
async_fire_mqtt_message(hass, "attr-topic", '[ "list", "of", "things"]')
state = hass.states.get("switch.test")
assert state.attributes.get("val") is None
assert "JSON result was not a dictionary" in caplog.text
async def test_update_with_json_attrs_bad_JSON(hass, mqtt_mock, caplog): async def test_update_with_json_attrs_bad_JSON(hass, mqtt_mock, caplog):
"""Test attributes get extracted from a JSON result.""" """Test attributes get extracted from a JSON result."""
assert await async_setup_component( config = {
hass,
switch.DOMAIN,
{
switch.DOMAIN: { switch.DOMAIN: {
"platform": "mqtt", "platform": "mqtt",
"name": "test", "name": "test",
"command_topic": "test-topic", "command_topic": "test-topic",
"json_attributes_topic": "attr-topic", "json_attributes_topic": "attr-topic",
} }
}, }
await help_test_update_with_json_attrs_bad_JSON(
hass, mqtt_mock, caplog, switch.DOMAIN, config
) )
async_fire_mqtt_message(hass, "attr-topic", "This is not JSON")
state = hass.states.get("switch.test")
assert state.attributes.get("val") is None
assert "Erroneous JSON: This is not JSON" in caplog.text
async def test_discovery_update_attr(hass, mqtt_mock, caplog): async def test_discovery_update_attr(hass, mqtt_mock, caplog):
"""Test update of discovered MQTTAttributes.""" """Test update of discovered MQTTAttributes."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
await async_start(hass, "homeassistant", {}, entry)
data1 = ( data1 = (
'{ "name": "Beer",' '{ "name": "Beer",'
' "command_topic": "test_topic",' ' "command_topic": "test_topic",'
@ -342,34 +326,14 @@ async def test_discovery_update_attr(hass, mqtt_mock, caplog):
' "command_topic": "test_topic",' ' "command_topic": "test_topic",'
' "json_attributes_topic": "attr-topic2" }' ' "json_attributes_topic": "attr-topic2" }'
) )
async_fire_mqtt_message(hass, "homeassistant/switch/bla/config", data1) await help_test_discovery_update_attr(
await hass.async_block_till_done() hass, mqtt_mock, caplog, switch.DOMAIN, data1, data2
async_fire_mqtt_message(hass, "attr-topic1", '{ "val": "100" }') )
state = hass.states.get("switch.beer")
assert state.attributes.get("val") == "100"
# Change json_attributes_topic
async_fire_mqtt_message(hass, "homeassistant/switch/bla/config", data2)
await hass.async_block_till_done()
# Verify we are no longer subscribing to the old topic
async_fire_mqtt_message(hass, "attr-topic1", '{ "val": "50" }')
state = hass.states.get("switch.beer")
assert state.attributes.get("val") == "100"
# Verify we are subscribing to the new topic
async_fire_mqtt_message(hass, "attr-topic2", '{ "val": "75" }')
state = hass.states.get("switch.beer")
assert state.attributes.get("val") == "75"
async def test_unique_id(hass): async def test_unique_id(hass):
"""Test unique id option only creates one switch per unique_id.""" """Test unique id option only creates one switch per unique_id."""
await async_mock_mqtt_component(hass) config = {
assert await async_setup_component(
hass,
switch.DOMAIN,
{
switch.DOMAIN: [ switch.DOMAIN: [
{ {
"platform": "mqtt", "platform": "mqtt",
@ -386,44 +350,22 @@ async def test_unique_id(hass):
"unique_id": "TOTALLY_UNIQUE", "unique_id": "TOTALLY_UNIQUE",
}, },
] ]
}, }
) await help_test_unique_id(hass, switch.DOMAIN, config)
async_fire_mqtt_message(hass, "test-topic", "payload")
assert len(hass.states.async_entity_ids()) == 1
async def test_discovery_removal_switch(hass, mqtt_mock, caplog): async def test_discovery_removal_switch(hass, mqtt_mock, caplog):
"""Test removal of discovered switch.""" """Test removal of discovered switch."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
await async_start(hass, "homeassistant", {}, entry)
data = ( data = (
'{ "name": "Beer",' '{ "name": "Beer",'
' "state_topic": "test_topic",' ' "state_topic": "test_topic",'
' "command_topic": "test_topic" }' ' "command_topic": "test_topic" }'
) )
await help_test_discovery_removal(hass, mqtt_mock, caplog, switch.DOMAIN, data)
async_fire_mqtt_message(hass, "homeassistant/switch/bla/config", data)
await hass.async_block_till_done()
state = hass.states.get("switch.beer")
assert state is not None
assert state.name == "Beer"
async_fire_mqtt_message(hass, "homeassistant/switch/bla/config", "")
await hass.async_block_till_done()
state = hass.states.get("switch.beer")
assert state is None
async def test_discovery_update_switch(hass, mqtt_mock, caplog): async def test_discovery_update_switch(hass, mqtt_mock, caplog):
"""Test update of discovered switch.""" """Test update of discovered switch."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
await async_start(hass, "homeassistant", {}, entry)
data1 = ( data1 = (
'{ "name": "Beer",' '{ "name": "Beer",'
' "state_topic": "test_topic",' ' "state_topic": "test_topic",'
@ -434,59 +376,26 @@ async def test_discovery_update_switch(hass, mqtt_mock, caplog):
' "state_topic": "test_topic",' ' "state_topic": "test_topic",'
' "command_topic": "test_topic" }' ' "command_topic": "test_topic" }'
) )
await help_test_discovery_update(
async_fire_mqtt_message(hass, "homeassistant/switch/bla/config", data1) hass, mqtt_mock, caplog, switch.DOMAIN, data1, data2
await hass.async_block_till_done() )
state = hass.states.get("switch.beer")
assert state is not None
assert state.name == "Beer"
async_fire_mqtt_message(hass, "homeassistant/switch/bla/config", data2)
await hass.async_block_till_done()
state = hass.states.get("switch.beer")
assert state is not None
assert state.name == "Milk"
state = hass.states.get("switch.milk")
assert state is None
async def test_discovery_broken(hass, mqtt_mock, caplog): async def test_discovery_broken(hass, mqtt_mock, caplog):
"""Test handling of bad discovery message.""" """Test handling of bad discovery message."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
await async_start(hass, "homeassistant", {}, entry)
data1 = '{ "name": "Beer" }' data1 = '{ "name": "Beer" }'
data2 = ( data2 = (
'{ "name": "Milk",' '{ "name": "Milk",'
' "state_topic": "test_topic",' ' "state_topic": "test_topic",'
' "command_topic": "test_topic" }' ' "command_topic": "test_topic" }'
) )
await help_test_discovery_broken(
async_fire_mqtt_message(hass, "homeassistant/switch/bla/config", data1) hass, mqtt_mock, caplog, switch.DOMAIN, data1, data2
await hass.async_block_till_done() )
state = hass.states.get("switch.beer")
assert state is None
async_fire_mqtt_message(hass, "homeassistant/switch/bla/config", data2)
await hass.async_block_till_done()
state = hass.states.get("switch.milk")
assert state is not None
assert state.name == "Milk"
state = hass.states.get("switch.beer")
assert state is None
async def test_entity_device_info_with_identifier(hass, mqtt_mock): async def test_entity_device_info_with_identifier(hass, mqtt_mock):
"""Test MQTT switch device registry integration.""" """Test MQTT switch device registry integration."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
entry.add_to_hass(hass)
await async_start(hass, "homeassistant", {}, entry)
registry = await hass.helpers.device_registry.async_get_registry()
data = json.dumps( data = json.dumps(
{ {
"platform": "mqtt", "platform": "mqtt",
@ -504,26 +413,13 @@ async def test_entity_device_info_with_identifier(hass, mqtt_mock):
"unique_id": "veryunique", "unique_id": "veryunique",
} }
) )
async_fire_mqtt_message(hass, "homeassistant/switch/bla/config", data) await help_test_entity_device_info_with_identifier(
await hass.async_block_till_done() hass, mqtt_mock, switch.DOMAIN, data
)
device = registry.async_get_device({("mqtt", "helloworld")}, set())
assert device is not None
assert device.identifiers == {("mqtt", "helloworld")}
assert device.connections == {("mac", "02:5b:26:a8:dc:12")}
assert device.manufacturer == "Whatever"
assert device.name == "Beer"
assert device.model == "Glass"
assert device.sw_version == "0.1-beta"
async def test_entity_device_info_update(hass, mqtt_mock): async def test_entity_device_info_update(hass, mqtt_mock):
"""Test device registry update.""" """Test device registry update."""
entry = MockConfigEntry(domain=mqtt.DOMAIN)
entry.add_to_hass(hass)
await async_start(hass, "homeassistant", {}, entry)
registry = await hass.helpers.device_registry.async_get_registry()
config = { config = {
"platform": "mqtt", "platform": "mqtt",
"name": "Test 1", "name": "Test 1",
@ -539,33 +435,12 @@ async def test_entity_device_info_update(hass, mqtt_mock):
}, },
"unique_id": "veryunique", "unique_id": "veryunique",
} }
await help_test_entity_device_info_update(hass, mqtt_mock, switch.DOMAIN, config)
data = json.dumps(config)
async_fire_mqtt_message(hass, "homeassistant/switch/bla/config", data)
await hass.async_block_till_done()
device = registry.async_get_device({("mqtt", "helloworld")}, set())
assert device is not None
assert device.name == "Beer"
config["device"]["name"] = "Milk"
data = json.dumps(config)
async_fire_mqtt_message(hass, "homeassistant/switch/bla/config", data)
await hass.async_block_till_done()
device = registry.async_get_device({("mqtt", "helloworld")}, set())
assert device is not None
assert device.name == "Milk"
async def test_entity_id_update(hass, mqtt_mock): async def test_entity_id_update(hass, mqtt_mock):
"""Test MQTT subscriptions are managed when entity_id is updated.""" """Test MQTT subscriptions are managed when entity_id is updated."""
registry = mock_registry(hass, {}) config = {
mock_mqtt = await async_mock_mqtt_component(hass)
assert await async_setup_component(
hass,
switch.DOMAIN,
{
switch.DOMAIN: [ switch.DOMAIN: [
{ {
"platform": "mqtt", "platform": "mqtt",
@ -576,24 +451,5 @@ async def test_entity_id_update(hass, mqtt_mock):
"unique_id": "TOTALLY_UNIQUE", "unique_id": "TOTALLY_UNIQUE",
} }
] ]
}, }
) await help_test_entity_id_update(hass, mqtt_mock, switch.DOMAIN, config)
state = hass.states.get("switch.beer")
assert state is not None
assert mock_mqtt.async_subscribe.call_count == 2
mock_mqtt.async_subscribe.assert_any_call("test-topic", ANY, 0, "utf-8")
mock_mqtt.async_subscribe.assert_any_call("avty-topic", ANY, 0, "utf-8")
mock_mqtt.async_subscribe.reset_mock()
registry.async_update_entity("switch.beer", new_entity_id="switch.milk")
await hass.async_block_till_done()
state = hass.states.get("switch.beer")
assert state is None
state = hass.states.get("switch.milk")
assert state is not None
assert mock_mqtt.async_subscribe.call_count == 2
mock_mqtt.async_subscribe.assert_any_call("test-topic", ANY, 0, "utf-8")
mock_mqtt.async_subscribe.assert_any_call("avty-topic", ANY, 0, "utf-8")