Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions homeassistant/components/fritzbox/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from urllib.parse import urlparse

from pyfritzhome import Fritzhome, LoginError
from requests.exceptions import HTTPError
import voluptuous as vol

from homeassistant import config_entries
Expand Down Expand Up @@ -32,6 +33,7 @@

RESULT_AUTH_FAILED = "auth_failed"
RESULT_NOT_FOUND = "not_found"
RESULT_NOT_SUPPORTED = "not_supported"
RESULT_SUCCESS = "success"


Expand Down Expand Up @@ -67,12 +69,15 @@ def _try_connect(self):
)
try:
fritzbox.login()
fritzbox.get_device_elements()
fritzbox.logout()
return RESULT_SUCCESS
except OSError:
return RESULT_NOT_FOUND
except LoginError:
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):
"""Handle configuration by yaml file."""
Expand Down Expand Up @@ -129,7 +134,7 @@ async def async_step_ssdp(self, user_input):
return self.async_abort(reason="already_configured")

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}
return await self.async_step_confirm()
Expand Down
3 changes: 2 additions & 1 deletion homeassistant/components/fritzbox/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
"abort": {
"already_in_progress": "AVM FRITZ!Box configuration is already in progress.",
"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": {
"auth_failed": "Username and/or password are incorrect."
Expand Down
41 changes: 41 additions & 0 deletions tests/components/fritzbox/test_config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from pyfritzhome import LoginError
import pytest
from requests.exceptions import HTTPError

from homeassistant.components.fritzbox.const import DOMAIN
from homeassistant.components.ssdp import (
Expand Down Expand Up @@ -121,6 +122,28 @@ async def test_ssdp(hass: HomeAssistantType, fritz: Mock):
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):
"""Test starting a flow from discovery with authentication failure."""
fritz().login.side_effect = LoginError("Boom")
Expand Down Expand Up @@ -159,6 +182,24 @@ async def test_ssdp_not_successful(hass: HomeAssistantType, fritz: Mock):
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):
"""Test starting a flow from discovery twice."""
result = await hass.config_entries.flow.async_init(
Expand Down