mirror of
https://github.com/home-assistant/core.git
synced 2026-01-25 09:02:38 +01:00
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
283 lines
8.2 KiB
Python
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"
|