diff --git a/tests/components/mqtt/test_binary_sensor.py b/tests/components/mqtt/test_binary_sensor.py index 3e6e36cd050..2c8faf66549 100644 --- a/tests/components/mqtt/test_binary_sensor.py +++ b/tests/components/mqtt/test_binary_sensor.py @@ -1,285 +1,269 @@ """The tests for the MQTT binary sensor platform.""" from datetime import timedelta import json -import unittest -from unittest.mock import ANY, Mock +from unittest.mock import ANY from homeassistant.components import binary_sensor, mqtt from homeassistant.components.mqtt.discovery import async_start from homeassistant.const import ( EVENT_STATE_CHANGED, STATE_OFF, STATE_ON, STATE_UNAVAILABLE) import homeassistant.core as ha -from homeassistant.setup import async_setup_component, setup_component +from homeassistant.setup import async_setup_component import homeassistant.util.dt as dt_util from tests.common import ( - MockConfigEntry, async_fire_mqtt_message, async_mock_mqtt_component, - fire_mqtt_message, fire_time_changed, get_test_home_assistant, - mock_component, mock_mqtt_component, mock_registry) + MockConfigEntry, async_fire_mqtt_message, async_fire_time_changed, + async_mock_mqtt_component, mock_registry) -class TestSensorMQTT(unittest.TestCase): - """Test the MQTT sensor.""" +async def test_setting_sensor_value_via_mqtt_message(hass, mqtt_mock): + """Test the setting of the value via MQTT.""" + assert await async_setup_component(hass, binary_sensor.DOMAIN, { + binary_sensor.DOMAIN: { + 'platform': 'mqtt', + 'name': 'test', + 'state_topic': 'test-topic', + 'payload_on': 'ON', + 'payload_off': 'OFF', + } + }) - def setUp(self): # pylint: disable=invalid-name - """Set up things to be run when tests are started.""" - self.hass = get_test_home_assistant() - self.hass.config_entries._async_schedule_save = Mock() - mock_mqtt_component(self.hass) + state = hass.states.get('binary_sensor.test') + assert STATE_OFF == state.state - def tearDown(self): # pylint: disable=invalid-name - """Stop everything that was started.""" - self.hass.stop() + async_fire_mqtt_message(hass, 'test-topic', 'ON') + state = hass.states.get('binary_sensor.test') + assert STATE_ON == state.state - def test_setting_sensor_value_via_mqtt_message(self): - """Test the setting of the value via MQTT.""" - assert setup_component(self.hass, binary_sensor.DOMAIN, { - binary_sensor.DOMAIN: { - 'platform': 'mqtt', - 'name': 'test', - 'state_topic': 'test-topic', - 'payload_on': 'ON', - 'payload_off': 'OFF', - } - }) + async_fire_mqtt_message(hass, 'test-topic', 'OFF') + state = hass.states.get('binary_sensor.test') + assert STATE_OFF == state.state - state = self.hass.states.get('binary_sensor.test') - assert STATE_OFF == state.state - fire_mqtt_message(self.hass, 'test-topic', 'ON') - self.hass.block_till_done() - state = self.hass.states.get('binary_sensor.test') - assert STATE_ON == state.state +async def test_setting_sensor_value_via_mqtt_message_and_template( + hass, mqtt_mock): + """Test the setting of the value via MQTT.""" + assert await async_setup_component(hass, binary_sensor.DOMAIN, { + binary_sensor.DOMAIN: { + 'platform': 'mqtt', + 'name': 'test', + 'state_topic': 'test-topic', + 'payload_on': 'ON', + 'payload_off': 'OFF', + 'value_template': '{%if is_state(entity_id,\"on\")-%}OFF' + '{%-else-%}ON{%-endif%}' + } + }) - fire_mqtt_message(self.hass, 'test-topic', 'OFF') - self.hass.block_till_done() - state = self.hass.states.get('binary_sensor.test') - assert STATE_OFF == state.state + state = hass.states.get('binary_sensor.test') + assert STATE_OFF == state.state - def test_setting_sensor_value_via_mqtt_message_and_template(self): - """Test the setting of the value via MQTT.""" - assert setup_component(self.hass, binary_sensor.DOMAIN, { - binary_sensor.DOMAIN: { - 'platform': 'mqtt', - 'name': 'test', - 'state_topic': 'test-topic', - 'payload_on': 'ON', - 'payload_off': 'OFF', - 'value_template': '{%if is_state(entity_id,\"on\")-%}OFF' - '{%-else-%}ON{%-endif%}' - } - }) + async_fire_mqtt_message(hass, 'test-topic', '') + state = hass.states.get('binary_sensor.test') + assert STATE_ON == state.state - state = self.hass.states.get('binary_sensor.test') - assert STATE_OFF == state.state + async_fire_mqtt_message(hass, 'test-topic', '') + state = hass.states.get('binary_sensor.test') + assert STATE_OFF == state.state - fire_mqtt_message(self.hass, 'test-topic', '') - self.hass.block_till_done() - state = self.hass.states.get('binary_sensor.test') - assert STATE_ON == state.state - fire_mqtt_message(self.hass, 'test-topic', '') - self.hass.block_till_done() - state = self.hass.states.get('binary_sensor.test') - assert STATE_OFF == state.state +async def test_valid_device_class(hass, mqtt_mock): + """Test the setting of a valid sensor class.""" + assert await async_setup_component(hass, binary_sensor.DOMAIN, { + binary_sensor.DOMAIN: { + 'platform': 'mqtt', + 'name': 'test', + 'device_class': 'motion', + 'state_topic': 'test-topic', + } + }) - def test_valid_device_class(self): - """Test the setting of a valid sensor class.""" - assert setup_component(self.hass, binary_sensor.DOMAIN, { - binary_sensor.DOMAIN: { - 'platform': 'mqtt', - 'name': 'test', - 'device_class': 'motion', - 'state_topic': 'test-topic', - } - }) + state = hass.states.get('binary_sensor.test') + assert 'motion' == state.attributes.get('device_class') - state = self.hass.states.get('binary_sensor.test') - assert 'motion' == state.attributes.get('device_class') - def test_invalid_device_class(self): - """Test the setting of an invalid sensor class.""" - assert setup_component(self.hass, binary_sensor.DOMAIN, { - binary_sensor.DOMAIN: { - 'platform': 'mqtt', - 'name': 'test', - 'device_class': 'abc123', - 'state_topic': 'test-topic', - } - }) +async def test_invalid_device_class(hass, mqtt_mock): + """Test the setting of an invalid sensor class.""" + assert await async_setup_component(hass, binary_sensor.DOMAIN, { + binary_sensor.DOMAIN: { + 'platform': 'mqtt', + 'name': 'test', + 'device_class': 'abc123', + 'state_topic': 'test-topic', + } + }) - state = self.hass.states.get('binary_sensor.test') - assert state is None + state = hass.states.get('binary_sensor.test') + assert state is None - def test_availability_without_topic(self): - """Test availability without defined availability topic.""" - assert setup_component(self.hass, binary_sensor.DOMAIN, { - binary_sensor.DOMAIN: { - 'platform': 'mqtt', - 'name': 'test', - 'state_topic': 'state-topic', - } - }) - state = self.hass.states.get('binary_sensor.test') - assert STATE_UNAVAILABLE != state.state +async def test_availability_without_topic(hass, mqtt_mock): + """Test availability without defined availability topic.""" + assert await async_setup_component(hass, binary_sensor.DOMAIN, { + binary_sensor.DOMAIN: { + 'platform': 'mqtt', + 'name': 'test', + 'state_topic': 'state-topic', + } + }) - def test_availability_by_defaults(self): - """Test availability by defaults with defined topic.""" - assert setup_component(self.hass, binary_sensor.DOMAIN, { - binary_sensor.DOMAIN: { - 'platform': 'mqtt', - 'name': 'test', - 'state_topic': 'state-topic', - 'availability_topic': 'availability-topic' - } - }) + state = hass.states.get('binary_sensor.test') + assert STATE_UNAVAILABLE != state.state - state = self.hass.states.get('binary_sensor.test') - assert STATE_UNAVAILABLE == state.state - fire_mqtt_message(self.hass, 'availability-topic', 'online') - self.hass.block_till_done() +async def test_availability_by_defaults(hass, mqtt_mock): + """Test availability by defaults with defined topic.""" + assert await async_setup_component(hass, binary_sensor.DOMAIN, { + binary_sensor.DOMAIN: { + 'platform': 'mqtt', + 'name': 'test', + 'state_topic': 'state-topic', + 'availability_topic': 'availability-topic' + } + }) - state = self.hass.states.get('binary_sensor.test') - assert STATE_UNAVAILABLE != state.state + state = hass.states.get('binary_sensor.test') + assert STATE_UNAVAILABLE == state.state - fire_mqtt_message(self.hass, 'availability-topic', 'offline') - self.hass.block_till_done() + async_fire_mqtt_message(hass, 'availability-topic', 'online') - state = self.hass.states.get('binary_sensor.test') - assert STATE_UNAVAILABLE == state.state + state = hass.states.get('binary_sensor.test') + assert STATE_UNAVAILABLE != state.state - def test_availability_by_custom_payload(self): - """Test availability by custom payload with defined topic.""" - assert setup_component(self.hass, binary_sensor.DOMAIN, { - binary_sensor.DOMAIN: { - 'platform': 'mqtt', - 'name': 'test', - 'state_topic': 'state-topic', - 'availability_topic': 'availability-topic', - 'payload_available': 'good', - 'payload_not_available': 'nogood' - } - }) + async_fire_mqtt_message(hass, 'availability-topic', 'offline') - state = self.hass.states.get('binary_sensor.test') - assert STATE_UNAVAILABLE == state.state + state = hass.states.get('binary_sensor.test') + assert STATE_UNAVAILABLE == state.state - fire_mqtt_message(self.hass, 'availability-topic', 'good') - self.hass.block_till_done() - state = self.hass.states.get('binary_sensor.test') - assert STATE_UNAVAILABLE != state.state +async def test_availability_by_custom_payload(hass, mqtt_mock): + """Test availability by custom payload with defined topic.""" + assert await async_setup_component(hass, binary_sensor.DOMAIN, { + binary_sensor.DOMAIN: { + 'platform': 'mqtt', + 'name': 'test', + 'state_topic': 'state-topic', + 'availability_topic': 'availability-topic', + 'payload_available': 'good', + 'payload_not_available': 'nogood' + } + }) - fire_mqtt_message(self.hass, 'availability-topic', 'nogood') - self.hass.block_till_done() + state = hass.states.get('binary_sensor.test') + assert STATE_UNAVAILABLE == state.state - state = self.hass.states.get('binary_sensor.test') - assert STATE_UNAVAILABLE == state.state + async_fire_mqtt_message(hass, 'availability-topic', 'good') - def test_force_update_disabled(self): - """Test force update option.""" - mock_component(self.hass, 'mqtt') - assert setup_component(self.hass, binary_sensor.DOMAIN, { - binary_sensor.DOMAIN: { - 'platform': 'mqtt', - 'name': 'test', - 'state_topic': 'test-topic', - 'payload_on': 'ON', - 'payload_off': 'OFF' - } - }) + state = hass.states.get('binary_sensor.test') + assert STATE_UNAVAILABLE != state.state - events = [] + async_fire_mqtt_message(hass, 'availability-topic', 'nogood') - @ha.callback - def callback(event): - """Verify event got called.""" - events.append(event) + state = hass.states.get('binary_sensor.test') + assert STATE_UNAVAILABLE == state.state - self.hass.bus.listen(EVENT_STATE_CHANGED, callback) - fire_mqtt_message(self.hass, 'test-topic', 'ON') - self.hass.block_till_done() - assert 1 == len(events) +async def test_force_update_disabled(hass, mqtt_mock): + """Test force update option.""" + assert await async_setup_component(hass, binary_sensor.DOMAIN, { + binary_sensor.DOMAIN: { + 'platform': 'mqtt', + 'name': 'test', + 'state_topic': 'test-topic', + 'payload_on': 'ON', + 'payload_off': 'OFF' + } + }) - fire_mqtt_message(self.hass, 'test-topic', 'ON') - self.hass.block_till_done() - assert 1 == len(events) + events = [] - def test_force_update_enabled(self): - """Test force update option.""" - mock_component(self.hass, 'mqtt') - assert setup_component(self.hass, binary_sensor.DOMAIN, { - binary_sensor.DOMAIN: { - 'platform': 'mqtt', - 'name': 'test', - 'state_topic': 'test-topic', - 'payload_on': 'ON', - 'payload_off': 'OFF', - 'force_update': True - } - }) + @ha.callback + def callback(event): + """Verify event got called.""" + events.append(event) - events = [] + hass.bus.async_listen(EVENT_STATE_CHANGED, callback) - @ha.callback - def callback(event): - """Verify event got called.""" - events.append(event) + async_fire_mqtt_message(hass, 'test-topic', 'ON') + await hass.async_block_till_done() + assert 1 == len(events) - self.hass.bus.listen(EVENT_STATE_CHANGED, callback) + async_fire_mqtt_message(hass, 'test-topic', 'ON') + await hass.async_block_till_done() + assert 1 == len(events) - fire_mqtt_message(self.hass, 'test-topic', 'ON') - self.hass.block_till_done() - assert 1 == len(events) - fire_mqtt_message(self.hass, 'test-topic', 'ON') - self.hass.block_till_done() - assert 2 == len(events) +async def test_force_update_enabled(hass, mqtt_mock): + """Test force update option.""" + assert await async_setup_component(hass, binary_sensor.DOMAIN, { + binary_sensor.DOMAIN: { + 'platform': 'mqtt', + 'name': 'test', + 'state_topic': 'test-topic', + 'payload_on': 'ON', + 'payload_off': 'OFF', + 'force_update': True + } + }) - def test_off_delay(self): - """Test off_delay option.""" - mock_component(self.hass, 'mqtt') - assert setup_component(self.hass, binary_sensor.DOMAIN, { - binary_sensor.DOMAIN: { - 'platform': 'mqtt', - 'name': 'test', - 'state_topic': 'test-topic', - 'payload_on': 'ON', - 'payload_off': 'OFF', - 'off_delay': 30, - 'force_update': True - } - }) + events = [] - events = [] + @ha.callback + def callback(event): + """Verify event got called.""" + events.append(event) - @ha.callback - def callback(event): - """Verify event got called.""" - events.append(event) + hass.bus.async_listen(EVENT_STATE_CHANGED, callback) - self.hass.bus.listen(EVENT_STATE_CHANGED, callback) + async_fire_mqtt_message(hass, 'test-topic', 'ON') + await hass.async_block_till_done() + assert 1 == len(events) - fire_mqtt_message(self.hass, 'test-topic', 'ON') - self.hass.block_till_done() - state = self.hass.states.get('binary_sensor.test') - assert STATE_ON == state.state - assert 1 == len(events) + async_fire_mqtt_message(hass, 'test-topic', 'ON') + await hass.async_block_till_done() + assert 2 == len(events) - fire_mqtt_message(self.hass, 'test-topic', 'ON') - self.hass.block_till_done() - state = self.hass.states.get('binary_sensor.test') - assert STATE_ON == state.state - assert 2 == len(events) - fire_time_changed(self.hass, dt_util.utcnow() + timedelta(seconds=30)) - self.hass.block_till_done() - state = self.hass.states.get('binary_sensor.test') - assert STATE_OFF == state.state - assert 3 == len(events) +async def test_off_delay(hass, mqtt_mock): + """Test off_delay option.""" + assert await async_setup_component(hass, binary_sensor.DOMAIN, { + binary_sensor.DOMAIN: { + 'platform': 'mqtt', + 'name': 'test', + 'state_topic': 'test-topic', + 'payload_on': 'ON', + 'payload_off': 'OFF', + 'off_delay': 30, + 'force_update': True + } + }) + + events = [] + + @ha.callback + def callback(event): + """Verify event got called.""" + events.append(event) + + hass.bus.async_listen(EVENT_STATE_CHANGED, callback) + + async_fire_mqtt_message(hass, 'test-topic', 'ON') + await hass.async_block_till_done() + state = hass.states.get('binary_sensor.test') + assert STATE_ON == state.state + assert 1 == len(events) + + async_fire_mqtt_message(hass, 'test-topic', 'ON') + await hass.async_block_till_done() + state = hass.states.get('binary_sensor.test') + assert STATE_ON == state.state + assert 2 == len(events) + + async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=30)) + await hass.async_block_till_done() + state = hass.states.get('binary_sensor.test') + assert STATE_OFF == state.state + assert 3 == len(events) async def test_setting_attribute_via_mqtt_json_message(hass, mqtt_mock): @@ -294,7 +278,6 @@ async def test_setting_attribute_via_mqtt_json_message(hass, mqtt_mock): }) async_fire_mqtt_message(hass, 'attr-topic', '{ "val": "100" }') - await hass.async_block_till_done() state = hass.states.get('binary_sensor.test') assert '100' == state.attributes.get('val') @@ -312,7 +295,6 @@ async def test_update_with_json_attrs_not_dict(hass, mqtt_mock, caplog): }) async_fire_mqtt_message(hass, 'attr-topic', '[ "list", "of", "things"]') - await hass.async_block_till_done() state = hass.states.get('binary_sensor.test') assert state.attributes.get('val') is None @@ -331,7 +313,6 @@ async def test_update_with_json_attrs_bad_JSON(hass, mqtt_mock, caplog): }) async_fire_mqtt_message(hass, 'attr-topic', 'This is not JSON') - await hass.async_block_till_done() state = hass.states.get('binary_sensor.test') assert state.attributes.get('val') is None @@ -356,8 +337,6 @@ async def test_discovery_update_attr(hass, mqtt_mock, caplog): data1) await hass.async_block_till_done() async_fire_mqtt_message(hass, 'attr-topic1', '{ "val": "100" }') - await hass.async_block_till_done() - await hass.async_block_till_done() state = hass.states.get('binary_sensor.beer') assert '100' == state.attributes.get('val') @@ -365,19 +344,14 @@ async def test_discovery_update_attr(hass, mqtt_mock, caplog): async_fire_mqtt_message(hass, 'homeassistant/binary_sensor/bla/config', data2) await hass.async_block_till_done() - 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" }') - await hass.async_block_till_done() - await hass.async_block_till_done() state = hass.states.get('binary_sensor.beer') assert '100' == state.attributes.get('val') # Verify we are subscribing to the new topic async_fire_mqtt_message(hass, 'attr-topic2', '{ "val": "75" }') - await hass.async_block_till_done() - await hass.async_block_till_done() state = hass.states.get('binary_sensor.beer') assert '75' == state.attributes.get('val') @@ -399,7 +373,6 @@ async def test_unique_id(hass): }] }) async_fire_mqtt_message(hass, 'test-topic', 'payload') - await hass.async_block_till_done() assert len(hass.states.async_all()) == 1 @@ -421,7 +394,6 @@ async def test_discovery_removal_binary_sensor(hass, mqtt_mock, caplog): async_fire_mqtt_message(hass, 'homeassistant/binary_sensor/bla/config', '') await hass.async_block_till_done() - await hass.async_block_till_done() state = hass.states.get('binary_sensor.beer') assert state is None @@ -449,7 +421,6 @@ async def test_discovery_update_binary_sensor(hass, mqtt_mock, caplog): async_fire_mqtt_message(hass, 'homeassistant/binary_sensor/bla/config', data2) await hass.async_block_till_done() - await hass.async_block_till_done() state = hass.states.get('binary_sensor.beer') assert state is not None assert state.name == 'Milk' @@ -482,7 +453,6 @@ async def test_discovery_broken(hass, mqtt_mock, caplog): async_fire_mqtt_message(hass, 'homeassistant/binary_sensor/bla/config', data2) await hass.async_block_till_done() - await hass.async_block_till_done() state = hass.states.get('binary_sensor.milk') assert state is not None @@ -517,7 +487,6 @@ async def test_entity_device_info_with_identifier(hass, mqtt_mock): async_fire_mqtt_message(hass, 'homeassistant/binary_sensor/bla/config', data) await hass.async_block_till_done() - await hass.async_block_till_done() device = registry.async_get_device({('mqtt', 'helloworld')}, set()) assert device is not None @@ -557,7 +526,6 @@ async def test_entity_device_info_update(hass, mqtt_mock): async_fire_mqtt_message(hass, 'homeassistant/binary_sensor/bla/config', data) await hass.async_block_till_done() - await hass.async_block_till_done() device = registry.async_get_device({('mqtt', 'helloworld')}, set()) assert device is not None @@ -568,7 +536,6 @@ async def test_entity_device_info_update(hass, mqtt_mock): async_fire_mqtt_message(hass, 'homeassistant/binary_sensor/bla/config', data) await hass.async_block_till_done() - await hass.async_block_till_done() device = registry.async_get_device({('mqtt', 'helloworld')}, set()) assert device is not None @@ -599,7 +566,6 @@ async def test_entity_id_update(hass, mqtt_mock): registry.async_update_entity( 'binary_sensor.beer', new_entity_id='binary_sensor.milk') await hass.async_block_till_done() - await hass.async_block_till_done() state = hass.states.get('binary_sensor.beer') assert state is None