2019-03-11 19:21:20 +00:00
|
|
|
"""Test the cloud.iot module."""
|
|
|
|
from unittest.mock import patch, MagicMock
|
|
|
|
|
|
|
|
from aiohttp import web
|
|
|
|
import pytest
|
|
|
|
|
2019-05-29 15:39:12 +00:00
|
|
|
from homeassistant.core import State
|
2019-03-11 19:21:20 +00:00
|
|
|
from homeassistant.setup import async_setup_component
|
2019-06-29 03:43:57 +00:00
|
|
|
from homeassistant.components.cloud import DOMAIN
|
2019-07-31 19:25:30 +00:00
|
|
|
from homeassistant.components.cloud.const import PREF_ENABLE_ALEXA, PREF_ENABLE_GOOGLE
|
2019-03-11 19:21:20 +00:00
|
|
|
from tests.components.alexa import test_smart_home as test_alexa
|
2019-06-29 03:43:57 +00:00
|
|
|
from tests.common import mock_coro
|
2019-03-11 19:21:20 +00:00
|
|
|
|
2019-06-21 09:17:21 +00:00
|
|
|
from . import mock_cloud_prefs, mock_cloud
|
2019-03-11 19:21:20 +00:00
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture
|
2019-06-21 09:17:21 +00:00
|
|
|
def mock_cloud_inst():
|
2019-03-11 19:21:20 +00:00
|
|
|
"""Mock cloud class."""
|
|
|
|
return MagicMock(subscription_expired=False)
|
|
|
|
|
|
|
|
|
|
|
|
async def test_handler_alexa(hass):
|
|
|
|
"""Test handler Alexa."""
|
2019-07-31 19:25:30 +00:00
|
|
|
hass.states.async_set("switch.test", "on", {"friendly_name": "Test switch"})
|
|
|
|
hass.states.async_set("switch.test2", "on", {"friendly_name": "Test switch 2"})
|
|
|
|
|
|
|
|
await mock_cloud(
|
|
|
|
hass,
|
|
|
|
{
|
|
|
|
"alexa": {
|
|
|
|
"filter": {"exclude_entities": "switch.test2"},
|
|
|
|
"entity_config": {
|
|
|
|
"switch.test": {
|
|
|
|
"name": "Config name",
|
|
|
|
"description": "Config description",
|
|
|
|
"display_categories": "LIGHT",
|
|
|
|
}
|
|
|
|
},
|
2019-03-11 19:21:20 +00:00
|
|
|
}
|
2019-07-31 19:25:30 +00:00
|
|
|
},
|
|
|
|
)
|
2019-03-11 19:21:20 +00:00
|
|
|
|
|
|
|
mock_cloud_prefs(hass)
|
2019-07-31 19:25:30 +00:00
|
|
|
cloud = hass.data["cloud"]
|
2019-03-11 19:21:20 +00:00
|
|
|
|
|
|
|
resp = await cloud.client.async_alexa_message(
|
2019-07-31 19:25:30 +00:00
|
|
|
test_alexa.get_new_request("Alexa.Discovery", "Discover")
|
|
|
|
)
|
2019-03-11 19:21:20 +00:00
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
endpoints = resp["event"]["payload"]["endpoints"]
|
2019-03-11 19:21:20 +00:00
|
|
|
|
|
|
|
assert len(endpoints) == 1
|
|
|
|
device = endpoints[0]
|
|
|
|
|
2019-09-27 19:51:46 +00:00
|
|
|
assert device["description"] == "Config description via Home Assistant"
|
2019-07-31 19:25:30 +00:00
|
|
|
assert device["friendlyName"] == "Config name"
|
|
|
|
assert device["displayCategories"] == ["LIGHT"]
|
|
|
|
assert device["manufacturerName"] == "Home Assistant"
|
2019-03-11 19:21:20 +00:00
|
|
|
|
|
|
|
|
|
|
|
async def test_handler_alexa_disabled(hass, mock_cloud_fixture):
|
|
|
|
"""Test handler Alexa when user has disabled it."""
|
|
|
|
mock_cloud_fixture[PREF_ENABLE_ALEXA] = False
|
2019-07-31 19:25:30 +00:00
|
|
|
cloud = hass.data["cloud"]
|
2019-03-11 19:21:20 +00:00
|
|
|
|
|
|
|
resp = await cloud.client.async_alexa_message(
|
2019-07-31 19:25:30 +00:00
|
|
|
test_alexa.get_new_request("Alexa.Discovery", "Discover")
|
|
|
|
)
|
2019-03-11 19:21:20 +00:00
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
assert resp["event"]["header"]["namespace"] == "Alexa"
|
|
|
|
assert resp["event"]["header"]["name"] == "ErrorResponse"
|
|
|
|
assert resp["event"]["payload"]["type"] == "BRIDGE_UNREACHABLE"
|
2019-03-11 19:21:20 +00:00
|
|
|
|
|
|
|
|
|
|
|
async def test_handler_google_actions(hass):
|
|
|
|
"""Test handler Google Actions."""
|
2019-07-31 19:25:30 +00:00
|
|
|
hass.states.async_set("switch.test", "on", {"friendly_name": "Test switch"})
|
|
|
|
hass.states.async_set("switch.test2", "on", {"friendly_name": "Test switch 2"})
|
|
|
|
hass.states.async_set("group.all_locks", "on", {"friendly_name": "Evil locks"})
|
|
|
|
|
|
|
|
await mock_cloud(
|
|
|
|
hass,
|
|
|
|
{
|
|
|
|
"google_actions": {
|
|
|
|
"filter": {"exclude_entities": "switch.test2"},
|
|
|
|
"entity_config": {
|
|
|
|
"switch.test": {
|
|
|
|
"name": "Config name",
|
|
|
|
"aliases": "Config alias",
|
|
|
|
"room": "living room",
|
|
|
|
}
|
|
|
|
},
|
2019-03-11 19:21:20 +00:00
|
|
|
}
|
2019-07-31 19:25:30 +00:00
|
|
|
},
|
|
|
|
)
|
2019-03-11 19:21:20 +00:00
|
|
|
|
|
|
|
mock_cloud_prefs(hass)
|
2019-07-31 19:25:30 +00:00
|
|
|
cloud = hass.data["cloud"]
|
2019-03-11 19:21:20 +00:00
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
reqid = "5711642932632160983"
|
|
|
|
data = {"requestId": reqid, "inputs": [{"intent": "action.devices.SYNC"}]}
|
2019-03-11 19:21:20 +00:00
|
|
|
|
|
|
|
with patch(
|
2019-07-31 19:25:30 +00:00
|
|
|
"hass_nabucasa.Cloud._decode_claims",
|
|
|
|
return_value={"cognito:username": "myUserName"},
|
2019-03-11 19:21:20 +00:00
|
|
|
):
|
|
|
|
resp = await cloud.client.async_google_message(data)
|
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
assert resp["requestId"] == reqid
|
|
|
|
payload = resp["payload"]
|
2019-03-11 19:21:20 +00:00
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
assert payload["agentUserId"] == "myUserName"
|
2019-03-11 19:21:20 +00:00
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
devices = payload["devices"]
|
2019-03-11 19:21:20 +00:00
|
|
|
assert len(devices) == 1
|
|
|
|
|
|
|
|
device = devices[0]
|
2019-07-31 19:25:30 +00:00
|
|
|
assert device["id"] == "switch.test"
|
|
|
|
assert device["name"]["name"] == "Config name"
|
|
|
|
assert device["name"]["nicknames"] == ["Config alias"]
|
|
|
|
assert device["type"] == "action.devices.types.SWITCH"
|
|
|
|
assert device["roomHint"] == "living room"
|
2019-03-11 19:21:20 +00:00
|
|
|
|
|
|
|
|
|
|
|
async def test_handler_google_actions_disabled(hass, mock_cloud_fixture):
|
|
|
|
"""Test handler Google Actions when user has disabled it."""
|
|
|
|
mock_cloud_fixture[PREF_ENABLE_GOOGLE] = False
|
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
with patch("hass_nabucasa.Cloud.start", return_value=mock_coro()):
|
|
|
|
assert await async_setup_component(hass, "cloud", {})
|
2019-03-11 19:21:20 +00:00
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
reqid = "5711642932632160983"
|
|
|
|
data = {"requestId": reqid, "inputs": [{"intent": "action.devices.SYNC"}]}
|
2019-03-11 19:21:20 +00:00
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
cloud = hass.data["cloud"]
|
2019-03-11 19:21:20 +00:00
|
|
|
resp = await cloud.client.async_google_message(data)
|
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
assert resp["requestId"] == reqid
|
|
|
|
assert resp["payload"]["errorCode"] == "deviceTurnedOff"
|
2019-03-11 19:21:20 +00:00
|
|
|
|
|
|
|
|
|
|
|
async def test_webhook_msg(hass):
|
|
|
|
"""Test webhook msg."""
|
2019-07-31 19:25:30 +00:00
|
|
|
with patch("hass_nabucasa.Cloud.start", return_value=mock_coro()):
|
|
|
|
setup = await async_setup_component(hass, "cloud", {"cloud": {}})
|
2019-03-11 19:21:20 +00:00
|
|
|
assert setup
|
2019-07-31 19:25:30 +00:00
|
|
|
cloud = hass.data["cloud"]
|
2019-03-11 19:21:20 +00:00
|
|
|
|
|
|
|
await cloud.client.prefs.async_initialize()
|
2019-07-31 19:25:30 +00:00
|
|
|
await cloud.client.prefs.async_update(
|
|
|
|
cloudhooks={
|
|
|
|
"hello": {"webhook_id": "mock-webhook-id", "cloudhook_id": "mock-cloud-id"}
|
2019-03-11 19:21:20 +00:00
|
|
|
}
|
2019-07-31 19:25:30 +00:00
|
|
|
)
|
2019-03-11 19:21:20 +00:00
|
|
|
|
|
|
|
received = []
|
|
|
|
|
|
|
|
async def handler(hass, webhook_id, request):
|
|
|
|
"""Handle a webhook."""
|
|
|
|
received.append(request)
|
2019-07-31 19:25:30 +00:00
|
|
|
return web.json_response({"from": "handler"})
|
2019-03-11 19:21:20 +00:00
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
hass.components.webhook.async_register("test", "Test", "mock-webhook-id", handler)
|
2019-03-11 19:21:20 +00:00
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
response = await cloud.client.async_webhook_message(
|
|
|
|
{
|
|
|
|
"cloudhook_id": "mock-cloud-id",
|
|
|
|
"body": '{"hello": "world"}',
|
|
|
|
"headers": {"content-type": "application/json"},
|
|
|
|
"method": "POST",
|
|
|
|
"query": None,
|
|
|
|
}
|
|
|
|
)
|
2019-03-11 19:21:20 +00:00
|
|
|
|
|
|
|
assert response == {
|
2019-07-31 19:25:30 +00:00
|
|
|
"status": 200,
|
|
|
|
"body": '{"from": "handler"}',
|
|
|
|
"headers": {"Content-Type": "application/json"},
|
2019-03-11 19:21:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
assert len(received) == 1
|
2019-07-31 19:25:30 +00:00
|
|
|
assert await received[0].json() == {"hello": "world"}
|
2019-05-29 15:39:12 +00:00
|
|
|
|
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
async def test_google_config_expose_entity(hass, mock_cloud_setup, mock_cloud_login):
|
2019-05-29 15:39:12 +00:00
|
|
|
"""Test Google config exposing entity method uses latest config."""
|
|
|
|
cloud_client = hass.data[DOMAIN].client
|
2019-07-31 19:25:30 +00:00
|
|
|
state = State("light.kitchen", "on")
|
2019-05-29 15:39:12 +00:00
|
|
|
|
|
|
|
assert cloud_client.google_config.should_expose(state)
|
|
|
|
|
|
|
|
await cloud_client.prefs.async_update_google_entity_config(
|
2019-07-31 19:25:30 +00:00
|
|
|
entity_id="light.kitchen", should_expose=False
|
2019-05-29 15:39:12 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
assert not cloud_client.google_config.should_expose(state)
|
|
|
|
|
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
async def test_google_config_should_2fa(hass, mock_cloud_setup, mock_cloud_login):
|
2019-05-29 15:39:12 +00:00
|
|
|
"""Test Google config disabling 2FA method uses latest config."""
|
|
|
|
cloud_client = hass.data[DOMAIN].client
|
2019-07-31 19:25:30 +00:00
|
|
|
state = State("light.kitchen", "on")
|
2019-05-29 15:39:12 +00:00
|
|
|
|
|
|
|
assert cloud_client.google_config.should_2fa(state)
|
|
|
|
|
|
|
|
await cloud_client.prefs.async_update_google_entity_config(
|
2019-07-31 19:25:30 +00:00
|
|
|
entity_id="light.kitchen", disable_2fa=True
|
2019-05-29 15:39:12 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
assert not cloud_client.google_config.should_2fa(state)
|