Booking entries parsed from the My Bookings page, comparison of expected and found bookings with the lecture's output, NoBookingsFoundError as the counterpart of NoSuchElementException, exit code 3 on a mismatch, tests for every starting weekday of the 8-day window, container tests against local fixtures. Task: MIL-006#1 Task: MIL-006#2 Task: MIL-006#3 Task: MIL-006#4
88 lines
2.8 KiB
Python
88 lines
2.8 KiB
Python
"""@file test_date_independence.py
|
|
@brief The bot picks classes by weekday and time only, whatever the first visible day is.
|
|
"""
|
|
|
|
from datetime import date, timedelta
|
|
|
|
import pytest
|
|
from tests.unit.fakes import FakeGym
|
|
|
|
from snack_and_lift.application.booking import book_target_classes
|
|
from snack_and_lift.application.verification import verify_bookings
|
|
from snack_and_lift.domain.models import ClassCard
|
|
from snack_and_lift.domain.rules import find_target_classes
|
|
|
|
## A Monday; the schedules below start on this day plus an offset, so every weekday occurs.
|
|
_A_MONDAY = date(2025, 8, 11)
|
|
_DAYS_SHOWN = 8
|
|
_TUESDAY, _THURSDAY = 1, 3
|
|
_TIMES = (
|
|
("Time: 6:00 AM", "Book Class"),
|
|
("Time: 6:00 PM", "Book Class"),
|
|
("Time: 7:00 PM", "Book Class"),
|
|
)
|
|
|
|
|
|
def _day_text(day: date) -> str:
|
|
return f"{day:%a}, {day:%b} {day.day}"
|
|
|
|
|
|
def _label(index: int, day: date) -> str:
|
|
if index == 0:
|
|
return f"Today ({_day_text(day)})"
|
|
if index == 1:
|
|
return f"Tomorrow ({_day_text(day)})"
|
|
return _day_text(day)
|
|
|
|
|
|
def make_schedule(start_offset: int) -> tuple[list[ClassCard], set[str]]:
|
|
"""@brief Cards of 8 days from a start weekday, and the ids of the Tue/Thu 6pm ones."""
|
|
cards: list[ClassCard] = []
|
|
wanted: set[str] = set()
|
|
for index in range(_DAYS_SHOWN):
|
|
day = _A_MONDAY + timedelta(days=start_offset + index)
|
|
for slot, (time_text, button) in enumerate(_TIMES):
|
|
card_id = f"{index}{slot}"
|
|
cards.append(ClassCard(card_id, "Spin Class", _label(index, day), time_text, button))
|
|
if day.weekday() in (_TUESDAY, _THURSDAY) and slot == 1:
|
|
wanted.add(card_id)
|
|
return cards, wanted
|
|
|
|
|
|
@pytest.mark.parametrize("start_offset", range(7))
|
|
def test_find_target_classes_for_every_starting_weekday(start_offset: int) -> None:
|
|
cards, wanted = make_schedule(start_offset)
|
|
|
|
assert {card.card_id for card in find_target_classes(cards)} == wanted
|
|
assert wanted
|
|
|
|
|
|
@pytest.mark.parametrize("start_offset", range(7))
|
|
def test_booking_and_verification_for_every_starting_weekday(start_offset: int) -> None:
|
|
cards, wanted = make_schedule(start_offset)
|
|
gym = FakeGym(cards=cards)
|
|
|
|
results = book_target_classes(gym)
|
|
|
|
assert set(gym.pressed) == wanted
|
|
assert len(gym.pressed) == len(wanted)
|
|
assert verify_bookings(gym, results).is_success
|
|
|
|
|
|
def test_schedule_whose_first_visible_day_is_a_thursday_includes_today() -> None:
|
|
cards, _ = make_schedule(3)
|
|
assert cards[0].day_label.startswith("Today (Thu,")
|
|
|
|
chosen = find_target_classes(cards)
|
|
|
|
assert [card.weekday for card in chosen] == ["Thu", "Tue", "Thu"]
|
|
assert chosen[0].card_id == "01"
|
|
|
|
|
|
def test_card_order_does_not_change_which_classes_are_chosen() -> None:
|
|
cards, wanted = make_schedule(2)
|
|
|
|
chosen = find_target_classes(list(reversed(cards)))
|
|
|
|
assert {card.card_id for card in chosen} == wanted
|