Rewrite MQTT & demo Lock tests (#33838)

* Refactor tests to remove tests.lock.common

* Remove unused is_locked hass binding

* Import constants via entity component

* Import constants via entity component

* Fix light vs lock in naming
This commit is contained in:
Franck Nijhof 2020-04-10 00:40:51 +02:00 committed by GitHub
parent 6b2baae0de
commit 30c6ace0f3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 90 additions and 154 deletions

View File

@ -22,7 +22,6 @@ from homeassistant.helpers.config_validation import ( # noqa: F401
)
from homeassistant.helpers.entity import Entity
from homeassistant.helpers.entity_component import EntityComponent
from homeassistant.loader import bind_hass
# mypy: allow-untyped-defs, no-check-untyped-defs
@ -45,12 +44,6 @@ _LOGGER = logging.getLogger(__name__)
PROP_TO_ATTR = {"changed_by": ATTR_CHANGED_BY, "code_format": ATTR_CODE_FORMAT}
@bind_hass
def is_locked(hass, entity_id):
"""Return if the lock is locked based on the statemachine."""
return hass.states.is_state(entity_id, STATE_LOCKED)
async def async_setup(hass, config):
"""Track states and offer events for locks."""
component = hass.data[DOMAIN] = EntityComponent(

View File

@ -4,7 +4,7 @@ import os
import pytest
from homeassistant.components import demo
from homeassistant.components.demo import DOMAIN
from homeassistant.components.device_tracker.legacy import YAML_DEVICES
from homeassistant.helpers.json import JSONEncoder
from homeassistant.setup import async_setup_component
@ -28,14 +28,14 @@ def demo_cleanup(hass):
async def test_setting_up_demo(hass):
"""Test if we can set up the demo and dump it to JSON."""
assert await async_setup_component(hass, demo.DOMAIN, {"demo": {}})
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {}})
await hass.async_start()
# This is done to make sure entity components don't accidentally store
# non-JSON-serializable data in the state machine.
try:
json.dumps(hass.states.async_all(), cls=JSONEncoder)
except Exception:
except Exception: # pylint: disable=broad-except
pytest.fail(
"Unable to convert all demo entities to JSON. "
"Wrong data in state machine!"

View File

@ -1,11 +1,19 @@
"""The tests for the Demo lock platform."""
import pytest
from homeassistant.components import lock
from homeassistant.components.demo import DOMAIN
from homeassistant.components.lock import (
DOMAIN as LOCK_DOMAIN,
SERVICE_LOCK,
SERVICE_OPEN,
SERVICE_UNLOCK,
STATE_LOCKED,
STATE_UNLOCKED,
)
from homeassistant.const import ATTR_ENTITY_ID
from homeassistant.setup import async_setup_component
from tests.common import async_mock_service
from tests.components.lock import common
FRONT = "lock.front_door"
KITCHEN = "lock.kitchen_door"
@ -16,34 +24,40 @@ OPENABLE_LOCK = "lock.openable_lock"
def setup_comp(hass):
"""Set up demo component."""
hass.loop.run_until_complete(
async_setup_component(hass, lock.DOMAIN, {lock.DOMAIN: {"platform": "demo"}})
async_setup_component(hass, LOCK_DOMAIN, {LOCK_DOMAIN: {"platform": DOMAIN}})
)
async def test_is_locked(hass):
"""Test if lock is locked."""
assert lock.is_locked(hass, FRONT)
assert hass.states.is_state(FRONT, "locked")
assert not lock.is_locked(hass, KITCHEN)
assert hass.states.is_state(KITCHEN, "unlocked")
async def test_locking(hass):
"""Test the locking of a lock."""
await common.async_lock(hass, KITCHEN)
assert lock.is_locked(hass, KITCHEN)
state = hass.states.get(KITCHEN)
assert state.state == STATE_UNLOCKED
await hass.services.async_call(
LOCK_DOMAIN, SERVICE_LOCK, {ATTR_ENTITY_ID: KITCHEN}, blocking=True
)
state = hass.states.get(KITCHEN)
assert state.state == STATE_LOCKED
async def test_unlocking(hass):
"""Test the unlocking of a lock."""
await common.async_unlock(hass, FRONT)
assert not lock.is_locked(hass, FRONT)
state = hass.states.get(FRONT)
assert state.state == STATE_LOCKED
await hass.services.async_call(
LOCK_DOMAIN, SERVICE_UNLOCK, {ATTR_ENTITY_ID: FRONT}, blocking=True
)
state = hass.states.get(FRONT)
assert state.state == STATE_UNLOCKED
async def test_opening(hass):
"""Test the opening of a lock."""
calls = async_mock_service(hass, lock.DOMAIN, lock.SERVICE_OPEN)
await common.async_open_lock(hass, OPENABLE_LOCK)
await hass.async_block_till_done()
calls = async_mock_service(hass, LOCK_DOMAIN, SERVICE_OPEN)
await hass.services.async_call(
LOCK_DOMAIN, SERVICE_OPEN, {ATTR_ENTITY_ID: OPENABLE_LOCK}, blocking=True
)
assert len(calls) == 1

View File

@ -1,84 +0,0 @@
"""Collection of helper methods.
All containing methods are legacy helpers that should not be used by new
components. Instead call the service directly.
"""
from homeassistant.components.lock import DOMAIN
from homeassistant.const import (
ATTR_CODE,
ATTR_ENTITY_ID,
ENTITY_MATCH_ALL,
SERVICE_LOCK,
SERVICE_OPEN,
SERVICE_UNLOCK,
)
from homeassistant.loader import bind_hass
@bind_hass
def lock(hass, entity_id=ENTITY_MATCH_ALL, code=None):
"""Lock all or specified locks."""
data = {}
if code:
data[ATTR_CODE] = code
if entity_id:
data[ATTR_ENTITY_ID] = entity_id
hass.services.call(DOMAIN, SERVICE_LOCK, data)
async def async_lock(hass, entity_id=ENTITY_MATCH_ALL, code=None):
"""Lock all or specified locks."""
data = {}
if code:
data[ATTR_CODE] = code
if entity_id:
data[ATTR_ENTITY_ID] = entity_id
await hass.services.async_call(DOMAIN, SERVICE_LOCK, data, blocking=True)
@bind_hass
def unlock(hass, entity_id=ENTITY_MATCH_ALL, code=None):
"""Unlock all or specified locks."""
data = {}
if code:
data[ATTR_CODE] = code
if entity_id:
data[ATTR_ENTITY_ID] = entity_id
hass.services.call(DOMAIN, SERVICE_UNLOCK, data)
async def async_unlock(hass, entity_id=ENTITY_MATCH_ALL, code=None):
"""Lock all or specified locks."""
data = {}
if code:
data[ATTR_CODE] = code
if entity_id:
data[ATTR_ENTITY_ID] = entity_id
await hass.services.async_call(DOMAIN, SERVICE_UNLOCK, data, blocking=True)
@bind_hass
def open_lock(hass, entity_id=ENTITY_MATCH_ALL, code=None):
"""Open all or specified locks."""
data = {}
if code:
data[ATTR_CODE] = code
if entity_id:
data[ATTR_ENTITY_ID] = entity_id
hass.services.call(DOMAIN, SERVICE_OPEN, data)
async def async_open_lock(hass, entity_id=ENTITY_MATCH_ALL, code=None):
"""Lock all or specified locks."""
data = {}
if code:
data[ATTR_CODE] = code
if entity_id:
data[ATTR_ENTITY_ID] = entity_id
await hass.services.async_call(DOMAIN, SERVICE_OPEN, data, blocking=True)

View File

@ -1,6 +1,12 @@
"""The tests for the MQTT lock platform."""
from homeassistant.components import lock
from homeassistant.const import ATTR_ASSUMED_STATE, STATE_LOCKED, STATE_UNLOCKED
from homeassistant.components.lock import (
DOMAIN as LOCK_DOMAIN,
SERVICE_LOCK,
SERVICE_UNLOCK,
STATE_LOCKED,
STATE_UNLOCKED,
)
from homeassistant.const import ATTR_ASSUMED_STATE, ATTR_ENTITY_ID
from homeassistant.setup import async_setup_component
from .test_common import (
@ -26,10 +32,9 @@ from .test_common import (
)
from tests.common import async_fire_mqtt_message
from tests.components.lock import common
DEFAULT_CONFIG = {
lock.DOMAIN: {"platform": "mqtt", "name": "test", "command_topic": "test-topic"}
LOCK_DOMAIN: {"platform": "mqtt", "name": "test", "command_topic": "test-topic"}
}
@ -37,9 +42,9 @@ async def test_controlling_state_via_topic(hass, mqtt_mock):
"""Test the controlling state via topic."""
assert await async_setup_component(
hass,
lock.DOMAIN,
LOCK_DOMAIN,
{
lock.DOMAIN: {
LOCK_DOMAIN: {
"platform": "mqtt",
"name": "test",
"state_topic": "state-topic",
@ -71,9 +76,9 @@ async def test_controlling_non_default_state_via_topic(hass, mqtt_mock):
"""Test the controlling state via topic."""
assert await async_setup_component(
hass,
lock.DOMAIN,
LOCK_DOMAIN,
{
lock.DOMAIN: {
LOCK_DOMAIN: {
"platform": "mqtt",
"name": "test",
"state_topic": "state-topic",
@ -105,9 +110,9 @@ async def test_controlling_state_via_topic_and_json_message(hass, mqtt_mock):
"""Test the controlling state via topic and JSON message."""
assert await async_setup_component(
hass,
lock.DOMAIN,
LOCK_DOMAIN,
{
lock.DOMAIN: {
LOCK_DOMAIN: {
"platform": "mqtt",
"name": "test",
"state_topic": "state-topic",
@ -141,9 +146,9 @@ async def test_controlling_non_default_state_via_topic_and_json_message(
"""Test the controlling state via topic and JSON message."""
assert await async_setup_component(
hass,
lock.DOMAIN,
LOCK_DOMAIN,
{
lock.DOMAIN: {
LOCK_DOMAIN: {
"platform": "mqtt",
"name": "test",
"state_topic": "state-topic",
@ -175,9 +180,9 @@ async def test_sending_mqtt_commands_and_optimistic(hass, mqtt_mock):
"""Test optimistic mode without state topic."""
assert await async_setup_component(
hass,
lock.DOMAIN,
LOCK_DOMAIN,
{
lock.DOMAIN: {
LOCK_DOMAIN: {
"platform": "mqtt",
"name": "test",
"command_topic": "command-topic",
@ -193,7 +198,9 @@ async def test_sending_mqtt_commands_and_optimistic(hass, mqtt_mock):
assert state.state is STATE_UNLOCKED
assert state.attributes.get(ATTR_ASSUMED_STATE)
await common.async_lock(hass, "lock.test")
await hass.services.async_call(
LOCK_DOMAIN, SERVICE_LOCK, {ATTR_ENTITY_ID: "lock.test"}, blocking=True
)
mqtt_mock.async_publish.assert_called_once_with("command-topic", "LOCK", 0, False)
mqtt_mock.async_publish.reset_mock()
@ -201,7 +208,9 @@ async def test_sending_mqtt_commands_and_optimistic(hass, mqtt_mock):
assert state.state is STATE_LOCKED
assert state.attributes.get(ATTR_ASSUMED_STATE)
await common.async_unlock(hass, "lock.test")
await hass.services.async_call(
LOCK_DOMAIN, SERVICE_UNLOCK, {ATTR_ENTITY_ID: "lock.test"}, blocking=True
)
mqtt_mock.async_publish.assert_called_once_with("command-topic", "UNLOCK", 0, False)
mqtt_mock.async_publish.reset_mock()
@ -214,9 +223,9 @@ async def test_sending_mqtt_commands_and_explicit_optimistic(hass, mqtt_mock):
"""Test optimistic mode without state topic."""
assert await async_setup_component(
hass,
lock.DOMAIN,
LOCK_DOMAIN,
{
lock.DOMAIN: {
LOCK_DOMAIN: {
"platform": "mqtt",
"name": "test",
"state_topic": "state-topic",
@ -234,7 +243,9 @@ async def test_sending_mqtt_commands_and_explicit_optimistic(hass, mqtt_mock):
assert state.state is STATE_UNLOCKED
assert state.attributes.get(ATTR_ASSUMED_STATE)
await common.async_lock(hass, "lock.test")
await hass.services.async_call(
LOCK_DOMAIN, SERVICE_LOCK, {ATTR_ENTITY_ID: "lock.test"}, blocking=True
)
mqtt_mock.async_publish.assert_called_once_with("command-topic", "LOCK", 0, False)
mqtt_mock.async_publish.reset_mock()
@ -242,7 +253,9 @@ async def test_sending_mqtt_commands_and_explicit_optimistic(hass, mqtt_mock):
assert state.state is STATE_LOCKED
assert state.attributes.get(ATTR_ASSUMED_STATE)
await common.async_unlock(hass, "lock.test")
await hass.services.async_call(
LOCK_DOMAIN, SERVICE_UNLOCK, {ATTR_ENTITY_ID: "lock.test"}, blocking=True
)
mqtt_mock.async_publish.assert_called_once_with("command-topic", "UNLOCK", 0, False)
mqtt_mock.async_publish.reset_mock()
@ -254,63 +267,63 @@ async def test_sending_mqtt_commands_and_explicit_optimistic(hass, mqtt_mock):
async def test_availability_without_topic(hass, mqtt_mock):
"""Test availability without defined availability topic."""
await help_test_availability_without_topic(
hass, mqtt_mock, lock.DOMAIN, DEFAULT_CONFIG
hass, mqtt_mock, LOCK_DOMAIN, DEFAULT_CONFIG
)
async def test_default_availability_payload(hass, mqtt_mock):
"""Test availability by default payload with defined topic."""
await help_test_default_availability_payload(
hass, mqtt_mock, lock.DOMAIN, DEFAULT_CONFIG
hass, mqtt_mock, LOCK_DOMAIN, DEFAULT_CONFIG
)
async def test_custom_availability_payload(hass, mqtt_mock):
"""Test availability by custom payload with defined topic."""
await help_test_custom_availability_payload(
hass, mqtt_mock, lock.DOMAIN, DEFAULT_CONFIG
hass, mqtt_mock, LOCK_DOMAIN, DEFAULT_CONFIG
)
async def test_setting_attribute_via_mqtt_json_message(hass, mqtt_mock):
"""Test the setting of attribute via MQTT with JSON payload."""
await help_test_setting_attribute_via_mqtt_json_message(
hass, mqtt_mock, lock.DOMAIN, DEFAULT_CONFIG
hass, mqtt_mock, LOCK_DOMAIN, DEFAULT_CONFIG
)
async def test_setting_attribute_with_template(hass, mqtt_mock):
"""Test the setting of attribute via MQTT with JSON payload."""
await help_test_setting_attribute_with_template(
hass, mqtt_mock, lock.DOMAIN, DEFAULT_CONFIG
hass, mqtt_mock, LOCK_DOMAIN, DEFAULT_CONFIG
)
async def test_update_with_json_attrs_not_dict(hass, mqtt_mock, caplog):
"""Test attributes get extracted from a JSON result."""
await help_test_update_with_json_attrs_not_dict(
hass, mqtt_mock, caplog, lock.DOMAIN, DEFAULT_CONFIG
hass, mqtt_mock, caplog, LOCK_DOMAIN, DEFAULT_CONFIG
)
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."""
await help_test_update_with_json_attrs_bad_JSON(
hass, mqtt_mock, caplog, lock.DOMAIN, DEFAULT_CONFIG
hass, mqtt_mock, caplog, LOCK_DOMAIN, DEFAULT_CONFIG
)
async def test_discovery_update_attr(hass, mqtt_mock, caplog):
"""Test update of discovered MQTTAttributes."""
await help_test_discovery_update_attr(
hass, mqtt_mock, caplog, lock.DOMAIN, DEFAULT_CONFIG
hass, mqtt_mock, caplog, LOCK_DOMAIN, DEFAULT_CONFIG
)
async def test_unique_id(hass):
"""Test unique id option only creates one lock per unique_id."""
config = {
lock.DOMAIN: [
LOCK_DOMAIN: [
{
"platform": "mqtt",
"name": "Test 1",
@ -327,13 +340,13 @@ async def test_unique_id(hass):
},
]
}
await help_test_unique_id(hass, lock.DOMAIN, config)
await help_test_unique_id(hass, LOCK_DOMAIN, config)
async def test_discovery_removal_lock(hass, mqtt_mock, caplog):
"""Test removal of discovered lock."""
data = '{ "name": "test",' ' "command_topic": "test_topic" }'
await help_test_discovery_removal(hass, mqtt_mock, caplog, lock.DOMAIN, data)
await help_test_discovery_removal(hass, mqtt_mock, caplog, LOCK_DOMAIN, data)
async def test_discovery_update_lock(hass, mqtt_mock, caplog):
@ -350,60 +363,60 @@ async def test_discovery_update_lock(hass, mqtt_mock, caplog):
' "command_topic": "command_topic",'
' "availability_topic": "availability_topic2" }'
)
await help_test_discovery_update(hass, mqtt_mock, caplog, lock.DOMAIN, data1, data2)
await help_test_discovery_update(hass, mqtt_mock, caplog, LOCK_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, lock.DOMAIN, data1, data2)
await help_test_discovery_broken(hass, mqtt_mock, caplog, LOCK_DOMAIN, data1, data2)
async def test_entity_device_info_with_connection(hass, mqtt_mock):
"""Test MQTT lock device registry integration."""
await help_test_entity_device_info_with_connection(
hass, mqtt_mock, lock.DOMAIN, DEFAULT_CONFIG
hass, mqtt_mock, LOCK_DOMAIN, DEFAULT_CONFIG
)
async def test_entity_device_info_with_identifier(hass, mqtt_mock):
"""Test MQTT lock device registry integration."""
await help_test_entity_device_info_with_identifier(
hass, mqtt_mock, lock.DOMAIN, DEFAULT_CONFIG
hass, mqtt_mock, LOCK_DOMAIN, DEFAULT_CONFIG
)
async def test_entity_device_info_update(hass, mqtt_mock):
"""Test device registry update."""
await help_test_entity_device_info_update(
hass, mqtt_mock, lock.DOMAIN, DEFAULT_CONFIG
hass, mqtt_mock, LOCK_DOMAIN, DEFAULT_CONFIG
)
async def test_entity_device_info_remove(hass, mqtt_mock):
"""Test device registry remove."""
await help_test_entity_device_info_remove(
hass, mqtt_mock, lock.DOMAIN, DEFAULT_CONFIG
hass, mqtt_mock, LOCK_DOMAIN, DEFAULT_CONFIG
)
async def test_entity_id_update_subscriptions(hass, mqtt_mock):
"""Test MQTT subscriptions are managed when entity_id is updated."""
await help_test_entity_id_update_subscriptions(
hass, mqtt_mock, lock.DOMAIN, DEFAULT_CONFIG
hass, mqtt_mock, LOCK_DOMAIN, DEFAULT_CONFIG
)
async def test_entity_id_update_discovery_update(hass, mqtt_mock):
"""Test MQTT discovery update when entity_id is updated."""
await help_test_entity_id_update_discovery_update(
hass, mqtt_mock, lock.DOMAIN, DEFAULT_CONFIG
hass, mqtt_mock, LOCK_DOMAIN, DEFAULT_CONFIG
)
async def test_entity_debug_info_message(hass, mqtt_mock):
"""Test MQTT debug info."""
await help_test_entity_debug_info_message(
hass, mqtt_mock, lock.DOMAIN, DEFAULT_CONFIG
hass, mqtt_mock, LOCK_DOMAIN, DEFAULT_CONFIG
)