core/tests/components/onboarding/test_views.py

249 lines
6.9 KiB
Python

"""Test the onboarding views."""
import asyncio
from unittest.mock import patch
import pytest
from homeassistant.components import onboarding
from homeassistant.components.onboarding import const, views
from homeassistant.setup import async_setup_component
from . import mock_storage
from tests.common import CLIENT_ID, register_auth_provider
from tests.components.met.conftest import mock_weather # noqa: F401
@pytest.fixture(autouse=True)
def always_mock_weather(mock_weather): # noqa: F811
"""Mock the Met weather provider."""
pass
@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={
"client_id": CLIENT_ID,
"name": "Test Name",
"username": "test-user",
"password": "test-pass",
"language": "en",
},
)
assert resp.status == 403
async def test_onboarding_user(hass, hass_storage, aiohttp_client):
"""Test creating a new user."""
assert await async_setup_component(hass, "person", {})
assert await async_setup_component(hass, "onboarding", {})
client = await aiohttp_client(hass.http.app)
resp = await client.post(
"/api/onboarding/users",
json={
"client_id": CLIENT_ID,
"name": "Test Name",
"username": "test-user",
"password": "test-pass",
"language": "en",
},
)
assert resp.status == 200
assert const.STEP_USER in hass_storage[const.DOMAIN]["data"]["done"]
data = await resp.json()
assert "auth_code" in data
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"
assert len(hass.data["person"][1].async_items()) == 1
# Validate refresh token 1
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
)
# 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",
]
async def test_onboarding_user_invalid_name(hass, hass_storage, aiohttp_client):
"""Test not providing name."""
mock_storage(hass_storage, {"done": []})
assert await async_setup_component(hass, "onboarding", {})
client = await aiohttp_client(hass.http.app)
resp = await client.post(
"/api/onboarding/users",
json={
"client_id": CLIENT_ID,
"username": "test-user",
"password": "test-pass",
"language": "en",
},
)
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={
"client_id": CLIENT_ID,
"name": "Test 1",
"username": "1-user",
"password": "1-pass",
"language": "en",
},
)
resp2 = client.post(
"/api/onboarding/users",
json={
"client_id": CLIENT_ID,
"name": "Test 2",
"username": "2-user",
"password": "2-pass",
"language": "es",
},
)
res1, res2 = await asyncio.gather(resp1, resp2)
assert sorted([res1.status, res2.status]) == [200, 403]
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
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