Add cloud pref for Google unlock (#18600)
parent
b7742999cf
commit
d9c7f777c5
|
@ -20,17 +20,12 @@ from homeassistant.components.alexa import smart_home as alexa_sh
|
||||||
from homeassistant.components.google_assistant import helpers as ga_h
|
from homeassistant.components.google_assistant import helpers as ga_h
|
||||||
from homeassistant.components.google_assistant import const as ga_c
|
from homeassistant.components.google_assistant import const as ga_c
|
||||||
|
|
||||||
from . import http_api, iot, auth_api
|
from . import http_api, iot, auth_api, prefs
|
||||||
from .const import CONFIG_DIR, DOMAIN, SERVERS
|
from .const import CONFIG_DIR, DOMAIN, SERVERS
|
||||||
|
|
||||||
REQUIREMENTS = ['warrant==0.6.1']
|
REQUIREMENTS = ['warrant==0.6.1']
|
||||||
STORAGE_KEY = DOMAIN
|
|
||||||
STORAGE_VERSION = 1
|
|
||||||
STORAGE_ENABLE_ALEXA = 'alexa_enabled'
|
|
||||||
STORAGE_ENABLE_GOOGLE = 'google_enabled'
|
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
_UNDEF = object()
|
|
||||||
|
|
||||||
CONF_ALEXA = 'alexa'
|
CONF_ALEXA = 'alexa'
|
||||||
CONF_ALIASES = 'aliases'
|
CONF_ALIASES = 'aliases'
|
||||||
|
@ -70,8 +65,6 @@ ALEXA_SCHEMA = ASSISTANT_SCHEMA.extend({
|
||||||
|
|
||||||
GACTIONS_SCHEMA = ASSISTANT_SCHEMA.extend({
|
GACTIONS_SCHEMA = ASSISTANT_SCHEMA.extend({
|
||||||
vol.Optional(CONF_ENTITY_CONFIG): {cv.entity_id: GOOGLE_ENTITY_SCHEMA},
|
vol.Optional(CONF_ENTITY_CONFIG): {cv.entity_id: GOOGLE_ENTITY_SCHEMA},
|
||||||
vol.Optional(ga_c.CONF_ALLOW_UNLOCK,
|
|
||||||
default=ga_c.DEFAULT_ALLOW_UNLOCK): cv.boolean
|
|
||||||
})
|
})
|
||||||
|
|
||||||
CONFIG_SCHEMA = vol.Schema({
|
CONFIG_SCHEMA = vol.Schema({
|
||||||
|
@ -127,12 +120,11 @@ class Cloud:
|
||||||
self.alexa_config = alexa
|
self.alexa_config = alexa
|
||||||
self.google_actions_user_conf = google_actions
|
self.google_actions_user_conf = google_actions
|
||||||
self._gactions_config = None
|
self._gactions_config = None
|
||||||
self._prefs = None
|
self.prefs = prefs.CloudPreferences(hass)
|
||||||
self.id_token = None
|
self.id_token = None
|
||||||
self.access_token = None
|
self.access_token = None
|
||||||
self.refresh_token = None
|
self.refresh_token = None
|
||||||
self.iot = iot.CloudIoT(self)
|
self.iot = iot.CloudIoT(self)
|
||||||
self._store = hass.helpers.storage.Store(STORAGE_VERSION, STORAGE_KEY)
|
|
||||||
|
|
||||||
if mode == MODE_DEV:
|
if mode == MODE_DEV:
|
||||||
self.cognito_client_id = cognito_client_id
|
self.cognito_client_id = cognito_client_id
|
||||||
|
@ -196,21 +188,11 @@ class Cloud:
|
||||||
should_expose=should_expose,
|
should_expose=should_expose,
|
||||||
agent_user_id=self.claims['cognito:username'],
|
agent_user_id=self.claims['cognito:username'],
|
||||||
entity_config=conf.get(CONF_ENTITY_CONFIG),
|
entity_config=conf.get(CONF_ENTITY_CONFIG),
|
||||||
allow_unlock=conf.get(ga_c.CONF_ALLOW_UNLOCK),
|
allow_unlock=self.prefs.google_allow_unlock,
|
||||||
)
|
)
|
||||||
|
|
||||||
return self._gactions_config
|
return self._gactions_config
|
||||||
|
|
||||||
@property
|
|
||||||
def alexa_enabled(self):
|
|
||||||
"""Return if Alexa is enabled."""
|
|
||||||
return self._prefs[STORAGE_ENABLE_ALEXA]
|
|
||||||
|
|
||||||
@property
|
|
||||||
def google_enabled(self):
|
|
||||||
"""Return if Google is enabled."""
|
|
||||||
return self._prefs[STORAGE_ENABLE_GOOGLE]
|
|
||||||
|
|
||||||
def path(self, *parts):
|
def path(self, *parts):
|
||||||
"""Get config path inside cloud dir.
|
"""Get config path inside cloud dir.
|
||||||
|
|
||||||
|
@ -250,20 +232,6 @@ class Cloud:
|
||||||
|
|
||||||
async def async_start(self, _):
|
async def async_start(self, _):
|
||||||
"""Start the cloud component."""
|
"""Start the cloud component."""
|
||||||
prefs = await self._store.async_load()
|
|
||||||
if prefs is None:
|
|
||||||
prefs = {}
|
|
||||||
if self.mode not in prefs:
|
|
||||||
# Default to True if already logged in to make this not a
|
|
||||||
# breaking change.
|
|
||||||
enabled = await self.hass.async_add_executor_job(
|
|
||||||
os.path.isfile, self.user_info_path)
|
|
||||||
prefs = {
|
|
||||||
STORAGE_ENABLE_ALEXA: enabled,
|
|
||||||
STORAGE_ENABLE_GOOGLE: enabled,
|
|
||||||
}
|
|
||||||
self._prefs = prefs
|
|
||||||
|
|
||||||
def load_config():
|
def load_config():
|
||||||
"""Load config."""
|
"""Load config."""
|
||||||
# Ensure config dir exists
|
# Ensure config dir exists
|
||||||
|
@ -280,6 +248,8 @@ class Cloud:
|
||||||
|
|
||||||
info = await self.hass.async_add_job(load_config)
|
info = await self.hass.async_add_job(load_config)
|
||||||
|
|
||||||
|
await self.prefs.async_initialize(not info)
|
||||||
|
|
||||||
if info is None:
|
if info is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -289,15 +259,6 @@ class Cloud:
|
||||||
|
|
||||||
self.hass.add_job(self.iot.connect())
|
self.hass.add_job(self.iot.connect())
|
||||||
|
|
||||||
async def update_preferences(self, *, google_enabled=_UNDEF,
|
|
||||||
alexa_enabled=_UNDEF):
|
|
||||||
"""Update user preferences."""
|
|
||||||
if google_enabled is not _UNDEF:
|
|
||||||
self._prefs[STORAGE_ENABLE_GOOGLE] = google_enabled
|
|
||||||
if alexa_enabled is not _UNDEF:
|
|
||||||
self._prefs[STORAGE_ENABLE_ALEXA] = alexa_enabled
|
|
||||||
await self._store.async_save(self._prefs)
|
|
||||||
|
|
||||||
def _decode_claims(self, token): # pylint: disable=no-self-use
|
def _decode_claims(self, token): # pylint: disable=no-self-use
|
||||||
"""Decode the claims in a token."""
|
"""Decode the claims in a token."""
|
||||||
from jose import jwt
|
from jose import jwt
|
||||||
|
|
|
@ -3,6 +3,10 @@ DOMAIN = 'cloud'
|
||||||
CONFIG_DIR = '.cloud'
|
CONFIG_DIR = '.cloud'
|
||||||
REQUEST_TIMEOUT = 10
|
REQUEST_TIMEOUT = 10
|
||||||
|
|
||||||
|
PREF_ENABLE_ALEXA = 'alexa_enabled'
|
||||||
|
PREF_ENABLE_GOOGLE = 'google_enabled'
|
||||||
|
PREF_GOOGLE_ALLOW_UNLOCK = 'google_allow_unlock'
|
||||||
|
|
||||||
SERVERS = {
|
SERVERS = {
|
||||||
'production': {
|
'production': {
|
||||||
'cognito_client_id': '60i2uvhvbiref2mftj7rgcrt9u',
|
'cognito_client_id': '60i2uvhvbiref2mftj7rgcrt9u',
|
||||||
|
|
|
@ -15,7 +15,9 @@ from homeassistant.components.alexa import smart_home as alexa_sh
|
||||||
from homeassistant.components.google_assistant import smart_home as google_sh
|
from homeassistant.components.google_assistant import smart_home as google_sh
|
||||||
|
|
||||||
from . import auth_api
|
from . import auth_api
|
||||||
from .const import DOMAIN, REQUEST_TIMEOUT
|
from .const import (
|
||||||
|
DOMAIN, REQUEST_TIMEOUT, PREF_ENABLE_ALEXA, PREF_ENABLE_GOOGLE,
|
||||||
|
PREF_GOOGLE_ALLOW_UNLOCK)
|
||||||
from .iot import STATE_DISCONNECTED, STATE_CONNECTED
|
from .iot import STATE_DISCONNECTED, STATE_CONNECTED
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
@ -30,8 +32,9 @@ SCHEMA_WS_STATUS = websocket_api.BASE_COMMAND_MESSAGE_SCHEMA.extend({
|
||||||
WS_TYPE_UPDATE_PREFS = 'cloud/update_prefs'
|
WS_TYPE_UPDATE_PREFS = 'cloud/update_prefs'
|
||||||
SCHEMA_WS_UPDATE_PREFS = websocket_api.BASE_COMMAND_MESSAGE_SCHEMA.extend({
|
SCHEMA_WS_UPDATE_PREFS = websocket_api.BASE_COMMAND_MESSAGE_SCHEMA.extend({
|
||||||
vol.Required('type'): WS_TYPE_UPDATE_PREFS,
|
vol.Required('type'): WS_TYPE_UPDATE_PREFS,
|
||||||
vol.Optional('google_enabled'): bool,
|
vol.Optional(PREF_ENABLE_GOOGLE): bool,
|
||||||
vol.Optional('alexa_enabled'): bool,
|
vol.Optional(PREF_ENABLE_ALEXA): bool,
|
||||||
|
vol.Optional(PREF_GOOGLE_ALLOW_UNLOCK): bool,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
@ -288,7 +291,7 @@ async def websocket_update_prefs(hass, connection, msg):
|
||||||
changes = dict(msg)
|
changes = dict(msg)
|
||||||
changes.pop('id')
|
changes.pop('id')
|
||||||
changes.pop('type')
|
changes.pop('type')
|
||||||
await cloud.update_preferences(**changes)
|
await cloud.prefs.async_update(**changes)
|
||||||
|
|
||||||
connection.send_message(websocket_api.result_message(
|
connection.send_message(websocket_api.result_message(
|
||||||
msg['id'], {'success': True}))
|
msg['id'], {'success': True}))
|
||||||
|
@ -308,10 +311,9 @@ def _account_data(cloud):
|
||||||
'logged_in': True,
|
'logged_in': True,
|
||||||
'email': claims['email'],
|
'email': claims['email'],
|
||||||
'cloud': cloud.iot.state,
|
'cloud': cloud.iot.state,
|
||||||
'google_enabled': cloud.google_enabled,
|
'prefs': cloud.prefs.as_dict(),
|
||||||
'google_entities': cloud.google_actions_user_conf['filter'].config,
|
'google_entities': cloud.google_actions_user_conf['filter'].config,
|
||||||
'google_domains': list(google_sh.DOMAIN_TO_GOOGLE_TYPES),
|
'google_domains': list(google_sh.DOMAIN_TO_GOOGLE_TYPES),
|
||||||
'alexa_enabled': cloud.alexa_enabled,
|
|
||||||
'alexa_entities': cloud.alexa_config.should_expose.config,
|
'alexa_entities': cloud.alexa_config.should_expose.config,
|
||||||
'alexa_domains': list(alexa_sh.ENTITY_ADAPTERS),
|
'alexa_domains': list(alexa_sh.ENTITY_ADAPTERS),
|
||||||
}
|
}
|
||||||
|
|
|
@ -229,7 +229,7 @@ def async_handle_alexa(hass, cloud, payload):
|
||||||
"""Handle an incoming IoT message for Alexa."""
|
"""Handle an incoming IoT message for Alexa."""
|
||||||
result = yield from alexa.async_handle_message(
|
result = yield from alexa.async_handle_message(
|
||||||
hass, cloud.alexa_config, payload,
|
hass, cloud.alexa_config, payload,
|
||||||
enabled=cloud.alexa_enabled)
|
enabled=cloud.prefs.alexa_enabled)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
@ -237,7 +237,7 @@ def async_handle_alexa(hass, cloud, payload):
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def async_handle_google_actions(hass, cloud, payload):
|
def async_handle_google_actions(hass, cloud, payload):
|
||||||
"""Handle an incoming IoT message for Google Actions."""
|
"""Handle an incoming IoT message for Google Actions."""
|
||||||
if not cloud.google_enabled:
|
if not cloud.prefs.google_enabled:
|
||||||
return ga.turned_off_response(payload)
|
return ga.turned_off_response(payload)
|
||||||
|
|
||||||
result = yield from ga.async_handle_message(
|
result = yield from ga.async_handle_message(
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
"""Preference management for cloud."""
|
||||||
|
from .const import (
|
||||||
|
DOMAIN, PREF_ENABLE_ALEXA, PREF_ENABLE_GOOGLE,
|
||||||
|
PREF_GOOGLE_ALLOW_UNLOCK)
|
||||||
|
|
||||||
|
STORAGE_KEY = DOMAIN
|
||||||
|
STORAGE_VERSION = 1
|
||||||
|
_UNDEF = object()
|
||||||
|
|
||||||
|
|
||||||
|
class CloudPreferences:
|
||||||
|
"""Handle cloud preferences."""
|
||||||
|
|
||||||
|
def __init__(self, hass):
|
||||||
|
"""Initialize cloud prefs."""
|
||||||
|
self._store = hass.helpers.storage.Store(STORAGE_VERSION, STORAGE_KEY)
|
||||||
|
self._prefs = None
|
||||||
|
|
||||||
|
async def async_initialize(self, logged_in):
|
||||||
|
"""Finish initializing the preferences."""
|
||||||
|
prefs = await self._store.async_load()
|
||||||
|
|
||||||
|
if prefs is None:
|
||||||
|
# Backwards compat: we enable alexa/google if already logged in
|
||||||
|
prefs = {
|
||||||
|
PREF_ENABLE_ALEXA: logged_in,
|
||||||
|
PREF_ENABLE_GOOGLE: logged_in,
|
||||||
|
PREF_GOOGLE_ALLOW_UNLOCK: False,
|
||||||
|
}
|
||||||
|
|
||||||
|
self._prefs = prefs
|
||||||
|
|
||||||
|
async def async_update(self, *, google_enabled=_UNDEF,
|
||||||
|
alexa_enabled=_UNDEF, google_allow_unlock=_UNDEF):
|
||||||
|
"""Update user preferences."""
|
||||||
|
for key, value in (
|
||||||
|
(PREF_ENABLE_GOOGLE, google_enabled),
|
||||||
|
(PREF_ENABLE_ALEXA, alexa_enabled),
|
||||||
|
(PREF_GOOGLE_ALLOW_UNLOCK, google_allow_unlock),
|
||||||
|
):
|
||||||
|
if value is not _UNDEF:
|
||||||
|
self._prefs[key] = value
|
||||||
|
|
||||||
|
await self._store.async_save(self._prefs)
|
||||||
|
|
||||||
|
def as_dict(self):
|
||||||
|
"""Return dictionary version."""
|
||||||
|
return self._prefs
|
||||||
|
|
||||||
|
@property
|
||||||
|
def alexa_enabled(self):
|
||||||
|
"""Return if Alexa is enabled."""
|
||||||
|
return self._prefs[PREF_ENABLE_ALEXA]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def google_enabled(self):
|
||||||
|
"""Return if Google is enabled."""
|
||||||
|
return self._prefs[PREF_ENABLE_GOOGLE]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def google_allow_unlock(self):
|
||||||
|
"""Return if Google is allowed to unlock locks."""
|
||||||
|
return self._prefs.get(PREF_GOOGLE_ALLOW_UNLOCK, False)
|
|
@ -2,6 +2,7 @@
|
||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
from homeassistant.setup import async_setup_component
|
from homeassistant.setup import async_setup_component
|
||||||
from homeassistant.components import cloud
|
from homeassistant.components import cloud
|
||||||
|
from homeassistant.components.cloud import const
|
||||||
|
|
||||||
from jose import jwt
|
from jose import jwt
|
||||||
|
|
||||||
|
@ -24,9 +25,10 @@ def mock_cloud(hass, config={}):
|
||||||
def mock_cloud_prefs(hass, prefs={}):
|
def mock_cloud_prefs(hass, prefs={}):
|
||||||
"""Fixture for cloud component."""
|
"""Fixture for cloud component."""
|
||||||
prefs_to_set = {
|
prefs_to_set = {
|
||||||
cloud.STORAGE_ENABLE_ALEXA: True,
|
const.PREF_ENABLE_ALEXA: True,
|
||||||
cloud.STORAGE_ENABLE_GOOGLE: True,
|
const.PREF_ENABLE_GOOGLE: True,
|
||||||
|
const.PREF_GOOGLE_ALLOW_UNLOCK: True,
|
||||||
}
|
}
|
||||||
prefs_to_set.update(prefs)
|
prefs_to_set.update(prefs)
|
||||||
hass.data[cloud.DOMAIN]._prefs = prefs_to_set
|
hass.data[cloud.DOMAIN].prefs._prefs = prefs_to_set
|
||||||
return prefs_to_set
|
return prefs_to_set
|
||||||
|
|
|
@ -6,7 +6,9 @@ import pytest
|
||||||
from jose import jwt
|
from jose import jwt
|
||||||
|
|
||||||
from homeassistant.components.cloud import (
|
from homeassistant.components.cloud import (
|
||||||
DOMAIN, auth_api, iot, STORAGE_ENABLE_GOOGLE, STORAGE_ENABLE_ALEXA)
|
DOMAIN, auth_api, iot)
|
||||||
|
from homeassistant.components.cloud.const import (
|
||||||
|
PREF_ENABLE_GOOGLE, PREF_ENABLE_ALEXA, PREF_GOOGLE_ALLOW_UNLOCK)
|
||||||
from homeassistant.util import dt as dt_util
|
from homeassistant.util import dt as dt_util
|
||||||
|
|
||||||
from tests.common import mock_coro
|
from tests.common import mock_coro
|
||||||
|
@ -350,7 +352,7 @@ async def test_websocket_status(hass, hass_ws_client, mock_cloud_fixture):
|
||||||
'logged_in': True,
|
'logged_in': True,
|
||||||
'email': 'hello@home-assistant.io',
|
'email': 'hello@home-assistant.io',
|
||||||
'cloud': 'connected',
|
'cloud': 'connected',
|
||||||
'alexa_enabled': True,
|
'prefs': mock_cloud_fixture,
|
||||||
'alexa_entities': {
|
'alexa_entities': {
|
||||||
'include_domains': [],
|
'include_domains': [],
|
||||||
'include_entities': ['light.kitchen', 'switch.ac'],
|
'include_entities': ['light.kitchen', 'switch.ac'],
|
||||||
|
@ -358,7 +360,6 @@ async def test_websocket_status(hass, hass_ws_client, mock_cloud_fixture):
|
||||||
'exclude_entities': [],
|
'exclude_entities': [],
|
||||||
},
|
},
|
||||||
'alexa_domains': ['switch'],
|
'alexa_domains': ['switch'],
|
||||||
'google_enabled': True,
|
|
||||||
'google_entities': {
|
'google_entities': {
|
||||||
'include_domains': ['light'],
|
'include_domains': ['light'],
|
||||||
'include_entities': [],
|
'include_entities': [],
|
||||||
|
@ -505,8 +506,9 @@ async def test_websocket_subscription_not_logged_in(hass, hass_ws_client):
|
||||||
async def test_websocket_update_preferences(hass, hass_ws_client,
|
async def test_websocket_update_preferences(hass, hass_ws_client,
|
||||||
aioclient_mock, setup_api):
|
aioclient_mock, setup_api):
|
||||||
"""Test updating preference."""
|
"""Test updating preference."""
|
||||||
assert setup_api[STORAGE_ENABLE_GOOGLE]
|
assert setup_api[PREF_ENABLE_GOOGLE]
|
||||||
assert setup_api[STORAGE_ENABLE_ALEXA]
|
assert setup_api[PREF_ENABLE_ALEXA]
|
||||||
|
assert setup_api[PREF_GOOGLE_ALLOW_UNLOCK]
|
||||||
hass.data[DOMAIN].id_token = jwt.encode({
|
hass.data[DOMAIN].id_token = jwt.encode({
|
||||||
'email': 'hello@home-assistant.io',
|
'email': 'hello@home-assistant.io',
|
||||||
'custom:sub-exp': '2018-01-03'
|
'custom:sub-exp': '2018-01-03'
|
||||||
|
@ -517,9 +519,11 @@ async def test_websocket_update_preferences(hass, hass_ws_client,
|
||||||
'type': 'cloud/update_prefs',
|
'type': 'cloud/update_prefs',
|
||||||
'alexa_enabled': False,
|
'alexa_enabled': False,
|
||||||
'google_enabled': False,
|
'google_enabled': False,
|
||||||
|
'google_allow_unlock': False,
|
||||||
})
|
})
|
||||||
response = await client.receive_json()
|
response = await client.receive_json()
|
||||||
|
|
||||||
assert response['success']
|
assert response['success']
|
||||||
assert not setup_api[STORAGE_ENABLE_GOOGLE]
|
assert not setup_api[PREF_ENABLE_GOOGLE]
|
||||||
assert not setup_api[STORAGE_ENABLE_ALEXA]
|
assert not setup_api[PREF_ENABLE_ALEXA]
|
||||||
|
assert not setup_api[PREF_GOOGLE_ALLOW_UNLOCK]
|
||||||
|
|
|
@ -7,8 +7,9 @@ import pytest
|
||||||
|
|
||||||
from homeassistant.setup import async_setup_component
|
from homeassistant.setup import async_setup_component
|
||||||
from homeassistant.components.cloud import (
|
from homeassistant.components.cloud import (
|
||||||
Cloud, iot, auth_api, MODE_DEV, STORAGE_ENABLE_ALEXA,
|
Cloud, iot, auth_api, MODE_DEV)
|
||||||
STORAGE_ENABLE_GOOGLE)
|
from homeassistant.components.cloud.const import (
|
||||||
|
PREF_ENABLE_ALEXA, PREF_ENABLE_GOOGLE)
|
||||||
from tests.components.alexa import test_smart_home as test_alexa
|
from tests.components.alexa import test_smart_home as test_alexa
|
||||||
from tests.common import mock_coro
|
from tests.common import mock_coro
|
||||||
|
|
||||||
|
@ -308,7 +309,7 @@ def test_handler_alexa(hass):
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def test_handler_alexa_disabled(hass, mock_cloud_fixture):
|
def test_handler_alexa_disabled(hass, mock_cloud_fixture):
|
||||||
"""Test handler Alexa when user has disabled it."""
|
"""Test handler Alexa when user has disabled it."""
|
||||||
mock_cloud_fixture[STORAGE_ENABLE_ALEXA] = False
|
mock_cloud_fixture[PREF_ENABLE_ALEXA] = False
|
||||||
|
|
||||||
resp = yield from iot.async_handle_alexa(
|
resp = yield from iot.async_handle_alexa(
|
||||||
hass, hass.data['cloud'],
|
hass, hass.data['cloud'],
|
||||||
|
@ -377,7 +378,7 @@ def test_handler_google_actions(hass):
|
||||||
|
|
||||||
async def test_handler_google_actions_disabled(hass, mock_cloud_fixture):
|
async def test_handler_google_actions_disabled(hass, mock_cloud_fixture):
|
||||||
"""Test handler Google Actions when user has disabled it."""
|
"""Test handler Google Actions when user has disabled it."""
|
||||||
mock_cloud_fixture[STORAGE_ENABLE_GOOGLE] = False
|
mock_cloud_fixture[PREF_ENABLE_GOOGLE] = False
|
||||||
|
|
||||||
with patch('homeassistant.components.cloud.Cloud.async_start',
|
with patch('homeassistant.components.cloud.Cloud.async_start',
|
||||||
return_value=mock_coro()):
|
return_value=mock_coro()):
|
||||||
|
|
Loading…
Reference in New Issue