core/tests/components/netgear/test_config_flow.py

282 lines
9.4 KiB
Python

"""Tests for the Netgear config flow."""
from unittest.mock import Mock, patch
from pynetgear import DEFAULT_HOST, DEFAULT_PORT, DEFAULT_USER
import pytest
from homeassistant import data_entry_flow
from homeassistant.components import ssdp
from homeassistant.components.netgear.const import CONF_CONSIDER_HOME, DOMAIN, ORBI_PORT
from homeassistant.config_entries import SOURCE_IMPORT, SOURCE_SSDP, SOURCE_USER
from homeassistant.const import (
CONF_HOST,
CONF_PASSWORD,
CONF_PORT,
CONF_SSL,
CONF_USERNAME,
)
from tests.common import MockConfigEntry
URL = "http://routerlogin.net"
SERIAL = "5ER1AL0000001"
ROUTER_INFOS = {
"Description": "Netgear Smart Wizard 3.0, specification 1.6 version",
"SignalStrength": "-4",
"SmartAgentversion": "3.0",
"FirewallVersion": "net-wall 2.0",
"VPNVersion": None,
"OthersoftwareVersion": "N/A",
"Hardwareversion": "N/A",
"Otherhardwareversion": "N/A",
"FirstUseDate": "Sunday, 30 Sep 2007 01:10:03",
"DeviceMode": "0",
"ModelName": "RBR20",
"SerialNumber": SERIAL,
"Firmwareversion": "V2.3.5.26",
"DeviceName": "Desk",
"DeviceNameUserSet": "true",
"FirmwareDLmethod": "HTTPS",
"FirmwareLastUpdate": "2019_10.5_18:42:58",
"FirmwareLastChecked": "2020_5.3_1:33:0",
"DeviceModeCapability": "0;1",
}
TITLE = f"{ROUTER_INFOS['ModelName']} - {ROUTER_INFOS['DeviceName']}"
HOST = "10.0.0.1"
SERIAL_2 = "5ER1AL0000002"
PORT = 80
SSL = False
USERNAME = "Home_Assistant"
PASSWORD = "password"
SSDP_URL = f"http://{HOST}:{PORT}/rootDesc.xml"
SSDP_URL_SLL = f"https://{HOST}:{PORT}/rootDesc.xml"
@pytest.fixture(name="service")
def mock_controller_service():
"""Mock a successful service."""
with patch(
"homeassistant.components.netgear.async_setup_entry", return_value=True
), patch("homeassistant.components.netgear.router.Netgear") as service_mock:
service_mock.return_value.get_info = Mock(return_value=ROUTER_INFOS)
yield service_mock
@pytest.fixture(name="service_failed")
def mock_controller_service_failed():
"""Mock a failed service."""
with patch("homeassistant.components.netgear.router.Netgear") as service_mock:
service_mock.return_value.login = Mock(return_value=None)
service_mock.return_value.get_info = Mock(return_value=None)
yield service_mock
async def test_user(hass, service):
"""Test user step."""
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_USER}
)
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
assert result["step_id"] == "user"
# Have to provide all config
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{
CONF_HOST: HOST,
CONF_PORT: PORT,
CONF_SSL: SSL,
CONF_USERNAME: USERNAME,
CONF_PASSWORD: PASSWORD,
},
)
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
assert result["result"].unique_id == SERIAL
assert result["title"] == TITLE
assert result["data"].get(CONF_HOST) == HOST
assert result["data"].get(CONF_PORT) == PORT
assert result["data"].get(CONF_SSL) == SSL
assert result["data"].get(CONF_USERNAME) == USERNAME
assert result["data"][CONF_PASSWORD] == PASSWORD
async def test_import_required(hass, service):
"""Test import step, with required config only."""
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_IMPORT}, data={CONF_PASSWORD: PASSWORD}
)
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
assert result["result"].unique_id == SERIAL
assert result["title"] == TITLE
assert result["data"].get(CONF_HOST) == DEFAULT_HOST
assert result["data"].get(CONF_PORT) == DEFAULT_PORT
assert result["data"].get(CONF_SSL) is False
assert result["data"].get(CONF_USERNAME) == DEFAULT_USER
assert result["data"][CONF_PASSWORD] == PASSWORD
async def test_import_required_login_failed(hass, service_failed):
"""Test import step, with required config only, while wrong password or connection issue."""
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_IMPORT}, data={CONF_PASSWORD: PASSWORD}
)
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
assert result["step_id"] == "user"
assert result["errors"] == {"base": "config"}
async def test_import_all(hass, service):
"""Test import step, with all config provided."""
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": SOURCE_IMPORT},
data={
CONF_HOST: HOST,
CONF_PORT: PORT,
CONF_SSL: SSL,
CONF_USERNAME: USERNAME,
CONF_PASSWORD: PASSWORD,
},
)
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
assert result["result"].unique_id == SERIAL
assert result["title"] == TITLE
assert result["data"].get(CONF_HOST) == HOST
assert result["data"].get(CONF_PORT) == PORT
assert result["data"].get(CONF_SSL) == SSL
assert result["data"].get(CONF_USERNAME) == USERNAME
assert result["data"][CONF_PASSWORD] == PASSWORD
async def test_import_all_connection_failed(hass, service_failed):
"""Test import step, with all config provided, while wrong host."""
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": SOURCE_IMPORT},
data={
CONF_HOST: HOST,
CONF_PORT: PORT,
CONF_SSL: SSL,
CONF_USERNAME: USERNAME,
CONF_PASSWORD: PASSWORD,
},
)
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
assert result["step_id"] == "user"
assert result["errors"] == {"base": "config"}
async def test_abort_if_already_setup(hass, service):
"""Test we abort if the router is already setup."""
MockConfigEntry(
domain=DOMAIN,
data={CONF_PASSWORD: PASSWORD},
unique_id=SERIAL,
).add_to_hass(hass)
# Should fail, same SERIAL (import)
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": SOURCE_IMPORT},
data={CONF_PASSWORD: PASSWORD},
)
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
assert result["reason"] == "already_configured"
# Should fail, same SERIAL (flow)
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_USER}
)
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
assert result["step_id"] == "user"
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{CONF_PASSWORD: PASSWORD},
)
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
assert result["reason"] == "already_configured"
async def test_ssdp_already_configured(hass):
"""Test ssdp abort when the router is already configured."""
MockConfigEntry(
domain=DOMAIN,
data={CONF_PASSWORD: PASSWORD},
unique_id=SERIAL,
).add_to_hass(hass)
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": SOURCE_SSDP},
data={
ssdp.ATTR_SSDP_LOCATION: SSDP_URL_SLL,
ssdp.ATTR_UPNP_MODEL_NUMBER: "RBR20",
ssdp.ATTR_UPNP_PRESENTATION_URL: URL,
ssdp.ATTR_UPNP_SERIAL: SERIAL,
},
)
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
assert result["reason"] == "already_configured"
async def test_ssdp(hass, service):
"""Test ssdp step."""
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": SOURCE_SSDP},
data={
ssdp.ATTR_SSDP_LOCATION: SSDP_URL,
ssdp.ATTR_UPNP_MODEL_NUMBER: "RBR20",
ssdp.ATTR_UPNP_PRESENTATION_URL: URL,
ssdp.ATTR_UPNP_SERIAL: SERIAL,
},
)
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
assert result["step_id"] == "user"
result = await hass.config_entries.flow.async_configure(
result["flow_id"], {CONF_PASSWORD: PASSWORD}
)
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
assert result["result"].unique_id == SERIAL
assert result["title"] == TITLE
assert result["data"].get(CONF_HOST) == HOST
assert result["data"].get(CONF_PORT) == ORBI_PORT
assert result["data"].get(CONF_SSL) == SSL
assert result["data"].get(CONF_USERNAME) == DEFAULT_USER
assert result["data"][CONF_PASSWORD] == PASSWORD
async def test_options_flow(hass, service):
"""Test specifying non default settings using options flow."""
config_entry = MockConfigEntry(
domain=DOMAIN,
data={CONF_PASSWORD: PASSWORD},
unique_id=SERIAL,
title=TITLE,
)
config_entry.add_to_hass(hass)
assert await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
result = await hass.config_entries.options.async_init(config_entry.entry_id)
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
assert result["step_id"] == "init"
result = await hass.config_entries.options.async_configure(
result["flow_id"],
user_input={
CONF_CONSIDER_HOME: 1800,
},
)
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
assert config_entry.options == {
CONF_CONSIDER_HOME: 1800,
}