2018-07-17 08:49:15 +00:00
|
|
|
"""Test the onboarding views."""
|
|
|
|
import asyncio
|
|
|
|
from unittest.mock import patch
|
|
|
|
|
|
|
|
import pytest
|
|
|
|
|
|
|
|
from homeassistant.setup import async_setup_component
|
|
|
|
from homeassistant.components import onboarding
|
2019-05-08 05:51:24 +00:00
|
|
|
from homeassistant.components.onboarding import const, views
|
2018-07-17 08:49:15 +00:00
|
|
|
|
2019-03-08 21:51:42 +00:00
|
|
|
from tests.common import CLIENT_ID, register_auth_provider
|
2019-06-19 21:41:27 +00:00
|
|
|
from tests.components.met.conftest import mock_weather # noqa
|
2018-07-17 08:49:15 +00:00
|
|
|
|
|
|
|
from . import mock_storage
|
|
|
|
|
|
|
|
|
2019-06-19 21:41:27 +00:00
|
|
|
@pytest.fixture(autouse=True)
|
|
|
|
def always_mock_weather(mock_weather): # noqa
|
|
|
|
"""Mock the Met weather provider."""
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
2018-07-17 08:49:15 +00:00
|
|
|
@pytest.fixture(autouse=True)
|
|
|
|
def auth_active(hass):
|
|
|
|
"""Ensure auth is always active."""
|
|
|
|
hass.loop.run_until_complete(register_auth_provider(hass, {
|
|
|
|
'type': 'homeassistant'
|
|
|
|
}))
|
|
|
|
|
|
|
|
|
|
|
|
async def test_onboarding_progress(hass, hass_storage, aiohttp_client):
|
|
|
|
"""Test fetching progress."""
|
|
|
|
mock_storage(hass_storage, {
|
|
|
|
'done': ['hello']
|
|
|
|
})
|
|
|
|
|
|
|
|
assert await async_setup_component(hass, 'onboarding', {})
|
|
|
|
client = await aiohttp_client(hass.http.app)
|
|
|
|
|
|
|
|
with patch.object(views, 'STEPS', ['hello', 'world']):
|
|
|
|
resp = await client.get('/api/onboarding')
|
|
|
|
|
|
|
|
assert resp.status == 200
|
|
|
|
data = await resp.json()
|
|
|
|
assert len(data) == 2
|
|
|
|
assert data[0] == {
|
|
|
|
'step': 'hello',
|
|
|
|
'done': True
|
|
|
|
}
|
|
|
|
assert data[1] == {
|
|
|
|
'step': 'world',
|
|
|
|
'done': False
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async def test_onboarding_user_already_done(hass, hass_storage,
|
|
|
|
aiohttp_client):
|
|
|
|
"""Test creating a new user when user step already done."""
|
|
|
|
mock_storage(hass_storage, {
|
|
|
|
'done': [views.STEP_USER]
|
|
|
|
})
|
|
|
|
|
|
|
|
with patch.object(onboarding, 'STEPS', ['hello', 'world']):
|
|
|
|
assert await async_setup_component(hass, 'onboarding', {})
|
|
|
|
|
|
|
|
client = await aiohttp_client(hass.http.app)
|
|
|
|
|
|
|
|
resp = await client.post('/api/onboarding/users', json={
|
2019-03-08 21:51:42 +00:00
|
|
|
'client_id': CLIENT_ID,
|
2018-07-17 08:49:15 +00:00
|
|
|
'name': 'Test Name',
|
|
|
|
'username': 'test-user',
|
|
|
|
'password': 'test-pass',
|
2019-05-08 05:51:24 +00:00
|
|
|
'language': 'en',
|
2018-07-17 08:49:15 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
assert resp.status == 403
|
|
|
|
|
|
|
|
|
|
|
|
async def test_onboarding_user(hass, hass_storage, aiohttp_client):
|
|
|
|
"""Test creating a new user."""
|
2019-02-14 04:00:08 +00:00
|
|
|
assert await async_setup_component(hass, 'person', {})
|
2018-07-17 08:49:15 +00:00
|
|
|
assert await async_setup_component(hass, 'onboarding', {})
|
|
|
|
|
|
|
|
client = await aiohttp_client(hass.http.app)
|
|
|
|
|
|
|
|
resp = await client.post('/api/onboarding/users', json={
|
2019-03-08 21:51:42 +00:00
|
|
|
'client_id': CLIENT_ID,
|
2018-07-17 08:49:15 +00:00
|
|
|
'name': 'Test Name',
|
|
|
|
'username': 'test-user',
|
|
|
|
'password': 'test-pass',
|
2019-05-08 05:51:24 +00:00
|
|
|
'language': 'en',
|
2018-07-17 08:49:15 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
assert resp.status == 200
|
2019-05-08 05:51:24 +00:00
|
|
|
assert const.STEP_USER in hass_storage[const.DOMAIN]['data']['done']
|
|
|
|
|
2019-03-08 21:51:42 +00:00
|
|
|
data = await resp.json()
|
|
|
|
assert 'auth_code' in data
|
|
|
|
|
2018-07-17 08:49:15 +00:00
|
|
|
users = await hass.auth.async_get_users()
|
|
|
|
assert len(users) == 1
|
|
|
|
user = users[0]
|
|
|
|
assert user.name == 'Test Name'
|
|
|
|
assert len(user.credentials) == 1
|
|
|
|
assert user.credentials[0].data['username'] == 'test-user'
|
2019-02-14 04:00:08 +00:00
|
|
|
assert len(hass.data['person'].storage_data) == 1
|
2018-07-17 08:49:15 +00:00
|
|
|
|
2019-05-08 05:51:24 +00:00
|
|
|
# Validate refresh token 1
|
2019-03-08 21:51:42 +00:00
|
|
|
resp = await client.post('/auth/token', data={
|
|
|
|
'client_id': CLIENT_ID,
|
|
|
|
'grant_type': 'authorization_code',
|
|
|
|
'code': data['auth_code']
|
|
|
|
})
|
|
|
|
|
|
|
|
assert resp.status == 200
|
|
|
|
tokens = await resp.json()
|
|
|
|
|
|
|
|
assert (
|
|
|
|
await hass.auth.async_validate_access_token(tokens['access_token'])
|
|
|
|
is not None
|
|
|
|
)
|
|
|
|
|
2019-05-08 05:51:24 +00:00
|
|
|
# Validate created areas
|
|
|
|
area_registry = await hass.helpers.area_registry.async_get_registry()
|
|
|
|
assert len(area_registry.areas) == 3
|
|
|
|
assert sorted([area.name for area
|
|
|
|
in area_registry.async_list_areas()]) == [
|
|
|
|
'Bedroom', 'Kitchen', 'Living Room'
|
|
|
|
]
|
|
|
|
|
2018-07-17 08:49:15 +00:00
|
|
|
|
|
|
|
async def test_onboarding_user_invalid_name(hass, hass_storage,
|
|
|
|
aiohttp_client):
|
|
|
|
"""Test not providing name."""
|
|
|
|
mock_storage(hass_storage, {
|
2019-05-08 05:51:24 +00:00
|
|
|
'done': []
|
2018-07-17 08:49:15 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
assert await async_setup_component(hass, 'onboarding', {})
|
|
|
|
|
|
|
|
client = await aiohttp_client(hass.http.app)
|
|
|
|
|
|
|
|
resp = await client.post('/api/onboarding/users', json={
|
2019-03-08 21:51:42 +00:00
|
|
|
'client_id': CLIENT_ID,
|
2018-07-17 08:49:15 +00:00
|
|
|
'username': 'test-user',
|
|
|
|
'password': 'test-pass',
|
2019-05-08 05:51:24 +00:00
|
|
|
'language': 'en',
|
2018-07-17 08:49:15 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
assert resp.status == 400
|
|
|
|
|
|
|
|
|
|
|
|
async def test_onboarding_user_race(hass, hass_storage, aiohttp_client):
|
|
|
|
"""Test race condition on creating new user."""
|
|
|
|
mock_storage(hass_storage, {
|
|
|
|
'done': ['hello']
|
|
|
|
})
|
|
|
|
|
|
|
|
assert await async_setup_component(hass, 'onboarding', {})
|
|
|
|
|
|
|
|
client = await aiohttp_client(hass.http.app)
|
|
|
|
|
|
|
|
resp1 = client.post('/api/onboarding/users', json={
|
2019-03-08 21:51:42 +00:00
|
|
|
'client_id': CLIENT_ID,
|
2018-07-17 08:49:15 +00:00
|
|
|
'name': 'Test 1',
|
|
|
|
'username': '1-user',
|
|
|
|
'password': '1-pass',
|
2019-05-08 05:51:24 +00:00
|
|
|
'language': 'en',
|
2018-07-17 08:49:15 +00:00
|
|
|
})
|
|
|
|
resp2 = client.post('/api/onboarding/users', json={
|
2019-03-08 21:51:42 +00:00
|
|
|
'client_id': CLIENT_ID,
|
2018-07-17 08:49:15 +00:00
|
|
|
'name': 'Test 2',
|
|
|
|
'username': '2-user',
|
|
|
|
'password': '2-pass',
|
2019-05-08 05:51:24 +00:00
|
|
|
'language': 'es',
|
2018-07-17 08:49:15 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
res1, res2 = await asyncio.gather(resp1, resp2)
|
|
|
|
|
|
|
|
assert sorted([res1.status, res2.status]) == [200, 403]
|
2019-05-08 05:51:24 +00:00
|
|
|
|
|
|
|
|
|
|
|
async def test_onboarding_integration(hass, hass_storage, hass_client):
|
|
|
|
"""Test finishing integration step."""
|
|
|
|
mock_storage(hass_storage, {
|
|
|
|
'done': [const.STEP_USER]
|
|
|
|
})
|
|
|
|
|
|
|
|
assert await async_setup_component(hass, 'onboarding', {})
|
|
|
|
|
|
|
|
client = await hass_client()
|
|
|
|
|
|
|
|
resp = await client.post('/api/onboarding/integration', json={
|
|
|
|
'client_id': CLIENT_ID,
|
|
|
|
})
|
|
|
|
|
|
|
|
assert resp.status == 200
|
|
|
|
data = await resp.json()
|
|
|
|
assert 'auth_code' in data
|
|
|
|
|
|
|
|
# Validate refresh token
|
|
|
|
resp = await client.post('/auth/token', data={
|
|
|
|
'client_id': CLIENT_ID,
|
|
|
|
'grant_type': 'authorization_code',
|
|
|
|
'code': data['auth_code']
|
|
|
|
})
|
|
|
|
|
|
|
|
assert resp.status == 200
|
|
|
|
assert const.STEP_INTEGRATION in hass_storage[const.DOMAIN]['data']['done']
|
|
|
|
tokens = await resp.json()
|
|
|
|
|
|
|
|
assert (
|
|
|
|
await hass.auth.async_validate_access_token(tokens['access_token'])
|
|
|
|
is not None
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
async def test_onboarding_integration_requires_auth(hass, hass_storage,
|
|
|
|
aiohttp_client):
|
|
|
|
"""Test finishing integration step."""
|
|
|
|
mock_storage(hass_storage, {
|
|
|
|
'done': [const.STEP_USER]
|
|
|
|
})
|
|
|
|
|
|
|
|
assert await async_setup_component(hass, 'onboarding', {})
|
|
|
|
|
|
|
|
client = await aiohttp_client(hass.http.app)
|
|
|
|
|
|
|
|
resp = await client.post('/api/onboarding/integration', json={
|
|
|
|
'client_id': CLIENT_ID,
|
|
|
|
})
|
|
|
|
|
|
|
|
assert resp.status == 401
|
2019-06-19 21:41:27 +00:00
|
|
|
|
|
|
|
|
|
|
|
async def test_onboarding_core_sets_up_met(hass, hass_storage, hass_client):
|
|
|
|
"""Test finishing the core step."""
|
|
|
|
mock_storage(hass_storage, {
|
|
|
|
'done': [const.STEP_USER]
|
|
|
|
})
|
|
|
|
|
|
|
|
assert await async_setup_component(hass, 'onboarding', {})
|
|
|
|
|
|
|
|
client = await hass_client()
|
|
|
|
|
|
|
|
resp = await client.post('/api/onboarding/core_config')
|
|
|
|
|
|
|
|
assert resp.status == 200
|
|
|
|
|
|
|
|
await hass.async_block_till_done()
|
|
|
|
assert len(hass.states.async_entity_ids('weather')) == 1
|