Home Connect test improvements (#141135)

* Home Connect test improvements

* Remove `appliance_ha_id` fixture in favour of `appliance` fixture
This commit is contained in:
J. Diego Rodríguez Royo 2025-03-23 11:33:55 +01:00 committed by GitHub
parent 883ce6842d
commit d8a5881eaa
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 386 additions and 339 deletions

View File

@ -473,20 +473,6 @@ def mock_client_with_exception(
return mock return mock
@pytest.fixture(name="appliance_ha_id")
def mock_appliance_ha_id(
appliances: list[HomeAppliance], request: pytest.FixtureRequest
) -> str:
"""Fixture to get the ha_id of an appliance."""
appliance_type = "Washer"
if hasattr(request, "param") and request.param:
appliance_type = request.param
for appliance in appliances:
if appliance.type == appliance_type:
return appliance.ha_id
raise ValueError(f"Appliance {appliance_type} not found")
@pytest.fixture(name="appliances") @pytest.fixture(name="appliances")
def mock_appliances( def mock_appliances(
appliances_data: str, request: pytest.FixtureRequest appliances_data: str, request: pytest.FixtureRequest

View File

@ -1,5 +1,5 @@
# serializer version: 1 # serializer version: 1
# name: test_set_program_and_options[service_call0-set_selected_program] # name: test_set_program_and_options[service_call0-set_selected_program-Washer]
_Call( _Call(
tuple( tuple(
'SIEMENS-HCS03WCH1-7BC6383CF794', 'SIEMENS-HCS03WCH1-7BC6383CF794',
@ -18,7 +18,7 @@
}), }),
) )
# --- # ---
# name: test_set_program_and_options[service_call1-start_program] # name: test_set_program_and_options[service_call1-start_program-Washer]
_Call( _Call(
tuple( tuple(
'SIEMENS-HCS03WCH1-7BC6383CF794', 'SIEMENS-HCS03WCH1-7BC6383CF794',
@ -37,7 +37,7 @@
}), }),
) )
# --- # ---
# name: test_set_program_and_options[service_call2-set_active_program_options] # name: test_set_program_and_options[service_call2-set_active_program_options-Washer]
_Call( _Call(
tuple( tuple(
'SIEMENS-HCS03WCH1-7BC6383CF794', 'SIEMENS-HCS03WCH1-7BC6383CF794',
@ -57,7 +57,7 @@
}), }),
) )
# --- # ---
# name: test_set_program_and_options[service_call3-set_selected_program_options] # name: test_set_program_and_options[service_call3-set_selected_program_options-Washer]
_Call( _Call(
tuple( tuple(
'SIEMENS-HCS03WCH1-7BC6383CF794', 'SIEMENS-HCS03WCH1-7BC6383CF794',

View File

@ -3,7 +3,14 @@
from collections.abc import Awaitable, Callable from collections.abc import Awaitable, Callable
from unittest.mock import AsyncMock, MagicMock from unittest.mock import AsyncMock, MagicMock
from aiohomeconnect.model import ArrayOfEvents, Event, EventKey, EventMessage, EventType from aiohomeconnect.model import (
ArrayOfEvents,
Event,
EventKey,
EventMessage,
EventType,
HomeAppliance,
)
from aiohomeconnect.model.error import HomeConnectApiError from aiohomeconnect.model.error import HomeConnectApiError
import pytest import pytest
@ -52,8 +59,9 @@ async def test_binary_sensors(
assert config_entry.state == ConfigEntryState.LOADED assert config_entry.state == ConfigEntryState.LOADED
@pytest.mark.parametrize("appliance", ["Washer"], indirect=True)
async def test_paired_depaired_devices_flow( async def test_paired_depaired_devices_flow(
appliance_ha_id: str, appliance: HomeAppliance,
hass: HomeAssistant, hass: HomeAssistant,
config_entry: MockConfigEntry, config_entry: MockConfigEntry,
integration_setup: Callable[[MagicMock], Awaitable[bool]], integration_setup: Callable[[MagicMock], Awaitable[bool]],
@ -67,7 +75,7 @@ async def test_paired_depaired_devices_flow(
assert await integration_setup(client) assert await integration_setup(client)
assert config_entry.state == ConfigEntryState.LOADED assert config_entry.state == ConfigEntryState.LOADED
device = device_registry.async_get_device(identifiers={(DOMAIN, appliance_ha_id)}) device = device_registry.async_get_device(identifiers={(DOMAIN, appliance.ha_id)})
assert device assert device
entity_entries = entity_registry.entities.get_entries_for_device_id(device.id) entity_entries = entity_registry.entities.get_entries_for_device_id(device.id)
assert entity_entries assert entity_entries
@ -75,7 +83,7 @@ async def test_paired_depaired_devices_flow(
await client.add_events( await client.add_events(
[ [
EventMessage( EventMessage(
appliance_ha_id, appliance.ha_id,
EventType.DEPAIRED, EventType.DEPAIRED,
data=ArrayOfEvents([]), data=ArrayOfEvents([]),
) )
@ -83,7 +91,7 @@ async def test_paired_depaired_devices_flow(
) )
await hass.async_block_till_done() await hass.async_block_till_done()
device = device_registry.async_get_device(identifiers={(DOMAIN, appliance_ha_id)}) device = device_registry.async_get_device(identifiers={(DOMAIN, appliance.ha_id)})
assert not device assert not device
for entity_entry in entity_entries: for entity_entry in entity_entries:
assert not entity_registry.async_get(entity_entry.entity_id) assert not entity_registry.async_get(entity_entry.entity_id)
@ -92,7 +100,7 @@ async def test_paired_depaired_devices_flow(
await client.add_events( await client.add_events(
[ [
EventMessage( EventMessage(
appliance_ha_id, appliance.ha_id,
EventType.PAIRED, EventType.PAIRED,
data=ArrayOfEvents([]), data=ArrayOfEvents([]),
) )
@ -100,13 +108,14 @@ async def test_paired_depaired_devices_flow(
) )
await hass.async_block_till_done() await hass.async_block_till_done()
assert device_registry.async_get_device(identifiers={(DOMAIN, appliance_ha_id)}) assert device_registry.async_get_device(identifiers={(DOMAIN, appliance.ha_id)})
for entity_entry in entity_entries: for entity_entry in entity_entries:
assert entity_registry.async_get(entity_entry.entity_id) assert entity_registry.async_get(entity_entry.entity_id)
@pytest.mark.parametrize("appliance", ["Washer"], indirect=True)
async def test_connected_devices( async def test_connected_devices(
appliance_ha_id: str, appliance: HomeAppliance,
hass: HomeAssistant, hass: HomeAssistant,
config_entry: MockConfigEntry, config_entry: MockConfigEntry,
integration_setup: Callable[[MagicMock], Awaitable[bool]], integration_setup: Callable[[MagicMock], Awaitable[bool]],
@ -123,7 +132,7 @@ async def test_connected_devices(
get_status_original_mock = client.get_status get_status_original_mock = client.get_status
def get_status_side_effect(ha_id: str): def get_status_side_effect(ha_id: str):
if ha_id == appliance_ha_id: if ha_id == appliance.ha_id:
raise HomeConnectApiError( raise HomeConnectApiError(
"SDK.Error.HomeAppliance.Connection.Initialization.Failed" "SDK.Error.HomeAppliance.Connection.Initialization.Failed"
) )
@ -135,14 +144,14 @@ async def test_connected_devices(
assert config_entry.state == ConfigEntryState.LOADED assert config_entry.state == ConfigEntryState.LOADED
client.get_status = get_status_original_mock client.get_status = get_status_original_mock
device = device_registry.async_get_device(identifiers={(DOMAIN, appliance_ha_id)}) device = device_registry.async_get_device(identifiers={(DOMAIN, appliance.ha_id)})
assert device assert device
entity_entries = entity_registry.entities.get_entries_for_device_id(device.id) entity_entries = entity_registry.entities.get_entries_for_device_id(device.id)
await client.add_events( await client.add_events(
[ [
EventMessage( EventMessage(
appliance_ha_id, appliance.ha_id,
EventType.CONNECTED, EventType.CONNECTED,
data=ArrayOfEvents([]), data=ArrayOfEvents([]),
) )
@ -150,19 +159,20 @@ async def test_connected_devices(
) )
await hass.async_block_till_done() await hass.async_block_till_done()
device = device_registry.async_get_device(identifiers={(DOMAIN, appliance_ha_id)}) device = device_registry.async_get_device(identifiers={(DOMAIN, appliance.ha_id)})
assert device assert device
new_entity_entries = entity_registry.entities.get_entries_for_device_id(device.id) new_entity_entries = entity_registry.entities.get_entries_for_device_id(device.id)
assert len(new_entity_entries) > len(entity_entries) assert len(new_entity_entries) > len(entity_entries)
async def test_binary_sensors_entity_availabilty( @pytest.mark.parametrize("appliance", ["Washer"], indirect=True)
async def test_binary_sensors_entity_availability(
hass: HomeAssistant, hass: HomeAssistant,
config_entry: MockConfigEntry, config_entry: MockConfigEntry,
integration_setup: Callable[[MagicMock], Awaitable[bool]], integration_setup: Callable[[MagicMock], Awaitable[bool]],
setup_credentials: None, setup_credentials: None,
client: MagicMock, client: MagicMock,
appliance_ha_id: str, appliance: HomeAppliance,
) -> None: ) -> None:
"""Test if binary sensor entities availability are based on the appliance connection state.""" """Test if binary sensor entities availability are based on the appliance connection state."""
entity_ids = [ entity_ids = [
@ -181,7 +191,7 @@ async def test_binary_sensors_entity_availabilty(
await client.add_events( await client.add_events(
[ [
EventMessage( EventMessage(
appliance_ha_id, appliance.ha_id,
EventType.DISCONNECTED, EventType.DISCONNECTED,
ArrayOfEvents([]), ArrayOfEvents([]),
) )
@ -195,7 +205,7 @@ async def test_binary_sensors_entity_availabilty(
await client.add_events( await client.add_events(
[ [
EventMessage( EventMessage(
appliance_ha_id, appliance.ha_id,
EventType.CONNECTED, EventType.CONNECTED,
ArrayOfEvents([]), ArrayOfEvents([]),
) )
@ -209,6 +219,7 @@ async def test_binary_sensors_entity_availabilty(
assert state.state != STATE_UNAVAILABLE assert state.state != STATE_UNAVAILABLE
@pytest.mark.parametrize("appliance", ["Washer"], indirect=True)
@pytest.mark.parametrize( @pytest.mark.parametrize(
("value", "expected"), ("value", "expected"),
[ [
@ -219,7 +230,7 @@ async def test_binary_sensors_entity_availabilty(
], ],
) )
async def test_binary_sensors_door_states( async def test_binary_sensors_door_states(
appliance_ha_id: str, appliance: HomeAppliance,
expected: str, expected: str,
value: str, value: str,
hass: HomeAssistant, hass: HomeAssistant,
@ -237,7 +248,7 @@ async def test_binary_sensors_door_states(
await client.add_events( await client.add_events(
[ [
EventMessage( EventMessage(
appliance_ha_id, appliance.ha_id,
EventType.STATUS, EventType.STATUS,
ArrayOfEvents( ArrayOfEvents(
[ [
@ -259,7 +270,7 @@ async def test_binary_sensors_door_states(
@pytest.mark.parametrize( @pytest.mark.parametrize(
("entity_id", "event_key", "event_value_update", "expected", "appliance_ha_id"), ("entity_id", "event_key", "event_value_update", "expected", "appliance"),
[ [
( (
"binary_sensor.washer_remote_control", "binary_sensor.washer_remote_control",
@ -304,13 +315,13 @@ async def test_binary_sensors_door_states(
"FridgeFreezer", "FridgeFreezer",
), ),
], ],
indirect=["appliance_ha_id"], indirect=["appliance"],
) )
async def test_binary_sensors_functionality( async def test_binary_sensors_functionality(
entity_id: str, entity_id: str,
event_key: EventKey, event_key: EventKey,
event_value_update: str, event_value_update: str,
appliance_ha_id: str, appliance: HomeAppliance,
expected: str, expected: str,
hass: HomeAssistant, hass: HomeAssistant,
config_entry: MockConfigEntry, config_entry: MockConfigEntry,
@ -325,7 +336,7 @@ async def test_binary_sensors_functionality(
await client.add_events( await client.add_events(
[ [
EventMessage( EventMessage(
appliance_ha_id, appliance.ha_id,
EventType.STATUS, EventType.STATUS,
ArrayOfEvents( ArrayOfEvents(
[ [
@ -346,13 +357,14 @@ async def test_binary_sensors_functionality(
assert hass.states.is_state(entity_id, expected) assert hass.states.is_state(entity_id, expected)
@pytest.mark.parametrize("appliance", ["Washer"], indirect=True)
async def test_connected_sensor_functionality( async def test_connected_sensor_functionality(
hass: HomeAssistant, hass: HomeAssistant,
config_entry: MockConfigEntry, config_entry: MockConfigEntry,
integration_setup: Callable[[MagicMock], Awaitable[bool]], integration_setup: Callable[[MagicMock], Awaitable[bool]],
setup_credentials: None, setup_credentials: None,
client: MagicMock, client: MagicMock,
appliance_ha_id: str, appliance: HomeAppliance,
) -> None: ) -> None:
"""Test if the connected binary sensor reports the right values.""" """Test if the connected binary sensor reports the right values."""
entity_id = "binary_sensor.washer_connectivity" entity_id = "binary_sensor.washer_connectivity"
@ -365,7 +377,7 @@ async def test_connected_sensor_functionality(
await client.add_events( await client.add_events(
[ [
EventMessage( EventMessage(
appliance_ha_id, appliance.ha_id,
EventType.DISCONNECTED, EventType.DISCONNECTED,
ArrayOfEvents([]), ArrayOfEvents([]),
) )
@ -378,7 +390,7 @@ async def test_connected_sensor_functionality(
await client.add_events( await client.add_events(
[ [
EventMessage( EventMessage(
appliance_ha_id, appliance.ha_id,
EventType.CONNECTED, EventType.CONNECTED,
ArrayOfEvents([]), ArrayOfEvents([]),
) )

View File

@ -4,7 +4,12 @@ from collections.abc import Awaitable, Callable
from typing import Any from typing import Any
from unittest.mock import AsyncMock, MagicMock from unittest.mock import AsyncMock, MagicMock
from aiohomeconnect.model import ArrayOfCommands, CommandKey, EventMessage from aiohomeconnect.model import (
ArrayOfCommands,
CommandKey,
EventMessage,
HomeAppliance,
)
from aiohomeconnect.model.command import Command from aiohomeconnect.model.command import Command
from aiohomeconnect.model.error import HomeConnectApiError from aiohomeconnect.model.error import HomeConnectApiError
from aiohomeconnect.model.event import ArrayOfEvents, EventType from aiohomeconnect.model.event import ArrayOfEvents, EventType
@ -40,8 +45,9 @@ async def test_buttons(
assert config_entry.state == ConfigEntryState.LOADED assert config_entry.state == ConfigEntryState.LOADED
@pytest.mark.parametrize("appliance", ["Washer"], indirect=True)
async def test_paired_depaired_devices_flow( async def test_paired_depaired_devices_flow(
appliance_ha_id: str, appliance: HomeAppliance,
hass: HomeAssistant, hass: HomeAssistant,
config_entry: MockConfigEntry, config_entry: MockConfigEntry,
integration_setup: Callable[[MagicMock], Awaitable[bool]], integration_setup: Callable[[MagicMock], Awaitable[bool]],
@ -55,7 +61,7 @@ async def test_paired_depaired_devices_flow(
assert await integration_setup(client) assert await integration_setup(client)
assert config_entry.state == ConfigEntryState.LOADED assert config_entry.state == ConfigEntryState.LOADED
device = device_registry.async_get_device(identifiers={(DOMAIN, appliance_ha_id)}) device = device_registry.async_get_device(identifiers={(DOMAIN, appliance.ha_id)})
assert device assert device
entity_entries = entity_registry.entities.get_entries_for_device_id(device.id) entity_entries = entity_registry.entities.get_entries_for_device_id(device.id)
assert entity_entries assert entity_entries
@ -63,7 +69,7 @@ async def test_paired_depaired_devices_flow(
await client.add_events( await client.add_events(
[ [
EventMessage( EventMessage(
appliance_ha_id, appliance.ha_id,
EventType.DEPAIRED, EventType.DEPAIRED,
data=ArrayOfEvents([]), data=ArrayOfEvents([]),
) )
@ -71,7 +77,7 @@ async def test_paired_depaired_devices_flow(
) )
await hass.async_block_till_done() await hass.async_block_till_done()
device = device_registry.async_get_device(identifiers={(DOMAIN, appliance_ha_id)}) device = device_registry.async_get_device(identifiers={(DOMAIN, appliance.ha_id)})
assert not device assert not device
for entity_entry in entity_entries: for entity_entry in entity_entries:
assert not entity_registry.async_get(entity_entry.entity_id) assert not entity_registry.async_get(entity_entry.entity_id)
@ -80,7 +86,7 @@ async def test_paired_depaired_devices_flow(
await client.add_events( await client.add_events(
[ [
EventMessage( EventMessage(
appliance_ha_id, appliance.ha_id,
EventType.PAIRED, EventType.PAIRED,
data=ArrayOfEvents([]), data=ArrayOfEvents([]),
) )
@ -88,13 +94,14 @@ async def test_paired_depaired_devices_flow(
) )
await hass.async_block_till_done() await hass.async_block_till_done()
assert device_registry.async_get_device(identifiers={(DOMAIN, appliance_ha_id)}) assert device_registry.async_get_device(identifiers={(DOMAIN, appliance.ha_id)})
for entity_entry in entity_entries: for entity_entry in entity_entries:
assert entity_registry.async_get(entity_entry.entity_id) assert entity_registry.async_get(entity_entry.entity_id)
@pytest.mark.parametrize("appliance", ["Washer"], indirect=True)
async def test_connected_devices( async def test_connected_devices(
appliance_ha_id: str, appliance: HomeAppliance,
hass: HomeAssistant, hass: HomeAssistant,
config_entry: MockConfigEntry, config_entry: MockConfigEntry,
integration_setup: Callable[[MagicMock], Awaitable[bool]], integration_setup: Callable[[MagicMock], Awaitable[bool]],
@ -112,14 +119,14 @@ async def test_connected_devices(
get_available_programs_mock = client.get_available_programs get_available_programs_mock = client.get_available_programs
async def get_available_commands_side_effect(ha_id: str): async def get_available_commands_side_effect(ha_id: str):
if ha_id == appliance_ha_id: if ha_id == appliance.ha_id:
raise HomeConnectApiError( raise HomeConnectApiError(
"SDK.Error.HomeAppliance.Connection.Initialization.Failed" "SDK.Error.HomeAppliance.Connection.Initialization.Failed"
) )
return await get_available_commands_original_mock.side_effect(ha_id) return await get_available_commands_original_mock.side_effect(ha_id)
async def get_available_programs_side_effect(ha_id: str): async def get_available_programs_side_effect(ha_id: str):
if ha_id == appliance_ha_id: if ha_id == appliance.ha_id:
raise HomeConnectApiError( raise HomeConnectApiError(
"SDK.Error.HomeAppliance.Connection.Initialization.Failed" "SDK.Error.HomeAppliance.Connection.Initialization.Failed"
) )
@ -137,14 +144,14 @@ async def test_connected_devices(
client.get_available_commands = get_available_commands_original_mock client.get_available_commands = get_available_commands_original_mock
client.get_available_programs = get_available_programs_mock client.get_available_programs = get_available_programs_mock
device = device_registry.async_get_device(identifiers={(DOMAIN, appliance_ha_id)}) device = device_registry.async_get_device(identifiers={(DOMAIN, appliance.ha_id)})
assert device assert device
entity_entries = entity_registry.entities.get_entries_for_device_id(device.id) entity_entries = entity_registry.entities.get_entries_for_device_id(device.id)
await client.add_events( await client.add_events(
[ [
EventMessage( EventMessage(
appliance_ha_id, appliance.ha_id,
EventType.CONNECTED, EventType.CONNECTED,
data=ArrayOfEvents([]), data=ArrayOfEvents([]),
) )
@ -152,19 +159,20 @@ async def test_connected_devices(
) )
await hass.async_block_till_done() await hass.async_block_till_done()
device = device_registry.async_get_device(identifiers={(DOMAIN, appliance_ha_id)}) device = device_registry.async_get_device(identifiers={(DOMAIN, appliance.ha_id)})
assert device assert device
new_entity_entries = entity_registry.entities.get_entries_for_device_id(device.id) new_entity_entries = entity_registry.entities.get_entries_for_device_id(device.id)
assert len(new_entity_entries) > len(entity_entries) assert len(new_entity_entries) > len(entity_entries)
async def test_button_entity_availabilty( @pytest.mark.parametrize("appliance", ["Washer"], indirect=True)
async def test_button_entity_availability(
hass: HomeAssistant, hass: HomeAssistant,
config_entry: MockConfigEntry, config_entry: MockConfigEntry,
integration_setup: Callable[[MagicMock], Awaitable[bool]], integration_setup: Callable[[MagicMock], Awaitable[bool]],
setup_credentials: None, setup_credentials: None,
client: MagicMock, client: MagicMock,
appliance_ha_id: str, appliance: HomeAppliance,
) -> None: ) -> None:
"""Test if button entities availability are based on the appliance connection state.""" """Test if button entities availability are based on the appliance connection state."""
entity_ids = [ entity_ids = [
@ -183,7 +191,7 @@ async def test_button_entity_availabilty(
await client.add_events( await client.add_events(
[ [
EventMessage( EventMessage(
appliance_ha_id, appliance.ha_id,
EventType.DISCONNECTED, EventType.DISCONNECTED,
ArrayOfEvents([]), ArrayOfEvents([]),
) )
@ -197,7 +205,7 @@ async def test_button_entity_availabilty(
await client.add_events( await client.add_events(
[ [
EventMessage( EventMessage(
appliance_ha_id, appliance.ha_id,
EventType.CONNECTED, EventType.CONNECTED,
ArrayOfEvents([]), ArrayOfEvents([]),
) )
@ -211,6 +219,7 @@ async def test_button_entity_availabilty(
assert state.state != STATE_UNAVAILABLE assert state.state != STATE_UNAVAILABLE
@pytest.mark.parametrize("appliance", ["Washer"], indirect=True)
@pytest.mark.parametrize( @pytest.mark.parametrize(
("entity_id", "method_call", "expected_kwargs"), ("entity_id", "method_call", "expected_kwargs"),
[ [
@ -231,7 +240,7 @@ async def test_button_functionality(
entity_id: str, entity_id: str,
method_call: str, method_call: str,
expected_kwargs: dict[str, Any], expected_kwargs: dict[str, Any],
appliance_ha_id: str, appliance: HomeAppliance,
) -> None: ) -> None:
"""Test if button entities availability are based on the appliance connection state.""" """Test if button entities availability are based on the appliance connection state."""
assert config_entry.state == ConfigEntryState.NOT_LOADED assert config_entry.state == ConfigEntryState.NOT_LOADED
@ -248,7 +257,7 @@ async def test_button_functionality(
{ATTR_ENTITY_ID: entity_id}, {ATTR_ENTITY_ID: entity_id},
blocking=True, blocking=True,
) )
getattr(client, method_call).assert_called_with(appliance_ha_id, **expected_kwargs) getattr(client, method_call).assert_called_with(appliance.ha_id, **expected_kwargs)
async def test_command_button_exception( async def test_command_button_exception(

View File

@ -31,8 +31,17 @@ from homeassistant.components.home_connect.const import (
BSH_POWER_OFF, BSH_POWER_OFF,
DOMAIN, DOMAIN,
) )
from homeassistant.components.homeassistant import (
DOMAIN as HA_DOMAIN,
SERVICE_UPDATE_ENTITY,
)
from homeassistant.config_entries import ConfigEntries, ConfigEntryState from homeassistant.config_entries import ConfigEntries, ConfigEntryState
from homeassistant.const import EVENT_STATE_REPORTED, Platform from homeassistant.const import (
ATTR_ENTITY_ID,
EVENT_STATE_REPORTED,
STATE_UNAVAILABLE,
Platform,
)
from homeassistant.core import ( from homeassistant.core import (
Event as HassEvent, Event as HassEvent,
EventStateReportedData, EventStateReportedData,
@ -98,30 +107,30 @@ async def test_coordinator_failure_refresh_and_stream(
) )
entity_id_1 = "binary_sensor.washer_remote_control" entity_id_1 = "binary_sensor.washer_remote_control"
entity_id_2 = "binary_sensor.washer_remote_start" entity_id_2 = "binary_sensor.washer_remote_start"
await async_setup_component(hass, "homeassistant", {}) await async_setup_component(hass, HA_DOMAIN, {})
await integration_setup(client) await integration_setup(client)
assert config_entry.state == ConfigEntryState.LOADED assert config_entry.state == ConfigEntryState.LOADED
state = hass.states.get(entity_id_1) state = hass.states.get(entity_id_1)
assert state assert state
assert state.state != "unavailable" assert state.state != STATE_UNAVAILABLE
state = hass.states.get(entity_id_2) state = hass.states.get(entity_id_2)
assert state assert state
assert state.state != "unavailable" assert state.state != STATE_UNAVAILABLE
client.get_home_appliances.side_effect = HomeConnectError() client.get_home_appliances.side_effect = HomeConnectError()
# Force a coordinator refresh. # Force a coordinator refresh.
await hass.services.async_call( await hass.services.async_call(
"homeassistant", "update_entity", {"entity_id": entity_id_1}, blocking=True HA_DOMAIN, SERVICE_UPDATE_ENTITY, {ATTR_ENTITY_ID: entity_id_1}, blocking=True
) )
await hass.async_block_till_done() await hass.async_block_till_done()
state = hass.states.get(entity_id_1) state = hass.states.get(entity_id_1)
assert state assert state
assert state.state == "unavailable" assert state.state == STATE_UNAVAILABLE
state = hass.states.get(entity_id_2) state = hass.states.get(entity_id_2)
assert state assert state
assert state.state == "unavailable" assert state.state == STATE_UNAVAILABLE
# Test that the entity becomes available again after a successful update. # Test that the entity becomes available again after a successful update.
@ -137,16 +146,16 @@ async def test_coordinator_failure_refresh_and_stream(
# Force a coordinator refresh. # Force a coordinator refresh.
await hass.services.async_call( await hass.services.async_call(
"homeassistant", "update_entity", {"entity_id": entity_id_1}, blocking=True HA_DOMAIN, SERVICE_UPDATE_ENTITY, {ATTR_ENTITY_ID: entity_id_1}, blocking=True
) )
await hass.async_block_till_done() await hass.async_block_till_done()
state = hass.states.get(entity_id_1) state = hass.states.get(entity_id_1)
assert state assert state
assert state.state != "unavailable" assert state.state != STATE_UNAVAILABLE
state = hass.states.get(entity_id_2) state = hass.states.get(entity_id_2)
assert state assert state
assert state.state != "unavailable" assert state.state != STATE_UNAVAILABLE
# Test that the event stream makes the entity go available too. # Test that the event stream makes the entity go available too.
@ -160,16 +169,16 @@ async def test_coordinator_failure_refresh_and_stream(
# Force a coordinator refresh # Force a coordinator refresh
await hass.services.async_call( await hass.services.async_call(
"homeassistant", "update_entity", {"entity_id": entity_id_1}, blocking=True HA_DOMAIN, SERVICE_UPDATE_ENTITY, {ATTR_ENTITY_ID: entity_id_1}, blocking=True
) )
await hass.async_block_till_done() await hass.async_block_till_done()
state = hass.states.get(entity_id_1) state = hass.states.get(entity_id_1)
assert state assert state
assert state.state == "unavailable" assert state.state == STATE_UNAVAILABLE
state = hass.states.get(entity_id_2) state = hass.states.get(entity_id_2)
assert state assert state
assert state.state == "unavailable" assert state.state == STATE_UNAVAILABLE
# Now make the entity available again. # Now make the entity available again.
client.get_home_appliances.side_effect = None client.get_home_appliances.side_effect = None
@ -199,10 +208,10 @@ async def test_coordinator_failure_refresh_and_stream(
state = hass.states.get(entity_id_1) state = hass.states.get(entity_id_1)
assert state assert state
assert state.state != "unavailable" assert state.state != STATE_UNAVAILABLE
state = hass.states.get(entity_id_2) state = hass.states.get(entity_id_2)
assert state assert state
assert state.state != "unavailable" assert state.state != STATE_UNAVAILABLE
@pytest.mark.parametrize( @pytest.mark.parametrize(
@ -235,9 +244,9 @@ async def test_coordinator_update_failing(
getattr(client, mock_method).assert_called() getattr(client, mock_method).assert_called()
@pytest.mark.parametrize("appliance_ha_id", ["Dishwasher"], indirect=True) @pytest.mark.parametrize("appliance", ["Dishwasher"], indirect=True)
@pytest.mark.parametrize( @pytest.mark.parametrize(
("event_type", "event_key", "event_value", "entity_id"), ("event_type", "event_key", "event_value", ATTR_ENTITY_ID),
[ [
( (
EventType.STATUS, EventType.STATUS,
@ -269,7 +278,7 @@ async def test_event_listener(
integration_setup: Callable[[MagicMock], Awaitable[bool]], integration_setup: Callable[[MagicMock], Awaitable[bool]],
setup_credentials: None, setup_credentials: None,
client: MagicMock, client: MagicMock,
appliance_ha_id: str, appliance: HomeAppliance,
entity_registry: er.EntityRegistry, entity_registry: er.EntityRegistry,
) -> None: ) -> None:
"""Test that the event listener works.""" """Test that the event listener works."""
@ -280,7 +289,7 @@ async def test_event_listener(
state = hass.states.get(entity_id) state = hass.states.get(entity_id)
assert state assert state
event_message = EventMessage( event_message = EventMessage(
appliance_ha_id, appliance.ha_id,
event_type, event_type,
ArrayOfEvents( ArrayOfEvents(
[ [
@ -327,13 +336,14 @@ async def test_event_listener(
listener.assert_called_once_with(new_entity_id) listener.assert_called_once_with(new_entity_id)
@pytest.mark.parametrize("appliance", ["Washer"], indirect=True)
async def tests_receive_setting_and_status_for_first_time_at_events( async def tests_receive_setting_and_status_for_first_time_at_events(
hass: HomeAssistant, hass: HomeAssistant,
config_entry: MockConfigEntry, config_entry: MockConfigEntry,
integration_setup: Callable[[MagicMock], Awaitable[bool]], integration_setup: Callable[[MagicMock], Awaitable[bool]],
setup_credentials: None, setup_credentials: None,
client: MagicMock, client: MagicMock,
appliance_ha_id: str, appliance: HomeAppliance,
) -> None: ) -> None:
"""Test that the event listener is capable of receiving settings and status for the first time.""" """Test that the event listener is capable of receiving settings and status for the first time."""
client.get_setting = AsyncMock(return_value=ArrayOfSettings([])) client.get_setting = AsyncMock(return_value=ArrayOfSettings([]))
@ -346,7 +356,7 @@ async def tests_receive_setting_and_status_for_first_time_at_events(
await client.add_events( await client.add_events(
[ [
EventMessage( EventMessage(
appliance_ha_id, appliance.ha_id,
EventType.NOTIFY, EventType.NOTIFY,
ArrayOfEvents( ArrayOfEvents(
[ [
@ -362,7 +372,7 @@ async def tests_receive_setting_and_status_for_first_time_at_events(
), ),
), ),
EventMessage( EventMessage(
appliance_ha_id, appliance.ha_id,
EventType.STATUS, EventType.STATUS,
ArrayOfEvents( ArrayOfEvents(
[ [
@ -519,7 +529,7 @@ async def test_devices_updated_on_refresh(
return_value=ArrayOfHomeAppliances(appliances[:2]), return_value=ArrayOfHomeAppliances(appliances[:2]),
) )
await async_setup_component(hass, "homeassistant", {}) await async_setup_component(hass, HA_DOMAIN, {})
assert config_entry.state == ConfigEntryState.NOT_LOADED assert config_entry.state == ConfigEntryState.NOT_LOADED
await integration_setup(client) await integration_setup(client)
assert config_entry.state == ConfigEntryState.LOADED assert config_entry.state == ConfigEntryState.LOADED
@ -532,9 +542,9 @@ async def test_devices_updated_on_refresh(
return_value=ArrayOfHomeAppliances(appliances[1:3]), return_value=ArrayOfHomeAppliances(appliances[1:3]),
) )
await hass.services.async_call( await hass.services.async_call(
"homeassistant", HA_DOMAIN,
"update_entity", SERVICE_UPDATE_ENTITY,
{"entity_id": "switch.dishwasher_power"}, {ATTR_ENTITY_ID: "switch.dishwasher_power"},
blocking=True, blocking=True,
) )

View File

@ -11,6 +11,7 @@ from aiohomeconnect.model import (
EventKey, EventKey,
EventMessage, EventMessage,
EventType, EventType,
HomeAppliance,
Option, Option,
OptionKey, OptionKey,
Program, Program,
@ -67,7 +68,7 @@ def platforms() -> list[str]:
) )
@pytest.mark.parametrize( @pytest.mark.parametrize(
( (
"appliance_ha_id", "appliance",
"option_entity_id", "option_entity_id",
"options_state_stage_1", "options_state_stage_1",
"options_availability_stage_2", "options_availability_stage_2",
@ -91,12 +92,12 @@ def platforms() -> list[str]:
(OptionKey.DISHCARE_DISHWASHER_EXTRA_DRY, "switch.dishwasher_extra_dry"), (OptionKey.DISHCARE_DISHWASHER_EXTRA_DRY, "switch.dishwasher_extra_dry"),
) )
], ],
indirect=["appliance_ha_id"], indirect=["appliance"],
) )
async def test_program_options_retrieval( async def test_program_options_retrieval(
array_of_programs_program_arg: str, array_of_programs_program_arg: str,
event_key: EventKey, event_key: EventKey,
appliance_ha_id: str, appliance: HomeAppliance,
option_entity_id: dict[OptionKey, str], option_entity_id: dict[OptionKey, str],
options_state_stage_1: list[tuple[str, bool | None]], options_state_stage_1: list[tuple[str, bool | None]],
options_availability_stage_2: list[bool], options_availability_stage_2: list[bool],
@ -122,7 +123,7 @@ async def test_program_options_retrieval(
] ]
async def get_all_programs_with_options_mock(ha_id: str) -> ArrayOfPrograms: async def get_all_programs_with_options_mock(ha_id: str) -> ArrayOfPrograms:
if ha_id != appliance_ha_id: if ha_id != appliance.ha_id:
return await original_get_all_programs_mock(ha_id) return await original_get_all_programs_mock(ha_id)
array_of_programs: ArrayOfPrograms = await original_get_all_programs_mock(ha_id) array_of_programs: ArrayOfPrograms = await original_get_all_programs_mock(ha_id)
@ -204,7 +205,7 @@ async def test_program_options_retrieval(
await client.add_events( await client.add_events(
[ [
EventMessage( EventMessage(
appliance_ha_id, appliance.ha_id,
EventType.NOTIFY, EventType.NOTIFY,
data=ArrayOfEvents( data=ArrayOfEvents(
[ [
@ -235,6 +236,7 @@ async def test_program_options_retrieval(
assert hass.states.is_state(entity_id, STATE_UNKNOWN) assert hass.states.is_state(entity_id, STATE_UNKNOWN)
@pytest.mark.parametrize("appliance", ["Washer"], indirect=True)
@pytest.mark.parametrize( @pytest.mark.parametrize(
("array_of_programs_program_arg", "event_key"), ("array_of_programs_program_arg", "event_key"),
[ [
@ -251,7 +253,7 @@ async def test_program_options_retrieval(
async def test_no_options_retrieval_on_unknown_program( async def test_no_options_retrieval_on_unknown_program(
array_of_programs_program_arg: str, array_of_programs_program_arg: str,
event_key: EventKey, event_key: EventKey,
appliance_ha_id: str, appliance: HomeAppliance,
hass: HomeAssistant, hass: HomeAssistant,
config_entry: MockConfigEntry, config_entry: MockConfigEntry,
integration_setup: Callable[[MagicMock], Awaitable[bool]], integration_setup: Callable[[MagicMock], Awaitable[bool]],
@ -285,7 +287,7 @@ async def test_no_options_retrieval_on_unknown_program(
await client.add_events( await client.add_events(
[ [
EventMessage( EventMessage(
appliance_ha_id, appliance.ha_id,
EventType.NOTIFY, EventType.NOTIFY,
data=ArrayOfEvents( data=ArrayOfEvents(
[ [
@ -315,7 +317,7 @@ async def test_no_options_retrieval_on_unknown_program(
], ],
) )
@pytest.mark.parametrize( @pytest.mark.parametrize(
("appliance_ha_id", "option_key", "option_entity_id"), ("appliance", "option_key", "option_entity_id"),
[ [
( (
"Dishwasher", "Dishwasher",
@ -323,11 +325,11 @@ async def test_no_options_retrieval_on_unknown_program(
"switch.dishwasher_half_load", "switch.dishwasher_half_load",
) )
], ],
indirect=["appliance_ha_id"], indirect=["appliance"],
) )
async def test_program_options_retrieval_after_appliance_connection( async def test_program_options_retrieval_after_appliance_connection(
event_key: EventKey, event_key: EventKey,
appliance_ha_id: str, appliance: HomeAppliance,
option_key: OptionKey, option_key: OptionKey,
option_entity_id: str, option_entity_id: str,
hass: HomeAssistant, hass: HomeAssistant,
@ -344,7 +346,7 @@ async def test_program_options_retrieval_after_appliance_connection(
[ [
appliance appliance
for appliance in array_of_home_appliances.homeappliances for appliance in array_of_home_appliances.homeappliances
if appliance.ha_id != appliance_ha_id if appliance.ha_id != appliance.ha_id
] ]
) )
@ -367,7 +369,7 @@ async def test_program_options_retrieval_after_appliance_connection(
await client.add_events( await client.add_events(
[ [
EventMessage( EventMessage(
appliance_ha_id, appliance.ha_id,
EventType.CONNECTED, EventType.CONNECTED,
data=ArrayOfEvents( data=ArrayOfEvents(
[ [
@ -405,7 +407,7 @@ async def test_program_options_retrieval_after_appliance_connection(
await client.add_events( await client.add_events(
[ [
EventMessage( EventMessage(
appliance_ha_id, appliance.ha_id,
EventType.NOTIFY, EventType.NOTIFY,
data=ArrayOfEvents( data=ArrayOfEvents(
[ [
@ -450,7 +452,6 @@ async def test_program_options_retrieval_after_appliance_connection(
async def test_option_entity_functionality_exception( async def test_option_entity_functionality_exception(
set_active_program_option_side_effect: HomeConnectError | None, set_active_program_option_side_effect: HomeConnectError | None,
set_selected_program_option_side_effect: HomeConnectError | None, set_selected_program_option_side_effect: HomeConnectError | None,
appliance_ha_id: str,
hass: HomeAssistant, hass: HomeAssistant,
config_entry: MockConfigEntry, config_entry: MockConfigEntry,
integration_setup: Callable[[MagicMock], Awaitable[bool]], integration_setup: Callable[[MagicMock], Awaitable[bool]],

View File

@ -5,7 +5,7 @@ from typing import Any
from unittest.mock import AsyncMock, MagicMock, patch from unittest.mock import AsyncMock, MagicMock, patch
from aiohomeconnect.const import OAUTH2_TOKEN from aiohomeconnect.const import OAUTH2_TOKEN
from aiohomeconnect.model import SettingKey, StatusKey from aiohomeconnect.model import HomeAppliance, SettingKey, StatusKey
from aiohomeconnect.model.error import ( from aiohomeconnect.model.error import (
HomeConnectError, HomeConnectError,
TooManyRequestsError, TooManyRequestsError,
@ -247,6 +247,7 @@ async def test_client_rate_limit_error(
asyncio_sleep_mock.assert_called_once_with(retry_after) asyncio_sleep_mock.assert_called_once_with(retry_after)
@pytest.mark.parametrize("appliance", ["Washer"], indirect=True)
async def test_required_program_or_at_least_an_option( async def test_required_program_or_at_least_an_option(
hass: HomeAssistant, hass: HomeAssistant,
device_registry: dr.DeviceRegistry, device_registry: dr.DeviceRegistry,
@ -254,7 +255,7 @@ async def test_required_program_or_at_least_an_option(
integration_setup: Callable[[MagicMock], Awaitable[bool]], integration_setup: Callable[[MagicMock], Awaitable[bool]],
setup_credentials: None, setup_credentials: None,
client: MagicMock, client: MagicMock,
appliance_ha_id: str, appliance: HomeAppliance,
) -> None: ) -> None:
"Test that the set_program_and_options does raise an exception if no program nor options are set." "Test that the set_program_and_options does raise an exception if no program nor options are set."
@ -264,7 +265,7 @@ async def test_required_program_or_at_least_an_option(
device_entry = device_registry.async_get_or_create( device_entry = device_registry.async_get_or_create(
config_entry_id=config_entry.entry_id, config_entry_id=config_entry.entry_id,
identifiers={(DOMAIN, appliance_ha_id)}, identifiers={(DOMAIN, appliance.ha_id)},
) )
with pytest.raises( with pytest.raises(
@ -281,12 +282,13 @@ async def test_required_program_or_at_least_an_option(
) )
@pytest.mark.parametrize("appliance", ["Washer"], indirect=True)
async def test_entity_migration( async def test_entity_migration(
hass: HomeAssistant, hass: HomeAssistant,
device_registry: dr.DeviceRegistry, device_registry: dr.DeviceRegistry,
entity_registry: er.EntityRegistry, entity_registry: er.EntityRegistry,
config_entry_v1_1: MockConfigEntry, config_entry_v1_1: MockConfigEntry,
appliance_ha_id: str, appliance: HomeAppliance,
platforms: list[Platform], platforms: list[Platform],
) -> None: ) -> None:
"""Test entity migration.""" """Test entity migration."""
@ -295,7 +297,7 @@ async def test_entity_migration(
device_entry = device_registry.async_get_or_create( device_entry = device_registry.async_get_or_create(
config_entry_id=config_entry_v1_1.entry_id, config_entry_id=config_entry_v1_1.entry_id,
identifiers={(DOMAIN, appliance_ha_id)}, identifiers={(DOMAIN, appliance.ha_id)},
) )
test_entities = [ test_entities = [
@ -335,7 +337,7 @@ async def test_entity_migration(
entity_registry.async_get_or_create( entity_registry.async_get_or_create(
domain, domain,
DOMAIN, DOMAIN,
f"{appliance_ha_id}-{old_unique_id_suffix}", f"{appliance.ha_id}-{old_unique_id_suffix}",
device_id=device_entry.id, device_id=device_entry.id,
config_entry=config_entry_v1_1, config_entry=config_entry_v1_1,
) )
@ -346,7 +348,7 @@ async def test_entity_migration(
for domain, _, expected_unique_id_suffix in test_entities: for domain, _, expected_unique_id_suffix in test_entities:
assert entity_registry.async_get_entity_id( assert entity_registry.async_get_entity_id(
domain, DOMAIN, f"{appliance_ha_id}-{expected_unique_id_suffix}" domain, DOMAIN, f"{appliance.ha_id}-{expected_unique_id_suffix}"
) )
assert config_entry_v1_1.minor_version == 2 assert config_entry_v1_1.minor_version == 2

View File

@ -12,6 +12,7 @@ from aiohomeconnect.model import (
EventMessage, EventMessage,
EventType, EventType,
GetSetting, GetSetting,
HomeAppliance,
SettingKey, SettingKey,
) )
from aiohomeconnect.model.error import HomeConnectApiError, HomeConnectError from aiohomeconnect.model.error import HomeConnectApiError, HomeConnectError
@ -21,9 +22,15 @@ from homeassistant.components.home_connect.const import (
BSH_AMBIENT_LIGHT_COLOR_CUSTOM_COLOR, BSH_AMBIENT_LIGHT_COLOR_CUSTOM_COLOR,
DOMAIN, DOMAIN,
) )
from homeassistant.components.light import DOMAIN as LIGHT_DOMAIN from homeassistant.components.light import (
ATTR_BRIGHTNESS,
ATTR_HS_COLOR,
ATTR_RGB_COLOR,
DOMAIN as LIGHT_DOMAIN,
)
from homeassistant.config_entries import ConfigEntryState from homeassistant.config_entries import ConfigEntryState
from homeassistant.const import ( from homeassistant.const import (
ATTR_ENTITY_ID,
SERVICE_TURN_OFF, SERVICE_TURN_OFF,
SERVICE_TURN_ON, SERVICE_TURN_ON,
STATE_OFF, STATE_OFF,
@ -58,9 +65,9 @@ async def test_light(
assert config_entry.state == ConfigEntryState.LOADED assert config_entry.state == ConfigEntryState.LOADED
@pytest.mark.parametrize("appliance_ha_id", ["Hood"], indirect=True) @pytest.mark.parametrize("appliance", ["Hood"], indirect=True)
async def test_paired_depaired_devices_flow( async def test_paired_depaired_devices_flow(
appliance_ha_id: str, appliance: HomeAppliance,
hass: HomeAssistant, hass: HomeAssistant,
config_entry: MockConfigEntry, config_entry: MockConfigEntry,
integration_setup: Callable[[MagicMock], Awaitable[bool]], integration_setup: Callable[[MagicMock], Awaitable[bool]],
@ -74,7 +81,7 @@ async def test_paired_depaired_devices_flow(
assert await integration_setup(client) assert await integration_setup(client)
assert config_entry.state == ConfigEntryState.LOADED assert config_entry.state == ConfigEntryState.LOADED
device = device_registry.async_get_device(identifiers={(DOMAIN, appliance_ha_id)}) device = device_registry.async_get_device(identifiers={(DOMAIN, appliance.ha_id)})
assert device assert device
entity_entries = entity_registry.entities.get_entries_for_device_id(device.id) entity_entries = entity_registry.entities.get_entries_for_device_id(device.id)
assert entity_entries assert entity_entries
@ -82,7 +89,7 @@ async def test_paired_depaired_devices_flow(
await client.add_events( await client.add_events(
[ [
EventMessage( EventMessage(
appliance_ha_id, appliance.ha_id,
EventType.DEPAIRED, EventType.DEPAIRED,
data=ArrayOfEvents([]), data=ArrayOfEvents([]),
) )
@ -90,7 +97,7 @@ async def test_paired_depaired_devices_flow(
) )
await hass.async_block_till_done() await hass.async_block_till_done()
device = device_registry.async_get_device(identifiers={(DOMAIN, appliance_ha_id)}) device = device_registry.async_get_device(identifiers={(DOMAIN, appliance.ha_id)})
assert not device assert not device
for entity_entry in entity_entries: for entity_entry in entity_entries:
assert not entity_registry.async_get(entity_entry.entity_id) assert not entity_registry.async_get(entity_entry.entity_id)
@ -99,7 +106,7 @@ async def test_paired_depaired_devices_flow(
await client.add_events( await client.add_events(
[ [
EventMessage( EventMessage(
appliance_ha_id, appliance.ha_id,
EventType.PAIRED, EventType.PAIRED,
data=ArrayOfEvents([]), data=ArrayOfEvents([]),
) )
@ -107,14 +114,14 @@ async def test_paired_depaired_devices_flow(
) )
await hass.async_block_till_done() await hass.async_block_till_done()
assert device_registry.async_get_device(identifiers={(DOMAIN, appliance_ha_id)}) assert device_registry.async_get_device(identifiers={(DOMAIN, appliance.ha_id)})
for entity_entry in entity_entries: for entity_entry in entity_entries:
assert entity_registry.async_get(entity_entry.entity_id) assert entity_registry.async_get(entity_entry.entity_id)
@pytest.mark.parametrize("appliance_ha_id", ["Hood"], indirect=True) @pytest.mark.parametrize("appliance", ["Hood"], indirect=True)
async def test_connected_devices( async def test_connected_devices(
appliance_ha_id: str, appliance: HomeAppliance,
hass: HomeAssistant, hass: HomeAssistant,
config_entry: MockConfigEntry, config_entry: MockConfigEntry,
integration_setup: Callable[[MagicMock], Awaitable[bool]], integration_setup: Callable[[MagicMock], Awaitable[bool]],
@ -132,14 +139,14 @@ async def test_connected_devices(
get_available_programs_mock = client.get_available_programs get_available_programs_mock = client.get_available_programs
async def get_settings_side_effect(ha_id: str): async def get_settings_side_effect(ha_id: str):
if ha_id == appliance_ha_id: if ha_id == appliance.ha_id:
raise HomeConnectApiError( raise HomeConnectApiError(
"SDK.Error.HomeAppliance.Connection.Initialization.Failed" "SDK.Error.HomeAppliance.Connection.Initialization.Failed"
) )
return await get_settings_original_mock.side_effect(ha_id) return await get_settings_original_mock.side_effect(ha_id)
async def get_available_programs_side_effect(ha_id: str): async def get_available_programs_side_effect(ha_id: str):
if ha_id == appliance_ha_id: if ha_id == appliance.ha_id:
raise HomeConnectApiError( raise HomeConnectApiError(
"SDK.Error.HomeAppliance.Connection.Initialization.Failed" "SDK.Error.HomeAppliance.Connection.Initialization.Failed"
) )
@ -155,14 +162,14 @@ async def test_connected_devices(
client.get_settings = get_settings_original_mock client.get_settings = get_settings_original_mock
client.get_available_programs = get_available_programs_mock client.get_available_programs = get_available_programs_mock
device = device_registry.async_get_device(identifiers={(DOMAIN, appliance_ha_id)}) device = device_registry.async_get_device(identifiers={(DOMAIN, appliance.ha_id)})
assert device assert device
entity_entries = entity_registry.entities.get_entries_for_device_id(device.id) entity_entries = entity_registry.entities.get_entries_for_device_id(device.id)
await client.add_events( await client.add_events(
[ [
EventMessage( EventMessage(
appliance_ha_id, appliance.ha_id,
EventType.CONNECTED, EventType.CONNECTED,
data=ArrayOfEvents([]), data=ArrayOfEvents([]),
) )
@ -170,20 +177,20 @@ async def test_connected_devices(
) )
await hass.async_block_till_done() await hass.async_block_till_done()
device = device_registry.async_get_device(identifiers={(DOMAIN, appliance_ha_id)}) device = device_registry.async_get_device(identifiers={(DOMAIN, appliance.ha_id)})
assert device assert device
new_entity_entries = entity_registry.entities.get_entries_for_device_id(device.id) new_entity_entries = entity_registry.entities.get_entries_for_device_id(device.id)
assert len(new_entity_entries) > len(entity_entries) assert len(new_entity_entries) > len(entity_entries)
@pytest.mark.parametrize("appliance_ha_id", ["Hood"], indirect=True) @pytest.mark.parametrize("appliance", ["Hood"], indirect=True)
async def test_light_availabilty( async def test_light_availability(
hass: HomeAssistant, hass: HomeAssistant,
config_entry: MockConfigEntry, config_entry: MockConfigEntry,
integration_setup: Callable[[MagicMock], Awaitable[bool]], integration_setup: Callable[[MagicMock], Awaitable[bool]],
setup_credentials: None, setup_credentials: None,
client: MagicMock, client: MagicMock,
appliance_ha_id: str, appliance: HomeAppliance,
) -> None: ) -> None:
"""Test if light entities availability are based on the appliance connection state.""" """Test if light entities availability are based on the appliance connection state."""
entity_ids = [ entity_ids = [
@ -201,7 +208,7 @@ async def test_light_availabilty(
await client.add_events( await client.add_events(
[ [
EventMessage( EventMessage(
appliance_ha_id, appliance.ha_id,
EventType.DISCONNECTED, EventType.DISCONNECTED,
ArrayOfEvents([]), ArrayOfEvents([]),
) )
@ -215,7 +222,7 @@ async def test_light_availabilty(
await client.add_events( await client.add_events(
[ [
EventMessage( EventMessage(
appliance_ha_id, appliance.ha_id,
EventType.CONNECTED, EventType.CONNECTED,
ArrayOfEvents([]), ArrayOfEvents([]),
) )
@ -236,7 +243,7 @@ async def test_light_availabilty(
"service", "service",
"exprected_attributes", "exprected_attributes",
"state", "state",
"appliance_ha_id", "appliance",
), ),
[ [
( (
@ -256,7 +263,7 @@ async def test_light_availabilty(
SettingKey.COOKING_COMMON_LIGHTING_BRIGHTNESS: 80, SettingKey.COOKING_COMMON_LIGHTING_BRIGHTNESS: 80,
}, },
SERVICE_TURN_ON, SERVICE_TURN_ON,
{"brightness": 199}, {ATTR_BRIGHTNESS: 199},
STATE_ON, STATE_ON,
"Hood", "Hood",
), ),
@ -277,7 +284,7 @@ async def test_light_availabilty(
SettingKey.BSH_COMMON_AMBIENT_LIGHT_BRIGHTNESS: 80, SettingKey.BSH_COMMON_AMBIENT_LIGHT_BRIGHTNESS: 80,
}, },
SERVICE_TURN_ON, SERVICE_TURN_ON,
{"brightness": 199}, {ATTR_BRIGHTNESS: 199},
STATE_ON, STATE_ON,
"Hood", "Hood",
), ),
@ -310,7 +317,7 @@ async def test_light_availabilty(
}, },
SERVICE_TURN_ON, SERVICE_TURN_ON,
{ {
"rgb_color": (255, 255, 0), ATTR_RGB_COLOR: (255, 255, 0),
}, },
STATE_ON, STATE_ON,
"Hood", "Hood",
@ -324,8 +331,8 @@ async def test_light_availabilty(
}, },
SERVICE_TURN_ON, SERVICE_TURN_ON,
{ {
"hs_color": (255.484, 15.196), ATTR_HS_COLOR: (255.484, 15.196),
"brightness": 199, ATTR_BRIGHTNESS: 199,
}, },
STATE_ON, STATE_ON,
"Hood", "Hood",
@ -341,7 +348,7 @@ async def test_light_availabilty(
"FridgeFreezer", "FridgeFreezer",
), ),
], ],
indirect=["appliance_ha_id"], indirect=["appliance"],
) )
async def test_light_functionality( async def test_light_functionality(
entity_id: str, entity_id: str,
@ -349,7 +356,7 @@ async def test_light_functionality(
service: str, service: str,
exprected_attributes: dict[str, Any], exprected_attributes: dict[str, Any],
state: str, state: str,
appliance_ha_id: str, appliance: HomeAppliance,
hass: HomeAssistant, hass: HomeAssistant,
config_entry: MockConfigEntry, config_entry: MockConfigEntry,
integration_setup: Callable[[MagicMock], Awaitable[bool]], integration_setup: Callable[[MagicMock], Awaitable[bool]],
@ -362,7 +369,7 @@ async def test_light_functionality(
assert config_entry.state == ConfigEntryState.LOADED assert config_entry.state == ConfigEntryState.LOADED
service_data = exprected_attributes.copy() service_data = exprected_attributes.copy()
service_data["entity_id"] = entity_id service_data[ATTR_ENTITY_ID] = entity_id
await hass.services.async_call( await hass.services.async_call(
LIGHT_DOMAIN, LIGHT_DOMAIN,
service, service,
@ -371,7 +378,7 @@ async def test_light_functionality(
await hass.async_block_till_done() await hass.async_block_till_done()
client.set_setting.assert_has_calls( client.set_setting.assert_has_calls(
[ [
call(appliance_ha_id, setting_key=setting_key, value=value) call(appliance.ha_id, setting_key=setting_key, value=value)
for setting_key, value in set_settings_args.items() for setting_key, value in set_settings_args.items()
] ]
) )
@ -386,7 +393,7 @@ async def test_light_functionality(
( (
"entity_id", "entity_id",
"events", "events",
"appliance_ha_id", "appliance",
), ),
[ [
( (
@ -397,12 +404,12 @@ async def test_light_functionality(
"Hood", "Hood",
), ),
], ],
indirect=["appliance_ha_id"], indirect=["appliance"],
) )
async def test_light_color_different_than_custom( async def test_light_color_different_than_custom(
entity_id: str, entity_id: str,
events: dict[EventKey, Any], events: dict[EventKey, Any],
appliance_ha_id: str, appliance: HomeAppliance,
hass: HomeAssistant, hass: HomeAssistant,
config_entry: MockConfigEntry, config_entry: MockConfigEntry,
integration_setup: Callable[[MagicMock], Awaitable[bool]], integration_setup: Callable[[MagicMock], Awaitable[bool]],
@ -417,21 +424,21 @@ async def test_light_color_different_than_custom(
LIGHT_DOMAIN, LIGHT_DOMAIN,
SERVICE_TURN_ON, SERVICE_TURN_ON,
{ {
"rgb_color": (255, 255, 0), ATTR_RGB_COLOR: (255, 255, 0),
"entity_id": entity_id, ATTR_ENTITY_ID: entity_id,
}, },
) )
await hass.async_block_till_done() await hass.async_block_till_done()
entity_state = hass.states.get(entity_id) entity_state = hass.states.get(entity_id)
assert entity_state is not None assert entity_state is not None
assert entity_state.state == STATE_ON assert entity_state.state == STATE_ON
assert entity_state.attributes["rgb_color"] is not None assert entity_state.attributes[ATTR_RGB_COLOR] is not None
assert entity_state.attributes["hs_color"] is not None assert entity_state.attributes[ATTR_HS_COLOR] is not None
await client.add_events( await client.add_events(
[ [
EventMessage( EventMessage(
appliance_ha_id, appliance.ha_id,
EventType.NOTIFY, EventType.NOTIFY,
ArrayOfEvents( ArrayOfEvents(
[ [
@ -454,8 +461,8 @@ async def test_light_color_different_than_custom(
entity_state = hass.states.get(entity_id) entity_state = hass.states.get(entity_id)
assert entity_state is not None assert entity_state is not None
assert entity_state.state == STATE_ON assert entity_state.state == STATE_ON
assert entity_state.attributes["rgb_color"] is None assert entity_state.attributes[ATTR_RGB_COLOR] is None
assert entity_state.attributes["hs_color"] is None assert entity_state.attributes[ATTR_HS_COLOR] is None
@pytest.mark.parametrize( @pytest.mark.parametrize(
@ -485,7 +492,7 @@ async def test_light_color_different_than_custom(
SettingKey.COOKING_COMMON_LIGHTING_BRIGHTNESS: 70, SettingKey.COOKING_COMMON_LIGHTING_BRIGHTNESS: 70,
}, },
SERVICE_TURN_ON, SERVICE_TURN_ON,
{"brightness": 200}, {ATTR_BRIGHTNESS: 200},
[HomeConnectError, HomeConnectError], [HomeConnectError, HomeConnectError],
r"Error.*turn.*on.*", r"Error.*turn.*on.*",
), ),
@ -517,7 +524,7 @@ async def test_light_color_different_than_custom(
SettingKey.BSH_COMMON_AMBIENT_LIGHT_BRIGHTNESS: 70, SettingKey.BSH_COMMON_AMBIENT_LIGHT_BRIGHTNESS: 70,
}, },
SERVICE_TURN_ON, SERVICE_TURN_ON,
{"brightness": 200}, {ATTR_BRIGHTNESS: 200},
[HomeConnectError, None, HomeConnectError], [HomeConnectError, None, HomeConnectError],
r"Error.*set.*brightness.*", r"Error.*set.*brightness.*",
), ),
@ -530,7 +537,7 @@ async def test_light_color_different_than_custom(
SettingKey.BSH_COMMON_AMBIENT_LIGHT_CUSTOM_COLOR: "#ffff00", SettingKey.BSH_COMMON_AMBIENT_LIGHT_CUSTOM_COLOR: "#ffff00",
}, },
SERVICE_TURN_ON, SERVICE_TURN_ON,
{"rgb_color": (255, 255, 0)}, {ATTR_RGB_COLOR: (255, 255, 0)},
[HomeConnectError, None, HomeConnectError], [HomeConnectError, None, HomeConnectError],
r"Error.*select.*custom color.*", r"Error.*select.*custom color.*",
), ),
@ -543,7 +550,7 @@ async def test_light_color_different_than_custom(
SettingKey.BSH_COMMON_AMBIENT_LIGHT_CUSTOM_COLOR: "#ffff00", SettingKey.BSH_COMMON_AMBIENT_LIGHT_CUSTOM_COLOR: "#ffff00",
}, },
SERVICE_TURN_ON, SERVICE_TURN_ON,
{"rgb_color": (255, 255, 0)}, {ATTR_RGB_COLOR: (255, 255, 0)},
[HomeConnectError, None, None, HomeConnectError], [HomeConnectError, None, None, HomeConnectError],
r"Error.*set.*color.*", r"Error.*set.*color.*",
), ),
@ -556,8 +563,8 @@ async def test_light_color_different_than_custom(
}, },
SERVICE_TURN_ON, SERVICE_TURN_ON,
{ {
"hs_color": (255.484, 15.196), ATTR_HS_COLOR: (255.484, 15.196),
"brightness": 199, ATTR_BRIGHTNESS: 199,
}, },
[HomeConnectError, None, None, HomeConnectError], [HomeConnectError, None, None, HomeConnectError],
r"Error.*set.*color.*", r"Error.*set.*color.*",
@ -600,7 +607,7 @@ async def test_light_exception_handling(
with pytest.raises(HomeConnectError): with pytest.raises(HomeConnectError):
await client_with_exception.set_setting() await client_with_exception.set_setting()
service_data["entity_id"] = entity_id service_data[ATTR_ENTITY_ID] = entity_id
with pytest.raises(HomeAssistantError, match=exception_match): with pytest.raises(HomeAssistantError, match=exception_match):
await hass.services.async_call( await hass.services.async_call(
LIGHT_DOMAIN, service, service_data, blocking=True LIGHT_DOMAIN, service, service_data, blocking=True

View File

@ -12,6 +12,7 @@ from aiohomeconnect.model import (
EventMessage, EventMessage,
EventType, EventType,
GetSetting, GetSetting,
HomeAppliance,
OptionKey, OptionKey,
ProgramDefinition, ProgramDefinition,
ProgramKey, ProgramKey,
@ -69,8 +70,9 @@ async def test_number(
assert config_entry.state is ConfigEntryState.LOADED assert config_entry.state is ConfigEntryState.LOADED
@pytest.mark.parametrize("appliance", ["Washer"], indirect=True)
async def test_paired_depaired_devices_flow( async def test_paired_depaired_devices_flow(
appliance_ha_id: str, appliance: HomeAppliance,
hass: HomeAssistant, hass: HomeAssistant,
config_entry: MockConfigEntry, config_entry: MockConfigEntry,
integration_setup: Callable[[MagicMock], Awaitable[bool]], integration_setup: Callable[[MagicMock], Awaitable[bool]],
@ -95,7 +97,7 @@ async def test_paired_depaired_devices_flow(
assert await integration_setup(client) assert await integration_setup(client)
assert config_entry.state == ConfigEntryState.LOADED assert config_entry.state == ConfigEntryState.LOADED
device = device_registry.async_get_device(identifiers={(DOMAIN, appliance_ha_id)}) device = device_registry.async_get_device(identifiers={(DOMAIN, appliance.ha_id)})
assert device assert device
entity_entries = entity_registry.entities.get_entries_for_device_id(device.id) entity_entries = entity_registry.entities.get_entries_for_device_id(device.id)
assert entity_entries assert entity_entries
@ -103,7 +105,7 @@ async def test_paired_depaired_devices_flow(
await client.add_events( await client.add_events(
[ [
EventMessage( EventMessage(
appliance_ha_id, appliance.ha_id,
EventType.DEPAIRED, EventType.DEPAIRED,
data=ArrayOfEvents([]), data=ArrayOfEvents([]),
) )
@ -111,7 +113,7 @@ async def test_paired_depaired_devices_flow(
) )
await hass.async_block_till_done() await hass.async_block_till_done()
device = device_registry.async_get_device(identifiers={(DOMAIN, appliance_ha_id)}) device = device_registry.async_get_device(identifiers={(DOMAIN, appliance.ha_id)})
assert not device assert not device
for entity_entry in entity_entries: for entity_entry in entity_entries:
assert not entity_registry.async_get(entity_entry.entity_id) assert not entity_registry.async_get(entity_entry.entity_id)
@ -120,7 +122,7 @@ async def test_paired_depaired_devices_flow(
await client.add_events( await client.add_events(
[ [
EventMessage( EventMessage(
appliance_ha_id, appliance.ha_id,
EventType.PAIRED, EventType.PAIRED,
data=ArrayOfEvents([]), data=ArrayOfEvents([]),
) )
@ -128,14 +130,14 @@ async def test_paired_depaired_devices_flow(
) )
await hass.async_block_till_done() await hass.async_block_till_done()
assert device_registry.async_get_device(identifiers={(DOMAIN, appliance_ha_id)}) assert device_registry.async_get_device(identifiers={(DOMAIN, appliance.ha_id)})
for entity_entry in entity_entries: for entity_entry in entity_entries:
assert entity_registry.async_get(entity_entry.entity_id) assert entity_registry.async_get(entity_entry.entity_id)
@pytest.mark.parametrize("appliance_ha_id", ["FridgeFreezer"], indirect=True) @pytest.mark.parametrize("appliance", ["FridgeFreezer"], indirect=True)
async def test_connected_devices( async def test_connected_devices(
appliance_ha_id: str, appliance: HomeAppliance,
hass: HomeAssistant, hass: HomeAssistant,
config_entry: MockConfigEntry, config_entry: MockConfigEntry,
integration_setup: Callable[[MagicMock], Awaitable[bool]], integration_setup: Callable[[MagicMock], Awaitable[bool]],
@ -152,7 +154,7 @@ async def test_connected_devices(
get_settings_original_mock = client.get_settings get_settings_original_mock = client.get_settings
def get_settings_side_effect(ha_id: str): def get_settings_side_effect(ha_id: str):
if ha_id == appliance_ha_id: if ha_id == appliance.ha_id:
raise HomeConnectApiError( raise HomeConnectApiError(
"SDK.Error.HomeAppliance.Connection.Initialization.Failed" "SDK.Error.HomeAppliance.Connection.Initialization.Failed"
) )
@ -164,14 +166,14 @@ async def test_connected_devices(
assert config_entry.state == ConfigEntryState.LOADED assert config_entry.state == ConfigEntryState.LOADED
client.get_settings = get_settings_original_mock client.get_settings = get_settings_original_mock
device = device_registry.async_get_device(identifiers={(DOMAIN, appliance_ha_id)}) device = device_registry.async_get_device(identifiers={(DOMAIN, appliance.ha_id)})
assert device assert device
entity_entries = entity_registry.entities.get_entries_for_device_id(device.id) entity_entries = entity_registry.entities.get_entries_for_device_id(device.id)
await client.add_events( await client.add_events(
[ [
EventMessage( EventMessage(
appliance_ha_id, appliance.ha_id,
EventType.CONNECTED, EventType.CONNECTED,
data=ArrayOfEvents([]), data=ArrayOfEvents([]),
) )
@ -179,20 +181,20 @@ async def test_connected_devices(
) )
await hass.async_block_till_done() await hass.async_block_till_done()
device = device_registry.async_get_device(identifiers={(DOMAIN, appliance_ha_id)}) device = device_registry.async_get_device(identifiers={(DOMAIN, appliance.ha_id)})
assert device assert device
new_entity_entries = entity_registry.entities.get_entries_for_device_id(device.id) new_entity_entries = entity_registry.entities.get_entries_for_device_id(device.id)
assert len(new_entity_entries) > len(entity_entries) assert len(new_entity_entries) > len(entity_entries)
@pytest.mark.parametrize("appliance_ha_id", ["FridgeFreezer"], indirect=True) @pytest.mark.parametrize("appliance", ["FridgeFreezer"], indirect=True)
async def test_number_entity_availabilty( async def test_number_entity_availability(
hass: HomeAssistant, hass: HomeAssistant,
config_entry: MockConfigEntry, config_entry: MockConfigEntry,
integration_setup: Callable[[MagicMock], Awaitable[bool]], integration_setup: Callable[[MagicMock], Awaitable[bool]],
setup_credentials: None, setup_credentials: None,
client: MagicMock, client: MagicMock,
appliance_ha_id: str, appliance: HomeAppliance,
) -> None: ) -> None:
"""Test if number entities availability are based on the appliance connection state.""" """Test if number entities availability are based on the appliance connection state."""
entity_ids = [ entity_ids = [
@ -215,7 +217,7 @@ async def test_number_entity_availabilty(
await client.add_events( await client.add_events(
[ [
EventMessage( EventMessage(
appliance_ha_id, appliance.ha_id,
EventType.DISCONNECTED, EventType.DISCONNECTED,
ArrayOfEvents([]), ArrayOfEvents([]),
) )
@ -229,7 +231,7 @@ async def test_number_entity_availabilty(
await client.add_events( await client.add_events(
[ [
EventMessage( EventMessage(
appliance_ha_id, appliance.ha_id,
EventType.CONNECTED, EventType.CONNECTED,
ArrayOfEvents([]), ArrayOfEvents([]),
) )
@ -243,7 +245,7 @@ async def test_number_entity_availabilty(
assert state.state != STATE_UNAVAILABLE assert state.state != STATE_UNAVAILABLE
@pytest.mark.parametrize("appliance_ha_id", ["FridgeFreezer"], indirect=True) @pytest.mark.parametrize("appliance", ["FridgeFreezer"], indirect=True)
@pytest.mark.parametrize( @pytest.mark.parametrize(
( (
"entity_id", "entity_id",
@ -279,7 +281,7 @@ async def test_number_entity_availabilty(
], ],
) )
async def test_number_entity_functionality( async def test_number_entity_functionality(
appliance_ha_id: str, appliance: HomeAppliance,
entity_id: str, entity_id: str,
setting_key: SettingKey, setting_key: SettingKey,
type: str, type: str,
@ -336,12 +338,12 @@ async def test_number_entity_functionality(
) )
await hass.async_block_till_done() await hass.async_block_till_done()
client.set_setting.assert_awaited_once_with( client.set_setting.assert_awaited_once_with(
appliance_ha_id, setting_key=setting_key, value=value appliance.ha_id, setting_key=setting_key, value=value
) )
assert hass.states.is_state(entity_id, str(float(value))) assert hass.states.is_state(entity_id, str(float(value)))
@pytest.mark.parametrize("appliance_ha_id", ["FridgeFreezer"], indirect=True) @pytest.mark.parametrize("appliance", ["FridgeFreezer"], indirect=True)
@pytest.mark.parametrize("retry_after", [0, None]) @pytest.mark.parametrize("retry_after", [0, None])
@pytest.mark.parametrize( @pytest.mark.parametrize(
( (
@ -368,7 +370,7 @@ async def test_number_entity_functionality(
@patch("homeassistant.components.home_connect.entity.API_DEFAULT_RETRY_AFTER", new=0) @patch("homeassistant.components.home_connect.entity.API_DEFAULT_RETRY_AFTER", new=0)
async def test_fetch_constraints_after_rate_limit_error( async def test_fetch_constraints_after_rate_limit_error(
retry_after: int | None, retry_after: int | None,
appliance_ha_id: str, appliance: HomeAppliance,
entity_id: str, entity_id: str,
setting_key: SettingKey, setting_key: SettingKey,
type: str, type: str,
@ -385,7 +387,7 @@ async def test_fetch_constraints_after_rate_limit_error(
"""Test that, if a API rate limit error is raised, the constraints are fetched later.""" """Test that, if a API rate limit error is raised, the constraints are fetched later."""
def get_settings_side_effect(ha_id: str): def get_settings_side_effect(ha_id: str):
if ha_id != appliance_ha_id: if ha_id != appliance.ha_id:
return ArrayOfSettings([]) return ArrayOfSettings([])
return ArrayOfSettings( return ArrayOfSettings(
[ [
@ -511,7 +513,7 @@ async def test_number_entity_error(
], ],
) )
@pytest.mark.parametrize( @pytest.mark.parametrize(
("appliance_ha_id", "entity_id", "option_key", "min", "max", "step_size", "unit"), ("appliance", "entity_id", "option_key", "min", "max", "step_size", "unit"),
[ [
( (
"Oven", "Oven",
@ -523,12 +525,12 @@ async def test_number_entity_error(
"°C", "°C",
), ),
], ],
indirect=["appliance_ha_id"], indirect=["appliance"],
) )
async def test_options_functionality( async def test_options_functionality(
entity_id: str, entity_id: str,
option_key: OptionKey, option_key: OptionKey,
appliance_ha_id: str, appliance: HomeAppliance,
min: int, min: int,
max: int, max: int,
step_size: int, step_size: int,
@ -615,7 +617,7 @@ async def test_options_functionality(
await hass.async_block_till_done() await hass.async_block_till_done()
assert called_mock.called assert called_mock.called
assert called_mock.call_args.args == (appliance_ha_id,) assert called_mock.call_args.args == (appliance.ha_id,)
assert called_mock.call_args.kwargs == { assert called_mock.call_args.kwargs == {
"option_key": option_key, "option_key": option_key,
"value": 80, "value": 80,

View File

@ -12,6 +12,7 @@ from aiohomeconnect.model import (
EventMessage, EventMessage,
EventType, EventType,
GetSetting, GetSetting,
HomeAppliance,
OptionKey, OptionKey,
ProgramDefinition, ProgramDefinition,
ProgramKey, ProgramKey,
@ -72,8 +73,9 @@ async def test_select(
assert config_entry.state is ConfigEntryState.LOADED assert config_entry.state is ConfigEntryState.LOADED
@pytest.mark.parametrize("appliance", ["Washer"], indirect=True)
async def test_paired_depaired_devices_flow( async def test_paired_depaired_devices_flow(
appliance_ha_id: str, appliance: HomeAppliance,
hass: HomeAssistant, hass: HomeAssistant,
config_entry: MockConfigEntry, config_entry: MockConfigEntry,
integration_setup: Callable[[MagicMock], Awaitable[bool]], integration_setup: Callable[[MagicMock], Awaitable[bool]],
@ -98,7 +100,7 @@ async def test_paired_depaired_devices_flow(
assert await integration_setup(client) assert await integration_setup(client)
assert config_entry.state == ConfigEntryState.LOADED assert config_entry.state == ConfigEntryState.LOADED
device = device_registry.async_get_device(identifiers={(DOMAIN, appliance_ha_id)}) device = device_registry.async_get_device(identifiers={(DOMAIN, appliance.ha_id)})
assert device assert device
entity_entries = entity_registry.entities.get_entries_for_device_id(device.id) entity_entries = entity_registry.entities.get_entries_for_device_id(device.id)
assert entity_entries assert entity_entries
@ -106,7 +108,7 @@ async def test_paired_depaired_devices_flow(
await client.add_events( await client.add_events(
[ [
EventMessage( EventMessage(
appliance_ha_id, appliance.ha_id,
EventType.DEPAIRED, EventType.DEPAIRED,
data=ArrayOfEvents([]), data=ArrayOfEvents([]),
) )
@ -114,7 +116,7 @@ async def test_paired_depaired_devices_flow(
) )
await hass.async_block_till_done() await hass.async_block_till_done()
device = device_registry.async_get_device(identifiers={(DOMAIN, appliance_ha_id)}) device = device_registry.async_get_device(identifiers={(DOMAIN, appliance.ha_id)})
assert not device assert not device
for entity_entry in entity_entries: for entity_entry in entity_entries:
assert not entity_registry.async_get(entity_entry.entity_id) assert not entity_registry.async_get(entity_entry.entity_id)
@ -123,7 +125,7 @@ async def test_paired_depaired_devices_flow(
await client.add_events( await client.add_events(
[ [
EventMessage( EventMessage(
appliance_ha_id, appliance.ha_id,
EventType.PAIRED, EventType.PAIRED,
data=ArrayOfEvents([]), data=ArrayOfEvents([]),
) )
@ -131,13 +133,14 @@ async def test_paired_depaired_devices_flow(
) )
await hass.async_block_till_done() await hass.async_block_till_done()
assert device_registry.async_get_device(identifiers={(DOMAIN, appliance_ha_id)}) assert device_registry.async_get_device(identifiers={(DOMAIN, appliance.ha_id)})
for entity_entry in entity_entries: for entity_entry in entity_entries:
assert entity_registry.async_get(entity_entry.entity_id) assert entity_registry.async_get(entity_entry.entity_id)
@pytest.mark.parametrize("appliance", ["Washer"], indirect=True)
async def test_connected_devices( async def test_connected_devices(
appliance_ha_id: str, appliance: HomeAppliance,
hass: HomeAssistant, hass: HomeAssistant,
config_entry: MockConfigEntry, config_entry: MockConfigEntry,
integration_setup: Callable[[MagicMock], Awaitable[bool]], integration_setup: Callable[[MagicMock], Awaitable[bool]],
@ -156,13 +159,13 @@ async def test_connected_devices(
assert await integration_setup(client) assert await integration_setup(client)
assert config_entry.state == ConfigEntryState.LOADED assert config_entry.state == ConfigEntryState.LOADED
device = device_registry.async_get_device(identifiers={(DOMAIN, appliance_ha_id)}) device = device_registry.async_get_device(identifiers={(DOMAIN, appliance.ha_id)})
assert device assert device
await client.add_events( await client.add_events(
[ [
EventMessage( EventMessage(
appliance_ha_id, appliance.ha_id,
EventType.CONNECTED, EventType.CONNECTED,
data=ArrayOfEvents([]), data=ArrayOfEvents([]),
) )
@ -170,19 +173,20 @@ async def test_connected_devices(
) )
await hass.async_block_till_done() await hass.async_block_till_done()
device = device_registry.async_get_device(identifiers={(DOMAIN, appliance_ha_id)}) device = device_registry.async_get_device(identifiers={(DOMAIN, appliance.ha_id)})
assert device assert device
entity_entries = entity_registry.entities.get_entries_for_device_id(device.id) entity_entries = entity_registry.entities.get_entries_for_device_id(device.id)
assert entity_entries assert entity_entries
async def test_select_entity_availabilty( @pytest.mark.parametrize("appliance", ["Washer"], indirect=True)
async def test_select_entity_availability(
hass: HomeAssistant, hass: HomeAssistant,
config_entry: MockConfigEntry, config_entry: MockConfigEntry,
integration_setup: Callable[[MagicMock], Awaitable[bool]], integration_setup: Callable[[MagicMock], Awaitable[bool]],
setup_credentials: None, setup_credentials: None,
client: MagicMock, client: MagicMock,
appliance_ha_id: str, appliance: HomeAppliance,
) -> None: ) -> None:
"""Test if select entities availability are based on the appliance connection state.""" """Test if select entities availability are based on the appliance connection state."""
entity_ids = [ entity_ids = [
@ -200,7 +204,7 @@ async def test_select_entity_availabilty(
await client.add_events( await client.add_events(
[ [
EventMessage( EventMessage(
appliance_ha_id, appliance.ha_id,
EventType.DISCONNECTED, EventType.DISCONNECTED,
ArrayOfEvents([]), ArrayOfEvents([]),
) )
@ -214,7 +218,7 @@ async def test_select_entity_availabilty(
await client.add_events( await client.add_events(
[ [
EventMessage( EventMessage(
appliance_ha_id, appliance.ha_id,
EventType.CONNECTED, EventType.CONNECTED,
ArrayOfEvents([]), ArrayOfEvents([]),
) )
@ -290,7 +294,7 @@ async def test_filter_programs(
@pytest.mark.parametrize( @pytest.mark.parametrize(
( (
"appliance_ha_id", "appliance",
"entity_id", "entity_id",
"expected_initial_state", "expected_initial_state",
"mock_method", "mock_method",
@ -318,10 +322,10 @@ async def test_filter_programs(
EventKey.BSH_COMMON_ROOT_ACTIVE_PROGRAM, EventKey.BSH_COMMON_ROOT_ACTIVE_PROGRAM,
), ),
], ],
indirect=["appliance_ha_id"], indirect=["appliance"],
) )
async def test_select_program_functionality( async def test_select_program_functionality(
appliance_ha_id: str, appliance: HomeAppliance,
entity_id: str, entity_id: str,
expected_initial_state: str, expected_initial_state: str,
mock_method: str, mock_method: str,
@ -347,14 +351,14 @@ async def test_select_program_functionality(
) )
await hass.async_block_till_done() await hass.async_block_till_done()
getattr(client, mock_method).assert_awaited_once_with( getattr(client, mock_method).assert_awaited_once_with(
appliance_ha_id, program_key=program_key appliance.ha_id, program_key=program_key
) )
assert hass.states.is_state(entity_id, program_to_set) assert hass.states.is_state(entity_id, program_to_set)
await client.add_events( await client.add_events(
[ [
EventMessage( EventMessage(
appliance_ha_id, appliance.ha_id,
EventType.NOTIFY, EventType.NOTIFY,
ArrayOfEvents( ArrayOfEvents(
[ [
@ -433,13 +437,13 @@ async def test_select_exception_handling(
await hass.services.async_call( await hass.services.async_call(
SELECT_DOMAIN, SELECT_DOMAIN,
SERVICE_SELECT_OPTION, SERVICE_SELECT_OPTION,
{"entity_id": entity_id, "option": program_to_set}, {ATTR_ENTITY_ID: entity_id, ATTR_OPTION: program_to_set},
blocking=True, blocking=True,
) )
assert getattr(client_with_exception, mock_attr).call_count == 2 assert getattr(client_with_exception, mock_attr).call_count == 2
@pytest.mark.parametrize("appliance_ha_id", ["Hood"], indirect=True) @pytest.mark.parametrize("appliance", ["Hood"], indirect=True)
@pytest.mark.parametrize( @pytest.mark.parametrize(
( (
"entity_id", "entity_id",
@ -473,7 +477,7 @@ async def test_select_exception_handling(
], ],
) )
async def test_select_functionality( async def test_select_functionality(
appliance_ha_id: str, appliance: HomeAppliance,
entity_id: str, entity_id: str,
setting_key: SettingKey, setting_key: SettingKey,
expected_options: set[str], expected_options: set[str],
@ -497,12 +501,12 @@ async def test_select_functionality(
await hass.services.async_call( await hass.services.async_call(
SELECT_DOMAIN, SELECT_DOMAIN,
SERVICE_SELECT_OPTION, SERVICE_SELECT_OPTION,
{ATTR_ENTITY_ID: entity_id, "option": value_to_set}, {ATTR_ENTITY_ID: entity_id, ATTR_OPTION: value_to_set},
) )
await hass.async_block_till_done() await hass.async_block_till_done()
client.set_setting.assert_called_once() client.set_setting.assert_called_once()
assert client.set_setting.call_args.args == (appliance_ha_id,) assert client.set_setting.call_args.args == (appliance.ha_id,)
assert client.set_setting.call_args.kwargs == { assert client.set_setting.call_args.kwargs == {
"setting_key": setting_key, "setting_key": setting_key,
"value": expected_value_call_arg, "value": expected_value_call_arg,
@ -510,7 +514,7 @@ async def test_select_functionality(
assert hass.states.is_state(entity_id, value_to_set) assert hass.states.is_state(entity_id, value_to_set)
@pytest.mark.parametrize("appliance_ha_id", ["Hood"], indirect=True) @pytest.mark.parametrize("appliance", ["Hood"], indirect=True)
@pytest.mark.parametrize( @pytest.mark.parametrize(
( (
"entity_id", "entity_id",
@ -537,7 +541,7 @@ async def test_select_functionality(
], ],
) )
async def test_fetch_allowed_values( async def test_fetch_allowed_values(
appliance_ha_id: str, appliance: HomeAppliance,
entity_id: str, entity_id: str,
test_setting_key: SettingKey, test_setting_key: SettingKey,
allowed_values: list[str | None], allowed_values: list[str | None],
@ -554,7 +558,7 @@ async def test_fetch_allowed_values(
async def get_setting_side_effect( async def get_setting_side_effect(
ha_id: str, setting_key: SettingKey ha_id: str, setting_key: SettingKey
) -> GetSetting: ) -> GetSetting:
if ha_id != appliance_ha_id or setting_key != test_setting_key: if ha_id != appliance.ha_id or setting_key != test_setting_key:
return await original_get_setting_side_effect(ha_id, setting_key) return await original_get_setting_side_effect(ha_id, setting_key)
return GetSetting( return GetSetting(
key=test_setting_key, key=test_setting_key,
@ -576,7 +580,7 @@ async def test_fetch_allowed_values(
assert set(entity_state.attributes[ATTR_OPTIONS]) == expected_options assert set(entity_state.attributes[ATTR_OPTIONS]) == expected_options
@pytest.mark.parametrize("appliance_ha_id", ["Hood"], indirect=True) @pytest.mark.parametrize("appliance", ["Hood"], indirect=True)
@pytest.mark.parametrize( @pytest.mark.parametrize(
( (
"entity_id", "entity_id",
@ -594,7 +598,7 @@ async def test_fetch_allowed_values(
], ],
) )
async def test_fetch_allowed_values_after_rate_limit_error( async def test_fetch_allowed_values_after_rate_limit_error(
appliance_ha_id: str, appliance: HomeAppliance,
entity_id: str, entity_id: str,
setting_key: SettingKey, setting_key: SettingKey,
allowed_values: list[str | None], allowed_values: list[str | None],
@ -608,7 +612,7 @@ async def test_fetch_allowed_values_after_rate_limit_error(
"""Test fetch allowed values.""" """Test fetch allowed values."""
def get_settings_side_effect(ha_id: str): def get_settings_side_effect(ha_id: str):
if ha_id != appliance_ha_id: if ha_id != appliance.ha_id:
return ArrayOfSettings([]) return ArrayOfSettings([])
return ArrayOfSettings( return ArrayOfSettings(
[ [
@ -648,7 +652,7 @@ async def test_fetch_allowed_values_after_rate_limit_error(
assert set(entity_state.attributes[ATTR_OPTIONS]) == expected_options assert set(entity_state.attributes[ATTR_OPTIONS]) == expected_options
@pytest.mark.parametrize("appliance_ha_id", ["Hood"], indirect=True) @pytest.mark.parametrize("appliance", ["Hood"], indirect=True)
@pytest.mark.parametrize( @pytest.mark.parametrize(
( (
"entity_id", "entity_id",
@ -669,7 +673,7 @@ async def test_fetch_allowed_values_after_rate_limit_error(
], ],
) )
async def test_default_values_after_fetch_allowed_values_error( async def test_default_values_after_fetch_allowed_values_error(
appliance_ha_id: str, appliance: HomeAppliance,
entity_id: str, entity_id: str,
setting_key: SettingKey, setting_key: SettingKey,
exception: Exception, exception: Exception,
@ -683,7 +687,7 @@ async def test_default_values_after_fetch_allowed_values_error(
"""Test fetch allowed values.""" """Test fetch allowed values."""
def get_settings_side_effect(ha_id: str): def get_settings_side_effect(ha_id: str):
if ha_id != appliance_ha_id: if ha_id != appliance.ha_id:
return ArrayOfSettings([]) return ArrayOfSettings([])
return ArrayOfSettings( return ArrayOfSettings(
[ [
@ -758,12 +762,13 @@ async def test_select_entity_error(
await hass.services.async_call( await hass.services.async_call(
SELECT_DOMAIN, SELECT_DOMAIN,
SERVICE_SELECT_OPTION, SERVICE_SELECT_OPTION,
{ATTR_ENTITY_ID: entity_id, "option": value_to_set}, {ATTR_ENTITY_ID: entity_id, ATTR_OPTION: value_to_set},
blocking=True, blocking=True,
) )
assert getattr(client_with_exception, mock_attr).call_count == 2 assert getattr(client_with_exception, mock_attr).call_count == 2
@pytest.mark.parametrize("appliance", ["Washer"], indirect=True)
@pytest.mark.parametrize( @pytest.mark.parametrize(
( (
"set_active_program_options_side_effect", "set_active_program_options_side_effect",
@ -840,7 +845,7 @@ async def test_options_functionality(
option_key: OptionKey, option_key: OptionKey,
allowed_values: list[str | None] | None, allowed_values: list[str | None] | None,
expected_options: set[str], expected_options: set[str],
appliance_ha_id: str, appliance: HomeAppliance,
set_active_program_options_side_effect: ActiveProgramNotSetError | None, set_active_program_options_side_effect: ActiveProgramNotSetError | None,
set_selected_program_options_side_effect: SelectedProgramNotSetError | None, set_selected_program_options_side_effect: SelectedProgramNotSetError | None,
called_mock_method: str, called_mock_method: str,
@ -894,7 +899,7 @@ async def test_options_functionality(
await hass.async_block_till_done() await hass.async_block_till_done()
assert called_mock.called assert called_mock.called
assert called_mock.call_args.args == (appliance_ha_id,) assert called_mock.call_args.args == (appliance.ha_id,)
assert called_mock.call_args.kwargs == { assert called_mock.call_args.kwargs == {
"option_key": option_key, "option_key": option_key,
"value": "LaundryCare.Washer.EnumType.Temperature.UlWarm", "value": "LaundryCare.Washer.EnumType.Temperature.UlWarm",

View File

@ -10,6 +10,7 @@ from aiohomeconnect.model import (
EventKey, EventKey,
EventMessage, EventMessage,
EventType, EventType,
HomeAppliance,
Status, Status,
StatusKey, StatusKey,
) )
@ -99,8 +100,9 @@ async def test_sensors(
assert config_entry.state == ConfigEntryState.LOADED assert config_entry.state == ConfigEntryState.LOADED
@pytest.mark.parametrize("appliance", ["Washer"], indirect=True)
async def test_paired_depaired_devices_flow( async def test_paired_depaired_devices_flow(
appliance_ha_id: str, appliance: HomeAppliance,
hass: HomeAssistant, hass: HomeAssistant,
config_entry: MockConfigEntry, config_entry: MockConfigEntry,
integration_setup: Callable[[MagicMock], Awaitable[bool]], integration_setup: Callable[[MagicMock], Awaitable[bool]],
@ -114,7 +116,7 @@ async def test_paired_depaired_devices_flow(
assert await integration_setup(client) assert await integration_setup(client)
assert config_entry.state == ConfigEntryState.LOADED assert config_entry.state == ConfigEntryState.LOADED
device = device_registry.async_get_device(identifiers={(DOMAIN, appliance_ha_id)}) device = device_registry.async_get_device(identifiers={(DOMAIN, appliance.ha_id)})
assert device assert device
entity_entries = entity_registry.entities.get_entries_for_device_id(device.id) entity_entries = entity_registry.entities.get_entries_for_device_id(device.id)
assert entity_entries assert entity_entries
@ -122,7 +124,7 @@ async def test_paired_depaired_devices_flow(
await client.add_events( await client.add_events(
[ [
EventMessage( EventMessage(
appliance_ha_id, appliance.ha_id,
EventType.DEPAIRED, EventType.DEPAIRED,
data=ArrayOfEvents([]), data=ArrayOfEvents([]),
) )
@ -130,7 +132,7 @@ async def test_paired_depaired_devices_flow(
) )
await hass.async_block_till_done() await hass.async_block_till_done()
device = device_registry.async_get_device(identifiers={(DOMAIN, appliance_ha_id)}) device = device_registry.async_get_device(identifiers={(DOMAIN, appliance.ha_id)})
assert not device assert not device
for entity_entry in entity_entries: for entity_entry in entity_entries:
assert not entity_registry.async_get(entity_entry.entity_id) assert not entity_registry.async_get(entity_entry.entity_id)
@ -139,7 +141,7 @@ async def test_paired_depaired_devices_flow(
await client.add_events( await client.add_events(
[ [
EventMessage( EventMessage(
appliance_ha_id, appliance.ha_id,
EventType.PAIRED, EventType.PAIRED,
data=ArrayOfEvents([]), data=ArrayOfEvents([]),
) )
@ -147,13 +149,14 @@ async def test_paired_depaired_devices_flow(
) )
await hass.async_block_till_done() await hass.async_block_till_done()
assert device_registry.async_get_device(identifiers={(DOMAIN, appliance_ha_id)}) assert device_registry.async_get_device(identifiers={(DOMAIN, appliance.ha_id)})
for entity_entry in entity_entries: for entity_entry in entity_entries:
assert entity_registry.async_get(entity_entry.entity_id) assert entity_registry.async_get(entity_entry.entity_id)
@pytest.mark.parametrize("appliance", ["Washer"], indirect=True)
async def test_connected_devices( async def test_connected_devices(
appliance_ha_id: str, appliance: HomeAppliance,
hass: HomeAssistant, hass: HomeAssistant,
config_entry: MockConfigEntry, config_entry: MockConfigEntry,
integration_setup: Callable[[MagicMock], Awaitable[bool]], integration_setup: Callable[[MagicMock], Awaitable[bool]],
@ -170,7 +173,7 @@ async def test_connected_devices(
get_status_original_mock = client.get_status get_status_original_mock = client.get_status
def get_status_side_effect(ha_id: str): def get_status_side_effect(ha_id: str):
if ha_id == appliance_ha_id: if ha_id == appliance.ha_id:
raise HomeConnectApiError( raise HomeConnectApiError(
"SDK.Error.HomeAppliance.Connection.Initialization.Failed" "SDK.Error.HomeAppliance.Connection.Initialization.Failed"
) )
@ -182,14 +185,14 @@ async def test_connected_devices(
assert config_entry.state == ConfigEntryState.LOADED assert config_entry.state == ConfigEntryState.LOADED
client.get_status = get_status_original_mock client.get_status = get_status_original_mock
device = device_registry.async_get_device(identifiers={(DOMAIN, appliance_ha_id)}) device = device_registry.async_get_device(identifiers={(DOMAIN, appliance.ha_id)})
assert device assert device
entity_entries = entity_registry.entities.get_entries_for_device_id(device.id) entity_entries = entity_registry.entities.get_entries_for_device_id(device.id)
await client.add_events( await client.add_events(
[ [
EventMessage( EventMessage(
appliance_ha_id, appliance.ha_id,
EventType.CONNECTED, EventType.CONNECTED,
data=ArrayOfEvents([]), data=ArrayOfEvents([]),
) )
@ -197,20 +200,20 @@ async def test_connected_devices(
) )
await hass.async_block_till_done() await hass.async_block_till_done()
device = device_registry.async_get_device(identifiers={(DOMAIN, appliance_ha_id)}) device = device_registry.async_get_device(identifiers={(DOMAIN, appliance.ha_id)})
assert device assert device
new_entity_entries = entity_registry.entities.get_entries_for_device_id(device.id) new_entity_entries = entity_registry.entities.get_entries_for_device_id(device.id)
assert len(new_entity_entries) > len(entity_entries) assert len(new_entity_entries) > len(entity_entries)
@pytest.mark.parametrize("appliance_ha_id", [TEST_HC_APP], indirect=True) @pytest.mark.parametrize("appliance", [TEST_HC_APP], indirect=True)
async def test_sensor_entity_availabilty( async def test_sensor_entity_availability(
hass: HomeAssistant, hass: HomeAssistant,
config_entry: MockConfigEntry, config_entry: MockConfigEntry,
integration_setup: Callable[[MagicMock], Awaitable[bool]], integration_setup: Callable[[MagicMock], Awaitable[bool]],
setup_credentials: None, setup_credentials: None,
client: MagicMock, client: MagicMock,
appliance_ha_id: str, appliance: HomeAppliance,
) -> None: ) -> None:
"""Test if sensor entities availability are based on the appliance connection state.""" """Test if sensor entities availability are based on the appliance connection state."""
entity_ids = [ entity_ids = [
@ -229,7 +232,7 @@ async def test_sensor_entity_availabilty(
await client.add_events( await client.add_events(
[ [
EventMessage( EventMessage(
appliance_ha_id, appliance.ha_id,
EventType.DISCONNECTED, EventType.DISCONNECTED,
ArrayOfEvents([]), ArrayOfEvents([]),
) )
@ -243,7 +246,7 @@ async def test_sensor_entity_availabilty(
await client.add_events( await client.add_events(
[ [
EventMessage( EventMessage(
appliance_ha_id, appliance.ha_id,
EventType.CONNECTED, EventType.CONNECTED,
ArrayOfEvents([]), ArrayOfEvents([]),
) )
@ -257,7 +260,7 @@ async def test_sensor_entity_availabilty(
assert state.state != STATE_UNAVAILABLE assert state.state != STATE_UNAVAILABLE
# Appliance_ha_id program sequence with a delayed start. # Appliance program sequence with a delayed start.
PROGRAM_SEQUENCE_EVENTS = ( PROGRAM_SEQUENCE_EVENTS = (
EVENT_PROG_DELAYED_START, EVENT_PROG_DELAYED_START,
EVENT_PROG_RUN, EVENT_PROG_RUN,
@ -292,7 +295,7 @@ ENTITY_ID_STATES = {
} }
@pytest.mark.parametrize("appliance_ha_id", [TEST_HC_APP], indirect=True) @pytest.mark.parametrize("appliance", [TEST_HC_APP], indirect=True)
@pytest.mark.parametrize( @pytest.mark.parametrize(
("states", "event_run"), ("states", "event_run"),
list( list(
@ -305,7 +308,7 @@ ENTITY_ID_STATES = {
) )
async def test_program_sensors( async def test_program_sensors(
client: MagicMock, client: MagicMock,
appliance_ha_id: str, appliance: HomeAppliance,
states: tuple, states: tuple,
event_run: dict[EventType, dict[EventKey, str | int]], event_run: dict[EventType, dict[EventKey, str | int]],
freezer: FrozenDateTimeFactory, freezer: FrozenDateTimeFactory,
@ -335,7 +338,7 @@ async def test_program_sensors(
await client.add_events( await client.add_events(
[ [
EventMessage( EventMessage(
appliance_ha_id, appliance.ha_id,
event_type, event_type,
ArrayOfEvents( ArrayOfEvents(
[ [
@ -359,7 +362,7 @@ async def test_program_sensors(
assert hass.states.is_state(entity_id, state) assert hass.states.is_state(entity_id, state)
@pytest.mark.parametrize("appliance_ha_id", [TEST_HC_APP], indirect=True) @pytest.mark.parametrize("appliance", [TEST_HC_APP], indirect=True)
@pytest.mark.parametrize( @pytest.mark.parametrize(
("initial_operation_state", "initial_state", "event_order", "entity_states"), ("initial_operation_state", "initial_state", "event_order", "entity_states"),
[ [
@ -382,7 +385,7 @@ async def test_program_sensor_edge_case(
initial_state: str, initial_state: str,
event_order: tuple[EventType, EventType], event_order: tuple[EventType, EventType],
entity_states: tuple[str, str], entity_states: tuple[str, str],
appliance_ha_id: str, appliance: HomeAppliance,
hass: HomeAssistant, hass: HomeAssistant,
config_entry: MockConfigEntry, config_entry: MockConfigEntry,
integration_setup: Callable[[MagicMock], Awaitable[bool]], integration_setup: Callable[[MagicMock], Awaitable[bool]],
@ -413,7 +416,7 @@ async def test_program_sensor_edge_case(
await client.add_events( await client.add_events(
[ [
EventMessage( EventMessage(
appliance_ha_id, appliance.ha_id,
event_type, event_type,
ArrayOfEvents( ArrayOfEvents(
[ [
@ -452,9 +455,9 @@ ENTITY_ID_EDGE_CASE_STATES = [
] ]
@pytest.mark.parametrize("appliance_ha_id", [TEST_HC_APP], indirect=True) @pytest.mark.parametrize("appliance", [TEST_HC_APP], indirect=True)
async def test_remaining_prog_time_edge_cases( async def test_remaining_prog_time_edge_cases(
appliance_ha_id: str, appliance: HomeAppliance,
freezer: FrozenDateTimeFactory, freezer: FrozenDateTimeFactory,
hass: HomeAssistant, hass: HomeAssistant,
config_entry: MockConfigEntry, config_entry: MockConfigEntry,
@ -478,7 +481,7 @@ async def test_remaining_prog_time_edge_cases(
await client.add_events( await client.add_events(
[ [
EventMessage( EventMessage(
appliance_ha_id, appliance.ha_id,
event_type, event_type,
ArrayOfEvents( ArrayOfEvents(
[ [
@ -509,7 +512,7 @@ async def test_remaining_prog_time_edge_cases(
"event_type", "event_type",
"event_value_update", "event_value_update",
"expected", "expected",
"appliance_ha_id", "appliance",
), ),
[ [
( (
@ -601,14 +604,14 @@ async def test_remaining_prog_time_edge_cases(
"CoffeeMaker", "CoffeeMaker",
), ),
], ],
indirect=["appliance_ha_id"], indirect=["appliance"],
) )
async def test_sensors_states( async def test_sensors_states(
entity_id: str, entity_id: str,
event_key: EventKey, event_key: EventKey,
event_type: EventType, event_type: EventType,
event_value_update: str, event_value_update: str,
appliance_ha_id: str, appliance: HomeAppliance,
expected: str, expected: str,
hass: HomeAssistant, hass: HomeAssistant,
config_entry: MockConfigEntry, config_entry: MockConfigEntry,
@ -616,7 +619,7 @@ async def test_sensors_states(
setup_credentials: None, setup_credentials: None,
client: MagicMock, client: MagicMock,
) -> None: ) -> None:
"""Tests for Appliance_ha_id alarm sensors.""" """Tests for appliance alarm sensors."""
assert config_entry.state == ConfigEntryState.NOT_LOADED assert config_entry.state == ConfigEntryState.NOT_LOADED
assert await integration_setup(client) assert await integration_setup(client)
assert config_entry.state == ConfigEntryState.LOADED assert config_entry.state == ConfigEntryState.LOADED
@ -624,7 +627,7 @@ async def test_sensors_states(
await client.add_events( await client.add_events(
[ [
EventMessage( EventMessage(
appliance_ha_id, appliance.ha_id,
event_type, event_type,
ArrayOfEvents( ArrayOfEvents(
[ [
@ -647,7 +650,7 @@ async def test_sensors_states(
@pytest.mark.parametrize( @pytest.mark.parametrize(
( (
"appliance_ha_id", "appliance",
"entity_id", "entity_id",
"status_key", "status_key",
"unit_get_status", "unit_get_status",
@ -672,10 +675,10 @@ async def test_sensors_states(
1, 1,
), ),
], ],
indirect=["appliance_ha_id"], indirect=["appliance"],
) )
async def test_sensor_unit_fetching( async def test_sensor_unit_fetching(
appliance_ha_id: str, appliance: HomeAppliance,
entity_id: str, entity_id: str,
status_key: StatusKey, status_key: StatusKey,
unit_get_status: str | None, unit_get_status: str | None,
@ -690,7 +693,7 @@ async def test_sensor_unit_fetching(
"""Test that the sensor entities are capable of fetching units.""" """Test that the sensor entities are capable of fetching units."""
async def get_status_mock(ha_id: str) -> ArrayOfStatus: async def get_status_mock(ha_id: str) -> ArrayOfStatus:
if ha_id != appliance_ha_id: if ha_id != appliance.ha_id:
return ArrayOfStatus([]) return ArrayOfStatus([])
return ArrayOfStatus( return ArrayOfStatus(
[ [
@ -729,7 +732,7 @@ async def test_sensor_unit_fetching(
@pytest.mark.parametrize( @pytest.mark.parametrize(
( (
"appliance_ha_id", "appliance",
"entity_id", "entity_id",
"status_key", "status_key",
), ),
@ -740,10 +743,10 @@ async def test_sensor_unit_fetching(
StatusKey.COOKING_OVEN_CURRENT_CAVITY_TEMPERATURE, StatusKey.COOKING_OVEN_CURRENT_CAVITY_TEMPERATURE,
), ),
], ],
indirect=["appliance_ha_id"], indirect=["appliance"],
) )
async def test_sensor_unit_fetching_error( async def test_sensor_unit_fetching_error(
appliance_ha_id: str, appliance: HomeAppliance,
entity_id: str, entity_id: str,
status_key: StatusKey, status_key: StatusKey,
hass: HomeAssistant, hass: HomeAssistant,
@ -755,7 +758,7 @@ async def test_sensor_unit_fetching_error(
"""Test that the sensor entities are capable of fetching units.""" """Test that the sensor entities are capable of fetching units."""
async def get_status_mock(ha_id: str) -> ArrayOfStatus: async def get_status_mock(ha_id: str) -> ArrayOfStatus:
if ha_id != appliance_ha_id: if ha_id != appliance.ha_id:
return ArrayOfStatus([]) return ArrayOfStatus([])
return ArrayOfStatus( return ArrayOfStatus(
[ [
@ -779,7 +782,7 @@ async def test_sensor_unit_fetching_error(
@pytest.mark.parametrize( @pytest.mark.parametrize(
( (
"appliance_ha_id", "appliance",
"entity_id", "entity_id",
"status_key", "status_key",
"unit", "unit",
@ -792,10 +795,10 @@ async def test_sensor_unit_fetching_error(
"°C", "°C",
), ),
], ],
indirect=["appliance_ha_id"], indirect=["appliance"],
) )
async def test_sensor_unit_fetching_after_rate_limit_error( async def test_sensor_unit_fetching_after_rate_limit_error(
appliance_ha_id: str, appliance: HomeAppliance,
entity_id: str, entity_id: str,
status_key: StatusKey, status_key: StatusKey,
unit: str, unit: str,
@ -808,7 +811,7 @@ async def test_sensor_unit_fetching_after_rate_limit_error(
"""Test that the sensor entities are capable of fetching units.""" """Test that the sensor entities are capable of fetching units."""
async def get_status_mock(ha_id: str) -> ArrayOfStatus: async def get_status_mock(ha_id: str) -> ArrayOfStatus:
if ha_id != appliance_ha_id: if ha_id != appliance.ha_id:
return ArrayOfStatus([]) return ArrayOfStatus([])
return ArrayOfStatus( return ArrayOfStatus(
[ [

View File

@ -5,7 +5,7 @@ from http import HTTPStatus
from typing import Any from typing import Any
from unittest.mock import MagicMock from unittest.mock import MagicMock
from aiohomeconnect.model import OptionKey, ProgramKey, SettingKey from aiohomeconnect.model import HomeAppliance, OptionKey, ProgramKey, SettingKey
import pytest import pytest
from syrupy.assertion import SnapshotAssertion from syrupy.assertion import SnapshotAssertion
@ -170,6 +170,7 @@ SERVICES_SET_PROGRAM_AND_OPTIONS = [
] ]
@pytest.mark.parametrize("appliance", ["Washer"], indirect=True)
@pytest.mark.parametrize( @pytest.mark.parametrize(
"service_call", "service_call",
SERVICE_KV_CALL_PARAMS + SERVICE_COMMAND_CALL_PARAMS + SERVICE_PROGRAM_CALL_PARAMS, SERVICE_KV_CALL_PARAMS + SERVICE_COMMAND_CALL_PARAMS + SERVICE_PROGRAM_CALL_PARAMS,
@ -182,7 +183,7 @@ async def test_key_value_services(
integration_setup: Callable[[MagicMock], Awaitable[bool]], integration_setup: Callable[[MagicMock], Awaitable[bool]],
setup_credentials: None, setup_credentials: None,
client: MagicMock, client: MagicMock,
appliance_ha_id: str, appliance: HomeAppliance,
) -> None: ) -> None:
"""Create and test services.""" """Create and test services."""
assert config_entry.state == ConfigEntryState.NOT_LOADED assert config_entry.state == ConfigEntryState.NOT_LOADED
@ -191,7 +192,7 @@ async def test_key_value_services(
device_entry = device_registry.async_get_or_create( device_entry = device_registry.async_get_or_create(
config_entry_id=config_entry.entry_id, config_entry_id=config_entry.entry_id,
identifiers={(DOMAIN, appliance_ha_id)}, identifiers={(DOMAIN, appliance.ha_id)},
) )
service_name = service_call["service"] service_name = service_call["service"]
@ -203,6 +204,7 @@ async def test_key_value_services(
) )
@pytest.mark.parametrize("appliance", ["Washer"], indirect=True)
@pytest.mark.parametrize( @pytest.mark.parametrize(
("service_call", "issue_id"), ("service_call", "issue_id"),
[ [
@ -231,7 +233,7 @@ async def test_programs_and_options_actions_deprecation(
integration_setup: Callable[[MagicMock], Awaitable[bool]], integration_setup: Callable[[MagicMock], Awaitable[bool]],
setup_credentials: None, setup_credentials: None,
client: MagicMock, client: MagicMock,
appliance_ha_id: str, appliance: HomeAppliance,
issue_registry: ir.IssueRegistry, issue_registry: ir.IssueRegistry,
hass_client: ClientSessionGenerator, hass_client: ClientSessionGenerator,
) -> None: ) -> None:
@ -242,7 +244,7 @@ async def test_programs_and_options_actions_deprecation(
device_entry = device_registry.async_get_or_create( device_entry = device_registry.async_get_or_create(
config_entry_id=config_entry.entry_id, config_entry_id=config_entry.entry_id,
identifiers={(DOMAIN, appliance_ha_id)}, identifiers={(DOMAIN, appliance.ha_id)},
) )
service_call["service_data"]["device_id"] = device_entry.id service_call["service_data"]["device_id"] = device_entry.id
@ -279,6 +281,7 @@ async def test_programs_and_options_actions_deprecation(
assert len(issue_registry.issues) == 0 assert len(issue_registry.issues) == 0
@pytest.mark.parametrize("appliance", ["Washer"], indirect=True)
@pytest.mark.parametrize( @pytest.mark.parametrize(
("service_call", "called_method"), ("service_call", "called_method"),
zip( zip(
@ -301,7 +304,7 @@ async def test_set_program_and_options(
integration_setup: Callable[[MagicMock], Awaitable[bool]], integration_setup: Callable[[MagicMock], Awaitable[bool]],
setup_credentials: None, setup_credentials: None,
client: MagicMock, client: MagicMock,
appliance_ha_id: str, appliance: HomeAppliance,
snapshot: SnapshotAssertion, snapshot: SnapshotAssertion,
) -> None: ) -> None:
"""Test recognized options.""" """Test recognized options."""
@ -311,7 +314,7 @@ async def test_set_program_and_options(
device_entry = device_registry.async_get_or_create( device_entry = device_registry.async_get_or_create(
config_entry_id=config_entry.entry_id, config_entry_id=config_entry.entry_id,
identifiers={(DOMAIN, appliance_ha_id)}, identifiers={(DOMAIN, appliance.ha_id)},
) )
service_call["service_data"]["device_id"] = device_entry.id service_call["service_data"]["device_id"] = device_entry.id
@ -322,6 +325,7 @@ async def test_set_program_and_options(
assert method_mock.call_args == snapshot assert method_mock.call_args == snapshot
@pytest.mark.parametrize("appliance", ["Washer"], indirect=True)
@pytest.mark.parametrize( @pytest.mark.parametrize(
("service_call", "error_regex"), ("service_call", "error_regex"),
zip( zip(
@ -344,7 +348,7 @@ async def test_set_program_and_options_exceptions(
integration_setup: Callable[[MagicMock], Awaitable[bool]], integration_setup: Callable[[MagicMock], Awaitable[bool]],
setup_credentials: None, setup_credentials: None,
client_with_exception: MagicMock, client_with_exception: MagicMock,
appliance_ha_id: str, appliance: HomeAppliance,
) -> None: ) -> None:
"""Test recognized options.""" """Test recognized options."""
assert config_entry.state == ConfigEntryState.NOT_LOADED assert config_entry.state == ConfigEntryState.NOT_LOADED
@ -353,7 +357,7 @@ async def test_set_program_and_options_exceptions(
device_entry = device_registry.async_get_or_create( device_entry = device_registry.async_get_or_create(
config_entry_id=config_entry.entry_id, config_entry_id=config_entry.entry_id,
identifiers={(DOMAIN, appliance_ha_id)}, identifiers={(DOMAIN, appliance.ha_id)},
) )
service_call["service_data"]["device_id"] = device_entry.id service_call["service_data"]["device_id"] = device_entry.id
@ -361,6 +365,7 @@ async def test_set_program_and_options_exceptions(
await hass.services.async_call(**service_call) await hass.services.async_call(**service_call)
@pytest.mark.parametrize("appliance", ["Washer"], indirect=True)
@pytest.mark.parametrize( @pytest.mark.parametrize(
"service_call", "service_call",
SERVICE_KV_CALL_PARAMS + SERVICE_COMMAND_CALL_PARAMS + SERVICE_PROGRAM_CALL_PARAMS, SERVICE_KV_CALL_PARAMS + SERVICE_COMMAND_CALL_PARAMS + SERVICE_PROGRAM_CALL_PARAMS,
@ -372,7 +377,7 @@ async def test_services_exception_device_id(
integration_setup: Callable[[MagicMock], Awaitable[bool]], integration_setup: Callable[[MagicMock], Awaitable[bool]],
setup_credentials: None, setup_credentials: None,
client_with_exception: MagicMock, client_with_exception: MagicMock,
appliance_ha_id: str, appliance: HomeAppliance,
device_registry: dr.DeviceRegistry, device_registry: dr.DeviceRegistry,
) -> None: ) -> None:
"""Raise a HomeAssistantError when there is an API error.""" """Raise a HomeAssistantError when there is an API error."""
@ -382,7 +387,7 @@ async def test_services_exception_device_id(
device_entry = device_registry.async_get_or_create( device_entry = device_registry.async_get_or_create(
config_entry_id=config_entry.entry_id, config_entry_id=config_entry.entry_id,
identifiers={(DOMAIN, appliance_ha_id)}, identifiers={(DOMAIN, appliance.ha_id)},
) )
service_call["service_data"]["device_id"] = device_entry.id service_call["service_data"]["device_id"] = device_entry.id
@ -434,6 +439,7 @@ async def test_services_appliance_not_found(
await hass.services.async_call(**service_call) await hass.services.async_call(**service_call)
@pytest.mark.parametrize("appliance", ["Washer"], indirect=True)
@pytest.mark.parametrize( @pytest.mark.parametrize(
"service_call", "service_call",
SERVICE_KV_CALL_PARAMS + SERVICE_COMMAND_CALL_PARAMS + SERVICE_PROGRAM_CALL_PARAMS, SERVICE_KV_CALL_PARAMS + SERVICE_COMMAND_CALL_PARAMS + SERVICE_PROGRAM_CALL_PARAMS,
@ -445,7 +451,7 @@ async def test_services_exception(
integration_setup: Callable[[MagicMock], Awaitable[bool]], integration_setup: Callable[[MagicMock], Awaitable[bool]],
setup_credentials: None, setup_credentials: None,
client_with_exception: MagicMock, client_with_exception: MagicMock,
appliance_ha_id: str, appliance: HomeAppliance,
device_registry: dr.DeviceRegistry, device_registry: dr.DeviceRegistry,
) -> None: ) -> None:
"""Raise a ValueError when device id does not match.""" """Raise a ValueError when device id does not match."""
@ -455,7 +461,7 @@ async def test_services_exception(
device_entry = device_registry.async_get_or_create( device_entry = device_registry.async_get_or_create(
config_entry_id=config_entry.entry_id, config_entry_id=config_entry.entry_id,
identifiers={(DOMAIN, appliance_ha_id)}, identifiers={(DOMAIN, appliance.ha_id)},
) )
service_call["service_data"]["device_id"] = device_entry.id service_call["service_data"]["device_id"] = device_entry.id

View File

@ -13,6 +13,7 @@ from aiohomeconnect.model import (
EventMessage, EventMessage,
EventType, EventType,
GetSetting, GetSetting,
HomeAppliance,
OptionKey, OptionKey,
ProgramDefinition, ProgramDefinition,
ProgramKey, ProgramKey,
@ -79,8 +80,9 @@ async def test_switches(
assert config_entry.state == ConfigEntryState.LOADED assert config_entry.state == ConfigEntryState.LOADED
@pytest.mark.parametrize("appliance", ["Washer"], indirect=True)
async def test_paired_depaired_devices_flow( async def test_paired_depaired_devices_flow(
appliance_ha_id: str, appliance: HomeAppliance,
hass: HomeAssistant, hass: HomeAssistant,
config_entry: MockConfigEntry, config_entry: MockConfigEntry,
integration_setup: Callable[[MagicMock], Awaitable[bool]], integration_setup: Callable[[MagicMock], Awaitable[bool]],
@ -105,7 +107,7 @@ async def test_paired_depaired_devices_flow(
assert await integration_setup(client) assert await integration_setup(client)
assert config_entry.state == ConfigEntryState.LOADED assert config_entry.state == ConfigEntryState.LOADED
device = device_registry.async_get_device(identifiers={(DOMAIN, appliance_ha_id)}) device = device_registry.async_get_device(identifiers={(DOMAIN, appliance.ha_id)})
assert device assert device
entity_entries = entity_registry.entities.get_entries_for_device_id(device.id) entity_entries = entity_registry.entities.get_entries_for_device_id(device.id)
assert entity_entries assert entity_entries
@ -113,7 +115,7 @@ async def test_paired_depaired_devices_flow(
await client.add_events( await client.add_events(
[ [
EventMessage( EventMessage(
appliance_ha_id, appliance.ha_id,
EventType.DEPAIRED, EventType.DEPAIRED,
data=ArrayOfEvents([]), data=ArrayOfEvents([]),
) )
@ -121,7 +123,7 @@ async def test_paired_depaired_devices_flow(
) )
await hass.async_block_till_done() await hass.async_block_till_done()
device = device_registry.async_get_device(identifiers={(DOMAIN, appliance_ha_id)}) device = device_registry.async_get_device(identifiers={(DOMAIN, appliance.ha_id)})
assert not device assert not device
for entity_entry in entity_entries: for entity_entry in entity_entries:
assert not entity_registry.async_get(entity_entry.entity_id) assert not entity_registry.async_get(entity_entry.entity_id)
@ -130,7 +132,7 @@ async def test_paired_depaired_devices_flow(
await client.add_events( await client.add_events(
[ [
EventMessage( EventMessage(
appliance_ha_id, appliance.ha_id,
EventType.PAIRED, EventType.PAIRED,
data=ArrayOfEvents([]), data=ArrayOfEvents([]),
) )
@ -138,13 +140,14 @@ async def test_paired_depaired_devices_flow(
) )
await hass.async_block_till_done() await hass.async_block_till_done()
assert device_registry.async_get_device(identifiers={(DOMAIN, appliance_ha_id)}) assert device_registry.async_get_device(identifiers={(DOMAIN, appliance.ha_id)})
for entity_entry in entity_entries: for entity_entry in entity_entries:
assert entity_registry.async_get(entity_entry.entity_id) assert entity_registry.async_get(entity_entry.entity_id)
@pytest.mark.parametrize("appliance", ["Washer"], indirect=True)
async def test_connected_devices( async def test_connected_devices(
appliance_ha_id: str, appliance: HomeAppliance,
hass: HomeAssistant, hass: HomeAssistant,
config_entry: MockConfigEntry, config_entry: MockConfigEntry,
integration_setup: Callable[[MagicMock], Awaitable[bool]], integration_setup: Callable[[MagicMock], Awaitable[bool]],
@ -162,14 +165,14 @@ async def test_connected_devices(
get_available_programs_mock = client.get_available_programs get_available_programs_mock = client.get_available_programs
async def get_settings_side_effect(ha_id: str): async def get_settings_side_effect(ha_id: str):
if ha_id == appliance_ha_id: if ha_id == appliance.ha_id:
raise HomeConnectApiError( raise HomeConnectApiError(
"SDK.Error.HomeAppliance.Connection.Initialization.Failed" "SDK.Error.HomeAppliance.Connection.Initialization.Failed"
) )
return await get_settings_original_mock.side_effect(ha_id) return await get_settings_original_mock.side_effect(ha_id)
async def get_available_programs_side_effect(ha_id: str): async def get_available_programs_side_effect(ha_id: str):
if ha_id == appliance_ha_id: if ha_id == appliance.ha_id:
raise HomeConnectApiError( raise HomeConnectApiError(
"SDK.Error.HomeAppliance.Connection.Initialization.Failed" "SDK.Error.HomeAppliance.Connection.Initialization.Failed"
) )
@ -185,14 +188,14 @@ async def test_connected_devices(
client.get_settings = get_settings_original_mock client.get_settings = get_settings_original_mock
client.get_available_programs = get_available_programs_mock client.get_available_programs = get_available_programs_mock
device = device_registry.async_get_device(identifiers={(DOMAIN, appliance_ha_id)}) device = device_registry.async_get_device(identifiers={(DOMAIN, appliance.ha_id)})
assert device assert device
entity_entries = entity_registry.entities.get_entries_for_device_id(device.id) entity_entries = entity_registry.entities.get_entries_for_device_id(device.id)
await client.add_events( await client.add_events(
[ [
EventMessage( EventMessage(
appliance_ha_id, appliance.ha_id,
EventType.CONNECTED, EventType.CONNECTED,
data=ArrayOfEvents([]), data=ArrayOfEvents([]),
) )
@ -200,20 +203,20 @@ async def test_connected_devices(
) )
await hass.async_block_till_done() await hass.async_block_till_done()
device = device_registry.async_get_device(identifiers={(DOMAIN, appliance_ha_id)}) device = device_registry.async_get_device(identifiers={(DOMAIN, appliance.ha_id)})
assert device assert device
new_entity_entries = entity_registry.entities.get_entries_for_device_id(device.id) new_entity_entries = entity_registry.entities.get_entries_for_device_id(device.id)
assert len(new_entity_entries) > len(entity_entries) assert len(new_entity_entries) > len(entity_entries)
@pytest.mark.parametrize("appliance_ha_id", ["Dishwasher"], indirect=True) @pytest.mark.parametrize("appliance", ["Dishwasher"], indirect=True)
async def test_switch_entity_availabilty( async def test_switch_entity_availability(
hass: HomeAssistant, hass: HomeAssistant,
config_entry: MockConfigEntry, config_entry: MockConfigEntry,
integration_setup: Callable[[MagicMock], Awaitable[bool]], integration_setup: Callable[[MagicMock], Awaitable[bool]],
setup_credentials: None, setup_credentials: None,
client: MagicMock, client: MagicMock,
appliance_ha_id: str, appliance: HomeAppliance,
) -> None: ) -> None:
"""Test if switch entities availability are based on the appliance connection state.""" """Test if switch entities availability are based on the appliance connection state."""
entity_ids = [ entity_ids = [
@ -233,7 +236,7 @@ async def test_switch_entity_availabilty(
await client.add_events( await client.add_events(
[ [
EventMessage( EventMessage(
appliance_ha_id, appliance.ha_id,
EventType.DISCONNECTED, EventType.DISCONNECTED,
ArrayOfEvents([]), ArrayOfEvents([]),
) )
@ -247,7 +250,7 @@ async def test_switch_entity_availabilty(
await client.add_events( await client.add_events(
[ [
EventMessage( EventMessage(
appliance_ha_id, appliance.ha_id,
EventType.CONNECTED, EventType.CONNECTED,
ArrayOfEvents([]), ArrayOfEvents([]),
) )
@ -268,7 +271,7 @@ async def test_switch_entity_availabilty(
"settings_key_arg", "settings_key_arg",
"setting_value_arg", "setting_value_arg",
"state", "state",
"appliance_ha_id", "appliance",
), ),
[ [
( (
@ -288,7 +291,7 @@ async def test_switch_entity_availabilty(
"Dishwasher", "Dishwasher",
), ),
], ],
indirect=["appliance_ha_id"], indirect=["appliance"],
) )
async def test_switch_functionality( async def test_switch_functionality(
entity_id: str, entity_id: str,
@ -300,7 +303,7 @@ async def test_switch_functionality(
config_entry: MockConfigEntry, config_entry: MockConfigEntry,
integration_setup: Callable[[MagicMock], Awaitable[bool]], integration_setup: Callable[[MagicMock], Awaitable[bool]],
setup_credentials: None, setup_credentials: None,
appliance_ha_id: str, appliance: HomeAppliance,
client: MagicMock, client: MagicMock,
) -> None: ) -> None:
"""Test switch functionality.""" """Test switch functionality."""
@ -312,13 +315,13 @@ async def test_switch_functionality(
await hass.services.async_call(SWITCH_DOMAIN, service, {ATTR_ENTITY_ID: entity_id}) await hass.services.async_call(SWITCH_DOMAIN, service, {ATTR_ENTITY_ID: entity_id})
await hass.async_block_till_done() await hass.async_block_till_done()
client.set_setting.assert_awaited_once_with( client.set_setting.assert_awaited_once_with(
appliance_ha_id, setting_key=settings_key_arg, value=setting_value_arg appliance.ha_id, setting_key=settings_key_arg, value=setting_value_arg
) )
assert hass.states.is_state(entity_id, state) assert hass.states.is_state(entity_id, state)
@pytest.mark.parametrize( @pytest.mark.parametrize(
("entity_id", "program_key", "initial_state", "appliance_ha_id"), ("entity_id", "program_key", "initial_state", "appliance"),
[ [
( (
"switch.dryer_program_mix", "switch.dryer_program_mix",
@ -333,7 +336,7 @@ async def test_switch_functionality(
"Dryer", "Dryer",
), ),
], ],
indirect=["appliance_ha_id"], indirect=["appliance"],
) )
async def test_program_switch_functionality( async def test_program_switch_functionality(
entity_id: str, entity_id: str,
@ -343,7 +346,7 @@ async def test_program_switch_functionality(
config_entry: MockConfigEntry, config_entry: MockConfigEntry,
integration_setup: Callable[[MagicMock], Awaitable[bool]], integration_setup: Callable[[MagicMock], Awaitable[bool]],
setup_credentials: None, setup_credentials: None,
appliance_ha_id: str, appliance: HomeAppliance,
client: MagicMock, client: MagicMock,
) -> None: ) -> None:
"""Test switch functionality.""" """Test switch functionality."""
@ -383,7 +386,7 @@ async def test_program_switch_functionality(
await hass.async_block_till_done() await hass.async_block_till_done()
assert hass.states.is_state(entity_id, STATE_ON) assert hass.states.is_state(entity_id, STATE_ON)
client.start_program.assert_awaited_once_with( client.start_program.assert_awaited_once_with(
appliance_ha_id, program_key=program_key appliance.ha_id, program_key=program_key
) )
await hass.services.async_call( await hass.services.async_call(
@ -391,7 +394,7 @@ async def test_program_switch_functionality(
) )
await hass.async_block_till_done() await hass.async_block_till_done()
assert hass.states.is_state(entity_id, STATE_OFF) assert hass.states.is_state(entity_id, STATE_OFF)
client.stop_program.assert_awaited_once_with(appliance_ha_id) client.stop_program.assert_awaited_once_with(appliance.ha_id)
@pytest.mark.parametrize( @pytest.mark.parametrize(
@ -496,7 +499,7 @@ async def test_switch_exception_handling(
@pytest.mark.parametrize( @pytest.mark.parametrize(
("entity_id", "status", "service", "state", "appliance_ha_id"), ("entity_id", "status", "service", "state", "appliance"),
[ [
( (
"switch.fridgefreezer_freezer_super_mode", "switch.fridgefreezer_freezer_super_mode",
@ -513,7 +516,7 @@ async def test_switch_exception_handling(
"FridgeFreezer", "FridgeFreezer",
), ),
], ],
indirect=["appliance_ha_id"], indirect=["appliance"],
) )
async def test_ent_desc_switch_functionality( async def test_ent_desc_switch_functionality(
entity_id: str, entity_id: str,
@ -524,7 +527,7 @@ async def test_ent_desc_switch_functionality(
config_entry: MockConfigEntry, config_entry: MockConfigEntry,
integration_setup: Callable[[MagicMock], Awaitable[bool]], integration_setup: Callable[[MagicMock], Awaitable[bool]],
setup_credentials: None, setup_credentials: None,
appliance_ha_id: str, appliance: HomeAppliance,
client: MagicMock, client: MagicMock,
) -> None: ) -> None:
"""Test switch functionality - entity description setup.""" """Test switch functionality - entity description setup."""
@ -544,7 +547,7 @@ async def test_ent_desc_switch_functionality(
"status", "status",
"service", "service",
"mock_attr", "mock_attr",
"appliance_ha_id", "appliance",
"exception_match", "exception_match",
), ),
[ [
@ -565,7 +568,7 @@ async def test_ent_desc_switch_functionality(
r"Error.*turn.*off.*", r"Error.*turn.*off.*",
), ),
], ],
indirect=["appliance_ha_id"], indirect=["appliance"],
) )
async def test_ent_desc_switch_exception_handling( async def test_ent_desc_switch_exception_handling(
entity_id: str, entity_id: str,
@ -577,7 +580,7 @@ async def test_ent_desc_switch_exception_handling(
integration_setup: Callable[[MagicMock], Awaitable[bool]], integration_setup: Callable[[MagicMock], Awaitable[bool]],
config_entry: MockConfigEntry, config_entry: MockConfigEntry,
setup_credentials: None, setup_credentials: None,
appliance_ha_id: str, appliance: HomeAppliance,
client_with_exception: MagicMock, client_with_exception: MagicMock,
) -> None: ) -> None:
"""Test switch exception handling - entity description setup.""" """Test switch exception handling - entity description setup."""
@ -613,7 +616,7 @@ async def test_ent_desc_switch_exception_handling(
"service", "service",
"setting_value_arg", "setting_value_arg",
"power_state", "power_state",
"appliance_ha_id", "appliance",
), ),
[ [
( (
@ -649,9 +652,9 @@ async def test_ent_desc_switch_exception_handling(
"Dishwasher", "Dishwasher",
), ),
], ],
indirect=["appliance_ha_id"], indirect=["appliance"],
) )
async def test_power_swtich( async def test_power_switch(
entity_id: str, entity_id: str,
allowed_values: list[str | None] | None, allowed_values: list[str | None] | None,
service: str, service: str,
@ -661,7 +664,7 @@ async def test_power_swtich(
config_entry: MockConfigEntry, config_entry: MockConfigEntry,
integration_setup: Callable[[MagicMock], Awaitable[bool]], integration_setup: Callable[[MagicMock], Awaitable[bool]],
setup_credentials: None, setup_credentials: None,
appliance_ha_id: str, appliance: HomeAppliance,
client: MagicMock, client: MagicMock,
) -> None: ) -> None:
"""Test power switch functionality.""" """Test power switch functionality."""
@ -686,7 +689,7 @@ async def test_power_swtich(
await hass.services.async_call(SWITCH_DOMAIN, service, {ATTR_ENTITY_ID: entity_id}) await hass.services.async_call(SWITCH_DOMAIN, service, {ATTR_ENTITY_ID: entity_id})
await hass.async_block_till_done() await hass.async_block_till_done()
client.set_setting.assert_awaited_once_with( client.set_setting.assert_awaited_once_with(
appliance_ha_id, appliance.ha_id,
setting_key=SettingKey.BSH_COMMON_POWER_STATE, setting_key=SettingKey.BSH_COMMON_POWER_STATE,
value=setting_value_arg, value=setting_value_arg,
) )
@ -800,7 +803,7 @@ async def test_power_switch_service_validation_errors(
@pytest.mark.usefixtures("entity_registry_enabled_by_default") @pytest.mark.usefixtures("entity_registry_enabled_by_default")
async def test_create_issue( async def test_create_issue(
hass: HomeAssistant, hass: HomeAssistant,
appliance_ha_id: str, appliance: HomeAppliance,
config_entry: MockConfigEntry, config_entry: MockConfigEntry,
integration_setup: Callable[[MagicMock], Awaitable[bool]], integration_setup: Callable[[MagicMock], Awaitable[bool]],
setup_credentials: None, setup_credentials: None,
@ -882,7 +885,7 @@ async def test_create_issue(
], ],
) )
@pytest.mark.parametrize( @pytest.mark.parametrize(
("entity_id", "option_key", "appliance_ha_id"), ("entity_id", "option_key", "appliance"),
[ [
( (
"switch.dishwasher_half_load", "switch.dishwasher_half_load",
@ -890,12 +893,12 @@ async def test_create_issue(
"Dishwasher", "Dishwasher",
) )
], ],
indirect=["appliance_ha_id"], indirect=["appliance"],
) )
async def test_options_functionality( async def test_options_functionality(
entity_id: str, entity_id: str,
option_key: OptionKey, option_key: OptionKey,
appliance_ha_id: str, appliance: HomeAppliance,
set_active_program_options_side_effect: ActiveProgramNotSetError | None, set_active_program_options_side_effect: ActiveProgramNotSetError | None,
set_selected_program_options_side_effect: SelectedProgramNotSetError | None, set_selected_program_options_side_effect: SelectedProgramNotSetError | None,
called_mock_method: str, called_mock_method: str,
@ -933,7 +936,7 @@ async def test_options_functionality(
await hass.async_block_till_done() await hass.async_block_till_done()
assert called_mock.called assert called_mock.called
assert called_mock.call_args.args == (appliance_ha_id,) assert called_mock.call_args.args == (appliance.ha_id,)
assert called_mock.call_args.kwargs == { assert called_mock.call_args.kwargs == {
"option_key": option_key, "option_key": option_key,
"value": False, "value": False,
@ -946,7 +949,7 @@ async def test_options_functionality(
await hass.async_block_till_done() await hass.async_block_till_done()
assert called_mock.called assert called_mock.called
assert called_mock.call_args.args == (appliance_ha_id,) assert called_mock.call_args.args == (appliance.ha_id,)
assert called_mock.call_args.kwargs == { assert called_mock.call_args.kwargs == {
"option_key": option_key, "option_key": option_key,
"value": True, "value": True,

View File

@ -10,6 +10,7 @@ from aiohomeconnect.model import (
EventMessage, EventMessage,
EventType, EventType,
GetSetting, GetSetting,
HomeAppliance,
SettingKey, SettingKey,
) )
from aiohomeconnect.model.error import HomeConnectApiError, HomeConnectError from aiohomeconnect.model.error import HomeConnectApiError, HomeConnectError
@ -44,9 +45,9 @@ async def test_time(
assert config_entry.state is ConfigEntryState.LOADED assert config_entry.state is ConfigEntryState.LOADED
@pytest.mark.parametrize("appliance_ha_id", ["Oven"], indirect=True) @pytest.mark.parametrize("appliance", ["Oven"], indirect=True)
async def test_paired_depaired_devices_flow( async def test_paired_depaired_devices_flow(
appliance_ha_id: str, appliance: HomeAppliance,
hass: HomeAssistant, hass: HomeAssistant,
config_entry: MockConfigEntry, config_entry: MockConfigEntry,
integration_setup: Callable[[MagicMock], Awaitable[bool]], integration_setup: Callable[[MagicMock], Awaitable[bool]],
@ -60,7 +61,7 @@ async def test_paired_depaired_devices_flow(
assert await integration_setup(client) assert await integration_setup(client)
assert config_entry.state == ConfigEntryState.LOADED assert config_entry.state == ConfigEntryState.LOADED
device = device_registry.async_get_device(identifiers={(DOMAIN, appliance_ha_id)}) device = device_registry.async_get_device(identifiers={(DOMAIN, appliance.ha_id)})
assert device assert device
entity_entries = entity_registry.entities.get_entries_for_device_id(device.id) entity_entries = entity_registry.entities.get_entries_for_device_id(device.id)
assert entity_entries assert entity_entries
@ -68,7 +69,7 @@ async def test_paired_depaired_devices_flow(
await client.add_events( await client.add_events(
[ [
EventMessage( EventMessage(
appliance_ha_id, appliance.ha_id,
EventType.DEPAIRED, EventType.DEPAIRED,
data=ArrayOfEvents([]), data=ArrayOfEvents([]),
) )
@ -76,7 +77,7 @@ async def test_paired_depaired_devices_flow(
) )
await hass.async_block_till_done() await hass.async_block_till_done()
device = device_registry.async_get_device(identifiers={(DOMAIN, appliance_ha_id)}) device = device_registry.async_get_device(identifiers={(DOMAIN, appliance.ha_id)})
assert not device assert not device
for entity_entry in entity_entries: for entity_entry in entity_entries:
assert not entity_registry.async_get(entity_entry.entity_id) assert not entity_registry.async_get(entity_entry.entity_id)
@ -85,7 +86,7 @@ async def test_paired_depaired_devices_flow(
await client.add_events( await client.add_events(
[ [
EventMessage( EventMessage(
appliance_ha_id, appliance.ha_id,
EventType.PAIRED, EventType.PAIRED,
data=ArrayOfEvents([]), data=ArrayOfEvents([]),
) )
@ -93,14 +94,14 @@ async def test_paired_depaired_devices_flow(
) )
await hass.async_block_till_done() await hass.async_block_till_done()
assert device_registry.async_get_device(identifiers={(DOMAIN, appliance_ha_id)}) assert device_registry.async_get_device(identifiers={(DOMAIN, appliance.ha_id)})
for entity_entry in entity_entries: for entity_entry in entity_entries:
assert entity_registry.async_get(entity_entry.entity_id) assert entity_registry.async_get(entity_entry.entity_id)
@pytest.mark.parametrize("appliance_ha_id", ["Oven"], indirect=True) @pytest.mark.parametrize("appliance", ["Oven"], indirect=True)
async def test_connected_devices( async def test_connected_devices(
appliance_ha_id: str, appliance: HomeAppliance,
hass: HomeAssistant, hass: HomeAssistant,
config_entry: MockConfigEntry, config_entry: MockConfigEntry,
integration_setup: Callable[[MagicMock], Awaitable[bool]], integration_setup: Callable[[MagicMock], Awaitable[bool]],
@ -117,7 +118,7 @@ async def test_connected_devices(
get_settings_original_mock = client.get_settings get_settings_original_mock = client.get_settings
async def get_settings_side_effect(ha_id: str): async def get_settings_side_effect(ha_id: str):
if ha_id == appliance_ha_id: if ha_id == appliance.ha_id:
raise HomeConnectApiError( raise HomeConnectApiError(
"SDK.Error.HomeAppliance.Connection.Initialization.Failed" "SDK.Error.HomeAppliance.Connection.Initialization.Failed"
) )
@ -129,14 +130,14 @@ async def test_connected_devices(
assert config_entry.state == ConfigEntryState.LOADED assert config_entry.state == ConfigEntryState.LOADED
client.get_settings = get_settings_original_mock client.get_settings = get_settings_original_mock
device = device_registry.async_get_device(identifiers={(DOMAIN, appliance_ha_id)}) device = device_registry.async_get_device(identifiers={(DOMAIN, appliance.ha_id)})
assert device assert device
entity_entries = entity_registry.entities.get_entries_for_device_id(device.id) entity_entries = entity_registry.entities.get_entries_for_device_id(device.id)
await client.add_events( await client.add_events(
[ [
EventMessage( EventMessage(
appliance_ha_id, appliance.ha_id,
EventType.CONNECTED, EventType.CONNECTED,
data=ArrayOfEvents([]), data=ArrayOfEvents([]),
) )
@ -144,20 +145,20 @@ async def test_connected_devices(
) )
await hass.async_block_till_done() await hass.async_block_till_done()
device = device_registry.async_get_device(identifiers={(DOMAIN, appliance_ha_id)}) device = device_registry.async_get_device(identifiers={(DOMAIN, appliance.ha_id)})
assert device assert device
new_entity_entries = entity_registry.entities.get_entries_for_device_id(device.id) new_entity_entries = entity_registry.entities.get_entries_for_device_id(device.id)
assert len(new_entity_entries) > len(entity_entries) assert len(new_entity_entries) > len(entity_entries)
@pytest.mark.parametrize("appliance_ha_id", ["Oven"], indirect=True) @pytest.mark.parametrize("appliance", ["Oven"], indirect=True)
async def test_time_entity_availabilty( async def test_time_entity_availability(
hass: HomeAssistant, hass: HomeAssistant,
config_entry: MockConfigEntry, config_entry: MockConfigEntry,
integration_setup: Callable[[MagicMock], Awaitable[bool]], integration_setup: Callable[[MagicMock], Awaitable[bool]],
setup_credentials: None, setup_credentials: None,
client: MagicMock, client: MagicMock,
appliance_ha_id: str, appliance: HomeAppliance,
) -> None: ) -> None:
"""Test if time entities availability are based on the appliance connection state.""" """Test if time entities availability are based on the appliance connection state."""
entity_ids = [ entity_ids = [
@ -175,7 +176,7 @@ async def test_time_entity_availabilty(
await client.add_events( await client.add_events(
[ [
EventMessage( EventMessage(
appliance_ha_id, appliance.ha_id,
EventType.DISCONNECTED, EventType.DISCONNECTED,
ArrayOfEvents([]), ArrayOfEvents([]),
) )
@ -189,7 +190,7 @@ async def test_time_entity_availabilty(
await client.add_events( await client.add_events(
[ [
EventMessage( EventMessage(
appliance_ha_id, appliance.ha_id,
EventType.CONNECTED, EventType.CONNECTED,
ArrayOfEvents([]), ArrayOfEvents([]),
) )
@ -203,7 +204,7 @@ async def test_time_entity_availabilty(
assert state.state != STATE_UNAVAILABLE assert state.state != STATE_UNAVAILABLE
@pytest.mark.parametrize("appliance_ha_id", ["Oven"], indirect=True) @pytest.mark.parametrize("appliance", ["Oven"], indirect=True)
@pytest.mark.parametrize( @pytest.mark.parametrize(
("entity_id", "setting_key"), ("entity_id", "setting_key"),
[ [
@ -214,7 +215,7 @@ async def test_time_entity_availabilty(
], ],
) )
async def test_time_entity_functionality( async def test_time_entity_functionality(
appliance_ha_id: str, appliance: HomeAppliance,
entity_id: str, entity_id: str,
setting_key: SettingKey, setting_key: SettingKey,
hass: HomeAssistant, hass: HomeAssistant,
@ -242,7 +243,7 @@ async def test_time_entity_functionality(
) )
await hass.async_block_till_done() await hass.async_block_till_done()
client.set_setting.assert_awaited_once_with( client.set_setting.assert_awaited_once_with(
appliance_ha_id, setting_key=setting_key, value=value appliance.ha_id, setting_key=setting_key, value=value
) )
assert hass.states.is_state(entity_id, str(time(second=value))) assert hass.states.is_state(entity_id, str(time(second=value)))