Refactor Husqvarna Automower (#117938)

pull/117934/head
Thomas55555 2024-05-24 10:54:19 +02:00 committed by GitHub
parent bc72f82776
commit 13385912d1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 120 additions and 256 deletions

View File

@ -1,6 +1,7 @@
"""The constants for the Husqvarna Automower integration."""
DOMAIN = "husqvarna_automower"
EXECUTION_TIME_DELAY = 5
NAME = "Husqvarna Automower"
OAUTH2_AUTHORIZE = "https://api.authentication.husqvarnagroup.dev/v1/oauth2/authorize"
OAUTH2_TOKEN = "https://api.authentication.husqvarnagroup.dev/v1/oauth2/token"

View File

@ -12,13 +12,13 @@ from aioautomower.session import AutomowerSession
from homeassistant.components.number import NumberEntity, NumberEntityDescription
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import PERCENTAGE, EntityCategory
from homeassistant.const import PERCENTAGE, EntityCategory, Platform
from homeassistant.core import HomeAssistant, callback
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import entity_registry as er
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import DOMAIN
from .const import DOMAIN, EXECUTION_TIME_DELAY
from .coordinator import AutomowerDataUpdateCoordinator
from .entity import AutomowerControlEntity
@ -52,10 +52,6 @@ async def async_set_work_area_cutting_height(
await coordinator.api.commands.set_cutting_height_workarea(
mower_id, int(cheight), work_area_id
)
# As there are no updates from the websocket regarding work area changes,
# we need to wait 5s and then poll the API.
await asyncio.sleep(5)
await coordinator.async_request_refresh()
async def async_set_cutting_height(
@ -189,6 +185,7 @@ class AutomowerWorkAreaNumberEntity(AutomowerControlEntity, NumberEntity):
) -> None:
"""Set up AutomowerNumberEntity."""
super().__init__(mower_id, coordinator)
self.coordinator = coordinator
self.entity_description = description
self.work_area_id = work_area_id
self._attr_unique_id = f"{mower_id}_{work_area_id}_{description.key}"
@ -221,6 +218,11 @@ class AutomowerWorkAreaNumberEntity(AutomowerControlEntity, NumberEntity):
raise HomeAssistantError(
f"Command couldn't be sent to the command queue: {exception}"
) from exception
else:
# As there are no updates from the websocket regarding work area changes,
# we need to wait 5s and then poll the API.
await asyncio.sleep(EXECUTION_TIME_DELAY)
await self.coordinator.async_request_refresh()
@callback
@ -238,10 +240,13 @@ def async_remove_entities(
for work_area_id in _work_areas:
uid = f"{mower_id}_{work_area_id}_cutting_height_work_area"
active_work_areas.add(uid)
for entity_entry in er.async_entries_for_config_entry(
entity_reg, config_entry.entry_id
for entity_entry in er.async_entries_for_config_entry(
entity_reg, config_entry.entry_id
):
if (
entity_entry.domain == Platform.NUMBER
and (split := entity_entry.unique_id.split("_"))[0] == mower_id
and split[-1] == "area"
and entity_entry.unique_id not in active_work_areas
):
if entity_entry.unique_id.split("_")[0] == mower_id:
if entity_entry.unique_id.endswith("cutting_height_work_area"):
if entity_entry.unique_id not in active_work_areas:
entity_reg.async_remove(entity_entry.entity_id)
entity_reg.async_remove(entity_entry.entity_id)

View File

@ -1,4 +1,4 @@
"""Creates a the sensor entities for the mower."""
"""Creates the sensor entities for the mower."""
from collections.abc import Callable
from dataclasses import dataclass

View File

@ -15,12 +15,13 @@ from aioautomower.model import (
from homeassistant.components.switch import SwitchEntity
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import Platform
from homeassistant.core import HomeAssistant, callback
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import entity_registry as er
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import DOMAIN
from .const import DOMAIN, EXECUTION_TIME_DELAY
from .coordinator import AutomowerDataUpdateCoordinator
from .entity import AutomowerControlEntity
@ -40,7 +41,6 @@ ERROR_STATES = [
MowerStates.STOPPED,
MowerStates.OFF,
]
EXECUTION_TIME = 5
async def async_setup_entry(
@ -172,7 +172,7 @@ class AutomowerStayOutZoneSwitchEntity(AutomowerControlEntity, SwitchEntity):
else:
# As there are no updates from the websocket regarding stay out zone changes,
# we need to wait until the command is executed and then poll the API.
await asyncio.sleep(EXECUTION_TIME)
await asyncio.sleep(EXECUTION_TIME_DELAY)
await self.coordinator.async_request_refresh()
async def async_turn_on(self, **kwargs: Any) -> None:
@ -188,7 +188,7 @@ class AutomowerStayOutZoneSwitchEntity(AutomowerControlEntity, SwitchEntity):
else:
# As there are no updates from the websocket regarding stay out zone changes,
# we need to wait until the command is executed and then poll the API.
await asyncio.sleep(EXECUTION_TIME)
await asyncio.sleep(EXECUTION_TIME_DELAY)
await self.coordinator.async_request_refresh()
@ -211,7 +211,8 @@ def async_remove_entities(
entity_reg, config_entry.entry_id
):
if (
(split := entity_entry.unique_id.split("_"))[0] == mower_id
entity_entry.domain == Platform.SWITCH
and (split := entity_entry.unique_id.split("_"))[0] == mower_id
and split[-1] == "zones"
and entity_entry.unique_id not in active_zones
):

View File

@ -4,6 +4,7 @@ from collections.abc import Generator
import time
from unittest.mock import AsyncMock, patch
from aioautomower.session import AutomowerSession, _MowerCommands
from aioautomower.utils import mower_list_to_dictionary_dataclass
from aiohttp import ClientWebSocketResponse
import pytest
@ -82,20 +83,18 @@ async def setup_credentials(hass: HomeAssistant) -> None:
@pytest.fixture
def mock_automower_client() -> Generator[AsyncMock, None, None]:
"""Mock a Husqvarna Automower client."""
mower_dict = mower_list_to_dictionary_dataclass(
load_json_value_fixture("mower.json", DOMAIN)
)
mock = AsyncMock(spec=AutomowerSession)
mock.auth = AsyncMock(side_effect=ClientWebSocketResponse)
mock.commands = AsyncMock(spec_set=_MowerCommands)
mock.get_status.return_value = mower_dict
with patch(
"homeassistant.components.husqvarna_automower.AutomowerSession",
autospec=True,
) as mock_client:
client = mock_client.return_value
client.get_status.return_value = mower_list_to_dictionary_dataclass(
load_json_value_fixture("mower.json", DOMAIN)
)
async def websocket_connect() -> ClientWebSocketResponse:
"""Mock listen."""
return ClientWebSocketResponse
client.auth = AsyncMock(side_effect=websocket_connect)
client.commands = AsyncMock()
yield client
return_value=mock,
):
yield mock

View File

@ -1,5 +1,5 @@
# serializer version: 1
# name: test_sensor[binary_sensor.test_mower_1_charging-entry]
# name: test_binary_sensor_snapshot[binary_sensor.test_mower_1_charging-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
@ -32,7 +32,7 @@
'unit_of_measurement': None,
})
# ---
# name: test_sensor[binary_sensor.test_mower_1_charging-state]
# name: test_binary_sensor_snapshot[binary_sensor.test_mower_1_charging-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'battery_charging',
@ -41,11 +41,12 @@
'context': <ANY>,
'entity_id': 'binary_sensor.test_mower_1_charging',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---
# name: test_sensor[binary_sensor.test_mower_1_leaving_dock-entry]
# name: test_binary_sensor_snapshot[binary_sensor.test_mower_1_leaving_dock-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
@ -78,7 +79,7 @@
'unit_of_measurement': None,
})
# ---
# name: test_sensor[binary_sensor.test_mower_1_leaving_dock-state]
# name: test_binary_sensor_snapshot[binary_sensor.test_mower_1_leaving_dock-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Test Mower 1 Leaving dock',
@ -86,11 +87,12 @@
'context': <ANY>,
'entity_id': 'binary_sensor.test_mower_1_leaving_dock',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---
# name: test_sensor[binary_sensor.test_mower_1_returning_to_dock-entry]
# name: test_binary_sensor_snapshot[binary_sensor.test_mower_1_returning_to_dock-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
@ -123,145 +125,7 @@
'unit_of_measurement': None,
})
# ---
# name: test_sensor[binary_sensor.test_mower_1_returning_to_dock-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Test Mower 1 Returning to dock',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.test_mower_1_returning_to_dock',
'last_changed': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---
# name: test_snapshot_binary_sensor[binary_sensor.test_mower_1_charging-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'binary_sensor',
'entity_category': None,
'entity_id': 'binary_sensor.test_mower_1_charging',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <BinarySensorDeviceClass.BATTERY_CHARGING: 'battery_charging'>,
'original_icon': None,
'original_name': 'Charging',
'platform': 'husqvarna_automower',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': None,
'unique_id': 'c7233734-b219-4287-a173-08e3643f89f0_battery_charging',
'unit_of_measurement': None,
})
# ---
# name: test_snapshot_binary_sensor[binary_sensor.test_mower_1_charging-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'battery_charging',
'friendly_name': 'Test Mower 1 Charging',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.test_mower_1_charging',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---
# name: test_snapshot_binary_sensor[binary_sensor.test_mower_1_leaving_dock-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'binary_sensor',
'entity_category': None,
'entity_id': 'binary_sensor.test_mower_1_leaving_dock',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Leaving dock',
'platform': 'husqvarna_automower',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'leaving_dock',
'unique_id': 'c7233734-b219-4287-a173-08e3643f89f0_leaving_dock',
'unit_of_measurement': None,
})
# ---
# name: test_snapshot_binary_sensor[binary_sensor.test_mower_1_leaving_dock-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Test Mower 1 Leaving dock',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.test_mower_1_leaving_dock',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---
# name: test_snapshot_binary_sensor[binary_sensor.test_mower_1_returning_to_dock-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'binary_sensor',
'entity_category': None,
'entity_id': 'binary_sensor.test_mower_1_returning_to_dock',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Returning to dock',
'platform': 'husqvarna_automower',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'returning_to_dock',
'unique_id': 'c7233734-b219-4287-a173-08e3643f89f0_returning_to_dock',
'unit_of_measurement': None,
})
# ---
# name: test_snapshot_binary_sensor[binary_sensor.test_mower_1_returning_to_dock-state]
# name: test_binary_sensor_snapshot[binary_sensor.test_mower_1_returning_to_dock-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Test Mower 1 Returning to dock',

View File

@ -1,5 +1,5 @@
# serializer version: 1
# name: test_snapshot_number[number.test_mower_1_back_lawn_cutting_height-entry]
# name: test_number_snapshot[number.test_mower_1_back_lawn_cutting_height-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
@ -37,7 +37,7 @@
'unit_of_measurement': '%',
})
# ---
# name: test_snapshot_number[number.test_mower_1_back_lawn_cutting_height-state]
# name: test_number_snapshot[number.test_mower_1_back_lawn_cutting_height-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Test Mower 1 Back lawn cutting height',
@ -55,7 +55,7 @@
'state': '25',
})
# ---
# name: test_snapshot_number[number.test_mower_1_cutting_height-entry]
# name: test_number_snapshot[number.test_mower_1_cutting_height-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
@ -93,7 +93,7 @@
'unit_of_measurement': None,
})
# ---
# name: test_snapshot_number[number.test_mower_1_cutting_height-state]
# name: test_number_snapshot[number.test_mower_1_cutting_height-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Test Mower 1 Cutting height',
@ -110,7 +110,7 @@
'state': '4',
})
# ---
# name: test_snapshot_number[number.test_mower_1_front_lawn_cutting_height-entry]
# name: test_number_snapshot[number.test_mower_1_front_lawn_cutting_height-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
@ -148,7 +148,7 @@
'unit_of_measurement': '%',
})
# ---
# name: test_snapshot_number[number.test_mower_1_front_lawn_cutting_height-state]
# name: test_number_snapshot[number.test_mower_1_front_lawn_cutting_height-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Test Mower 1 Front lawn cutting height',
@ -166,7 +166,7 @@
'state': '50',
})
# ---
# name: test_snapshot_number[number.test_mower_1_my_lawn_cutting_height-entry]
# name: test_number_snapshot[number.test_mower_1_my_lawn_cutting_height-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
@ -204,7 +204,7 @@
'unit_of_measurement': '%',
})
# ---
# name: test_snapshot_number[number.test_mower_1_my_lawn_cutting_height-state]
# name: test_number_snapshot[number.test_mower_1_my_lawn_cutting_height-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Test Mower 1 My lawn cutting height ',

View File

@ -1,5 +1,5 @@
# serializer version: 1
# name: test_sensor[sensor.test_mower_1_battery-entry]
# name: test_sensor_snapshot[sensor.test_mower_1_battery-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
@ -34,7 +34,7 @@
'unit_of_measurement': '%',
})
# ---
# name: test_sensor[sensor.test_mower_1_battery-state]
# name: test_sensor_snapshot[sensor.test_mower_1_battery-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'battery',
@ -50,7 +50,7 @@
'state': '100',
})
# ---
# name: test_sensor[sensor.test_mower_1_cutting_blade_usage_time-entry]
# name: test_sensor_snapshot[sensor.test_mower_1_cutting_blade_usage_time-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
@ -88,7 +88,7 @@
'unit_of_measurement': <UnitOfTime.HOURS: 'h'>,
})
# ---
# name: test_sensor[sensor.test_mower_1_cutting_blade_usage_time-state]
# name: test_sensor_snapshot[sensor.test_mower_1_cutting_blade_usage_time-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'duration',
@ -104,7 +104,7 @@
'state': '0.034',
})
# ---
# name: test_sensor[sensor.test_mower_1_error-entry]
# name: test_sensor_snapshot[sensor.test_mower_1_error-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
@ -283,7 +283,7 @@
'unit_of_measurement': None,
})
# ---
# name: test_sensor[sensor.test_mower_1_error-state]
# name: test_sensor_snapshot[sensor.test_mower_1_error-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'enum',
@ -442,7 +442,7 @@
'state': 'no_error',
})
# ---
# name: test_sensor[sensor.test_mower_1_mode-entry]
# name: test_sensor_snapshot[sensor.test_mower_1_mode-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
@ -483,7 +483,7 @@
'unit_of_measurement': None,
})
# ---
# name: test_sensor[sensor.test_mower_1_mode-state]
# name: test_sensor_snapshot[sensor.test_mower_1_mode-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'enum',
@ -504,7 +504,7 @@
'state': 'main_area',
})
# ---
# name: test_sensor[sensor.test_mower_1_next_start-entry]
# name: test_sensor_snapshot[sensor.test_mower_1_next_start-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
@ -537,7 +537,7 @@
'unit_of_measurement': None,
})
# ---
# name: test_sensor[sensor.test_mower_1_next_start-state]
# name: test_sensor_snapshot[sensor.test_mower_1_next_start-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'timestamp',
@ -551,7 +551,7 @@
'state': '2023-06-05T19:00:00+00:00',
})
# ---
# name: test_sensor[sensor.test_mower_1_number_of_charging_cycles-entry]
# name: test_sensor_snapshot[sensor.test_mower_1_number_of_charging_cycles-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
@ -586,7 +586,7 @@
'unit_of_measurement': None,
})
# ---
# name: test_sensor[sensor.test_mower_1_number_of_charging_cycles-state]
# name: test_sensor_snapshot[sensor.test_mower_1_number_of_charging_cycles-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Test Mower 1 Number of charging cycles',
@ -600,7 +600,7 @@
'state': '1380',
})
# ---
# name: test_sensor[sensor.test_mower_1_number_of_collisions-entry]
# name: test_sensor_snapshot[sensor.test_mower_1_number_of_collisions-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
@ -635,7 +635,7 @@
'unit_of_measurement': None,
})
# ---
# name: test_sensor[sensor.test_mower_1_number_of_collisions-state]
# name: test_sensor_snapshot[sensor.test_mower_1_number_of_collisions-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Test Mower 1 Number of collisions',
@ -649,7 +649,7 @@
'state': '11396',
})
# ---
# name: test_sensor[sensor.test_mower_1_restricted_reason-entry]
# name: test_sensor_snapshot[sensor.test_mower_1_restricted_reason-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
@ -695,7 +695,7 @@
'unit_of_measurement': None,
})
# ---
# name: test_sensor[sensor.test_mower_1_restricted_reason-state]
# name: test_sensor_snapshot[sensor.test_mower_1_restricted_reason-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'enum',
@ -721,7 +721,7 @@
'state': 'week_schedule',
})
# ---
# name: test_sensor[sensor.test_mower_1_total_charging_time-entry]
# name: test_sensor_snapshot[sensor.test_mower_1_total_charging_time-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
@ -759,7 +759,7 @@
'unit_of_measurement': <UnitOfTime.HOURS: 'h'>,
})
# ---
# name: test_sensor[sensor.test_mower_1_total_charging_time-state]
# name: test_sensor_snapshot[sensor.test_mower_1_total_charging_time-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'duration',
@ -775,7 +775,7 @@
'state': '1204.000',
})
# ---
# name: test_sensor[sensor.test_mower_1_total_cutting_time-entry]
# name: test_sensor_snapshot[sensor.test_mower_1_total_cutting_time-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
@ -813,7 +813,7 @@
'unit_of_measurement': <UnitOfTime.HOURS: 'h'>,
})
# ---
# name: test_sensor[sensor.test_mower_1_total_cutting_time-state]
# name: test_sensor_snapshot[sensor.test_mower_1_total_cutting_time-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'duration',
@ -829,7 +829,7 @@
'state': '1165.000',
})
# ---
# name: test_sensor[sensor.test_mower_1_total_drive_distance-entry]
# name: test_sensor_snapshot[sensor.test_mower_1_total_drive_distance-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
@ -867,7 +867,7 @@
'unit_of_measurement': <UnitOfLength.KILOMETERS: 'km'>,
})
# ---
# name: test_sensor[sensor.test_mower_1_total_drive_distance-state]
# name: test_sensor_snapshot[sensor.test_mower_1_total_drive_distance-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'distance',
@ -883,7 +883,7 @@
'state': '1780.272',
})
# ---
# name: test_sensor[sensor.test_mower_1_total_running_time-entry]
# name: test_sensor_snapshot[sensor.test_mower_1_total_running_time-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
@ -921,7 +921,7 @@
'unit_of_measurement': <UnitOfTime.HOURS: 'h'>,
})
# ---
# name: test_sensor[sensor.test_mower_1_total_running_time-state]
# name: test_sensor_snapshot[sensor.test_mower_1_total_running_time-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'duration',
@ -937,7 +937,7 @@
'state': '1268.000',
})
# ---
# name: test_sensor[sensor.test_mower_1_total_searching_time-entry]
# name: test_sensor_snapshot[sensor.test_mower_1_total_searching_time-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
@ -975,7 +975,7 @@
'unit_of_measurement': <UnitOfTime.HOURS: 'h'>,
})
# ---
# name: test_sensor[sensor.test_mower_1_total_searching_time-state]
# name: test_sensor_snapshot[sensor.test_mower_1_total_searching_time-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'duration',

View File

@ -1,5 +1,5 @@
# serializer version: 1
# name: test_switch[switch.test_mower_1_avoid_danger_zone-entry]
# name: test_switch_snapshot[switch.test_mower_1_avoid_danger_zone-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
@ -32,7 +32,7 @@
'unit_of_measurement': None,
})
# ---
# name: test_switch[switch.test_mower_1_avoid_danger_zone-state]
# name: test_switch_snapshot[switch.test_mower_1_avoid_danger_zone-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Test Mower 1 Avoid Danger Zone',
@ -45,7 +45,7 @@
'state': 'off',
})
# ---
# name: test_switch[switch.test_mower_1_avoid_springflowers-entry]
# name: test_switch_snapshot[switch.test_mower_1_avoid_springflowers-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
@ -78,7 +78,7 @@
'unit_of_measurement': None,
})
# ---
# name: test_switch[switch.test_mower_1_avoid_springflowers-state]
# name: test_switch_snapshot[switch.test_mower_1_avoid_springflowers-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Test Mower 1 Avoid Springflowers',
@ -91,7 +91,7 @@
'state': 'on',
})
# ---
# name: test_switch[switch.test_mower_1_enable_schedule-entry]
# name: test_switch_snapshot[switch.test_mower_1_enable_schedule-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
@ -124,7 +124,7 @@
'unit_of_measurement': None,
})
# ---
# name: test_switch[switch.test_mower_1_enable_schedule-state]
# name: test_switch_snapshot[switch.test_mower_1_enable_schedule-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Test Mower 1 Enable schedule',

View File

@ -59,14 +59,14 @@ async def test_binary_sensor_states(
assert state.state == "on"
async def test_snapshot_binary_sensor(
async def test_binary_sensor_snapshot(
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
mock_automower_client: AsyncMock,
mock_config_entry: MockConfigEntry,
snapshot: SnapshotAssertion,
) -> None:
"""Test states of the binary sensors."""
"""Snapshot test states of the binary sensors."""
with patch(
"homeassistant.components.husqvarna_automower.PLATFORMS",
[Platform.BINARY_SENSOR],

View File

@ -20,7 +20,7 @@ async def test_device_tracker_snapshot(
mock_config_entry: MockConfigEntry,
snapshot: SnapshotAssertion,
) -> None:
"""Test device tracker with a snapshot."""
"""Snapshot test of the device tracker."""
with patch(
"homeassistant.components.husqvarna_automower.PLATFORMS",
[Platform.DEVICE_TRACKER],

View File

@ -70,19 +70,16 @@ async def test_lawn_mower_commands(
) -> None:
"""Test lawn_mower commands."""
await setup_integration(hass, mock_config_entry)
getattr(
mock_automower_client.commands, aioautomower_command
).side_effect = ApiException("Test error")
with pytest.raises(HomeAssistantError) as exc_info:
with pytest.raises(
HomeAssistantError,
match="Command couldn't be sent to the command queue: Test error",
):
await hass.services.async_call(
domain="lawn_mower",
service=service,
service_data={"entity_id": "lawn_mower.test_mower_1"},
blocking=True,
)
assert (
str(exc_info.value)
== "Command couldn't be sent to the command queue: Test error"
)

View File

@ -36,10 +36,13 @@ async def test_number_commands(
blocking=True,
)
mocked_method = mock_automower_client.commands.set_cutting_height
assert len(mocked_method.mock_calls) == 1
mocked_method.assert_called_once_with(TEST_MOWER_ID, 3)
mocked_method.side_effect = ApiException("Test error")
with pytest.raises(HomeAssistantError) as exc_info:
with pytest.raises(
HomeAssistantError,
match="Command couldn't be sent to the command queue: Test error",
):
await hass.services.async_call(
domain="number",
service="set_value",
@ -47,10 +50,6 @@ async def test_number_commands(
service_data={"value": "3"},
blocking=True,
)
assert (
str(exc_info.value)
== "Command couldn't be sent to the command queue: Test error"
)
assert len(mocked_method.mock_calls) == 2
@ -78,13 +77,16 @@ async def test_number_workarea_commands(
service_data={"value": "75"},
blocking=True,
)
assert len(mocked_method.mock_calls) == 1
mocked_method.assert_called_once_with(TEST_MOWER_ID, 75, 123456)
state = hass.states.get(entity_id)
assert state.state is not None
assert state.state == "75"
mocked_method.side_effect = ApiException("Test error")
with pytest.raises(HomeAssistantError) as exc_info:
with pytest.raises(
HomeAssistantError,
match="Command couldn't be sent to the command queue: Test error",
):
await hass.services.async_call(
domain="number",
service="set_value",
@ -92,10 +94,6 @@ async def test_number_workarea_commands(
service_data={"value": "75"},
blocking=True,
)
assert (
str(exc_info.value)
== "Command couldn't be sent to the command queue: Test error"
)
assert len(mocked_method.mock_calls) == 2
@ -125,14 +123,14 @@ async def test_workarea_deleted(
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
async def test_snapshot_number(
async def test_number_snapshot(
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
mock_automower_client: AsyncMock,
mock_config_entry: MockConfigEntry,
snapshot: SnapshotAssertion,
) -> None:
"""Test states of the number entity."""
"""Snapshot tests of the number entities."""
with patch(
"homeassistant.components.husqvarna_automower.PLATFORMS",
[Platform.NUMBER],

View File

@ -82,10 +82,14 @@ async def test_select_commands(
blocking=True,
)
mocked_method = mock_automower_client.commands.set_headlight_mode
mocked_method.assert_called_once_with(TEST_MOWER_ID, service.upper())
assert len(mocked_method.mock_calls) == 1
mocked_method.side_effect = ApiException("Test error")
with pytest.raises(HomeAssistantError) as exc_info:
with pytest.raises(
HomeAssistantError,
match="Command couldn't be sent to the command queue: Test error",
):
await hass.services.async_call(
domain="select",
service="select_option",
@ -95,8 +99,4 @@ async def test_select_commands(
},
blocking=True,
)
assert (
str(exc_info.value)
== "Command couldn't be sent to the command queue: Test error"
)
assert len(mocked_method.mock_calls) == 2

View File

@ -144,14 +144,14 @@ async def test_error_sensor(
assert state.state == expected_state
async def test_sensor(
async def test_sensor_snapshot(
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
mock_automower_client: AsyncMock,
mock_config_entry: MockConfigEntry,
snapshot: SnapshotAssertion,
) -> None:
"""Test states of the sensors."""
"""Snapshot test of the sensors."""
with patch(
"homeassistant.components.husqvarna_automower.PLATFORMS",
[Platform.SENSOR],

View File

@ -79,20 +79,19 @@ async def test_switch_commands(
blocking=True,
)
mocked_method = getattr(mock_automower_client.commands, aioautomower_command)
assert len(mocked_method.mock_calls) == 1
mocked_method.assert_called_once_with(TEST_MOWER_ID)
mocked_method.side_effect = ApiException("Test error")
with pytest.raises(HomeAssistantError) as exc_info:
with pytest.raises(
HomeAssistantError,
match="Command couldn't be sent to the command queue: Test error",
):
await hass.services.async_call(
domain="switch",
service=service,
service_data={"entity_id": "switch.test_mower_1_enable_schedule"},
blocking=True,
)
assert (
str(exc_info.value)
== "Command couldn't be sent to the command queue: Test error"
)
assert len(mocked_method.mock_calls) == 2
@ -172,14 +171,14 @@ async def test_zones_deleted(
) == (current_entries - 1)
async def test_switch(
async def test_switch_snapshot(
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
mock_automower_client: AsyncMock,
mock_config_entry: MockConfigEntry,
snapshot: SnapshotAssertion,
) -> None:
"""Test states of the switch."""
"""Snapshot tests of the switches."""
with patch(
"homeassistant.components.husqvarna_automower.PLATFORMS",
[Platform.SWITCH],