hass-core/tests/components/august/test_init.py
J. Nick Koston 17f3332c89
Audit state handling off august bridges and sensors (#31935)
* Audit state handling of august bridges and sensors

This addresses issue #29980

* Prevent setting up august locks that do not have a bridge as they will never work

* Prevent locks showing available when their bridge is offline

* Prevent door sensors from showing available when their bridge is offline

* Prevent creating door sensors for locks that do not have them

* Prevent doorbells showing unavailable when they are in standby mode

* Set SCAN_INTERVAL for binary_sensors to 5 seconds as
  data comes in from the activity endpoint more frequently

* Update homeassistant/components/august/__init__.py

raise if the detail is missing when checking doorsense

Co-Authored-By: Paulus Schoutsen <paulus@home-assistant.io>

* Handle another place where the lock detail could not exist

* Address review comments

* Handle lock detail update failing and add test

Co-authored-by: Paulus Schoutsen <paulus@home-assistant.io>
2020-02-18 12:11:05 -08:00

137 lines
4.6 KiB
Python

"""The tests for the august platform."""
import asyncio
from unittest.mock import MagicMock
from august.lock import LockDetail
from requests import RequestException
from homeassistant.components import august
from homeassistant.exceptions import HomeAssistantError
from tests.components.august.mocks import (
MockAugustApiFailing,
MockAugustComponentData,
_mock_august_authentication,
_mock_august_authenticator,
_mock_august_lock,
_mock_doorsense_enabled_august_lock_detail,
_mock_doorsense_missing_august_lock_detail,
_mock_inoperative_august_lock_detail,
_mock_operative_august_lock_detail,
)
def test_get_lock_name():
"""Get the lock name from August data."""
data = MockAugustComponentData(last_lock_status_update_timestamp=1)
lock = _mock_august_lock()
data.set_mocked_locks([lock])
assert data.get_lock_name("mocklockid1") == "mocklockid1 Name"
def test_unlock_throws_august_api_http_error():
"""Test unlock."""
data = MockAugustComponentData(api=MockAugustApiFailing())
lock = _mock_august_lock()
data.set_mocked_locks([lock])
last_err = None
try:
data.unlock("mocklockid1")
except HomeAssistantError as err:
last_err = err
assert (
str(last_err)
== "mocklockid1 Name: This should bubble up as its user consumable"
)
def test_lock_throws_august_api_http_error():
"""Test lock."""
data = MockAugustComponentData(api=MockAugustApiFailing())
lock = _mock_august_lock()
data.set_mocked_locks([lock])
last_err = None
try:
data.unlock("mocklockid1")
except HomeAssistantError as err:
last_err = err
assert (
str(last_err)
== "mocklockid1 Name: This should bubble up as its user consumable"
)
def test_inoperative_locks_are_filtered_out():
"""Ensure inoperative locks do not get setup."""
august_operative_lock = _mock_operative_august_lock_detail("oplockid1")
data = _create_august_data_with_lock_details(
[august_operative_lock, _mock_inoperative_august_lock_detail("inoplockid1")]
)
assert len(data.locks) == 1
assert data.locks[0].device_id == "oplockid1"
def test_lock_has_doorsense():
"""Check to see if a lock has doorsense."""
data = _create_august_data_with_lock_details(
[
_mock_doorsense_enabled_august_lock_detail("doorsenselock1"),
_mock_doorsense_missing_august_lock_detail("nodoorsenselock1"),
RequestException("mocked request error"),
RequestException("mocked request error"),
]
)
assert data.lock_has_doorsense("doorsenselock1") is True
assert data.lock_has_doorsense("nodoorsenselock1") is False
# The api calls are mocked to fail on the second
# run of async_get_lock_detail
#
# This will be switched to await data.async_get_lock_detail("doorsenselock1")
# once we mock the full home assistant setup
data._update_locks_detail()
# doorsenselock1 should be false if we cannot tell due
# to an api error
assert data.lock_has_doorsense("doorsenselock1") is False
async def test__refresh_access_token(hass):
"""Test refresh of the access token."""
authentication = _mock_august_authentication("original_token", 1234)
authenticator = _mock_august_authenticator()
token_refresh_lock = asyncio.Lock()
data = august.AugustData(
hass, MagicMock(name="api"), authentication, authenticator, token_refresh_lock
)
await data._async_refresh_access_token_if_needed()
authenticator.refresh_access_token.assert_not_called()
authenticator.should_refresh.return_value = 1
authenticator.refresh_access_token.return_value = _mock_august_authentication(
"new_token", 5678
)
await data._async_refresh_access_token_if_needed()
authenticator.refresh_access_token.assert_called()
assert data._access_token == "new_token"
assert data._access_token_expires == 5678
def _create_august_data_with_lock_details(lock_details):
locks = []
for lock in lock_details:
if isinstance(lock, LockDetail):
locks.append(_mock_august_lock(lock.device_id))
authentication = _mock_august_authentication("original_token", 1234)
authenticator = _mock_august_authenticator()
token_refresh_lock = MagicMock()
api = MagicMock()
api.get_lock_status = MagicMock(return_value=(MagicMock(), MagicMock()))
api.get_lock_detail = MagicMock(side_effect=lock_details)
api.get_operable_locks = MagicMock(return_value=locks)
api.get_doorbells = MagicMock(return_value=[])
return august.AugustData(
MagicMock(), api, authentication, authenticator, token_refresh_lock
)