Files
core/tests/components/wsdot/test_config_flow.py
Jeremiah Paige 7790a2ebdd Add config flow to wsdot (#149208)
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-12-29 18:58:09 +01:00

283 lines
8.2 KiB
Python

"""Define tests for the wsdot config flow."""
from typing import Any
from unittest.mock import AsyncMock
import pytest
from wsdot import WsdotTravelError
from homeassistant.components.wsdot.const import (
CONF_TRAVEL_TIMES,
DOMAIN,
SUBENTRY_TRAVEL_TIMES,
)
from homeassistant.config_entries import SOURCE_IMPORT, SOURCE_USER
from homeassistant.const import CONF_API_KEY, CONF_ID, CONF_NAME
from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import FlowResultType
from tests.common import MockConfigEntry
VALID_USER_CONFIG = {
CONF_API_KEY: "abcd-1234",
}
VALID_USER_TRAVEL_TIME_CONFIG = {
CONF_NAME: "Seattle-Bellevue via I-90 (EB AM)",
}
async def test_create_user_entry(
hass: HomeAssistant, mock_travel_time: AsyncMock
) -> None:
"""Test that the user step works."""
# No user data; form is being show for the first time
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_USER}
)
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "user"
# User data; the user entered data and hit submit
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
user_input=VALID_USER_CONFIG,
)
assert result["type"] is FlowResultType.CREATE_ENTRY
assert result["title"] == DOMAIN
assert result["data"][CONF_API_KEY] == "abcd-1234"
@pytest.mark.parametrize(
("failed_travel_time_status", "errors"),
[
(400, {CONF_API_KEY: "invalid_api_key"}),
(404, {"base": "cannot_connect"}),
],
)
async def test_errors(
hass: HomeAssistant,
mock_travel_time: AsyncMock,
mock_setup_entry: AsyncMock,
failed_travel_time_status: int,
errors: dict[str, str],
) -> None:
"""Test that the user step works."""
mock_travel_time.get_all_travel_times.side_effect = WsdotTravelError(
status=failed_travel_time_status
)
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_USER}
)
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "user"
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
user_input=VALID_USER_CONFIG,
)
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "user"
assert result["errors"] == errors
mock_travel_time.get_all_travel_times.side_effect = None
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
user_input=VALID_USER_CONFIG,
)
assert result["type"] is FlowResultType.CREATE_ENTRY
@pytest.mark.parametrize(
"mock_subentries",
[
[],
],
)
async def test_create_travel_time_subentry(
hass: HomeAssistant,
mock_travel_time: AsyncMock,
init_integration: MockConfigEntry,
) -> None:
"""Test that the user step for Travel Time works."""
# No user data; form is being show for the first time
result = await hass.config_entries.subentries.async_init(
(init_integration.entry_id, SUBENTRY_TRAVEL_TIMES),
context={"source": SOURCE_USER},
)
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "user"
# User data; the user made a choice and hit submit
result = await hass.config_entries.subentries.async_init(
(init_integration.entry_id, SUBENTRY_TRAVEL_TIMES),
context={"source": SOURCE_USER},
data=VALID_USER_TRAVEL_TIME_CONFIG,
)
assert result["type"] is FlowResultType.CREATE_ENTRY
assert result["data"][CONF_NAME] == "Seattle-Bellevue via I-90 (EB AM)"
assert result["data"][CONF_ID] == 96
@pytest.mark.parametrize(
"import_config",
[
{
CONF_API_KEY: "abcd-5678",
CONF_TRAVEL_TIMES: [{CONF_ID: 96, CONF_NAME: "I-90 EB"}],
},
{
CONF_API_KEY: "abcd-5678",
CONF_TRAVEL_TIMES: [{CONF_ID: "96", CONF_NAME: "I-90 EB"}],
},
],
ids=["with-int-id", "with-str-id"],
)
async def test_create_import_entry(
hass: HomeAssistant,
mock_travel_time: AsyncMock,
import_config: dict[str, str | int],
) -> None:
"""Test that the yaml import works."""
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": SOURCE_IMPORT},
data=import_config,
)
assert result["type"] is FlowResultType.CREATE_ENTRY
assert result["title"] == "wsdot"
assert result["data"][CONF_API_KEY] == "abcd-5678"
entry = result["result"]
assert entry is not None
assert len(entry.subentries) == 1
subentry = next(iter(entry.subentries.values()))
assert subentry.subentry_type == SUBENTRY_TRAVEL_TIMES
assert subentry.title == "Seattle-Bellevue via I-90 (EB AM)"
assert subentry.data[CONF_NAME] == "Seattle-Bellevue via I-90 (EB AM)"
assert subentry.data[CONF_ID] == 96
@pytest.mark.parametrize(
("failed_travel_time_status", "abort_reason"),
[
(400, "invalid_api_key"),
(404, "cannot_connect"),
],
)
async def test_failed_import_entry(
hass: HomeAssistant,
mock_failed_travel_time: AsyncMock,
mock_config_data: dict[str, Any],
failed_travel_time_status: int,
abort_reason: str,
) -> None:
"""Test the failure modes of a yaml import."""
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": SOURCE_IMPORT},
data=mock_config_data,
)
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == abort_reason
async def test_incorrect_import_entry(
hass: HomeAssistant,
mock_travel_time: AsyncMock,
mock_config_data: dict[str, Any],
) -> None:
"""Test a yaml import of a non-existent route."""
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": SOURCE_IMPORT},
data={
CONF_API_KEY: "abcd-5678",
CONF_TRAVEL_TIMES: [{CONF_ID: "100001", CONF_NAME: "nowhere"}],
},
)
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "invalid_travel_time_id"
async def test_import_integration_already_exists(
hass: HomeAssistant,
mock_travel_time: AsyncMock,
mock_setup_entry: AsyncMock,
mock_config_entry: MockConfigEntry,
init_integration: MockConfigEntry,
) -> None:
"""Test we only allow one entry per API key."""
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": SOURCE_IMPORT},
data={
CONF_API_KEY: "abcd-1234",
CONF_TRAVEL_TIMES: [{CONF_ID: "100001", CONF_NAME: "nowhere"}],
},
)
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "already_configured"
async def test_integration_already_exists(
hass: HomeAssistant,
mock_travel_time: AsyncMock,
mock_config_entry: MockConfigEntry,
init_integration: MockConfigEntry,
) -> None:
"""Test we only allow one entry per API key."""
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": SOURCE_USER},
)
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "user"
assert not result["errors"]
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
user_input=VALID_USER_CONFIG,
)
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "already_configured"
async def test_travel_route_already_exists(
hass: HomeAssistant,
mock_travel_time: AsyncMock,
mock_config_entry: MockConfigEntry,
init_integration: MockConfigEntry,
) -> None:
"""Test we only allow choosing a travel time route once."""
result = await hass.config_entries.subentries.async_init(
(init_integration.entry_id, SUBENTRY_TRAVEL_TIMES),
context={"source": SOURCE_USER},
)
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "user"
assert not result["errors"]
result = await hass.config_entries.subentries.async_configure(
result["flow_id"],
user_input=VALID_USER_TRAVEL_TIME_CONFIG,
)
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "already_configured"