Implement config flow for trafikverket_train (#65182)

This commit is contained in:
G Johansson 2022-03-29 20:32:38 +02:00 committed by GitHub
parent 425b825ae9
commit 06435f633f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 710 additions and 40 deletions

View file

@ -1272,6 +1272,7 @@ omit =
homeassistant/components/tradfri/light.py
homeassistant/components/tradfri/sensor.py
homeassistant/components/tradfri/switch.py
homeassistant/components/trafikverket_train/__init__.py
homeassistant/components/trafikverket_train/sensor.py
homeassistant/components/trafikverket_weatherstation/__init__.py
homeassistant/components/trafikverket_weatherstation/coordinator.py

View file

@ -1048,6 +1048,7 @@ build.json @home-assistant/supervisor
/homeassistant/components/tractive/ @Danielhiversen @zhulik @bieniu
/tests/components/tractive/ @Danielhiversen @zhulik @bieniu
/homeassistant/components/trafikverket_train/ @endor-force @gjohansson-ST
/tests/components/trafikverket_train/ @endor-force @gjohansson-ST
/homeassistant/components/trafikverket_weatherstation/ @endor-force @gjohansson-ST
/tests/components/trafikverket_weatherstation/ @endor-force @gjohansson-ST
/homeassistant/components/transmission/ @engrbm87 @JPHutchins
@ -1201,4 +1202,4 @@ build.json @home-assistant/supervisor
/homeassistant/components/demo/weather.py @fabaff
# Remove codeowners from files
/homeassistant/components/*/translations/
/homeassistant/components/*/translations/

View file

@ -1 +1,21 @@
"""The trafikverket_train component."""
from __future__ import annotations
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from .const import PLATFORMS
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Set up Trafikverket Train from a config entry."""
hass.config_entries.async_setup_platforms(entry, PLATFORMS)
return True
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Unload Trafikverket Weatherstation config entry."""
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)

View file

