core/tests/components/august/test_init.py

170 lines
6.0 KiB
Python
Raw Normal View History

"""The tests for the august platform."""
import asyncio
from asynctest import patch
from august.exceptions import AugustApiAIOHTTPError
from homeassistant import setup
from homeassistant.components.august.const import (
CONF_ACCESS_TOKEN_CACHE_FILE,
CONF_INSTALL_ID,
CONF_LOGIN_METHOD,
DEFAULT_AUGUST_CONFIG_FILE,
DOMAIN,
)
from homeassistant.components.lock import DOMAIN as LOCK_DOMAIN
from homeassistant.config_entries import ENTRY_STATE_SETUP_RETRY
from homeassistant.const import (
ATTR_ENTITY_ID,
CONF_PASSWORD,
CONF_TIMEOUT,
CONF_USERNAME,
SERVICE_LOCK,
SERVICE_UNLOCK,
STATE_LOCKED,
STATE_ON,
)
from homeassistant.exceptions import HomeAssistantError
from homeassistant.setup import async_setup_component
from tests.common import MockConfigEntry
from tests.components.august.mocks import (
_create_august_with_devices,
_mock_doorsense_enabled_august_lock_detail,
_mock_doorsense_missing_august_lock_detail,
_mock_get_config,
_mock_inoperative_august_lock_detail,
_mock_operative_august_lock_detail,
)
async def test_august_is_offline(hass):
"""Config entry state is ENTRY_STATE_SETUP_RETRY when august is offline."""
config_entry = MockConfigEntry(
domain=DOMAIN, data=_mock_get_config()[DOMAIN], title="August august",
)
config_entry.add_to_hass(hass)
await setup.async_setup_component(hass, "persistent_notification", {})
with patch(
"august.authenticator_async.AuthenticatorAsync.async_authenticate",
side_effect=asyncio.TimeoutError,
):
await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
assert config_entry.state == ENTRY_STATE_SETUP_RETRY
async def test_unlock_throws_august_api_http_error(hass):
"""Test unlock throws correct error on http error."""
mocked_lock_detail = await _mock_operative_august_lock_detail(hass)
def _unlock_return_activities_side_effect(access_token, device_id):
raise AugustApiAIOHTTPError("This should bubble up as its user consumable")
await _create_august_with_devices(
hass,
[mocked_lock_detail],
api_call_side_effects={
"unlock_return_activities": _unlock_return_activities_side_effect
},
)
last_err = None
data = {ATTR_ENTITY_ID: "lock.a6697750d607098bae8d6baa11ef8063_name"}
try:
await hass.services.async_call(LOCK_DOMAIN, SERVICE_UNLOCK, data, blocking=True)
except HomeAssistantError as err:
last_err = err
assert (
str(last_err)
== "A6697750D607098BAE8D6BAA11EF8063 Name: This should bubble up as its user consumable"
)
async def test_lock_throws_august_api_http_error(hass):
"""Test lock throws correct error on http error."""
mocked_lock_detail = await _mock_operative_august_lock_detail(hass)
def _lock_return_activities_side_effect(access_token, device_id):
raise AugustApiAIOHTTPError("This should bubble up as its user consumable")
await _create_august_with_devices(
hass,
[mocked_lock_detail],
api_call_side_effects={
"lock_return_activities": _lock_return_activities_side_effect
},
)
last_err = None
data = {ATTR_ENTITY_ID: "lock.a6697750d607098bae8d6baa11ef8063_name"}
try:
await hass.services.async_call(LOCK_DOMAIN, SERVICE_LOCK, data, blocking=True)
except HomeAssistantError as err:
last_err = err
assert (
str(last_err)
== "A6697750D607098BAE8D6BAA11EF8063 Name: This should bubble up as its user consumable"
)
async def test_inoperative_locks_are_filtered_out(hass):
"""Ensure inoperative locks do not get setup."""
august_operative_lock = await _mock_operative_august_lock_detail(hass)
august_inoperative_lock = await _mock_inoperative_august_lock_detail(hass)
await _create_august_with_devices(
hass, [august_operative_lock, august_inoperative_lock]
)
lock_abc_name = hass.states.get("lock.abc_name")
assert lock_abc_name is None
lock_a6697750d607098bae8d6baa11ef8063_name = hass.states.get(
"lock.a6697750d607098bae8d6baa11ef8063_name"
)
assert lock_a6697750d607098bae8d6baa11ef8063_name.state == STATE_LOCKED
async def test_lock_has_doorsense(hass):
"""Check to see if a lock has doorsense."""
doorsenselock = await _mock_doorsense_enabled_august_lock_detail(hass)
nodoorsenselock = await _mock_doorsense_missing_august_lock_detail(hass)
await _create_august_with_devices(hass, [doorsenselock, nodoorsenselock])
binary_sensor_online_with_doorsense_name_open = hass.states.get(
"binary_sensor.online_with_doorsense_name_open"
)
assert binary_sensor_online_with_doorsense_name_open.state == STATE_ON
binary_sensor_missing_doorsense_id_name_open = hass.states.get(
"binary_sensor.missing_doorsense_id_name_open"
)
assert binary_sensor_missing_doorsense_id_name_open is None
async def test_set_up_from_yaml(hass):
"""Test to make sure config is imported from yaml."""
await setup.async_setup_component(hass, "persistent_notification", {})
with patch(
"homeassistant.components.august.async_setup_august", return_value=True,
) as mock_setup_august, patch(
"homeassistant.components.august.config_flow.AugustGateway.async_authenticate",
return_value=True,
):
assert await async_setup_component(hass, DOMAIN, _mock_get_config())
await hass.async_block_till_done()
assert len(mock_setup_august.mock_calls) == 1
call = mock_setup_august.call_args
args, kwargs = call
imported_config_entry = args[1]
# The import must use DEFAULT_AUGUST_CONFIG_FILE so they
# do not loose their token when config is migrated
assert imported_config_entry.data == {
CONF_ACCESS_TOKEN_CACHE_FILE: DEFAULT_AUGUST_CONFIG_FILE,
CONF_INSTALL_ID: None,
CONF_LOGIN_METHOD: "email",
CONF_PASSWORD: "mocked_password",
CONF_TIMEOUT: None,
CONF_USERNAME: "mocked_username",
}