import pytest from datetime import datetime, time, timedelta from app.utils.time_utils import get_day_night_splits, minutes_after, day_start_pattern class TestGetDayNightSplits: def test_zero_length_session(self): start = datetime(2024, 1, 15, 10, 0) end = datetime(2024, 1, 15, 10, 0) day_start = time(7, 0) day_end = time(20, 0) segments = get_day_night_splits(start, end, day_start, day_end) assert len(segments) == 0 def test_session_entirely_in_day(self): start = datetime(2024, 1, 15, 10, 0) end = datetime(2024, 1, 15, 14, 0) day_start = time(7, 0) day_end = time(20, 0) segments = get_day_night_splits(start, end, day_start, day_end) assert len(segments) == 1 assert segments[0]["type"] == "day" def test_session_entirely_in_night(self): start = datetime(2024, 1, 15, 22, 0) end = datetime(2024, 1, 16, 2, 0) day_start = time(7, 0) day_end = time(20, 0) segments = get_day_night_splits(start, end, day_start, day_end) assert len(segments) == 1 assert segments[0]["type"] == "night" def test_session_spans_day_night_boundary(self): start = datetime(2024, 1, 15, 18, 0) end = datetime(2024, 1, 15, 22, 0) day_start = time(7, 0) day_end = time(20, 0) segments = get_day_night_splits(start, end, day_start, day_end) assert len(segments) == 2 assert segments[0]["type"] == "day" assert segments[1]["type"] == "night" def test_session_spans_midnight(self): start = datetime(2024, 1, 15, 23, 0) end = datetime(2024, 1, 16, 2, 0) day_start = time(7, 0) day_end = time(20, 0) segments = get_day_night_splits(start, end, day_start, day_end) assert len(segments) == 1 assert segments[0]["type"] == "night" def test_session_spans_two_days(self): # Start Day 1 at 23:00, End Day 2 at 01:00 (Night) # It should catch the transition if day_start/end logic is correct. # But here, no boundary (07:00 or 20:00) is in the session. # So it should just be one segment of type 'night'. start = datetime(2024, 1, 15, 23, 0) end = datetime(2024, 1, 16, 1, 0) day_start = time(7, 0) segments = get_day_night_splits(start, end, day_start, time(20, 0)) assert len(segments) == 1 assert segments[0]["type"] == "night" def test_session_boundary_at_start(self): # Session starts exactly at day_start start = datetime(2024, 1, 15, 7, 0) end = datetime(2024, 1, 15, 10, 0) day_start = time(7, 0) day_end = time(20, 0) segments = get_day_night_splits(start, end, day_start, day_end) # The loop uses: if session_start < b1 < session_end # Since 7:00 is not > 7:00, b1 won't be added. # So it should result in 1 segment [start, end] assert len(segments) == 1 assert segments[0]["type"] == "day" def test_session_boundary_at_end(self): # Session ends exactly at day_end start = datetime(2024, 1, 15, 18, 0) end = datetime(2024, 1, 15, 20, 0) day_start = time(7, 0) day_end = time(20, 0) segments = get_day_night_splits(start, end, day_start, day_end) assert len(segments) == 1 assert segments[0]["type"] == "day" class TestMinutesAfter: def test_minutes_at_reference(self): dt = datetime(2024, 1, 15, 4, 0) ref = time(4, 0) result = minutes_after(dt, ref) assert result == 0 def test_minutes_after_reference(self): dt = datetime(2024, 1, 15, 7, 30) ref = time(4, 0) result = minutes_after(dt, ref) assert result == 210 def test_before_reference(self): dt = datetime(2024, 1, 15, 3, 30) ref = time(4, 0) result = minutes_after(dt, ref) assert result == -30 class TestDayStartPattern: def test_within_day_range(self): assert day_start_pattern(time(12, 0), time(7, 0), time(20, 0)) is True def test_outside_day_range(self): assert day_start_pattern(time(3, 0), time(7, 0), time(20, 0)) is False def test_at_boundary(self): assert day_start_pattern(time(7, 0), time(7, 0), time(20, 0)) is True def test_just_after_boundary(self): # Test that the end boundary is exclusive assert day_start_pattern(time(20, 0), time(7, 0), time(20, 0)) is False def test_spans_midnight(self): assert day_start_pattern(time(22, 0), time(20, 0), time(7, 0)) is True assert day_start_pattern(time(3, 0), time(20, 0), time(7, 0)) is True