@ -0,0 +1,164 @@
"""Adds config flow for Trafikverket Train integration."""
from __future__ import annotations
from typing import Any
from pytrafikverket import TrafikverketTrain
import voluptuous as vol
from homeassistant import config_entries
from homeassistant.const import CONF_API_KEY, CONF_NAME, CONF_WEEKDAY, WEEKDAYS
from homeassistant.data_entry_flow import FlowResult
from homeassistant.helpers.aiohttp_client import async_get_clientsession
import homeassistant.helpers.config_validation as cv
import homeassistant.util.dt as dt_util
from .const import CONF_FROM, CONF_TIME, CONF_TO, DOMAIN
from .util import create_unique_id
ERROR_INVALID_AUTH = "Source: Security, message: Invalid authentication"
ERROR_INVALID_STATION = "Could not find a station with the specified name"
ERROR_MULTIPLE_STATION = "Found multiple stations with the specified name"
DATA_SCHEMA = vol.Schema(
{
vol.Required(CONF_API_KEY): cv.string,
vol.Required(CONF_FROM): cv.string,
vol.Required(CONF_TO): cv.string,
vol.Optional(CONF_TIME): cv.string,
vol.Required(CONF_WEEKDAY, default=WEEKDAYS): cv.multi_select(
{day: day for day in WEEKDAYS}
),
}
)
DATA_SCHEMA_REAUTH = vol.Schema(
{
vol.Required(CONF_API_KEY): cv.string,
}
)
class TVTrainConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
"""Handle a config flow for Trafikverket Train integration."""
VERSION = 1
entry: config_entries.ConfigEntry | None
async def validate_input(
self, api_key: str, train_from: str, train_to: str
) -> None:
"""Validate input from user input."""
web_session = async_get_clientsession(self.hass)
train_api = TrafikverketTrain(web_session, api_key)
await train_api.async_get_train_station(train_from)
await train_api.async_get_train_station(train_to)
async def async_step_reauth(
self, user_input: dict[str, Any] | None = None
) -> FlowResult:
"""Handle re-authentication with Trafikverket."""
self.entry = self.hass.config_entries.async_get_entry(self.context["entry_id"])
return await self.async_step_reauth_confirm()
async def async_step_reauth_confirm(
self, user_input: dict[str, Any] | None = None
) -> FlowResult:
"""Confirm re-authentication with Trafikverket."""
errors: dict[str, str] = {}
if user_input:
api_key = user_input[CONF_API_KEY]
assert self.entry is not None
try:
await self.validate_input(
api_key, self.entry.data[CONF_FROM], self.entry.data[CONF_TO]
)
except ValueError as err:
if str(err) == ERROR_INVALID_AUTH:
errors["base"] = "invalid_auth"
elif str(err) == ERROR_INVALID_STATION:
errors["base"] = "invalid_station"
elif str(err) == ERROR_MULTIPLE_STATION:
errors["base"] = "more_stations"
else:
errors["base"] = "cannot_connect"
else:
self.hass.config_entries.async_update_entry(
self.entry,
data={
**self.entry.data,
CONF_API_KEY: api_key,
},
)
await self.hass.config_entries.async_reload(self.entry.entry_id)
return self.async_abort(reason="reauth_successful")
return self.async_show_form(
step_id="reauth_confirm",
data_schema=DATA_SCHEMA_REAUTH,
errors=errors,
)
async def async_step_import(self, config: dict[str, Any] | None) -> FlowResult:
"""Import a configuration from config.yaml."""
return await self.async_step_user(user_input=config)
async def async_step_user(
self, user_input: dict[str, Any] | None = None
) -> FlowResult:
"""Handle the user step."""
errors: dict[str, str] = {}
if user_input is not None:
api_key: str = user_input[CONF_API_KEY]
train_from: str = user_input[CONF_FROM]
train_to: str = user_input[CONF_TO]
train_time: str | None = user_input.get(CONF_TIME)
train_days: list = user_input[CONF_WEEKDAY]
name = f"{train_from} to {train_to}"
if train_time:
name = f"{train_from} to {train_to} at {train_time}"
try:
await self.validate_input(api_key, train_from, train_to)
except ValueError as err:
if str(err) == ERROR_INVALID_AUTH:
errors["base"] = "invalid_auth"
elif str(err) == ERROR_INVALID_STATION:
errors["base"] = "invalid_station"
elif str(err) == ERROR_MULTIPLE_STATION:
errors["base"] = "more_stations"
else:
errors["base"] = "cannot_connect"
else:
if train_time:
if bool(dt_util.parse_time(train_time) is None):
errors["base"] = "invalid_time"
if not errors:
unique_id = create_unique_id(
train_from, train_to, train_time, train_days
)
await self.async_set_unique_id(unique_id)
self._abort_if_unique_id_configured()
return self.async_create_entry(
title=name,
data={
CONF_API_KEY: api_key,
CONF_NAME: name,
CONF_FROM: train_from,
CONF_TO: train_to,
CONF_TIME: train_time,
CONF_WEEKDAY: train_days,
},
)
return self.async_show_form(
step_id="user",
data_schema=DATA_SCHEMA,
errors=errors,
)

View file

@ -0,0 +1,11 @@
"""Adds constants for Trafikverket Train integration."""
from homeassistant.const import Platform
DOMAIN = "trafikverket_train"
PLATFORMS = [Platform.SENSOR]
ATTRIBUTION = "Data provided by Trafikverket"
CONF_TRAINS = "trains"
CONF_FROM = "from"
CONF_TO = "to"
CONF_TIME = "time"

View file

@ -4,6 +4,7 @@
"documentation": "https://www.home-assistant.io/integrations/trafikverket_train",
"requirements": ["pytrafikverket==0.1.6.2"],
"codeowners": ["@endor-force", "@gjohansson-ST"],
"config_flow": true,
"iot_class": "cloud_polling",
"loggers": ["pytrafikverket"]
}

View file

