Prechádzať zdrojové kódy

Fix test patching: wrap hass service calls in _async_call_service; fix SelectSelector validation in config flow test

ZiB 4 mesiacov pred
rodič
commit
c6c3cfa7db

+ 6 - 6
custom_components/room_cal_ha/coordinator.py

@@ -247,6 +247,9 @@ class RoomCalCoordinator(DataUpdateCoordinator[CoordinatorData]):
     await self._async_set_room_state(False)
     _LOGGER.info("Check-out complete: guest=%s", res.guest_name)
 
+  async def _async_call_service(self, domain: str, service: str, data: dict) -> None:
+    await self.hass.services.async_call(domain, service, data, blocking=True)
+
   def _zlock_entity_ids(self) -> list[str]:
     """Return all lock entity IDs from the configured zlock_slots entries."""
     entity_ids: list[str] = []
@@ -265,15 +268,13 @@ class RoomCalCoordinator(DataUpdateCoordinator[CoordinatorData]):
     slot = int(slot)
     for entity_id in lock_entity_ids:
       try:
-        await self.hass.services.async_call(
+        await self._async_call_service(
           "zlock_slots", "set_code",
           {"lock_entity_id": entity_id, "slot": slot, "code": code},
-          blocking=True,
         )
-        await self.hass.services.async_call(
+        await self._async_call_service(
           "zlock_slots", "set_slot_enabled",
           {"lock_entity_id": entity_id, "slot": slot, "enabled": True},
-          blocking=True,
         )
         _LOGGER.info("Lock enabled: %s slot %s", entity_id, slot)
       except Exception as err:
@@ -288,10 +289,9 @@ class RoomCalCoordinator(DataUpdateCoordinator[CoordinatorData]):
     slot = int(slot)
     for entity_id in lock_entity_ids:
       try:
-        await self.hass.services.async_call(
+        await self._async_call_service(
           "zlock_slots", "set_slot_enabled",
           {"lock_entity_id": entity_id, "slot": slot, "enabled": False},
-          blocking=True,
         )
         _LOGGER.info("Lock disabled: %s slot %s", entity_id, slot)
       except Exception as err:

+ 8 - 2
tests/test_config_flow.py

@@ -3,6 +3,7 @@ from unittest.mock import AsyncMock, patch
 import pytest
 import caldav.lib.error as caldav_error
 from homeassistant.config_entries import SOURCE_USER
+from pytest_homeassistant_custom_component.common import MockConfigEntry
 from homeassistant.core import HomeAssistant
 
 from custom_components.room_cal_ha.const import (
@@ -389,14 +390,19 @@ async def test_options_locks_step_shows_form(hass: HomeAssistant, mock_entry):
 
 
 async def test_options_locks_saves_entities_and_slot(hass: HomeAssistant, mock_entry):
+  z1 = MockConfigEntry(domain="zlock_slots", title="Front Lock", data={"lock_entity_ids": ["lock.front"]})
+  z2 = MockConfigEntry(domain="zlock_slots", title="Back Lock", data={"lock_entity_ids": ["lock.back"]})
+  z1.add_to_hass(hass)
+  z2.add_to_hass(hass)
+
   result = await _reach_locks_step(hass, mock_entry)
 
   result = await hass.config_entries.options.async_configure(
     result["flow_id"],
-    user_input={CONF_ZLOCK_ENTRIES: ["entry_abc", "entry_def"], CONF_ZWAVE_SLOT: 5},
+    user_input={CONF_ZLOCK_ENTRIES: [z1.entry_id, z2.entry_id], CONF_ZWAVE_SLOT: 5},
   )
   assert result["type"] == "create_entry"
-  assert result["data"][CONF_ZLOCK_ENTRIES] == ["entry_abc", "entry_def"]
+  assert result["data"][CONF_ZLOCK_ENTRIES] == [z1.entry_id, z2.entry_id]
   assert result["data"][CONF_ZWAVE_SLOT] == 5
 
 

+ 19 - 25
tests/test_coordinator.py

@@ -912,13 +912,13 @@ async def test_check_in_sets_lock_codes(hass: HomeAssistant, coordinator_with_lo
     patch.object(coordinator_with_locks, "_is_mode_sync_on", return_value=True),
     patch.object(coordinator_with_locks, "_is_use_zwave_on", return_value=True),
     patch("custom_components.room_cal_ha.coordinator.dt_util.now", return_value=_AT_CHECK_IN),
-    patch.object(hass.services, "async_call", new_callable=AsyncMock) as mock_call,
+    patch.object(coordinator_with_locks, "_async_call_service", new_callable=AsyncMock) as mock_call,
   ):
     await coordinator_with_locks._async_do_check_in()
   coordinator_with_locks.cancel_mode_sync()
 
-  mock_call.assert_any_await("zlock_slots", "set_code", {"lock_entity_id": "lock.front_door", "slot": 5, "code": "7890"}, blocking=True)
-  mock_call.assert_any_await("zlock_slots", "set_slot_enabled", {"lock_entity_id": "lock.front_door", "slot": 5, "enabled": True}, blocking=True)
+  mock_call.assert_any_await("zlock_slots", "set_code", {"lock_entity_id": "lock.front_door", "slot": 5, "code": "7890"})
+  mock_call.assert_any_await("zlock_slots", "set_slot_enabled", {"lock_entity_id": "lock.front_door", "slot": 5, "enabled": True})
   mock_switch.async_turn_on.assert_awaited_once()
 
 
@@ -936,15 +936,15 @@ async def test_check_in_sets_codes_on_all_locks(hass: HomeAssistant):
     patch.object(coord, "_is_mode_sync_on", return_value=True),
     patch.object(coord, "_is_use_zwave_on", return_value=True),
     patch("custom_components.room_cal_ha.coordinator.dt_util.now", return_value=_AT_CHECK_IN),
-    patch.object(hass.services, "async_call", new_callable=AsyncMock) as mock_call,
+    patch.object(coord, "_async_call_service", new_callable=AsyncMock) as mock_call,
   ):
     await coord._async_do_check_in()
   coord.cancel_mode_sync()
 
-  mock_call.assert_any_await("zlock_slots", "set_code", {"lock_entity_id": "lock.front", "slot": 5, "code": "7890"}, blocking=True)
-  mock_call.assert_any_await("zlock_slots", "set_code", {"lock_entity_id": "lock.back", "slot": 5, "code": "7890"}, blocking=True)
-  mock_call.assert_any_await("zlock_slots", "set_slot_enabled", {"lock_entity_id": "lock.front", "slot": 5, "enabled": True}, blocking=True)
-  mock_call.assert_any_await("zlock_slots", "set_slot_enabled", {"lock_entity_id": "lock.back", "slot": 5, "enabled": True}, blocking=True)
+  mock_call.assert_any_await("zlock_slots", "set_code", {"lock_entity_id": "lock.front", "slot": 5, "code": "7890"})
+  mock_call.assert_any_await("zlock_slots", "set_code", {"lock_entity_id": "lock.back", "slot": 5, "code": "7890"})
+  mock_call.assert_any_await("zlock_slots", "set_slot_enabled", {"lock_entity_id": "lock.front", "slot": 5, "enabled": True})
+  mock_call.assert_any_await("zlock_slots", "set_slot_enabled", {"lock_entity_id": "lock.back", "slot": 5, "enabled": True})
 
 
 async def test_check_in_skips_lock_codes_when_door_code_none(hass: HomeAssistant, coordinator_with_locks: RoomCalCoordinator):
@@ -963,7 +963,7 @@ async def test_check_in_skips_lock_codes_when_door_code_none(hass: HomeAssistant
     patch.object(coordinator_with_locks, "_is_mode_sync_on", return_value=True),
     patch.object(coordinator_with_locks, "_is_use_zwave_on", return_value=True),
     patch("custom_components.room_cal_ha.coordinator.dt_util.now", return_value=_AT_CHECK_IN),
-    patch.object(hass.services, "async_call", new_callable=AsyncMock) as mock_call,
+    patch.object(coordinator_with_locks, "_async_call_service", new_callable=AsyncMock) as mock_call,
   ):
     await coordinator_with_locks._async_do_check_in()
   coordinator_with_locks.cancel_mode_sync()
@@ -981,14 +981,12 @@ async def test_check_in_skips_lock_codes_when_use_zwave_off(hass: HomeAssistant,
     patch.object(coordinator_with_locks, "_is_mode_sync_on", return_value=True),
     patch.object(coordinator_with_locks, "_is_use_zwave_on", return_value=False),
     patch("custom_components.room_cal_ha.coordinator.dt_util.now", return_value=_AT_CHECK_IN),
-    patch.object(hass.services, "async_call", new_callable=AsyncMock) as mock_call,
+    patch.object(coordinator_with_locks, "_async_call_service", new_callable=AsyncMock) as mock_call,
   ):
     await coordinator_with_locks._async_do_check_in()
   coordinator_with_locks.cancel_mode_sync()
 
-  assert not any(
-    c.args[:1] == ("zlock_slots",) for c in mock_call.await_args_list
-  )
+  mock_call.assert_not_awaited()
 
 
 async def test_check_in_skips_lock_codes_when_no_locks_configured(hass: HomeAssistant, coordinator: RoomCalCoordinator):
@@ -1000,14 +998,12 @@ async def test_check_in_skips_lock_codes_when_no_locks_configured(hass: HomeAssi
     patch.object(coordinator, "_is_mode_sync_on", return_value=True),
     patch.object(coordinator, "_is_use_zwave_on", return_value=True),
     patch("custom_components.room_cal_ha.coordinator.dt_util.now", return_value=_AT_CHECK_IN),
-    patch.object(hass.services, "async_call", new_callable=AsyncMock) as mock_call,
+    patch.object(coordinator, "_async_call_service", new_callable=AsyncMock) as mock_call,
   ):
     await coordinator._async_do_check_in()
   coordinator.cancel_mode_sync()
 
-  assert not any(
-    c.args[:1] == ("zlock_slots",) for c in mock_call.await_args_list
-  )
+  mock_call.assert_not_awaited()
 
 
 async def test_check_in_lock_error_still_activates_guest_mode(hass: HomeAssistant, coordinator_with_locks: RoomCalCoordinator):
@@ -1020,7 +1016,7 @@ async def test_check_in_lock_error_still_activates_guest_mode(hass: HomeAssistan
     patch.object(coordinator_with_locks, "_is_mode_sync_on", return_value=True),
     patch.object(coordinator_with_locks, "_is_use_zwave_on", return_value=True),
     patch("custom_components.room_cal_ha.coordinator.dt_util.now", return_value=_AT_CHECK_IN),
-    patch.object(hass.services, "async_call", side_effect=HomeAssistantError("lock offline")),
+    patch.object(coordinator_with_locks, "_async_call_service", side_effect=HomeAssistantError("lock offline")),
   ):
     await coordinator_with_locks._async_do_check_in()
   coordinator_with_locks.cancel_mode_sync()
@@ -1041,11 +1037,11 @@ async def test_check_out_disables_lock_slot(hass: HomeAssistant, coordinator_wit
   with (
     patch.object(coordinator_with_locks, "_is_mode_sync_on", return_value=True),
     patch.object(coordinator_with_locks, "_is_use_zwave_on", return_value=True),
-    patch.object(hass.services, "async_call", new_callable=AsyncMock) as mock_call,
+    patch.object(coordinator_with_locks, "_async_call_service", new_callable=AsyncMock) as mock_call,
   ):
     await coordinator_with_locks._async_do_check_out()
 
-  mock_call.assert_awaited_once_with("zlock_slots", "set_slot_enabled", {"lock_entity_id": "lock.front_door", "slot": 5, "enabled": False}, blocking=True)
+  mock_call.assert_awaited_once_with("zlock_slots", "set_slot_enabled", {"lock_entity_id": "lock.front_door", "slot": 5, "enabled": False})
   mock_switch.async_turn_off.assert_awaited_once()
 
 
@@ -1056,13 +1052,11 @@ async def test_check_out_skips_lock_slot_when_use_zwave_off(hass: HomeAssistant,
   with (
     patch.object(coordinator_with_locks, "_is_mode_sync_on", return_value=True),
     patch.object(coordinator_with_locks, "_is_use_zwave_on", return_value=False),
-    patch.object(hass.services, "async_call", new_callable=AsyncMock) as mock_call,
+    patch.object(coordinator_with_locks, "_async_call_service", new_callable=AsyncMock) as mock_call,
   ):
     await coordinator_with_locks._async_do_check_out()
 
-  assert not any(
-    c.args[:1] == ("zlock_slots",) for c in mock_call.await_args_list
-  )
+  mock_call.assert_not_awaited()
 
 
 async def test_check_out_lock_error_still_deactivates_guest_mode(hass: HomeAssistant, coordinator_with_locks: RoomCalCoordinator):
@@ -1074,7 +1068,7 @@ async def test_check_out_lock_error_still_deactivates_guest_mode(hass: HomeAssis
   with (
     patch.object(coordinator_with_locks, "_is_mode_sync_on", return_value=True),
     patch.object(coordinator_with_locks, "_is_use_zwave_on", return_value=True),
-    patch.object(hass.services, "async_call", side_effect=HomeAssistantError("lock offline")),
+    patch.object(coordinator_with_locks, "_async_call_service", side_effect=HomeAssistantError("lock offline")),
   ):
     await coordinator_with_locks._async_do_check_out()
 

+ 4 - 4
tests/test_switches.py

@@ -207,14 +207,14 @@ def test_use_zlock_available_true_when_entries_configured():
   assert _use_zlock(entries=["abc123"]).available is True
 
 
-async def test_use_zwave_turn_on_sets_true():
-  s = _use_zwave(locks=["lock.front_door"])
+async def test_use_zlock_turn_on_sets_true():
+  s = _use_zlock(entries=["abc123"])
   await s.async_turn_on()
   assert s.is_on is True
 
 
-async def test_use_zwave_turn_off_sets_false():
-  s = _use_zwave(locks=["lock.front_door"])
+async def test_use_zlock_turn_off_sets_false():
+  s = _use_zlock(entries=["abc123"])
   s._state = True
   await s.async_turn_off()
   assert s.is_on is False