Skip to content

Commit 1b7e53f

Browse files
MartinHjelmarefrenck
authored andcommitted
Improve Home Connect appliances test fixture (#139787)
Improve Home Connect appliances fixture
1 parent bfabf97 commit 1b7e53f

File tree

4 files changed

+267
-225
lines changed

4 files changed

+267
-225
lines changed

tests/components/home_connect/__init__.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,10 @@
22

33
from typing import Any
44

5-
from aiohomeconnect.model import ArrayOfHomeAppliances, ArrayOfStatus
5+
from aiohomeconnect.model import ArrayOfStatus
66

77
from tests.common import load_json_object_fixture
88

9-
MOCK_APPLIANCES = ArrayOfHomeAppliances.from_dict(
10-
load_json_object_fixture("home_connect/appliances.json")["data"] # type: ignore[arg-type]
11-
)
129
MOCK_PROGRAMS: dict[str, Any] = load_json_object_fixture("home_connect/programs.json")
1310
MOCK_SETTINGS: dict[str, Any] = load_json_object_fixture("home_connect/settings.json")
1411
MOCK_STATUS = ArrayOfStatus.from_dict(

tests/components/home_connect/conftest.py

Lines changed: 124 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from aiohomeconnect.model import (
1212
ArrayOfCommands,
1313
ArrayOfEvents,
14+
ArrayOfHomeAppliances,
1415
ArrayOfOptions,
1516
ArrayOfPrograms,
1617
ArrayOfSettings,
@@ -39,15 +40,9 @@
3940
from homeassistant.core import HomeAssistant
4041
from homeassistant.setup import async_setup_component
4142

42-
from . import (
43-
MOCK_APPLIANCES,
44-
MOCK_AVAILABLE_COMMANDS,
45-
MOCK_PROGRAMS,
46-
MOCK_SETTINGS,
47-
MOCK_STATUS,
48-
)
43+
from . import MOCK_AVAILABLE_COMMANDS, MOCK_PROGRAMS, MOCK_SETTINGS, MOCK_STATUS
4944

50-
from tests.common import MockConfigEntry
45+
from tests.common import MockConfigEntry, load_fixture
5146

5247
CLIENT_ID = "1234"
5348
CLIENT_SECRET = "5678"
@@ -148,14 +143,6 @@ async def run(client: MagicMock) -> bool:
148143
return run
149144

150145

151-
def _get_specific_appliance_side_effect(ha_id: str) -> HomeAppliance:
152-
"""Get specific appliance side effect."""
153-
for appliance in copy.deepcopy(MOCK_APPLIANCES).homeappliances:
154-
if appliance.ha_id == ha_id:
155-
return appliance
156-
raise HomeConnectApiError("error.key", "error description")
157-
158-
159146
def _get_set_program_side_effect(
160147
event_queue: asyncio.Queue[list[EventMessage]], event_key: EventKey
161148
):
@@ -271,68 +258,12 @@ async def set_program_options_side_effect(ha_id: str, *_, **kwargs) -> None:
271258
return set_program_options_side_effect
272259

273260

274-
async def _get_all_programs_side_effect(ha_id: str) -> ArrayOfPrograms:
275-
"""Get all programs."""
276-
appliance_type = next(
277-
appliance
278-
for appliance in MOCK_APPLIANCES.homeappliances
279-
if appliance.ha_id == ha_id
280-
).type
281-
if appliance_type not in MOCK_PROGRAMS:
282-
raise HomeConnectApiError("error.key", "error description")
283-
284-
return ArrayOfPrograms(
285-
[
286-
EnumerateProgram.from_dict(program)
287-
for program in MOCK_PROGRAMS[appliance_type]["data"]["programs"]
288-
],
289-
Program.from_dict(MOCK_PROGRAMS[appliance_type]["data"]["programs"][0]),
290-
Program.from_dict(MOCK_PROGRAMS[appliance_type]["data"]["programs"][0]),
291-
)
292-
293-
294-
async def _get_settings_side_effect(ha_id: str) -> ArrayOfSettings:
295-
"""Get settings."""
296-
return ArrayOfSettings.from_dict(
297-
MOCK_SETTINGS.get(
298-
next(
299-
appliance
300-
for appliance in MOCK_APPLIANCES.homeappliances
301-
if appliance.ha_id == ha_id
302-
).type,
303-
{},
304-
).get("data", {"settings": []})
305-
)
306-
307-
308-
async def _get_setting_side_effect(ha_id: str, setting_key: SettingKey):
309-
"""Get setting."""
310-
for appliance in MOCK_APPLIANCES.homeappliances:
311-
if appliance.ha_id == ha_id:
312-
settings = MOCK_SETTINGS.get(
313-
next(
314-
appliance
315-
for appliance in MOCK_APPLIANCES.homeappliances
316-
if appliance.ha_id == ha_id
317-
).type,
318-
{},
319-
).get("data", {"settings": []})
320-
for setting_dict in cast(list[dict], settings["settings"]):
321-
if setting_dict["key"] == setting_key:
322-
return GetSetting.from_dict(setting_dict)
323-
raise HomeConnectApiError("error.key", "error description")
324-
325-
326-
async def _get_available_commands_side_effect(ha_id: str) -> ArrayOfCommands:
327-
"""Get available commands."""
328-
for appliance in MOCK_APPLIANCES.homeappliances:
329-
if appliance.ha_id == ha_id and appliance.type in MOCK_AVAILABLE_COMMANDS:
330-
return ArrayOfCommands.from_dict(MOCK_AVAILABLE_COMMANDS[appliance.type])
331-
raise HomeConnectApiError("error.key", "error description")
332-
333-
334261
@pytest.fixture(name="client")
335-
def mock_client(request: pytest.FixtureRequest) -> MagicMock:
262+
def mock_client(
263+
appliances: list[HomeAppliance],
264+
appliance: HomeAppliance | None,
265+
request: pytest.FixtureRequest,
266+
) -> MagicMock:
336267
"""Fixture to mock Client from HomeConnect."""
337268

338269
mock = MagicMock(
@@ -369,17 +300,78 @@ async def set_program_option_side_effect(ha_id: str, *_, **kwargs) -> None:
369300
]
370301
)
371302

303+
appliances = [appliance] if appliance else appliances
304+
372305
async def stream_all_events() -> AsyncGenerator[EventMessage]:
373306
"""Mock stream_all_events."""
374307
while True:
375308
for event in await event_queue.get():
376309
yield event
377310

378-
mock.get_home_appliances = AsyncMock(return_value=copy.deepcopy(MOCK_APPLIANCES))
311+
mock.get_home_appliances = AsyncMock(return_value=ArrayOfHomeAppliances(appliances))
312+
313+
def _get_specific_appliance_side_effect(ha_id: str) -> HomeAppliance:
314+
"""Get specific appliance side effect."""
315+
for appliance_ in appliances:
316+
if appliance_.ha_id == ha_id:
317+
return appliance_
318+
raise HomeConnectApiError("error.key", "error description")
319+
379320
mock.get_specific_appliance = AsyncMock(
380321
side_effect=_get_specific_appliance_side_effect
381322
)
382323
mock.stream_all_events = stream_all_events
324+
325+
async def _get_all_programs_side_effect(ha_id: str) -> ArrayOfPrograms:
326+
"""Get all programs."""
327+
appliance_type = next(
328+
appliance for appliance in appliances if appliance.ha_id == ha_id
329+
).type
330+
if appliance_type not in MOCK_PROGRAMS:
331+
raise HomeConnectApiError("error.key", "error description")
332+
333+
return ArrayOfPrograms(
334+
[
335+
EnumerateProgram.from_dict(program)
336+
for program in MOCK_PROGRAMS[appliance_type]["data"]["programs"]
337+
],
338+
Program.from_dict(MOCK_PROGRAMS[appliance_type]["data"]["programs"][0]),
339+
Program.from_dict(MOCK_PROGRAMS[appliance_type]["data"]["programs"][0]),
340+
)
341+
342+
async def _get_settings_side_effect(ha_id: str) -> ArrayOfSettings:
343+
"""Get settings."""
344+
return ArrayOfSettings.from_dict(
345+
MOCK_SETTINGS.get(
346+
next(
347+
appliance for appliance in appliances if appliance.ha_id == ha_id
348+
).type,
349+
{},
350+
).get("data", {"settings": []})
351+
)
352+
353+
async def _get_setting_side_effect(ha_id: str, setting_key: SettingKey):
354+
"""Get setting."""
355+
for appliance_ in appliances:
356+
if appliance_.ha_id == ha_id:
357+
settings = MOCK_SETTINGS.get(
358+
appliance_.type,
359+
{},
360+
).get("data", {"settings": []})
361+
for setting_dict in cast(list[dict], settings["settings"]):
362+
if setting_dict["key"] == setting_key:
363+
return GetSetting.from_dict(setting_dict)
364+
raise HomeConnectApiError("error.key", "error description")
365+
366+
async def _get_available_commands_side_effect(ha_id: str) -> ArrayOfCommands:
367+
"""Get available commands."""
368+
for appliance_ in appliances:
369+
if appliance_.ha_id == ha_id and appliance_.type in MOCK_AVAILABLE_COMMANDS:
370+
return ArrayOfCommands.from_dict(
371+
MOCK_AVAILABLE_COMMANDS[appliance_.type]
372+
)
373+
raise HomeConnectApiError("error.key", "error description")
374+
383375
mock.start_program = AsyncMock(
384376
side_effect=_get_set_program_side_effect(
385377
event_queue, EventKey.BSH_COMMON_ROOT_ACTIVE_PROGRAM
@@ -431,7 +423,11 @@ async def stream_all_events() -> AsyncGenerator[EventMessage]:
431423

432424

433425
@pytest.fixture(name="client_with_exception")
434-
def mock_client_with_exception(request: pytest.FixtureRequest) -> MagicMock:
426+
def mock_client_with_exception(
427+
appliances: list[HomeAppliance],
428+
appliance: HomeAppliance | None,
429+
request: pytest.FixtureRequest,
430+
) -> MagicMock:
435431
"""Fixture to mock Client from HomeConnect that raise exceptions."""
436432
mock = MagicMock(
437433
autospec=HomeConnectClient,
@@ -449,7 +445,8 @@ async def stream_all_events() -> AsyncGenerator[EventMessage]:
449445
for event in await event_queue.get():
450446
yield event
451447

452-
mock.get_home_appliances = AsyncMock(return_value=copy.deepcopy(MOCK_APPLIANCES))
448+
appliances = [appliance] if appliance else appliances
449+
mock.get_home_appliances = AsyncMock(return_value=ArrayOfHomeAppliances(appliances))
453450
mock.stream_all_events = stream_all_events
454451

455452
mock.start_program = AsyncMock(side_effect=exception)
@@ -477,12 +474,52 @@ async def stream_all_events() -> AsyncGenerator[EventMessage]:
477474

478475

479476
@pytest.fixture(name="appliance_ha_id")
480-
def mock_appliance_ha_id(request: pytest.FixtureRequest) -> str:
481-
"""Fixture to mock Appliance."""
482-
app = "Washer"
477+
def mock_appliance_ha_id(
478+
appliances: list[HomeAppliance], request: pytest.FixtureRequest
479+
) -> str:
480+
"""Fixture to get the ha_id of an appliance."""
481+
appliance_type = "Washer"
483482
if hasattr(request, "param") and request.param:
484-
app = request.param
485-
for appliance in MOCK_APPLIANCES.homeappliances:
486-
if appliance.type == app:
483+
appliance_type = request.param
484+
for appliance in appliances:
485+
if appliance.type == appliance_type:
487486
return appliance.ha_id
488-
raise ValueError(f"Appliance {app} not found")
487+
raise ValueError(f"Appliance {appliance_type} not found")
488+
489+
490+
@pytest.fixture(name="appliances")
491+
def mock_appliances(
492+
appliances_data: str, request: pytest.FixtureRequest
493+
) -> list[HomeAppliance]:
494+
"""Fixture to mock the returned appliances."""
495+
appliances = ArrayOfHomeAppliances.from_json(appliances_data).homeappliances
496+
appliance_types = {appliance.type for appliance in appliances}
497+
if hasattr(request, "param") and request.param:
498+
appliance_types = request.param
499+
return [appliance for appliance in appliances if appliance.type in appliance_types]
500+
501+
502+
@pytest.fixture(name="appliance")
503+
def mock_appliance(
504+
appliances_data: str, request: pytest.FixtureRequest
505+
) -> HomeAppliance | None:
506+
"""Fixture to mock a single specific appliance to return."""
507+
appliance_type = None
508+
if hasattr(request, "param") and request.param:
509+
appliance_type = request.param
510+
return next(
511+
(
512+
appliance
513+
for appliance in ArrayOfHomeAppliances.from_json(
514+
appliances_data
515+
).homeappliances
516+
if appliance.type == appliance_type
517+
),
518+
None,
519+
)
520+
521+
522+
@pytest.fixture(name="appliances_data")
523+
def appliances_data_fixture() -> str:
524+
"""Fixture to return a the string for an array of appliances."""
525+
return load_fixture("appliances.json", integration=DOMAIN)

0 commit comments

Comments
 (0)