1
mirror of https://github.com/home-assistant/core synced 2024-09-06 10:29:55 +02:00

Handle more fritzbox edge cases (#34802)

This commit is contained in:
escoand 2020-04-29 07:17:35 +02:00 committed by GitHub
parent 592f316b3f
commit f64c35c3f9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 51 additions and 4 deletions

View File

@ -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()

View File

@ -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."

View File

@ -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(