From c2f8dfcb9f704ed32b9b0fd0fda913d0ab75958d Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Tue, 27 Nov 2018 10:41:44 +0100 Subject: [PATCH] Legacy api fix (#18733) * Set user for API password requests * Fix tests * Fix typing --- .../auth/providers/legacy_api_password.py | 29 +++++++++-- homeassistant/components/http/auth.py | 5 ++ tests/components/alexa/test_intent.py | 4 +- tests/components/alexa/test_smart_home.py | 12 ++--- tests/components/conftest.py | 39 ++++++++++++++- tests/components/hassio/conftest.py | 2 +- tests/components/http/test_auth.py | 11 +++-- tests/components/http/test_init.py | 2 +- tests/components/test_api.py | 22 ++++++--- tests/components/test_conversation.py | 12 ++--- tests/components/test_history.py | 4 +- tests/components/test_shopping_list.py | 24 +++++----- tests/components/test_spaceapi.py | 4 +- tests/components/test_system_log.py | 48 +++++++++---------- tests/components/test_webhook.py | 4 +- 15 files changed, 148 insertions(+), 74 deletions(-) diff --git a/homeassistant/auth/providers/legacy_api_password.py b/homeassistant/auth/providers/legacy_api_password.py index 111b9e7d39f3..6cdb12b7157f 100644 --- a/homeassistant/auth/providers/legacy_api_password.py +++ b/homeassistant/auth/providers/legacy_api_password.py @@ -4,16 +4,19 @@ Support Legacy API password auth provider. It will be removed when auth system production ready """ import hmac -from typing import Any, Dict, Optional, cast +from typing import Any, Dict, Optional, cast, TYPE_CHECKING import voluptuous as vol -from homeassistant.components.http import HomeAssistantHTTP # noqa: F401 -from homeassistant.core import callback +from homeassistant.core import HomeAssistant, callback from homeassistant.exceptions import HomeAssistantError from . import AuthProvider, AUTH_PROVIDER_SCHEMA, AUTH_PROVIDERS, LoginFlow -from ..models import Credentials, UserMeta +from .. import AuthManager +from ..models import Credentials, UserMeta, User + +if TYPE_CHECKING: + from homeassistant.components.http import HomeAssistantHTTP # noqa: F401 USER_SCHEMA = vol.Schema({ @@ -31,6 +34,24 @@ class InvalidAuthError(HomeAssistantError): """Raised when submitting invalid authentication.""" +async def async_get_user(hass: HomeAssistant) -> User: + """Return the legacy API password user.""" + auth = cast(AuthManager, hass.auth) # type: ignore + found = None + + for prv in auth.auth_providers: + if prv.type == 'legacy_api_password': + found = prv + break + + if found is None: + raise ValueError('Legacy API password provider not found') + + return await auth.async_get_or_create_user( + await found.async_get_or_create_credentials({}) + ) + + @AUTH_PROVIDERS.register('legacy_api_password') class LegacyApiPasswordAuthProvider(AuthProvider): """Example auth provider based on hardcoded usernames and passwords.""" diff --git a/homeassistant/components/http/auth.py b/homeassistant/components/http/auth.py index 1f89dc5e4ca2..0e943b33fb83 100644 --- a/homeassistant/components/http/auth.py +++ b/homeassistant/components/http/auth.py @@ -10,6 +10,7 @@ import jwt from homeassistant.core import callback from homeassistant.const import HTTP_HEADER_HA_AUTH +from homeassistant.auth.providers import legacy_api_password from homeassistant.auth.util import generate_secret from homeassistant.util import dt as dt_util @@ -78,12 +79,16 @@ def setup_auth(app, trusted_networks, use_auth, request.headers[HTTP_HEADER_HA_AUTH].encode('utf-8'))): # A valid auth header has been set authenticated = True + request['hass_user'] = await legacy_api_password.async_get_user( + app['hass']) elif (legacy_auth and DATA_API_PASSWORD in request.query and hmac.compare_digest( api_password.encode('utf-8'), request.query[DATA_API_PASSWORD].encode('utf-8'))): authenticated = True + request['hass_user'] = await legacy_api_password.async_get_user( + app['hass']) elif _is_trusted_ip(request, trusted_networks): authenticated = True diff --git a/tests/components/alexa/test_intent.py b/tests/components/alexa/test_intent.py index d15c7ccbb34e..ab84dd2a3bc5 100644 --- a/tests/components/alexa/test_intent.py +++ b/tests/components/alexa/test_intent.py @@ -23,7 +23,7 @@ NPR_NEWS_MP3_URL = "https://pd.npr.org/anon.npr-mp3/npr/news/newscast.mp3" @pytest.fixture -def alexa_client(loop, hass, aiohttp_client): +def alexa_client(loop, hass, hass_client): """Initialize a Home Assistant server for testing this module.""" @callback def mock_service(call): @@ -95,7 +95,7 @@ def alexa_client(loop, hass, aiohttp_client): }, } })) - return loop.run_until_complete(aiohttp_client(hass.http.app)) + return loop.run_until_complete(hass_client()) def _intent_req(client, data=None): diff --git a/tests/components/alexa/test_smart_home.py b/tests/components/alexa/test_smart_home.py index 766075f8eb53..3cfb8068177f 100644 --- a/tests/components/alexa/test_smart_home.py +++ b/tests/components/alexa/test_smart_home.py @@ -1437,10 +1437,10 @@ async def test_unsupported_domain(hass): assert not msg['payload']['endpoints'] -async def do_http_discovery(config, hass, aiohttp_client): +async def do_http_discovery(config, hass, hass_client): """Submit a request to the Smart Home HTTP API.""" await async_setup_component(hass, alexa.DOMAIN, config) - http_client = await aiohttp_client(hass.http.app) + http_client = await hass_client() request = get_new_request('Alexa.Discovery', 'Discover') response = await http_client.post( @@ -1450,7 +1450,7 @@ async def do_http_discovery(config, hass, aiohttp_client): return response -async def test_http_api(hass, aiohttp_client): +async def test_http_api(hass, hass_client): """With `smart_home:` HTTP API is exposed.""" config = { 'alexa': { @@ -1458,7 +1458,7 @@ async def test_http_api(hass, aiohttp_client): } } - response = await do_http_discovery(config, hass, aiohttp_client) + response = await do_http_discovery(config, hass, hass_client) response_data = await response.json() # Here we're testing just the HTTP view glue -- details of discovery are @@ -1466,12 +1466,12 @@ async def test_http_api(hass, aiohttp_client): assert response_data['event']['header']['name'] == 'Discover.Response' -async def test_http_api_disabled(hass, aiohttp_client): +async def test_http_api_disabled(hass, hass_client): """Without `smart_home:`, the HTTP API is disabled.""" config = { 'alexa': {} } - response = await do_http_discovery(config, hass, aiohttp_client) + response = await do_http_discovery(config, hass, hass_client) assert response.status == 404 diff --git a/tests/components/conftest.py b/tests/components/conftest.py index 46d75a56ad67..110ba8d5ad6d 100644 --- a/tests/components/conftest.py +++ b/tests/components/conftest.py @@ -4,6 +4,7 @@ from unittest.mock import patch import pytest from homeassistant.auth.const import GROUP_ID_ADMIN, GROUP_ID_READ_ONLY +from homeassistant.auth.providers import legacy_api_password, homeassistant from homeassistant.setup import async_setup_component from homeassistant.components.websocket_api.http import URL from homeassistant.components.websocket_api.auth import ( @@ -88,7 +89,7 @@ def hass_access_token(hass, hass_admin_user): @pytest.fixture -def hass_admin_user(hass): +def hass_admin_user(hass, local_auth): """Return a Home Assistant admin user.""" admin_group = hass.loop.run_until_complete(hass.auth.async_get_group( GROUP_ID_ADMIN)) @@ -96,8 +97,42 @@ def hass_admin_user(hass): @pytest.fixture -def hass_read_only_user(hass): +def hass_read_only_user(hass, local_auth): """Return a Home Assistant read only user.""" read_only_group = hass.loop.run_until_complete(hass.auth.async_get_group( GROUP_ID_READ_ONLY)) return MockUser(groups=[read_only_group]).add_to_hass(hass) + + +@pytest.fixture +def legacy_auth(hass): + """Load legacy API password provider.""" + prv = legacy_api_password.LegacyApiPasswordAuthProvider( + hass, hass.auth._store, { + 'type': 'legacy_api_password' + } + ) + hass.auth._providers[(prv.type, prv.id)] = prv + + +@pytest.fixture +def local_auth(hass): + """Load local auth provider.""" + prv = homeassistant.HassAuthProvider( + hass, hass.auth._store, { + 'type': 'homeassistant' + } + ) + hass.auth._providers[(prv.type, prv.id)] = prv + + +@pytest.fixture +def hass_client(hass, aiohttp_client, hass_access_token): + """Return an authenticated HTTP client.""" + async def auth_client(): + """Return an authenticated client.""" + return await aiohttp_client(hass.http.app, headers={ + 'Authorization': "Bearer {}".format(hass_access_token) + }) + + return auth_client diff --git a/tests/components/hassio/conftest.py b/tests/components/hassio/conftest.py index f9ad1c578de1..435de6d1edf9 100644 --- a/tests/components/hassio/conftest.py +++ b/tests/components/hassio/conftest.py @@ -27,7 +27,7 @@ def hassio_env(): @pytest.fixture -def hassio_client(hassio_env, hass, aiohttp_client): +def hassio_client(hassio_env, hass, aiohttp_client, legacy_auth): """Create mock hassio http client.""" with patch('homeassistant.components.hassio.HassIO.update_hass_api', Mock(return_value=mock_coro({"result": "ok"}))), \ diff --git a/tests/components/http/test_auth.py b/tests/components/http/test_auth.py index 2746abcf15c5..979bfc28689e 100644 --- a/tests/components/http/test_auth.py +++ b/tests/components/http/test_auth.py @@ -83,7 +83,8 @@ async def test_access_without_password(app, aiohttp_client): assert resp.status == 200 -async def test_access_with_password_in_header(app, aiohttp_client): +async def test_access_with_password_in_header(app, aiohttp_client, + legacy_auth): """Test access with password in header.""" setup_auth(app, [], False, api_password=API_PASSWORD) client = await aiohttp_client(app) @@ -97,7 +98,7 @@ async def test_access_with_password_in_header(app, aiohttp_client): assert req.status == 401 -async def test_access_with_password_in_query(app, aiohttp_client): +async def test_access_with_password_in_query(app, aiohttp_client, legacy_auth): """Test access with password in URL.""" setup_auth(app, [], False, api_password=API_PASSWORD) client = await aiohttp_client(app) @@ -219,7 +220,8 @@ async def test_auth_active_access_with_trusted_ip(app2, aiohttp_client): "{} should be trusted".format(remote_addr) -async def test_auth_active_blocked_api_password_access(app, aiohttp_client): +async def test_auth_active_blocked_api_password_access( + app, aiohttp_client, legacy_auth): """Test access using api_password should be blocked when auth.active.""" setup_auth(app, [], True, api_password=API_PASSWORD) client = await aiohttp_client(app) @@ -239,7 +241,8 @@ async def test_auth_active_blocked_api_password_access(app, aiohttp_client): assert req.status == 401 -async def test_auth_legacy_support_api_password_access(app, aiohttp_client): +async def test_auth_legacy_support_api_password_access( + app, aiohttp_client, legacy_auth): """Test access using api_password if auth.support_legacy.""" setup_auth(app, [], True, support_legacy=True, api_password=API_PASSWORD) client = await aiohttp_client(app) diff --git a/tests/components/http/test_init.py b/tests/components/http/test_init.py index 9f6441c52386..1c1afe711c61 100644 --- a/tests/components/http/test_init.py +++ b/tests/components/http/test_init.py @@ -124,7 +124,7 @@ async def test_api_no_base_url(hass): assert hass.config.api.base_url == 'http://127.0.0.1:8123' -async def test_not_log_password(hass, aiohttp_client, caplog): +async def test_not_log_password(hass, aiohttp_client, caplog, legacy_auth): """Test access with password doesn't get logged.""" assert await async_setup_component(hass, 'api', { 'http': { diff --git a/tests/components/test_api.py b/tests/components/test_api.py index 3ebfa05a3d39..0bc89292855e 100644 --- a/tests/components/test_api.py +++ b/tests/components/test_api.py @@ -16,12 +16,10 @@ from tests.common import async_mock_service @pytest.fixture -def mock_api_client(hass, aiohttp_client, hass_access_token): +def mock_api_client(hass, hass_client): """Start the Hass HTTP component and return admin API client.""" hass.loop.run_until_complete(async_setup_component(hass, 'api', {})) - return hass.loop.run_until_complete(aiohttp_client(hass.http.app, headers={ - 'Authorization': 'Bearer {}'.format(hass_access_token) - })) + return hass.loop.run_until_complete(hass_client()) @asyncio.coroutine @@ -408,7 +406,7 @@ def _listen_count(hass): async def test_api_error_log(hass, aiohttp_client, hass_access_token, - hass_admin_user): + hass_admin_user, legacy_auth): """Test if we can fetch the error log.""" hass.data[DATA_LOGGING] = '/some/path' await async_setup_component(hass, 'api', { @@ -566,5 +564,17 @@ async def test_rendering_template_admin(hass, mock_api_client, hass_admin_user): """Test rendering a template requires admin.""" hass_admin_user.groups = [] - resp = await mock_api_client.post('/api/template') + resp = await mock_api_client.post(const.URL_API_TEMPLATE) + assert resp.status == 401 + + +async def test_rendering_template_legacy_user( + hass, mock_api_client, aiohttp_client, legacy_auth): + """Test rendering a template with legacy API password.""" + hass.states.async_set('sensor.temperature', 10) + client = await aiohttp_client(hass.http.app) + resp = await client.post( + const.URL_API_TEMPLATE, + json={"template": '{{ states.sensor.temperature.state }}'} + ) assert resp.status == 401 diff --git a/tests/components/test_conversation.py b/tests/components/test_conversation.py index 7934e0162816..2aa1f499a768 100644 --- a/tests/components/test_conversation.py +++ b/tests/components/test_conversation.py @@ -90,7 +90,7 @@ async def test_register_before_setup(hass): assert intent.text_input == 'I would like the Grolsch beer' -async def test_http_processing_intent(hass, aiohttp_client): +async def test_http_processing_intent(hass, hass_client): """Test processing intent via HTTP API.""" class TestIntentHandler(intent.IntentHandler): """Test Intent Handler.""" @@ -120,7 +120,7 @@ async def test_http_processing_intent(hass, aiohttp_client): }) assert result - client = await aiohttp_client(hass.http.app) + client = await hass_client() resp = await client.post('/api/conversation/process', json={ 'text': 'I would like the Grolsch beer' }) @@ -244,7 +244,7 @@ async def test_toggle_intent(hass, sentence): assert call.data == {'entity_id': 'light.kitchen'} -async def test_http_api(hass, aiohttp_client): +async def test_http_api(hass, hass_client): """Test the HTTP conversation API.""" result = await component.async_setup(hass, {}) assert result @@ -252,7 +252,7 @@ async def test_http_api(hass, aiohttp_client): result = await async_setup_component(hass, 'conversation', {}) assert result - client = await aiohttp_client(hass.http.app) + client = await hass_client() hass.states.async_set('light.kitchen', 'off') calls = async_mock_service(hass, HASS_DOMAIN, 'turn_on') @@ -268,7 +268,7 @@ async def test_http_api(hass, aiohttp_client): assert call.data == {'entity_id': 'light.kitchen'} -async def test_http_api_wrong_data(hass, aiohttp_client): +async def test_http_api_wrong_data(hass, hass_client): """Test the HTTP conversation API.""" result = await component.async_setup(hass, {}) assert result @@ -276,7 +276,7 @@ async def test_http_api_wrong_data(hass, aiohttp_client): result = await async_setup_component(hass, 'conversation', {}) assert result - client = await aiohttp_client(hass.http.app) + client = await hass_client() resp = await client.post('/api/conversation/process', json={ 'text': 123 diff --git a/tests/components/test_history.py b/tests/components/test_history.py index 9764af1592cc..641dff3b4e63 100644 --- a/tests/components/test_history.py +++ b/tests/components/test_history.py @@ -515,13 +515,13 @@ class TestComponentHistory(unittest.TestCase): return zero, four, states -async def test_fetch_period_api(hass, aiohttp_client): +async def test_fetch_period_api(hass, hass_client): """Test the fetch period view for history.""" await hass.async_add_job(init_recorder_component, hass) await async_setup_component(hass, 'history', {}) await hass.components.recorder.wait_connection_ready() await hass.async_add_job(hass.data[recorder.DATA_INSTANCE].block_till_done) - client = await aiohttp_client(hass.http.app) + client = await hass_client() response = await client.get( '/api/history/period/{}'.format(dt_util.utcnow().isoformat())) assert response.status == 200 diff --git a/tests/components/test_shopping_list.py b/tests/components/test_shopping_list.py index c2899f6b7535..1e89287bcc10 100644 --- a/tests/components/test_shopping_list.py +++ b/tests/components/test_shopping_list.py @@ -55,7 +55,7 @@ def test_recent_items_intent(hass): @asyncio.coroutine -def test_deprecated_api_get_all(hass, aiohttp_client): +def test_deprecated_api_get_all(hass, hass_client): """Test the API.""" yield from async_setup_component(hass, 'shopping_list', {}) @@ -66,7 +66,7 @@ def test_deprecated_api_get_all(hass, aiohttp_client): hass, 'test', 'HassShoppingListAddItem', {'item': {'value': 'wine'}} ) - client = yield from aiohttp_client(hass.http.app) + client = yield from hass_client() resp = yield from client.get('/api/shopping_list') assert resp.status == 200 @@ -110,7 +110,7 @@ async def test_ws_get_items(hass, hass_ws_client): @asyncio.coroutine -def test_deprecated_api_update(hass, aiohttp_client): +def test_deprecated_api_update(hass, hass_client): """Test the API.""" yield from async_setup_component(hass, 'shopping_list', {}) @@ -124,7 +124,7 @@ def test_deprecated_api_update(hass, aiohttp_client): beer_id = hass.data['shopping_list'].items[0]['id'] wine_id = hass.data['shopping_list'].items[1]['id'] - client = yield from aiohttp_client(hass.http.app) + client = yield from hass_client() resp = yield from client.post( '/api/shopping_list/item/{}'.format(beer_id), json={ 'name': 'soda' @@ -220,7 +220,7 @@ async def test_ws_update_item(hass, hass_ws_client): @asyncio.coroutine -def test_api_update_fails(hass, aiohttp_client): +def test_api_update_fails(hass, hass_client): """Test the API.""" yield from async_setup_component(hass, 'shopping_list', {}) @@ -228,7 +228,7 @@ def test_api_update_fails(hass, aiohttp_client): hass, 'test', 'HassShoppingListAddItem', {'item': {'value': 'beer'}} ) - client = yield from aiohttp_client(hass.http.app) + client = yield from hass_client() resp = yield from client.post( '/api/shopping_list/non_existing', json={ 'name': 'soda' @@ -275,7 +275,7 @@ async def test_ws_update_item_fail(hass, hass_ws_client): @asyncio.coroutine -def test_api_clear_completed(hass, aiohttp_client): +def test_api_clear_completed(hass, hass_client): """Test the API.""" yield from async_setup_component(hass, 'shopping_list', {}) @@ -289,7 +289,7 @@ def test_api_clear_completed(hass, aiohttp_client): beer_id = hass.data['shopping_list'].items[0]['id'] wine_id = hass.data['shopping_list'].items[1]['id'] - client = yield from aiohttp_client(hass.http.app) + client = yield from hass_client() # Mark beer as completed resp = yield from client.post( @@ -312,11 +312,11 @@ def test_api_clear_completed(hass, aiohttp_client): @asyncio.coroutine -def test_deprecated_api_create(hass, aiohttp_client): +def test_deprecated_api_create(hass, hass_client): """Test the API.""" yield from async_setup_component(hass, 'shopping_list', {}) - client = yield from aiohttp_client(hass.http.app) + client = yield from hass_client() resp = yield from client.post('/api/shopping_list/item', json={ 'name': 'soda' }) @@ -333,11 +333,11 @@ def test_deprecated_api_create(hass, aiohttp_client): @asyncio.coroutine -def test_deprecated_api_create_fail(hass, aiohttp_client): +def test_deprecated_api_create_fail(hass, hass_client): """Test the API.""" yield from async_setup_component(hass, 'shopping_list', {}) - client = yield from aiohttp_client(hass.http.app) + client = yield from hass_client() resp = yield from client.post('/api/shopping_list/item', json={ 'name': 1234 }) diff --git a/tests/components/test_spaceapi.py b/tests/components/test_spaceapi.py index e7e7d158a31a..61bb009ff8f2 100644 --- a/tests/components/test_spaceapi.py +++ b/tests/components/test_spaceapi.py @@ -56,7 +56,7 @@ SENSOR_OUTPUT = { @pytest.fixture -def mock_client(hass, aiohttp_client): +def mock_client(hass, hass_client): """Start the Home Assistant HTTP component.""" with patch('homeassistant.components.spaceapi', return_value=mock_coro(True)): @@ -70,7 +70,7 @@ def mock_client(hass, aiohttp_client): hass.states.async_set('test.hum1', 88, attributes={'unit_of_measurement': '%'}) - return hass.loop.run_until_complete(aiohttp_client(hass.http.app)) + return hass.loop.run_until_complete(hass_client()) async def test_spaceapi_get(hass, mock_client): diff --git a/tests/components/test_system_log.py b/tests/components/test_system_log.py index 5d48fd881273..6afd792be9c6 100644 --- a/tests/components/test_system_log.py +++ b/tests/components/test_system_log.py @@ -14,9 +14,9 @@ BASIC_CONFIG = { } -async def get_error_log(hass, aiohttp_client, expected_count): +async def get_error_log(hass, hass_client, expected_count): """Fetch all entries from system_log via the API.""" - client = await aiohttp_client(hass.http.app) + client = await hass_client() resp = await client.get('/api/error/all') assert resp.status == 200 @@ -45,37 +45,37 @@ def get_frame(name): return (name, None, None, None) -async def test_normal_logs(hass, aiohttp_client): +async def test_normal_logs(hass, hass_client): """Test that debug and info are not logged.""" await async_setup_component(hass, system_log.DOMAIN, BASIC_CONFIG) _LOGGER.debug('debug') _LOGGER.info('info') # Assert done by get_error_log - await get_error_log(hass, aiohttp_client, 0) + await get_error_log(hass, hass_client, 0) -async def test_exception(hass, aiohttp_client): +async def test_exception(hass, hass_client): """Test that exceptions are logged and retrieved correctly.""" await async_setup_component(hass, system_log.DOMAIN, BASIC_CONFIG) _generate_and_log_exception('exception message', 'log message') - log = (await get_error_log(hass, aiohttp_client, 1))[0] + log = (await get_error_log(hass, hass_client, 1))[0] assert_log(log, 'exception message', 'log message', 'ERROR') -async def test_warning(hass, aiohttp_client): +async def test_warning(hass, hass_client): """Test that warning are logged and retrieved correctly.""" await async_setup_component(hass, system_log.DOMAIN, BASIC_CONFIG) _LOGGER.warning('warning message') - log = (await get_error_log(hass, aiohttp_client, 1))[0] + log = (await get_error_log(hass, hass_client, 1))[0] assert_log(log, '', 'warning message', 'WARNING') -async def test_error(hass, aiohttp_client): +async def test_error(hass, hass_client): """Test that errors are logged and retrieved correctly.""" await async_setup_component(hass, system_log.DOMAIN, BASIC_CONFIG) _LOGGER.error('error message') - log = (await get_error_log(hass, aiohttp_client, 1))[0] + log = (await get_error_log(hass, hass_client, 1))[0] assert_log(log, '', 'error message', 'ERROR') @@ -121,26 +121,26 @@ async def test_error_posted_as_event(hass): assert_log(events[0].data, '', 'error message', 'ERROR') -async def test_critical(hass, aiohttp_client): +async def test_critical(hass, hass_client): """Test that critical are logged and retrieved correctly.""" await async_setup_component(hass, system_log.DOMAIN, BASIC_CONFIG) _LOGGER.critical('critical message') - log = (await get_error_log(hass, aiohttp_client, 1))[0] + log = (await get_error_log(hass, hass_client, 1))[0] assert_log(log, '', 'critical message', 'CRITICAL') -async def test_remove_older_logs(hass, aiohttp_client): +async def test_remove_older_logs(hass, hass_client): """Test that older logs are rotated out.""" await async_setup_component(hass, system_log.DOMAIN, BASIC_CONFIG) _LOGGER.error('error message 1') _LOGGER.error('error message 2') _LOGGER.error('error message 3') - log = await get_error_log(hass, aiohttp_client, 2) + log = await get_error_log(hass, hass_client, 2) assert_log(log[0], '', 'error message 3', 'ERROR') assert_log(log[1], '', 'error message 2', 'ERROR') -async def test_clear_logs(hass, aiohttp_client): +async def test_clear_logs(hass, hass_client): """Test that the log can be cleared via a service call.""" await async_setup_component(hass, system_log.DOMAIN, BASIC_CONFIG) _LOGGER.error('error message') @@ -151,7 +151,7 @@ async def test_clear_logs(hass, aiohttp_client): await hass.async_block_till_done() # Assert done by get_error_log - await get_error_log(hass, aiohttp_client, 0) + await get_error_log(hass, hass_client, 0) async def test_write_log(hass): @@ -197,13 +197,13 @@ async def test_write_choose_level(hass): assert logger.method_calls[0] == ('debug', ('test_message',)) -async def test_unknown_path(hass, aiohttp_client): +async def test_unknown_path(hass, hass_client): """Test error logged from unknown path.""" await async_setup_component(hass, system_log.DOMAIN, BASIC_CONFIG) _LOGGER.findCaller = MagicMock( return_value=('unknown_path', 0, None, None)) _LOGGER.error('error message') - log = (await get_error_log(hass, aiohttp_client, 1))[0] + log = (await get_error_log(hass, hass_client, 1))[0] assert log['source'] == 'unknown_path' @@ -222,31 +222,31 @@ def log_error_from_test_path(path): _LOGGER.error('error message') -async def test_homeassistant_path(hass, aiohttp_client): +async def test_homeassistant_path(hass, hass_client): """Test error logged from homeassistant path.""" await async_setup_component(hass, system_log.DOMAIN, BASIC_CONFIG) with patch('homeassistant.components.system_log.HOMEASSISTANT_PATH', new=['venv_path/homeassistant']): log_error_from_test_path( 'venv_path/homeassistant/component/component.py') - log = (await get_error_log(hass, aiohttp_client, 1))[0] + log = (await get_error_log(hass, hass_client, 1))[0] assert log['source'] == 'component/component.py' -async def test_config_path(hass, aiohttp_client): +async def test_config_path(hass, hass_client): """Test error logged from config path.""" await async_setup_component(hass, system_log.DOMAIN, BASIC_CONFIG) with patch.object(hass.config, 'config_dir', new='config'): log_error_from_test_path('config/custom_component/test.py') - log = (await get_error_log(hass, aiohttp_client, 1))[0] + log = (await get_error_log(hass, hass_client, 1))[0] assert log['source'] == 'custom_component/test.py' -async def test_netdisco_path(hass, aiohttp_client): +async def test_netdisco_path(hass, hass_client): """Test error logged from netdisco path.""" await async_setup_component(hass, system_log.DOMAIN, BASIC_CONFIG) with patch.dict('sys.modules', netdisco=MagicMock(__path__=['venv_path/netdisco'])): log_error_from_test_path('venv_path/netdisco/disco_component.py') - log = (await get_error_log(hass, aiohttp_client, 1))[0] + log = (await get_error_log(hass, hass_client, 1))[0] assert log['source'] == 'disco_component.py' diff --git a/tests/components/test_webhook.py b/tests/components/test_webhook.py index c16fef3e0592..e67cf7481ccb 100644 --- a/tests/components/test_webhook.py +++ b/tests/components/test_webhook.py @@ -7,10 +7,10 @@ from homeassistant.setup import async_setup_component @pytest.fixture -def mock_client(hass, aiohttp_client): +def mock_client(hass, hass_client): """Create http client for webhooks.""" hass.loop.run_until_complete(async_setup_component(hass, 'webhook', {})) - return hass.loop.run_until_complete(aiohttp_client(hass.http.app)) + return hass.loop.run_until_complete(hass_client()) async def test_unregistering_webhook(hass, mock_client):