1
0
mirror of https://github.com/home-assistant/core.git synced 2025-12-24 12:59:34 +00:00

Cloud connection via aiohttp (#9860)

* Cloud: connect to cloud

* Fix tests in py34

* Update warrant to 0.5.0

* Differentiate errors between unknown handler vs exception

* Lint

* Respond to cloud message to logout

* Refresh token exception handling

* Swap out bare exception for RuntimeError

* Add more tests

* Fix tests py34
This commit is contained in:
Paulus Schoutsen
2017-10-14 19:43:14 -07:00
committed by GitHub
parent 26cb67dec2
commit 0362a76cd6
12 changed files with 930 additions and 429 deletions

View File

@@ -7,25 +7,25 @@ import pytest
from homeassistant.bootstrap import async_setup_component
from homeassistant.components.cloud import DOMAIN, auth_api
from tests.common import mock_coro
@pytest.fixture
def cloud_client(hass, test_client):
"""Fixture that can fetch from the cloud client."""
hass.loop.run_until_complete(async_setup_component(hass, 'cloud', {
'cloud': {
'mode': 'development'
}
}))
with patch('homeassistant.components.cloud.Cloud.initialize'):
hass.loop.run_until_complete(async_setup_component(hass, 'cloud', {
'cloud': {
'mode': 'development',
'cognito_client_id': 'cognito_client_id',
'user_pool_id': 'user_pool_id',
'region': 'region',
'relayer': 'relayer',
}
}))
return hass.loop.run_until_complete(test_client(hass.http.app))
@pytest.fixture
def mock_auth(cloud_client, hass):
"""Fixture to mock authentication."""
auth = hass.data[DOMAIN]['auth'] = MagicMock()
return auth
@pytest.fixture
def mock_cognito():
"""Mock warrant."""
@@ -41,9 +41,9 @@ def test_account_view_no_account(cloud_client):
@asyncio.coroutine
def test_account_view(mock_auth, cloud_client):
def test_account_view(hass, cloud_client):
"""Test fetching account if no account available."""
mock_auth.account = MagicMock(email='hello@home-assistant.io')
hass.data[DOMAIN].email = 'hello@home-assistant.io'
req = yield from cloud_client.get('/api/cloud/account')
assert req.status == 200
result = yield from req.json()
@@ -51,99 +51,112 @@ def test_account_view(mock_auth, cloud_client):
@asyncio.coroutine
def test_login_view(mock_auth, cloud_client):
def test_login_view(hass, cloud_client):
"""Test logging in."""
mock_auth.account = MagicMock(email='hello@home-assistant.io')
req = yield from cloud_client.post('/api/cloud/login', json={
'email': 'my_username',
'password': 'my_password'
})
hass.data[DOMAIN].email = 'hello@home-assistant.io'
with patch('homeassistant.components.cloud.iot.CloudIoT.connect'), \
patch('homeassistant.components.cloud.'
'auth_api.login') as mock_login:
req = yield from cloud_client.post('/api/cloud/login', json={
'email': 'my_username',
'password': 'my_password'
})
assert req.status == 200
result = yield from req.json()
assert result == {'email': 'hello@home-assistant.io'}
assert len(mock_auth.login.mock_calls) == 1
result_user, result_pass = mock_auth.login.mock_calls[0][1]
assert len(mock_login.mock_calls) == 1
cloud, result_user, result_pass = mock_login.mock_calls[0][1]
assert result_user == 'my_username'
assert result_pass == 'my_password'
@asyncio.coroutine
def test_login_view_invalid_json(mock_auth, cloud_client):
def test_login_view_invalid_json(cloud_client):
"""Try logging in with invalid JSON."""
req = yield from cloud_client.post('/api/cloud/login', data='Not JSON')
with patch('homeassistant.components.cloud.auth_api.login') as mock_login:
req = yield from cloud_client.post('/api/cloud/login', data='Not JSON')
assert req.status == 400
assert len(mock_auth.mock_calls) == 0
assert len(mock_login.mock_calls) == 0
@asyncio.coroutine
def test_login_view_invalid_schema(mock_auth, cloud_client):
def test_login_view_invalid_schema(cloud_client):
"""Try logging in with invalid schema."""
req = yield from cloud_client.post('/api/cloud/login', json={
'invalid': 'schema'
})
with patch('homeassistant.components.cloud.auth_api.login') as mock_login:
req = yield from cloud_client.post('/api/cloud/login', json={
'invalid': 'schema'
})
assert req.status == 400
assert len(mock_auth.mock_calls) == 0
assert len(mock_login.mock_calls) == 0
@asyncio.coroutine
def test_login_view_request_timeout(mock_auth, cloud_client):
def test_login_view_request_timeout(cloud_client):
"""Test request timeout while trying to log in."""
mock_auth.login.side_effect = asyncio.TimeoutError
req = yield from cloud_client.post('/api/cloud/login', json={
'email': 'my_username',
'password': 'my_password'
})
with patch('homeassistant.components.cloud.auth_api.login',
side_effect=asyncio.TimeoutError):
req = yield from cloud_client.post('/api/cloud/login', json={
'email': 'my_username',
'password': 'my_password'
})
assert req.status == 502
@asyncio.coroutine
def test_login_view_invalid_credentials(mock_auth, cloud_client):
def test_login_view_invalid_credentials(cloud_client):
"""Test logging in with invalid credentials."""
mock_auth.login.side_effect = auth_api.Unauthenticated
req = yield from cloud_client.post('/api/cloud/login', json={
'email': 'my_username',
'password': 'my_password'
})
with patch('homeassistant.components.cloud.auth_api.login',
side_effect=auth_api.Unauthenticated):
req = yield from cloud_client.post('/api/cloud/login', json={
'email': 'my_username',
'password': 'my_password'
})
assert req.status == 401
@asyncio.coroutine
def test_login_view_unknown_error(mock_auth, cloud_client):
def test_login_view_unknown_error(cloud_client):
"""Test unknown error while logging in."""
mock_auth.login.side_effect = auth_api.UnknownError
req = yield from cloud_client.post('/api/cloud/login', json={
'email': 'my_username',
'password': 'my_password'
})
with patch('homeassistant.components.cloud.auth_api.login',
side_effect=auth_api.UnknownError):
req = yield from cloud_client.post('/api/cloud/login', json={
'email': 'my_username',
'password': 'my_password'
})
assert req.status == 502
@asyncio.coroutine
def test_logout_view(mock_auth, cloud_client):
def test_logout_view(hass, cloud_client):
"""Test logging out."""
cloud = hass.data['cloud'] = MagicMock()
cloud.logout.return_value = mock_coro()
req = yield from cloud_client.post('/api/cloud/logout')
assert req.status == 200
data = yield from req.json()
assert data == {'message': 'ok'}
assert len(mock_auth.logout.mock_calls) == 1
assert len(cloud.logout.mock_calls) == 1
@asyncio.coroutine
def test_logout_view_request_timeout(mock_auth, cloud_client):
def test_logout_view_request_timeout(hass, cloud_client):
"""Test timeout while logging out."""
mock_auth.logout.side_effect = asyncio.TimeoutError
cloud = hass.data['cloud'] = MagicMock()
cloud.logout.side_effect = asyncio.TimeoutError
req = yield from cloud_client.post('/api/cloud/logout')
assert req.status == 502
@asyncio.coroutine
def test_logout_view_unknown_error(mock_auth, cloud_client):
def test_logout_view_unknown_error(hass, cloud_client):
"""Test unknown error while logging out."""
mock_auth.logout.side_effect = auth_api.UnknownError
cloud = hass.data['cloud'] = MagicMock()
cloud.logout.side_effect = auth_api.UnknownError
req = yield from cloud_client.post('/api/cloud/logout')
assert req.status == 502
@@ -158,7 +171,7 @@ def test_register_view(mock_cognito, cloud_client):
assert req.status == 200
assert len(mock_cognito.register.mock_calls) == 1
result_email, result_pass = mock_cognito.register.mock_calls[0][1]
assert result_email == 'hello@bla.com'
assert result_email == auth_api._generate_username('hello@bla.com')
assert result_pass == 'falcon42'
@@ -205,7 +218,7 @@ def test_confirm_register_view(mock_cognito, cloud_client):
assert req.status == 200
assert len(mock_cognito.confirm_sign_up.mock_calls) == 1
result_code, result_email = mock_cognito.confirm_sign_up.mock_calls[0][1]
assert result_email == 'hello@bla.com'
assert result_email == auth_api._generate_username('hello@bla.com')
assert result_code == '123456'