@ -14,21 +14,23 @@ from homeassistant.components.sensor import (
SensorDeviceClass,
SensorEntity,
)
from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry
from homeassistant.const import CONF_API_KEY, CONF_NAME, CONF_WEEKDAY, WEEKDAYS
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady
from homeassistant.helpers.aiohttp_client import async_get_clientsession
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.device_registry import DeviceEntryType
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from homeassistant.util.dt import as_utc, get_time_zone
from homeassistant.util.dt import as_utc, get_time_zone, parse_time
from .const import CONF_FROM, CONF_TIME, CONF_TO, CONF_TRAINS, DOMAIN
from .util import create_unique_id
_LOGGER = logging.getLogger(__name__)
CONF_TRAINS = "trains"
CONF_FROM = "from"
CONF_TO = "to"
CONF_TIME = "time"
ATTR_DEPARTURE_STATE = "departure_state"
ATTR_CANCELED = "canceled"
ATTR_DELAY_TIME = "number_of_minutes_delayed"
@ -66,43 +68,66 @@ async def async_setup_platform(
async_add_entities: AddEntitiesCallback,
discovery_info: DiscoveryInfoType | None = None,
) -> None:
"""Set up the departure sensor."""
httpsession = async_get_clientsession(hass)
train_api = TrafikverketTrain(httpsession, config[CONF_API_KEY])
sensors = []
station_cache = {}
"""Import Trafikverket Train configuration from YAML."""
_LOGGER.warning(
# Config flow added in Home Assistant Core 2022.3, remove import flow in 2022.7
"Loading Trafikverket Train via platform setup is deprecated; Please remove it from your configuration"
)
for train in config[CONF_TRAINS]:
try:
trainstops = [train[CONF_FROM], train[CONF_TO]]
for station in trainstops:
if station not in station_cache:
station_cache[station] = await train_api.async_get_train_station(
station
)
except ValueError as station_error:
if "Invalid authentication" in station_error.args[0]:
_LOGGER.error("Unable to set up up component: %s", station_error)
return
_LOGGER.error(
"Problem when trying station %s to %s. Error: %s ",
train[CONF_FROM],
train[CONF_TO],
station_error,
new_config = {
CONF_API_KEY: config[CONF_API_KEY],
CONF_FROM: train[CONF_FROM],
CONF_TO: train[CONF_TO],
CONF_TIME: str(train.get(CONF_TIME)),
CONF_WEEKDAY: train.get(CONF_WEEKDAY, WEEKDAYS),
}
hass.async_create_task(
hass.config_entries.flow.async_init(
DOMAIN,
context={"source": SOURCE_IMPORT},
data=new_config,
)
continue
sensor = TrainSensor(
train_api,
train[CONF_NAME],
station_cache[train[CONF_FROM]],
station_cache[train[CONF_TO]],
train[CONF_WEEKDAY],
train.get(CONF_TIME),
)
sensors.append(sensor)
async_add_entities(sensors, update_before_add=True)
async def async_setup_entry(
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
) -> None:
"""Set up the Trafikverket sensor entry."""
httpsession = async_get_clientsession(hass)
train_api = TrafikverketTrain(httpsession, entry.data[CONF_API_KEY])
try:
to_station = await train_api.async_get_train_station(entry.data[CONF_TO])
from_station = await train_api.async_get_train_station(entry.data[CONF_FROM])
except ValueError as error:
if "Invalid authentication" in error.args[0]:
raise ConfigEntryAuthFailed from error
raise ConfigEntryNotReady(
f"Problem when trying station {entry.data[CONF_FROM]} to {entry.data[CONF_TO]}. Error: {error} "
) from error
train_time = (
parse_time(entry.data.get(CONF_TIME, "")) if entry.data.get(CONF_TIME) else None
)
async_add_entities(
[
TrainSensor(
train_api,
entry.data[CONF_NAME],
from_station,
to_station,
entry.data[CONF_WEEKDAY],
train_time,
entry.entry_id,
)
],
True,
)
def next_weekday(fromdate: date, weekday: int) -> date:
@ -144,7 +169,8 @@ class TrainSensor(SensorEntity):
from_station: str,
to_station: str,
weekday: list,
departuretime: time,
departuretime: time | None,
entry_id: str,
) -> None:
"""Initialize the sensor."""
self._train_api = train_api
@ -153,6 +179,17 @@ class TrainSensor(SensorEntity):
self._to_station = to_station
self._weekday = weekday
self._time = departuretime
self._attr_device_info = DeviceInfo(
entry_type=DeviceEntryType.SERVICE,
identifiers={(DOMAIN, entry_id)},
manufacturer="Trafikverket",
model="v1.2",
name=name,
configuration_url="https://api.trafikinfo.trafikverket.se/",
)
self._attr_unique_id = create_unique_id(
from_station, to_station, departuretime, weekday
)
async def async_update(self) -> None:
"""Retrieve latest state."""

View file

@ -0,0 +1,32 @@
{
"config": {
"abort": {
"already_configured": "[%key:common::config_flow::abort::already_configured_account%]",
"reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]"
},
"error": {
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
"invalid_auth": "[%key:common::config_flow::error::invalid_auth%]",
"invalid_station": "Could not find a station with the specified name",
"more_stations": "Found multiple stations with the specified name",
"invalid_time": "Invalid time provided",
"incorrect_api_key": "Invalid API key for selected account"
},
"step": {
"user": {
"data": {
"api_key": "[%key:common::config_flow::data::api_key%]",
"to": "To station",
"from": "From station",
"time": "Time (optional)",
"weekday": "Days"
}
},
"reauth_confirm": {
"data": {
"api_key": "[%key:common::config_flow::data::api_key%]"
}
}
}
}
}

View file

@ -0,0 +1,32 @@
{
"config": {
"abort": {
"already_configured": "Account is already configured",
"reauth_successful": "Re-authentication was successful"
},
"error": {
"cannot_connect": "Failed to connect",
"invalid_auth": "Invalid authentication",
"invalid_station": "Could not find a station with the specified name",
"more_stations": "Found multiple stations with the specified name",
"invalid_time": "Invalid time provided",
"incorrect_api_key": "Invalid API key for selected account"
},
"step": {
"user": {
"data": {
"api_key": "API Key",
"to": "To station",
"from": "From station",
"time": "Time (optional)",
"weekday": "Days"
}
},
"reauth_confirm": {
"data": {
"api_key": "API Key"
}
}
}
}
}

View file

@ -0,0 +1,15 @@
"""Utils for trafikverket_train."""
from __future__ import annotations
from datetime import time
def create_unique_id(
from_station: str, to_station: str, depart_time: time | str | None, weekdays: list
) -> str:
"""Create unique id."""
timestr = str(depart_time) if depart_time else ""
return (
f"{from_station.casefold().replace(' ', '')}-{to_station.casefold().replace(' ', '')}"
f"-{timestr.casefold().replace(' ', '')}-{str(weekdays)}"
)

View file

@ -348,6 +348,7 @@ FLOWS = {
"traccar",
"tractive",
"tradfri",
"trafikverket_train",
"trafikverket_weatherstation",
"transmission",
"tuya",

View file

@ -0,0 +1 @@
"""Tests for the Trafikverket Train integration."""

View file

@ -0,0 +1,354 @@
"""Test the Trafikverket Train config flow."""
from __future__ import annotations
from unittest.mock import patch
import pytest
from homeassistant import config_entries
from homeassistant.components.trafikverket_train.const import (
CONF_FROM,
CONF_TIME,
CONF_TO,
DOMAIN,
)
from homeassistant.const import CONF_API_KEY, CONF_NAME, CONF_WEEKDAY, WEEKDAYS
from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import (
RESULT_TYPE_ABORT,
RESULT_TYPE_CREATE_ENTRY,
RESULT_TYPE_FORM,
)
from tests.common import MockConfigEntry
async def test_form(hass: HomeAssistant) -> None:
"""Test we get the form."""
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER}
)
assert result["type"] == RESULT_TYPE_FORM
assert result["errors"] == {}
with patch(
"homeassistant.components.trafikverket_train.config_flow.TrafikverketTrain.async_get_train_station",
), patch(
"homeassistant.components.trafikverket_train.async_setup_entry",
return_value=True,
) as mock_setup_entry:
result2 = await hass.config_entries.flow.async_configure(
result["flow_id"],
{
CONF_API_KEY: "1234567890",
CONF_FROM: "Stockholm C",
CONF_TO: "Uppsala C",
CONF_TIME: "10:00",
CONF_WEEKDAY: ["mon", "fri"],
},
)
await hass.async_block_till_done()
assert result2["type"] == RESULT_TYPE_CREATE_ENTRY
assert result2["title"] == "Stockholm C to Uppsala C at 10:00"
assert result2["data"] == {
"api_key": "1234567890",
"name": "Stockholm C to Uppsala C at 10:00",
"from": "Stockholm C",
"to": "Uppsala C",
"time": "10:00",
"weekday": ["mon", "fri"],
}
assert len(mock_setup_entry.mock_calls) == 1
assert result2["result"].unique_id == "{}-{}-{}-{}".format(
"stockholmc", "uppsalac", "10:00", "['mon', 'fri']"
)
async def test_import_flow_success(hass: HomeAssistant) -> None:
"""Test a successful import of yaml."""
with patch(
"homeassistant.components.trafikverket_train.config_flow.TrafikverketTrain.async_get_train_station",
), patch(
"homeassistant.components.trafikverket_train.async_setup_entry",
return_value=True,
) as mock_setup_entry:
result2 = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": config_entries.SOURCE_IMPORT},
data={
CONF_API_KEY: "1234567890",
CONF_FROM: "Stockholm C",
CONF_TO: "Uppsala C",
CONF_TIME: "10:00",
CONF_WEEKDAY: ["mon", "fri"],
},
)
await hass.async_block_till_done()
assert result2["type"] == RESULT_TYPE_CREATE_ENTRY
assert result2["title"] == "Stockholm C to Uppsala C at 10:00"
assert result2["data"] == {
"api_key": "1234567890",
"name": "Stockholm C to Uppsala C at 10:00",
"from": "Stockholm C",
"to": "Uppsala C",
"time": "10:00",
"weekday": ["mon", "fri"],
}
assert len(mock_setup_entry.mock_calls) == 1
async def test_import_flow_already_exist(hass: HomeAssistant) -> None:
"""Test import of yaml already exist."""
MockConfigEntry(
domain=DOMAIN,
data={
CONF_API_KEY: "1234567890",
CONF_NAME: "Stockholm C to Uppsala C",
CONF_FROM: "Stockholm C",
CONF_TO: "Uppsala C",
CONF_TIME: "10:00",
CONF_WEEKDAY: WEEKDAYS,
},
unique_id=f"stockholmc-uppsalac-10:00-{WEEKDAYS}",
).add_to_hass(hass)
with patch(
"homeassistant.components.trafikverket_train.async_setup_entry",
return_value=True,
), patch(
"homeassistant.components.trafikverket_train.config_flow.TrafikverketTrain.async_get_train_station",
):
result3 = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": config_entries.SOURCE_IMPORT},
data={
CONF_NAME: "Stockholm C to Uppsala C",
CONF_API_KEY: "1234567890",
CONF_FROM: "Stockholm C",
CONF_TO: "Uppsala C",
CONF_TIME: "10:00",
CONF_WEEKDAY: WEEKDAYS,
},
)
await hass.async_block_till_done()
assert result3["type"] == RESULT_TYPE_ABORT
assert result3["reason"] == "already_configured"
@pytest.mark.parametrize(
"error_message,base_error",
[
(
"Source: Security, message: Invalid authentication",
"invalid_auth",
),
(
"Could not find a station with the specified name",
"invalid_station",
),
(
"Found multiple stations with the specified name",
"more_stations",
),
(
"Unknown",
"cannot_connect",
),
],
)
async def test_flow_fails(
hass: HomeAssistant, error_message: str, base_error: str
) -> None:
"""Test config flow errors."""
result4 = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER}
)
assert result4["type"] == RESULT_TYPE_FORM
assert result4["step_id"] == config_entries.SOURCE_USER
with patch(
"homeassistant.components.trafikverket_train.config_flow.TrafikverketTrain.async_get_train_station",
side_effect=ValueError(error_message),
):
result4 = await hass.config_entries.flow.async_configure(
result4["flow_id"],
user_input={
CONF_API_KEY: "1234567890",
CONF_FROM: "Stockholm C",
CONF_TO: "Uppsala C",
},
)
assert result4["errors"] == {"base": base_error}
async def test_flow_fails_incorrect_time(hass: HomeAssistant) -> None:
"""Test config flow errors due to bad time."""
result5 = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER}
)
assert result5["type"] == RESULT_TYPE_FORM
assert result5["step_id"] == config_entries.SOURCE_USER
with patch(
"homeassistant.components.trafikverket_train.config_flow.TrafikverketTrain.async_get_train_station",
):
result6 = await hass.config_entries.flow.async_configure(
result5["flow_id"],
user_input={
CONF_API_KEY: "1234567890",
CONF_FROM: "Stockholm C",
CONF_TO: "Uppsala C",
CONF_TIME: "25:25",
},
)
assert result6["errors"] == {"base": "invalid_time"}
async def test_reauth_flow(hass: HomeAssistant) -> None:
"""Test a reauthentication flow."""
entry = MockConfigEntry(
domain=DOMAIN,
data={
CONF_API_KEY: "1234567890",
CONF_NAME: "Stockholm C to Uppsala C at 10:00",
CONF_FROM: "Stockholm C",
CONF_TO: "Uppsala C",
CONF_TIME: "10:00",
CONF_WEEKDAY: WEEKDAYS,
},
unique_id=f"stockholmc-uppsalac-10:00-{WEEKDAYS}",
)
entry.add_to_hass(hass)
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={
"source": config_entries.SOURCE_REAUTH,
"unique_id": entry.unique_id,
"entry_id": entry.entry_id,
},
data=entry.data,
)
assert result["step_id"] == "reauth_confirm"
assert result["type"] == RESULT_TYPE_FORM
assert result["errors"] == {}
with patch(
"homeassistant.components.trafikverket_train.config_flow.TrafikverketTrain.async_get_train_station",
), patch(
"homeassistant.components.trafikverket_train.async_setup_entry",
return_value=True,
):
result2 = await hass.config_entries.flow.async_configure(
result["flow_id"],
{CONF_API_KEY: "1234567891"},
)
await hass.async_block_till_done()
assert result2["type"] == RESULT_TYPE_ABORT
assert result2["reason"] == "reauth_successful"
assert entry.data == {
"api_key": "1234567891",
"name": "Stockholm C to Uppsala C at 10:00",
"from": "Stockholm C",
"to": "Uppsala C",
"time": "10:00",
"weekday": ["mon", "tue", "wed", "thu", "fri", "sat", "sun"],
}
@pytest.mark.parametrize(
"sideeffect,p_error",
[
(
ValueError("Source: Security, message: Invalid authentication"),
"invalid_auth",
),
(
ValueError("Could not find a station with the specified name"),
"invalid_station",
),
(
ValueError("Found multiple stations with the specified name"),
"more_stations",
),
(
ValueError("Unknown"),
"cannot_connect",
),
],
)
async def test_reauth_flow_error(
hass: HomeAssistant, sideeffect: Exception, p_error: str
) -> None:
"""Test a reauthentication flow with error."""
entry = MockConfigEntry(
domain=DOMAIN,
data={
CONF_API_KEY: "1234567890",
CONF_NAME: "Stockholm C to Uppsala C at 10:00",
CONF_FROM: "Stockholm C",
CONF_TO: "Uppsala C",
CONF_TIME: "10:00",
CONF_WEEKDAY: WEEKDAYS,
},
unique_id=f"stockholmc-uppsalac-10:00-{WEEKDAYS}",
)
entry.add_to_hass(hass)
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={
"source": config_entries.SOURCE_REAUTH,
"unique_id": entry.unique_id,
"entry_id": entry.entry_id,
},
data=entry.data,
)
with patch(
"homeassistant.components.trafikverket_train.config_flow.TrafikverketTrain.async_get_train_station",
side_effect=sideeffect,
):
result2 = await hass.config_entries.flow.async_configure(
result["flow_id"],
{CONF_API_KEY: "1234567890"},
)
await hass.async_block_till_done()
assert result2["step_id"] == "reauth_confirm"
assert result2["type"] == RESULT_TYPE_FORM
assert result2["errors"] == {"base": p_error}
with patch(
"homeassistant.components.trafikverket_train.config_flow.TrafikverketTrain.async_get_train_station",
), patch(
"homeassistant.components.trafikverket_train.async_setup_entry",
return_value=True,
):
result2 = await hass.config_entries.flow.async_configure(
result["flow_id"],
{CONF_API_KEY: "1234567891"},
)
await hass.async_block_till_done()
assert result2["type"] == RESULT_TYPE_ABORT
assert result2["reason"] == "reauth_successful"
assert entry.data == {
"api_key": "1234567891",
"name": "Stockholm C to Uppsala C at 10:00",
"from": "Stockholm C",
"to": "Uppsala C",
"time": "10:00",
"weekday": ["mon", "tue", "wed", "thu", "fri", "sat", "sun"],
}