mirror of
https://github.com/home-assistant/core.git
synced 2025-08-22 03:40:02 +00:00
.github
docs
homeassistant
script
tests
components
alarm_control_panel
alexa
automation
binary_sensor
calendar
camera
climate
cloud
__init__.py
test_auth_api.py
test_http_api.py
test_init.py
test_iot.py
config
counter
cover
deconz
device_tracker
emulated_hue
fan
google_assistant
group
hassio
homekit
http
hue
image_processing
light
lock
mailbox
media_player
mqtt
notify
persistent_notification
recorder
remote
scene
sensor
switch
timer
tts
vacuum
weather
zone
zwave
__init__.py
test_alert.py
test_api.py
test_canary.py
test_configurator.py
test_conversation.py
test_datadog.py
test_demo.py
test_device_sun_light_trigger.py
test_dialogflow.py
test_discovery.py
test_duckdns.py
test_dyson.py
test_ffmpeg.py
test_folder_watcher.py
test_freedns.py
test_frontend.py
test_google.py
test_google_domains.py
test_graphite.py
test_history.py
test_history_graph.py
test_influxdb.py
test_init.py
test_input_boolean.py
test_input_datetime.py
test_input_number.py
test_input_select.py
test_input_text.py
test_intent_script.py
test_introduction.py
test_kira.py
test_litejet.py
test_logbook.py
test_logentries.py
test_logger.py
test_melissa.py
test_microsoft_face.py
test_mqtt_eventstream.py
test_mqtt_statestream.py
test_namecheapdns.py
test_no_ip.py
test_nuheat.py
test_panel_custom.py
test_panel_iframe.py
test_pilight.py
test_plant.py
test_prometheus.py
test_proximity.py
test_python_script.py
test_qwikswitch.py
test_remember_the_milk.py
test_rest_command.py
test_rflink.py
test_rfxtrx.py
test_ring.py
test_rss_feed_template.py
test_script.py
test_shell_command.py
test_shopping_list.py
test_sleepiq.py
test_snips.py
test_spc.py
test_splunk.py
test_statsd.py
test_sun.py
test_system_log.py
test_updater.py
test_upnp.py
test_vultr.py
test_wake_on_lan.py
test_weblink.py
test_websocket_api.py
fixtures
helpers
mock
resources
scripts
test_util
testing_config
util
__init__.py
common.py
conftest.py
test_bootstrap.py
test_config.py
test_config_entries.py
test_core.py
test_data_entry_flow.py
test_loader.py
test_main.py
test_remote.py
test_requirements.py
test_setup.py
virtualization
.coveragerc
.dockerignore
.gitattributes
.gitignore
.hound.yml
.ignore
.travis.yml
CLA.md
CODEOWNERS
CODE_OF_CONDUCT.md
CONTRIBUTING.md
Dockerfile
LICENSE.md
MANIFEST.in
README.rst
pylintrc
requirements_all.txt
requirements_docs.txt
requirements_test.txt
requirements_test_all.txt
setup.cfg
setup.py
tox.ini
333 lines
11 KiB
Python
333 lines
11 KiB
Python
"""Tests for the HTTP API for the cloud component."""
|
|
import asyncio
|
|
from unittest.mock import patch, MagicMock
|
|
|
|
import pytest
|
|
from jose import jwt
|
|
|
|
from homeassistant.bootstrap import async_setup_component
|
|
from homeassistant.components.cloud import DOMAIN, auth_api, iot
|
|
|
|
from tests.common import mock_coro
|
|
|
|
|
|
GOOGLE_ACTIONS_SYNC_URL = 'https://api-test.hass.io/google_actions_sync'
|
|
|
|
|
|
@pytest.fixture
|
|
def cloud_client(hass, aiohttp_client):
|
|
"""Fixture that can fetch from the cloud client."""
|
|
with patch('homeassistant.components.cloud.Cloud.async_start',
|
|
return_value=mock_coro()):
|
|
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',
|
|
'google_actions_sync_url': GOOGLE_ACTIONS_SYNC_URL,
|
|
}
|
|
}))
|
|
hass.data['cloud']._decode_claims = \
|
|
lambda token: jwt.get_unverified_claims(token)
|
|
with patch('homeassistant.components.cloud.Cloud.write_user_info'):
|
|
yield hass.loop.run_until_complete(aiohttp_client(hass.http.app))
|
|
|
|
|
|
@pytest.fixture
|
|
def mock_cognito():
|
|
"""Mock warrant."""
|
|
with patch('homeassistant.components.cloud.auth_api._cognito') as mock_cog:
|
|
yield mock_cog()
|
|
|
|
|
|
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
|
|
|
|
|
|
@asyncio.coroutine
|
|
def test_account_view_no_account(cloud_client):
|
|
"""Test fetching account if no account available."""
|
|
req = yield from cloud_client.get('/api/cloud/account')
|
|
assert req.status == 400
|
|
|
|
|
|
@asyncio.coroutine
|
|
def test_account_view(hass, cloud_client):
|
|
"""Test fetching account if no account available."""
|
|
hass.data[DOMAIN].id_token = jwt.encode({
|
|
'email': 'hello@home-assistant.io',
|
|
'custom:sub-exp': '2018-01-03'
|
|
}, 'test')
|
|
hass.data[DOMAIN].iot.state = iot.STATE_CONNECTED
|
|
req = yield from cloud_client.get('/api/cloud/account')
|
|
assert req.status == 200
|
|
result = yield from req.json()
|
|
assert result == {
|
|
'email': 'hello@home-assistant.io',
|
|
'sub_exp': '2018-01-03',
|
|
'cloud': iot.STATE_CONNECTED,
|
|
}
|
|
|
|
|
|
@asyncio.coroutine
|
|
def test_login_view(hass, cloud_client, mock_cognito):
|
|
"""Test logging in."""
|
|
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'
|
|
|
|
with patch('homeassistant.components.cloud.iot.CloudIoT.'
|
|
'connect') as mock_connect, \
|
|
patch('homeassistant.components.cloud.auth_api._authenticate',
|
|
return_value=mock_cognito) as mock_auth:
|
|
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 result['sub_exp'] == '2018-01-03'
|
|
|
|
assert len(mock_connect.mock_calls) == 1
|
|
|
|
assert len(mock_auth.mock_calls) == 1
|
|
cloud, result_user, result_pass = mock_auth.mock_calls[0][1]
|
|
assert result_user == 'my_username'
|
|
assert result_pass == 'my_password'
|
|
|
|
|
|
@asyncio.coroutine
|
|
def test_login_view_invalid_json(cloud_client):
|
|
"""Try logging in with invalid 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_login.mock_calls) == 0
|
|
|
|
|
|
@asyncio.coroutine
|
|
def test_login_view_invalid_schema(cloud_client):
|
|
"""Try logging in with 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_login.mock_calls) == 0
|
|
|
|
|
|
@asyncio.coroutine
|
|
def test_login_view_request_timeout(cloud_client):
|
|
"""Test request timeout while trying to log in."""
|
|
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(cloud_client):
|
|
"""Test logging in with invalid credentials."""
|
|
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(cloud_client):
|
|
"""Test unknown error while logging in."""
|
|
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(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(cloud.logout.mock_calls) == 1
|
|
|
|
|
|
@asyncio.coroutine
|
|
def test_logout_view_request_timeout(hass, cloud_client):
|
|
"""Test timeout while logging out."""
|
|
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(hass, cloud_client):
|
|
"""Test unknown error while logging out."""
|
|
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
|
|
|
|
|
|
@asyncio.coroutine
|
|
def test_register_view(mock_cognito, cloud_client):
|
|
"""Test logging out."""
|
|
req = yield from cloud_client.post('/api/cloud/register', json={
|
|
'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]
|
|
assert result_email == 'hello@bla.com'
|
|
assert result_pass == 'falcon42'
|
|
|
|
|
|
@asyncio.coroutine
|
|
def test_register_view_bad_data(mock_cognito, cloud_client):
|
|
"""Test logging out."""
|
|
req = yield from cloud_client.post('/api/cloud/register', json={
|
|
'email': 'hello@bla.com',
|
|
'not_password': 'falcon'
|
|
})
|
|
assert req.status == 400
|
|
assert len(mock_cognito.logout.mock_calls) == 0
|
|
|
|
|
|
@asyncio.coroutine
|
|
def test_register_view_request_timeout(mock_cognito, cloud_client):
|
|
"""Test timeout while logging out."""
|
|
mock_cognito.register.side_effect = asyncio.TimeoutError
|
|
req = yield from cloud_client.post('/api/cloud/register', json={
|
|
'email': 'hello@bla.com',
|
|
'password': 'falcon42'
|
|
})
|
|
assert req.status == 502
|
|
|
|
|
|
@asyncio.coroutine
|
|
def test_register_view_unknown_error(mock_cognito, cloud_client):
|
|
"""Test unknown error while logging out."""
|
|
mock_cognito.register.side_effect = auth_api.UnknownError
|
|
req = yield from cloud_client.post('/api/cloud/register', json={
|
|
'email': 'hello@bla.com',
|
|
'password': 'falcon42'
|
|
})
|
|
assert req.status == 502
|
|
|
|
|
|
@asyncio.coroutine
|
|
def test_forgot_password_view(mock_cognito, cloud_client):
|
|
"""Test logging out."""
|
|
req = yield from cloud_client.post('/api/cloud/forgot_password', json={
|
|
'email': 'hello@bla.com',
|
|
})
|
|
assert req.status == 200
|
|
assert len(mock_cognito.initiate_forgot_password.mock_calls) == 1
|
|
|
|
|
|
@asyncio.coroutine
|
|
def test_forgot_password_view_bad_data(mock_cognito, cloud_client):
|
|
"""Test logging out."""
|
|
req = yield from cloud_client.post('/api/cloud/forgot_password', json={
|
|
'not_email': 'hello@bla.com',
|
|
})
|
|
assert req.status == 400
|
|
assert len(mock_cognito.initiate_forgot_password.mock_calls) == 0
|
|
|
|
|
|
@asyncio.coroutine
|
|
def test_forgot_password_view_request_timeout(mock_cognito, cloud_client):
|
|
"""Test timeout while logging out."""
|
|
mock_cognito.initiate_forgot_password.side_effect = asyncio.TimeoutError
|
|
req = yield from cloud_client.post('/api/cloud/forgot_password', json={
|
|
'email': 'hello@bla.com',
|
|
})
|
|
assert req.status == 502
|
|
|
|
|
|
@asyncio.coroutine
|
|
def test_forgot_password_view_unknown_error(mock_cognito, cloud_client):
|
|
"""Test unknown error while logging out."""
|
|
mock_cognito.initiate_forgot_password.side_effect = auth_api.UnknownError
|
|
req = yield from cloud_client.post('/api/cloud/forgot_password', json={
|
|
'email': 'hello@bla.com',
|
|
})
|
|
assert req.status == 502
|
|
|
|
|
|
@asyncio.coroutine
|
|
def test_resend_confirm_view(mock_cognito, cloud_client):
|
|
"""Test logging out."""
|
|
req = yield from cloud_client.post('/api/cloud/resend_confirm', json={
|
|
'email': 'hello@bla.com',
|
|
})
|
|
assert req.status == 200
|
|
assert len(mock_cognito.client.resend_confirmation_code.mock_calls) == 1
|
|
|
|
|
|
@asyncio.coroutine
|
|
def test_resend_confirm_view_bad_data(mock_cognito, cloud_client):
|
|
"""Test logging out."""
|
|
req = yield from cloud_client.post('/api/cloud/resend_confirm', json={
|
|
'not_email': 'hello@bla.com',
|
|
})
|
|
assert req.status == 400
|
|
assert len(mock_cognito.client.resend_confirmation_code.mock_calls) == 0
|
|
|
|
|
|
@asyncio.coroutine
|
|
def test_resend_confirm_view_request_timeout(mock_cognito, cloud_client):
|
|
"""Test timeout while logging out."""
|
|
mock_cognito.client.resend_confirmation_code.side_effect = \
|
|
asyncio.TimeoutError
|
|
req = yield from cloud_client.post('/api/cloud/resend_confirm', json={
|
|
'email': 'hello@bla.com',
|
|
})
|
|
assert req.status == 502
|
|
|
|
|
|
@asyncio.coroutine
|
|
def test_resend_confirm_view_unknown_error(mock_cognito, cloud_client):
|
|
"""Test unknown error while logging out."""
|
|
mock_cognito.client.resend_confirmation_code.side_effect = \
|
|
auth_api.UnknownError
|
|
req = yield from cloud_client.post('/api/cloud/resend_confirm', json={
|
|
'email': 'hello@bla.com',
|
|
})
|
|
assert req.status == 502
|