mirror of
https://github.com/home-assistant/core.git
synced 2026-09-24 07:25:52 -05:00
Add config-flow to NextBus (#92149)
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
"""Test helpers for NextBus tests."""
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_nextbus_lists(mock_nextbus: MagicMock) -> MagicMock:
|
||||
"""Mock all list functions in nextbus to test validate logic."""
|
||||
instance = mock_nextbus.return_value
|
||||
instance.get_agency_list.return_value = {
|
||||
"agency": [{"tag": "sf-muni", "title": "San Francisco Muni"}]
|
||||
}
|
||||
instance.get_route_list.return_value = {
|
||||
"route": [{"tag": "F", "title": "F - Market & Wharves"}]
|
||||
}
|
||||
instance.get_route_config.return_value = {
|
||||
"route": {
|
||||
"stop": [
|
||||
{"tag": "5650", "title": "Market St & 7th St"},
|
||||
{"tag": "5651", "title": "Market St & 7th St"},
|
||||
],
|
||||
"direction": [
|
||||
{
|
||||
"name": "Outbound",
|
||||
"stop": [{"tag": "5650"}],
|
||||
},
|
||||
{
|
||||
"name": "Inbound",
|
||||
"stop": [{"tag": "5651"}],
|
||||
},
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
return instance
|
||||
@@ -0,0 +1,162 @@
|
||||
"""Test the NextBus config flow."""
|
||||
from collections.abc import Generator
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
from homeassistant import config_entries, setup
|
||||
from homeassistant.components.nextbus.const import (
|
||||
CONF_AGENCY,
|
||||
CONF_ROUTE,
|
||||
CONF_STOP,
|
||||
DOMAIN,
|
||||
)
|
||||
from homeassistant.const import CONF_NAME
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.data_entry_flow import FlowResultType
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_setup_entry() -> Generator[MagicMock, None, None]:
|
||||
"""Create a mock for the nextbus component setup."""
|
||||
with patch(
|
||||
"homeassistant.components.nextbus.async_setup_entry",
|
||||
return_value=True,
|
||||
) as mock_setup_entry:
|
||||
yield mock_setup_entry
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_nextbus() -> Generator[MagicMock, None, None]:
|
||||
"""Create a mock py_nextbus module."""
|
||||
with patch("homeassistant.components.nextbus.config_flow.NextBusClient") as client:
|
||||
yield client
|
||||
|
||||
|
||||
async def test_import_config(
|
||||
hass: HomeAssistant, mock_setup_entry: MagicMock, mock_nextbus_lists: MagicMock
|
||||
) -> None:
|
||||
"""Test config is imported and component set up."""
|
||||
await setup.async_setup_component(hass, "persistent_notification", {})
|
||||
data = {
|
||||
CONF_AGENCY: "sf-muni",
|
||||
CONF_ROUTE: "F",
|
||||
CONF_STOP: "5650",
|
||||
}
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={"source": config_entries.SOURCE_IMPORT},
|
||||
data=data,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result.get("type") == FlowResultType.CREATE_ENTRY
|
||||
assert (
|
||||
result.get("title")
|
||||
== "San Francisco Muni F - Market & Wharves Market St & 7th St (Outbound)"
|
||||
)
|
||||
assert result.get("data") == {CONF_NAME: "sf-muni F", **data}
|
||||
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
||||
# Check duplicate entries are aborted
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={"source": config_entries.SOURCE_IMPORT},
|
||||
data=data,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result.get("type") == FlowResultType.ABORT
|
||||
assert result.get("reason") == "already_configured"
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("override", "expected_reason"),
|
||||
(
|
||||
({CONF_AGENCY: "not muni"}, "invalid_agency"),
|
||||
({CONF_ROUTE: "not F"}, "invalid_route"),
|
||||
({CONF_STOP: "not 5650"}, "invalid_stop"),
|
||||
),
|
||||
)
|
||||
async def test_import_config_invalid(
|
||||
hass: HomeAssistant,
|
||||
mock_setup_entry: MagicMock,
|
||||
mock_nextbus_lists: MagicMock,
|
||||
override: dict[str, str],
|
||||
expected_reason: str,
|
||||
) -> None:
|
||||
"""Test user is redirected to user setup flow because they have invalid config."""
|
||||
await setup.async_setup_component(hass, "persistent_notification", {})
|
||||
|
||||
data = {
|
||||
CONF_AGENCY: "sf-muni",
|
||||
CONF_ROUTE: "F",
|
||||
CONF_STOP: "5650",
|
||||
**override,
|
||||
}
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={"source": config_entries.SOURCE_IMPORT},
|
||||
data=data,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result.get("type") == FlowResultType.ABORT
|
||||
assert result.get("reason") == expected_reason
|
||||
|
||||
|
||||
async def test_user_config(
|
||||
hass: HomeAssistant, mock_setup_entry: MagicMock, mock_nextbus_lists: MagicMock
|
||||
) -> None:
|
||||
"""Test we get the form."""
|
||||
await setup.async_setup_component(hass, "persistent_notification", {})
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
assert result.get("type") == FlowResultType.FORM
|
||||
assert result.get("step_id") == "agency"
|
||||
|
||||
# Select agency
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
{
|
||||
CONF_AGENCY: "sf-muni",
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result.get("type") == "form"
|
||||
assert result.get("step_id") == "route"
|
||||
|
||||
# Select route
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
{
|
||||
CONF_ROUTE: "F",
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result.get("type") == FlowResultType.FORM
|
||||
assert result.get("step_id") == "stop"
|
||||
|
||||
# Select stop
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
{
|
||||
CONF_STOP: "5650",
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result.get("type") == FlowResultType.CREATE_ENTRY
|
||||
assert result.get("data") == {
|
||||
"agency": "sf-muni",
|
||||
"route": "F",
|
||||
"stop": "5650",
|
||||
}
|
||||
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
@@ -1,15 +1,24 @@
|
||||
"""The tests for the nexbus sensor component."""
|
||||
from collections.abc import Generator
|
||||
from copy import deepcopy
|
||||
from unittest.mock import patch
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
import homeassistant.components.nextbus.sensor as nextbus
|
||||
import homeassistant.components.sensor as sensor
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.components import sensor
|
||||
from homeassistant.components.nextbus.const import (
|
||||
CONF_AGENCY,
|
||||
CONF_ROUTE,
|
||||
CONF_STOP,
|
||||
DOMAIN,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntryState
|
||||
from homeassistant.const import CONF_NAME
|
||||
from homeassistant.core import DOMAIN as HOMEASSISTANT_DOMAIN, HomeAssistant
|
||||
from homeassistant.helpers import issue_registry as ir
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
||||
from tests.common import assert_setup_component
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
VALID_AGENCY = "sf-muni"
|
||||
VALID_ROUTE = "F"
|
||||
@@ -17,24 +26,34 @@ VALID_STOP = "5650"
|
||||
VALID_AGENCY_TITLE = "San Francisco Muni"
|
||||
VALID_ROUTE_TITLE = "F-Market & Wharves"
|
||||
VALID_STOP_TITLE = "Market St & 7th St"
|
||||
SENSOR_ID_SHORT = "sensor.sf_muni_f"
|
||||
SENSOR_ID = "sensor.san_francisco_muni_f_market_wharves_market_st_7th_st"
|
||||
|
||||
CONFIG_BASIC = {
|
||||
"sensor": {
|
||||
"platform": "nextbus",
|
||||
"agency": VALID_AGENCY,
|
||||
"route": VALID_ROUTE,
|
||||
"stop": VALID_STOP,
|
||||
}
|
||||
PLATFORM_CONFIG = {
|
||||
sensor.DOMAIN: {
|
||||
"platform": DOMAIN,
|
||||
CONF_AGENCY: VALID_AGENCY,
|
||||
CONF_ROUTE: VALID_ROUTE,
|
||||
CONF_STOP: VALID_STOP,
|
||||
},
|
||||
}
|
||||
|
||||
CONFIG_INVALID_MISSING = {"sensor": {"platform": "nextbus"}}
|
||||
|
||||
CONFIG_BASIC = {
|
||||
DOMAIN: {
|
||||
CONF_AGENCY: VALID_AGENCY,
|
||||
CONF_ROUTE: VALID_ROUTE,
|
||||
CONF_STOP: VALID_STOP,
|
||||
}
|
||||
}
|
||||
|
||||
BASIC_RESULTS = {
|
||||
"predictions": {
|
||||
"agencyTitle": VALID_AGENCY_TITLE,
|
||||
"agencyTag": VALID_AGENCY,
|
||||
"routeTitle": VALID_ROUTE_TITLE,
|
||||
"routeTag": VALID_ROUTE,
|
||||
"stopTitle": VALID_STOP_TITLE,
|
||||
"stopTag": VALID_STOP,
|
||||
"direction": {
|
||||
"title": "Outbound",
|
||||
"prediction": [
|
||||
@@ -48,24 +67,19 @@ BASIC_RESULTS = {
|
||||
}
|
||||
|
||||
|
||||
async def assert_setup_sensor(hass, config, count=1):
|
||||
"""Set up the sensor and assert it's been created."""
|
||||
with assert_setup_component(count):
|
||||
assert await async_setup_component(hass, sensor.DOMAIN, config)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_nextbus():
|
||||
def mock_nextbus() -> Generator[MagicMock, None, None]:
|
||||
"""Create a mock py_nextbus module."""
|
||||
with patch(
|
||||
"homeassistant.components.nextbus.sensor.NextBusClient"
|
||||
) as NextBusClient:
|
||||
yield NextBusClient
|
||||
"homeassistant.components.nextbus.sensor.NextBusClient",
|
||||
) as client:
|
||||
yield client
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_nextbus_predictions(mock_nextbus):
|
||||
def mock_nextbus_predictions(
|
||||
mock_nextbus: MagicMock,
|
||||
) -> Generator[MagicMock, None, None]:
|
||||
"""Create a mock of NextBusClient predictions."""
|
||||
instance = mock_nextbus.return_value
|
||||
instance.get_predictions_for_multi_stops.return_value = BASIC_RESULTS
|
||||
@@ -73,63 +87,69 @@ def mock_nextbus_predictions(mock_nextbus):
|
||||
return instance.get_predictions_for_multi_stops
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_nextbus_lists(mock_nextbus):
|
||||
"""Mock all list functions in nextbus to test validate logic."""
|
||||
instance = mock_nextbus.return_value
|
||||
instance.get_agency_list.return_value = {
|
||||
"agency": [{"tag": "sf-muni", "title": "San Francisco Muni"}]
|
||||
}
|
||||
instance.get_route_list.return_value = {
|
||||
"route": [{"tag": "F", "title": "F - Market & Wharves"}]
|
||||
}
|
||||
instance.get_route_config.return_value = {
|
||||
"route": {"stop": [{"tag": "5650", "title": "Market St & 7th St"}]}
|
||||
}
|
||||
async def assert_setup_sensor(
|
||||
hass: HomeAssistant,
|
||||
config: dict[str, str],
|
||||
expected_state=ConfigEntryState.LOADED,
|
||||
) -> MockConfigEntry:
|
||||
"""Set up the sensor and assert it's been created."""
|
||||
config_entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
data=config[DOMAIN],
|
||||
title=f"{VALID_AGENCY_TITLE} {VALID_ROUTE_TITLE} {VALID_STOP_TITLE}",
|
||||
unique_id=f"{VALID_AGENCY}_{VALID_ROUTE}_{VALID_STOP}",
|
||||
)
|
||||
config_entry.add_to_hass(hass)
|
||||
|
||||
await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert config_entry.state is expected_state
|
||||
|
||||
return config_entry
|
||||
|
||||
|
||||
async def test_legacy_yaml_setup(
|
||||
hass: HomeAssistant,
|
||||
issue_registry: ir.IssueRegistry,
|
||||
) -> None:
|
||||
"""Test config setup and yaml deprecation."""
|
||||
with patch(
|
||||
"homeassistant.components.nextbus.config_flow.NextBusClient",
|
||||
) as NextBusClient:
|
||||
NextBusClient.return_value.get_predictions_for_multi_stops.return_value = (
|
||||
BASIC_RESULTS
|
||||
)
|
||||
await async_setup_component(hass, sensor.DOMAIN, PLATFORM_CONFIG)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
issue = issue_registry.async_get_issue(
|
||||
HOMEASSISTANT_DOMAIN, f"deprecated_yaml_{DOMAIN}"
|
||||
)
|
||||
assert issue
|
||||
|
||||
|
||||
async def test_valid_config(
|
||||
hass: HomeAssistant, mock_nextbus, mock_nextbus_lists
|
||||
hass: HomeAssistant, mock_nextbus: MagicMock, mock_nextbus_lists: MagicMock
|
||||
) -> None:
|
||||
"""Test that sensor is set up properly with valid config."""
|
||||
await assert_setup_sensor(hass, CONFIG_BASIC)
|
||||
|
||||
|
||||
async def test_invalid_config(
|
||||
hass: HomeAssistant, mock_nextbus, mock_nextbus_lists
|
||||
) -> None:
|
||||
"""Checks that component is not setup when missing information."""
|
||||
await assert_setup_sensor(hass, CONFIG_INVALID_MISSING, count=0)
|
||||
|
||||
|
||||
async def test_validate_tags(
|
||||
hass: HomeAssistant, mock_nextbus, mock_nextbus_lists
|
||||
) -> None:
|
||||
"""Test that additional validation against the API is successful."""
|
||||
# with self.subTest('Valid everything'):
|
||||
assert nextbus.validate_tags(mock_nextbus(), VALID_AGENCY, VALID_ROUTE, VALID_STOP)
|
||||
# with self.subTest('Invalid agency'):
|
||||
assert not nextbus.validate_tags(
|
||||
mock_nextbus(), "not-valid", VALID_ROUTE, VALID_STOP
|
||||
)
|
||||
|
||||
# with self.subTest('Invalid route'):
|
||||
assert not nextbus.validate_tags(mock_nextbus(), VALID_AGENCY, "0", VALID_STOP)
|
||||
|
||||
# with self.subTest('Invalid stop'):
|
||||
assert not nextbus.validate_tags(mock_nextbus(), VALID_AGENCY, VALID_ROUTE, 0)
|
||||
|
||||
|
||||
async def test_verify_valid_state(
|
||||
hass: HomeAssistant, mock_nextbus, mock_nextbus_lists, mock_nextbus_predictions
|
||||
hass: HomeAssistant,
|
||||
mock_nextbus: MagicMock,
|
||||
mock_nextbus_lists: MagicMock,
|
||||
mock_nextbus_predictions: MagicMock,
|
||||
) -> None:
|
||||
"""Verify all attributes are set from a valid response."""
|
||||
await assert_setup_sensor(hass, CONFIG_BASIC)
|
||||
|
||||
mock_nextbus_predictions.assert_called_once_with(
|
||||
[{"stop_tag": VALID_STOP, "route_tag": VALID_ROUTE}], VALID_AGENCY
|
||||
)
|
||||
|
||||
state = hass.states.get(SENSOR_ID_SHORT)
|
||||
state = hass.states.get(SENSOR_ID)
|
||||
assert state is not None
|
||||
assert state.state == "2019-03-28T21:09:31+00:00"
|
||||
assert state.attributes["agency"] == VALID_AGENCY_TITLE
|
||||
@@ -140,14 +160,20 @@ async def test_verify_valid_state(
|
||||
|
||||
|
||||
async def test_message_dict(
|
||||
hass: HomeAssistant, mock_nextbus, mock_nextbus_lists, mock_nextbus_predictions
|
||||
hass: HomeAssistant,
|
||||
mock_nextbus: MagicMock,
|
||||
mock_nextbus_lists: MagicMock,
|
||||
mock_nextbus_predictions: MagicMock,
|
||||
) -> None:
|
||||
"""Verify that a single dict message is rendered correctly."""
|
||||
mock_nextbus_predictions.return_value = {
|
||||
"predictions": {
|
||||
"agencyTitle": VALID_AGENCY_TITLE,
|
||||
"agencyTag": VALID_AGENCY,
|
||||
"routeTitle": VALID_ROUTE_TITLE,
|
||||
"routeTag": VALID_ROUTE,
|
||||
"stopTitle": VALID_STOP_TITLE,
|
||||
"stopTag": VALID_STOP,
|
||||
"message": {"text": "Message"},
|
||||
"direction": {
|
||||
"title": "Outbound",
|
||||
@@ -162,20 +188,26 @@ async def test_message_dict(
|
||||
|
||||
await assert_setup_sensor(hass, CONFIG_BASIC)
|
||||
|
||||
state = hass.states.get(SENSOR_ID_SHORT)
|
||||
state = hass.states.get(SENSOR_ID)
|
||||
assert state is not None
|
||||
assert state.attributes["message"] == "Message"
|
||||
|
||||
|
||||
async def test_message_list(
|
||||
hass: HomeAssistant, mock_nextbus, mock_nextbus_lists, mock_nextbus_predictions
|
||||
hass: HomeAssistant,
|
||||
mock_nextbus: MagicMock,
|
||||
mock_nextbus_lists: MagicMock,
|
||||
mock_nextbus_predictions: MagicMock,
|
||||
) -> None:
|
||||
"""Verify that a list of messages are rendered correctly."""
|
||||
mock_nextbus_predictions.return_value = {
|
||||
"predictions": {
|
||||
"agencyTitle": VALID_AGENCY_TITLE,
|
||||
"agencyTag": VALID_AGENCY,
|
||||
"routeTitle": VALID_ROUTE_TITLE,
|
||||
"routeTag": VALID_ROUTE,
|
||||
"stopTitle": VALID_STOP_TITLE,
|
||||
"stopTag": VALID_STOP,
|
||||
"message": [{"text": "Message 1"}, {"text": "Message 2"}],
|
||||
"direction": {
|
||||
"title": "Outbound",
|
||||
@@ -190,20 +222,26 @@ async def test_message_list(
|
||||
|
||||
await assert_setup_sensor(hass, CONFIG_BASIC)
|
||||
|
||||
state = hass.states.get(SENSOR_ID_SHORT)
|
||||
state = hass.states.get(SENSOR_ID)
|
||||
assert state is not None
|
||||
assert state.attributes["message"] == "Message 1 -- Message 2"
|
||||
|
||||
|
||||
async def test_direction_list(
|
||||
hass: HomeAssistant, mock_nextbus, mock_nextbus_lists, mock_nextbus_predictions
|
||||
hass: HomeAssistant,
|
||||
mock_nextbus: MagicMock,
|
||||
mock_nextbus_lists: MagicMock,
|
||||
mock_nextbus_predictions: MagicMock,
|
||||
) -> None:
|
||||
"""Verify that a list of messages are rendered correctly."""
|
||||
mock_nextbus_predictions.return_value = {
|
||||
"predictions": {
|
||||
"agencyTitle": VALID_AGENCY_TITLE,
|
||||
"agencyTag": VALID_AGENCY,
|
||||
"routeTitle": VALID_ROUTE_TITLE,
|
||||
"routeTag": VALID_ROUTE,
|
||||
"stopTitle": VALID_STOP_TITLE,
|
||||
"stopTag": VALID_STOP,
|
||||
"message": [{"text": "Message 1"}, {"text": "Message 2"}],
|
||||
"direction": [
|
||||
{
|
||||
@@ -224,7 +262,7 @@ async def test_direction_list(
|
||||
|
||||
await assert_setup_sensor(hass, CONFIG_BASIC)
|
||||
|
||||
state = hass.states.get(SENSOR_ID_SHORT)
|
||||
state = hass.states.get(SENSOR_ID)
|
||||
assert state is not None
|
||||
assert state.state == "2019-03-28T21:09:31+00:00"
|
||||
assert state.attributes["agency"] == VALID_AGENCY_TITLE
|
||||
@@ -235,46 +273,67 @@ async def test_direction_list(
|
||||
|
||||
|
||||
async def test_custom_name(
|
||||
hass: HomeAssistant, mock_nextbus, mock_nextbus_lists, mock_nextbus_predictions
|
||||
hass: HomeAssistant,
|
||||
mock_nextbus: MagicMock,
|
||||
mock_nextbus_lists: MagicMock,
|
||||
mock_nextbus_predictions: MagicMock,
|
||||
) -> None:
|
||||
"""Verify that a custom name can be set via config."""
|
||||
config = deepcopy(CONFIG_BASIC)
|
||||
config["sensor"]["name"] = "Custom Name"
|
||||
config[DOMAIN][CONF_NAME] = "Custom Name"
|
||||
|
||||
await assert_setup_sensor(hass, config)
|
||||
state = hass.states.get("sensor.custom_name")
|
||||
assert state is not None
|
||||
assert state.name == "Custom Name"
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"prediction_results",
|
||||
(
|
||||
{},
|
||||
{"Error": "Failed"},
|
||||
),
|
||||
)
|
||||
async def test_no_predictions(
|
||||
hass: HomeAssistant, mock_nextbus, mock_nextbus_predictions, mock_nextbus_lists
|
||||
hass: HomeAssistant,
|
||||
mock_nextbus: MagicMock,
|
||||
mock_nextbus_predictions: MagicMock,
|
||||
mock_nextbus_lists: MagicMock,
|
||||
prediction_results: dict[str, str],
|
||||
) -> None:
|
||||
"""Verify there are no exceptions when no predictions are returned."""
|
||||
mock_nextbus_predictions.return_value = {}
|
||||
mock_nextbus_predictions.return_value = prediction_results
|
||||
|
||||
await assert_setup_sensor(hass, CONFIG_BASIC)
|
||||
|
||||
state = hass.states.get(SENSOR_ID_SHORT)
|
||||
state = hass.states.get(SENSOR_ID)
|
||||
assert state is not None
|
||||
assert state.state == "unknown"
|
||||
|
||||
|
||||
async def test_verify_no_upcoming(
|
||||
hass: HomeAssistant, mock_nextbus, mock_nextbus_lists, mock_nextbus_predictions
|
||||
hass: HomeAssistant,
|
||||
mock_nextbus: MagicMock,
|
||||
mock_nextbus_lists: MagicMock,
|
||||
mock_nextbus_predictions: MagicMock,
|
||||
) -> None:
|
||||
"""Verify attributes are set despite no upcoming times."""
|
||||
mock_nextbus_predictions.return_value = {
|
||||
"predictions": {
|
||||
"agencyTitle": VALID_AGENCY_TITLE,
|
||||
"agencyTag": VALID_AGENCY,
|
||||
"routeTitle": VALID_ROUTE_TITLE,
|
||||
"routeTag": VALID_ROUTE,
|
||||
"stopTitle": VALID_STOP_TITLE,
|
||||
"stopTag": VALID_STOP,
|
||||
"direction": {"title": "Outbound", "prediction": []},
|
||||
}
|
||||
}
|
||||
|
||||
await assert_setup_sensor(hass, CONFIG_BASIC)
|
||||
|
||||
state = hass.states.get(SENSOR_ID_SHORT)
|
||||
state = hass.states.get(SENSOR_ID)
|
||||
assert state is not None
|
||||
assert state.state == "unknown"
|
||||
assert state.attributes["upcoming"] == "No upcoming predictions"
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
"""Test NextBus util functions."""
|
||||
from typing import Any
|
||||
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.nextbus.util import listify, maybe_first
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("input", "expected"),
|
||||
(
|
||||
("foo", ["foo"]),
|
||||
(["foo"], ["foo"]),
|
||||
(None, []),
|
||||
),
|
||||
)
|
||||
def test_listify(input: Any, expected: list[Any]) -> None:
|
||||
"""Test input listification."""
|
||||
assert listify(input) == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("input", "expected"),
|
||||
(
|
||||
([], []),
|
||||
(None, None),
|
||||
("test", "test"),
|
||||
(["test"], "test"),
|
||||
(["test", "second"], "test"),
|
||||
),
|
||||
)
|
||||
def test_maybe_first(input: list[Any] | None, expected: Any) -> None:
|
||||
"""Test maybe getting the first thing from a list."""
|
||||
assert maybe_first(input) == expected
|
||||
Reference in New Issue
Block a user