|
@@ -191,19 +191,14 @@ def _res(checkin_h: int, checkout_h: int, *, wifi_key="key", wifi_ssid="ssid", d
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
-_DURING = datetime(2026, 7, 1, 15, 0) # 15:00 — inside a 14:00–12:00 window
|
|
|
|
|
-_BEFORE = datetime(2026, 7, 1, 12, 0) # 12:00 — before 14:00 check-in
|
|
|
|
|
-_AFTER = datetime(2026, 7, 1, 22, 0) # 22:00 — after typical check-out
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
def test_diff_both_inactive_returns_no_changes():
|
|
def test_diff_both_inactive_returns_no_changes():
|
|
|
- diff = reservation_diff(None, None, _DURING)
|
|
|
|
|
|
|
+ diff = reservation_diff(None, None)
|
|
|
assert not diff.has_changes
|
|
assert not diff.has_changes
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_diff_old_none_new_active_returns_checkin():
|
|
def test_diff_old_none_new_active_returns_checkin():
|
|
|
res = _res(14, 20)
|
|
res = _res(14, 20)
|
|
|
- diff = reservation_diff(None, res, _DURING)
|
|
|
|
|
|
|
+ diff = reservation_diff(None, res)
|
|
|
assert diff.checkin_needed
|
|
assert diff.checkin_needed
|
|
|
assert not diff.checkout_needed
|
|
assert not diff.checkout_needed
|
|
|
assert diff.departing is None
|
|
assert diff.departing is None
|
|
@@ -211,24 +206,24 @@ def test_diff_old_none_new_active_returns_checkin():
|
|
|
|
|
|
|
|
def test_diff_old_active_new_none_returns_checkout():
|
|
def test_diff_old_active_new_none_returns_checkout():
|
|
|
res = _res(14, 20)
|
|
res = _res(14, 20)
|
|
|
- diff = reservation_diff(res, None, _DURING)
|
|
|
|
|
|
|
+ diff = reservation_diff(res, None)
|
|
|
assert diff.checkout_needed
|
|
assert diff.checkout_needed
|
|
|
assert not diff.checkin_needed
|
|
assert not diff.checkin_needed
|
|
|
assert diff.departing is res
|
|
assert diff.departing is res
|
|
|
|
|
|
|
|
|
|
|
|
|
-def test_diff_both_elapsed_returns_no_changes():
|
|
|
|
|
- # Window already passed for both — time-based handler owns this transition, not diff.
|
|
|
|
|
|
|
+def test_diff_unchanged_record_returns_no_changes():
|
|
|
old = _res(14, 20)
|
|
old = _res(14, 20)
|
|
|
- diff = reservation_diff(old, old, _AFTER)
|
|
|
|
|
|
|
+ diff = reservation_diff(old, old)
|
|
|
assert not diff.has_changes
|
|
assert not diff.has_changes
|
|
|
|
|
|
|
|
|
|
|
|
|
-def test_diff_backend_clears_active_reservation_returns_checkout():
|
|
|
|
|
- # Backend returns None while we're still inside the window → checkout needed.
|
|
|
|
|
|
|
+def test_diff_checkout_needed_even_when_now_is_past_check_out():
|
|
|
|
|
+ # Regression test: a scheduled natural checkout runs at/after old's check-out time,
|
|
|
|
|
+ # so the diff must not re-derive "was old active" from wall-clock time — it must
|
|
|
|
|
+ # trigger checkout purely because old was occupied and new (cleared) is not.
|
|
|
old = _res(14, 20)
|
|
old = _res(14, 20)
|
|
|
- now = datetime(2026, 7, 1, 16, 0)
|
|
|
|
|
- diff = reservation_diff(old, None, now)
|
|
|
|
|
|
|
+ diff = reservation_diff(old, None)
|
|
|
assert diff.checkout_needed
|
|
assert diff.checkout_needed
|
|
|
assert not diff.checkin_needed
|
|
assert not diff.checkin_needed
|
|
|
assert diff.departing is old
|
|
assert diff.departing is old
|
|
@@ -236,14 +231,14 @@ def test_diff_backend_clears_active_reservation_returns_checkout():
|
|
|
|
|
|
|
|
def test_diff_same_window_no_changes_returns_empty():
|
|
def test_diff_same_window_no_changes_returns_empty():
|
|
|
res = _res(14, 20)
|
|
res = _res(14, 20)
|
|
|
- diff = reservation_diff(res, res, _DURING)
|
|
|
|
|
|
|
+ diff = reservation_diff(res, res)
|
|
|
assert not diff.has_changes
|
|
assert not diff.has_changes
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_diff_same_window_wifi_key_changed():
|
|
def test_diff_same_window_wifi_key_changed():
|
|
|
old = _res(14, 20, wifi_key="old-key")
|
|
old = _res(14, 20, wifi_key="old-key")
|
|
|
new = _res(14, 20, wifi_key="new-key")
|
|
new = _res(14, 20, wifi_key="new-key")
|
|
|
- diff = reservation_diff(old, new, _DURING)
|
|
|
|
|
|
|
+ diff = reservation_diff(old, new)
|
|
|
assert diff.wifi_key_changed
|
|
assert diff.wifi_key_changed
|
|
|
assert not diff.door_code_changed
|
|
assert not diff.door_code_changed
|
|
|
assert not diff.checkin_needed
|
|
assert not diff.checkin_needed
|
|
@@ -253,7 +248,7 @@ def test_diff_same_window_wifi_key_changed():
|
|
|
def test_diff_same_window_door_code_changed():
|
|
def test_diff_same_window_door_code_changed():
|
|
|
old = _res(14, 20, door_code="1234")
|
|
old = _res(14, 20, door_code="1234")
|
|
|
new = _res(14, 20, door_code="5678")
|
|
new = _res(14, 20, door_code="5678")
|
|
|
- diff = reservation_diff(old, new, _DURING)
|
|
|
|
|
|
|
+ diff = reservation_diff(old, new)
|
|
|
assert diff.door_code_changed
|
|
assert diff.door_code_changed
|
|
|
assert not diff.wifi_key_changed
|
|
assert not diff.wifi_key_changed
|
|
|
assert not diff.checkin_needed
|
|
assert not diff.checkin_needed
|
|
@@ -263,7 +258,7 @@ def test_diff_same_window_door_code_changed():
|
|
|
def test_diff_same_window_no_change():
|
|
def test_diff_same_window_no_change():
|
|
|
old = _res(14, 20, wifi_key="key", door_code="1234")
|
|
old = _res(14, 20, wifi_key="key", door_code="1234")
|
|
|
new = _res(14, 20, wifi_key="key", door_code="1234")
|
|
new = _res(14, 20, wifi_key="key", door_code="1234")
|
|
|
- diff = reservation_diff(old, new, _DURING)
|
|
|
|
|
|
|
+ diff = reservation_diff(old, new)
|
|
|
assert not diff.has_changes
|
|
assert not diff.has_changes
|
|
|
|
|
|
|
|
|
|
|
|
@@ -278,23 +273,15 @@ def test_diff_different_window_both_active_returns_checkout_and_checkin():
|
|
|
check_out_date=date(2026, 7, 2), check_out_time=time(12, 0),
|
|
check_out_date=date(2026, 7, 2), check_out_time=time(12, 0),
|
|
|
wifi_ssid="s", wifi_key="k",
|
|
wifi_ssid="s", wifi_key="k",
|
|
|
)
|
|
)
|
|
|
- now = datetime(2026, 7, 1, 15, 0) # after both check-ins
|
|
|
|
|
- diff = reservation_diff(old, new, now)
|
|
|
|
|
|
|
+ diff = reservation_diff(old, new)
|
|
|
assert diff.checkout_needed
|
|
assert diff.checkout_needed
|
|
|
assert diff.checkin_needed
|
|
assert diff.checkin_needed
|
|
|
assert diff.departing is old
|
|
assert diff.departing is old
|
|
|
|
|
|
|
|
|
|
|
|
|
-def test_diff_inactive_old_becomes_active_new_returns_checkin():
|
|
|
|
|
- res = _res(14, 20)
|
|
|
|
|
- diff = reservation_diff(res, res, _BEFORE) # same record, but we're before check-in
|
|
|
|
|
- # old is inactive (before window), new is inactive too → no changes
|
|
|
|
|
- assert not diff.has_changes
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-def test_diff_no_checkin_time_treated_as_inactive():
|
|
|
|
|
|
|
+def test_diff_no_checkin_time_treated_as_unoccupied():
|
|
|
res = ReservationData(check_in_date=date(2026, 7, 1)) # no time fields
|
|
res = ReservationData(check_in_date=date(2026, 7, 1)) # no time fields
|
|
|
- diff = reservation_diff(None, res, _DURING)
|
|
|
|
|
|
|
+ diff = reservation_diff(None, res)
|
|
|
assert not diff.has_changes
|
|
assert not diff.has_changes
|
|
|
|
|
|
|
|
|
|
|