mirror of
https://github.com/home-assistant/core.git
synced 2026-08-24 10:13:52 -05:00
Add command error-path tests to Teslemetry (#174163)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
9decee350f
commit
15aaddf4ac
@@ -4,6 +4,7 @@ from unittest.mock import AsyncMock, patch
|
||||
|
||||
import pytest
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
from tesla_fleet_api.exceptions import InvalidCommand
|
||||
from teslemetry_stream import Signal
|
||||
|
||||
from homeassistant.components.cover import (
|
||||
@@ -15,10 +16,11 @@ from homeassistant.components.cover import (
|
||||
)
|
||||
from homeassistant.const import ATTR_ENTITY_ID, Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
|
||||
from . import assert_entities, setup_platform
|
||||
from .const import COMMAND_OK, METADATA_NOSCOPE, VEHICLE_DATA_ALT
|
||||
from .const import COMMAND_ERRORS, COMMAND_OK, METADATA_NOSCOPE, VEHICLE_DATA_ALT
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
|
||||
@@ -221,6 +223,49 @@ async def test_cover_services(
|
||||
assert state.state == CoverState.CLOSED
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("entity_registry_enabled_by_default", "mock_legacy")
|
||||
@pytest.mark.parametrize("response", COMMAND_ERRORS)
|
||||
async def test_cover_command_errors(hass: HomeAssistant, response: dict) -> None:
|
||||
"""Tests that vehicle command failures raise HomeAssistantError."""
|
||||
|
||||
await setup_platform(hass, [Platform.COVER])
|
||||
|
||||
with (
|
||||
patch(
|
||||
"tesla_fleet_api.teslemetry.Vehicle.window_control",
|
||||
return_value=response,
|
||||
),
|
||||
pytest.raises(HomeAssistantError),
|
||||
):
|
||||
await hass.services.async_call(
|
||||
COVER_DOMAIN,
|
||||
SERVICE_OPEN_COVER,
|
||||
{ATTR_ENTITY_ID: ["cover.test_windows"]},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("entity_registry_enabled_by_default", "mock_legacy")
|
||||
async def test_cover_command_exception(hass: HomeAssistant) -> None:
|
||||
"""Tests that a command SDK exception raises HomeAssistantError."""
|
||||
|
||||
await setup_platform(hass, [Platform.COVER])
|
||||
|
||||
with (
|
||||
patch(
|
||||
"tesla_fleet_api.teslemetry.Vehicle.window_control",
|
||||
side_effect=InvalidCommand,
|
||||
),
|
||||
pytest.raises(HomeAssistantError),
|
||||
):
|
||||
await hass.services.async_call(
|
||||
COVER_DOMAIN,
|
||||
SERVICE_OPEN_COVER,
|
||||
{ATTR_ENTITY_ID: ["cover.test_windows"]},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
|
||||
async def test_cover_streaming(
|
||||
hass: HomeAssistant,
|
||||
mock_vehicle_data: AsyncMock,
|
||||
|
||||
@@ -4,6 +4,7 @@ from unittest.mock import AsyncMock, patch
|
||||
|
||||
import pytest
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
from tesla_fleet_api.exceptions import InvalidCommand
|
||||
from teslemetry_stream.const import Signal
|
||||
|
||||
from homeassistant.components.lock import (
|
||||
@@ -14,11 +15,11 @@ from homeassistant.components.lock import (
|
||||
)
|
||||
from homeassistant.const import ATTR_ENTITY_ID, Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import ServiceValidationError
|
||||
from homeassistant.exceptions import HomeAssistantError, ServiceValidationError
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
|
||||
from . import assert_entities, reload_platform, setup_platform
|
||||
from .const import COMMAND_OK, VEHICLE_DATA_ALT
|
||||
from .const import COMMAND_ERRORS, COMMAND_OK, VEHICLE_DATA_ALT
|
||||
|
||||
|
||||
async def test_lock(
|
||||
@@ -109,6 +110,47 @@ async def test_lock_services(
|
||||
call.assert_called_once()
|
||||
|
||||
|
||||
@pytest.mark.parametrize("response", COMMAND_ERRORS)
|
||||
async def test_lock_command_errors(hass: HomeAssistant, response: dict) -> None:
|
||||
"""Tests that vehicle command failures raise HomeAssistantError."""
|
||||
|
||||
await setup_platform(hass, [Platform.LOCK])
|
||||
|
||||
with (
|
||||
patch(
|
||||
"tesla_fleet_api.teslemetry.Vehicle.door_lock",
|
||||
return_value=response,
|
||||
),
|
||||
pytest.raises(HomeAssistantError),
|
||||
):
|
||||
await hass.services.async_call(
|
||||
LOCK_DOMAIN,
|
||||
SERVICE_LOCK,
|
||||
{ATTR_ENTITY_ID: "lock.test_lock"},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
|
||||
async def test_lock_command_exception(hass: HomeAssistant) -> None:
|
||||
"""Tests that a command SDK exception raises HomeAssistantError."""
|
||||
|
||||
await setup_platform(hass, [Platform.LOCK])
|
||||
|
||||
with (
|
||||
patch(
|
||||
"tesla_fleet_api.teslemetry.Vehicle.door_lock",
|
||||
side_effect=InvalidCommand,
|
||||
),
|
||||
pytest.raises(HomeAssistantError),
|
||||
):
|
||||
await hass.services.async_call(
|
||||
LOCK_DOMAIN,
|
||||
SERVICE_LOCK,
|
||||
{ATTR_ENTITY_ID: "lock.test_lock"},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
|
||||
async def test_lock_streaming(
|
||||
hass: HomeAssistant,
|
||||
mock_vehicle_data: AsyncMock,
|
||||
|
||||
@@ -4,6 +4,7 @@ from unittest.mock import AsyncMock, patch
|
||||
|
||||
import pytest
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
from tesla_fleet_api.exceptions import InvalidCommand
|
||||
from teslemetry_stream import Signal
|
||||
|
||||
from homeassistant.components.media_player import (
|
||||
@@ -18,10 +19,11 @@ from homeassistant.components.media_player import (
|
||||
)
|
||||
from homeassistant.const import ATTR_ENTITY_ID, Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
|
||||
from . import assert_entities, assert_entities_alt, reload_platform, setup_platform
|
||||
from .const import COMMAND_OK, METADATA_NOSCOPE, VEHICLE_DATA_ALT
|
||||
from .const import COMMAND_ERRORS, COMMAND_OK, METADATA_NOSCOPE, VEHICLE_DATA_ALT
|
||||
|
||||
|
||||
async def test_media_player(
|
||||
@@ -144,6 +146,55 @@ async def test_media_player_services(
|
||||
call.assert_called_once()
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("mock_legacy")
|
||||
@pytest.mark.parametrize("response", COMMAND_ERRORS)
|
||||
async def test_media_player_command_errors(hass: HomeAssistant, response: dict) -> None:
|
||||
"""Tests that vehicle command failures raise HomeAssistantError."""
|
||||
|
||||
await setup_platform(hass, [Platform.MEDIA_PLAYER])
|
||||
|
||||
with (
|
||||
patch(
|
||||
"tesla_fleet_api.teslemetry.Vehicle.adjust_volume",
|
||||
return_value=response,
|
||||
),
|
||||
pytest.raises(HomeAssistantError),
|
||||
):
|
||||
await hass.services.async_call(
|
||||
MEDIA_PLAYER_DOMAIN,
|
||||
SERVICE_VOLUME_SET,
|
||||
{
|
||||
ATTR_ENTITY_ID: "media_player.test_media_player",
|
||||
ATTR_MEDIA_VOLUME_LEVEL: 0.5,
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("mock_legacy")
|
||||
async def test_media_player_command_exception(hass: HomeAssistant) -> None:
|
||||
"""Tests that a command SDK exception raises HomeAssistantError."""
|
||||
|
||||
await setup_platform(hass, [Platform.MEDIA_PLAYER])
|
||||
|
||||
with (
|
||||
patch(
|
||||
"tesla_fleet_api.teslemetry.Vehicle.adjust_volume",
|
||||
side_effect=InvalidCommand,
|
||||
),
|
||||
pytest.raises(HomeAssistantError),
|
||||
):
|
||||
await hass.services.async_call(
|
||||
MEDIA_PLAYER_DOMAIN,
|
||||
SERVICE_VOLUME_SET,
|
||||
{
|
||||
ATTR_ENTITY_ID: "media_player.test_media_player",
|
||||
ATTR_MEDIA_VOLUME_LEVEL: 0.5,
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
|
||||
async def test_update_streaming(
|
||||
hass: HomeAssistant,
|
||||
|
||||
@@ -4,6 +4,7 @@ from unittest.mock import AsyncMock, patch
|
||||
|
||||
import pytest
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
from tesla_fleet_api.exceptions import InvalidCommand
|
||||
from teslemetry_stream import Signal
|
||||
|
||||
from homeassistant.components.number import (
|
||||
@@ -13,10 +14,11 @@ from homeassistant.components.number import (
|
||||
)
|
||||
from homeassistant.const import ATTR_ENTITY_ID, Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
|
||||
from . import assert_entities, reload_platform, setup_platform
|
||||
from .const import COMMAND_OK, VEHICLE_DATA_ALT
|
||||
from .const import COMMAND_ERRORS, COMMAND_OK, VEHICLE_DATA_ALT
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
|
||||
@@ -104,6 +106,50 @@ async def test_number_services(
|
||||
call.assert_called_once()
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
|
||||
@pytest.mark.parametrize("response", COMMAND_ERRORS)
|
||||
async def test_number_command_errors(
|
||||
hass: HomeAssistant, mock_vehicle_data: AsyncMock, response: dict
|
||||
) -> None:
|
||||
"""Tests that vehicle command failures raise HomeAssistantError."""
|
||||
mock_vehicle_data.return_value = VEHICLE_DATA_ALT
|
||||
await setup_platform(hass, [Platform.NUMBER])
|
||||
|
||||
with (
|
||||
patch(
|
||||
"tesla_fleet_api.teslemetry.Vehicle.set_charging_amps",
|
||||
return_value=response,
|
||||
),
|
||||
pytest.raises(HomeAssistantError),
|
||||
):
|
||||
await hass.services.async_call(
|
||||
NUMBER_DOMAIN,
|
||||
SERVICE_SET_VALUE,
|
||||
{ATTR_ENTITY_ID: "number.test_charge_current", ATTR_VALUE: 16},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
|
||||
async def test_number_command_exception(hass: HomeAssistant) -> None:
|
||||
"""Tests that an energy command SDK exception raises HomeAssistantError."""
|
||||
await setup_platform(hass, [Platform.NUMBER])
|
||||
|
||||
with (
|
||||
patch(
|
||||
"tesla_fleet_api.teslemetry.EnergySite.backup",
|
||||
side_effect=InvalidCommand,
|
||||
),
|
||||
pytest.raises(HomeAssistantError),
|
||||
):
|
||||
await hass.services.async_call(
|
||||
NUMBER_DOMAIN,
|
||||
SERVICE_SET_VALUE,
|
||||
{ATTR_ENTITY_ID: "number.energy_site_backup_reserve", ATTR_VALUE: 80},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
|
||||
async def test_number_streaming(
|
||||
hass: HomeAssistant,
|
||||
mock_vehicle_data: AsyncMock,
|
||||
|
||||
@@ -7,6 +7,7 @@ from freezegun.api import FrozenDateTimeFactory
|
||||
import pytest
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
from tesla_fleet_api.const import EnergyExportMode, EnergyOperationMode
|
||||
from tesla_fleet_api.exceptions import InvalidCommand
|
||||
from teslemetry_stream.const import Signal
|
||||
|
||||
from homeassistant.components.select import (
|
||||
@@ -18,10 +19,11 @@ from homeassistant.components.teslemetry.coordinator import ENERGY_INFO_INTERVAL
|
||||
from homeassistant.components.teslemetry.select import LOW
|
||||
from homeassistant.const import ATTR_ENTITY_ID, STATE_UNKNOWN, Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
|
||||
from . import assert_entities, reload_platform, setup_platform
|
||||
from .const import COMMAND_OK, SITE_INFO, VEHICLE_DATA_ALT
|
||||
from .const import COMMAND_ERRORS, COMMAND_OK, SITE_INFO, VEHICLE_DATA_ALT
|
||||
|
||||
from tests.common import async_fire_time_changed
|
||||
|
||||
@@ -108,6 +110,51 @@ async def test_select_services(hass: HomeAssistant, mock_vehicle_data) -> None:
|
||||
call.assert_called_once()
|
||||
|
||||
|
||||
@pytest.mark.parametrize("response", COMMAND_ERRORS)
|
||||
async def test_select_command_errors(
|
||||
hass: HomeAssistant, mock_vehicle_data: AsyncMock, response: dict
|
||||
) -> None:
|
||||
"""Tests that vehicle command failures raise HomeAssistantError."""
|
||||
mock_vehicle_data.return_value = VEHICLE_DATA_ALT
|
||||
await setup_platform(hass, [Platform.SELECT])
|
||||
|
||||
with (
|
||||
patch(
|
||||
"tesla_fleet_api.teslemetry.Vehicle.remote_seat_heater_request",
|
||||
return_value=response,
|
||||
),
|
||||
pytest.raises(HomeAssistantError),
|
||||
):
|
||||
await hass.services.async_call(
|
||||
SELECT_DOMAIN,
|
||||
SERVICE_SELECT_OPTION,
|
||||
{ATTR_ENTITY_ID: "select.test_seat_heater_front_left", ATTR_OPTION: LOW},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
|
||||
async def test_select_command_exception(hass: HomeAssistant) -> None:
|
||||
"""Tests that an energy command SDK exception raises HomeAssistantError."""
|
||||
await setup_platform(hass, [Platform.SELECT])
|
||||
|
||||
with (
|
||||
patch(
|
||||
"tesla_fleet_api.teslemetry.EnergySite.operation",
|
||||
side_effect=InvalidCommand,
|
||||
),
|
||||
pytest.raises(HomeAssistantError),
|
||||
):
|
||||
await hass.services.async_call(
|
||||
SELECT_DOMAIN,
|
||||
SERVICE_SELECT_OPTION,
|
||||
{
|
||||
ATTR_ENTITY_ID: "select.energy_site_operation_mode",
|
||||
ATTR_OPTION: EnergyOperationMode.AUTONOMOUS.value,
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
|
||||
async def test_select_invalid_data(
|
||||
hass: HomeAssistant,
|
||||
snapshot: SnapshotAssertion,
|
||||
|
||||
@@ -4,6 +4,7 @@ from unittest.mock import AsyncMock, patch
|
||||
|
||||
import pytest
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
from tesla_fleet_api.exceptions import InvalidCommand
|
||||
from teslemetry_stream import Signal
|
||||
|
||||
from homeassistant.components.switch import (
|
||||
@@ -13,10 +14,11 @@ from homeassistant.components.switch import (
|
||||
)
|
||||
from homeassistant.const import ATTR_ENTITY_ID, STATE_OFF, STATE_ON, Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
|
||||
from . import assert_entities, assert_entities_alt, reload_platform, setup_platform
|
||||
from .const import COMMAND_OK, VEHICLE_DATA_ALT
|
||||
from .const import COMMAND_ERRORS, COMMAND_OK, VEHICLE_DATA_ALT
|
||||
|
||||
|
||||
async def test_switch(
|
||||
@@ -124,6 +126,49 @@ async def test_switch_services(
|
||||
call.assert_called_once()
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
|
||||
@pytest.mark.parametrize("response", COMMAND_ERRORS)
|
||||
async def test_switch_command_errors(hass: HomeAssistant, response: dict) -> None:
|
||||
"""Tests that vehicle command failures raise HomeAssistantError."""
|
||||
|
||||
await setup_platform(hass, [Platform.SWITCH])
|
||||
|
||||
with (
|
||||
patch(
|
||||
"tesla_fleet_api.teslemetry.Vehicle.charge_start",
|
||||
return_value=response,
|
||||
),
|
||||
pytest.raises(HomeAssistantError),
|
||||
):
|
||||
await hass.services.async_call(
|
||||
SWITCH_DOMAIN,
|
||||
SERVICE_TURN_ON,
|
||||
{ATTR_ENTITY_ID: "switch.test_charge"},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
|
||||
async def test_switch_command_exception(hass: HomeAssistant) -> None:
|
||||
"""Tests that an energy command SDK exception raises HomeAssistantError."""
|
||||
|
||||
await setup_platform(hass, [Platform.SWITCH])
|
||||
|
||||
with (
|
||||
patch(
|
||||
"tesla_fleet_api.teslemetry.EnergySite.storm_mode",
|
||||
side_effect=InvalidCommand,
|
||||
),
|
||||
pytest.raises(HomeAssistantError),
|
||||
):
|
||||
await hass.services.async_call(
|
||||
SWITCH_DOMAIN,
|
||||
SERVICE_TURN_ON,
|
||||
{ATTR_ENTITY_ID: "switch.energy_site_storm_watch"},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
|
||||
async def test_switch_streaming(
|
||||
hass: HomeAssistant,
|
||||
mock_vehicle_data: AsyncMock,
|
||||
|
||||
Reference in New Issue
Block a user