|
@@ -767,3 +767,86 @@ async def test_reconcile_does_not_touch_guest_mode_when_mode_sync_off(coordinato
|
|
|
|
|
|
|
|
mock_switch.async_turn_on.assert_not_awaited()
|
|
mock_switch.async_turn_on.assert_not_awaited()
|
|
|
mock_switch.async_turn_off.assert_not_awaited()
|
|
mock_switch.async_turn_off.assert_not_awaited()
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+# ---------------------------------------------------------------------------
|
|
|
|
|
+# _diff_with_unifi_check
|
|
|
|
|
+# ---------------------------------------------------------------------------
|
|
|
|
|
+
|
|
|
|
|
+_ACTIVE_WIFI_RES = ReservationData(
|
|
|
|
|
+ check_in_date=date(2026, 7, 1),
|
|
|
|
|
+ check_in_time=time(14, 0),
|
|
|
|
|
+ check_out_date=date(2026, 7, 5),
|
|
|
|
|
+ check_out_time=time(12, 0),
|
|
|
|
|
+ wifi_ssid="GuestNet",
|
|
|
|
|
+ wifi_key="correct-key",
|
|
|
|
|
+)
|
|
|
|
|
+_DURING_WINDOW = datetime(2026, 7, 3, 12, 0, 0)
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+def _unifi_diff(coordinator, old, new, now, *, enabled, key):
|
|
|
|
|
+ with (
|
|
|
|
|
+ patch.object(coordinator, "_is_use_unifi_on", return_value=True),
|
|
|
|
|
+ patch("custom_components.room_cal_ha.wifi.get_wlan_state", return_value=(enabled, key)),
|
|
|
|
|
+ ):
|
|
|
|
|
+ return coordinator._diff_with_unifi_check(old, new, now)
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+async def test_unifi_diff_ssid_disabled_adds_checkin_needed(coordinator):
|
|
|
|
|
+ diff = _unifi_diff(coordinator, None, _ACTIVE_WIFI_RES, _DURING_WINDOW, enabled=False, key="correct-key")
|
|
|
|
|
+ assert diff.checkin_needed
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+async def test_unifi_diff_key_mismatch_adds_wifi_key_changed(coordinator):
|
|
|
|
|
+ diff = _unifi_diff(coordinator, _ACTIVE_WIFI_RES, _ACTIVE_WIFI_RES, _DURING_WINDOW, enabled=True, key="wrong-key")
|
|
|
|
|
+ assert diff.wifi_key_changed
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+async def test_unifi_diff_ssid_disabled_and_key_wrong_sets_both(coordinator):
|
|
|
|
|
+ diff = _unifi_diff(coordinator, _ACTIVE_WIFI_RES, _ACTIVE_WIFI_RES, _DURING_WINDOW, enabled=False, key="wrong-key")
|
|
|
|
|
+ assert diff.checkin_needed
|
|
|
|
|
+ assert diff.wifi_key_changed
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+async def test_unifi_diff_state_matches_no_extra_flags(coordinator):
|
|
|
|
|
+ diff = _unifi_diff(coordinator, _ACTIVE_WIFI_RES, _ACTIVE_WIFI_RES, _DURING_WINDOW, enabled=True, key="correct-key")
|
|
|
|
|
+ assert not diff.has_changes
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+async def test_unifi_diff_skipped_when_use_unifi_off(coordinator):
|
|
|
|
|
+ with (
|
|
|
|
|
+ patch.object(coordinator, "_is_use_unifi_on", return_value=False),
|
|
|
|
|
+ patch("custom_components.room_cal_ha.wifi.get_wlan_state") as mock_get,
|
|
|
|
|
+ ):
|
|
|
|
|
+ diff = coordinator._diff_with_unifi_check(_ACTIVE_WIFI_RES, _ACTIVE_WIFI_RES, _DURING_WINDOW)
|
|
|
|
|
+ mock_get.assert_not_called()
|
|
|
|
|
+ assert not diff.has_changes # base diff: same record, no changes; unifi check skipped
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+async def test_unifi_diff_skipped_when_window_not_active(coordinator):
|
|
|
|
|
+ before_window = datetime(2026, 6, 30, 12, 0, 0)
|
|
|
|
|
+ with (
|
|
|
|
|
+ patch.object(coordinator, "_is_use_unifi_on", return_value=True),
|
|
|
|
|
+ patch("custom_components.room_cal_ha.wifi.get_wlan_state") as mock_get,
|
|
|
|
|
+ ):
|
|
|
|
|
+ diff = coordinator._diff_with_unifi_check(None, _ACTIVE_WIFI_RES, before_window)
|
|
|
|
|
+ mock_get.assert_not_called()
|
|
|
|
|
+ assert not diff.has_changes
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+async def test_unifi_diff_skipped_when_hub_unavailable(coordinator):
|
|
|
|
|
+ diff = _unifi_diff(coordinator, _ACTIVE_WIFI_RES, _ACTIVE_WIFI_RES, _DURING_WINDOW, enabled=None, key=None)
|
|
|
|
|
+ assert not diff.has_changes
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+async def test_unifi_diff_key_check_skipped_when_actual_key_none(coordinator):
|
|
|
|
|
+ # Controller doesn't expose passphrase — only enabled state checked.
|
|
|
|
|
+ diff = _unifi_diff(coordinator, _ACTIVE_WIFI_RES, _ACTIVE_WIFI_RES, _DURING_WINDOW, enabled=True, key=None)
|
|
|
|
|
+ assert not diff.has_changes
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+async def test_unifi_diff_preserves_original_diff_flags(coordinator):
|
|
|
|
|
+ # Even when UniFi state is clean, original checkin_needed from the base diff is kept.
|
|
|
|
|
+ old_inactive = ReservationData(wifi_ssid="GuestNet", wifi_key="correct-key") # no dates → not active
|
|
|
|
|
+ diff = _unifi_diff(coordinator, old_inactive, _ACTIVE_WIFI_RES, _DURING_WINDOW, enabled=True, key="correct-key")
|
|
|
|
|
+ assert diff.checkin_needed # from reservation_diff: old not active, new is active
|