297 lines
9.7 KiB
Python
297 lines
9.7 KiB
Python
"""Tests for the AsusWrt config flow."""
|
|
from socket import gaierror
|
|
from unittest.mock import AsyncMock, Mock, patch
|
|
|
|
import pytest
|
|
|
|
from homeassistant import data_entry_flow
|
|
from homeassistant.components.asuswrt.const import (
|
|
CONF_DNSMASQ,
|
|
CONF_INTERFACE,
|
|
CONF_REQUIRE_IP,
|
|
CONF_SSH_KEY,
|
|
CONF_TRACK_UNKNOWN,
|
|
DOMAIN,
|
|
)
|
|
from homeassistant.components.device_tracker.const import CONF_CONSIDER_HOME
|
|
from homeassistant.config_entries import SOURCE_IMPORT, SOURCE_USER
|
|
from homeassistant.const import (
|
|
CONF_HOST,
|
|
CONF_MODE,
|
|
CONF_PASSWORD,
|
|
CONF_PORT,
|
|
CONF_PROTOCOL,
|
|
CONF_USERNAME,
|
|
)
|
|
|
|
from tests.common import MockConfigEntry
|
|
|
|
HOST = "myrouter.asuswrt.com"
|
|
IP_ADDRESS = "192.168.1.1"
|
|
SSH_KEY = "1234"
|
|
|
|
CONFIG_DATA = {
|
|
CONF_HOST: HOST,
|
|
CONF_PORT: 22,
|
|
CONF_PROTOCOL: "telnet",
|
|
CONF_USERNAME: "user",
|
|
CONF_PASSWORD: "pwd",
|
|
CONF_MODE: "ap",
|
|
}
|
|
|
|
|
|
@pytest.fixture(name="connect")
|
|
def mock_controller_connect():
|
|
"""Mock a successful connection."""
|
|
with patch("homeassistant.components.asuswrt.router.AsusWrt") as service_mock:
|
|
service_mock.return_value.connection.async_connect = AsyncMock()
|
|
service_mock.return_value.is_connected = True
|
|
service_mock.return_value.connection.disconnect = Mock()
|
|
yield service_mock
|
|
|
|
|
|
async def test_user(hass, connect):
|
|
"""Test user config."""
|
|
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"
|
|
|
|
# test with all provided
|
|
with patch(
|
|
"homeassistant.components.asuswrt.async_setup_entry",
|
|
return_value=True,
|
|
) as mock_setup_entry, patch(
|
|
"homeassistant.components.asuswrt.config_flow.socket.gethostbyname",
|
|
return_value=IP_ADDRESS,
|
|
):
|
|
result = await hass.config_entries.flow.async_init(
|
|
DOMAIN,
|
|
context={"source": SOURCE_USER},
|
|
data=CONFIG_DATA,
|
|
)
|
|
await hass.async_block_till_done()
|
|
|
|
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
|
|
assert result["title"] == HOST
|
|
assert result["data"] == CONFIG_DATA
|
|
|
|
assert len(mock_setup_entry.mock_calls) == 1
|
|
|
|
|
|
async def test_import(hass, connect):
|
|
"""Test import step."""
|
|
with patch(
|
|
"homeassistant.components.asuswrt.async_setup_entry",
|
|
return_value=True,
|
|
) as mock_setup_entry, patch(
|
|
"homeassistant.components.asuswrt.config_flow.socket.gethostbyname",
|
|
return_value=IP_ADDRESS,
|
|
):
|
|
result = await hass.config_entries.flow.async_init(
|
|
DOMAIN,
|
|
context={"source": SOURCE_IMPORT},
|
|
data=CONFIG_DATA,
|
|
)
|
|
await hass.async_block_till_done()
|
|
|
|
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
|
|
assert result["title"] == HOST
|
|
assert result["data"] == CONFIG_DATA
|
|
|
|
assert len(mock_setup_entry.mock_calls) == 1
|
|
|
|
|
|
async def test_import_ssh(hass, connect):
|
|
"""Test import step with ssh file."""
|
|
config_data = CONFIG_DATA.copy()
|
|
config_data.pop(CONF_PASSWORD)
|
|
config_data[CONF_SSH_KEY] = SSH_KEY
|
|
|
|
with patch(
|
|
"homeassistant.components.asuswrt.async_setup_entry",
|
|
return_value=True,
|
|
) as mock_setup_entry, patch(
|
|
"homeassistant.components.asuswrt.config_flow.socket.gethostbyname",
|
|
return_value=IP_ADDRESS,
|
|
), patch(
|
|
"homeassistant.components.asuswrt.config_flow.os.path.isfile",
|
|
return_value=True,
|
|
), patch(
|
|
"homeassistant.components.asuswrt.config_flow.os.access",
|
|
return_value=True,
|
|
):
|
|
result = await hass.config_entries.flow.async_init(
|
|
DOMAIN,
|
|
context={"source": SOURCE_IMPORT},
|
|
data=config_data,
|
|
)
|
|
await hass.async_block_till_done()
|
|
|
|
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
|
|
assert result["title"] == HOST
|
|
assert result["data"] == config_data
|
|
|
|
assert len(mock_setup_entry.mock_calls) == 1
|
|
|
|
|
|
async def test_error_no_password_ssh(hass):
|
|
"""Test we abort if component is already setup."""
|
|
config_data = CONFIG_DATA.copy()
|
|
config_data.pop(CONF_PASSWORD)
|
|
result = await hass.config_entries.flow.async_init(
|
|
DOMAIN,
|
|
context={"source": SOURCE_USER},
|
|
data=config_data,
|
|
)
|
|
|
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
|
assert result["errors"] == {"base": "pwd_or_ssh"}
|
|
|
|
|
|
async def test_error_both_password_ssh(hass):
|
|
"""Test we abort if component is already setup."""
|
|
config_data = CONFIG_DATA.copy()
|
|
config_data[CONF_SSH_KEY] = SSH_KEY
|
|
result = await hass.config_entries.flow.async_init(
|
|
DOMAIN,
|
|
context={"source": SOURCE_USER},
|
|
data=config_data,
|
|
)
|
|
|
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
|
assert result["errors"] == {"base": "pwd_and_ssh"}
|
|
|
|
|
|
async def test_error_invalid_ssh(hass):
|
|
"""Test we abort if component is already setup."""
|
|
config_data = CONFIG_DATA.copy()
|
|
config_data.pop(CONF_PASSWORD)
|
|
config_data[CONF_SSH_KEY] = SSH_KEY
|
|
result = await hass.config_entries.flow.async_init(
|
|
DOMAIN,
|
|
context={"source": SOURCE_USER},
|
|
data=config_data,
|
|
)
|
|
|
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
|
assert result["errors"] == {"base": "ssh_not_file"}
|
|
|
|
|
|
async def test_error_invalid_host(hass):
|
|
"""Test we abort if host name is invalid."""
|
|
with patch(
|
|
"homeassistant.components.asuswrt.config_flow.socket.gethostbyname",
|
|
side_effect=gaierror,
|
|
):
|
|
result = await hass.config_entries.flow.async_init(
|
|
DOMAIN,
|
|
context={"source": SOURCE_USER},
|
|
data=CONFIG_DATA,
|
|
)
|
|
|
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
|
assert result["errors"] == {"base": "invalid_host"}
|
|
|
|
|
|
async def test_abort_if_already_setup(hass):
|
|
"""Test we abort if component is already setup."""
|
|
MockConfigEntry(
|
|
domain=DOMAIN,
|
|
data=CONFIG_DATA,
|
|
).add_to_hass(hass)
|
|
|
|
with patch(
|
|
"homeassistant.components.asuswrt.config_flow.socket.gethostbyname",
|
|
return_value=IP_ADDRESS,
|
|
):
|
|
# Should fail, same HOST (flow)
|
|
result = await hass.config_entries.flow.async_init(
|
|
DOMAIN,
|
|
context={"source": SOURCE_USER},
|
|
data=CONFIG_DATA,
|
|
)
|
|
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
|
|
assert result["reason"] == "single_instance_allowed"
|
|
|
|
# Should fail, same HOST (import)
|
|
result = await hass.config_entries.flow.async_init(
|
|
DOMAIN,
|
|
context={"source": SOURCE_IMPORT},
|
|
data=CONFIG_DATA,
|
|
)
|
|
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
|
|
assert result["reason"] == "single_instance_allowed"
|
|
|
|
|
|
async def test_on_connect_failed(hass):
|
|
"""Test when we have errors connecting the router."""
|
|
flow_result = await hass.config_entries.flow.async_init(
|
|
DOMAIN,
|
|
context={"source": SOURCE_USER},
|
|
)
|
|
|
|
with patch("homeassistant.components.asuswrt.router.AsusWrt") as asus_wrt:
|
|
asus_wrt.return_value.connection.async_connect = AsyncMock()
|
|
asus_wrt.return_value.is_connected = False
|
|
result = await hass.config_entries.flow.async_configure(
|
|
flow_result["flow_id"], user_input=CONFIG_DATA
|
|
)
|
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
|
assert result["errors"] == {"base": "cannot_connect"}
|
|
|
|
with patch("homeassistant.components.asuswrt.router.AsusWrt") as asus_wrt:
|
|
asus_wrt.return_value.connection.async_connect = AsyncMock(side_effect=OSError)
|
|
result = await hass.config_entries.flow.async_configure(
|
|
flow_result["flow_id"], user_input=CONFIG_DATA
|
|
)
|
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
|
assert result["errors"] == {"base": "cannot_connect"}
|
|
|
|
with patch("homeassistant.components.asuswrt.router.AsusWrt") as asus_wrt:
|
|
asus_wrt.return_value.connection.async_connect = AsyncMock(
|
|
side_effect=TypeError
|
|
)
|
|
result = await hass.config_entries.flow.async_configure(
|
|
flow_result["flow_id"], user_input=CONFIG_DATA
|
|
)
|
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
|
assert result["errors"] == {"base": "unknown"}
|
|
|
|
|
|
async def test_options_flow(hass):
|
|
"""Test config flow options."""
|
|
config_entry = MockConfigEntry(
|
|
domain=DOMAIN,
|
|
data=CONFIG_DATA,
|
|
options={CONF_REQUIRE_IP: True},
|
|
)
|
|
config_entry.add_to_hass(hass)
|
|
|
|
with patch("homeassistant.components.asuswrt.async_setup_entry", return_value=True):
|
|
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: 20,
|
|
CONF_TRACK_UNKNOWN: True,
|
|
CONF_INTERFACE: "aaa",
|
|
CONF_DNSMASQ: "bbb",
|
|
CONF_REQUIRE_IP: False,
|
|
},
|
|
)
|
|
|
|
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
|
|
assert config_entry.options[CONF_CONSIDER_HOME] == 20
|
|
assert config_entry.options[CONF_TRACK_UNKNOWN] is True
|
|
assert config_entry.options[CONF_INTERFACE] == "aaa"
|
|
assert config_entry.options[CONF_DNSMASQ] == "bbb"
|
|
assert config_entry.options[CONF_REQUIRE_IP] is False
|