Improve SmartThings test mocking (#25028)
* Migrate to asynctest * Simplify mock access * Use mocks
This commit is contained in:
parent
2fbbcafaed
commit
a31e49c857
5 changed files with 186 additions and 336 deletions
|
@ -1,12 +1,11 @@
|
|||
"""Test configuration and mocks for the SmartThings component."""
|
||||
from collections import defaultdict
|
||||
from unittest.mock import Mock, patch
|
||||
from uuid import uuid4
|
||||
|
||||
from asynctest import Mock, patch
|
||||
from pysmartthings import (
|
||||
CLASSIFICATION_AUTOMATION, AppEntity, AppOAuthClient, AppSettings,
|
||||
DeviceEntity, InstalledApp, Location, SceneEntity, SmartThings,
|
||||
Subscription)
|
||||
DeviceEntity, DeviceStatus, InstalledApp, InstalledAppStatus,
|
||||
InstalledAppType, Location, SceneEntity, SmartThings, Subscription)
|
||||
from pysmartthings.api import Api
|
||||
import pytest
|
||||
|
||||
|
@ -22,8 +21,6 @@ from homeassistant.config_entries import (
|
|||
from homeassistant.const import CONF_ACCESS_TOKEN, CONF_WEBHOOK_ID
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
||||
from tests.common import mock_coro
|
||||
|
||||
COMPONENT_PREFIX = "homeassistant.components.smartthings."
|
||||
|
||||
|
||||
|
@ -58,11 +55,9 @@ async def setup_component(hass, config_file, hass_storage):
|
|||
|
||||
|
||||
def _create_location():
|
||||
loc = Location()
|
||||
loc.apply_data({
|
||||
'name': 'Test Location',
|
||||
'locationId': str(uuid4())
|
||||
})
|
||||
loc = Mock(Location)
|
||||
loc.name = 'Test Location'
|
||||
loc.location_id = str(uuid4())
|
||||
return loc
|
||||
|
||||
|
||||
|
@ -81,58 +76,50 @@ def locations_fixture(location):
|
|||
@pytest.fixture(name="app")
|
||||
def app_fixture(hass, config_file):
|
||||
"""Fixture for a single app."""
|
||||
app = AppEntity(Mock())
|
||||
app.apply_data({
|
||||
'appName': APP_NAME_PREFIX + str(uuid4()),
|
||||
'appId': str(uuid4()),
|
||||
'appType': 'WEBHOOK_SMART_APP',
|
||||
'classifications': [CLASSIFICATION_AUTOMATION],
|
||||
'displayName': 'Home Assistant',
|
||||
'description':
|
||||
hass.config.location_name + " at " + hass.config.api.base_url,
|
||||
'singleInstance': True,
|
||||
'webhookSmartApp': {
|
||||
'targetUrl': webhook.async_generate_url(
|
||||
hass, hass.data[DOMAIN][CONF_WEBHOOK_ID]),
|
||||
'publicKey': ''}
|
||||
})
|
||||
app.refresh = Mock()
|
||||
app.refresh.return_value = mock_coro()
|
||||
app.save = Mock()
|
||||
app.save.return_value = mock_coro()
|
||||
settings = AppSettings(app.app_id)
|
||||
settings.settings[SETTINGS_INSTANCE_ID] = config_file[CONF_INSTANCE_ID]
|
||||
app.settings = Mock()
|
||||
app.settings.return_value = mock_coro(return_value=settings)
|
||||
app = Mock(AppEntity)
|
||||
app.app_name = APP_NAME_PREFIX + str(uuid4())
|
||||
app.app_id = str(uuid4())
|
||||
app.app_type = 'WEBHOOK_SMART_APP'
|
||||
app.classifications = [CLASSIFICATION_AUTOMATION]
|
||||
app.display_name = 'Home Assistant'
|
||||
app.description = hass.config.location_name + " at " + \
|
||||
hass.config.api.base_url
|
||||
app.single_instance = True
|
||||
app.webhook_target_url = webhook.async_generate_url(
|
||||
hass, hass.data[DOMAIN][CONF_WEBHOOK_ID])
|
||||
|
||||
settings = Mock(AppSettings)
|
||||
settings.app_id = app.app_id
|
||||
settings.settings = {SETTINGS_INSTANCE_ID: config_file[CONF_INSTANCE_ID]}
|
||||
app.settings.return_value = settings
|
||||
return app
|
||||
|
||||
|
||||
@pytest.fixture(name="app_oauth_client")
|
||||
def app_oauth_client_fixture():
|
||||
"""Fixture for a single app's oauth."""
|
||||
return AppOAuthClient({
|
||||
'oauthClientId': str(uuid4()),
|
||||
'oauthClientSecret': str(uuid4())
|
||||
})
|
||||
client = Mock(AppOAuthClient)
|
||||
client.client_id = str(uuid4())
|
||||
client.client_secret = str(uuid4())
|
||||
return client
|
||||
|
||||
|
||||
@pytest.fixture(name='app_settings')
|
||||
def app_settings_fixture(app, config_file):
|
||||
"""Fixture for an app settings."""
|
||||
settings = AppSettings(app.app_id)
|
||||
settings.settings[SETTINGS_INSTANCE_ID] = config_file[CONF_INSTANCE_ID]
|
||||
settings = Mock(AppSettings)
|
||||
settings.app_id = app.app_id
|
||||
settings.settings = {SETTINGS_INSTANCE_ID: config_file[CONF_INSTANCE_ID]}
|
||||
return settings
|
||||
|
||||
|
||||
def _create_installed_app(location_id, app_id):
|
||||
item = InstalledApp()
|
||||
item.apply_data(defaultdict(str, {
|
||||
'installedAppId': str(uuid4()),
|
||||
'installedAppStatus': 'AUTHORIZED',
|
||||
'installedAppType': 'UNKNOWN',
|
||||
'appId': app_id,
|
||||
'locationId': location_id
|
||||
}))
|
||||
item = Mock(InstalledApp)
|
||||
item.installed_app_id = str(uuid4())
|
||||
item.installed_app_status = InstalledAppStatus.AUTHORIZED
|
||||
item.installed_app_type = InstalledAppType.WEBHOOK_SMART_APP
|
||||
item.app_id = app_id
|
||||
item.location_id = location_id
|
||||
return item
|
||||
|
||||
|
||||
|
@ -161,10 +148,9 @@ def config_file_fixture():
|
|||
@pytest.fixture(name='smartthings_mock')
|
||||
def smartthings_mock_fixture(locations):
|
||||
"""Fixture to mock smartthings API calls."""
|
||||
def _location(location_id):
|
||||
return mock_coro(
|
||||
return_value=next(location for location in locations
|
||||
if location.location_id == location_id))
|
||||
async def _location(location_id):
|
||||
return next(location for location in locations
|
||||
if location.location_id == location_id)
|
||||
|
||||
smartthings_mock = Mock(SmartThings)
|
||||
smartthings_mock.location.side_effect = _location
|
||||
|
@ -172,71 +158,23 @@ def smartthings_mock_fixture(locations):
|
|||
with patch(COMPONENT_PREFIX + "SmartThings", new=mock), \
|
||||
patch(COMPONENT_PREFIX + "config_flow.SmartThings", new=mock), \
|
||||
patch(COMPONENT_PREFIX + "smartapp.SmartThings", new=mock):
|
||||
yield mock
|
||||
yield smartthings_mock
|
||||
|
||||
|
||||
@pytest.fixture(name='device')
|
||||
def device_fixture(location):
|
||||
"""Fixture representing devices loaded."""
|
||||
item = DeviceEntity(None)
|
||||
item.status.refresh = Mock()
|
||||
item.status.refresh.return_value = mock_coro()
|
||||
item.apply_data({
|
||||
"deviceId": "743de49f-036f-4e9c-839a-2f89d57607db",
|
||||
"name": "GE In-Wall Smart Dimmer",
|
||||
"label": "Front Porch Lights",
|
||||
"deviceManufacturerCode": "0063-4944-3038",
|
||||
"locationId": location.location_id,
|
||||
"deviceTypeId": "8a9d4b1e3b9b1fe3013b9b206a7f000d",
|
||||
"deviceTypeName": "Dimmer Switch",
|
||||
"deviceNetworkType": "ZWAVE",
|
||||
"components": [
|
||||
{
|
||||
"id": "main",
|
||||
"capabilities": [
|
||||
{
|
||||
"id": "switch",
|
||||
"version": 1
|
||||
},
|
||||
{
|
||||
"id": "switchLevel",
|
||||
"version": 1
|
||||
},
|
||||
{
|
||||
"id": "refresh",
|
||||
"version": 1
|
||||
},
|
||||
{
|
||||
"id": "indicator",
|
||||
"version": 1
|
||||
},
|
||||
{
|
||||
"id": "sensor",
|
||||
"version": 1
|
||||
},
|
||||
{
|
||||
"id": "actuator",
|
||||
"version": 1
|
||||
},
|
||||
{
|
||||
"id": "healthCheck",
|
||||
"version": 1
|
||||
},
|
||||
{
|
||||
"id": "light",
|
||||
"version": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"dth": {
|
||||
"deviceTypeId": "8a9d4b1e3b9b1fe3013b9b206a7f000d",
|
||||
"deviceTypeName": "Dimmer Switch",
|
||||
"deviceNetworkType": "ZWAVE",
|
||||
"completedSetup": False
|
||||
},
|
||||
"type": "DTH"
|
||||
})
|
||||
item = Mock(DeviceEntity)
|
||||
item.device_id = "743de49f-036f-4e9c-839a-2f89d57607db"
|
||||
item.name = "GE In-Wall Smart Dimmer"
|
||||
item.label = "Front Porch Lights"
|
||||
item.location_id = location.location_id
|
||||
item.capabilities = [
|
||||
"switch", "switchLevel", "refresh", "indicator", "sensor", "actuator",
|
||||
"healthCheck", "light"
|
||||
]
|
||||
item.components = {"main": item.capabilities}
|
||||
item.status = Mock(DeviceStatus)
|
||||
return item
|
||||
|
||||
|
||||
|
@ -269,9 +207,8 @@ def subscription_factory_fixture():
|
|||
@pytest.fixture(name="device_factory")
|
||||
def device_factory_fixture():
|
||||
"""Fixture for creating mock devices."""
|
||||
api = Mock(spec=Api)
|
||||
api.post_device_command.side_effect = \
|
||||
lambda *args, **kwargs: mock_coro(return_value={})
|
||||
api = Mock(Api)
|
||||
api.post_device_command.return_value = {}
|
||||
|
||||
def _factory(label, capabilities, status: dict = None):
|
||||
device_data = {
|
||||
|
@ -308,19 +245,12 @@ def device_factory_fixture():
|
|||
@pytest.fixture(name="scene_factory")
|
||||
def scene_factory_fixture(location):
|
||||
"""Fixture for creating mock devices."""
|
||||
api = Mock(spec=Api)
|
||||
api.execute_scene.side_effect = \
|
||||
lambda *args, **kwargs: mock_coro(return_value={})
|
||||
|
||||
def _factory(name):
|
||||
scene_data = {
|
||||
'sceneId': str(uuid4()),
|
||||
'sceneName': name,
|
||||
'sceneIcon': '',
|
||||
'sceneColor': '',
|
||||
'locationId': location.location_id
|
||||
}
|
||||
return SceneEntity(api, scene_data)
|
||||
scene = Mock(SceneEntity)
|
||||
scene.scene_id = str(uuid4())
|
||||
scene.name = name
|
||||
scene.location_id = location.location_id
|
||||
return scene
|
||||
return _factory
|
||||
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
"""Tests for the SmartThings config flow module."""
|
||||
from unittest.mock import Mock, patch
|
||||
from uuid import uuid4
|
||||
|
||||
from aiohttp import ClientResponseError
|
||||
from asynctest import Mock, patch
|
||||
from pysmartthings import APIResponseError
|
||||
|
||||
from homeassistant import data_entry_flow
|
||||
|
@ -15,8 +15,6 @@ from homeassistant.components.smartthings.const import (
|
|||
CONF_REFRESH_TOKEN, DOMAIN)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
|
||||
from tests.common import mock_coro
|
||||
|
||||
|
||||
async def test_step_user(hass):
|
||||
"""Test the access token form is shown for a user initiated flow."""
|
||||
|
@ -84,8 +82,8 @@ async def test_token_unauthorized(hass, smartthings_mock):
|
|||
flow = SmartThingsFlowHandler()
|
||||
flow.hass = hass
|
||||
|
||||
smartthings_mock.return_value.apps.return_value = mock_coro(
|
||||
exception=ClientResponseError(None, None, status=401))
|
||||
smartthings_mock.apps.side_effect = \
|
||||
ClientResponseError(None, None, status=401)
|
||||
|
||||
result = await flow.async_step_user({'access_token': str(uuid4())})
|
||||
|
||||
|
@ -99,8 +97,8 @@ async def test_token_forbidden(hass, smartthings_mock):
|
|||
flow = SmartThingsFlowHandler()
|
||||
flow.hass = hass
|
||||
|
||||
smartthings_mock.return_value.apps.return_value = mock_coro(
|
||||
exception=ClientResponseError(None, None, status=403))
|
||||
smartthings_mock.apps.side_effect = \
|
||||
ClientResponseError(None, None, status=403)
|
||||
|
||||
result = await flow.async_step_user({'access_token': str(uuid4())})
|
||||
|
||||
|
@ -118,8 +116,7 @@ async def test_webhook_error(hass, smartthings_mock):
|
|||
error = APIResponseError(None, None, data=data, status=422)
|
||||
error.is_target_error = Mock(return_value=True)
|
||||
|
||||
smartthings_mock.return_value.apps.return_value = mock_coro(
|
||||
exception=error)
|
||||
smartthings_mock.apps.side_effect = error
|
||||
|
||||
result = await flow.async_step_user({'access_token': str(uuid4())})
|
||||
|
||||
|
@ -136,8 +133,7 @@ async def test_api_error(hass, smartthings_mock):
|
|||
data = {'error': {}}
|
||||
error = APIResponseError(None, None, data=data, status=400)
|
||||
|
||||
smartthings_mock.return_value.apps.return_value = mock_coro(
|
||||
exception=error)
|
||||
smartthings_mock.apps.side_effect = error
|
||||
|
||||
result = await flow.async_step_user({'access_token': str(uuid4())})
|
||||
|
||||
|
@ -151,8 +147,8 @@ async def test_unknown_api_error(hass, smartthings_mock):
|
|||
flow = SmartThingsFlowHandler()
|
||||
flow.hass = hass
|
||||
|
||||
smartthings_mock.return_value.apps.return_value = mock_coro(
|
||||
exception=ClientResponseError(None, None, status=404))
|
||||
smartthings_mock.apps.side_effect = \
|
||||
ClientResponseError(None, None, status=404)
|
||||
|
||||
result = await flow.async_step_user({'access_token': str(uuid4())})
|
||||
|
||||
|
@ -166,8 +162,7 @@ async def test_unknown_error(hass, smartthings_mock):
|
|||
flow = SmartThingsFlowHandler()
|
||||
flow.hass = hass
|
||||
|
||||
smartthings_mock.return_value.apps.return_value = mock_coro(
|
||||
exception=Exception('Unknown error'))
|
||||
smartthings_mock.apps.side_effect = Exception('Unknown error')
|
||||
|
||||
result = await flow.async_step_user({'access_token': str(uuid4())})
|
||||
|
||||
|
@ -182,12 +177,8 @@ async def test_app_created_then_show_wait_form(
|
|||
flow = SmartThingsFlowHandler()
|
||||
flow.hass = hass
|
||||
|
||||
smartthings = smartthings_mock.return_value
|
||||
smartthings.apps.return_value = mock_coro(return_value=[])
|
||||
smartthings.create_app.return_value = \
|
||||
mock_coro(return_value=(app, app_oauth_client))
|
||||
smartthings.update_app_settings.return_value = mock_coro()
|
||||
smartthings.update_app_oauth.return_value = mock_coro()
|
||||
smartthings_mock.apps.return_value = []
|
||||
smartthings_mock.create_app.return_value = (app, app_oauth_client)
|
||||
|
||||
result = await flow.async_step_user({'access_token': str(uuid4())})
|
||||
|
||||
|
@ -201,24 +192,17 @@ async def test_cloudhook_app_created_then_show_wait_form(
|
|||
# Unload the endpoint so we can reload it under the cloud.
|
||||
await smartapp.unload_smartapp_endpoint(hass)
|
||||
|
||||
mock_async_active_subscription = Mock(return_value=True)
|
||||
mock_create_cloudhook = Mock(return_value=mock_coro(
|
||||
return_value="http://cloud.test"))
|
||||
with patch.object(cloud, 'async_active_subscription',
|
||||
new=mock_async_active_subscription), \
|
||||
patch.object(cloud, 'async_create_cloudhook',
|
||||
new=mock_create_cloudhook):
|
||||
with patch.object(cloud, 'async_active_subscription', return_value=True), \
|
||||
patch.object(
|
||||
cloud, 'async_create_cloudhook',
|
||||
return_value='http://cloud.test') as mock_create_cloudhook:
|
||||
|
||||
await smartapp.setup_smartapp_endpoint(hass)
|
||||
|
||||
flow = SmartThingsFlowHandler()
|
||||
flow.hass = hass
|
||||
smartthings = smartthings_mock.return_value
|
||||
smartthings.apps.return_value = mock_coro(return_value=[])
|
||||
smartthings.create_app.return_value = \
|
||||
mock_coro(return_value=(app, app_oauth_client))
|
||||
smartthings.update_app_settings.return_value = mock_coro()
|
||||
smartthings.update_app_oauth.return_value = mock_coro()
|
||||
smartthings_mock.apps.return_value = []
|
||||
smartthings_mock.create_app.return_value = (app, app_oauth_client)
|
||||
|
||||
result = await flow.async_step_user({'access_token': str(uuid4())})
|
||||
|
||||
|
@ -233,10 +217,8 @@ async def test_app_updated_then_show_wait_form(
|
|||
flow = SmartThingsFlowHandler()
|
||||
flow.hass = hass
|
||||
|
||||
api = smartthings_mock.return_value
|
||||
api.apps.return_value = mock_coro(return_value=[app])
|
||||
api.generate_app_oauth.return_value = \
|
||||
mock_coro(return_value=app_oauth_client)
|
||||
smartthings_mock.apps.return_value = [app]
|
||||
smartthings_mock.generate_app_oauth.return_value = app_oauth_client
|
||||
|
||||
result = await flow.async_step_user({'access_token': str(uuid4())})
|
||||
|
||||
|
@ -275,7 +257,7 @@ async def test_config_entry_created_when_installed(
|
|||
flow.hass = hass
|
||||
flow.access_token = str(uuid4())
|
||||
flow.app_id = installed_app.app_id
|
||||
flow.api = smartthings_mock.return_value
|
||||
flow.api = smartthings_mock
|
||||
flow.oauth_client_id = str(uuid4())
|
||||
flow.oauth_client_secret = str(uuid4())
|
||||
data = {
|
||||
|
@ -307,7 +289,7 @@ async def test_multiple_config_entry_created_when_installed(
|
|||
flow.hass = hass
|
||||
flow.access_token = str(uuid4())
|
||||
flow.app_id = app.app_id
|
||||
flow.api = smartthings_mock.return_value
|
||||
flow.api = smartthings_mock
|
||||
flow.oauth_client_id = str(uuid4())
|
||||
flow.oauth_client_secret = str(uuid4())
|
||||
for installed_app in installed_apps:
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
"""Tests for the SmartThings component init module."""
|
||||
from unittest.mock import Mock, patch
|
||||
from uuid import uuid4
|
||||
|
||||
from aiohttp import ClientConnectionError, ClientResponseError
|
||||
from pysmartthings import InstalledAppStatus
|
||||
from asynctest import Mock, patch
|
||||
from pysmartthings import InstalledAppStatus, OAuthToken
|
||||
import pytest
|
||||
|
||||
from homeassistant.components import cloud, smartthings
|
||||
|
@ -14,7 +14,7 @@ from homeassistant.components.smartthings.const import (
|
|||
from homeassistant.exceptions import ConfigEntryNotReady
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||
|
||||
from tests.common import MockConfigEntry, mock_coro
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
|
||||
async def test_migration_creates_new_flow(
|
||||
|
@ -22,15 +22,12 @@ async def test_migration_creates_new_flow(
|
|||
"""Test migration deletes app and creates new flow."""
|
||||
config_entry.version = 1
|
||||
setattr(hass.config_entries, '_entries', [config_entry])
|
||||
api = smartthings_mock.return_value
|
||||
api.delete_installed_app.side_effect = lambda _: mock_coro()
|
||||
api.delete_app.side_effect = lambda _: mock_coro()
|
||||
|
||||
await smartthings.async_migrate_entry(hass, config_entry)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert api.delete_installed_app.call_count == 1
|
||||
assert api.delete_app.call_count == 1
|
||||
assert smartthings_mock.delete_installed_app.call_count == 1
|
||||
assert smartthings_mock.delete_app.call_count == 1
|
||||
assert not hass.config_entries.async_entries(DOMAIN)
|
||||
flows = hass.config_entries.flow.async_progress()
|
||||
assert len(flows) == 1
|
||||
|
@ -47,34 +44,30 @@ async def test_unrecoverable_api_errors_create_new_flow(
|
|||
403 (forbidden/not found): Occurs when the app or installed app could
|
||||
not be retrieved/found (likely deleted?)
|
||||
"""
|
||||
api = smartthings_mock.return_value
|
||||
for error_status in (401, 403):
|
||||
setattr(hass.config_entries, '_entries', [config_entry])
|
||||
api.app.return_value = mock_coro(
|
||||
exception=ClientResponseError(None, None,
|
||||
status=error_status))
|
||||
setattr(hass.config_entries, '_entries', [config_entry])
|
||||
smartthings_mock.app.side_effect = \
|
||||
ClientResponseError(None, None, status=401)
|
||||
|
||||
# Assert setup returns false
|
||||
result = await smartthings.async_setup_entry(hass, config_entry)
|
||||
assert not result
|
||||
# Assert setup returns false
|
||||
result = await smartthings.async_setup_entry(hass, config_entry)
|
||||
assert not result
|
||||
|
||||
# Assert entry was removed and new flow created
|
||||
await hass.async_block_till_done()
|
||||
assert not hass.config_entries.async_entries(DOMAIN)
|
||||
flows = hass.config_entries.flow.async_progress()
|
||||
assert len(flows) == 1
|
||||
assert flows[0]['handler'] == 'smartthings'
|
||||
assert flows[0]['context'] == {'source': 'import'}
|
||||
hass.config_entries.flow.async_abort(flows[0]['flow_id'])
|
||||
# Assert entry was removed and new flow created
|
||||
await hass.async_block_till_done()
|
||||
assert not hass.config_entries.async_entries(DOMAIN)
|
||||
flows = hass.config_entries.flow.async_progress()
|
||||
assert len(flows) == 1
|
||||
assert flows[0]['handler'] == 'smartthings'
|
||||
assert flows[0]['context'] == {'source': 'import'}
|
||||
hass.config_entries.flow.async_abort(flows[0]['flow_id'])
|
||||
|
||||
|
||||
async def test_recoverable_api_errors_raise_not_ready(
|
||||
hass, config_entry, smartthings_mock):
|
||||
"""Test config entry not ready raised for recoverable API errors."""
|
||||
setattr(hass.config_entries, '_entries', [config_entry])
|
||||
api = smartthings_mock.return_value
|
||||
api.app.return_value = mock_coro(
|
||||
exception=ClientResponseError(None, None, status=500))
|
||||
smartthings_mock.app.side_effect = \
|
||||
ClientResponseError(None, None, status=500)
|
||||
|
||||
with pytest.raises(ConfigEntryNotReady):
|
||||
await smartthings.async_setup_entry(hass, config_entry)
|
||||
|
@ -84,11 +77,10 @@ async def test_scenes_api_errors_raise_not_ready(
|
|||
hass, config_entry, app, installed_app, smartthings_mock):
|
||||
"""Test if scenes are unauthorized we continue to load platforms."""
|
||||
setattr(hass.config_entries, '_entries', [config_entry])
|
||||
api = smartthings_mock.return_value
|
||||
api.app.return_value = mock_coro(return_value=app)
|
||||
api.installed_app.return_value = mock_coro(return_value=installed_app)
|
||||
api.scenes.return_value = mock_coro(
|
||||
exception=ClientResponseError(None, None, status=500))
|
||||
smartthings_mock.app.return_value = app
|
||||
smartthings_mock.installed_app.return_value = installed_app
|
||||
smartthings_mock.scenes.side_effect = \
|
||||
ClientResponseError(None, None, status=500)
|
||||
with pytest.raises(ConfigEntryNotReady):
|
||||
await smartthings.async_setup_entry(hass, config_entry)
|
||||
|
||||
|
@ -97,9 +89,7 @@ async def test_connection_errors_raise_not_ready(
|
|||
hass, config_entry, smartthings_mock):
|
||||
"""Test config entry not ready raised for connection errors."""
|
||||
setattr(hass.config_entries, '_entries', [config_entry])
|
||||
api = smartthings_mock.return_value
|
||||
api.app.return_value = mock_coro(
|
||||
exception=ClientConnectionError())
|
||||
smartthings_mock.app.side_effect = ClientConnectionError()
|
||||
|
||||
with pytest.raises(ConfigEntryNotReady):
|
||||
await smartthings.async_setup_entry(hass, config_entry)
|
||||
|
@ -110,8 +100,7 @@ async def test_base_url_no_longer_https_does_not_load(
|
|||
"""Test base_url no longer valid creates a new flow."""
|
||||
hass.config.api.base_url = 'http://0.0.0.0'
|
||||
setattr(hass.config_entries, '_entries', [config_entry])
|
||||
api = smartthings_mock.return_value
|
||||
api.app.return_value = mock_coro(return_value=app)
|
||||
smartthings_mock.app.return_value = app
|
||||
|
||||
# Assert setup returns false
|
||||
result = await smartthings.async_setup_entry(hass, config_entry)
|
||||
|
@ -123,12 +112,10 @@ async def test_unauthorized_installed_app_raises_not_ready(
|
|||
smartthings_mock):
|
||||
"""Test config entry not ready raised when the app isn't authorized."""
|
||||
setattr(hass.config_entries, '_entries', [config_entry])
|
||||
setattr(installed_app, '_installed_app_status',
|
||||
InstalledAppStatus.PENDING)
|
||||
installed_app.installed_app_status = InstalledAppStatus.PENDING
|
||||
|
||||
api = smartthings_mock.return_value
|
||||
api.app.return_value = mock_coro(return_value=app)
|
||||
api.installed_app.return_value = mock_coro(return_value=installed_app)
|
||||
smartthings_mock.app.return_value = app
|
||||
smartthings_mock.installed_app.return_value = installed_app
|
||||
|
||||
with pytest.raises(ConfigEntryNotReady):
|
||||
await smartthings.async_setup_entry(hass, config_entry)
|
||||
|
@ -139,23 +126,21 @@ async def test_scenes_unauthorized_loads_platforms(
|
|||
device, smartthings_mock, subscription_factory):
|
||||
"""Test if scenes are unauthorized we continue to load platforms."""
|
||||
setattr(hass.config_entries, '_entries', [config_entry])
|
||||
api = smartthings_mock.return_value
|
||||
api.app.return_value = mock_coro(return_value=app)
|
||||
api.installed_app.return_value = mock_coro(return_value=installed_app)
|
||||
api.devices.side_effect = \
|
||||
lambda *args, **kwargs: mock_coro(return_value=[device])
|
||||
api.scenes.return_value = mock_coro(
|
||||
exception=ClientResponseError(None, None, status=403))
|
||||
smartthings_mock.app.return_value = app
|
||||
smartthings_mock.installed_app.return_value = installed_app
|
||||
smartthings_mock.devices.return_value = [device]
|
||||
smartthings_mock.scenes.side_effect = \
|
||||
ClientResponseError(None, None, status=403)
|
||||
mock_token = Mock()
|
||||
mock_token.access_token.return_value = str(uuid4())
|
||||
mock_token.refresh_token.return_value = str(uuid4())
|
||||
api.generate_tokens.return_value = mock_coro(return_value=mock_token)
|
||||
smartthings_mock.generate_tokens.return_value = mock_token
|
||||
subscriptions = [subscription_factory(capability)
|
||||
for capability in device.capabilities]
|
||||
api.subscriptions.return_value = mock_coro(return_value=subscriptions)
|
||||
smartthings_mock.subscriptions.return_value = subscriptions
|
||||
|
||||
with patch.object(hass.config_entries, 'async_forward_entry_setup',
|
||||
return_value=mock_coro()) as forward_mock:
|
||||
with patch.object(hass.config_entries,
|
||||
'async_forward_entry_setup') as forward_mock:
|
||||
assert await smartthings.async_setup_entry(hass, config_entry)
|
||||
# Assert platforms loaded
|
||||
await hass.async_block_till_done()
|
||||
|
@ -167,22 +152,20 @@ async def test_config_entry_loads_platforms(
|
|||
device, smartthings_mock, subscription_factory, scene):
|
||||
"""Test config entry loads properly and proxies to platforms."""
|
||||
setattr(hass.config_entries, '_entries', [config_entry])
|
||||
api = smartthings_mock.return_value
|
||||
api.app.return_value = mock_coro(return_value=app)
|
||||
api.installed_app.return_value = mock_coro(return_value=installed_app)
|
||||
api.devices.side_effect = \
|
||||
lambda *args, **kwargs: mock_coro(return_value=[device])
|
||||
api.scenes.return_value = mock_coro(return_value=[scene])
|
||||
smartthings_mock.app.return_value = app
|
||||
smartthings_mock.installed_app.return_value = installed_app
|
||||
smartthings_mock.devices.return_value = [device]
|
||||
smartthings_mock.scenes.return_value = [scene]
|
||||
mock_token = Mock()
|
||||
mock_token.access_token.return_value = str(uuid4())
|
||||
mock_token.refresh_token.return_value = str(uuid4())
|
||||
api.generate_tokens.return_value = mock_coro(return_value=mock_token)
|
||||
smartthings_mock.generate_tokens.return_value = mock_token
|
||||
subscriptions = [subscription_factory(capability)
|
||||
for capability in device.capabilities]
|
||||
api.subscriptions.return_value = mock_coro(return_value=subscriptions)
|
||||
smartthings_mock.subscriptions.return_value = subscriptions
|
||||
|
||||
with patch.object(hass.config_entries, 'async_forward_entry_setup',
|
||||
return_value=mock_coro()) as forward_mock:
|
||||
with patch.object(hass.config_entries,
|
||||
'async_forward_entry_setup') as forward_mock:
|
||||
assert await smartthings.async_setup_entry(hass, config_entry)
|
||||
# Assert platforms loaded
|
||||
await hass.async_block_till_done()
|
||||
|
@ -196,21 +179,19 @@ async def test_config_entry_loads_unconnected_cloud(
|
|||
setattr(hass.config_entries, '_entries', [config_entry])
|
||||
hass.data[DOMAIN][CONF_CLOUDHOOK_URL] = "https://test.cloud"
|
||||
hass.config.api.base_url = 'http://0.0.0.0'
|
||||
api = smartthings_mock.return_value
|
||||
api.app.return_value = mock_coro(return_value=app)
|
||||
api.installed_app.return_value = mock_coro(return_value=installed_app)
|
||||
api.devices.side_effect = \
|
||||
lambda *args, **kwargs: mock_coro(return_value=[device])
|
||||
api.scenes.return_value = mock_coro(return_value=[scene])
|
||||
smartthings_mock.app.return_value = app
|
||||
smartthings_mock.installed_app.return_value = installed_app
|
||||
smartthings_mock.devices.return_value = [device]
|
||||
smartthings_mock.scenes.return_value = [scene]
|
||||
mock_token = Mock()
|
||||
mock_token.access_token.return_value = str(uuid4())
|
||||
mock_token.refresh_token.return_value = str(uuid4())
|
||||
api.generate_tokens.return_value = mock_coro(return_value=mock_token)
|
||||
smartthings_mock.generate_tokens.return_value = mock_token
|
||||
subscriptions = [subscription_factory(capability)
|
||||
for capability in device.capabilities]
|
||||
api.subscriptions.return_value = mock_coro(return_value=subscriptions)
|
||||
with patch.object(hass.config_entries, 'async_forward_entry_setup',
|
||||
return_value=mock_coro()) as forward_mock:
|
||||
smartthings_mock.subscriptions.return_value = subscriptions
|
||||
with patch.object(
|
||||
hass.config_entries, 'async_forward_entry_setup') as forward_mock:
|
||||
assert await smartthings.async_setup_entry(hass, config_entry)
|
||||
await hass.async_block_till_done()
|
||||
assert forward_mock.call_count == len(SUPPORTED_PLATFORMS)
|
||||
|
@ -227,9 +208,7 @@ async def test_unload_entry(hass, config_entry):
|
|||
hass.data[DOMAIN][DATA_BROKERS][config_entry.entry_id] = broker
|
||||
|
||||
with patch.object(hass.config_entries, 'async_forward_entry_unload',
|
||||
return_value=mock_coro(
|
||||
return_value=True
|
||||
)) as forward_mock:
|
||||
return_value=True) as forward_mock:
|
||||
assert await smartthings.async_unload_entry(hass, config_entry)
|
||||
|
||||
assert connect_disconnect.call_count == 1
|
||||
|
@ -241,15 +220,11 @@ async def test_unload_entry(hass, config_entry):
|
|||
|
||||
async def test_remove_entry(hass, config_entry, smartthings_mock):
|
||||
"""Test that the installed app and app are removed up."""
|
||||
# Arrange
|
||||
api = smartthings_mock.return_value
|
||||
api.delete_installed_app.side_effect = lambda _: mock_coro()
|
||||
api.delete_app.side_effect = lambda _: mock_coro()
|
||||
# Act
|
||||
await smartthings.async_remove_entry(hass, config_entry)
|
||||
# Assert
|
||||
assert api.delete_installed_app.call_count == 1
|
||||
assert api.delete_app.call_count == 1
|
||||
assert smartthings_mock.delete_installed_app.call_count == 1
|
||||
assert smartthings_mock.delete_app.call_count == 1
|
||||
|
||||
|
||||
async def test_remove_entry_cloudhook(hass, config_entry, smartthings_mock):
|
||||
|
@ -257,20 +232,15 @@ async def test_remove_entry_cloudhook(hass, config_entry, smartthings_mock):
|
|||
# Arrange
|
||||
setattr(hass.config_entries, '_entries', [config_entry])
|
||||
hass.data[DOMAIN][CONF_CLOUDHOOK_URL] = "https://test.cloud"
|
||||
api = smartthings_mock.return_value
|
||||
api.delete_installed_app.side_effect = lambda _: mock_coro()
|
||||
api.delete_app.side_effect = lambda _: mock_coro()
|
||||
mock_async_is_logged_in = Mock(return_value=True)
|
||||
mock_async_delete_cloudhook = Mock(return_value=mock_coro())
|
||||
# Act
|
||||
with patch.object(cloud, 'async_is_logged_in',
|
||||
new=mock_async_is_logged_in), \
|
||||
patch.object(cloud, 'async_delete_cloudhook',
|
||||
new=mock_async_delete_cloudhook):
|
||||
return_value=True) as mock_async_is_logged_in, \
|
||||
patch.object(cloud, 'async_delete_cloudhook') \
|
||||
as mock_async_delete_cloudhook:
|
||||
await smartthings.async_remove_entry(hass, config_entry)
|
||||
# Assert
|
||||
assert api.delete_installed_app.call_count == 1
|
||||
assert api.delete_app.call_count == 1
|
||||
assert smartthings_mock.delete_installed_app.call_count == 1
|
||||
assert smartthings_mock.delete_app.call_count == 1
|
||||
assert mock_async_is_logged_in.call_count == 1
|
||||
assert mock_async_delete_cloudhook.call_count == 1
|
||||
|
||||
|
@ -282,99 +252,87 @@ async def test_remove_entry_app_in_use(hass, config_entry, smartthings_mock):
|
|||
data[CONF_INSTALLED_APP_ID] = str(uuid4())
|
||||
entry2 = MockConfigEntry(version=2, domain=DOMAIN, data=data)
|
||||
setattr(hass.config_entries, '_entries', [config_entry, entry2])
|
||||
api = smartthings_mock.return_value
|
||||
api.delete_installed_app.side_effect = lambda _: mock_coro()
|
||||
# Act
|
||||
await smartthings.async_remove_entry(hass, config_entry)
|
||||
# Assert
|
||||
assert api.delete_installed_app.call_count == 1
|
||||
assert api.delete_app.call_count == 0
|
||||
assert smartthings_mock.delete_installed_app.call_count == 1
|
||||
assert smartthings_mock.delete_app.call_count == 0
|
||||
|
||||
|
||||
async def test_remove_entry_already_deleted(
|
||||
hass, config_entry, smartthings_mock):
|
||||
"""Test handles when the apps have already been removed."""
|
||||
# Arrange
|
||||
api = smartthings_mock.return_value
|
||||
api.delete_installed_app.side_effect = lambda _: mock_coro(
|
||||
exception=ClientResponseError(None, None, status=403))
|
||||
api.delete_app.side_effect = lambda _: mock_coro(
|
||||
exception=ClientResponseError(None, None, status=403))
|
||||
smartthings_mock.delete_installed_app.side_effect = ClientResponseError(
|
||||
None, None, status=403)
|
||||
smartthings_mock.delete_app.side_effect = ClientResponseError(
|
||||
None, None, status=403)
|
||||
# Act
|
||||
await smartthings.async_remove_entry(hass, config_entry)
|
||||
# Assert
|
||||
assert api.delete_installed_app.call_count == 1
|
||||
assert api.delete_app.call_count == 1
|
||||
assert smartthings_mock.delete_installed_app.call_count == 1
|
||||
assert smartthings_mock.delete_app.call_count == 1
|
||||
|
||||
|
||||
async def test_remove_entry_installedapp_api_error(
|
||||
hass, config_entry, smartthings_mock):
|
||||
"""Test raises exceptions removing the installed app."""
|
||||
# Arrange
|
||||
api = smartthings_mock.return_value
|
||||
api.delete_installed_app.side_effect = lambda _: mock_coro(
|
||||
exception=ClientResponseError(None, None, status=500))
|
||||
smartthings_mock.delete_installed_app.side_effect = \
|
||||
ClientResponseError(None, None, status=500)
|
||||
# Act
|
||||
with pytest.raises(ClientResponseError):
|
||||
await smartthings.async_remove_entry(hass, config_entry)
|
||||
# Assert
|
||||
assert api.delete_installed_app.call_count == 1
|
||||
assert api.delete_app.call_count == 0
|
||||
assert smartthings_mock.delete_installed_app.call_count == 1
|
||||
assert smartthings_mock.delete_app.call_count == 0
|
||||
|
||||
|
||||
async def test_remove_entry_installedapp_unknown_error(
|
||||
hass, config_entry, smartthings_mock):
|
||||
"""Test raises exceptions removing the installed app."""
|
||||
# Arrange
|
||||
api = smartthings_mock.return_value
|
||||
api.delete_installed_app.side_effect = lambda _: mock_coro(
|
||||
exception=Exception)
|
||||
smartthings_mock.delete_installed_app.side_effect = Exception
|
||||
# Act
|
||||
with pytest.raises(Exception):
|
||||
await smartthings.async_remove_entry(hass, config_entry)
|
||||
# Assert
|
||||
assert api.delete_installed_app.call_count == 1
|
||||
assert api.delete_app.call_count == 0
|
||||
assert smartthings_mock.delete_installed_app.call_count == 1
|
||||
assert smartthings_mock.delete_app.call_count == 0
|
||||
|
||||
|
||||
async def test_remove_entry_app_api_error(
|
||||
hass, config_entry, smartthings_mock):
|
||||
"""Test raises exceptions removing the app."""
|
||||
# Arrange
|
||||
api = smartthings_mock.return_value
|
||||
api.delete_installed_app.side_effect = lambda _: mock_coro()
|
||||
api.delete_app.side_effect = lambda _: mock_coro(
|
||||
exception=ClientResponseError(None, None, status=500))
|
||||
smartthings_mock.delete_app.side_effect = \
|
||||
ClientResponseError(None, None, status=500)
|
||||
# Act
|
||||
with pytest.raises(ClientResponseError):
|
||||
await smartthings.async_remove_entry(hass, config_entry)
|
||||
# Assert
|
||||
assert api.delete_installed_app.call_count == 1
|
||||
assert api.delete_app.call_count == 1
|
||||
assert smartthings_mock.delete_installed_app.call_count == 1
|
||||
assert smartthings_mock.delete_app.call_count == 1
|
||||
|
||||
|
||||
async def test_remove_entry_app_unknown_error(
|
||||
hass, config_entry, smartthings_mock):
|
||||
"""Test raises exceptions removing the app."""
|
||||
# Arrange
|
||||
api = smartthings_mock.return_value
|
||||
api.delete_installed_app.side_effect = lambda _: mock_coro()
|
||||
api.delete_app.side_effect = lambda _: mock_coro(
|
||||
exception=Exception)
|
||||
smartthings_mock.delete_app.side_effect = Exception
|
||||
# Act
|
||||
with pytest.raises(Exception):
|
||||
await smartthings.async_remove_entry(hass, config_entry)
|
||||
# Assert
|
||||
assert api.delete_installed_app.call_count == 1
|
||||
assert api.delete_app.call_count == 1
|
||||
assert smartthings_mock.delete_installed_app.call_count == 1
|
||||
assert smartthings_mock.delete_app.call_count == 1
|
||||
|
||||
|
||||
async def test_broker_regenerates_token(
|
||||
hass, config_entry):
|
||||
"""Test the device broker regenerates the refresh token."""
|
||||
token = Mock()
|
||||
token = Mock(OAuthToken)
|
||||
token.refresh_token = str(uuid4())
|
||||
token.refresh.return_value = mock_coro()
|
||||
stored_action = None
|
||||
|
||||
def async_track_time_interval(hass, action, interval):
|
||||
|
|
|
@ -40,7 +40,7 @@ async def test_scene_activate(hass, scene):
|
|||
assert state.attributes['color'] == scene.color
|
||||
assert state.attributes['location_id'] == scene.location_id
|
||||
# pylint: disable=protected-access
|
||||
assert scene._api.execute_scene.call_count == 1 # type: ignore
|
||||
assert scene.execute.call_count == 1 # type: ignore
|
||||
|
||||
|
||||
async def test_unload_config_entry(hass, scene):
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
"""Tests for the smartapp module."""
|
||||
from unittest.mock import Mock, patch
|
||||
from uuid import uuid4
|
||||
|
||||
from asynctest import CoroutineMock, Mock, patch
|
||||
from pysmartthings import AppEntity, Capability
|
||||
|
||||
from homeassistant.components.smartthings import smartapp
|
||||
|
@ -9,8 +9,6 @@ from homeassistant.components.smartthings.const import (
|
|||
CONF_INSTALLED_APP_ID, CONF_INSTALLED_APPS, CONF_LOCATION_ID,
|
||||
CONF_REFRESH_TOKEN, DATA_MANAGER, DOMAIN)
|
||||
|
||||
from tests.common import mock_coro
|
||||
|
||||
|
||||
async def test_update_app(hass, app):
|
||||
"""Test update_app does not save if app is current."""
|
||||
|
@ -20,10 +18,8 @@ async def test_update_app(hass, app):
|
|||
|
||||
async def test_update_app_updated_needed(hass, app):
|
||||
"""Test update_app updates when an app is needed."""
|
||||
mock_app = Mock(spec=AppEntity)
|
||||
mock_app = Mock(AppEntity)
|
||||
mock_app.app_name = 'Test'
|
||||
mock_app.refresh.return_value = mock_coro()
|
||||
mock_app.save.return_value = mock_coro()
|
||||
|
||||
await smartapp.update_app(hass, mock_app)
|
||||
|
||||
|
@ -64,7 +60,6 @@ async def test_smartapp_install_creates_flow(
|
|||
"""Test installation creates flow."""
|
||||
# Arrange
|
||||
setattr(hass.config_entries, '_entries', [config_entry])
|
||||
api = smartthings_mock.return_value
|
||||
app = Mock()
|
||||
app.app_id = config_entry.data['app_id']
|
||||
request = Mock()
|
||||
|
@ -77,8 +72,7 @@ async def test_smartapp_install_creates_flow(
|
|||
device_factory('', [Capability.switch, Capability.switch_level]),
|
||||
device_factory('', [Capability.switch])
|
||||
]
|
||||
api.devices = Mock()
|
||||
api.devices.return_value = mock_coro(return_value=devices)
|
||||
smartthings_mock.devices.return_value = devices
|
||||
# Act
|
||||
await smartapp.smartapp_install(hass, request, None, app)
|
||||
# Assert
|
||||
|
@ -131,8 +125,7 @@ async def test_smartapp_uninstall(hass, config_entry):
|
|||
request = Mock()
|
||||
request.installed_app_id = config_entry.data['installed_app_id']
|
||||
|
||||
with patch.object(hass.config_entries, 'async_remove',
|
||||
return_value=mock_coro()) as remove:
|
||||
with patch.object(hass.config_entries, 'async_remove') as remove:
|
||||
await smartapp.smartapp_uninstall(hass, request, None, app)
|
||||
assert remove.call_count == 1
|
||||
|
||||
|
@ -140,12 +133,11 @@ async def test_smartapp_uninstall(hass, config_entry):
|
|||
async def test_smartapp_webhook(hass):
|
||||
"""Test the smartapp webhook calls the manager."""
|
||||
manager = Mock()
|
||||
manager.handle_request = Mock()
|
||||
manager.handle_request.return_value = mock_coro(return_value={})
|
||||
manager.handle_request = CoroutineMock(return_value={})
|
||||
hass.data[DOMAIN][DATA_MANAGER] = manager
|
||||
request = Mock()
|
||||
request.headers = []
|
||||
request.json.return_value = mock_coro(return_value={})
|
||||
request.json = CoroutineMock(return_value={})
|
||||
result = await smartapp.smartapp_webhook(hass, '', request)
|
||||
|
||||
assert result.body == b'{}'
|
||||
|
@ -154,15 +146,11 @@ async def test_smartapp_webhook(hass):
|
|||
async def test_smartapp_sync_subscriptions(
|
||||
hass, smartthings_mock, device_factory, subscription_factory):
|
||||
"""Test synchronization adds and removes."""
|
||||
api = smartthings_mock.return_value
|
||||
api.delete_subscription.side_effect = lambda loc_id, sub_id: mock_coro()
|
||||
api.create_subscription.side_effect = lambda sub: mock_coro()
|
||||
subscriptions = [
|
||||
smartthings_mock.subscriptions.return_value = [
|
||||
subscription_factory(Capability.thermostat),
|
||||
subscription_factory(Capability.switch),
|
||||
subscription_factory(Capability.switch_level)
|
||||
]
|
||||
api.subscriptions.return_value = mock_coro(return_value=subscriptions)
|
||||
devices = [
|
||||
device_factory('', [Capability.battery, 'ping']),
|
||||
device_factory('', [Capability.switch, Capability.switch_level]),
|
||||
|
@ -172,23 +160,19 @@ async def test_smartapp_sync_subscriptions(
|
|||
await smartapp.smartapp_sync_subscriptions(
|
||||
hass, str(uuid4()), str(uuid4()), str(uuid4()), devices)
|
||||
|
||||
assert api.subscriptions.call_count == 1
|
||||
assert api.delete_subscription.call_count == 1
|
||||
assert api.create_subscription.call_count == 1
|
||||
assert smartthings_mock.subscriptions.call_count == 1
|
||||
assert smartthings_mock.delete_subscription.call_count == 1
|
||||
assert smartthings_mock.create_subscription.call_count == 1
|
||||
|
||||
|
||||
async def test_smartapp_sync_subscriptions_up_to_date(
|
||||
hass, smartthings_mock, device_factory, subscription_factory):
|
||||
"""Test synchronization does nothing when current."""
|
||||
api = smartthings_mock.return_value
|
||||
api.delete_subscription.side_effect = lambda loc_id, sub_id: mock_coro()
|
||||
api.create_subscription.side_effect = lambda sub: mock_coro()
|
||||
subscriptions = [
|
||||
smartthings_mock.subscriptions.return_value = [
|
||||
subscription_factory(Capability.battery),
|
||||
subscription_factory(Capability.switch),
|
||||
subscription_factory(Capability.switch_level)
|
||||
]
|
||||
api.subscriptions.return_value = mock_coro(return_value=subscriptions)
|
||||
devices = [
|
||||
device_factory('', [Capability.battery, 'ping']),
|
||||
device_factory('', [Capability.switch, Capability.switch_level]),
|
||||
|
@ -198,25 +182,21 @@ async def test_smartapp_sync_subscriptions_up_to_date(
|
|||
await smartapp.smartapp_sync_subscriptions(
|
||||
hass, str(uuid4()), str(uuid4()), str(uuid4()), devices)
|
||||
|
||||
assert api.subscriptions.call_count == 1
|
||||
assert api.delete_subscription.call_count == 0
|
||||
assert api.create_subscription.call_count == 0
|
||||
assert smartthings_mock.subscriptions.call_count == 1
|
||||
assert smartthings_mock.delete_subscription.call_count == 0
|
||||
assert smartthings_mock.create_subscription.call_count == 0
|
||||
|
||||
|
||||
async def test_smartapp_sync_subscriptions_handles_exceptions(
|
||||
hass, smartthings_mock, device_factory, subscription_factory):
|
||||
"""Test synchronization does nothing when current."""
|
||||
api = smartthings_mock.return_value
|
||||
api.delete_subscription.side_effect = \
|
||||
lambda loc_id, sub_id: mock_coro(exception=Exception)
|
||||
api.create_subscription.side_effect = \
|
||||
lambda sub: mock_coro(exception=Exception)
|
||||
subscriptions = [
|
||||
smartthings_mock.delete_subscription.side_effect = Exception
|
||||
smartthings_mock.create_subscription.side_effect = Exception
|
||||
smartthings_mock.subscriptions.return_value = [
|
||||
subscription_factory(Capability.battery),
|
||||
subscription_factory(Capability.switch),
|
||||
subscription_factory(Capability.switch_level)
|
||||
]
|
||||
api.subscriptions.return_value = mock_coro(return_value=subscriptions)
|
||||
devices = [
|
||||
device_factory('', [Capability.thermostat, 'ping']),
|
||||
device_factory('', [Capability.switch, Capability.switch_level]),
|
||||
|
@ -226,6 +206,6 @@ async def test_smartapp_sync_subscriptions_handles_exceptions(
|
|||
await smartapp.smartapp_sync_subscriptions(
|
||||
hass, str(uuid4()), str(uuid4()), str(uuid4()), devices)
|
||||
|
||||
assert api.subscriptions.call_count == 1
|
||||
assert api.delete_subscription.call_count == 1
|
||||
assert api.create_subscription.call_count == 1
|
||||
assert smartthings_mock.subscriptions.call_count == 1
|
||||
assert smartthings_mock.delete_subscription.call_count == 1
|
||||
assert smartthings_mock.create_subscription.call_count == 1
|
||||
|
|
Loading…
Add table
Reference in a new issue