All checks were successful
Deploy Development / deploy (push) Successful in 46s
Test Suite / pytest-backend (push) Successful in 5m3s
Test Suite / lint-backend (push) Successful in 3s
Test Suite / compose-smoke (push) Has been skipped
Test Suite / k6 /api/health Baseline (push) Successful in 19s
Test Suite / playwright-smoke (push) Successful in 13s
Gate- und Kit-Übungen legen ein Arbeitspaket plus Schedule an; Today zeigt nur fällige Wochentage, nicht die ganze Gate-Liste. Co-authored-by: Cursor <cursoragent@cursor.com>
86 lines
2.5 KiB
Python
86 lines
2.5 KiB
Python
"""Unit tests for schedule due-date logic (no DB)."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from datetime import date, datetime, timezone
|
|
|
|
from services.schedule import (
|
|
format_schedule_label,
|
|
initial_due_at,
|
|
is_due_on_date,
|
|
next_due_after_completion,
|
|
weekday_bit,
|
|
weekday_mask_for_date,
|
|
)
|
|
|
|
|
|
def test_interval_daily_label():
|
|
label = format_schedule_label({"schedule_kind": "interval", "interval_days": 1, "weekday_mask": 0})
|
|
assert label == "Täglich"
|
|
|
|
|
|
def test_interval_seven_is_not_weekly():
|
|
label = format_schedule_label({"schedule_kind": "interval", "interval_days": 7, "weekday_mask": 0})
|
|
assert label == "Alle 7 Tage"
|
|
|
|
|
|
def test_weekday_label_lists_days():
|
|
label = format_schedule_label(
|
|
{"schedule_kind": "weekdays", "weekday_mask": weekday_bit(0) | weekday_bit(2) | weekday_bit(6)}
|
|
)
|
|
assert label == "Mo, Mi, So"
|
|
assert "Wöchentlich" not in label
|
|
|
|
|
|
def test_weekday_mask_next_due_after_friday():
|
|
schedule = {
|
|
"schedule_kind": "weekdays",
|
|
"weekday_mask": weekday_bit(0) | weekday_bit(2) | weekday_bit(4),
|
|
"pause_until": None,
|
|
}
|
|
friday = datetime(2026, 8, 7, 12, 0, tzinfo=timezone.utc)
|
|
nxt = next_due_after_completion(schedule=schedule, completed_at=friday)
|
|
assert nxt.date() == date(2026, 8, 10)
|
|
|
|
|
|
def test_is_due_on_date_hides_future_weekday():
|
|
schedule = {
|
|
"schedule_kind": "weekdays",
|
|
"weekday_mask": weekday_bit(1),
|
|
"pause_until": None,
|
|
}
|
|
next_due = datetime(2026, 8, 18, tzinfo=timezone.utc)
|
|
assert is_due_on_date(schedule=schedule, next_due_at=next_due, on_date=date(2026, 8, 17)) is False
|
|
assert is_due_on_date(schedule=schedule, next_due_at=next_due, on_date=date(2026, 8, 18)) is True
|
|
|
|
|
|
def test_is_due_on_date_keeps_overdue_weekday():
|
|
schedule = {
|
|
"schedule_kind": "weekdays",
|
|
"weekday_mask": weekday_bit(0),
|
|
"pause_until": None,
|
|
}
|
|
missed_monday = datetime(2026, 8, 17, tzinfo=timezone.utc)
|
|
assert (
|
|
is_due_on_date(
|
|
schedule=schedule, next_due_at=missed_monday, on_date=date(2026, 8, 18)
|
|
)
|
|
is True
|
|
)
|
|
|
|
|
|
def test_weekday_mask_for_monday():
|
|
assert weekday_mask_for_date(date(2026, 8, 17)) == weekday_bit(0)
|
|
|
|
|
|
def test_pause_until_pushes_initial_due():
|
|
schedule = {
|
|
"schedule_kind": "interval",
|
|
"interval_days": 1,
|
|
"weekday_mask": 0,
|
|
"pause_until": "2026-08-10",
|
|
}
|
|
now = datetime(2026, 8, 4, 9, 0, tzinfo=timezone.utc)
|
|
due = initial_due_at(schedule=schedule, now=now)
|
|
assert due.date() == date(2026, 8, 11)
|