core/tests/components/nextbus/test_sensor.py

174 lines
5.6 KiB
Python

"""The tests for the nexbus sensor component."""
from copy import deepcopy
from unittest.mock import MagicMock
from urllib.error import HTTPError
from freezegun.api import FrozenDateTimeFactory
from py_nextbus.client import NextBusFormatError, NextBusHTTPError
import pytest
from homeassistant.components.nextbus.const import DOMAIN
from homeassistant.components.nextbus.coordinator import NextBusDataUpdateCoordinator
from homeassistant.config_entries import ConfigEntryState
from homeassistant.const import CONF_NAME
from homeassistant.core import HomeAssistant
from homeassistant.helpers.update_coordinator import UpdateFailed
from . import assert_setup_sensor
from .const import (
BASIC_RESULTS,
CONFIG_BASIC,
CONFIG_BASIC_2,
NO_UPCOMING,
ROUTE_TITLE_2,
SENSOR_ID,
SENSOR_ID_2,
VALID_AGENCY,
VALID_COORDINATOR_KEY,
VALID_ROUTE_TITLE,
VALID_STOP_TITLE,
)
from tests.common import async_fire_time_changed
async def test_predictions(
hass: HomeAssistant,
mock_nextbus: MagicMock,
mock_nextbus_lists: MagicMock,
mock_nextbus_predictions: MagicMock,
) -> None:
"""Verify that a list of messages are rendered correctly."""
await assert_setup_sensor(hass, CONFIG_BASIC)
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
assert state.attributes["route"] == VALID_ROUTE_TITLE
assert state.attributes["stop"] == VALID_STOP_TITLE
assert state.attributes["upcoming"] == "1, 2, 3, 10"
@pytest.mark.parametrize(
"client_exception",
[
NextBusHTTPError("failed", HTTPError("url", 500, "error", MagicMock(), None)),
NextBusFormatError("failed"),
],
)
async def test_prediction_exceptions(
hass: HomeAssistant,
mock_nextbus: MagicMock,
mock_nextbus_lists: MagicMock,
mock_nextbus_predictions: MagicMock,
client_exception: Exception,
) -> None:
"""Test that some coodinator exceptions raise UpdateFailed exceptions."""
await assert_setup_sensor(hass, CONFIG_BASIC)
coordinator: NextBusDataUpdateCoordinator = hass.data[DOMAIN][VALID_COORDINATOR_KEY]
mock_nextbus_predictions.side_effect = client_exception
with pytest.raises(UpdateFailed):
await coordinator._async_update_data()
async def test_custom_name(
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[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"
async def test_verify_no_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 = []
await assert_setup_sensor(hass, CONFIG_BASIC)
state = hass.states.get(SENSOR_ID)
assert state is not None
assert "upcoming" not in state.attributes
assert state.state == "unknown"
async def test_verify_no_upcoming(
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 = NO_UPCOMING
await assert_setup_sensor(hass, CONFIG_BASIC)
state = hass.states.get(SENSOR_ID)
assert state is not None
assert state.attributes["upcoming"] == "No upcoming predictions"
assert state.state == "unknown"
async def test_unload_entry(
hass: HomeAssistant,
mock_nextbus: MagicMock,
mock_nextbus_lists: MagicMock,
mock_nextbus_predictions: MagicMock,
freezer: FrozenDateTimeFactory,
) -> None:
"""Test that the sensor can be unloaded."""
config_entry1 = await assert_setup_sensor(hass, CONFIG_BASIC)
await assert_setup_sensor(hass, CONFIG_BASIC_2, route_title=ROUTE_TITLE_2)
# Verify the first sensor
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
assert state.attributes["route"] == VALID_ROUTE_TITLE
assert state.attributes["stop"] == VALID_STOP_TITLE
assert state.attributes["upcoming"] == "1, 2, 3, 10"
# Verify the second sensor
state = hass.states.get(SENSOR_ID_2)
assert state is not None
assert state.state == "2019-03-28T21:09:39+00:00"
assert state.attributes["agency"] == VALID_AGENCY
assert state.attributes["route"] == ROUTE_TITLE_2
assert state.attributes["stop"] == VALID_STOP_TITLE
assert state.attributes["upcoming"] == "90"
# Update mock to return new predictions
new_predictions = deepcopy(BASIC_RESULTS)
new_predictions[1]["values"] = [{"minutes": 5, "timestamp": 1553807375000}]
mock_nextbus_predictions.return_value = new_predictions
# Unload config entry 1
await hass.config_entries.async_unload(config_entry1.entry_id)
await hass.async_block_till_done()
assert config_entry1.state is ConfigEntryState.NOT_LOADED
# Skip ahead in time
freezer.tick(120)
async_fire_time_changed(hass)
await hass.async_block_till_done(wait_background_tasks=True)
# Check update for new predictions
state = hass.states.get(SENSOR_ID_2)
assert state is not None
assert state.attributes["upcoming"] == "5"
assert state.state == "2019-03-28T21:09:35+00:00"