Handle more fritzbox edge cases (#34802)
parent
f47055a1b0
commit
996af94bb8
|
@ -2,6 +2,7 @@
|
||||||
from urllib.parse import urlparse
|
from urllib.parse import urlparse
|
||||||
|
|
||||||
from pyfritzhome import Fritzhome, LoginError
|
from pyfritzhome import Fritzhome, LoginError
|
||||||
|
from requests.exceptions import HTTPError
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant import config_entries
|
from homeassistant import config_entries
|
||||||
|
@ -32,6 +33,7 @@ DATA_SCHEMA_CONFIRM = vol.Schema(
|
||||||
|
|
||||||
RESULT_AUTH_FAILED = "auth_failed"
|
RESULT_AUTH_FAILED = "auth_failed"
|
||||||
RESULT_NOT_FOUND = "not_found"
|
RESULT_NOT_FOUND = "not_found"
|
||||||
|
RESULT_NOT_SUPPORTED = "not_supported"
|
||||||
RESULT_SUCCESS = "success"
|
RESULT_SUCCESS = "success"
|
||||||
|
|
||||||
|
|
||||||
|
@ -67,12 +69,15 @@ class FritzboxConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
fritzbox.login()
|
fritzbox.login()
|
||||||
|
fritzbox.get_device_elements()
|
||||||
fritzbox.logout()
|
fritzbox.logout()
|
||||||
return RESULT_SUCCESS
|
return RESULT_SUCCESS
|
||||||
except OSError:
|
|
||||||
return RESULT_NOT_FOUND
|
|
||||||
except LoginError:
|
except LoginError:
|
||||||
return RESULT_AUTH_FAILED
|
return RESULT_AUTH_FAILED
|
||||||
|
except HTTPError:
|
||||||
|
return RESULT_NOT_SUPPORTED
|
||||||
|
except OSError:
|
||||||
|
return RESULT_NOT_FOUND
|
||||||
|
|
||||||
async def async_step_import(self, user_input=None):
|
async def async_step_import(self, user_input=None):
|
||||||
"""Handle configuration by yaml file."""
|
"""Handle configuration by yaml file."""
|
||||||
|
@ -129,7 +134,7 @@ class FritzboxConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
||||||
return self.async_abort(reason="already_configured")
|
return self.async_abort(reason="already_configured")
|
||||||
|
|
||||||
self._host = host
|
self._host = host
|
||||||
self._name = user_input[ATTR_UPNP_FRIENDLY_NAME]
|
self._name = user_input.get(ATTR_UPNP_FRIENDLY_NAME) or host
|
||||||
|
|
||||||
self.context["title_placeholders"] = {"name": self._name}
|
self.context["title_placeholders"] = {"name": self._name}
|
||||||
return await self.async_step_confirm()
|
return await self.async_step_confirm()
|
||||||
|
|
|
@ -21,7 +21,8 @@
|
||||||
"abort": {
|
"abort": {
|
||||||
"already_in_progress": "AVM FRITZ!Box configuration is already in progress.",
|
"already_in_progress": "AVM FRITZ!Box configuration is already in progress.",
|
||||||
"already_configured": "This AVM FRITZ!Box is already configured.",
|
"already_configured": "This AVM FRITZ!Box is already configured.",
|
||||||
"not_found": "No supported AVM FRITZ!Box found on the network."
|
"not_found": "No supported AVM FRITZ!Box found on the network.",
|
||||||
|
"not_supported": "Connected to AVM FRITZ!Box but it's unable to control Smart Home devices."
|
||||||
},
|
},
|
||||||
"error": {
|
"error": {
|
||||||
"auth_failed": "Username and/or password are incorrect."
|
"auth_failed": "Username and/or password are incorrect."
|
||||||
|
|
|
@ -4,6 +4,7 @@ from unittest.mock import Mock, patch
|
||||||
|
|
||||||
from pyfritzhome import LoginError
|
from pyfritzhome import LoginError
|
||||||
import pytest
|
import pytest
|
||||||
|
from requests.exceptions import HTTPError
|
||||||
|
|
||||||
from homeassistant.components.fritzbox.const import DOMAIN
|
from homeassistant.components.fritzbox.const import DOMAIN
|
||||||
from homeassistant.components.ssdp import (
|
from homeassistant.components.ssdp import (
|
||||||
|
@ -121,6 +122,28 @@ async def test_ssdp(hass: HomeAssistantType, fritz: Mock):
|
||||||
assert result["result"].unique_id == "only-a-test"
|
assert result["result"].unique_id == "only-a-test"
|
||||||
|
|
||||||
|
|
||||||
|
async def test_ssdp_no_friendly_name(hass: HomeAssistantType, fritz: Mock):
|
||||||
|
"""Test starting a flow from discovery without friendly name."""
|
||||||
|
MOCK_NO_NAME = MOCK_SSDP_DATA.copy()
|
||||||
|
del MOCK_NO_NAME[ATTR_UPNP_FRIENDLY_NAME]
|
||||||
|
result = await hass.config_entries.flow.async_init(
|
||||||
|
DOMAIN, context={"source": "ssdp"}, data=MOCK_NO_NAME
|
||||||
|
)
|
||||||
|
assert result["type"] == "form"
|
||||||
|
assert result["step_id"] == "confirm"
|
||||||
|
|
||||||
|
result = await hass.config_entries.flow.async_configure(
|
||||||
|
result["flow_id"],
|
||||||
|
user_input={CONF_PASSWORD: "fake_pass", CONF_USERNAME: "fake_user"},
|
||||||
|
)
|
||||||
|
assert result["type"] == "create_entry"
|
||||||
|
assert result["title"] == "fake_host"
|
||||||
|
assert result["data"][CONF_HOST] == "fake_host"
|
||||||
|
assert result["data"][CONF_PASSWORD] == "fake_pass"
|
||||||
|
assert result["data"][CONF_USERNAME] == "fake_user"
|
||||||
|
assert result["result"].unique_id == "only-a-test"
|
||||||
|
|
||||||
|
|
||||||
async def test_ssdp_auth_failed(hass: HomeAssistantType, fritz: Mock):
|
async def test_ssdp_auth_failed(hass: HomeAssistantType, fritz: Mock):
|
||||||
"""Test starting a flow from discovery with authentication failure."""
|
"""Test starting a flow from discovery with authentication failure."""
|
||||||
fritz().login.side_effect = LoginError("Boom")
|
fritz().login.side_effect = LoginError("Boom")
|
||||||
|
@ -159,6 +182,24 @@ async def test_ssdp_not_successful(hass: HomeAssistantType, fritz: Mock):
|
||||||
assert result["reason"] == "not_found"
|
assert result["reason"] == "not_found"
|
||||||
|
|
||||||
|
|
||||||
|
async def test_ssdp_not_supported(hass: HomeAssistantType, fritz: Mock):
|
||||||
|
"""Test starting a flow from discovery with unsupported device."""
|
||||||
|
fritz().get_device_elements.side_effect = HTTPError("Boom")
|
||||||
|
|
||||||
|
result = await hass.config_entries.flow.async_init(
|
||||||
|
DOMAIN, context={"source": "ssdp"}, data=MOCK_SSDP_DATA
|
||||||
|
)
|
||||||
|
assert result["type"] == "form"
|
||||||
|
assert result["step_id"] == "confirm"
|
||||||
|
|
||||||
|
result = await hass.config_entries.flow.async_configure(
|
||||||
|
result["flow_id"],
|
||||||
|
user_input={CONF_PASSWORD: "whatever", CONF_USERNAME: "whatever"},
|
||||||
|
)
|
||||||
|
assert result["type"] == "abort"
|
||||||
|
assert result["reason"] == "not_supported"
|
||||||
|
|
||||||
|
|
||||||
async def test_ssdp_already_in_progress_unique_id(hass: HomeAssistantType, fritz: Mock):
|
async def test_ssdp_already_in_progress_unique_id(hass: HomeAssistantType, fritz: Mock):
|
||||||
"""Test starting a flow from discovery twice."""
|
"""Test starting a flow from discovery twice."""
|
||||||
result = await hass.config_entries.flow.async_init(
|
result = await hass.config_entries.flow.async_init(
|
||||||
|
|
Loading…
Reference in New Issue