diff --git a/homeassistant/components/mobile_app/__init__.py b/homeassistant/components/mobile_app/__init__.py index abb7bcb7628..839aa8a6c3b 100644 --- a/homeassistant/components/mobile_app/__init__.py +++ b/homeassistant/components/mobile_app/__init__.py @@ -7,13 +7,15 @@ from homeassistant.helpers.typing import ConfigType, HomeAssistantType from .const import (ATTR_DEVICE_ID, ATTR_DEVICE_NAME, ATTR_MANUFACTURER, ATTR_MODEL, ATTR_OS_VERSION, DATA_BINARY_SENSOR, DATA_CONFIG_ENTRIES, DATA_DELETED_IDS, - DATA_DEVICES, DATA_SENSOR, DATA_STORE, DOMAIN, STORAGE_KEY, - STORAGE_VERSION) + DATA_DEVICES, DATA_DEVICE_TRACKER, DATA_SENSOR, DATA_STORE, + DOMAIN, STORAGE_KEY, STORAGE_VERSION) from .http_api import RegistrationsView from .webhook import handle_webhook from .websocket_api import register_websocket_handlers +PLATFORMS = 'sensor', 'binary_sensor', 'device_tracker' + async def async_setup(hass: HomeAssistantType, config: ConfigType): """Set up the mobile app component.""" @@ -24,7 +26,6 @@ async def async_setup(hass: HomeAssistantType, config: ConfigType): DATA_BINARY_SENSOR: {}, DATA_CONFIG_ENTRIES: {}, DATA_DELETED_IDS: [], - DATA_DEVICES: {}, DATA_SENSOR: {} } @@ -33,6 +34,7 @@ async def async_setup(hass: HomeAssistantType, config: ConfigType): DATA_CONFIG_ENTRIES: {}, DATA_DELETED_IDS: app_config.get(DATA_DELETED_IDS, []), DATA_DEVICES: {}, + DATA_DEVICE_TRACKER: {}, DATA_SENSOR: app_config.get(DATA_SENSOR, {}), DATA_STORE: store, } @@ -83,10 +85,8 @@ async def async_setup_entry(hass, entry): webhook_register(hass, DOMAIN, registration_name, webhook_id, handle_webhook) - hass.async_create_task( - hass.config_entries.async_forward_entry_setup(entry, - DATA_BINARY_SENSOR)) - hass.async_create_task( - hass.config_entries.async_forward_entry_setup(entry, DATA_SENSOR)) + for domain in PLATFORMS: + hass.async_create_task( + hass.config_entries.async_forward_entry_setup(entry, domain)) return True diff --git a/homeassistant/components/mobile_app/const.py b/homeassistant/components/mobile_app/const.py index 8b33406216e..8cb5aa12731 100644 --- a/homeassistant/components/mobile_app/const.py +++ b/homeassistant/components/mobile_app/const.py @@ -25,6 +25,7 @@ DATA_BINARY_SENSOR = 'binary_sensor' DATA_CONFIG_ENTRIES = 'config_entries' DATA_DELETED_IDS = 'deleted_ids' DATA_DEVICES = 'devices' +DATA_DEVICE_TRACKER = 'device_tracker' DATA_SENSOR = 'sensor' DATA_STORE = 'store' @@ -160,6 +161,7 @@ SENSOR_TYPES = [ATTR_SENSOR_TYPE_BINARY_SENSOR, ATTR_SENSOR_TYPE_SENSOR] COMBINED_CLASSES = sorted(set(BINARY_SENSOR_CLASSES + SENSOR_CLASSES)) SIGNAL_SENSOR_UPDATE = DOMAIN + '_sensor_update' +SIGNAL_LOCATION_UPDATE = DOMAIN + '_location_update_{}' REGISTER_SENSOR_SCHEMA = vol.Schema({ vol.Optional(ATTR_SENSOR_ATTRIBUTES, default={}): dict, diff --git a/homeassistant/components/mobile_app/device_tracker.py b/homeassistant/components/mobile_app/device_tracker.py new file mode 100644 index 00000000000..19aade50876 --- /dev/null +++ b/homeassistant/components/mobile_app/device_tracker.py @@ -0,0 +1,137 @@ +"""Device tracker platform that adds support for OwnTracks over MQTT.""" +import logging + +from homeassistant.core import callback +from homeassistant.components.device_tracker.const import ( + DOMAIN, SOURCE_TYPE_GPS) +from homeassistant.components.device_tracker.config_entry import ( + DeviceTrackerEntity +) +from .const import ( + DOMAIN as MA_DOMAIN, + + ATTR_ALTITUDE, + ATTR_BATTERY, + ATTR_COURSE, + ATTR_DEVICE_ID, + ATTR_DEVICE_NAME, + ATTR_GPS_ACCURACY, + ATTR_GPS, + ATTR_LOCATION_NAME, + ATTR_SPEED, + ATTR_VERTICAL_ACCURACY, + + SIGNAL_LOCATION_UPDATE, +) +from .helpers import device_info + +_LOGGER = logging.getLogger(__name__) + + +async def async_setup_entry(hass, entry, async_add_entities): + """Set up OwnTracks based off an entry.""" + @callback + def _receive_data(data): + """Receive set location.""" + dev_id = entry.data[ATTR_DEVICE_ID] + device = hass.data[MA_DOMAIN][DOMAIN].get(dev_id) + + if device is not None: + device.update_data(data) + return + + device = hass.data[MA_DOMAIN][DOMAIN][dev_id] = MobileAppEntity( + entry, data + ) + async_add_entities([device]) + + hass.helpers.dispatcher.async_dispatcher_connect( + SIGNAL_LOCATION_UPDATE.format(entry.entry_id), _receive_data) + return True + + +class MobileAppEntity(DeviceTrackerEntity): + """Represent a tracked device.""" + + def __init__(self, entry, data): + """Set up OwnTracks entity.""" + self._entry = entry + self._data = data + + @property + def unique_id(self): + """Return the unique ID.""" + return self._entry.data[ATTR_DEVICE_ID] + + @property + def battery_level(self): + """Return the battery level of the device.""" + return self._data.get(ATTR_BATTERY) + + @property + def device_state_attributes(self): + """Return device specific attributes.""" + attrs = {} + for key in (ATTR_ALTITUDE, ATTR_COURSE, + ATTR_SPEED, ATTR_VERTICAL_ACCURACY): + value = self._data.get(key) + if value is not None: + attrs[key] = value + + return attrs + + @property + def location_accuracy(self): + """Return the gps accuracy of the device.""" + return self._data.get(ATTR_GPS_ACCURACY) + + @property + def latitude(self): + """Return latitude value of the device.""" + gps = self._data.get(ATTR_GPS) + + if gps is None: + return None + + return gps[0] + + @property + def longitude(self): + """Return longitude value of the device.""" + gps = self._data.get(ATTR_GPS) + + if gps is None: + return None + + return gps[1] + + @property + def location_name(self): + """Return a location name for the current location of the device.""" + return self._data.get(ATTR_LOCATION_NAME) + + @property + def name(self): + """Return the name of the device.""" + return self._entry.data[ATTR_DEVICE_NAME] + + @property + def should_poll(self): + """No polling needed.""" + return False + + @property + def source_type(self): + """Return the source type, eg gps or router, of the device.""" + return SOURCE_TYPE_GPS + + @property + def device_info(self): + """Return the device info.""" + return device_info(self._entry.data) + + @callback + def update_data(self, data): + """Mark the device as seen.""" + self._data = data + self.async_write_ha_state() diff --git a/homeassistant/components/mobile_app/entity.py b/homeassistant/components/mobile_app/entity.py index eca9d2b024b..8c1747d6f2b 100644 --- a/homeassistant/components/mobile_app/entity.py +++ b/homeassistant/components/mobile_app/entity.py @@ -6,11 +6,11 @@ from homeassistant.helpers.device_registry import DeviceEntry from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.helpers.entity import Entity -from .const import (ATTR_DEVICE_ID, ATTR_DEVICE_NAME, ATTR_MANUFACTURER, - ATTR_MODEL, ATTR_OS_VERSION, ATTR_SENSOR_ATTRIBUTES, +from .const import (ATTR_SENSOR_ATTRIBUTES, ATTR_SENSOR_DEVICE_CLASS, ATTR_SENSOR_ICON, ATTR_SENSOR_NAME, ATTR_SENSOR_TYPE, ATTR_SENSOR_UNIQUE_ID, DOMAIN, SIGNAL_SENSOR_UPDATE) +from .helpers import device_info def sensor_id(webhook_id, unique_id): @@ -76,17 +76,7 @@ class MobileAppEntity(Entity): @property def device_info(self): """Return device registry information for this entity.""" - return { - 'identifiers': { - (ATTR_DEVICE_ID, self._registration[ATTR_DEVICE_ID]), - (CONF_WEBHOOK_ID, self._registration[CONF_WEBHOOK_ID]) - }, - 'manufacturer': self._registration[ATTR_MANUFACTURER], - 'model': self._registration[ATTR_MODEL], - 'device_name': self._registration[ATTR_DEVICE_NAME], - 'sw_version': self._registration[ATTR_OS_VERSION], - 'config_entries': self._device.config_entries - } + return device_info(self._registration) async def async_update(self): """Get the latest state of the sensor.""" diff --git a/homeassistant/components/mobile_app/helpers.py b/homeassistant/components/mobile_app/helpers.py index 6aec4307464..30c111fe0b4 100644 --- a/homeassistant/components/mobile_app/helpers.py +++ b/homeassistant/components/mobile_app/helpers.py @@ -9,7 +9,7 @@ from homeassistant.core import Context from homeassistant.helpers.json import JSONEncoder from homeassistant.helpers.typing import HomeAssistantType -from .const import (ATTR_APP_DATA, ATTR_APP_ID, ATTR_APP_NAME, +from .const import (ATTR_APP_DATA, ATTR_APP_ID, ATTR_APP_NAME, ATTR_DEVICE_ID, ATTR_APP_VERSION, ATTR_DEVICE_NAME, ATTR_MANUFACTURER, ATTR_MODEL, ATTR_OS_VERSION, ATTR_SUPPORTS_ENCRYPTION, CONF_SECRET, CONF_USER_ID, DATA_BINARY_SENSOR, @@ -148,3 +148,16 @@ def webhook_response(data, *, registration: Dict, status: int = 200, return Response(text=data, status=status, content_type='application/json', headers=headers) + + +def device_info(registration: Dict) -> Dict: + """Return the device info for this registration.""" + return { + 'identifiers': { + (DOMAIN, registration[ATTR_DEVICE_ID]), + }, + 'manufacturer': registration[ATTR_MANUFACTURER], + 'model': registration[ATTR_MODEL], + 'device_name': registration[ATTR_DEVICE_NAME], + 'sw_version': registration[ATTR_OS_VERSION], + } diff --git a/homeassistant/components/mobile_app/manifest.json b/homeassistant/components/mobile_app/manifest.json index 969817b62c7..85c6231daa8 100644 --- a/homeassistant/components/mobile_app/manifest.json +++ b/homeassistant/components/mobile_app/manifest.json @@ -7,7 +7,6 @@ "PyNaCl==1.3.0" ], "dependencies": [ - "device_tracker", "http", "webhook" ], diff --git a/homeassistant/components/mobile_app/webhook.py b/homeassistant/components/mobile_app/webhook.py index 4f867885d4f..40002b5cfec 100644 --- a/homeassistant/components/mobile_app/webhook.py +++ b/homeassistant/components/mobile_app/webhook.py @@ -6,10 +6,6 @@ import voluptuous as vol from homeassistant.components.cloud import (async_remote_ui_url, CloudNotAvailable) -from homeassistant.components.device_tracker import (ATTR_ATTRIBUTES, - ATTR_DEV_ID, - DOMAIN as DT_DOMAIN, - SERVICE_SEE as DT_SEE) from homeassistant.components.frontend import MANIFEST_JSON from homeassistant.components.zone.const import DOMAIN as ZONE_DOMAIN @@ -24,15 +20,12 @@ from homeassistant.helpers.dispatcher import async_dispatcher_send from homeassistant.helpers.template import attach from homeassistant.helpers.typing import HomeAssistantType -from homeassistant.util import slugify - -from .const import (ATTR_ALTITUDE, ATTR_BATTERY, ATTR_COURSE, ATTR_DEVICE_ID, +from .const import (ATTR_DEVICE_ID, ATTR_DEVICE_NAME, ATTR_EVENT_DATA, ATTR_EVENT_TYPE, - ATTR_GPS, ATTR_GPS_ACCURACY, ATTR_LOCATION_NAME, ATTR_MANUFACTURER, ATTR_MODEL, ATTR_OS_VERSION, - ATTR_SENSOR_TYPE, ATTR_SENSOR_UNIQUE_ID, ATTR_SPEED, + ATTR_SENSOR_TYPE, ATTR_SENSOR_UNIQUE_ID, ATTR_SUPPORTS_ENCRYPTION, ATTR_TEMPLATE, - ATTR_TEMPLATE_VARIABLES, ATTR_VERTICAL_ACCURACY, + ATTR_TEMPLATE_VARIABLES, ATTR_WEBHOOK_DATA, ATTR_WEBHOOK_ENCRYPTED, ATTR_WEBHOOK_ENCRYPTED_DATA, ATTR_WEBHOOK_TYPE, CONF_CLOUDHOOK_URL, CONF_REMOTE_UI_URL, CONF_SECRET, @@ -45,7 +38,7 @@ from .const import (ATTR_ALTITUDE, ATTR_BATTERY, ATTR_COURSE, ATTR_DEVICE_ID, WEBHOOK_TYPE_REGISTER_SENSOR, WEBHOOK_TYPE_RENDER_TEMPLATE, WEBHOOK_TYPE_UPDATE_LOCATION, WEBHOOK_TYPE_UPDATE_REGISTRATION, - WEBHOOK_TYPE_UPDATE_SENSOR_STATES) + WEBHOOK_TYPE_UPDATE_SENSOR_STATES, SIGNAL_LOCATION_UPDATE) from .helpers import (_decrypt_payload, empty_okay_response, error_response, @@ -151,37 +144,9 @@ async def handle_webhook(hass: HomeAssistantType, webhook_id: str, headers=headers) if webhook_type == WEBHOOK_TYPE_UPDATE_LOCATION: - see_payload = { - ATTR_DEV_ID: slugify(registration[ATTR_DEVICE_NAME]), - ATTR_GPS: data[ATTR_GPS], - ATTR_GPS_ACCURACY: data[ATTR_GPS_ACCURACY], - } - - for key in (ATTR_LOCATION_NAME, ATTR_BATTERY): - value = data.get(key) - if value is not None: - see_payload[key] = value - - attrs = {} - - for key in (ATTR_ALTITUDE, ATTR_COURSE, - ATTR_SPEED, ATTR_VERTICAL_ACCURACY): - value = data.get(key) - if value is not None: - attrs[key] = value - - if attrs: - see_payload[ATTR_ATTRIBUTES] = attrs - - try: - await hass.services.async_call(DT_DOMAIN, - DT_SEE, see_payload, - blocking=True, context=context) - # noqa: E722 pylint: disable=broad-except - except (vol.Invalid, ServiceNotFound, Exception) as ex: - _LOGGER.error("Error when updating location during mobile_app " - "webhook (device name: %s): %s", - registration[ATTR_DEVICE_NAME], ex) + hass.helpers.dispatcher.async_dispatcher_send( + SIGNAL_LOCATION_UPDATE.format(config_entry.entry_id), data + ) return empty_okay_response(headers=headers) if webhook_type == WEBHOOK_TYPE_UPDATE_REGISTRATION: diff --git a/tests/components/mobile_app/__init__.py b/tests/components/mobile_app/__init__.py index 98c7a20b059..9b37214d079 100644 --- a/tests/components/mobile_app/__init__.py +++ b/tests/components/mobile_app/__init__.py @@ -1,74 +1 @@ -"""Tests for mobile_app component.""" -# pylint: disable=redefined-outer-name,unused-import -import pytest - -from tests.common import mock_device_registry - -from homeassistant.setup import async_setup_component - -from homeassistant.components.mobile_app.const import (DATA_BINARY_SENSOR, - DATA_DELETED_IDS, - DATA_SENSOR, - DOMAIN, - STORAGE_KEY, - STORAGE_VERSION) - -from .const import REGISTER, REGISTER_CLEARTEXT - - -@pytest.fixture -def registry(hass): - """Return a configured device registry.""" - return mock_device_registry(hass) - - -@pytest.fixture -async def create_registrations(authed_api_client): - """Return two new registrations.""" - enc_reg = await authed_api_client.post( - '/api/mobile_app/registrations', json=REGISTER - ) - - assert enc_reg.status == 201 - enc_reg_json = await enc_reg.json() - - clear_reg = await authed_api_client.post( - '/api/mobile_app/registrations', json=REGISTER_CLEARTEXT - ) - - assert clear_reg.status == 201 - clear_reg_json = await clear_reg.json() - - return (enc_reg_json, clear_reg_json) - - -@pytest.fixture -async def webhook_client(hass, aiohttp_client, hass_storage, hass_admin_user): - """mobile_app mock client.""" - hass_storage[STORAGE_KEY] = { - 'version': STORAGE_VERSION, - 'data': { - DATA_BINARY_SENSOR: {}, - DATA_DELETED_IDS: [], - DATA_SENSOR: {} - } - } - - await async_setup_component(hass, DOMAIN, {DOMAIN: {}}) - await hass.async_block_till_done() - return await aiohttp_client(hass.http.app) - - -@pytest.fixture -async def authed_api_client(hass, hass_client): - """Provide an authenticated client for mobile_app to use.""" - await async_setup_component(hass, DOMAIN, {DOMAIN: {}}) - await hass.async_block_till_done() - return await hass_client() - - -@pytest.fixture(autouse=True) -async def setup_ws(hass): - """Configure the websocket_api component.""" - assert await async_setup_component(hass, 'websocket_api', {}) - await hass.async_block_till_done() +"""Tests for the mobile app integration.""" diff --git a/tests/components/mobile_app/conftest.py b/tests/components/mobile_app/conftest.py new file mode 100644 index 00000000000..b20d164e6e6 --- /dev/null +++ b/tests/components/mobile_app/conftest.py @@ -0,0 +1,60 @@ +"""Tests for mobile_app component.""" +# pylint: disable=redefined-outer-name,unused-import +import pytest + +from tests.common import mock_device_registry + +from homeassistant.setup import async_setup_component + +from homeassistant.components.mobile_app.const import DOMAIN + +from .const import REGISTER, REGISTER_CLEARTEXT + + +@pytest.fixture +def registry(hass): + """Return a configured device registry.""" + return mock_device_registry(hass) + + +@pytest.fixture +async def create_registrations(authed_api_client): + """Return two new registrations.""" + enc_reg = await authed_api_client.post( + '/api/mobile_app/registrations', json=REGISTER + ) + + assert enc_reg.status == 201 + enc_reg_json = await enc_reg.json() + + clear_reg = await authed_api_client.post( + '/api/mobile_app/registrations', json=REGISTER_CLEARTEXT + ) + + assert clear_reg.status == 201 + clear_reg_json = await clear_reg.json() + + return (enc_reg_json, clear_reg_json) + + +@pytest.fixture +async def webhook_client(hass, aiohttp_client): + """mobile_app mock client.""" + await async_setup_component(hass, DOMAIN, {DOMAIN: {}}) + await hass.async_block_till_done() + return await aiohttp_client(hass.http.app) + + +@pytest.fixture +async def authed_api_client(hass, hass_client): + """Provide an authenticated client for mobile_app to use.""" + await async_setup_component(hass, DOMAIN, {DOMAIN: {}}) + await hass.async_block_till_done() + return await hass_client() + + +@pytest.fixture(autouse=True) +async def setup_ws(hass): + """Configure the websocket_api component.""" + assert await async_setup_component(hass, 'websocket_api', {}) + await hass.async_block_till_done() diff --git a/tests/components/mobile_app/test_device_tracker.py b/tests/components/mobile_app/test_device_tracker.py new file mode 100644 index 00000000000..448bd9181c8 --- /dev/null +++ b/tests/components/mobile_app/test_device_tracker.py @@ -0,0 +1,68 @@ +"""Test mobile app device tracker.""" + + +async def test_sending_location(hass, create_registrations, webhook_client): + """Test sending a location via a webhook.""" + resp = await webhook_client.post( + '/api/webhook/{}'.format(create_registrations[1]['webhook_id']), + json={ + 'type': 'update_location', + 'data': { + 'gps': [10, 20], + 'gps_accuracy': 30, + 'battery': 40, + 'altitude': 50, + 'course': 60, + 'speed': 70, + 'vertical_accuracy': 80, + 'location_name': 'bar', + } + } + ) + + assert resp.status == 200 + await hass.async_block_till_done() + state = hass.states.get('device_tracker.test_1') + assert state is not None + assert state.name == 'Test 1' + assert state.state == 'bar' + assert state.attributes['source_type'] == 'gps' + assert state.attributes['latitude'] == 10 + assert state.attributes['longitude'] == 20 + assert state.attributes['gps_accuracy'] == 30 + assert state.attributes['battery_level'] == 40 + assert state.attributes['altitude'] == 50 + assert state.attributes['course'] == 60 + assert state.attributes['speed'] == 70 + assert state.attributes['vertical_accuracy'] == 80 + + resp = await webhook_client.post( + '/api/webhook/{}'.format(create_registrations[1]['webhook_id']), + json={ + 'type': 'update_location', + 'data': { + 'gps': [1, 2], + 'gps_accuracy': 3, + 'battery': 4, + 'altitude': 5, + 'course': 6, + 'speed': 7, + 'vertical_accuracy': 8, + } + } + ) + + assert resp.status == 200 + await hass.async_block_till_done() + state = hass.states.get('device_tracker.test_1') + assert state is not None + assert state.state == 'not_home' + assert state.attributes['source_type'] == 'gps' + assert state.attributes['latitude'] == 1 + assert state.attributes['longitude'] == 2 + assert state.attributes['gps_accuracy'] == 3 + assert state.attributes['battery_level'] == 4 + assert state.attributes['altitude'] == 5 + assert state.attributes['course'] == 6 + assert state.attributes['speed'] == 7 + assert state.attributes['vertical_accuracy'] == 8 diff --git a/tests/components/mobile_app/test_entity.py b/tests/components/mobile_app/test_entity.py index e98307468d1..750c346cbc3 100644 --- a/tests/components/mobile_app/test_entity.py +++ b/tests/components/mobile_app/test_entity.py @@ -2,9 +2,6 @@ # pylint: disable=redefined-outer-name,unused-import import logging -from . import (authed_api_client, create_registrations, # noqa: F401 - webhook_client) # noqa: F401 - _LOGGER = logging.getLogger(__name__) diff --git a/tests/components/mobile_app/test_http_api.py b/tests/components/mobile_app/test_http_api.py index dc51b850a16..80f01315f70 100644 --- a/tests/components/mobile_app/test_http_api.py +++ b/tests/components/mobile_app/test_http_api.py @@ -7,10 +7,9 @@ from homeassistant.const import CONF_WEBHOOK_ID from homeassistant.setup import async_setup_component from .const import REGISTER, RENDER_TEMPLATE -from . import authed_api_client # noqa: F401 -async def test_registration(hass, hass_client): # noqa: F811 +async def test_registration(hass, hass_client): """Test that registrations happen.""" try: # pylint: disable=unused-import diff --git a/tests/components/mobile_app/test_webhook.py b/tests/components/mobile_app/test_webhook.py index 43eac28ec18..cd5b0a5bbed 100644 --- a/tests/components/mobile_app/test_webhook.py +++ b/tests/components/mobile_app/test_webhook.py @@ -11,17 +11,14 @@ from homeassistant.setup import async_setup_component from tests.common import async_mock_service -from . import (authed_api_client, create_registrations, # noqa: F401 - webhook_client) # noqa: F401 - from .const import (CALL_SERVICE, FIRE_EVENT, REGISTER_CLEARTEXT, RENDER_TEMPLATE, UPDATE) _LOGGER = logging.getLogger(__name__) -async def test_webhook_handle_render_template(create_registrations, # noqa: F401, F811, E501 - webhook_client): # noqa: F811 +async def test_webhook_handle_render_template(create_registrations, + webhook_client): """Test that we render templates properly.""" resp = await webhook_client.post( '/api/webhook/{}'.format(create_registrations[1]['webhook_id']), @@ -34,7 +31,7 @@ async def test_webhook_handle_render_template(create_registrations, # noqa: F40 assert json == {'one': 'Hello world'} -async def test_webhook_handle_call_services(hass, create_registrations, # noqa: F401, F811, E501 +async def test_webhook_handle_call_services(hass, create_registrations, webhook_client): # noqa: E501 F811 """Test that we call services properly.""" calls = async_mock_service(hass, 'test', 'mobile_app') @@ -49,8 +46,8 @@ async def test_webhook_handle_call_services(hass, create_registrations, # noqa: assert len(calls) == 1 -async def test_webhook_handle_fire_event(hass, create_registrations, # noqa: F401, F811, E501 - webhook_client): # noqa: F811 +async def test_webhook_handle_fire_event(hass, create_registrations, + webhook_client): """Test that we can fire events.""" events = [] @@ -76,7 +73,7 @@ async def test_webhook_handle_fire_event(hass, create_registrations, # noqa: F4 async def test_webhook_update_registration(webhook_client, hass_client): # noqa: E501 F811 """Test that a we can update an existing registration via webhook.""" - authed_api_client = await hass_client() # noqa: F811 + authed_api_client = await hass_client() register_resp = await authed_api_client.post( '/api/mobile_app/registrations', json=REGISTER_CLEARTEXT ) @@ -102,8 +99,8 @@ async def test_webhook_update_registration(webhook_client, hass_client): # noqa assert CONF_SECRET not in update_json -async def test_webhook_handle_get_zones(hass, create_registrations, # noqa: F401, F811, E501 - webhook_client): # noqa: F811 +async def test_webhook_handle_get_zones(hass, create_registrations, + webhook_client): """Test that we can get zones properly.""" await async_setup_component(hass, ZONE_DOMAIN, { ZONE_DOMAIN: { @@ -126,8 +123,8 @@ async def test_webhook_handle_get_zones(hass, create_registrations, # noqa: F40 assert json[0]['entity_id'] == 'zone.home' -async def test_webhook_handle_get_config(hass, create_registrations, # noqa: F401, F811, E501 - webhook_client): # noqa: F811 +async def test_webhook_handle_get_config(hass, create_registrations, + webhook_client): """Test that we can get config properly.""" resp = await webhook_client.post( '/api/webhook/{}'.format(create_registrations[1]['webhook_id']), @@ -160,8 +157,8 @@ async def test_webhook_handle_get_config(hass, create_registrations, # noqa: F4 assert expected_dict == json -async def test_webhook_returns_error_incorrect_json(webhook_client, # noqa: F401, F811, E501 - create_registrations, # noqa: F401, F811, E501 +async def test_webhook_returns_error_incorrect_json(webhook_client, + create_registrations, caplog): # noqa: E501 F811 """Test that an error is returned when JSON is invalid.""" resp = await webhook_client.post( @@ -175,8 +172,8 @@ async def test_webhook_returns_error_incorrect_json(webhook_client, # noqa: F40 assert 'invalid JSON' in caplog.text -async def test_webhook_handle_decryption(webhook_client, # noqa: F811 - create_registrations): # noqa: F401, F811, E501 +async def test_webhook_handle_decryption(webhook_client, + create_registrations): """Test that we can encrypt/decrypt properly.""" try: # pylint: disable=unused-import @@ -221,8 +218,8 @@ async def test_webhook_handle_decryption(webhook_client, # noqa: F811 assert json.loads(decrypted_data) == {'one': 'Hello world'} -async def test_webhook_requires_encryption(webhook_client, # noqa: F811 - create_registrations): # noqa: F401, F811, E501 +async def test_webhook_requires_encryption(webhook_client, + create_registrations): """Test that encrypted registrations only accept encrypted data.""" resp = await webhook_client.post( '/api/webhook/{}'.format(create_registrations[0]['webhook_id']), diff --git a/tests/components/mobile_app/test_websocket_api.py b/tests/components/mobile_app/test_websocket_api.py index ee656159d2e..20676731393 100644 --- a/tests/components/mobile_app/test_websocket_api.py +++ b/tests/components/mobile_app/test_websocket_api.py @@ -5,7 +5,6 @@ from homeassistant.components.websocket_api.const import TYPE_RESULT from homeassistant.const import CONF_WEBHOOK_ID from homeassistant.setup import async_setup_component -from . import authed_api_client, setup_ws, webhook_client # noqa: F401 from .const import (CALL_SERVICE, REGISTER) @@ -45,7 +44,7 @@ async def test_webocket_get_user_registrations(hass, aiohttp_client, async def test_webocket_delete_registration(hass, hass_client, - hass_ws_client, webhook_client): # noqa: E501 F811 + hass_ws_client, webhook_client): """Test delete_registration websocket command.""" authed_api_client = await hass_client() # noqa: F811 register_resp = await authed_api_client.post(