mirror of https://github.com/home-assistant/core
278 lines
8.3 KiB
Python
278 lines
8.3 KiB
Python
"""Test the roon config flow."""
|
|
|
|
from unittest.mock import patch
|
|
|
|
from homeassistant import config_entries
|
|
from homeassistant.components.roon.const import DOMAIN
|
|
from homeassistant.core import HomeAssistant
|
|
from homeassistant.data_entry_flow import FlowResultType
|
|
|
|
from tests.common import MockConfigEntry
|
|
|
|
|
|
class RoonApiMock:
|
|
"""Class to mock the Roon API for testing."""
|
|
|
|
@property
|
|
def token(self):
|
|
"""Return a good authentication key."""
|
|
return "good_token"
|
|
|
|
@property
|
|
def core_id(self):
|
|
"""Return the roon host."""
|
|
return "core_id"
|
|
|
|
@property
|
|
def core_name(self):
|
|
"""Return the roon core name."""
|
|
return "Roon Core"
|
|
|
|
def stop(self):
|
|
"""Stop socket."""
|
|
return
|
|
|
|
|
|
class RoonApiMockNoToken(RoonApiMock):
|
|
"""Class to mock the Roon API for testing, with failed authorisation."""
|
|
|
|
@property
|
|
def token(self):
|
|
"""Return a bad authentication key."""
|
|
return None
|
|
|
|
|
|
class RoonApiMockException(RoonApiMock):
|
|
"""Class to mock the Roon API for testing, throws an unexpected exception."""
|
|
|
|
@property
|
|
def token(self):
|
|
"""Throw exception."""
|
|
raise Exception # noqa: TRY002
|
|
|
|
|
|
class RoonDiscoveryMock:
|
|
"""Class to mock Roon Discovery for testing."""
|
|
|
|
def all(self):
|
|
"""Return a discovered roon server."""
|
|
return ["2.2.2.2"]
|
|
|
|
def stop(self):
|
|
"""Stop discovery running."""
|
|
return
|
|
|
|
|
|
class RoonDiscoveryFailedMock(RoonDiscoveryMock):
|
|
"""Class to mock Roon Discovery for testing, with no servers discovered."""
|
|
|
|
def all(self):
|
|
"""Return no discovered roon servers."""
|
|
return []
|
|
|
|
|
|
async def test_successful_discovery_and_auth(hass: HomeAssistant) -> None:
|
|
"""Test when discovery and auth both work ok."""
|
|
|
|
with (
|
|
patch(
|
|
"homeassistant.components.roon.config_flow.RoonApi",
|
|
return_value=RoonApiMock(),
|
|
),
|
|
patch(
|
|
"homeassistant.components.roon.config_flow.RoonDiscovery",
|
|
return_value=RoonDiscoveryMock(),
|
|
),
|
|
patch(
|
|
"homeassistant.components.roon.async_setup_entry",
|
|
return_value=True,
|
|
),
|
|
):
|
|
result = await hass.config_entries.flow.async_init(
|
|
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
|
)
|
|
await hass.async_block_till_done()
|
|
|
|
# Should go straight to link if server was discovered
|
|
assert result["type"] is FlowResultType.FORM
|
|
assert result["step_id"] == "link"
|
|
assert result["errors"] == {}
|
|
|
|
result2 = await hass.config_entries.flow.async_configure(
|
|
result["flow_id"], user_input={}
|
|
)
|
|
await hass.async_block_till_done()
|
|
|
|
assert result2["title"] == "Roon Labs Music Player"
|
|
assert result2["data"] == {
|
|
"host": None,
|
|
"port": None,
|
|
"api_key": "good_token",
|
|
"roon_server_id": "core_id",
|
|
"roon_server_name": "Roon Core",
|
|
}
|
|
|
|
|
|
async def test_unsuccessful_discovery_user_form_and_auth(hass: HomeAssistant) -> None:
|
|
"""Test unsuccessful discover, user adding the host via the form and then successful auth."""
|
|
|
|
with (
|
|
patch(
|
|
"homeassistant.components.roon.config_flow.RoonApi",
|
|
return_value=RoonApiMock(),
|
|
),
|
|
patch(
|
|
"homeassistant.components.roon.config_flow.RoonDiscovery",
|
|
return_value=RoonDiscoveryFailedMock(),
|
|
),
|
|
patch(
|
|
"homeassistant.components.roon.async_setup_entry",
|
|
return_value=True,
|
|
),
|
|
):
|
|
result = await hass.config_entries.flow.async_init(
|
|
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
|
)
|
|
await hass.async_block_till_done()
|
|
|
|
# Should show the form if server was not discovered
|
|
assert result["type"] is FlowResultType.FORM
|
|
assert result["step_id"] == "fallback"
|
|
assert result["errors"] == {}
|
|
|
|
await hass.config_entries.flow.async_configure(
|
|
result["flow_id"], {"host": "1.1.1.1", "port": 9331}
|
|
)
|
|
result2 = await hass.config_entries.flow.async_configure(
|
|
result["flow_id"], user_input={}
|
|
)
|
|
await hass.async_block_till_done()
|
|
|
|
assert result2["title"] == "Roon Labs Music Player"
|
|
assert result2["data"] == {
|
|
"host": "1.1.1.1",
|
|
"api_key": "good_token",
|
|
"port": 9331,
|
|
"roon_server_id": "core_id",
|
|
"roon_server_name": "Roon Core",
|
|
}
|
|
|
|
|
|
async def test_duplicate_config(hass: HomeAssistant) -> None:
|
|
"""Test user adding the host via the form for host that is already configured."""
|
|
|
|
CONFIG = {"host": "1.1.1.1"}
|
|
|
|
MockConfigEntry(domain=DOMAIN, unique_id="0123456789", data=CONFIG).add_to_hass(
|
|
hass
|
|
)
|
|
|
|
with (
|
|
patch(
|
|
"homeassistant.components.roon.config_flow.RoonApi",
|
|
return_value=RoonApiMock(),
|
|
),
|
|
patch(
|
|
"homeassistant.components.roon.config_flow.RoonDiscovery",
|
|
return_value=RoonDiscoveryFailedMock(),
|
|
),
|
|
):
|
|
result = await hass.config_entries.flow.async_init(
|
|
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
|
)
|
|
await hass.async_block_till_done()
|
|
|
|
# Should show the form if server was not discovered
|
|
assert result["type"] is FlowResultType.FORM
|
|
assert result["step_id"] == "fallback"
|
|
assert result["errors"] == {}
|
|
|
|
await hass.config_entries.flow.async_configure(
|
|
result["flow_id"], {"host": "1.1.1.1", "port": 9331}
|
|
)
|
|
result2 = await hass.config_entries.flow.async_configure(
|
|
result["flow_id"], user_input={}
|
|
)
|
|
await hass.async_block_till_done()
|
|
|
|
assert result2["type"] is FlowResultType.ABORT
|
|
assert result2["reason"] == "already_configured"
|
|
|
|
|
|
async def test_successful_discovery_no_auth(hass: HomeAssistant) -> None:
|
|
"""Test successful discover, but failed auth."""
|
|
|
|
with (
|
|
patch(
|
|
"homeassistant.components.roon.config_flow.RoonApi",
|
|
return_value=RoonApiMockNoToken(),
|
|
),
|
|
patch(
|
|
"homeassistant.components.roon.config_flow.RoonDiscovery",
|
|
return_value=RoonDiscoveryMock(),
|
|
),
|
|
patch(
|
|
"homeassistant.components.roon.config_flow.TIMEOUT",
|
|
0,
|
|
),
|
|
patch(
|
|
"homeassistant.components.roon.config_flow.AUTHENTICATE_TIMEOUT",
|
|
0.01,
|
|
),
|
|
patch(
|
|
"homeassistant.components.roon.async_setup_entry",
|
|
return_value=True,
|
|
),
|
|
):
|
|
result = await hass.config_entries.flow.async_init(
|
|
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
|
)
|
|
await hass.async_block_till_done()
|
|
|
|
# Should go straight to link if server was discovered
|
|
assert result["type"] is FlowResultType.FORM
|
|
assert result["step_id"] == "link"
|
|
assert result["errors"] == {}
|
|
|
|
result2 = await hass.config_entries.flow.async_configure(
|
|
result["flow_id"], user_input={}
|
|
)
|
|
await hass.async_block_till_done()
|
|
|
|
assert result2["errors"] == {"base": "invalid_auth"}
|
|
|
|
|
|
async def test_unexpected_exception(hass: HomeAssistant) -> None:
|
|
"""Test successful discover, and unexpected exception during auth."""
|
|
|
|
with (
|
|
patch(
|
|
"homeassistant.components.roon.config_flow.RoonApi",
|
|
return_value=RoonApiMockException(),
|
|
),
|
|
patch(
|
|
"homeassistant.components.roon.config_flow.RoonDiscovery",
|
|
return_value=RoonDiscoveryMock(),
|
|
),
|
|
patch(
|
|
"homeassistant.components.roon.async_setup_entry",
|
|
return_value=True,
|
|
),
|
|
):
|
|
result = await hass.config_entries.flow.async_init(
|
|
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
|
)
|
|
await hass.async_block_till_done()
|
|
|
|
# Should go straight to link if server was discovered
|
|
assert result["type"] is FlowResultType.FORM
|
|
assert result["step_id"] == "link"
|
|
assert result["errors"] == {}
|
|
|
|
result2 = await hass.config_entries.flow.async_configure(
|
|
result["flow_id"], user_input={}
|
|
)
|
|
await hass.async_block_till_done()
|
|
|
|
assert result2["errors"] == {"base": "unknown"}
|