Convert Nanoleaf integration to use Async library aionanoleaf (#56548)
This commit is contained in:
parent
7ece35cd6f
commit
0b53f73fe2
9 changed files with 127 additions and 136 deletions
|
@ -695,7 +695,6 @@ omit =
|
|||
homeassistant/components/nad/media_player.py
|
||||
homeassistant/components/nanoleaf/__init__.py
|
||||
homeassistant/components/nanoleaf/light.py
|
||||
homeassistant/components/nanoleaf/util.py
|
||||
homeassistant/components/neato/__init__.py
|
||||
homeassistant/components/neato/api.py
|
||||
homeassistant/components/neato/camera.py
|
||||
|
|
|
@ -1,21 +1,22 @@
|
|||
"""The Nanoleaf integration."""
|
||||
from pynanoleaf.pynanoleaf import InvalidToken, Nanoleaf, Unavailable
|
||||
from aionanoleaf import InvalidToken, Nanoleaf, Unavailable
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import CONF_HOST, CONF_TOKEN
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady
|
||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||
|
||||
from .const import DEVICE, DOMAIN, NAME, SERIAL_NO
|
||||
from .util import pynanoleaf_get_info
|
||||
|
||||
|
||||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
"""Set up Nanoleaf from a config entry."""
|
||||
nanoleaf = Nanoleaf(entry.data[CONF_HOST])
|
||||
nanoleaf.token = entry.data[CONF_TOKEN]
|
||||
nanoleaf = Nanoleaf(
|
||||
async_get_clientsession(hass), entry.data[CONF_HOST], entry.data[CONF_TOKEN]
|
||||
)
|
||||
try:
|
||||
info = await hass.async_add_executor_job(pynanoleaf_get_info, nanoleaf)
|
||||
await nanoleaf.get_info()
|
||||
except Unavailable as err:
|
||||
raise ConfigEntryNotReady from err
|
||||
except InvalidToken as err:
|
||||
|
@ -23,8 +24,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||
|
||||
hass.data.setdefault(DOMAIN, {})[entry.entry_id] = {
|
||||
DEVICE: nanoleaf,
|
||||
NAME: info["name"],
|
||||
SERIAL_NO: info["serialNo"],
|
||||
NAME: nanoleaf.name,
|
||||
SERIAL_NO: nanoleaf.serial_no,
|
||||
}
|
||||
|
||||
hass.async_create_task(
|
||||
|
|
|
@ -5,17 +5,17 @@ import logging
|
|||
import os
|
||||
from typing import Any, Final, cast
|
||||
|
||||
from pynanoleaf import InvalidToken, Nanoleaf, NotAuthorizingNewTokens, Unavailable
|
||||
from aionanoleaf import InvalidToken, Nanoleaf, Unauthorized, Unavailable
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant import config_entries
|
||||
from homeassistant.const import CONF_HOST, CONF_TOKEN
|
||||
from homeassistant.data_entry_flow import FlowResult
|
||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||
from homeassistant.helpers.typing import DiscoveryInfoType
|
||||
from homeassistant.util.json import load_json, save_json
|
||||
|
||||
from .const import DOMAIN
|
||||
from .util import pynanoleaf_get_info
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
@ -53,9 +53,11 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
step_id="user", data_schema=USER_SCHEMA, last_step=False
|
||||
)
|
||||
self._async_abort_entries_match({CONF_HOST: user_input[CONF_HOST]})
|
||||
self.nanoleaf = Nanoleaf(user_input[CONF_HOST])
|
||||
self.nanoleaf = Nanoleaf(
|
||||
async_get_clientsession(self.hass), user_input[CONF_HOST]
|
||||
)
|
||||
try:
|
||||
await self.hass.async_add_executor_job(self.nanoleaf.authorize)
|
||||
await self.nanoleaf.authorize()
|
||||
except Unavailable:
|
||||
return self.async_show_form(
|
||||
step_id="user",
|
||||
|
@ -63,7 +65,7 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
errors={"base": "cannot_connect"},
|
||||
last_step=False,
|
||||
)
|
||||
except NotAuthorizingNewTokens:
|
||||
except Unauthorized:
|
||||
pass
|
||||
except Exception: # pylint: disable=broad-except
|
||||
_LOGGER.exception("Unknown error connecting to Nanoleaf")
|
||||
|
@ -81,7 +83,7 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
config_entries.ConfigEntry,
|
||||
self.hass.config_entries.async_get_entry(self.context["entry_id"]),
|
||||
)
|
||||
self.nanoleaf = Nanoleaf(data[CONF_HOST])
|
||||
self.nanoleaf = Nanoleaf(async_get_clientsession(self.hass), data[CONF_HOST])
|
||||
self.context["title_placeholders"] = {"name": self.reauth_entry.title}
|
||||
return await self.async_step_link()
|
||||
|
||||
|
@ -106,7 +108,6 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
name = discovery_info["name"].replace(f".{discovery_info['type']}", "")
|
||||
await self.async_set_unique_id(name)
|
||||
self._abort_if_unique_id_configured({CONF_HOST: host})
|
||||
self.nanoleaf = Nanoleaf(host)
|
||||
|
||||
# Import from discovery integration
|
||||
self.device_id = discovery_info["properties"]["id"]
|
||||
|
@ -116,16 +117,19 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
load_json, self.hass.config.path(CONFIG_FILE)
|
||||
),
|
||||
)
|
||||
self.nanoleaf.token = self.discovery_conf.get(self.device_id, {}).get(
|
||||
auth_token: str | None = self.discovery_conf.get(self.device_id, {}).get(
|
||||
"token", # >= 2021.4
|
||||
self.discovery_conf.get(host, {}).get("token"), # < 2021.4
|
||||
)
|
||||
if self.nanoleaf.token is not None:
|
||||
if auth_token is not None:
|
||||
self.nanoleaf = Nanoleaf(
|
||||
async_get_clientsession(self.hass), host, auth_token
|
||||
)
|
||||
_LOGGER.warning(
|
||||
"Importing Nanoleaf %s from the discovery integration", name
|
||||
)
|
||||
return await self.async_setup_finish(discovery_integration_import=True)
|
||||
|
||||
self.nanoleaf = Nanoleaf(async_get_clientsession(self.hass), host)
|
||||
self.context["title_placeholders"] = {"name": name}
|
||||
return await self.async_step_link()
|
||||
|
||||
|
@ -137,8 +141,8 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
return self.async_show_form(step_id="link")
|
||||
|
||||
try:
|
||||
await self.hass.async_add_executor_job(self.nanoleaf.authorize)
|
||||
except NotAuthorizingNewTokens:
|
||||
await self.nanoleaf.authorize()
|
||||
except Unauthorized:
|
||||
return self.async_show_form(
|
||||
step_id="link", errors={"base": "not_allowing_new_tokens"}
|
||||
)
|
||||
|
@ -153,7 +157,7 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
self.reauth_entry,
|
||||
data={
|
||||
**self.reauth_entry.data,
|
||||
CONF_TOKEN: self.nanoleaf.token,
|
||||
CONF_TOKEN: self.nanoleaf.auth_token,
|
||||
},
|
||||
)
|
||||
await self.hass.config_entries.async_reload(self.reauth_entry.entry_id)
|
||||
|
@ -167,8 +171,9 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
_LOGGER.debug(
|
||||
"Importing Nanoleaf on %s from your configuration.yaml", config[CONF_HOST]
|
||||
)
|
||||
self.nanoleaf = Nanoleaf(config[CONF_HOST])
|
||||
self.nanoleaf.token = config[CONF_TOKEN]
|
||||
self.nanoleaf = Nanoleaf(
|
||||
async_get_clientsession(self.hass), config[CONF_HOST], config[CONF_TOKEN]
|
||||
)
|
||||
return await self.async_setup_finish()
|
||||
|
||||
async def async_setup_finish(
|
||||
|
@ -176,9 +181,7 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
) -> FlowResult:
|
||||
"""Finish Nanoleaf config flow."""
|
||||
try:
|
||||
info = await self.hass.async_add_executor_job(
|
||||
pynanoleaf_get_info, self.nanoleaf
|
||||
)
|
||||
await self.nanoleaf.get_info()
|
||||
except Unavailable:
|
||||
return self.async_abort(reason="cannot_connect")
|
||||
except InvalidToken:
|
||||
|
@ -188,7 +191,7 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
"Unknown error connecting with Nanoleaf at %s", self.nanoleaf.host
|
||||
)
|
||||
return self.async_abort(reason="unknown")
|
||||
name = info["name"]
|
||||
name = self.nanoleaf.name
|
||||
|
||||
await self.async_set_unique_id(name)
|
||||
self._abort_if_unique_id_configured({CONF_HOST: self.nanoleaf.host})
|
||||
|
@ -215,6 +218,6 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
title=name,
|
||||
data={
|
||||
CONF_HOST: self.nanoleaf.host,
|
||||
CONF_TOKEN: self.nanoleaf.token,
|
||||
CONF_TOKEN: self.nanoleaf.auth_token,
|
||||
},
|
||||
)
|
||||
|
|
|
@ -3,7 +3,8 @@ from __future__ import annotations
|
|||
|
||||
import logging
|
||||
|
||||
from pynanoleaf import Unavailable
|
||||
from aiohttp import ServerDisconnectedError
|
||||
from aionanoleaf import Unavailable
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.light import (
|
||||
|
@ -153,7 +154,7 @@ class NanoleafLight(LightEntity):
|
|||
@property
|
||||
def is_on(self):
|
||||
"""Return true if light is on."""
|
||||
return self._state
|
||||
return self._light.is_on
|
||||
|
||||
@property
|
||||
def hs_color(self):
|
||||
|
@ -165,7 +166,7 @@ class NanoleafLight(LightEntity):
|
|||
"""Flag supported features."""
|
||||
return SUPPORT_NANOLEAF
|
||||
|
||||
def turn_on(self, **kwargs):
|
||||
async def async_turn_on(self, **kwargs):
|
||||
"""Instruct the light to turn on."""
|
||||
brightness = kwargs.get(ATTR_BRIGHTNESS)
|
||||
hs_color = kwargs.get(ATTR_HS_COLOR)
|
||||
|
@ -175,44 +176,51 @@ class NanoleafLight(LightEntity):
|
|||
|
||||
if hs_color:
|
||||
hue, saturation = hs_color
|
||||
self._light.hue = int(hue)
|
||||
self._light.saturation = int(saturation)
|
||||
await self._light.set_hue(int(hue))
|
||||
await self._light.set_saturation(int(saturation))
|
||||
if color_temp_mired:
|
||||
self._light.color_temperature = mired_to_kelvin(color_temp_mired)
|
||||
|
||||
await self._light.set_color_temperature(mired_to_kelvin(color_temp_mired))
|
||||
if transition:
|
||||
if brightness: # tune to the required brightness in n seconds
|
||||
self._light.brightness_transition(
|
||||
int(brightness / 2.55), int(transition)
|
||||
await self._light.set_brightness(
|
||||
int(brightness / 2.55), transition=int(kwargs[ATTR_TRANSITION])
|
||||
)
|
||||
else: # If brightness is not specified, assume full brightness
|
||||
self._light.brightness_transition(100, int(transition))
|
||||
await self._light.set_brightness(
|
||||
100, transition=int(kwargs[ATTR_TRANSITION])
|
||||
)
|
||||
else: # If no transition is occurring, turn on the light
|
||||
self._light.on = True
|
||||
await self._light.turn_on()
|
||||
if brightness:
|
||||
self._light.brightness = int(brightness / 2.55)
|
||||
|
||||
await self._light.set_brightness(int(brightness / 2.55))
|
||||
if effect:
|
||||
if effect not in self._effects_list:
|
||||
raise ValueError(
|
||||
f"Attempting to apply effect not in the effect list: '{effect}'"
|
||||
)
|
||||
self._light.effect = effect
|
||||
await self._light.set_effect(effect)
|
||||
|
||||
def turn_off(self, **kwargs):
|
||||
async def async_turn_off(self, **kwargs):
|
||||
"""Instruct the light to turn off."""
|
||||
transition = kwargs.get(ATTR_TRANSITION)
|
||||
if transition:
|
||||
self._light.brightness_transition(0, int(transition))
|
||||
await self._light.set_brightness(0, transition=int(transition))
|
||||
else:
|
||||
self._light.on = False
|
||||
await self._light.turn_off()
|
||||
|
||||
def update(self):
|
||||
async def async_update(self) -> None:
|
||||
"""Fetch new state data for this light."""
|
||||
try:
|
||||
self._available = self._light.available
|
||||
await self._light.get_info()
|
||||
except ServerDisconnectedError:
|
||||
# Retry the request once if the device disconnected
|
||||
await self._light.get_info()
|
||||
except Unavailable:
|
||||
self._available = False
|
||||
return
|
||||
self._available = True
|
||||
self._brightness = self._light.brightness
|
||||
self._effects_list = self._light.effects
|
||||
self._effects_list = self._light.effects_list
|
||||
# Nanoleaf api returns non-existent effect named "*Solid*" when light set to solid color.
|
||||
# This causes various issues with scening (see https://github.com/home-assistant/core/issues/36359).
|
||||
# Until fixed at the library level, we should ensure the effect exists before saving to light properties
|
||||
|
@ -225,7 +233,4 @@ class NanoleafLight(LightEntity):
|
|||
else:
|
||||
self._color_temp = None
|
||||
self._hs_color = None
|
||||
self._state = self._light.on
|
||||
except Unavailable as err:
|
||||
_LOGGER.error("Could not update status for %s (%s)", self.name, err)
|
||||
self._available = False
|
||||
self._state = self._light.is_on
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
"name": "Nanoleaf",
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/nanoleaf",
|
||||
"requirements": ["pynanoleaf==0.1.0"],
|
||||
"requirements": ["aionanoleaf==0.0.1"],
|
||||
"zeroconf": ["_nanoleafms._tcp.local.", "_nanoleafapi._tcp.local."],
|
||||
"homekit" : {
|
||||
"models": [
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
"""Nanoleaf integration util."""
|
||||
from pynanoleaf.pynanoleaf import Nanoleaf
|
||||
|
||||
|
||||
def pynanoleaf_get_info(nanoleaf_light: Nanoleaf) -> dict:
|
||||
"""Get Nanoleaf light info."""
|
||||
return nanoleaf_light.info
|
|
@ -218,6 +218,9 @@ aiomodernforms==0.1.8
|
|||
# homeassistant.components.yamaha_musiccast
|
||||
aiomusiccast==0.9.2
|
||||
|
||||
# homeassistant.components.nanoleaf
|
||||
aionanoleaf==0.0.1
|
||||
|
||||
# homeassistant.components.keyboard_remote
|
||||
aionotify==0.2.0
|
||||
|
||||
|
@ -1649,9 +1652,6 @@ pymyq==3.1.4
|
|||
# homeassistant.components.mysensors
|
||||
pymysensors==0.21.0
|
||||
|
||||
# homeassistant.components.nanoleaf
|
||||
pynanoleaf==0.1.0
|
||||
|
||||
# homeassistant.components.nello
|
||||
pynello==2.0.3
|
||||
|
||||
|
|
|
@ -145,6 +145,9 @@ aiomodernforms==0.1.8
|
|||
# homeassistant.components.yamaha_musiccast
|
||||
aiomusiccast==0.9.2
|
||||
|
||||
# homeassistant.components.nanoleaf
|
||||
aionanoleaf==0.0.1
|
||||
|
||||
# homeassistant.components.notion
|
||||
aionotion==3.0.2
|
||||
|
||||
|
@ -968,9 +971,6 @@ pymyq==3.1.4
|
|||
# homeassistant.components.mysensors
|
||||
pymysensors==0.21.0
|
||||
|
||||
# homeassistant.components.nanoleaf
|
||||
pynanoleaf==0.1.0
|
||||
|
||||
# homeassistant.components.netgear
|
||||
pynetgear==0.7.0
|
||||
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
"""Test the Nanoleaf config flow."""
|
||||
from __future__ import annotations
|
||||
|
||||
from unittest.mock import MagicMock, patch
|
||||
from unittest.mock import AsyncMock, MagicMock, patch
|
||||
|
||||
from pynanoleaf import InvalidToken, NotAuthorizingNewTokens, Unavailable
|
||||
from pynanoleaf.pynanoleaf import NanoleafError
|
||||
from aionanoleaf import InvalidToken, NanoleafException, Unauthorized, Unavailable
|
||||
import pytest
|
||||
|
||||
from homeassistant import config_entries
|
||||
|
@ -23,6 +22,21 @@ TEST_DEVICE_ID = "5E:2E:EA:XX:XX:XX"
|
|||
TEST_OTHER_DEVICE_ID = "5E:2E:EA:YY:YY:YY"
|
||||
|
||||
|
||||
def _mock_nanoleaf(
|
||||
host: str = TEST_HOST,
|
||||
auth_token: str = TEST_TOKEN,
|
||||
authorize_error: Exception | None = None,
|
||||
get_info_error: Exception | None = None,
|
||||
):
|
||||
nanoleaf = MagicMock()
|
||||
nanoleaf.name = TEST_NAME
|
||||
nanoleaf.host = host
|
||||
nanoleaf.auth_token = auth_token
|
||||
nanoleaf.authorize = AsyncMock(side_effect=authorize_error)
|
||||
nanoleaf.get_info = AsyncMock(side_effect=get_info_error)
|
||||
return nanoleaf
|
||||
|
||||
|
||||
async def test_user_unavailable_user_step_link_step(hass: HomeAssistant) -> None:
|
||||
"""Test we handle Unavailable in user and link step."""
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
|
@ -30,7 +44,7 @@ async def test_user_unavailable_user_step_link_step(hass: HomeAssistant) -> None
|
|||
)
|
||||
with patch(
|
||||
"homeassistant.components.nanoleaf.config_flow.Nanoleaf.authorize",
|
||||
side_effect=Unavailable("message"),
|
||||
side_effect=Unavailable,
|
||||
):
|
||||
result2 = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
|
@ -58,7 +72,7 @@ async def test_user_unavailable_user_step_link_step(hass: HomeAssistant) -> None
|
|||
|
||||
with patch(
|
||||
"homeassistant.components.nanoleaf.config_flow.Nanoleaf.authorize",
|
||||
side_effect=Unavailable("message"),
|
||||
side_effect=Unavailable,
|
||||
):
|
||||
result3 = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
|
@ -71,8 +85,8 @@ async def test_user_unavailable_user_step_link_step(hass: HomeAssistant) -> None
|
|||
@pytest.mark.parametrize(
|
||||
"error, reason",
|
||||
[
|
||||
(Unavailable("message"), "cannot_connect"),
|
||||
(InvalidToken("message"), "invalid_token"),
|
||||
(Unavailable, "cannot_connect"),
|
||||
(InvalidToken, "invalid_token"),
|
||||
(Exception, "unknown"),
|
||||
],
|
||||
)
|
||||
|
@ -85,7 +99,6 @@ async def test_user_error_setup_finish(
|
|||
)
|
||||
with patch(
|
||||
"homeassistant.components.nanoleaf.config_flow.Nanoleaf.authorize",
|
||||
return_value=None,
|
||||
):
|
||||
result2 = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
|
@ -98,9 +111,8 @@ async def test_user_error_setup_finish(
|
|||
|
||||
with patch(
|
||||
"homeassistant.components.nanoleaf.config_flow.Nanoleaf.authorize",
|
||||
return_value=None,
|
||||
), patch(
|
||||
"homeassistant.components.nanoleaf.config_flow.pynanoleaf_get_info",
|
||||
"homeassistant.components.nanoleaf.config_flow.Nanoleaf.get_info",
|
||||
side_effect=error,
|
||||
):
|
||||
result3 = await hass.config_entries.flow.async_configure(
|
||||
|
@ -117,19 +129,10 @@ async def test_user_not_authorizing_new_tokens_user_step_link_step(
|
|||
"""Test we handle NotAuthorizingNewTokens in user step and link step."""
|
||||
with patch(
|
||||
"homeassistant.components.nanoleaf.config_flow.Nanoleaf",
|
||||
return_value=_mock_nanoleaf(authorize_error=Unauthorized()),
|
||||
) as mock_nanoleaf, patch(
|
||||
"homeassistant.components.nanoleaf.config_flow.pynanoleaf_get_info",
|
||||
return_value={"name": TEST_NAME},
|
||||
), patch(
|
||||
"homeassistant.components.nanoleaf.async_setup_entry", return_value=True
|
||||
) as mock_setup_entry:
|
||||
nanoleaf = mock_nanoleaf.return_value
|
||||
nanoleaf.authorize.side_effect = NotAuthorizingNewTokens(
|
||||
"Not authorizing new tokens"
|
||||
)
|
||||
nanoleaf.host = TEST_HOST
|
||||
nanoleaf.token = TEST_TOKEN
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
|
@ -160,8 +163,7 @@ async def test_user_not_authorizing_new_tokens_user_step_link_step(
|
|||
assert result4["errors"] == {"base": "not_allowing_new_tokens"}
|
||||
assert result4["step_id"] == "link"
|
||||
|
||||
nanoleaf.authorize.side_effect = None
|
||||
nanoleaf.authorize.return_value = None
|
||||
mock_nanoleaf.return_value.authorize.side_effect = None
|
||||
|
||||
result5 = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
|
@ -183,8 +185,8 @@ async def test_user_exception_user_step(hass: HomeAssistant) -> None:
|
|||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
with patch(
|
||||
"homeassistant.components.nanoleaf.config_flow.Nanoleaf.authorize",
|
||||
side_effect=Exception,
|
||||
"homeassistant.components.nanoleaf.config_flow.Nanoleaf",
|
||||
return_value=_mock_nanoleaf(authorize_error=Exception()),
|
||||
):
|
||||
result2 = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
|
@ -198,9 +200,9 @@ async def test_user_exception_user_step(hass: HomeAssistant) -> None:
|
|||
assert not result2["last_step"]
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.nanoleaf.config_flow.Nanoleaf.authorize",
|
||||
return_value=None,
|
||||
):
|
||||
"homeassistant.components.nanoleaf.config_flow.Nanoleaf",
|
||||
return_value=_mock_nanoleaf(),
|
||||
) as mock_nanoleaf:
|
||||
result3 = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
{
|
||||
|
@ -209,10 +211,8 @@ async def test_user_exception_user_step(hass: HomeAssistant) -> None:
|
|||
)
|
||||
assert result3["step_id"] == "link"
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.nanoleaf.config_flow.Nanoleaf.authorize",
|
||||
side_effect=Exception,
|
||||
):
|
||||
mock_nanoleaf.return_value.authorize.side_effect = Exception()
|
||||
|
||||
result4 = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
{},
|
||||
|
@ -221,13 +221,8 @@ async def test_user_exception_user_step(hass: HomeAssistant) -> None:
|
|||
assert result4["step_id"] == "link"
|
||||
assert result4["errors"] == {"base": "unknown"}
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.nanoleaf.config_flow.Nanoleaf.authorize",
|
||||
return_value=None,
|
||||
), patch(
|
||||
"homeassistant.components.nanoleaf.config_flow.pynanoleaf_get_info",
|
||||
side_effect=Exception,
|
||||
):
|
||||
mock_nanoleaf.return_value.authorize.side_effect = None
|
||||
mock_nanoleaf.return_value.get_info.side_effect = Exception()
|
||||
result5 = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
{},
|
||||
|
@ -249,8 +244,7 @@ async def test_discovery_link_unavailable(
|
|||
) -> None:
|
||||
"""Test discovery and abort if device is unavailable."""
|
||||
with patch(
|
||||
"homeassistant.components.nanoleaf.config_flow.pynanoleaf_get_info",
|
||||
return_value={"name": TEST_NAME},
|
||||
"homeassistant.components.nanoleaf.config_flow.Nanoleaf.get_info",
|
||||
), patch(
|
||||
"homeassistant.components.nanoleaf.config_flow.load_json",
|
||||
return_value={},
|
||||
|
@ -278,7 +272,7 @@ async def test_discovery_link_unavailable(
|
|||
|
||||
with patch(
|
||||
"homeassistant.components.nanoleaf.config_flow.Nanoleaf.authorize",
|
||||
side_effect=Unavailable("message"),
|
||||
side_effect=Unavailable,
|
||||
):
|
||||
result = await hass.config_entries.flow.async_configure(result["flow_id"], {})
|
||||
assert result["type"] == "abort"
|
||||
|
@ -287,10 +281,6 @@ async def test_discovery_link_unavailable(
|
|||
|
||||
async def test_reauth(hass: HomeAssistant) -> None:
|
||||
"""Test Nanoleaf reauth flow."""
|
||||
nanoleaf = MagicMock()
|
||||
nanoleaf.host = TEST_HOST
|
||||
nanoleaf.token = TEST_TOKEN
|
||||
|
||||
entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
unique_id=TEST_NAME,
|
||||
|
@ -300,7 +290,7 @@ async def test_reauth(hass: HomeAssistant) -> None:
|
|||
|
||||
with patch(
|
||||
"homeassistant.components.nanoleaf.config_flow.Nanoleaf",
|
||||
return_value=nanoleaf,
|
||||
return_value=_mock_nanoleaf(),
|
||||
), patch(
|
||||
"homeassistant.components.nanoleaf.async_setup_entry",
|
||||
return_value=True,
|
||||
|
@ -331,8 +321,8 @@ async def test_reauth(hass: HomeAssistant) -> None:
|
|||
async def test_import_config(hass: HomeAssistant) -> None:
|
||||
"""Test configuration import."""
|
||||
with patch(
|
||||
"homeassistant.components.nanoleaf.config_flow.pynanoleaf_get_info",
|
||||
return_value={"name": TEST_NAME},
|
||||
"homeassistant.components.nanoleaf.config_flow.Nanoleaf",
|
||||
return_value=_mock_nanoleaf(TEST_HOST, TEST_TOKEN),
|
||||
), patch(
|
||||
"homeassistant.components.nanoleaf.async_setup_entry",
|
||||
return_value=True,
|
||||
|
@ -355,17 +345,17 @@ async def test_import_config(hass: HomeAssistant) -> None:
|
|||
@pytest.mark.parametrize(
|
||||
"error, reason",
|
||||
[
|
||||
(Unavailable("message"), "cannot_connect"),
|
||||
(InvalidToken("message"), "invalid_token"),
|
||||
(Unavailable, "cannot_connect"),
|
||||
(InvalidToken, "invalid_token"),
|
||||
(Exception, "unknown"),
|
||||
],
|
||||
)
|
||||
async def test_import_config_error(
|
||||
hass: HomeAssistant, error: NanoleafError, reason: str
|
||||
hass: HomeAssistant, error: NanoleafException, reason: str
|
||||
) -> None:
|
||||
"""Test configuration import with errors in setup_finish."""
|
||||
with patch(
|
||||
"homeassistant.components.nanoleaf.config_flow.pynanoleaf_get_info",
|
||||
"homeassistant.components.nanoleaf.config_flow.Nanoleaf.get_info",
|
||||
side_effect=error,
|
||||
):
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
|
@ -432,8 +422,8 @@ async def test_import_discovery_integration(
|
|||
"homeassistant.components.nanoleaf.config_flow.load_json",
|
||||
return_value=dict(nanoleaf_conf_file),
|
||||
), patch(
|
||||
"homeassistant.components.nanoleaf.config_flow.pynanoleaf_get_info",
|
||||
return_value={"name": TEST_NAME},
|
||||
"homeassistant.components.nanoleaf.config_flow.Nanoleaf",
|
||||
return_value=_mock_nanoleaf(TEST_HOST, TEST_TOKEN),
|
||||
), patch(
|
||||
"homeassistant.components.nanoleaf.config_flow.save_json",
|
||||
return_value=None,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue