mirror of
https://github.com/home-assistant/core.git
synced 2025-07-21 20:27:08 +00:00
Bump aioautomower to 2024.10.3 (#128788)
This commit is contained in:
parent
bd55fe868d
commit
1c5193aa4d
@ -14,6 +14,7 @@ from homeassistant.helpers import (
|
|||||||
config_entry_oauth2_flow,
|
config_entry_oauth2_flow,
|
||||||
device_registry as dr,
|
device_registry as dr,
|
||||||
)
|
)
|
||||||
|
from homeassistant.util import dt as dt_util
|
||||||
|
|
||||||
from . import api
|
from . import api
|
||||||
from .const import DOMAIN
|
from .const import DOMAIN
|
||||||
@ -48,7 +49,11 @@ async def async_setup_entry(hass: HomeAssistant, entry: AutomowerConfigEntry) ->
|
|||||||
aiohttp_client.async_get_clientsession(hass),
|
aiohttp_client.async_get_clientsession(hass),
|
||||||
session,
|
session,
|
||||||
)
|
)
|
||||||
automower_api = AutomowerSession(api_api)
|
time_zone_str = str(dt_util.DEFAULT_TIME_ZONE)
|
||||||
|
automower_api = AutomowerSession(
|
||||||
|
api_api,
|
||||||
|
await dt_util.async_get_time_zone(time_zone_str),
|
||||||
|
)
|
||||||
try:
|
try:
|
||||||
await api_api.async_get_access_token()
|
await api_api.async_get_access_token()
|
||||||
except ClientResponseError as err:
|
except ClientResponseError as err:
|
||||||
|
@ -11,7 +11,6 @@ from aioautomower.session import AutomowerSession
|
|||||||
from homeassistant.components.button import ButtonEntity, ButtonEntityDescription
|
from homeassistant.components.button import ButtonEntity, ButtonEntityDescription
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
from homeassistant.util import dt as dt_util
|
|
||||||
|
|
||||||
from . import AutomowerConfigEntry
|
from . import AutomowerConfigEntry
|
||||||
from .coordinator import AutomowerDataUpdateCoordinator
|
from .coordinator import AutomowerDataUpdateCoordinator
|
||||||
@ -24,19 +23,6 @@ from .entity import (
|
|||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
async def _async_set_time(
|
|
||||||
session: AutomowerSession,
|
|
||||||
mower_id: str,
|
|
||||||
) -> None:
|
|
||||||
"""Set datetime for the mower."""
|
|
||||||
# dt_util returns the current (aware) local datetime, set in the frontend.
|
|
||||||
# We assume it's the timezone in which the mower is.
|
|
||||||
await session.commands.set_datetime(
|
|
||||||
mower_id,
|
|
||||||
dt_util.now(),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True, kw_only=True)
|
@dataclass(frozen=True, kw_only=True)
|
||||||
class AutomowerButtonEntityDescription(ButtonEntityDescription):
|
class AutomowerButtonEntityDescription(ButtonEntityDescription):
|
||||||
"""Describes Automower button entities."""
|
"""Describes Automower button entities."""
|
||||||
@ -58,7 +44,7 @@ MOWER_BUTTON_TYPES: tuple[AutomowerButtonEntityDescription, ...] = (
|
|||||||
key="sync_clock",
|
key="sync_clock",
|
||||||
translation_key="sync_clock",
|
translation_key="sync_clock",
|
||||||
available_fn=_check_error_free,
|
available_fn=_check_error_free,
|
||||||
press_fn=_async_set_time,
|
press_fn=lambda session, mower_id: session.commands.set_datetime(mower_id),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -60,8 +60,8 @@ class AutomowerCalendarEntity(AutomowerBaseEntity, CalendarEntity):
|
|||||||
]
|
]
|
||||||
return CalendarEvent(
|
return CalendarEvent(
|
||||||
summary=make_name_string(work_area_name, program_event.schedule_no),
|
summary=make_name_string(work_area_name, program_event.schedule_no),
|
||||||
start=program_event.start.replace(tzinfo=dt_util.DEFAULT_TIME_ZONE),
|
start=program_event.start,
|
||||||
end=program_event.end.replace(tzinfo=dt_util.DEFAULT_TIME_ZONE),
|
end=program_event.end,
|
||||||
rrule=program_event.rrule_str,
|
rrule=program_event.rrule_str,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -7,5 +7,5 @@
|
|||||||
"documentation": "https://www.home-assistant.io/integrations/husqvarna_automower",
|
"documentation": "https://www.home-assistant.io/integrations/husqvarna_automower",
|
||||||
"iot_class": "cloud_push",
|
"iot_class": "cloud_push",
|
||||||
"loggers": ["aioautomower"],
|
"loggers": ["aioautomower"],
|
||||||
"requirements": ["aioautomower==2024.10.0"]
|
"requirements": ["aioautomower==2024.10.3"]
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,8 @@ from collections.abc import Callable, Mapping
|
|||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import logging
|
import logging
|
||||||
|
from operator import attrgetter
|
||||||
from typing import TYPE_CHECKING, Any
|
from typing import TYPE_CHECKING, Any
|
||||||
from zoneinfo import ZoneInfo
|
|
||||||
|
|
||||||
from aioautomower.model import (
|
from aioautomower.model import (
|
||||||
MowerAttributes,
|
MowerAttributes,
|
||||||
@ -14,7 +14,6 @@ from aioautomower.model import (
|
|||||||
RestrictedReasons,
|
RestrictedReasons,
|
||||||
WorkArea,
|
WorkArea,
|
||||||
)
|
)
|
||||||
from aioautomower.utils import naive_to_aware
|
|
||||||
|
|
||||||
from homeassistant.components.sensor import (
|
from homeassistant.components.sensor import (
|
||||||
SensorDeviceClass,
|
SensorDeviceClass,
|
||||||
@ -26,7 +25,6 @@ from homeassistant.const import PERCENTAGE, EntityCategory, UnitOfLength, UnitOf
|
|||||||
from homeassistant.core import HomeAssistant, callback
|
from homeassistant.core import HomeAssistant, callback
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
from homeassistant.helpers.typing import StateType
|
from homeassistant.helpers.typing import StateType
|
||||||
from homeassistant.util import dt as dt_util
|
|
||||||
|
|
||||||
from . import AutomowerConfigEntry
|
from . import AutomowerConfigEntry
|
||||||
from .coordinator import AutomowerDataUpdateCoordinator
|
from .coordinator import AutomowerDataUpdateCoordinator
|
||||||
@ -196,16 +194,16 @@ ERROR_STATES = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
RESTRICTED_REASONS: list = [
|
RESTRICTED_REASONS: list = [
|
||||||
RestrictedReasons.ALL_WORK_AREAS_COMPLETED.lower(),
|
RestrictedReasons.ALL_WORK_AREAS_COMPLETED,
|
||||||
RestrictedReasons.DAILY_LIMIT.lower(),
|
RestrictedReasons.DAILY_LIMIT,
|
||||||
RestrictedReasons.EXTERNAL.lower(),
|
RestrictedReasons.EXTERNAL,
|
||||||
RestrictedReasons.FOTA.lower(),
|
RestrictedReasons.FOTA,
|
||||||
RestrictedReasons.FROST.lower(),
|
RestrictedReasons.FROST,
|
||||||
RestrictedReasons.NONE.lower(),
|
RestrictedReasons.NONE,
|
||||||
RestrictedReasons.NOT_APPLICABLE.lower(),
|
RestrictedReasons.NOT_APPLICABLE,
|
||||||
RestrictedReasons.PARK_OVERRIDE.lower(),
|
RestrictedReasons.PARK_OVERRIDE,
|
||||||
RestrictedReasons.SENSOR.lower(),
|
RestrictedReasons.SENSOR,
|
||||||
RestrictedReasons.WEEK_SCHEDULE.lower(),
|
RestrictedReasons.WEEK_SCHEDULE,
|
||||||
]
|
]
|
||||||
|
|
||||||
STATE_NO_WORK_AREA_ACTIVE = "no_work_area_active"
|
STATE_NO_WORK_AREA_ACTIVE = "no_work_area_active"
|
||||||
@ -272,15 +270,15 @@ MOWER_SENSOR_TYPES: tuple[AutomowerSensorEntityDescription, ...] = (
|
|||||||
state_class=SensorStateClass.MEASUREMENT,
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
device_class=SensorDeviceClass.BATTERY,
|
device_class=SensorDeviceClass.BATTERY,
|
||||||
native_unit_of_measurement=PERCENTAGE,
|
native_unit_of_measurement=PERCENTAGE,
|
||||||
value_fn=lambda data: data.battery.battery_percent,
|
value_fn=attrgetter("battery.battery_percent"),
|
||||||
),
|
),
|
||||||
AutomowerSensorEntityDescription(
|
AutomowerSensorEntityDescription(
|
||||||
key="mode",
|
key="mode",
|
||||||
translation_key="mode",
|
translation_key="mode",
|
||||||
device_class=SensorDeviceClass.ENUM,
|
device_class=SensorDeviceClass.ENUM,
|
||||||
option_fn=lambda data: [option.lower() for option in list(MowerModes)],
|
option_fn=lambda data: list(MowerModes),
|
||||||
value_fn=(
|
value_fn=(
|
||||||
lambda data: data.mower.mode.lower()
|
lambda data: data.mower.mode
|
||||||
if data.mower.mode != MowerModes.UNKNOWN
|
if data.mower.mode != MowerModes.UNKNOWN
|
||||||
else None
|
else None
|
||||||
),
|
),
|
||||||
@ -293,7 +291,7 @@ MOWER_SENSOR_TYPES: tuple[AutomowerSensorEntityDescription, ...] = (
|
|||||||
native_unit_of_measurement=UnitOfTime.SECONDS,
|
native_unit_of_measurement=UnitOfTime.SECONDS,
|
||||||
suggested_unit_of_measurement=UnitOfTime.HOURS,
|
suggested_unit_of_measurement=UnitOfTime.HOURS,
|
||||||
exists_fn=lambda data: data.statistics.cutting_blade_usage_time is not None,
|
exists_fn=lambda data: data.statistics.cutting_blade_usage_time is not None,
|
||||||
value_fn=lambda data: data.statistics.cutting_blade_usage_time,
|
value_fn=attrgetter("statistics.cutting_blade_usage_time"),
|
||||||
),
|
),
|
||||||
AutomowerSensorEntityDescription(
|
AutomowerSensorEntityDescription(
|
||||||
key="total_charging_time",
|
key="total_charging_time",
|
||||||
@ -304,7 +302,7 @@ MOWER_SENSOR_TYPES: tuple[AutomowerSensorEntityDescription, ...] = (
|
|||||||
native_unit_of_measurement=UnitOfTime.SECONDS,
|
native_unit_of_measurement=UnitOfTime.SECONDS,
|
||||||
suggested_unit_of_measurement=UnitOfTime.HOURS,
|
suggested_unit_of_measurement=UnitOfTime.HOURS,
|
||||||
exists_fn=lambda data: data.statistics.total_charging_time is not None,
|
exists_fn=lambda data: data.statistics.total_charging_time is not None,
|
||||||
value_fn=lambda data: data.statistics.total_charging_time,
|
value_fn=attrgetter("statistics.total_charging_time"),
|
||||||
),
|
),
|
||||||
AutomowerSensorEntityDescription(
|
AutomowerSensorEntityDescription(
|
||||||
key="total_cutting_time",
|
key="total_cutting_time",
|
||||||
@ -315,7 +313,7 @@ MOWER_SENSOR_TYPES: tuple[AutomowerSensorEntityDescription, ...] = (
|
|||||||
native_unit_of_measurement=UnitOfTime.SECONDS,
|
native_unit_of_measurement=UnitOfTime.SECONDS,
|
||||||
suggested_unit_of_measurement=UnitOfTime.HOURS,
|
suggested_unit_of_measurement=UnitOfTime.HOURS,
|
||||||
exists_fn=lambda data: data.statistics.total_cutting_time is not None,
|
exists_fn=lambda data: data.statistics.total_cutting_time is not None,
|
||||||
value_fn=lambda data: data.statistics.total_cutting_time,
|
value_fn=attrgetter("statistics.total_cutting_time"),
|
||||||
),
|
),
|
||||||
AutomowerSensorEntityDescription(
|
AutomowerSensorEntityDescription(
|
||||||
key="total_running_time",
|
key="total_running_time",
|
||||||
@ -326,7 +324,7 @@ MOWER_SENSOR_TYPES: tuple[AutomowerSensorEntityDescription, ...] = (
|
|||||||
native_unit_of_measurement=UnitOfTime.SECONDS,
|
native_unit_of_measurement=UnitOfTime.SECONDS,
|
||||||
suggested_unit_of_measurement=UnitOfTime.HOURS,
|
suggested_unit_of_measurement=UnitOfTime.HOURS,
|
||||||
exists_fn=lambda data: data.statistics.total_running_time is not None,
|
exists_fn=lambda data: data.statistics.total_running_time is not None,
|
||||||
value_fn=lambda data: data.statistics.total_running_time,
|
value_fn=attrgetter("statistics.total_running_time"),
|
||||||
),
|
),
|
||||||
AutomowerSensorEntityDescription(
|
AutomowerSensorEntityDescription(
|
||||||
key="total_searching_time",
|
key="total_searching_time",
|
||||||
@ -337,7 +335,7 @@ MOWER_SENSOR_TYPES: tuple[AutomowerSensorEntityDescription, ...] = (
|
|||||||
native_unit_of_measurement=UnitOfTime.SECONDS,
|
native_unit_of_measurement=UnitOfTime.SECONDS,
|
||||||
suggested_unit_of_measurement=UnitOfTime.HOURS,
|
suggested_unit_of_measurement=UnitOfTime.HOURS,
|
||||||
exists_fn=lambda data: data.statistics.total_searching_time is not None,
|
exists_fn=lambda data: data.statistics.total_searching_time is not None,
|
||||||
value_fn=lambda data: data.statistics.total_searching_time,
|
value_fn=attrgetter("statistics.total_searching_time"),
|
||||||
),
|
),
|
||||||
AutomowerSensorEntityDescription(
|
AutomowerSensorEntityDescription(
|
||||||
key="number_of_charging_cycles",
|
key="number_of_charging_cycles",
|
||||||
@ -345,7 +343,7 @@ MOWER_SENSOR_TYPES: tuple[AutomowerSensorEntityDescription, ...] = (
|
|||||||
entity_category=EntityCategory.DIAGNOSTIC,
|
entity_category=EntityCategory.DIAGNOSTIC,
|
||||||
state_class=SensorStateClass.TOTAL,
|
state_class=SensorStateClass.TOTAL,
|
||||||
exists_fn=lambda data: data.statistics.number_of_charging_cycles is not None,
|
exists_fn=lambda data: data.statistics.number_of_charging_cycles is not None,
|
||||||
value_fn=lambda data: data.statistics.number_of_charging_cycles,
|
value_fn=attrgetter("statistics.number_of_charging_cycles"),
|
||||||
),
|
),
|
||||||
AutomowerSensorEntityDescription(
|
AutomowerSensorEntityDescription(
|
||||||
key="number_of_collisions",
|
key="number_of_collisions",
|
||||||
@ -353,7 +351,7 @@ MOWER_SENSOR_TYPES: tuple[AutomowerSensorEntityDescription, ...] = (
|
|||||||
entity_category=EntityCategory.DIAGNOSTIC,
|
entity_category=EntityCategory.DIAGNOSTIC,
|
||||||
state_class=SensorStateClass.TOTAL,
|
state_class=SensorStateClass.TOTAL,
|
||||||
exists_fn=lambda data: data.statistics.number_of_collisions is not None,
|
exists_fn=lambda data: data.statistics.number_of_collisions is not None,
|
||||||
value_fn=lambda data: data.statistics.number_of_collisions,
|
value_fn=attrgetter("statistics.number_of_collisions"),
|
||||||
),
|
),
|
||||||
AutomowerSensorEntityDescription(
|
AutomowerSensorEntityDescription(
|
||||||
key="total_drive_distance",
|
key="total_drive_distance",
|
||||||
@ -364,16 +362,13 @@ MOWER_SENSOR_TYPES: tuple[AutomowerSensorEntityDescription, ...] = (
|
|||||||
native_unit_of_measurement=UnitOfLength.METERS,
|
native_unit_of_measurement=UnitOfLength.METERS,
|
||||||
suggested_unit_of_measurement=UnitOfLength.KILOMETERS,
|
suggested_unit_of_measurement=UnitOfLength.KILOMETERS,
|
||||||
exists_fn=lambda data: data.statistics.total_drive_distance is not None,
|
exists_fn=lambda data: data.statistics.total_drive_distance is not None,
|
||||||
value_fn=lambda data: data.statistics.total_drive_distance,
|
value_fn=attrgetter("statistics.total_drive_distance"),
|
||||||
),
|
),
|
||||||
AutomowerSensorEntityDescription(
|
AutomowerSensorEntityDescription(
|
||||||
key="next_start_timestamp",
|
key="next_start_timestamp",
|
||||||
translation_key="next_start_timestamp",
|
translation_key="next_start_timestamp",
|
||||||
device_class=SensorDeviceClass.TIMESTAMP,
|
device_class=SensorDeviceClass.TIMESTAMP,
|
||||||
value_fn=lambda data: naive_to_aware(
|
value_fn=attrgetter("planner.next_start_datetime"),
|
||||||
data.planner.next_start_datetime_naive,
|
|
||||||
ZoneInfo(str(dt_util.DEFAULT_TIME_ZONE)),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
AutomowerSensorEntityDescription(
|
AutomowerSensorEntityDescription(
|
||||||
key="error",
|
key="error",
|
||||||
@ -387,7 +382,7 @@ MOWER_SENSOR_TYPES: tuple[AutomowerSensorEntityDescription, ...] = (
|
|||||||
translation_key="restricted_reason",
|
translation_key="restricted_reason",
|
||||||
device_class=SensorDeviceClass.ENUM,
|
device_class=SensorDeviceClass.ENUM,
|
||||||
option_fn=lambda data: RESTRICTED_REASONS,
|
option_fn=lambda data: RESTRICTED_REASONS,
|
||||||
value_fn=lambda data: data.planner.restricted_reason.lower(),
|
value_fn=attrgetter("planner.restricted_reason"),
|
||||||
),
|
),
|
||||||
AutomowerSensorEntityDescription(
|
AutomowerSensorEntityDescription(
|
||||||
key="work_area",
|
key="work_area",
|
||||||
@ -417,17 +412,14 @@ WORK_AREA_SENSOR_TYPES: tuple[WorkAreaSensorEntityDescription, ...] = (
|
|||||||
exists_fn=lambda data: data.progress is not None,
|
exists_fn=lambda data: data.progress is not None,
|
||||||
state_class=SensorStateClass.MEASUREMENT,
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
native_unit_of_measurement=PERCENTAGE,
|
native_unit_of_measurement=PERCENTAGE,
|
||||||
value_fn=lambda data: data.progress,
|
value_fn=attrgetter("progress"),
|
||||||
),
|
),
|
||||||
WorkAreaSensorEntityDescription(
|
WorkAreaSensorEntityDescription(
|
||||||
key="last_time_completed",
|
key="last_time_completed",
|
||||||
translation_key_fn=_work_area_translation_key,
|
translation_key_fn=_work_area_translation_key,
|
||||||
exists_fn=lambda data: data.last_time_completed_naive is not None,
|
exists_fn=lambda data: data.last_time_completed is not None,
|
||||||
device_class=SensorDeviceClass.TIMESTAMP,
|
device_class=SensorDeviceClass.TIMESTAMP,
|
||||||
value_fn=lambda data: naive_to_aware(
|
value_fn=attrgetter("last_time_completed"),
|
||||||
data.last_time_completed_naive,
|
|
||||||
ZoneInfo(str(dt_util.DEFAULT_TIME_ZONE)),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -198,7 +198,7 @@ aioaseko==1.0.0
|
|||||||
aioasuswrt==1.4.0
|
aioasuswrt==1.4.0
|
||||||
|
|
||||||
# homeassistant.components.husqvarna_automower
|
# homeassistant.components.husqvarna_automower
|
||||||
aioautomower==2024.10.0
|
aioautomower==2024.10.3
|
||||||
|
|
||||||
# homeassistant.components.azure_devops
|
# homeassistant.components.azure_devops
|
||||||
aioazuredevops==2.2.1
|
aioazuredevops==2.2.1
|
||||||
|
@ -186,7 +186,7 @@ aioaseko==1.0.0
|
|||||||
aioasuswrt==1.4.0
|
aioasuswrt==1.4.0
|
||||||
|
|
||||||
# homeassistant.components.husqvarna_automower
|
# homeassistant.components.husqvarna_automower
|
||||||
aioautomower==2024.10.0
|
aioautomower==2024.10.3
|
||||||
|
|
||||||
# homeassistant.components.azure_devops
|
# homeassistant.components.azure_devops
|
||||||
aioazuredevops==2.2.1
|
aioazuredevops==2.2.1
|
||||||
|
@ -4,6 +4,7 @@ from collections.abc import Generator
|
|||||||
import time
|
import time
|
||||||
from unittest.mock import AsyncMock, patch
|
from unittest.mock import AsyncMock, patch
|
||||||
|
|
||||||
|
from aioautomower.model import MowerAttributes
|
||||||
from aioautomower.session import AutomowerSession, _MowerCommands
|
from aioautomower.session import AutomowerSession, _MowerCommands
|
||||||
from aioautomower.utils import mower_list_to_dictionary_dataclass
|
from aioautomower.utils import mower_list_to_dictionary_dataclass
|
||||||
from aiohttp import ClientWebSocketResponse
|
from aiohttp import ClientWebSocketResponse
|
||||||
@ -16,6 +17,7 @@ from homeassistant.components.application_credentials import (
|
|||||||
from homeassistant.components.husqvarna_automower.const import DOMAIN
|
from homeassistant.components.husqvarna_automower.const import DOMAIN
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.setup import async_setup_component
|
from homeassistant.setup import async_setup_component
|
||||||
|
from homeassistant.util import dt as dt_util
|
||||||
|
|
||||||
from .const import CLIENT_ID, CLIENT_SECRET, USER_ID
|
from .const import CLIENT_ID, CLIENT_SECRET, USER_ID
|
||||||
|
|
||||||
@ -40,6 +42,21 @@ def mock_scope() -> str:
|
|||||||
return "iam:read amc:api"
|
return "iam:read amc:api"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(name="mower_time_zone")
|
||||||
|
async def mock_time_zone(hass: HomeAssistant) -> dict[str, MowerAttributes]:
|
||||||
|
"""Fixture to set correct scope for the token."""
|
||||||
|
return await dt_util.async_get_time_zone("Europe/Berlin")
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(name="values")
|
||||||
|
def mock_values(mower_time_zone) -> dict[str, MowerAttributes]:
|
||||||
|
"""Fixture to set correct scope for the token."""
|
||||||
|
return mower_list_to_dictionary_dataclass(
|
||||||
|
load_json_value_fixture("mower.json", DOMAIN),
|
||||||
|
mower_time_zone,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def mock_config_entry(jwt: str, expires_at: int, scope: str) -> MockConfigEntry:
|
def mock_config_entry(jwt: str, expires_at: int, scope: str) -> MockConfigEntry:
|
||||||
"""Return the default mocked config entry."""
|
"""Return the default mocked config entry."""
|
||||||
@ -81,17 +98,13 @@ async def setup_credentials(hass: HomeAssistant) -> None:
|
|||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def mock_automower_client() -> Generator[AsyncMock]:
|
def mock_automower_client(values) -> Generator[AsyncMock]:
|
||||||
"""Mock a Husqvarna Automower client."""
|
"""Mock a Husqvarna Automower client."""
|
||||||
|
|
||||||
mower_dict = mower_list_to_dictionary_dataclass(
|
|
||||||
load_json_value_fixture("mower.json", DOMAIN)
|
|
||||||
)
|
|
||||||
|
|
||||||
mock = AsyncMock(spec=AutomowerSession)
|
mock = AsyncMock(spec=AutomowerSession)
|
||||||
mock.auth = AsyncMock(side_effect=ClientWebSocketResponse)
|
mock.auth = AsyncMock(side_effect=ClientWebSocketResponse)
|
||||||
mock.commands = AsyncMock(spec_set=_MowerCommands)
|
mock.commands = AsyncMock(spec_set=_MowerCommands)
|
||||||
mock.get_status.return_value = mower_dict
|
mock.get_status.return_value = values
|
||||||
|
|
||||||
with patch(
|
with patch(
|
||||||
"homeassistant.components.husqvarna_automower.AutomowerSession",
|
"homeassistant.components.husqvarna_automower.AutomowerSession",
|
||||||
|
@ -68,6 +68,11 @@
|
|||||||
'start': '2023-06-10T01:00:00+02:00',
|
'start': '2023-06-10T01:00:00+02:00',
|
||||||
'summary': 'Back lawn schedule 2',
|
'summary': 'Back lawn schedule 2',
|
||||||
}),
|
}),
|
||||||
|
dict({
|
||||||
|
'end': '2023-06-12T09:00:00+02:00',
|
||||||
|
'start': '2023-06-12T01:00:00+02:00',
|
||||||
|
'summary': 'Back lawn schedule 2',
|
||||||
|
}),
|
||||||
]),
|
]),
|
||||||
}),
|
}),
|
||||||
'calendar.test_mower_2': dict({
|
'calendar.test_mower_2': dict({
|
||||||
|
@ -68,31 +68,33 @@
|
|||||||
'status_dateteime': '2023-06-05T00:00:00+00:00',
|
'status_dateteime': '2023-06-05T00:00:00+00:00',
|
||||||
}),
|
}),
|
||||||
'mower': dict({
|
'mower': dict({
|
||||||
'activity': 'PARKED_IN_CS',
|
'activity': 'parked_in_cs',
|
||||||
'error_code': 0,
|
'error_code': 0,
|
||||||
|
'error_datetime': None,
|
||||||
'error_datetime_naive': None,
|
'error_datetime_naive': None,
|
||||||
'error_key': None,
|
'error_key': None,
|
||||||
'error_timestamp': 0,
|
'error_timestamp': 0,
|
||||||
'inactive_reason': 'NONE',
|
'inactive_reason': 'none',
|
||||||
'is_error_confirmable': False,
|
'is_error_confirmable': False,
|
||||||
'mode': 'MAIN_AREA',
|
'mode': 'main_area',
|
||||||
'state': 'RESTRICTED',
|
'state': 'restricted',
|
||||||
'work_area_id': 123456,
|
'work_area_id': 123456,
|
||||||
'work_area_name': 'Front lawn',
|
'work_area_name': 'Front lawn',
|
||||||
}),
|
}),
|
||||||
'planner': dict({
|
'planner': dict({
|
||||||
'next_start': 1685991600000,
|
'next_start': 1685991600000,
|
||||||
|
'next_start_datetime': '2023-06-05T19:00:00+02:00',
|
||||||
'next_start_datetime_naive': '2023-06-05T19:00:00',
|
'next_start_datetime_naive': '2023-06-05T19:00:00',
|
||||||
'override': dict({
|
'override': dict({
|
||||||
'action': 'NOT_ACTIVE',
|
'action': 'not_active',
|
||||||
}),
|
}),
|
||||||
'restricted_reason': 'WEEK_SCHEDULE',
|
'restricted_reason': 'week_schedule',
|
||||||
}),
|
}),
|
||||||
'positions': '**REDACTED**',
|
'positions': '**REDACTED**',
|
||||||
'settings': dict({
|
'settings': dict({
|
||||||
'cutting_height': 4,
|
'cutting_height': 4,
|
||||||
'headlight': dict({
|
'headlight': dict({
|
||||||
'mode': 'EVENING_ONLY',
|
'mode': 'evening_only',
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
'statistics': dict({
|
'statistics': dict({
|
||||||
@ -138,6 +140,7 @@
|
|||||||
'0': dict({
|
'0': dict({
|
||||||
'cutting_height': 50,
|
'cutting_height': 50,
|
||||||
'enabled': False,
|
'enabled': False,
|
||||||
|
'last_time_completed': '2024-08-12T05:07:49+02:00',
|
||||||
'last_time_completed_naive': '2024-08-12T05:07:49',
|
'last_time_completed_naive': '2024-08-12T05:07:49',
|
||||||
'name': 'my_lawn',
|
'name': 'my_lawn',
|
||||||
'progress': 20,
|
'progress': 20,
|
||||||
@ -145,6 +148,7 @@
|
|||||||
'123456': dict({
|
'123456': dict({
|
||||||
'cutting_height': 50,
|
'cutting_height': 50,
|
||||||
'enabled': True,
|
'enabled': True,
|
||||||
|
'last_time_completed': '2024-08-12T07:54:29+02:00',
|
||||||
'last_time_completed_naive': '2024-08-12T07:54:29',
|
'last_time_completed_naive': '2024-08-12T07:54:29',
|
||||||
'name': 'Front lawn',
|
'name': 'Front lawn',
|
||||||
'progress': 40,
|
'progress': 40,
|
||||||
@ -152,6 +156,7 @@
|
|||||||
'654321': dict({
|
'654321': dict({
|
||||||
'cutting_height': 25,
|
'cutting_height': 25,
|
||||||
'enabled': True,
|
'enabled': True,
|
||||||
|
'last_time_completed': None,
|
||||||
'last_time_completed_naive': None,
|
'last_time_completed_naive': None,
|
||||||
'name': 'Back lawn',
|
'name': 'Back lawn',
|
||||||
'progress': None,
|
'progress': None,
|
||||||
@ -165,7 +170,7 @@
|
|||||||
'auth_implementation': 'husqvarna_automower',
|
'auth_implementation': 'husqvarna_automower',
|
||||||
'token': dict({
|
'token': dict({
|
||||||
'access_token': '**REDACTED**',
|
'access_token': '**REDACTED**',
|
||||||
'expires_at': 1685926800.0,
|
'expires_at': 1685919600.0,
|
||||||
'expires_in': 86399,
|
'expires_in': 86399,
|
||||||
'provider': 'husqvarna',
|
'provider': 'husqvarna',
|
||||||
'refresh_token': '**REDACTED**',
|
'refresh_token': '**REDACTED**',
|
||||||
|
@ -552,11 +552,11 @@
|
|||||||
'area_id': None,
|
'area_id': None,
|
||||||
'capabilities': dict({
|
'capabilities': dict({
|
||||||
'options': list([
|
'options': list([
|
||||||
'main_area',
|
<MowerModes.MAIN_AREA: 'main_area'>,
|
||||||
'demo',
|
<MowerModes.DEMO: 'demo'>,
|
||||||
'secondary_area',
|
<MowerModes.SECONDARY_AREA: 'secondary_area'>,
|
||||||
'home',
|
<MowerModes.HOME: 'home'>,
|
||||||
'unknown',
|
<MowerModes.UNKNOWN: 'unknown'>,
|
||||||
]),
|
]),
|
||||||
}),
|
}),
|
||||||
'config_entry_id': <ANY>,
|
'config_entry_id': <ANY>,
|
||||||
@ -592,11 +592,11 @@
|
|||||||
'device_class': 'enum',
|
'device_class': 'enum',
|
||||||
'friendly_name': 'Test Mower 1 Mode',
|
'friendly_name': 'Test Mower 1 Mode',
|
||||||
'options': list([
|
'options': list([
|
||||||
'main_area',
|
<MowerModes.MAIN_AREA: 'main_area'>,
|
||||||
'demo',
|
<MowerModes.DEMO: 'demo'>,
|
||||||
'secondary_area',
|
<MowerModes.SECONDARY_AREA: 'secondary_area'>,
|
||||||
'home',
|
<MowerModes.HOME: 'home'>,
|
||||||
'unknown',
|
<MowerModes.UNKNOWN: 'unknown'>,
|
||||||
]),
|
]),
|
||||||
}),
|
}),
|
||||||
'context': <ANY>,
|
'context': <ANY>,
|
||||||
@ -856,16 +856,16 @@
|
|||||||
'area_id': None,
|
'area_id': None,
|
||||||
'capabilities': dict({
|
'capabilities': dict({
|
||||||
'options': list([
|
'options': list([
|
||||||
'all_work_areas_completed',
|
<RestrictedReasons.ALL_WORK_AREAS_COMPLETED: 'all_work_areas_completed'>,
|
||||||
'daily_limit',
|
<RestrictedReasons.DAILY_LIMIT: 'daily_limit'>,
|
||||||
'external',
|
<RestrictedReasons.EXTERNAL: 'external'>,
|
||||||
'fota',
|
<RestrictedReasons.FOTA: 'fota'>,
|
||||||
'frost',
|
<RestrictedReasons.FROST: 'frost'>,
|
||||||
'none',
|
<RestrictedReasons.NONE: 'none'>,
|
||||||
'not_applicable',
|
<RestrictedReasons.NOT_APPLICABLE: 'not_applicable'>,
|
||||||
'park_override',
|
<RestrictedReasons.PARK_OVERRIDE: 'park_override'>,
|
||||||
'sensor',
|
<RestrictedReasons.SENSOR: 'sensor'>,
|
||||||
'week_schedule',
|
<RestrictedReasons.WEEK_SCHEDULE: 'week_schedule'>,
|
||||||
]),
|
]),
|
||||||
}),
|
}),
|
||||||
'config_entry_id': <ANY>,
|
'config_entry_id': <ANY>,
|
||||||
@ -901,16 +901,16 @@
|
|||||||
'device_class': 'enum',
|
'device_class': 'enum',
|
||||||
'friendly_name': 'Test Mower 1 Restricted reason',
|
'friendly_name': 'Test Mower 1 Restricted reason',
|
||||||
'options': list([
|
'options': list([
|
||||||
'all_work_areas_completed',
|
<RestrictedReasons.ALL_WORK_AREAS_COMPLETED: 'all_work_areas_completed'>,
|
||||||
'daily_limit',
|
<RestrictedReasons.DAILY_LIMIT: 'daily_limit'>,
|
||||||
'external',
|
<RestrictedReasons.EXTERNAL: 'external'>,
|
||||||
'fota',
|
<RestrictedReasons.FOTA: 'fota'>,
|
||||||
'frost',
|
<RestrictedReasons.FROST: 'frost'>,
|
||||||
'none',
|
<RestrictedReasons.NONE: 'none'>,
|
||||||
'not_applicable',
|
<RestrictedReasons.NOT_APPLICABLE: 'not_applicable'>,
|
||||||
'park_override',
|
<RestrictedReasons.PARK_OVERRIDE: 'park_override'>,
|
||||||
'sensor',
|
<RestrictedReasons.SENSOR: 'sensor'>,
|
||||||
'week_schedule',
|
<RestrictedReasons.WEEK_SCHEDULE: 'week_schedule'>,
|
||||||
]),
|
]),
|
||||||
}),
|
}),
|
||||||
'context': <ANY>,
|
'context': <ANY>,
|
||||||
@ -1658,11 +1658,11 @@
|
|||||||
'area_id': None,
|
'area_id': None,
|
||||||
'capabilities': dict({
|
'capabilities': dict({
|
||||||
'options': list([
|
'options': list([
|
||||||
'main_area',
|
<MowerModes.MAIN_AREA: 'main_area'>,
|
||||||
'demo',
|
<MowerModes.DEMO: 'demo'>,
|
||||||
'secondary_area',
|
<MowerModes.SECONDARY_AREA: 'secondary_area'>,
|
||||||
'home',
|
<MowerModes.HOME: 'home'>,
|
||||||
'unknown',
|
<MowerModes.UNKNOWN: 'unknown'>,
|
||||||
]),
|
]),
|
||||||
}),
|
}),
|
||||||
'config_entry_id': <ANY>,
|
'config_entry_id': <ANY>,
|
||||||
@ -1698,11 +1698,11 @@
|
|||||||
'device_class': 'enum',
|
'device_class': 'enum',
|
||||||
'friendly_name': 'Test Mower 2 Mode',
|
'friendly_name': 'Test Mower 2 Mode',
|
||||||
'options': list([
|
'options': list([
|
||||||
'main_area',
|
<MowerModes.MAIN_AREA: 'main_area'>,
|
||||||
'demo',
|
<MowerModes.DEMO: 'demo'>,
|
||||||
'secondary_area',
|
<MowerModes.SECONDARY_AREA: 'secondary_area'>,
|
||||||
'home',
|
<MowerModes.HOME: 'home'>,
|
||||||
'unknown',
|
<MowerModes.UNKNOWN: 'unknown'>,
|
||||||
]),
|
]),
|
||||||
}),
|
}),
|
||||||
'context': <ANY>,
|
'context': <ANY>,
|
||||||
@ -1767,16 +1767,16 @@
|
|||||||
'area_id': None,
|
'area_id': None,
|
||||||
'capabilities': dict({
|
'capabilities': dict({
|
||||||
'options': list([
|
'options': list([
|
||||||
'all_work_areas_completed',
|
<RestrictedReasons.ALL_WORK_AREAS_COMPLETED: 'all_work_areas_completed'>,
|
||||||
'daily_limit',
|
<RestrictedReasons.DAILY_LIMIT: 'daily_limit'>,
|
||||||
'external',
|
<RestrictedReasons.EXTERNAL: 'external'>,
|
||||||
'fota',
|
<RestrictedReasons.FOTA: 'fota'>,
|
||||||
'frost',
|
<RestrictedReasons.FROST: 'frost'>,
|
||||||
'none',
|
<RestrictedReasons.NONE: 'none'>,
|
||||||
'not_applicable',
|
<RestrictedReasons.NOT_APPLICABLE: 'not_applicable'>,
|
||||||
'park_override',
|
<RestrictedReasons.PARK_OVERRIDE: 'park_override'>,
|
||||||
'sensor',
|
<RestrictedReasons.SENSOR: 'sensor'>,
|
||||||
'week_schedule',
|
<RestrictedReasons.WEEK_SCHEDULE: 'week_schedule'>,
|
||||||
]),
|
]),
|
||||||
}),
|
}),
|
||||||
'config_entry_id': <ANY>,
|
'config_entry_id': <ANY>,
|
||||||
@ -1812,16 +1812,16 @@
|
|||||||
'device_class': 'enum',
|
'device_class': 'enum',
|
||||||
'friendly_name': 'Test Mower 2 Restricted reason',
|
'friendly_name': 'Test Mower 2 Restricted reason',
|
||||||
'options': list([
|
'options': list([
|
||||||
'all_work_areas_completed',
|
<RestrictedReasons.ALL_WORK_AREAS_COMPLETED: 'all_work_areas_completed'>,
|
||||||
'daily_limit',
|
<RestrictedReasons.DAILY_LIMIT: 'daily_limit'>,
|
||||||
'external',
|
<RestrictedReasons.EXTERNAL: 'external'>,
|
||||||
'fota',
|
<RestrictedReasons.FOTA: 'fota'>,
|
||||||
'frost',
|
<RestrictedReasons.FROST: 'frost'>,
|
||||||
'none',
|
<RestrictedReasons.NONE: 'none'>,
|
||||||
'not_applicable',
|
<RestrictedReasons.NOT_APPLICABLE: 'not_applicable'>,
|
||||||
'park_override',
|
<RestrictedReasons.PARK_OVERRIDE: 'park_override'>,
|
||||||
'sensor',
|
<RestrictedReasons.SENSOR: 'sensor'>,
|
||||||
'week_schedule',
|
<RestrictedReasons.WEEK_SCHEDULE: 'week_schedule'>,
|
||||||
]),
|
]),
|
||||||
}),
|
}),
|
||||||
'context': <ANY>,
|
'context': <ANY>,
|
||||||
|
@ -2,12 +2,10 @@
|
|||||||
|
|
||||||
from unittest.mock import AsyncMock, patch
|
from unittest.mock import AsyncMock, patch
|
||||||
|
|
||||||
from aioautomower.model import MowerActivities
|
from aioautomower.model import MowerActivities, MowerAttributes
|
||||||
from aioautomower.utils import mower_list_to_dictionary_dataclass
|
|
||||||
from freezegun.api import FrozenDateTimeFactory
|
from freezegun.api import FrozenDateTimeFactory
|
||||||
from syrupy import SnapshotAssertion
|
from syrupy import SnapshotAssertion
|
||||||
|
|
||||||
from homeassistant.components.husqvarna_automower.const import DOMAIN
|
|
||||||
from homeassistant.components.husqvarna_automower.coordinator import SCAN_INTERVAL
|
from homeassistant.components.husqvarna_automower.coordinator import SCAN_INTERVAL
|
||||||
from homeassistant.const import Platform
|
from homeassistant.const import Platform
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
@ -16,12 +14,7 @@ from homeassistant.helpers import entity_registry as er
|
|||||||
from . import setup_integration
|
from . import setup_integration
|
||||||
from .const import TEST_MOWER_ID
|
from .const import TEST_MOWER_ID
|
||||||
|
|
||||||
from tests.common import (
|
from tests.common import MockConfigEntry, async_fire_time_changed, snapshot_platform
|
||||||
MockConfigEntry,
|
|
||||||
async_fire_time_changed,
|
|
||||||
load_json_value_fixture,
|
|
||||||
snapshot_platform,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def test_binary_sensor_states(
|
async def test_binary_sensor_states(
|
||||||
@ -29,11 +22,9 @@ async def test_binary_sensor_states(
|
|||||||
mock_automower_client: AsyncMock,
|
mock_automower_client: AsyncMock,
|
||||||
mock_config_entry: MockConfigEntry,
|
mock_config_entry: MockConfigEntry,
|
||||||
freezer: FrozenDateTimeFactory,
|
freezer: FrozenDateTimeFactory,
|
||||||
|
values: dict[str, MowerAttributes],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test binary sensor states."""
|
"""Test binary sensor states."""
|
||||||
values = mower_list_to_dictionary_dataclass(
|
|
||||||
load_json_value_fixture("mower.json", DOMAIN)
|
|
||||||
)
|
|
||||||
await setup_integration(hass, mock_config_entry)
|
await setup_integration(hass, mock_config_entry)
|
||||||
state = hass.states.get("binary_sensor.test_mower_1_charging")
|
state = hass.states.get("binary_sensor.test_mower_1_charging")
|
||||||
assert state is not None
|
assert state is not None
|
||||||
|
@ -2,16 +2,14 @@
|
|||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
from unittest.mock import AsyncMock, patch
|
from unittest.mock import AsyncMock, patch
|
||||||
import zoneinfo
|
|
||||||
|
|
||||||
from aioautomower.exceptions import ApiException
|
from aioautomower.exceptions import ApiException
|
||||||
from aioautomower.utils import mower_list_to_dictionary_dataclass
|
from aioautomower.model import MowerAttributes
|
||||||
from freezegun.api import FrozenDateTimeFactory
|
from freezegun.api import FrozenDateTimeFactory
|
||||||
import pytest
|
import pytest
|
||||||
from syrupy import SnapshotAssertion
|
from syrupy import SnapshotAssertion
|
||||||
|
|
||||||
from homeassistant.components.button import DOMAIN as BUTTON_DOMAIN, SERVICE_PRESS
|
from homeassistant.components.button import DOMAIN as BUTTON_DOMAIN, SERVICE_PRESS
|
||||||
from homeassistant.components.husqvarna_automower.const import DOMAIN
|
|
||||||
from homeassistant.components.husqvarna_automower.coordinator import SCAN_INTERVAL
|
from homeassistant.components.husqvarna_automower.coordinator import SCAN_INTERVAL
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
ATTR_ENTITY_ID,
|
ATTR_ENTITY_ID,
|
||||||
@ -26,12 +24,7 @@ from homeassistant.helpers import entity_registry as er
|
|||||||
from . import setup_integration
|
from . import setup_integration
|
||||||
from .const import TEST_MOWER_ID
|
from .const import TEST_MOWER_ID
|
||||||
|
|
||||||
from tests.common import (
|
from tests.common import MockConfigEntry, async_fire_time_changed, snapshot_platform
|
||||||
MockConfigEntry,
|
|
||||||
async_fire_time_changed,
|
|
||||||
load_json_value_fixture,
|
|
||||||
snapshot_platform,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.freeze_time(datetime.datetime(2023, 6, 5, tzinfo=datetime.UTC))
|
@pytest.mark.freeze_time(datetime.datetime(2023, 6, 5, tzinfo=datetime.UTC))
|
||||||
@ -40,6 +33,7 @@ async def test_button_states_and_commands(
|
|||||||
mock_automower_client: AsyncMock,
|
mock_automower_client: AsyncMock,
|
||||||
mock_config_entry: MockConfigEntry,
|
mock_config_entry: MockConfigEntry,
|
||||||
freezer: FrozenDateTimeFactory,
|
freezer: FrozenDateTimeFactory,
|
||||||
|
values: dict[str, MowerAttributes],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test error confirm button command."""
|
"""Test error confirm button command."""
|
||||||
entity_id = "button.test_mower_1_confirm_error"
|
entity_id = "button.test_mower_1_confirm_error"
|
||||||
@ -48,9 +42,6 @@ async def test_button_states_and_commands(
|
|||||||
assert state.name == "Test Mower 1 Confirm error"
|
assert state.name == "Test Mower 1 Confirm error"
|
||||||
assert state.state == STATE_UNAVAILABLE
|
assert state.state == STATE_UNAVAILABLE
|
||||||
|
|
||||||
values = mower_list_to_dictionary_dataclass(
|
|
||||||
load_json_value_fixture("mower.json", DOMAIN)
|
|
||||||
)
|
|
||||||
values[TEST_MOWER_ID].mower.is_error_confirmable = None
|
values[TEST_MOWER_ID].mower.is_error_confirmable = None
|
||||||
mock_automower_client.get_status.return_value = values
|
mock_automower_client.get_status.return_value = values
|
||||||
freezer.tick(SCAN_INTERVAL)
|
freezer.tick(SCAN_INTERVAL)
|
||||||
@ -99,6 +90,7 @@ async def test_sync_clock(
|
|||||||
mock_automower_client: AsyncMock,
|
mock_automower_client: AsyncMock,
|
||||||
mock_config_entry: MockConfigEntry,
|
mock_config_entry: MockConfigEntry,
|
||||||
freezer: FrozenDateTimeFactory,
|
freezer: FrozenDateTimeFactory,
|
||||||
|
values: dict[str, MowerAttributes],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test sync clock button command."""
|
"""Test sync clock button command."""
|
||||||
entity_id = "button.test_mower_1_sync_clock"
|
entity_id = "button.test_mower_1_sync_clock"
|
||||||
@ -106,9 +98,6 @@ async def test_sync_clock(
|
|||||||
state = hass.states.get(entity_id)
|
state = hass.states.get(entity_id)
|
||||||
assert state.name == "Test Mower 1 Sync clock"
|
assert state.name == "Test Mower 1 Sync clock"
|
||||||
|
|
||||||
values = mower_list_to_dictionary_dataclass(
|
|
||||||
load_json_value_fixture("mower.json", DOMAIN)
|
|
||||||
)
|
|
||||||
mock_automower_client.get_status.return_value = values
|
mock_automower_client.get_status.return_value = values
|
||||||
|
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
@ -118,12 +107,7 @@ async def test_sync_clock(
|
|||||||
blocking=True,
|
blocking=True,
|
||||||
)
|
)
|
||||||
mocked_method = mock_automower_client.commands.set_datetime
|
mocked_method = mock_automower_client.commands.set_datetime
|
||||||
# datetime(2024, 2, 29, 11, tzinfo=datetime.UTC) is in local time of the tests
|
mocked_method.assert_called_once_with(TEST_MOWER_ID)
|
||||||
# datetime(2024, 2, 29, 12, tzinfo=zoneinfo.ZoneInfo(key='Europe/Berlin'))
|
|
||||||
mocked_method.assert_called_once_with(
|
|
||||||
TEST_MOWER_ID,
|
|
||||||
datetime.datetime(2024, 2, 29, 12, tzinfo=zoneinfo.ZoneInfo("Europe/Berlin")),
|
|
||||||
)
|
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
state = hass.states.get(entity_id)
|
state = hass.states.get(entity_id)
|
||||||
assert state.state == "2024-02-29T11:00:00+00:00"
|
assert state.state == "2024-02-29T11:00:00+00:00"
|
||||||
|
@ -6,6 +6,7 @@ from http import HTTPStatus
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
from unittest.mock import AsyncMock
|
from unittest.mock import AsyncMock
|
||||||
import urllib
|
import urllib
|
||||||
|
import zoneinfo
|
||||||
|
|
||||||
from aioautomower.utils import mower_list_to_dictionary_dataclass
|
from aioautomower.utils import mower_list_to_dictionary_dataclass
|
||||||
from freezegun.api import FrozenDateTimeFactory
|
from freezegun.api import FrozenDateTimeFactory
|
||||||
@ -93,12 +94,16 @@ async def test_empty_calendar(
|
|||||||
mock_config_entry: MockConfigEntry,
|
mock_config_entry: MockConfigEntry,
|
||||||
freezer: FrozenDateTimeFactory,
|
freezer: FrozenDateTimeFactory,
|
||||||
get_events: GetEventsFn,
|
get_events: GetEventsFn,
|
||||||
|
mower_time_zone: zoneinfo.ZoneInfo,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""State if there is no schedule set."""
|
"""State if there is no schedule set."""
|
||||||
await setup_integration(hass, mock_config_entry)
|
await setup_integration(hass, mock_config_entry)
|
||||||
json_values = load_json_value_fixture("mower.json", DOMAIN)
|
json_values = load_json_value_fixture("mower.json", DOMAIN)
|
||||||
json_values["data"][0]["attributes"]["calendar"]["tasks"] = []
|
json_values["data"][0]["attributes"]["calendar"]["tasks"] = []
|
||||||
values = mower_list_to_dictionary_dataclass(json_values)
|
values = mower_list_to_dictionary_dataclass(
|
||||||
|
json_values,
|
||||||
|
mower_time_zone,
|
||||||
|
)
|
||||||
mock_automower_client.get_status.return_value = values
|
mock_automower_client.get_status.return_value = values
|
||||||
freezer.tick(SCAN_INTERVAL)
|
freezer.tick(SCAN_INTERVAL)
|
||||||
async_fire_time_changed(hass)
|
async_fire_time_changed(hass)
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
from unittest.mock import AsyncMock
|
from unittest.mock import AsyncMock
|
||||||
|
import zoneinfo
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from syrupy.assertion import SnapshotAssertion
|
from syrupy.assertion import SnapshotAssertion
|
||||||
@ -21,7 +22,9 @@ from tests.components.diagnostics import (
|
|||||||
from tests.typing import ClientSessionGenerator
|
from tests.typing import ClientSessionGenerator
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.freeze_time(datetime.datetime(2023, 6, 5, tzinfo=datetime.UTC))
|
@pytest.mark.freeze_time(
|
||||||
|
datetime.datetime(2023, 6, 5, tzinfo=zoneinfo.ZoneInfo("Europe/Berlin"))
|
||||||
|
)
|
||||||
async def test_entry_diagnostics(
|
async def test_entry_diagnostics(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
hass_client: ClientSessionGenerator,
|
hass_client: ClientSessionGenerator,
|
||||||
@ -40,7 +43,9 @@ async def test_entry_diagnostics(
|
|||||||
assert result == snapshot(exclude=props("created_at", "modified_at"))
|
assert result == snapshot(exclude=props("created_at", "modified_at"))
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.freeze_time(datetime.datetime(2023, 6, 5, tzinfo=datetime.UTC))
|
@pytest.mark.freeze_time(
|
||||||
|
datetime.datetime(2023, 6, 5, tzinfo=zoneinfo.ZoneInfo("Europe/Berlin"))
|
||||||
|
)
|
||||||
async def test_device_diagnostics(
|
async def test_device_diagnostics(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
hass_client: ClientSessionGenerator,
|
hass_client: ClientSessionGenerator,
|
||||||
|
@ -10,7 +10,7 @@ from aioautomower.exceptions import (
|
|||||||
AuthException,
|
AuthException,
|
||||||
HusqvarnaWSServerHandshakeError,
|
HusqvarnaWSServerHandshakeError,
|
||||||
)
|
)
|
||||||
from aioautomower.utils import mower_list_to_dictionary_dataclass
|
from aioautomower.model import MowerAttributes
|
||||||
from freezegun.api import FrozenDateTimeFactory
|
from freezegun.api import FrozenDateTimeFactory
|
||||||
import pytest
|
import pytest
|
||||||
from syrupy.assertion import SnapshotAssertion
|
from syrupy.assertion import SnapshotAssertion
|
||||||
@ -23,11 +23,7 @@ from homeassistant.helpers import device_registry as dr, entity_registry as er
|
|||||||
from . import setup_integration
|
from . import setup_integration
|
||||||
from .const import TEST_MOWER_ID
|
from .const import TEST_MOWER_ID
|
||||||
|
|
||||||
from tests.common import (
|
from tests.common import MockConfigEntry, async_fire_time_changed
|
||||||
MockConfigEntry,
|
|
||||||
async_fire_time_changed,
|
|
||||||
load_json_value_fixture,
|
|
||||||
)
|
|
||||||
from tests.test_util.aiohttp import AiohttpClientMocker
|
from tests.test_util.aiohttp import AiohttpClientMocker
|
||||||
|
|
||||||
|
|
||||||
@ -172,12 +168,10 @@ async def test_workarea_deleted(
|
|||||||
mock_automower_client: AsyncMock,
|
mock_automower_client: AsyncMock,
|
||||||
mock_config_entry: MockConfigEntry,
|
mock_config_entry: MockConfigEntry,
|
||||||
entity_registry: er.EntityRegistry,
|
entity_registry: er.EntityRegistry,
|
||||||
|
values: dict[str, MowerAttributes],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test if work area is deleted after removed."""
|
"""Test if work area is deleted after removed."""
|
||||||
|
|
||||||
values = mower_list_to_dictionary_dataclass(
|
|
||||||
load_json_value_fixture("mower.json", DOMAIN)
|
|
||||||
)
|
|
||||||
await setup_integration(hass, mock_config_entry)
|
await setup_integration(hass, mock_config_entry)
|
||||||
current_entries = len(
|
current_entries = len(
|
||||||
er.async_entries_for_config_entry(entity_registry, mock_config_entry.entry_id)
|
er.async_entries_for_config_entry(entity_registry, mock_config_entry.entry_id)
|
||||||
@ -198,6 +192,7 @@ async def test_coordinator_automatic_registry_cleanup(
|
|||||||
mock_config_entry: MockConfigEntry,
|
mock_config_entry: MockConfigEntry,
|
||||||
device_registry: dr.DeviceRegistry,
|
device_registry: dr.DeviceRegistry,
|
||||||
entity_registry: er.EntityRegistry,
|
entity_registry: er.EntityRegistry,
|
||||||
|
values: dict[str, MowerAttributes],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test automatic registry cleanup."""
|
"""Test automatic registry cleanup."""
|
||||||
await setup_integration(hass, mock_config_entry)
|
await setup_integration(hass, mock_config_entry)
|
||||||
@ -211,9 +206,6 @@ async def test_coordinator_automatic_registry_cleanup(
|
|||||||
dr.async_entries_for_config_entry(device_registry, entry.entry_id)
|
dr.async_entries_for_config_entry(device_registry, entry.entry_id)
|
||||||
)
|
)
|
||||||
|
|
||||||
values = mower_list_to_dictionary_dataclass(
|
|
||||||
load_json_value_fixture("mower.json", DOMAIN)
|
|
||||||
)
|
|
||||||
values.pop(TEST_MOWER_ID)
|
values.pop(TEST_MOWER_ID)
|
||||||
mock_automower_client.get_status.return_value = values
|
mock_automower_client.get_status.return_value = values
|
||||||
await hass.config_entries.async_reload(mock_config_entry.entry_id)
|
await hass.config_entries.async_reload(mock_config_entry.entry_id)
|
||||||
|
@ -4,7 +4,7 @@ from datetime import timedelta
|
|||||||
from unittest.mock import AsyncMock
|
from unittest.mock import AsyncMock
|
||||||
|
|
||||||
from aioautomower.exceptions import ApiException
|
from aioautomower.exceptions import ApiException
|
||||||
from aioautomower.utils import mower_list_to_dictionary_dataclass
|
from aioautomower.model import MowerActivities, MowerAttributes, MowerStates
|
||||||
from freezegun.api import FrozenDateTimeFactory
|
from freezegun.api import FrozenDateTimeFactory
|
||||||
import pytest
|
import pytest
|
||||||
from voluptuous.error import MultipleInvalid
|
from voluptuous.error import MultipleInvalid
|
||||||
@ -18,11 +18,7 @@ from homeassistant.exceptions import HomeAssistantError, ServiceValidationError
|
|||||||
from . import setup_integration
|
from . import setup_integration
|
||||||
from .const import TEST_MOWER_ID
|
from .const import TEST_MOWER_ID
|
||||||
|
|
||||||
from tests.common import (
|
from tests.common import MockConfigEntry, async_fire_time_changed
|
||||||
MockConfigEntry,
|
|
||||||
async_fire_time_changed,
|
|
||||||
load_json_value_fixture,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def test_lawn_mower_states(
|
async def test_lawn_mower_states(
|
||||||
@ -30,21 +26,23 @@ async def test_lawn_mower_states(
|
|||||||
mock_automower_client: AsyncMock,
|
mock_automower_client: AsyncMock,
|
||||||
mock_config_entry: MockConfigEntry,
|
mock_config_entry: MockConfigEntry,
|
||||||
freezer: FrozenDateTimeFactory,
|
freezer: FrozenDateTimeFactory,
|
||||||
|
values: dict[str, MowerAttributes],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test lawn_mower state."""
|
"""Test lawn_mower state."""
|
||||||
values = mower_list_to_dictionary_dataclass(
|
|
||||||
load_json_value_fixture("mower.json", DOMAIN)
|
|
||||||
)
|
|
||||||
await setup_integration(hass, mock_config_entry)
|
await setup_integration(hass, mock_config_entry)
|
||||||
state = hass.states.get("lawn_mower.test_mower_1")
|
state = hass.states.get("lawn_mower.test_mower_1")
|
||||||
assert state is not None
|
assert state is not None
|
||||||
assert state.state == LawnMowerActivity.DOCKED
|
assert state.state == LawnMowerActivity.DOCKED
|
||||||
|
|
||||||
for activity, state, expected_state in (
|
for activity, state, expected_state in (
|
||||||
("UNKNOWN", "PAUSED", LawnMowerActivity.PAUSED),
|
(MowerActivities.UNKNOWN, MowerStates.PAUSED, LawnMowerActivity.PAUSED),
|
||||||
("MOWING", "NOT_APPLICABLE", LawnMowerActivity.MOWING),
|
(MowerActivities.MOWING, MowerStates.NOT_APPLICABLE, LawnMowerActivity.MOWING),
|
||||||
("NOT_APPLICABLE", "ERROR", LawnMowerActivity.ERROR),
|
(MowerActivities.NOT_APPLICABLE, MowerStates.ERROR, LawnMowerActivity.ERROR),
|
||||||
("GOING_HOME", "IN_OPERATION", LawnMowerActivity.RETURNING),
|
(
|
||||||
|
MowerActivities.GOING_HOME,
|
||||||
|
MowerStates.IN_OPERATION,
|
||||||
|
LawnMowerActivity.RETURNING,
|
||||||
|
),
|
||||||
):
|
):
|
||||||
values[TEST_MOWER_ID].mower.activity = activity
|
values[TEST_MOWER_ID].mower.activity = activity
|
||||||
values[TEST_MOWER_ID].mower.state = state
|
values[TEST_MOWER_ID].mower.state = state
|
||||||
@ -253,12 +251,10 @@ async def test_lawn_mower_wrong_service_commands(
|
|||||||
mock_automower_client: AsyncMock,
|
mock_automower_client: AsyncMock,
|
||||||
mock_config_entry: MockConfigEntry,
|
mock_config_entry: MockConfigEntry,
|
||||||
freezer: FrozenDateTimeFactory,
|
freezer: FrozenDateTimeFactory,
|
||||||
|
values: dict[str, MowerAttributes],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test lawn_mower commands."""
|
"""Test lawn_mower commands."""
|
||||||
await setup_integration(hass, mock_config_entry)
|
await setup_integration(hass, mock_config_entry)
|
||||||
values = mower_list_to_dictionary_dataclass(
|
|
||||||
load_json_value_fixture("mower.json", DOMAIN)
|
|
||||||
)
|
|
||||||
values[TEST_MOWER_ID].capabilities.work_areas = mower_support_wa
|
values[TEST_MOWER_ID].capabilities.work_areas = mower_support_wa
|
||||||
mock_automower_client.get_status.return_value = values
|
mock_automower_client.get_status.return_value = values
|
||||||
freezer.tick(SCAN_INTERVAL)
|
freezer.tick(SCAN_INTERVAL)
|
||||||
|
@ -4,15 +4,12 @@ from datetime import timedelta
|
|||||||
from unittest.mock import AsyncMock, patch
|
from unittest.mock import AsyncMock, patch
|
||||||
|
|
||||||
from aioautomower.exceptions import ApiException
|
from aioautomower.exceptions import ApiException
|
||||||
from aioautomower.utils import mower_list_to_dictionary_dataclass
|
from aioautomower.model import MowerAttributes
|
||||||
from freezegun.api import FrozenDateTimeFactory
|
from freezegun.api import FrozenDateTimeFactory
|
||||||
import pytest
|
import pytest
|
||||||
from syrupy import SnapshotAssertion
|
from syrupy import SnapshotAssertion
|
||||||
|
|
||||||
from homeassistant.components.husqvarna_automower.const import (
|
from homeassistant.components.husqvarna_automower.const import EXECUTION_TIME_DELAY
|
||||||
DOMAIN,
|
|
||||||
EXECUTION_TIME_DELAY,
|
|
||||||
)
|
|
||||||
from homeassistant.const import Platform
|
from homeassistant.const import Platform
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.exceptions import HomeAssistantError
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
@ -21,12 +18,7 @@ from homeassistant.helpers import entity_registry as er
|
|||||||
from . import setup_integration
|
from . import setup_integration
|
||||||
from .const import TEST_MOWER_ID
|
from .const import TEST_MOWER_ID
|
||||||
|
|
||||||
from tests.common import (
|
from tests.common import MockConfigEntry, async_fire_time_changed, snapshot_platform
|
||||||
MockConfigEntry,
|
|
||||||
async_fire_time_changed,
|
|
||||||
load_json_value_fixture,
|
|
||||||
snapshot_platform,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
|
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
|
||||||
@ -68,13 +60,11 @@ async def test_number_workarea_commands(
|
|||||||
mock_automower_client: AsyncMock,
|
mock_automower_client: AsyncMock,
|
||||||
mock_config_entry: MockConfigEntry,
|
mock_config_entry: MockConfigEntry,
|
||||||
freezer: FrozenDateTimeFactory,
|
freezer: FrozenDateTimeFactory,
|
||||||
|
values: dict[str, MowerAttributes],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test number commands."""
|
"""Test number commands."""
|
||||||
entity_id = "number.test_mower_1_front_lawn_cutting_height"
|
entity_id = "number.test_mower_1_front_lawn_cutting_height"
|
||||||
await setup_integration(hass, mock_config_entry)
|
await setup_integration(hass, mock_config_entry)
|
||||||
values = mower_list_to_dictionary_dataclass(
|
|
||||||
load_json_value_fixture("mower.json", DOMAIN)
|
|
||||||
)
|
|
||||||
values[TEST_MOWER_ID].work_areas[123456].cutting_height = 75
|
values[TEST_MOWER_ID].work_areas[123456].cutting_height = 75
|
||||||
mock_automower_client.get_status.return_value = values
|
mock_automower_client.get_status.return_value = values
|
||||||
mocked_method = AsyncMock()
|
mocked_method = AsyncMock()
|
||||||
|
@ -3,12 +3,10 @@
|
|||||||
from unittest.mock import AsyncMock
|
from unittest.mock import AsyncMock
|
||||||
|
|
||||||
from aioautomower.exceptions import ApiException
|
from aioautomower.exceptions import ApiException
|
||||||
from aioautomower.model import HeadlightModes
|
from aioautomower.model import HeadlightModes, MowerAttributes
|
||||||
from aioautomower.utils import mower_list_to_dictionary_dataclass
|
|
||||||
from freezegun.api import FrozenDateTimeFactory
|
from freezegun.api import FrozenDateTimeFactory
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from homeassistant.components.husqvarna_automower.const import DOMAIN
|
|
||||||
from homeassistant.components.husqvarna_automower.coordinator import SCAN_INTERVAL
|
from homeassistant.components.husqvarna_automower.coordinator import SCAN_INTERVAL
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.exceptions import HomeAssistantError
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
@ -16,11 +14,7 @@ from homeassistant.exceptions import HomeAssistantError
|
|||||||
from . import setup_integration
|
from . import setup_integration
|
||||||
from .const import TEST_MOWER_ID
|
from .const import TEST_MOWER_ID
|
||||||
|
|
||||||
from tests.common import (
|
from tests.common import MockConfigEntry, async_fire_time_changed
|
||||||
MockConfigEntry,
|
|
||||||
async_fire_time_changed,
|
|
||||||
load_json_value_fixture,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def test_select_states(
|
async def test_select_states(
|
||||||
@ -28,11 +22,9 @@ async def test_select_states(
|
|||||||
mock_automower_client: AsyncMock,
|
mock_automower_client: AsyncMock,
|
||||||
mock_config_entry: MockConfigEntry,
|
mock_config_entry: MockConfigEntry,
|
||||||
freezer: FrozenDateTimeFactory,
|
freezer: FrozenDateTimeFactory,
|
||||||
|
values: dict[str, MowerAttributes],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test states of headlight mode select."""
|
"""Test states of headlight mode select."""
|
||||||
values = mower_list_to_dictionary_dataclass(
|
|
||||||
load_json_value_fixture("mower.json", DOMAIN)
|
|
||||||
)
|
|
||||||
await setup_integration(hass, mock_config_entry)
|
await setup_integration(hass, mock_config_entry)
|
||||||
state = hass.states.get("select.test_mower_1_headlight_mode")
|
state = hass.states.get("select.test_mower_1_headlight_mode")
|
||||||
assert state is not None
|
assert state is not None
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
"""Tests for sensor platform."""
|
"""Tests for sensor platform."""
|
||||||
|
|
||||||
|
import datetime
|
||||||
from unittest.mock import AsyncMock, patch
|
from unittest.mock import AsyncMock, patch
|
||||||
|
import zoneinfo
|
||||||
|
|
||||||
from aioautomower.model import MowerModes, MowerStates
|
from aioautomower.model import MowerAttributes, MowerModes, MowerStates
|
||||||
from aioautomower.utils import mower_list_to_dictionary_dataclass
|
|
||||||
from freezegun.api import FrozenDateTimeFactory
|
from freezegun.api import FrozenDateTimeFactory
|
||||||
import pytest
|
import pytest
|
||||||
from syrupy import SnapshotAssertion
|
from syrupy import SnapshotAssertion
|
||||||
|
|
||||||
from homeassistant.components.husqvarna_automower.const import DOMAIN
|
|
||||||
from homeassistant.components.husqvarna_automower.coordinator import SCAN_INTERVAL
|
from homeassistant.components.husqvarna_automower.coordinator import SCAN_INTERVAL
|
||||||
from homeassistant.const import STATE_UNKNOWN, Platform
|
from homeassistant.const import STATE_UNKNOWN, Platform
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
@ -17,12 +17,7 @@ from homeassistant.helpers import entity_registry as er
|
|||||||
from . import setup_integration
|
from . import setup_integration
|
||||||
from .const import TEST_MOWER_ID
|
from .const import TEST_MOWER_ID
|
||||||
|
|
||||||
from tests.common import (
|
from tests.common import MockConfigEntry, async_fire_time_changed, snapshot_platform
|
||||||
MockConfigEntry,
|
|
||||||
async_fire_time_changed,
|
|
||||||
load_json_value_fixture,
|
|
||||||
snapshot_platform,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def test_sensor_unknown_states(
|
async def test_sensor_unknown_states(
|
||||||
@ -30,11 +25,9 @@ async def test_sensor_unknown_states(
|
|||||||
mock_automower_client: AsyncMock,
|
mock_automower_client: AsyncMock,
|
||||||
mock_config_entry: MockConfigEntry,
|
mock_config_entry: MockConfigEntry,
|
||||||
freezer: FrozenDateTimeFactory,
|
freezer: FrozenDateTimeFactory,
|
||||||
|
values: dict[str, MowerAttributes],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test a sensor which returns unknown."""
|
"""Test a sensor which returns unknown."""
|
||||||
values = mower_list_to_dictionary_dataclass(
|
|
||||||
load_json_value_fixture("mower.json", DOMAIN)
|
|
||||||
)
|
|
||||||
await setup_integration(hass, mock_config_entry)
|
await setup_integration(hass, mock_config_entry)
|
||||||
state = hass.states.get("sensor.test_mower_1_mode")
|
state = hass.states.get("sensor.test_mower_1_mode")
|
||||||
assert state is not None
|
assert state is not None
|
||||||
@ -63,11 +56,15 @@ async def test_cutting_blade_usage_time_sensor(
|
|||||||
assert state.state == "0.034"
|
assert state.state == "0.034"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.freeze_time(
|
||||||
|
datetime.datetime(2023, 6, 5, tzinfo=zoneinfo.ZoneInfo("Europe/Berlin"))
|
||||||
|
)
|
||||||
async def test_next_start_sensor(
|
async def test_next_start_sensor(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
mock_automower_client: AsyncMock,
|
mock_automower_client: AsyncMock,
|
||||||
mock_config_entry: MockConfigEntry,
|
mock_config_entry: MockConfigEntry,
|
||||||
freezer: FrozenDateTimeFactory,
|
freezer: FrozenDateTimeFactory,
|
||||||
|
values: dict[str, MowerAttributes],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test if this sensor is only added, if data is available."""
|
"""Test if this sensor is only added, if data is available."""
|
||||||
await setup_integration(hass, mock_config_entry)
|
await setup_integration(hass, mock_config_entry)
|
||||||
@ -75,10 +72,7 @@ async def test_next_start_sensor(
|
|||||||
assert state is not None
|
assert state is not None
|
||||||
assert state.state == "2023-06-05T17:00:00+00:00"
|
assert state.state == "2023-06-05T17:00:00+00:00"
|
||||||
|
|
||||||
values = mower_list_to_dictionary_dataclass(
|
values[TEST_MOWER_ID].planner.next_start_datetime = None
|
||||||
load_json_value_fixture("mower.json", DOMAIN)
|
|
||||||
)
|
|
||||||
values[TEST_MOWER_ID].planner.next_start_datetime_naive = None
|
|
||||||
mock_automower_client.get_status.return_value = values
|
mock_automower_client.get_status.return_value = values
|
||||||
freezer.tick(SCAN_INTERVAL)
|
freezer.tick(SCAN_INTERVAL)
|
||||||
async_fire_time_changed(hass)
|
async_fire_time_changed(hass)
|
||||||
@ -92,6 +86,7 @@ async def test_work_area_sensor(
|
|||||||
mock_automower_client: AsyncMock,
|
mock_automower_client: AsyncMock,
|
||||||
mock_config_entry: MockConfigEntry,
|
mock_config_entry: MockConfigEntry,
|
||||||
freezer: FrozenDateTimeFactory,
|
freezer: FrozenDateTimeFactory,
|
||||||
|
values: dict[str, MowerAttributes],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test the work area sensor."""
|
"""Test the work area sensor."""
|
||||||
await setup_integration(hass, mock_config_entry)
|
await setup_integration(hass, mock_config_entry)
|
||||||
@ -99,9 +94,6 @@ async def test_work_area_sensor(
|
|||||||
assert state is not None
|
assert state is not None
|
||||||
assert state.state == "Front lawn"
|
assert state.state == "Front lawn"
|
||||||
|
|
||||||
values = mower_list_to_dictionary_dataclass(
|
|
||||||
load_json_value_fixture("mower.json", DOMAIN)
|
|
||||||
)
|
|
||||||
values[TEST_MOWER_ID].mower.work_area_id = None
|
values[TEST_MOWER_ID].mower.work_area_id = None
|
||||||
mock_automower_client.get_status.return_value = values
|
mock_automower_client.get_status.return_value = values
|
||||||
freezer.tick(SCAN_INTERVAL)
|
freezer.tick(SCAN_INTERVAL)
|
||||||
@ -137,13 +129,10 @@ async def test_statistics_not_available(
|
|||||||
mock_automower_client: AsyncMock,
|
mock_automower_client: AsyncMock,
|
||||||
mock_config_entry: MockConfigEntry,
|
mock_config_entry: MockConfigEntry,
|
||||||
sensor_to_test: str,
|
sensor_to_test: str,
|
||||||
|
values: dict[str, MowerAttributes],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test if this sensor is only added, if data is available."""
|
"""Test if this sensor is only added, if data is available."""
|
||||||
|
|
||||||
values = mower_list_to_dictionary_dataclass(
|
|
||||||
load_json_value_fixture("mower.json", DOMAIN)
|
|
||||||
)
|
|
||||||
|
|
||||||
delattr(values[TEST_MOWER_ID].statistics, sensor_to_test)
|
delattr(values[TEST_MOWER_ID].statistics, sensor_to_test)
|
||||||
mock_automower_client.get_status.return_value = values
|
mock_automower_client.get_status.return_value = values
|
||||||
await setup_integration(hass, mock_config_entry)
|
await setup_integration(hass, mock_config_entry)
|
||||||
@ -156,11 +145,9 @@ async def test_error_sensor(
|
|||||||
mock_automower_client: AsyncMock,
|
mock_automower_client: AsyncMock,
|
||||||
mock_config_entry: MockConfigEntry,
|
mock_config_entry: MockConfigEntry,
|
||||||
freezer: FrozenDateTimeFactory,
|
freezer: FrozenDateTimeFactory,
|
||||||
|
values: dict[str, MowerAttributes],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test error sensor."""
|
"""Test error sensor."""
|
||||||
values = mower_list_to_dictionary_dataclass(
|
|
||||||
load_json_value_fixture("mower.json", DOMAIN)
|
|
||||||
)
|
|
||||||
await setup_integration(hass, mock_config_entry)
|
await setup_integration(hass, mock_config_entry)
|
||||||
|
|
||||||
for state, error_key, expected_state in (
|
for state, error_key, expected_state in (
|
||||||
|
@ -2,9 +2,10 @@
|
|||||||
|
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from unittest.mock import AsyncMock, patch
|
from unittest.mock import AsyncMock, patch
|
||||||
|
import zoneinfo
|
||||||
|
|
||||||
from aioautomower.exceptions import ApiException
|
from aioautomower.exceptions import ApiException
|
||||||
from aioautomower.model import MowerModes
|
from aioautomower.model import MowerAttributes, MowerModes
|
||||||
from aioautomower.utils import mower_list_to_dictionary_dataclass
|
from aioautomower.utils import mower_list_to_dictionary_dataclass
|
||||||
from freezegun.api import FrozenDateTimeFactory
|
from freezegun.api import FrozenDateTimeFactory
|
||||||
import pytest
|
import pytest
|
||||||
@ -46,11 +47,9 @@ async def test_switch_states(
|
|||||||
mock_automower_client: AsyncMock,
|
mock_automower_client: AsyncMock,
|
||||||
mock_config_entry: MockConfigEntry,
|
mock_config_entry: MockConfigEntry,
|
||||||
freezer: FrozenDateTimeFactory,
|
freezer: FrozenDateTimeFactory,
|
||||||
|
values: dict[str, MowerAttributes],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test switch state."""
|
"""Test switch state."""
|
||||||
values = mower_list_to_dictionary_dataclass(
|
|
||||||
load_json_value_fixture("mower.json", DOMAIN)
|
|
||||||
)
|
|
||||||
await setup_integration(hass, mock_config_entry)
|
await setup_integration(hass, mock_config_entry)
|
||||||
|
|
||||||
for mode, expected_state in (
|
for mode, expected_state in (
|
||||||
@ -122,12 +121,14 @@ async def test_stay_out_zone_switch_commands(
|
|||||||
mock_automower_client: AsyncMock,
|
mock_automower_client: AsyncMock,
|
||||||
mock_config_entry: MockConfigEntry,
|
mock_config_entry: MockConfigEntry,
|
||||||
freezer: FrozenDateTimeFactory,
|
freezer: FrozenDateTimeFactory,
|
||||||
|
mower_time_zone: zoneinfo.ZoneInfo,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test switch commands."""
|
"""Test switch commands."""
|
||||||
entity_id = "switch.test_mower_1_avoid_danger_zone"
|
entity_id = "switch.test_mower_1_avoid_danger_zone"
|
||||||
await setup_integration(hass, mock_config_entry)
|
await setup_integration(hass, mock_config_entry)
|
||||||
values = mower_list_to_dictionary_dataclass(
|
values = mower_list_to_dictionary_dataclass(
|
||||||
load_json_value_fixture("mower.json", DOMAIN)
|
load_json_value_fixture("mower.json", DOMAIN),
|
||||||
|
mower_time_zone,
|
||||||
)
|
)
|
||||||
values[TEST_MOWER_ID].stay_out_zones.zones[TEST_ZONE_ID].enabled = boolean
|
values[TEST_MOWER_ID].stay_out_zones.zones[TEST_ZONE_ID].enabled = boolean
|
||||||
mock_automower_client.get_status.return_value = values
|
mock_automower_client.get_status.return_value = values
|
||||||
@ -177,12 +178,14 @@ async def test_work_area_switch_commands(
|
|||||||
mock_automower_client: AsyncMock,
|
mock_automower_client: AsyncMock,
|
||||||
mock_config_entry: MockConfigEntry,
|
mock_config_entry: MockConfigEntry,
|
||||||
freezer: FrozenDateTimeFactory,
|
freezer: FrozenDateTimeFactory,
|
||||||
|
mower_time_zone: zoneinfo.ZoneInfo,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test switch commands."""
|
"""Test switch commands."""
|
||||||
entity_id = "switch.test_mower_1_my_lawn"
|
entity_id = "switch.test_mower_1_my_lawn"
|
||||||
await setup_integration(hass, mock_config_entry)
|
await setup_integration(hass, mock_config_entry)
|
||||||
values = mower_list_to_dictionary_dataclass(
|
values = mower_list_to_dictionary_dataclass(
|
||||||
load_json_value_fixture("mower.json", DOMAIN)
|
load_json_value_fixture("mower.json", DOMAIN),
|
||||||
|
mower_time_zone,
|
||||||
)
|
)
|
||||||
values[TEST_MOWER_ID].work_areas[TEST_AREA_ID].enabled = boolean
|
values[TEST_MOWER_ID].work_areas[TEST_AREA_ID].enabled = boolean
|
||||||
mock_automower_client.get_status.return_value = values
|
mock_automower_client.get_status.return_value = values
|
||||||
@ -221,12 +224,9 @@ async def test_zones_deleted(
|
|||||||
mock_automower_client: AsyncMock,
|
mock_automower_client: AsyncMock,
|
||||||
mock_config_entry: MockConfigEntry,
|
mock_config_entry: MockConfigEntry,
|
||||||
entity_registry: er.EntityRegistry,
|
entity_registry: er.EntityRegistry,
|
||||||
|
values: dict[str, MowerAttributes],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test if stay-out-zone is deleted after removed."""
|
"""Test if stay-out-zone is deleted after removed."""
|
||||||
|
|
||||||
values = mower_list_to_dictionary_dataclass(
|
|
||||||
load_json_value_fixture("mower.json", DOMAIN)
|
|
||||||
)
|
|
||||||
await setup_integration(hass, mock_config_entry)
|
await setup_integration(hass, mock_config_entry)
|
||||||
current_entries = len(
|
current_entries = len(
|
||||||
er.async_entries_for_config_entry(entity_registry, mock_config_entry.entry_id)
|
er.async_entries_for_config_entry(entity_registry, mock_config_entry.entry_id)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user