2017-08-29 20:40:08 +00:00
|
|
|
"""Tests for the HTTP API for the cloud component."""
|
|
|
|
import asyncio
|
|
|
|
from unittest.mock import patch, MagicMock
|
2019-06-08 06:08:55 +00:00
|
|
|
from ipaddress import ip_network
|
2017-08-29 20:40:08 +00:00
|
|
|
|
|
|
|
import pytest
|
2017-11-15 07:16:19 +00:00
|
|
|
from jose import jwt
|
2019-03-11 19:21:20 +00:00
|
|
|
from hass_nabucasa.auth import Unauthenticated, UnknownError
|
|
|
|
from hass_nabucasa.const import STATE_CONNECTED
|
2017-08-29 20:40:08 +00:00
|
|
|
|
2019-05-29 15:39:12 +00:00
|
|
|
from homeassistant.core import State
|
2019-03-16 02:26:10 +00:00
|
|
|
from homeassistant.auth.providers import trusted_networks as tn_auth
|
2018-11-20 22:23:07 +00:00
|
|
|
from homeassistant.components.cloud.const import (
|
2019-04-19 21:50:21 +00:00
|
|
|
PREF_ENABLE_GOOGLE, PREF_ENABLE_ALEXA, PREF_GOOGLE_SECURE_DEVICES_PIN,
|
|
|
|
DOMAIN)
|
2019-05-29 15:39:12 +00:00
|
|
|
from homeassistant.components.google_assistant.helpers import (
|
2019-06-21 09:17:21 +00:00
|
|
|
GoogleEntity)
|
2019-06-13 18:58:08 +00:00
|
|
|
from homeassistant.components.alexa.entities import LightCapabilities
|
2019-06-25 05:04:31 +00:00
|
|
|
from homeassistant.components.alexa import errors as alexa_errors
|
2017-08-29 20:40:08 +00:00
|
|
|
|
2017-10-15 02:43:14 +00:00
|
|
|
from tests.common import mock_coro
|
2019-06-21 09:17:21 +00:00
|
|
|
from tests.components.google_assistant import MockConfig
|
2017-10-15 02:43:14 +00:00
|
|
|
|
2018-09-20 21:46:51 +00:00
|
|
|
from . import mock_cloud, mock_cloud_prefs
|
2017-08-29 20:40:08 +00:00
|
|
|
|
2018-03-23 19:13:52 +00:00
|
|
|
GOOGLE_ACTIONS_SYNC_URL = 'https://api-test.hass.io/google_actions_sync'
|
2018-09-20 12:53:13 +00:00
|
|
|
SUBSCRIPTION_INFO_URL = 'https://api-test.hass.io/subscription_info'
|
2018-03-23 19:13:52 +00:00
|
|
|
|
|
|
|
|
2018-09-20 12:53:13 +00:00
|
|
|
@pytest.fixture()
|
|
|
|
def mock_auth():
|
|
|
|
"""Mock check token."""
|
2019-03-11 19:21:20 +00:00
|
|
|
with patch('hass_nabucasa.auth.CognitoAuth.check_token'):
|
2018-09-20 12:53:13 +00:00
|
|
|
yield
|
|
|
|
|
|
|
|
|
2019-03-12 14:54:04 +00:00
|
|
|
@pytest.fixture()
|
|
|
|
def mock_cloud_login(hass, setup_api):
|
|
|
|
"""Mock cloud is logged in."""
|
|
|
|
hass.data[DOMAIN].id_token = jwt.encode({
|
|
|
|
'email': 'hello@home-assistant.io',
|
2019-05-29 15:39:12 +00:00
|
|
|
'custom:sub-exp': '2018-01-03',
|
|
|
|
'cognito:username': 'abcdefghjkl',
|
2019-03-12 14:54:04 +00:00
|
|
|
}, 'test')
|
|
|
|
|
|
|
|
|
2018-09-20 12:53:13 +00:00
|
|
|
@pytest.fixture(autouse=True)
|
2019-03-11 19:21:20 +00:00
|
|
|
def setup_api(hass, aioclient_mock):
|
2018-09-20 12:53:13 +00:00
|
|
|
"""Initialize HTTP API."""
|
2019-06-21 09:17:21 +00:00
|
|
|
hass.loop.run_until_complete(mock_cloud(hass, {
|
2018-09-20 21:46:51 +00:00
|
|
|
'mode': 'development',
|
|
|
|
'cognito_client_id': 'cognito_client_id',
|
|
|
|
'user_pool_id': 'user_pool_id',
|
|
|
|
'region': 'region',
|
|
|
|
'relayer': 'relayer',
|
|
|
|
'google_actions_sync_url': GOOGLE_ACTIONS_SYNC_URL,
|
|
|
|
'subscription_info_url': SUBSCRIPTION_INFO_URL,
|
2018-11-05 12:21:03 +00:00
|
|
|
'google_actions': {
|
|
|
|
'filter': {
|
|
|
|
'include_domains': 'light'
|
|
|
|
}
|
|
|
|
},
|
|
|
|
'alexa': {
|
|
|
|
'filter': {
|
|
|
|
'include_entities': ['light.kitchen', 'switch.ac']
|
|
|
|
}
|
|
|
|
}
|
2019-06-21 09:17:21 +00:00
|
|
|
}))
|
2018-09-20 21:46:51 +00:00
|
|
|
return mock_cloud_prefs(hass)
|
2018-09-20 12:53:13 +00:00
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture
|
2018-12-02 15:32:53 +00:00
|
|
|
def cloud_client(hass, hass_client):
|
2018-09-20 12:53:13 +00:00
|
|
|
"""Fixture that can fetch from the cloud client."""
|
2019-03-11 19:21:20 +00:00
|
|
|
with patch('hass_nabucasa.Cloud.write_user_info'):
|
2018-12-02 15:32:53 +00:00
|
|
|
yield hass.loop.run_until_complete(hass_client())
|
2017-08-29 20:40:08 +00:00
|
|
|
|
|
|
|
|
2017-09-12 16:47:04 +00:00
|
|
|
@pytest.fixture
|
|
|
|
def mock_cognito():
|
|
|
|
"""Mock warrant."""
|
2019-03-11 19:21:20 +00:00
|
|
|
with patch('hass_nabucasa.auth.CognitoAuth._cognito') as mock_cog:
|
2017-09-12 16:47:04 +00:00
|
|
|
yield mock_cog()
|
|
|
|
|
|
|
|
|
2018-03-23 19:13:52 +00:00
|
|
|
async def test_google_actions_sync(mock_cognito, cloud_client, aioclient_mock):
|
|
|
|
"""Test syncing Google Actions."""
|
|
|
|
aioclient_mock.post(GOOGLE_ACTIONS_SYNC_URL)
|
|
|
|
req = await cloud_client.post('/api/cloud/google_actions/sync')
|
|
|
|
assert req.status == 200
|
|
|
|
|
|
|
|
|
|
|
|
async def test_google_actions_sync_fails(mock_cognito, cloud_client,
|
|
|
|
aioclient_mock):
|
|
|
|
"""Test syncing Google Actions gone bad."""
|
|
|
|
aioclient_mock.post(GOOGLE_ACTIONS_SYNC_URL, status=403)
|
|
|
|
req = await cloud_client.post('/api/cloud/google_actions/sync')
|
|
|
|
assert req.status == 403
|
|
|
|
|
|
|
|
|
2019-03-11 19:21:20 +00:00
|
|
|
async def test_login_view(hass, cloud_client, mock_cognito):
|
2017-08-29 20:40:08 +00:00
|
|
|
"""Test logging in."""
|
2017-11-15 07:16:19 +00:00
|
|
|
mock_cognito.id_token = jwt.encode({
|
|
|
|
'email': 'hello@home-assistant.io',
|
|
|
|
'custom:sub-exp': '2018-01-03'
|
|
|
|
}, 'test')
|
|
|
|
mock_cognito.access_token = 'access_token'
|
|
|
|
mock_cognito.refresh_token = 'refresh_token'
|
|
|
|
|
2019-03-11 19:21:20 +00:00
|
|
|
with patch('hass_nabucasa.iot.CloudIoT.connect') as mock_connect, \
|
|
|
|
patch('hass_nabucasa.auth.CognitoAuth._authenticate',
|
2017-11-15 07:16:19 +00:00
|
|
|
return_value=mock_cognito) as mock_auth:
|
2019-03-11 19:21:20 +00:00
|
|
|
req = await cloud_client.post('/api/cloud/login', json={
|
2017-10-15 02:43:14 +00:00
|
|
|
'email': 'my_username',
|
|
|
|
'password': 'my_password'
|
|
|
|
})
|
2017-08-29 20:40:08 +00:00
|
|
|
|
|
|
|
assert req.status == 200
|
2019-03-11 19:21:20 +00:00
|
|
|
result = await req.json()
|
2018-09-20 12:53:13 +00:00
|
|
|
assert result == {'success': True}
|
2017-11-15 07:16:19 +00:00
|
|
|
|
|
|
|
assert len(mock_connect.mock_calls) == 1
|
|
|
|
|
|
|
|
assert len(mock_auth.mock_calls) == 1
|
2019-03-11 19:21:20 +00:00
|
|
|
result_user, result_pass = mock_auth.mock_calls[0][1]
|
2017-09-12 16:47:04 +00:00
|
|
|
assert result_user == 'my_username'
|
|
|
|
assert result_pass == 'my_password'
|
2017-08-29 20:40:08 +00:00
|
|
|
|
|
|
|
|
2019-02-04 09:14:30 +00:00
|
|
|
async def test_login_view_random_exception(cloud_client):
|
|
|
|
"""Try logging in with invalid JSON."""
|
|
|
|
with patch('async_timeout.timeout', side_effect=ValueError('Boom')):
|
|
|
|
req = await cloud_client.post('/api/cloud/login', json={
|
|
|
|
'email': 'my_username',
|
|
|
|
'password': 'my_password'
|
|
|
|
})
|
|
|
|
assert req.status == 502
|
|
|
|
resp = await req.json()
|
|
|
|
assert resp == {'code': 'valueerror', 'message': 'Unexpected error: Boom'}
|
|
|
|
|
|
|
|
|
2019-03-11 19:21:20 +00:00
|
|
|
async def test_login_view_invalid_json(cloud_client):
|
2017-08-29 20:40:08 +00:00
|
|
|
"""Try logging in with invalid JSON."""
|
2019-03-11 19:21:20 +00:00
|
|
|
with patch('hass_nabucasa.auth.CognitoAuth.login') as mock_login:
|
|
|
|
req = await cloud_client.post('/api/cloud/login', data='Not JSON')
|
2017-08-29 20:40:08 +00:00
|
|
|
assert req.status == 400
|
2017-10-15 02:43:14 +00:00
|
|
|
assert len(mock_login.mock_calls) == 0
|
2017-08-29 20:40:08 +00:00
|
|
|
|
|
|
|
|
2019-03-11 19:21:20 +00:00
|
|
|
async def test_login_view_invalid_schema(cloud_client):
|
2017-08-29 20:40:08 +00:00
|
|
|
"""Try logging in with invalid schema."""
|
2019-03-11 19:21:20 +00:00
|
|
|
with patch('hass_nabucasa.auth.CognitoAuth.login') as mock_login:
|
|
|
|
req = await cloud_client.post('/api/cloud/login', json={
|
2017-10-15 02:43:14 +00:00
|
|
|
'invalid': 'schema'
|
|
|
|
})
|
2017-08-29 20:40:08 +00:00
|
|
|
assert req.status == 400
|
2017-10-15 02:43:14 +00:00
|
|
|
assert len(mock_login.mock_calls) == 0
|
2017-08-29 20:40:08 +00:00
|
|
|
|
|
|
|
|
2019-03-11 19:21:20 +00:00
|
|
|
async def test_login_view_request_timeout(cloud_client):
|
2017-08-29 20:40:08 +00:00
|
|
|
"""Test request timeout while trying to log in."""
|
2019-03-11 19:21:20 +00:00
|
|
|
with patch('hass_nabucasa.auth.CognitoAuth.login',
|
2017-10-15 02:43:14 +00:00
|
|
|
side_effect=asyncio.TimeoutError):
|
2019-03-11 19:21:20 +00:00
|
|
|
req = await cloud_client.post('/api/cloud/login', json={
|
2017-10-15 02:43:14 +00:00
|
|
|
'email': 'my_username',
|
|
|
|
'password': 'my_password'
|
|
|
|
})
|
2017-08-29 20:40:08 +00:00
|
|
|
|
|
|
|
assert req.status == 502
|
|
|
|
|
|
|
|
|
2019-03-11 19:21:20 +00:00
|
|
|
async def test_login_view_invalid_credentials(cloud_client):
|
2017-08-29 20:40:08 +00:00
|
|
|
"""Test logging in with invalid credentials."""
|
2019-03-11 19:21:20 +00:00
|
|
|
with patch('hass_nabucasa.auth.CognitoAuth.login',
|
|
|
|
side_effect=Unauthenticated):
|
|
|
|
req = await cloud_client.post('/api/cloud/login', json={
|
2017-10-15 02:43:14 +00:00
|
|
|
'email': 'my_username',
|
|
|
|
'password': 'my_password'
|
|
|
|
})
|
2017-08-29 20:40:08 +00:00
|
|
|
|
|
|
|
assert req.status == 401
|
|
|
|
|
|
|
|
|
2019-03-11 19:21:20 +00:00
|
|
|
async def test_login_view_unknown_error(cloud_client):
|
2017-08-29 20:40:08 +00:00
|
|
|
"""Test unknown error while logging in."""
|
2019-03-11 19:21:20 +00:00
|
|
|
with patch('hass_nabucasa.auth.CognitoAuth.login',
|
|
|
|
side_effect=UnknownError):
|
|
|
|
req = await cloud_client.post('/api/cloud/login', json={
|
2017-10-15 02:43:14 +00:00
|
|
|
'email': 'my_username',
|
|
|
|
'password': 'my_password'
|
|
|
|
})
|
2017-08-29 20:40:08 +00:00
|
|
|
|
2017-09-12 16:47:04 +00:00
|
|
|
assert req.status == 502
|
2017-08-29 20:40:08 +00:00
|
|
|
|
|
|
|
|
2019-03-11 19:21:20 +00:00
|
|
|
async def test_logout_view(hass, cloud_client):
|
2017-08-29 20:40:08 +00:00
|
|
|
"""Test logging out."""
|
2017-10-15 02:43:14 +00:00
|
|
|
cloud = hass.data['cloud'] = MagicMock()
|
|
|
|
cloud.logout.return_value = mock_coro()
|
2019-03-11 19:21:20 +00:00
|
|
|
req = await cloud_client.post('/api/cloud/logout')
|
2017-08-29 20:40:08 +00:00
|
|
|
assert req.status == 200
|
2019-03-11 19:21:20 +00:00
|
|
|
data = await req.json()
|
2017-09-12 16:47:04 +00:00
|
|
|
assert data == {'message': 'ok'}
|
2017-10-15 02:43:14 +00:00
|
|
|
assert len(cloud.logout.mock_calls) == 1
|
2017-08-29 20:40:08 +00:00
|
|
|
|
|
|
|
|
2019-03-11 19:21:20 +00:00
|
|
|
async def test_logout_view_request_timeout(hass, cloud_client):
|
2017-08-29 20:40:08 +00:00
|
|
|
"""Test timeout while logging out."""
|
2017-10-15 02:43:14 +00:00
|
|
|
cloud = hass.data['cloud'] = MagicMock()
|
|
|
|
cloud.logout.side_effect = asyncio.TimeoutError
|
2019-03-11 19:21:20 +00:00
|
|
|
req = await cloud_client.post('/api/cloud/logout')
|
2017-09-12 16:47:04 +00:00
|
|
|
assert req.status == 502
|
|
|
|
|
2017-08-29 20:40:08 +00:00
|
|
|
|
2019-03-11 19:21:20 +00:00
|
|
|
async def test_logout_view_unknown_error(hass, cloud_client):
|
2017-09-23 15:15:46 +00:00
|
|
|
"""Test unknown error while logging out."""
|
2017-10-15 02:43:14 +00:00
|
|
|
cloud = hass.data['cloud'] = MagicMock()
|
2019-03-11 19:21:20 +00:00
|
|
|
cloud.logout.side_effect = UnknownError
|
|
|
|
req = await cloud_client.post('/api/cloud/logout')
|
2017-08-29 20:40:08 +00:00
|
|
|
assert req.status == 502
|
|
|
|
|
|
|
|
|
2019-03-11 19:21:20 +00:00
|
|
|
async def test_register_view(mock_cognito, cloud_client):
|
2017-09-12 16:47:04 +00:00
|
|
|
"""Test logging out."""
|
2019-03-11 19:21:20 +00:00
|
|
|
req = await cloud_client.post('/api/cloud/register', json={
|
2017-09-12 16:47:04 +00:00
|
|
|
'email': 'hello@bla.com',
|
|
|
|
'password': 'falcon42'
|
|
|
|
})
|
|
|
|
assert req.status == 200
|
|
|
|
assert len(mock_cognito.register.mock_calls) == 1
|
|
|
|
result_email, result_pass = mock_cognito.register.mock_calls[0][1]
|
2017-11-27 09:09:17 +00:00
|
|
|
assert result_email == 'hello@bla.com'
|
2017-09-12 16:47:04 +00:00
|
|
|
assert result_pass == 'falcon42'
|
|
|
|
|
|
|
|
|
2019-03-11 19:21:20 +00:00
|
|
|
async def test_register_view_bad_data(mock_cognito, cloud_client):
|
2017-09-12 16:47:04 +00:00
|
|
|
"""Test logging out."""
|
2019-03-11 19:21:20 +00:00
|
|
|
req = await cloud_client.post('/api/cloud/register', json={
|
2017-09-12 16:47:04 +00:00
|
|
|
'email': 'hello@bla.com',
|
|
|
|
'not_password': 'falcon'
|
|
|
|
})
|
|
|
|
assert req.status == 400
|
|
|
|
assert len(mock_cognito.logout.mock_calls) == 0
|
|
|
|
|
|
|
|
|
2019-03-11 19:21:20 +00:00
|
|
|
async def test_register_view_request_timeout(mock_cognito, cloud_client):
|
2017-09-12 16:47:04 +00:00
|
|
|
"""Test timeout while logging out."""
|
|
|
|
mock_cognito.register.side_effect = asyncio.TimeoutError
|
2019-03-11 19:21:20 +00:00
|
|
|
req = await cloud_client.post('/api/cloud/register', json={
|
2017-09-12 16:47:04 +00:00
|
|
|
'email': 'hello@bla.com',
|
|
|
|
'password': 'falcon42'
|
|
|
|
})
|
|
|
|
assert req.status == 502
|
|
|
|
|
|
|
|
|
2019-03-11 19:21:20 +00:00
|
|
|
async def test_register_view_unknown_error(mock_cognito, cloud_client):
|
2017-09-23 15:15:46 +00:00
|
|
|
"""Test unknown error while logging out."""
|
2019-03-11 19:21:20 +00:00
|
|
|
mock_cognito.register.side_effect = UnknownError
|
|
|
|
req = await cloud_client.post('/api/cloud/register', json={
|
2017-09-12 16:47:04 +00:00
|
|
|
'email': 'hello@bla.com',
|
|
|
|
'password': 'falcon42'
|
|
|
|
})
|
|
|
|
assert req.status == 502
|
2017-08-29 20:40:08 +00:00
|
|
|
|
2017-09-12 16:47:04 +00:00
|
|
|
|
2019-03-11 19:21:20 +00:00
|
|
|
async def test_forgot_password_view(mock_cognito, cloud_client):
|
2017-09-12 16:47:04 +00:00
|
|
|
"""Test logging out."""
|
2019-03-11 19:21:20 +00:00
|
|
|
req = await cloud_client.post('/api/cloud/forgot_password', json={
|
2017-09-12 16:47:04 +00:00
|
|
|
'email': 'hello@bla.com',
|
|
|
|
})
|
|
|
|
assert req.status == 200
|
|
|
|
assert len(mock_cognito.initiate_forgot_password.mock_calls) == 1
|
|
|
|
|
|
|
|
|
2019-03-11 19:21:20 +00:00
|
|
|
async def test_forgot_password_view_bad_data(mock_cognito, cloud_client):
|
2017-09-12 16:47:04 +00:00
|
|
|
"""Test logging out."""
|
2019-03-11 19:21:20 +00:00
|
|
|
req = await cloud_client.post('/api/cloud/forgot_password', json={
|
2017-09-12 16:47:04 +00:00
|
|
|
'not_email': 'hello@bla.com',
|
|
|
|
})
|
|
|
|
assert req.status == 400
|
|
|
|
assert len(mock_cognito.initiate_forgot_password.mock_calls) == 0
|
|
|
|
|
|
|
|
|
2019-03-11 19:21:20 +00:00
|
|
|
async def test_forgot_password_view_request_timeout(mock_cognito,
|
|
|
|
cloud_client):
|
2017-09-12 16:47:04 +00:00
|
|
|
"""Test timeout while logging out."""
|
|
|
|
mock_cognito.initiate_forgot_password.side_effect = asyncio.TimeoutError
|
2019-03-11 19:21:20 +00:00
|
|
|
req = await cloud_client.post('/api/cloud/forgot_password', json={
|
2017-09-12 16:47:04 +00:00
|
|
|
'email': 'hello@bla.com',
|
|
|
|
})
|
|
|
|
assert req.status == 502
|
|
|
|
|
|
|
|
|
2019-03-11 19:21:20 +00:00
|
|
|
async def test_forgot_password_view_unknown_error(mock_cognito, cloud_client):
|
2017-09-23 15:15:46 +00:00
|
|
|
"""Test unknown error while logging out."""
|
2019-03-11 19:21:20 +00:00
|
|
|
mock_cognito.initiate_forgot_password.side_effect = UnknownError
|
|
|
|
req = await cloud_client.post('/api/cloud/forgot_password', json={
|
2017-09-12 16:47:04 +00:00
|
|
|
'email': 'hello@bla.com',
|
|
|
|
})
|
|
|
|
assert req.status == 502
|
|
|
|
|
|
|
|
|
2019-03-11 19:21:20 +00:00
|
|
|
async def test_resend_confirm_view(mock_cognito, cloud_client):
|
2017-12-29 13:46:10 +00:00
|
|
|
"""Test logging out."""
|
2019-03-11 19:21:20 +00:00
|
|
|
req = await cloud_client.post('/api/cloud/resend_confirm', json={
|
2017-12-29 13:46:10 +00:00
|
|
|
'email': 'hello@bla.com',
|
|
|
|
})
|
|
|
|
assert req.status == 200
|
|
|
|
assert len(mock_cognito.client.resend_confirmation_code.mock_calls) == 1
|
|
|
|
|
|
|
|
|
2019-03-11 19:21:20 +00:00
|
|
|
async def test_resend_confirm_view_bad_data(mock_cognito, cloud_client):
|
2017-12-29 13:46:10 +00:00
|
|
|
"""Test logging out."""
|
2019-03-11 19:21:20 +00:00
|
|
|
req = await cloud_client.post('/api/cloud/resend_confirm', json={
|
2017-12-29 13:46:10 +00:00
|
|
|
'not_email': 'hello@bla.com',
|
|
|
|
})
|
|
|
|
assert req.status == 400
|
|
|
|
assert len(mock_cognito.client.resend_confirmation_code.mock_calls) == 0
|
|
|
|
|
|
|
|
|
2019-03-11 19:21:20 +00:00
|
|
|
async def test_resend_confirm_view_request_timeout(mock_cognito, cloud_client):
|
2017-12-29 13:46:10 +00:00
|
|
|
"""Test timeout while logging out."""
|
|
|
|
mock_cognito.client.resend_confirmation_code.side_effect = \
|
|
|
|
asyncio.TimeoutError
|
2019-03-11 19:21:20 +00:00
|
|
|
req = await cloud_client.post('/api/cloud/resend_confirm', json={
|
2017-12-29 13:46:10 +00:00
|
|
|
'email': 'hello@bla.com',
|
|
|
|
})
|
|
|
|
assert req.status == 502
|
|
|
|
|
|
|
|
|
2019-03-11 19:21:20 +00:00
|
|
|
async def test_resend_confirm_view_unknown_error(mock_cognito, cloud_client):
|
2017-12-29 13:46:10 +00:00
|
|
|
"""Test unknown error while logging out."""
|
2019-03-11 19:21:20 +00:00
|
|
|
mock_cognito.client.resend_confirmation_code.side_effect = UnknownError
|
|
|
|
req = await cloud_client.post('/api/cloud/resend_confirm', json={
|
2017-12-29 13:46:10 +00:00
|
|
|
'email': 'hello@bla.com',
|
|
|
|
})
|
|
|
|
assert req.status == 502
|
2018-09-20 12:53:13 +00:00
|
|
|
|
|
|
|
|
2019-03-12 14:54:04 +00:00
|
|
|
async def test_websocket_status(hass, hass_ws_client, mock_cloud_fixture,
|
|
|
|
mock_cloud_login):
|
2018-09-20 12:53:13 +00:00
|
|
|
"""Test querying the status."""
|
2019-03-11 19:21:20 +00:00
|
|
|
hass.data[DOMAIN].iot.state = STATE_CONNECTED
|
2018-09-20 12:53:13 +00:00
|
|
|
client = await hass_ws_client(hass)
|
2018-11-05 12:21:03 +00:00
|
|
|
|
|
|
|
with patch.dict(
|
2019-04-18 05:37:39 +00:00
|
|
|
'homeassistant.components.google_assistant.const.'
|
2018-11-05 12:21:03 +00:00
|
|
|
'DOMAIN_TO_GOOGLE_TYPES', {'light': None}, clear=True
|
2019-06-13 15:43:57 +00:00
|
|
|
), patch.dict('homeassistant.components.alexa.entities.ENTITY_ADAPTERS',
|
2018-11-05 12:21:03 +00:00
|
|
|
{'switch': None}, clear=True):
|
|
|
|
await client.send_json({
|
|
|
|
'id': 5,
|
|
|
|
'type': 'cloud/status'
|
|
|
|
})
|
|
|
|
response = await client.receive_json()
|
2018-09-20 12:53:13 +00:00
|
|
|
assert response['result'] == {
|
|
|
|
'logged_in': True,
|
|
|
|
'email': 'hello@home-assistant.io',
|
|
|
|
'cloud': 'connected',
|
2019-05-29 15:39:12 +00:00
|
|
|
'prefs': {
|
|
|
|
'alexa_enabled': True,
|
|
|
|
'cloud_user': None,
|
|
|
|
'cloudhooks': {},
|
|
|
|
'google_enabled': True,
|
|
|
|
'google_entity_configs': {},
|
|
|
|
'google_secure_devices_pin': None,
|
2019-06-13 18:58:08 +00:00
|
|
|
'alexa_entity_configs': {},
|
2019-06-17 20:50:01 +00:00
|
|
|
'alexa_report_state': False,
|
2019-05-29 15:39:12 +00:00
|
|
|
'remote_enabled': False,
|
|
|
|
},
|
2018-11-05 12:21:03 +00:00
|
|
|
'alexa_entities': {
|
|
|
|
'include_domains': [],
|
|
|
|
'include_entities': ['light.kitchen', 'switch.ac'],
|
|
|
|
'exclude_domains': [],
|
|
|
|
'exclude_entities': [],
|
|
|
|
},
|
|
|
|
'google_entities': {
|
|
|
|
'include_domains': ['light'],
|
|
|
|
'include_entities': [],
|
|
|
|
'exclude_domains': [],
|
|
|
|
'exclude_entities': [],
|
|
|
|
},
|
2019-03-12 14:54:04 +00:00
|
|
|
'remote_domain': None,
|
|
|
|
'remote_connected': False,
|
|
|
|
'remote_certificate': None,
|
2018-09-20 12:53:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async def test_websocket_status_not_logged_in(hass, hass_ws_client):
|
|
|
|
"""Test querying the status."""
|
|
|
|
client = await hass_ws_client(hass)
|
|
|
|
await client.send_json({
|
|
|
|
'id': 5,
|
|
|
|
'type': 'cloud/status'
|
|
|
|
})
|
|
|
|
response = await client.receive_json()
|
|
|
|
assert response['result'] == {
|
|
|
|
'logged_in': False,
|
|
|
|
'cloud': 'disconnected'
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-10-21 10:16:24 +00:00
|
|
|
async def test_websocket_subscription_reconnect(
|
2019-03-12 14:54:04 +00:00
|
|
|
hass, hass_ws_client, aioclient_mock, mock_auth, mock_cloud_login):
|
2018-10-21 10:16:24 +00:00
|
|
|
"""Test querying the status and connecting because valid account."""
|
|
|
|
aioclient_mock.get(SUBSCRIPTION_INFO_URL, json={'provider': 'stripe'})
|
|
|
|
client = await hass_ws_client(hass)
|
|
|
|
|
|
|
|
with patch(
|
2019-03-11 19:21:20 +00:00
|
|
|
'hass_nabucasa.auth.CognitoAuth.renew_access_token'
|
2018-10-21 10:16:24 +00:00
|
|
|
) as mock_renew, patch(
|
2019-03-11 19:21:20 +00:00
|
|
|
'hass_nabucasa.iot.CloudIoT.connect'
|
2018-10-21 10:16:24 +00:00
|
|
|
) as mock_connect:
|
|
|
|
await client.send_json({
|
|
|
|
'id': 5,
|
|
|
|
'type': 'cloud/subscription'
|
|
|
|
})
|
|
|
|
response = await client.receive_json()
|
|
|
|
|
|
|
|
assert response['result'] == {
|
|
|
|
'provider': 'stripe'
|
|
|
|
}
|
|
|
|
assert len(mock_renew.mock_calls) == 1
|
|
|
|
assert len(mock_connect.mock_calls) == 1
|
|
|
|
|
|
|
|
|
|
|
|
async def test_websocket_subscription_no_reconnect_if_connected(
|
2019-03-12 14:54:04 +00:00
|
|
|
hass, hass_ws_client, aioclient_mock, mock_auth, mock_cloud_login):
|
2018-10-21 10:16:24 +00:00
|
|
|
"""Test querying the status and not reconnecting because still expired."""
|
|
|
|
aioclient_mock.get(SUBSCRIPTION_INFO_URL, json={'provider': 'stripe'})
|
2019-03-11 19:21:20 +00:00
|
|
|
hass.data[DOMAIN].iot.state = STATE_CONNECTED
|
2018-10-21 10:16:24 +00:00
|
|
|
client = await hass_ws_client(hass)
|
|
|
|
|
|
|
|
with patch(
|
2019-03-11 19:21:20 +00:00
|
|
|
'hass_nabucasa.auth.CognitoAuth.renew_access_token'
|
2018-10-21 10:16:24 +00:00
|
|
|
) as mock_renew, patch(
|
2019-03-11 19:21:20 +00:00
|
|
|
'hass_nabucasa.iot.CloudIoT.connect'
|
2018-10-21 10:16:24 +00:00
|
|
|
) as mock_connect:
|
|
|
|
await client.send_json({
|
|
|
|
'id': 5,
|
|
|
|
'type': 'cloud/subscription'
|
|
|
|
})
|
|
|
|
response = await client.receive_json()
|
|
|
|
|
|
|
|
assert response['result'] == {
|
|
|
|
'provider': 'stripe'
|
|
|
|
}
|
|
|
|
assert len(mock_renew.mock_calls) == 0
|
|
|
|
assert len(mock_connect.mock_calls) == 0
|
|
|
|
|
|
|
|
|
|
|
|
async def test_websocket_subscription_no_reconnect_if_expired(
|
2019-03-12 14:54:04 +00:00
|
|
|
hass, hass_ws_client, aioclient_mock, mock_auth, mock_cloud_login):
|
2018-10-21 10:16:24 +00:00
|
|
|
"""Test querying the status and not reconnecting because still expired."""
|
|
|
|
aioclient_mock.get(SUBSCRIPTION_INFO_URL, json={'provider': 'stripe'})
|
2018-09-20 12:53:13 +00:00
|
|
|
client = await hass_ws_client(hass)
|
2018-10-21 10:16:24 +00:00
|
|
|
|
|
|
|
with patch(
|
2019-03-11 19:21:20 +00:00
|
|
|
'hass_nabucasa.auth.CognitoAuth.renew_access_token'
|
2018-10-21 10:16:24 +00:00
|
|
|
) as mock_renew, patch(
|
2019-03-11 19:21:20 +00:00
|
|
|
'hass_nabucasa.iot.CloudIoT.connect'
|
2018-10-21 10:16:24 +00:00
|
|
|
) as mock_connect:
|
|
|
|
await client.send_json({
|
|
|
|
'id': 5,
|
|
|
|
'type': 'cloud/subscription'
|
|
|
|
})
|
|
|
|
response = await client.receive_json()
|
2018-09-20 12:53:13 +00:00
|
|
|
|
|
|
|
assert response['result'] == {
|
2018-10-21 10:16:24 +00:00
|
|
|
'provider': 'stripe'
|
2018-09-20 12:53:13 +00:00
|
|
|
}
|
2018-10-21 10:16:24 +00:00
|
|
|
assert len(mock_renew.mock_calls) == 1
|
|
|
|
assert len(mock_connect.mock_calls) == 1
|
2018-09-20 12:53:13 +00:00
|
|
|
|
|
|
|
|
|
|
|
async def test_websocket_subscription_fail(hass, hass_ws_client,
|
2019-03-12 14:54:04 +00:00
|
|
|
aioclient_mock, mock_auth,
|
|
|
|
mock_cloud_login):
|
2018-09-20 12:53:13 +00:00
|
|
|
"""Test querying the status."""
|
|
|
|
aioclient_mock.get(SUBSCRIPTION_INFO_URL, status=500)
|
|
|
|
client = await hass_ws_client(hass)
|
|
|
|
await client.send_json({
|
|
|
|
'id': 5,
|
|
|
|
'type': 'cloud/subscription'
|
|
|
|
})
|
|
|
|
response = await client.receive_json()
|
|
|
|
|
|
|
|
assert not response['success']
|
|
|
|
assert response['error']['code'] == 'request_failed'
|
|
|
|
|
|
|
|
|
|
|
|
async def test_websocket_subscription_not_logged_in(hass, hass_ws_client):
|
|
|
|
"""Test querying the status."""
|
|
|
|
client = await hass_ws_client(hass)
|
2019-03-11 19:21:20 +00:00
|
|
|
with patch('hass_nabucasa.Cloud.fetch_subscription_info',
|
2018-09-20 12:53:13 +00:00
|
|
|
return_value=mock_coro({'return': 'value'})):
|
|
|
|
await client.send_json({
|
|
|
|
'id': 5,
|
|
|
|
'type': 'cloud/subscription'
|
|
|
|
})
|
|
|
|
response = await client.receive_json()
|
|
|
|
|
|
|
|
assert not response['success']
|
|
|
|
assert response['error']['code'] == 'not_logged_in'
|
2018-09-20 21:46:51 +00:00
|
|
|
|
|
|
|
|
|
|
|
async def test_websocket_update_preferences(hass, hass_ws_client,
|
2019-03-12 14:54:04 +00:00
|
|
|
aioclient_mock, setup_api,
|
|
|
|
mock_cloud_login):
|
2018-09-20 21:46:51 +00:00
|
|
|
"""Test updating preference."""
|
2018-11-20 22:23:07 +00:00
|
|
|
assert setup_api[PREF_ENABLE_GOOGLE]
|
|
|
|
assert setup_api[PREF_ENABLE_ALEXA]
|
2019-04-19 21:50:21 +00:00
|
|
|
assert setup_api[PREF_GOOGLE_SECURE_DEVICES_PIN] is None
|
2018-09-20 21:46:51 +00:00
|
|
|
client = await hass_ws_client(hass)
|
|
|
|
await client.send_json({
|
|
|
|
'id': 5,
|
|
|
|
'type': 'cloud/update_prefs',
|
|
|
|
'alexa_enabled': False,
|
|
|
|
'google_enabled': False,
|
2019-04-19 21:50:21 +00:00
|
|
|
'google_secure_devices_pin': '1234',
|
2018-09-20 21:46:51 +00:00
|
|
|
})
|
|
|
|
response = await client.receive_json()
|
|
|
|
|
|
|
|
assert response['success']
|
2018-11-20 22:23:07 +00:00
|
|
|
assert not setup_api[PREF_ENABLE_GOOGLE]
|
|
|
|
assert not setup_api[PREF_ENABLE_ALEXA]
|
2019-04-19 21:50:21 +00:00
|
|
|
assert setup_api[PREF_GOOGLE_SECURE_DEVICES_PIN] == '1234'
|
2018-11-26 13:10:18 +00:00
|
|
|
|
|
|
|
|
2019-03-12 14:54:04 +00:00
|
|
|
async def test_enabling_webhook(hass, hass_ws_client, setup_api,
|
|
|
|
mock_cloud_login):
|
2018-11-26 13:10:18 +00:00
|
|
|
"""Test we call right code to enable webhooks."""
|
|
|
|
client = await hass_ws_client(hass)
|
2019-03-11 19:21:20 +00:00
|
|
|
with patch(
|
|
|
|
'hass_nabucasa.cloudhooks.Cloudhooks.async_create',
|
|
|
|
return_value=mock_coro()
|
|
|
|
) as mock_enable:
|
2018-11-26 13:10:18 +00:00
|
|
|
await client.send_json({
|
|
|
|
'id': 5,
|
|
|
|
'type': 'cloud/cloudhook/create',
|
|
|
|
'webhook_id': 'mock-webhook-id',
|
|
|
|
})
|
|
|
|
response = await client.receive_json()
|
|
|
|
assert response['success']
|
|
|
|
|
|
|
|
assert len(mock_enable.mock_calls) == 1
|
|
|
|
assert mock_enable.mock_calls[0][1][0] == 'mock-webhook-id'
|
|
|
|
|
|
|
|
|
2019-03-12 14:54:04 +00:00
|
|
|
async def test_disabling_webhook(hass, hass_ws_client, setup_api,
|
|
|
|
mock_cloud_login):
|
2018-11-26 13:10:18 +00:00
|
|
|
"""Test we call right code to disable webhooks."""
|
|
|
|
client = await hass_ws_client(hass)
|
2019-03-11 19:21:20 +00:00
|
|
|
with patch(
|
|
|
|
'hass_nabucasa.cloudhooks.Cloudhooks.async_delete',
|
|
|
|
return_value=mock_coro()
|
|
|
|
) as mock_disable:
|
2018-11-26 13:10:18 +00:00
|
|
|
await client.send_json({
|
|
|
|
'id': 5,
|
|
|
|
'type': 'cloud/cloudhook/delete',
|
|
|
|
'webhook_id': 'mock-webhook-id',
|
|
|
|
})
|
|
|
|
response = await client.receive_json()
|
|
|
|
assert response['success']
|
|
|
|
|
|
|
|
assert len(mock_disable.mock_calls) == 1
|
|
|
|
assert mock_disable.mock_calls[0][1][0] == 'mock-webhook-id'
|
2019-03-12 14:54:04 +00:00
|
|
|
|
|
|
|
|
|
|
|
async def test_enabling_remote(hass, hass_ws_client, setup_api,
|
|
|
|
mock_cloud_login):
|
|
|
|
"""Test we call right code to enable remote UI."""
|
|
|
|
client = await hass_ws_client(hass)
|
|
|
|
cloud = hass.data[DOMAIN]
|
|
|
|
|
|
|
|
with patch(
|
|
|
|
'hass_nabucasa.remote.RemoteUI.connect',
|
|
|
|
return_value=mock_coro()
|
|
|
|
) as mock_connect:
|
|
|
|
await client.send_json({
|
|
|
|
'id': 5,
|
|
|
|
'type': 'cloud/remote/connect',
|
|
|
|
})
|
|
|
|
response = await client.receive_json()
|
|
|
|
assert response['success']
|
|
|
|
assert cloud.client.remote_autostart
|
|
|
|
|
|
|
|
assert len(mock_connect.mock_calls) == 1
|
|
|
|
|
|
|
|
|
|
|
|
async def test_disabling_remote(hass, hass_ws_client, setup_api,
|
|
|
|
mock_cloud_login):
|
|
|
|
"""Test we call right code to disable remote UI."""
|
|
|
|
client = await hass_ws_client(hass)
|
|
|
|
cloud = hass.data[DOMAIN]
|
|
|
|
|
|
|
|
with patch(
|
|
|
|
'hass_nabucasa.remote.RemoteUI.disconnect',
|
|
|
|
return_value=mock_coro()
|
|
|
|
) as mock_disconnect:
|
|
|
|
await client.send_json({
|
|
|
|
'id': 5,
|
|
|
|
'type': 'cloud/remote/disconnect',
|
|
|
|
})
|
|
|
|
response = await client.receive_json()
|
|
|
|
assert response['success']
|
|
|
|
assert not cloud.client.remote_autostart
|
|
|
|
|
|
|
|
assert len(mock_disconnect.mock_calls) == 1
|
2019-03-16 02:26:10 +00:00
|
|
|
|
|
|
|
|
|
|
|
async def test_enabling_remote_trusted_networks_local4(
|
|
|
|
hass, hass_ws_client, setup_api, mock_cloud_login):
|
|
|
|
"""Test we cannot enable remote UI when trusted networks active."""
|
|
|
|
hass.auth._providers[('trusted_networks', None)] = \
|
|
|
|
tn_auth.TrustedNetworksAuthProvider(
|
|
|
|
hass, None, tn_auth.CONFIG_SCHEMA({
|
|
|
|
'type': 'trusted_networks',
|
|
|
|
'trusted_networks': [
|
|
|
|
'127.0.0.1'
|
|
|
|
]
|
|
|
|
})
|
|
|
|
)
|
|
|
|
|
|
|
|
client = await hass_ws_client(hass)
|
|
|
|
|
|
|
|
with patch(
|
|
|
|
'hass_nabucasa.remote.RemoteUI.connect',
|
|
|
|
side_effect=AssertionError
|
|
|
|
) as mock_connect:
|
|
|
|
await client.send_json({
|
|
|
|
'id': 5,
|
|
|
|
'type': 'cloud/remote/connect',
|
|
|
|
})
|
|
|
|
response = await client.receive_json()
|
|
|
|
|
|
|
|
assert not response['success']
|
|
|
|
assert response['error']['code'] == 500
|
|
|
|
assert response['error']['message'] == \
|
|
|
|
'Remote UI not compatible with 127.0.0.1/::1 as a trusted network.'
|
|
|
|
|
|
|
|
assert len(mock_connect.mock_calls) == 0
|
|
|
|
|
|
|
|
|
|
|
|
async def test_enabling_remote_trusted_networks_local6(
|
|
|
|
hass, hass_ws_client, setup_api, mock_cloud_login):
|
|
|
|
"""Test we cannot enable remote UI when trusted networks active."""
|
|
|
|
hass.auth._providers[('trusted_networks', None)] = \
|
|
|
|
tn_auth.TrustedNetworksAuthProvider(
|
|
|
|
hass, None, tn_auth.CONFIG_SCHEMA({
|
|
|
|
'type': 'trusted_networks',
|
|
|
|
'trusted_networks': [
|
|
|
|
'::1'
|
|
|
|
]
|
|
|
|
})
|
|
|
|
)
|
|
|
|
|
|
|
|
client = await hass_ws_client(hass)
|
|
|
|
|
|
|
|
with patch(
|
|
|
|
'hass_nabucasa.remote.RemoteUI.connect',
|
|
|
|
side_effect=AssertionError
|
|
|
|
) as mock_connect:
|
|
|
|
await client.send_json({
|
|
|
|
'id': 5,
|
|
|
|
'type': 'cloud/remote/connect',
|
|
|
|
})
|
|
|
|
response = await client.receive_json()
|
|
|
|
|
|
|
|
assert not response['success']
|
|
|
|
assert response['error']['code'] == 500
|
|
|
|
assert response['error']['message'] == \
|
|
|
|
'Remote UI not compatible with 127.0.0.1/::1 as a trusted network.'
|
|
|
|
|
|
|
|
assert len(mock_connect.mock_calls) == 0
|
|
|
|
|
|
|
|
|
|
|
|
async def test_enabling_remote_trusted_networks_other(
|
|
|
|
hass, hass_ws_client, setup_api, mock_cloud_login):
|
2019-06-08 06:08:55 +00:00
|
|
|
"""Test we can enable remote UI when trusted networks active."""
|
2019-03-16 02:26:10 +00:00
|
|
|
hass.auth._providers[('trusted_networks', None)] = \
|
|
|
|
tn_auth.TrustedNetworksAuthProvider(
|
|
|
|
hass, None, tn_auth.CONFIG_SCHEMA({
|
|
|
|
'type': 'trusted_networks',
|
|
|
|
'trusted_networks': [
|
|
|
|
'192.168.0.0/24'
|
|
|
|
]
|
|
|
|
})
|
|
|
|
)
|
|
|
|
|
|
|
|
client = await hass_ws_client(hass)
|
|
|
|
cloud = hass.data[DOMAIN]
|
|
|
|
|
|
|
|
with patch(
|
|
|
|
'hass_nabucasa.remote.RemoteUI.connect',
|
|
|
|
return_value=mock_coro()
|
|
|
|
) as mock_connect:
|
|
|
|
await client.send_json({
|
|
|
|
'id': 5,
|
|
|
|
'type': 'cloud/remote/connect',
|
|
|
|
})
|
|
|
|
response = await client.receive_json()
|
|
|
|
|
|
|
|
assert response['success']
|
|
|
|
assert cloud.client.remote_autostart
|
|
|
|
|
|
|
|
assert len(mock_connect.mock_calls) == 1
|
2019-05-29 15:39:12 +00:00
|
|
|
|
|
|
|
|
|
|
|
async def test_list_google_entities(
|
|
|
|
hass, hass_ws_client, setup_api, mock_cloud_login):
|
|
|
|
"""Test that we can list Google entities."""
|
|
|
|
client = await hass_ws_client(hass)
|
2019-06-21 09:17:21 +00:00
|
|
|
entity = GoogleEntity(
|
|
|
|
hass, MockConfig(should_expose=lambda *_: False), State(
|
|
|
|
'light.kitchen', 'on'
|
|
|
|
))
|
2019-05-29 15:39:12 +00:00
|
|
|
with patch('homeassistant.components.google_assistant.helpers'
|
|
|
|
'.async_get_entities', return_value=[entity]):
|
|
|
|
await client.send_json({
|
|
|
|
'id': 5,
|
|
|
|
'type': 'cloud/google_assistant/entities',
|
|
|
|
})
|
|
|
|
response = await client.receive_json()
|
|
|
|
|
|
|
|
assert response['success']
|
|
|
|
assert len(response['result']) == 1
|
|
|
|
assert response['result'][0] == {
|
|
|
|
'entity_id': 'light.kitchen',
|
|
|
|
'might_2fa': False,
|
|
|
|
'traits': ['action.devices.traits.OnOff'],
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async def test_update_google_entity(
|
|
|
|
hass, hass_ws_client, setup_api, mock_cloud_login):
|
|
|
|
"""Test that we can update config of a Google entity."""
|
|
|
|
client = await hass_ws_client(hass)
|
|
|
|
await client.send_json({
|
|
|
|
'id': 5,
|
|
|
|
'type': 'cloud/google_assistant/entities/update',
|
|
|
|
'entity_id': 'light.kitchen',
|
|
|
|
'should_expose': False,
|
|
|
|
'override_name': 'updated name',
|
|
|
|
'aliases': ['lefty', 'righty'],
|
|
|
|
'disable_2fa': False,
|
|
|
|
})
|
|
|
|
response = await client.receive_json()
|
|
|
|
|
|
|
|
assert response['success']
|
|
|
|
prefs = hass.data[DOMAIN].client.prefs
|
|
|
|
assert prefs.google_entity_configs['light.kitchen'] == {
|
|
|
|
'should_expose': False,
|
|
|
|
'override_name': 'updated name',
|
|
|
|
'aliases': ['lefty', 'righty'],
|
|
|
|
'disable_2fa': False,
|
|
|
|
}
|
2019-06-08 06:08:55 +00:00
|
|
|
|
|
|
|
|
|
|
|
async def test_enabling_remote_trusted_proxies_local4(
|
|
|
|
hass, hass_ws_client, setup_api, mock_cloud_login):
|
|
|
|
"""Test we cannot enable remote UI when trusted networks active."""
|
|
|
|
hass.http.trusted_proxies.append(ip_network('127.0.0.1'))
|
|
|
|
|
|
|
|
client = await hass_ws_client(hass)
|
|
|
|
|
|
|
|
with patch(
|
|
|
|
'hass_nabucasa.remote.RemoteUI.connect',
|
|
|
|
side_effect=AssertionError
|
|
|
|
) as mock_connect:
|
|
|
|
await client.send_json({
|
|
|
|
'id': 5,
|
|
|
|
'type': 'cloud/remote/connect',
|
|
|
|
})
|
|
|
|
response = await client.receive_json()
|
|
|
|
|
|
|
|
assert not response['success']
|
|
|
|
assert response['error']['code'] == 500
|
|
|
|
assert response['error']['message'] == \
|
|
|
|
'Remote UI not compatible with 127.0.0.1/::1 as trusted proxies.'
|
|
|
|
|
|
|
|
assert len(mock_connect.mock_calls) == 0
|
|
|
|
|
|
|
|
|
|
|
|
async def test_enabling_remote_trusted_proxies_local6(
|
|
|
|
hass, hass_ws_client, setup_api, mock_cloud_login):
|
|
|
|
"""Test we cannot enable remote UI when trusted networks active."""
|
|
|
|
hass.http.trusted_proxies.append(ip_network('::1'))
|
|
|
|
|
|
|
|
client = await hass_ws_client(hass)
|
|
|
|
|
|
|
|
with patch(
|
|
|
|
'hass_nabucasa.remote.RemoteUI.connect',
|
|
|
|
side_effect=AssertionError
|
|
|
|
) as mock_connect:
|
|
|
|
await client.send_json({
|
|
|
|
'id': 5,
|
|
|
|
'type': 'cloud/remote/connect',
|
|
|
|
})
|
|
|
|
response = await client.receive_json()
|
|
|
|
|
|
|
|
assert not response['success']
|
|
|
|
assert response['error']['code'] == 500
|
|
|
|
assert response['error']['message'] == \
|
|
|
|
'Remote UI not compatible with 127.0.0.1/::1 as trusted proxies.'
|
|
|
|
|
|
|
|
assert len(mock_connect.mock_calls) == 0
|
2019-06-13 18:58:08 +00:00
|
|
|
|
|
|
|
|
|
|
|
async def test_list_alexa_entities(
|
|
|
|
hass, hass_ws_client, setup_api, mock_cloud_login):
|
|
|
|
"""Test that we can list Alexa entities."""
|
|
|
|
client = await hass_ws_client(hass)
|
|
|
|
entity = LightCapabilities(hass, MagicMock(entity_config={}), State(
|
|
|
|
'light.kitchen', 'on'
|
|
|
|
))
|
|
|
|
with patch('homeassistant.components.alexa.entities'
|
|
|
|
'.async_get_entities', return_value=[entity]):
|
|
|
|
await client.send_json({
|
|
|
|
'id': 5,
|
|
|
|
'type': 'cloud/alexa/entities',
|
|
|
|
})
|
|
|
|
response = await client.receive_json()
|
|
|
|
|
|
|
|
assert response['success']
|
|
|
|
assert len(response['result']) == 1
|
|
|
|
assert response['result'][0] == {
|
|
|
|
'entity_id': 'light.kitchen',
|
|
|
|
'display_categories': ['LIGHT'],
|
|
|
|
'interfaces': ['Alexa.PowerController', 'Alexa.EndpointHealth'],
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async def test_update_alexa_entity(
|
|
|
|
hass, hass_ws_client, setup_api, mock_cloud_login):
|
|
|
|
"""Test that we can update config of an Alexa entity."""
|
|
|
|
client = await hass_ws_client(hass)
|
|
|
|
await client.send_json({
|
|
|
|
'id': 5,
|
|
|
|
'type': 'cloud/alexa/entities/update',
|
|
|
|
'entity_id': 'light.kitchen',
|
|
|
|
'should_expose': False,
|
|
|
|
})
|
|
|
|
response = await client.receive_json()
|
|
|
|
|
|
|
|
assert response['success']
|
|
|
|
prefs = hass.data[DOMAIN].client.prefs
|
|
|
|
assert prefs.alexa_entity_configs['light.kitchen'] == {
|
|
|
|
'should_expose': False,
|
|
|
|
}
|
2019-06-25 05:04:31 +00:00
|
|
|
|
|
|
|
|
|
|
|
async def test_sync_alexa_entities_timeout(
|
|
|
|
hass, hass_ws_client, setup_api, mock_cloud_login):
|
|
|
|
"""Test that timeout syncing Alexa entities."""
|
|
|
|
client = await hass_ws_client(hass)
|
|
|
|
with patch('homeassistant.components.cloud.alexa_config.AlexaConfig'
|
|
|
|
'.async_sync_entities', side_effect=asyncio.TimeoutError):
|
|
|
|
await client.send_json({
|
|
|
|
'id': 5,
|
|
|
|
'type': 'cloud/alexa/sync',
|
|
|
|
})
|
|
|
|
response = await client.receive_json()
|
|
|
|
|
|
|
|
assert not response['success']
|
|
|
|
assert response['error']['code'] == 'timeout'
|
|
|
|
|
|
|
|
|
|
|
|
async def test_sync_alexa_entities_no_token(
|
|
|
|
hass, hass_ws_client, setup_api, mock_cloud_login):
|
|
|
|
"""Test sync Alexa entities when we have no token."""
|
|
|
|
client = await hass_ws_client(hass)
|
|
|
|
with patch('homeassistant.components.cloud.alexa_config.AlexaConfig'
|
|
|
|
'.async_sync_entities',
|
|
|
|
side_effect=alexa_errors.NoTokenAvailable):
|
|
|
|
await client.send_json({
|
|
|
|
'id': 5,
|
|
|
|
'type': 'cloud/alexa/sync',
|
|
|
|
})
|
|
|
|
response = await client.receive_json()
|
|
|
|
|
|
|
|
assert not response['success']
|
|
|
|
assert response['error']['code'] == 'alexa_relink'
|
|
|
|
|
|
|
|
|
|
|
|
async def test_enable_alexa_state_report_fail(
|
|
|
|
hass, hass_ws_client, setup_api, mock_cloud_login):
|
|
|
|
"""Test enable Alexa entities state reporting when no token available."""
|
|
|
|
client = await hass_ws_client(hass)
|
|
|
|
with patch('homeassistant.components.cloud.alexa_config.AlexaConfig'
|
|
|
|
'.async_sync_entities',
|
|
|
|
side_effect=alexa_errors.NoTokenAvailable):
|
|
|
|
await client.send_json({
|
|
|
|
'id': 5,
|
|
|
|
'type': 'cloud/alexa/sync',
|
|
|
|
})
|
|
|
|
response = await client.receive_json()
|
|
|
|
|
|
|
|
assert not response['success']
|
|
|
|
assert response['error']['code'] == 'alexa_relink'
|