from app.business.time_calc import ( minutes_to_str, work_minutes_reference, week_balance_minutes, ) def test_minutes_to_str_basic(): assert minutes_to_str(465) == "7h45" def test_minutes_to_str_zero(): assert minutes_to_str(0) == "0h00" def test_minutes_to_str_negative(): assert minutes_to_str(-75) == "-1h15" def test_work_minutes_reference_normal_day(): assert work_minutes_reference("WORK") == 465 assert work_minutes_reference("TT") == 465 assert work_minutes_reference("FORMATION") == 465 def test_work_minutes_reference_garde(): assert work_minutes_reference("GARDE") == 600 def test_work_minutes_reference_absence(): assert work_minutes_reference("RTT") == 0 assert work_minutes_reference("CONGE") == 0 assert work_minutes_reference("MALADE") == 0 assert work_minutes_reference("FERIE") == 0 def test_week_balance_positive(): assert week_balance_minutes(2400, 2325) == 75 def test_week_balance_negative(): assert week_balance_minutes(2200, 2325) == -125 from app.business.time_calc import count_day_types from app.models import WorkEntry, TimeSlot from app.business.time_calc import monthly_stats from datetime import date, time as dtime def test_count_day_types_basic(): entries = [ WorkEntry(date=date(2025, 1, 2), day_type="WORK"), WorkEntry(date=date(2025, 1, 3), day_type="WORK"), WorkEntry(date=date(2025, 1, 6), day_type="TT"), WorkEntry(date=date(2025, 1, 7), day_type="GARDE"), ] result = count_day_types(entries) assert result == {"WORK": 2, "TT": 1, "GARDE": 1} def test_count_day_types_empty(): assert count_day_types([]) == {} def _entry(d: date, *slots: tuple[str, str]) -> WorkEntry: """Helper : crée un WorkEntry avec des TimeSlots.""" entry = WorkEntry(date=d, day_type="WORK") entry.time_slots = [ TimeSlot(start_time=dtime(*[int(x) for x in s.split(":")]), end_time=dtime(*[int(x) for x in e.split(":")])) for s, e in slots ] return entry def _absence(d: date) -> WorkEntry: """Helper : crée un WorkEntry sans time_slots (0 min).""" entry = WorkEntry(date=d, day_type="CONGE") entry.time_slots = [] return entry def test_monthly_stats_empty(): result = monthly_stats([]) assert result == {"median_daily_min": 0, "median_weekly_min": 0} def test_monthly_stats_median_daily_odd(): # 420, 465, 510 → médiane = 465 entries = [ _entry(date(2025, 1, 6), ("9:00", "16:00")), # 420 min _entry(date(2025, 1, 7), ("9:00", "16:45")), # 465 min _entry(date(2025, 1, 8), ("9:00", "17:30")), # 510 min ] result = monthly_stats(entries) assert result["median_daily_min"] == 465 def test_monthly_stats_includes_absences(): # 0, 465 → médiane de 2 valeurs = (0+465)/2 = 232 (int) entries = [ _absence(date(2025, 1, 6)), _entry(date(2025, 1, 7), ("9:00", "16:45")), ] result = monthly_stats(entries) assert result["median_daily_min"] == 232 def test_monthly_stats_median_weekly(): # Semaine 1 : 465+465 = 930 min # Semaine 2 : 420 min # médiane([930, 420]) = (420+930)/2 = 675 entries = [ _entry(date(2025, 1, 6), ("9:00", "16:45")), # sem 2 _entry(date(2025, 1, 7), ("9:00", "16:45")), # sem 2 _entry(date(2025, 1, 13), ("9:00", "16:00")), # sem 3 ] result = monthly_stats(entries) assert result["median_weekly_min"] == 675 def test_count_day_types_single_type(): entries = [ WorkEntry(date=date(2025, 2, 1), day_type="RTT"), WorkEntry(date=date(2025, 2, 2), day_type="RTT"), ] result = count_day_types(entries) assert result == {"RTT": 2}