2020-02-12 23:35:07 +00:00
|
|
|
"""Mocks for the august component."""
|
2020-02-21 05:06:24 +00:00
|
|
|
import json
|
|
|
|
import os
|
2020-02-23 21:54:35 +00:00
|
|
|
import time
|
2020-02-12 23:35:07 +00:00
|
|
|
|
2020-02-21 05:06:24 +00:00
|
|
|
from asynctest import mock
|
2020-03-09 20:54:05 +00:00
|
|
|
from asynctest.mock import CoroutineMock, MagicMock, PropertyMock
|
2020-02-26 07:43:41 +00:00
|
|
|
from august.activity import (
|
|
|
|
ACTIVITY_ACTIONS_DOOR_OPERATION,
|
|
|
|
ACTIVITY_ACTIONS_DOORBELL_DING,
|
|
|
|
ACTIVITY_ACTIONS_DOORBELL_MOTION,
|
|
|
|
ACTIVITY_ACTIONS_DOORBELL_VIEW,
|
|
|
|
ACTIVITY_ACTIONS_LOCK_OPERATION,
|
|
|
|
DoorbellDingActivity,
|
|
|
|
DoorbellMotionActivity,
|
|
|
|
DoorbellViewActivity,
|
|
|
|
DoorOperationActivity,
|
|
|
|
LockOperationActivity,
|
|
|
|
)
|
2020-02-21 05:06:24 +00:00
|
|
|
from august.authenticator import AuthenticationState
|
|
|
|
from august.doorbell import Doorbell, DoorbellDetail
|
2020-02-23 21:54:35 +00:00
|
|
|
from august.lock import Lock, LockDetail
|
2020-02-21 05:06:24 +00:00
|
|
|
|
|
|
|
from homeassistant.components.august import (
|
|
|
|
CONF_LOGIN_METHOD,
|
|
|
|
CONF_PASSWORD,
|
|
|
|
CONF_USERNAME,
|
|
|
|
DOMAIN,
|
|
|
|
)
|
|
|
|
from homeassistant.setup import async_setup_component
|
2020-02-12 23:35:07 +00:00
|
|
|
|
2020-02-21 05:06:24 +00:00
|
|
|
from tests.common import load_fixture
|
|
|
|
|
|
|
|
|
|
|
|
def _mock_get_config():
|
|
|
|
"""Return a default august config."""
|
|
|
|
return {
|
|
|
|
DOMAIN: {
|
|
|
|
CONF_LOGIN_METHOD: "email",
|
|
|
|
CONF_USERNAME: "mocked_username",
|
|
|
|
CONF_PASSWORD: "mocked_password",
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-03-09 20:54:05 +00:00
|
|
|
@mock.patch("homeassistant.components.august.gateway.ApiAsync")
|
|
|
|
@mock.patch(
|
|
|
|
"homeassistant.components.august.gateway.AuthenticatorAsync.async_authenticate"
|
|
|
|
)
|
2020-02-23 21:54:35 +00:00
|
|
|
async def _mock_setup_august(hass, api_instance, authenticate_mock, api_mock):
|
2020-02-21 05:06:24 +00:00
|
|
|
"""Set up august integration."""
|
|
|
|
authenticate_mock.side_effect = MagicMock(
|
|
|
|
return_value=_mock_august_authentication("original_token", 1234)
|
|
|
|
)
|
2020-02-23 21:54:35 +00:00
|
|
|
api_mock.return_value = api_instance
|
2020-02-21 05:06:24 +00:00
|
|
|
assert await async_setup_component(hass, DOMAIN, _mock_get_config())
|
|
|
|
await hass.async_block_till_done()
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
2020-02-26 07:43:41 +00:00
|
|
|
async def _create_august_with_devices(
|
|
|
|
hass, devices, api_call_side_effects=None, activities=None
|
|
|
|
):
|
2020-02-23 21:54:35 +00:00
|
|
|
if api_call_side_effects is None:
|
|
|
|
api_call_side_effects = {}
|
2020-02-26 07:43:41 +00:00
|
|
|
|
2020-02-23 21:54:35 +00:00
|
|
|
device_data = {
|
|
|
|
"doorbells": [],
|
|
|
|
"locks": [],
|
|
|
|
}
|
|
|
|
for device in devices:
|
|
|
|
if isinstance(device, LockDetail):
|
|
|
|
device_data["locks"].append(
|
|
|
|
{"base": _mock_august_lock(device.device_id), "detail": device}
|
|
|
|
)
|
|
|
|
elif isinstance(device, DoorbellDetail):
|
|
|
|
device_data["doorbells"].append(
|
|
|
|
{"base": _mock_august_doorbell(device.device_id), "detail": device}
|
|
|
|
)
|
|
|
|
else:
|
|
|
|
raise ValueError
|
|
|
|
|
|
|
|
def _get_device_detail(device_type, device_id):
|
|
|
|
for device in device_data[device_type]:
|
|
|
|
if device["detail"].device_id == device_id:
|
|
|
|
return device["detail"]
|
|
|
|
raise ValueError
|
|
|
|
|
|
|
|
def _get_base_devices(device_type):
|
|
|
|
base_devices = []
|
|
|
|
for device in device_data[device_type]:
|
|
|
|
base_devices.append(device["base"])
|
|
|
|
return base_devices
|
|
|
|
|
|
|
|
def get_lock_detail_side_effect(access_token, device_id):
|
|
|
|
return _get_device_detail("locks", device_id)
|
|
|
|
|
2020-02-25 18:18:15 +00:00
|
|
|
def get_doorbell_detail_side_effect(access_token, device_id):
|
|
|
|
return _get_device_detail("doorbells", device_id)
|
|
|
|
|
2020-02-23 21:54:35 +00:00
|
|
|
def get_operable_locks_side_effect(access_token):
|
|
|
|
return _get_base_devices("locks")
|
|
|
|
|
|
|
|
def get_doorbells_side_effect(access_token):
|
|
|
|
return _get_base_devices("doorbells")
|
|
|
|
|
|
|
|
def get_house_activities_side_effect(access_token, house_id, limit=10):
|
2020-02-26 07:43:41 +00:00
|
|
|
if activities is not None:
|
|
|
|
return activities
|
2020-02-23 21:54:35 +00:00
|
|
|
return []
|
|
|
|
|
|
|
|
def lock_return_activities_side_effect(access_token, device_id):
|
|
|
|
lock = _get_device_detail("locks", device_id)
|
|
|
|
return [
|
|
|
|
_mock_lock_operation_activity(lock, "lock"),
|
|
|
|
_mock_door_operation_activity(lock, "doorclosed"),
|
|
|
|
]
|
|
|
|
|
|
|
|
def unlock_return_activities_side_effect(access_token, device_id):
|
|
|
|
lock = _get_device_detail("locks", device_id)
|
|
|
|
return [
|
|
|
|
_mock_lock_operation_activity(lock, "unlock"),
|
|
|
|
_mock_door_operation_activity(lock, "dooropen"),
|
|
|
|
]
|
|
|
|
|
|
|
|
if "get_lock_detail" not in api_call_side_effects:
|
|
|
|
api_call_side_effects["get_lock_detail"] = get_lock_detail_side_effect
|
2020-02-25 18:18:15 +00:00
|
|
|
if "get_doorbell_detail" not in api_call_side_effects:
|
|
|
|
api_call_side_effects["get_doorbell_detail"] = get_doorbell_detail_side_effect
|
2020-02-23 21:54:35 +00:00
|
|
|
if "get_operable_locks" not in api_call_side_effects:
|
|
|
|
api_call_side_effects["get_operable_locks"] = get_operable_locks_side_effect
|
|
|
|
if "get_doorbells" not in api_call_side_effects:
|
|
|
|
api_call_side_effects["get_doorbells"] = get_doorbells_side_effect
|
|
|
|
if "get_house_activities" not in api_call_side_effects:
|
|
|
|
api_call_side_effects["get_house_activities"] = get_house_activities_side_effect
|
|
|
|
if "lock_return_activities" not in api_call_side_effects:
|
|
|
|
api_call_side_effects[
|
|
|
|
"lock_return_activities"
|
|
|
|
] = lock_return_activities_side_effect
|
|
|
|
if "unlock_return_activities" not in api_call_side_effects:
|
|
|
|
api_call_side_effects[
|
|
|
|
"unlock_return_activities"
|
|
|
|
] = unlock_return_activities_side_effect
|
|
|
|
|
|
|
|
return await _mock_setup_august_with_api_side_effects(hass, api_call_side_effects)
|
|
|
|
|
|
|
|
|
|
|
|
async def _mock_setup_august_with_api_side_effects(hass, api_call_side_effects):
|
|
|
|
api_instance = MagicMock(name="Api")
|
|
|
|
|
|
|
|
if api_call_side_effects["get_lock_detail"]:
|
2020-03-09 20:54:05 +00:00
|
|
|
type(api_instance).async_get_lock_detail = CoroutineMock(
|
|
|
|
side_effect=api_call_side_effects["get_lock_detail"]
|
|
|
|
)
|
2020-02-23 21:54:35 +00:00
|
|
|
|
|
|
|
if api_call_side_effects["get_operable_locks"]:
|
2020-03-09 20:54:05 +00:00
|
|
|
type(api_instance).async_get_operable_locks = CoroutineMock(
|
|
|
|
side_effect=api_call_side_effects["get_operable_locks"]
|
|
|
|
)
|
2020-02-23 21:54:35 +00:00
|
|
|
|
|
|
|
if api_call_side_effects["get_doorbells"]:
|
2020-03-09 20:54:05 +00:00
|
|
|
type(api_instance).async_get_doorbells = CoroutineMock(
|
|
|
|
side_effect=api_call_side_effects["get_doorbells"]
|
|
|
|
)
|
2020-02-23 21:54:35 +00:00
|
|
|
|
2020-02-25 18:18:15 +00:00
|
|
|
if api_call_side_effects["get_doorbell_detail"]:
|
2020-03-09 20:54:05 +00:00
|
|
|
type(api_instance).async_get_doorbell_detail = CoroutineMock(
|
|
|
|
side_effect=api_call_side_effects["get_doorbell_detail"]
|
|
|
|
)
|
2020-02-25 18:18:15 +00:00
|
|
|
|
2020-02-23 21:54:35 +00:00
|
|
|
if api_call_side_effects["get_house_activities"]:
|
2020-03-09 20:54:05 +00:00
|
|
|
type(api_instance).async_get_house_activities = CoroutineMock(
|
|
|
|
side_effect=api_call_side_effects["get_house_activities"]
|
|
|
|
)
|
2020-02-23 21:54:35 +00:00
|
|
|
|
|
|
|
if api_call_side_effects["lock_return_activities"]:
|
2020-03-09 20:54:05 +00:00
|
|
|
type(api_instance).async_lock_return_activities = CoroutineMock(
|
|
|
|
side_effect=api_call_side_effects["lock_return_activities"]
|
|
|
|
)
|
2020-02-23 21:54:35 +00:00
|
|
|
|
|
|
|
if api_call_side_effects["unlock_return_activities"]:
|
2020-03-09 20:54:05 +00:00
|
|
|
type(api_instance).async_unlock_return_activities = CoroutineMock(
|
|
|
|
side_effect=api_call_side_effects["unlock_return_activities"]
|
|
|
|
)
|
|
|
|
|
2020-02-23 21:54:35 +00:00
|
|
|
return await _mock_setup_august(hass, api_instance)
|
2020-02-21 05:06:24 +00:00
|
|
|
|
2020-02-12 23:35:07 +00:00
|
|
|
|
|
|
|
def _mock_august_authentication(token_text, token_timestamp):
|
|
|
|
authentication = MagicMock(name="august.authentication")
|
2020-02-21 05:06:24 +00:00
|
|
|
type(authentication).state = PropertyMock(
|
|
|
|
return_value=AuthenticationState.AUTHENTICATED
|
|
|
|
)
|
2020-02-12 23:35:07 +00:00
|
|
|
type(authentication).access_token = PropertyMock(return_value=token_text)
|
|
|
|
type(authentication).access_token_expires = PropertyMock(
|
|
|
|
return_value=token_timestamp
|
|
|
|
)
|
|
|
|
return authentication
|
2020-02-17 18:30:14 +00:00
|
|
|
|
|
|
|
|
2020-02-18 20:11:05 +00:00
|
|
|
def _mock_august_lock(lockid="mocklockid1", houseid="mockhouseid1"):
|
|
|
|
return Lock(lockid, _mock_august_lock_data(lockid=lockid, houseid=houseid))
|
|
|
|
|
|
|
|
|
2020-02-21 05:06:24 +00:00
|
|
|
def _mock_august_doorbell(deviceid="mockdeviceid1", houseid="mockhouseid1"):
|
|
|
|
return Doorbell(
|
2020-02-23 21:54:35 +00:00
|
|
|
deviceid, _mock_august_doorbell_data(deviceid=deviceid, houseid=houseid)
|
2020-02-21 05:06:24 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
def _mock_august_doorbell_data(deviceid="mockdeviceid1", houseid="mockhouseid1"):
|
|
|
|
return {
|
|
|
|
"_id": deviceid,
|
|
|
|
"DeviceID": deviceid,
|
2020-02-23 21:54:35 +00:00
|
|
|
"name": deviceid + " Name",
|
2020-02-21 05:06:24 +00:00
|
|
|
"HouseID": houseid,
|
|
|
|
"UserType": "owner",
|
2020-02-23 21:54:35 +00:00
|
|
|
"serialNumber": "mockserial",
|
2020-02-21 05:06:24 +00:00
|
|
|
"battery": 90,
|
2020-02-23 21:54:35 +00:00
|
|
|
"status": "standby",
|
2020-02-21 05:06:24 +00:00
|
|
|
"currentFirmwareVersion": "mockfirmware",
|
|
|
|
"Bridge": {
|
|
|
|
"_id": "bridgeid1",
|
|
|
|
"firmwareVersion": "mockfirm",
|
|
|
|
"operative": True,
|
|
|
|
},
|
|
|
|
"LockStatus": {"doorState": "open"},
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-02-18 20:11:05 +00:00
|
|
|
def _mock_august_lock_data(lockid="mocklockid1", houseid="mockhouseid1"):
|
|
|
|
return {
|
|
|
|
"_id": lockid,
|
|
|
|
"LockID": lockid,
|
|
|
|
"LockName": lockid + " Name",
|
|
|
|
"HouseID": houseid,
|
|
|
|
"UserType": "owner",
|
|
|
|
"SerialNumber": "mockserial",
|
|
|
|
"battery": 90,
|
|
|
|
"currentFirmwareVersion": "mockfirmware",
|
|
|
|
"Bridge": {
|
|
|
|
"_id": "bridgeid1",
|
|
|
|
"firmwareVersion": "mockfirm",
|
|
|
|
"operative": True,
|
|
|
|
},
|
|
|
|
"LockStatus": {"doorState": "open"},
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-02-25 18:18:15 +00:00
|
|
|
async def _mock_operative_august_lock_detail(hass):
|
|
|
|
return await _mock_lock_from_fixture(hass, "get_lock.online.json")
|
2020-02-18 20:11:05 +00:00
|
|
|
|
|
|
|
|
2020-02-25 18:18:15 +00:00
|
|
|
async def _mock_inoperative_august_lock_detail(hass):
|
|
|
|
return await _mock_lock_from_fixture(hass, "get_lock.offline.json")
|
2020-02-18 20:11:05 +00:00
|
|
|
|
|
|
|
|
2020-02-26 07:43:41 +00:00
|
|
|
async def _mock_activities_from_fixture(hass, path):
|
|
|
|
json_dict = await _load_json_fixture(hass, path)
|
|
|
|
activities = []
|
|
|
|
for activity_json in json_dict:
|
|
|
|
activity = _activity_from_dict(activity_json)
|
|
|
|
if activity:
|
|
|
|
activities.append(activity)
|
|
|
|
|
|
|
|
return activities
|
|
|
|
|
|
|
|
|
2020-02-21 05:06:24 +00:00
|
|
|
async def _mock_lock_from_fixture(hass, path):
|
|
|
|
json_dict = await _load_json_fixture(hass, path)
|
|
|
|
return LockDetail(json_dict)
|
|
|
|
|
|
|
|
|
2020-02-23 21:54:35 +00:00
|
|
|
async def _mock_doorbell_from_fixture(hass, path):
|
|
|
|
json_dict = await _load_json_fixture(hass, path)
|
|
|
|
return DoorbellDetail(json_dict)
|
|
|
|
|
|
|
|
|
2020-02-21 05:06:24 +00:00
|
|
|
async def _load_json_fixture(hass, path):
|
|
|
|
fixture = await hass.async_add_executor_job(
|
|
|
|
load_fixture, os.path.join("august", path)
|
|
|
|
)
|
|
|
|
return json.loads(fixture)
|
|
|
|
|
|
|
|
|
2020-02-25 18:18:15 +00:00
|
|
|
async def _mock_doorsense_enabled_august_lock_detail(hass):
|
|
|
|
return await _mock_lock_from_fixture(hass, "get_lock.online_with_doorsense.json")
|
|
|
|
|
|
|
|
|
|
|
|
async def _mock_doorsense_missing_august_lock_detail(hass):
|
|
|
|
return await _mock_lock_from_fixture(hass, "get_lock.online_missing_doorsense.json")
|
2020-02-23 21:54:35 +00:00
|
|
|
|
|
|
|
|
|
|
|
def _mock_lock_operation_activity(lock, action):
|
|
|
|
return LockOperationActivity(
|
|
|
|
{
|
|
|
|
"dateTime": time.time() * 1000,
|
|
|
|
"deviceID": lock.device_id,
|
|
|
|
"deviceType": "lock",
|
|
|
|
"action": action,
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
def _mock_door_operation_activity(lock, action):
|
|
|
|
return DoorOperationActivity(
|
|
|
|
{
|
|
|
|
"dateTime": time.time() * 1000,
|
|
|
|
"deviceID": lock.device_id,
|
|
|
|
"deviceType": "lock",
|
|
|
|
"action": action,
|
|
|
|
}
|
|
|
|
)
|
2020-02-26 07:43:41 +00:00
|
|
|
|
|
|
|
|
|
|
|
def _activity_from_dict(activity_dict):
|
|
|
|
action = activity_dict.get("action")
|
|
|
|
|
|
|
|
activity_dict["dateTime"] = time.time() * 1000
|
|
|
|
|
|
|
|
if action in ACTIVITY_ACTIONS_DOORBELL_DING:
|
|
|
|
return DoorbellDingActivity(activity_dict)
|
|
|
|
if action in ACTIVITY_ACTIONS_DOORBELL_MOTION:
|
|
|
|
return DoorbellMotionActivity(activity_dict)
|
|
|
|
if action in ACTIVITY_ACTIONS_DOORBELL_VIEW:
|
|
|
|
return DoorbellViewActivity(activity_dict)
|
|
|
|
if action in ACTIVITY_ACTIONS_LOCK_OPERATION:
|
|
|
|
return LockOperationActivity(activity_dict)
|
|
|
|
if action in ACTIVITY_ACTIONS_DOOR_OPERATION:
|
|
|
|
return DoorOperationActivity(activity_dict)
|
|
|
|
return None
|