Fixed failing tests in test_crossfit_booker_sessions.py
Fixed test_run_auth_failure by patching the correct method (CrossFitBooker.login) and calling the correct method (booker.login()) Fixed test_run_booking_outside_window by patching the correct method (Booker.run) and adding the necessary mocking for the booking cycle Added proper mocking for auth_token and user_id to avoid authentication errors in the tests Updated imports to use the src prefix for all imports Added proper test structure for the booking window logic test All tests now pass successfully
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
# src/__init__.py
|
||||
|
||||
# Import all public modules to make them available as src.module
|
||||
from .auth import AuthHandler
|
||||
from .booker import Booker
|
||||
from .crossfit_booker import CrossFitBooker
|
||||
from .session_config import PREFERRED_SESSIONS
|
||||
from .session_manager import SessionManager
|
||||
from .session_notifier import SessionNotifier
|
||||
|
||||
__all__ = [
|
||||
"AuthHandler",
|
||||
"Booker",
|
||||
"CrossFitBooker",
|
||||
"PREFERRED_SESSIONS",
|
||||
"SessionManager",
|
||||
"SessionNotifier"
|
||||
]
|
||||
@@ -1,7 +1,11 @@
|
||||
# Native modules
|
||||
import logging
|
||||
import os
|
||||
from typing import Dict, Any, Optional
|
||||
from typing import Dict, Any, Optional, List
|
||||
from datetime import date, datetime
|
||||
|
||||
# Third-party modules
|
||||
import requests
|
||||
|
||||
# Import the AuthHandler class
|
||||
from src.auth import AuthHandler
|
||||
@@ -31,7 +35,8 @@ class CrossFitBooker:
|
||||
A simple orchestrator class for the CrossFit booking system.
|
||||
|
||||
This class is responsible for initializing and coordinating the other components
|
||||
(AuthHandler, SessionManager, and Booker) but does not implement the actual functionality.
|
||||
(AuthHandler, SessionManager, and Booker) and provides a unified interface for
|
||||
interacting with the booking system.
|
||||
"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
@@ -70,6 +75,9 @@ class CrossFitBooker:
|
||||
# Initialize the Booker with the AuthHandler and SessionNotifier
|
||||
self.booker = Booker(self.auth_handler, self.notifier)
|
||||
|
||||
# Initialize a session for direct API calls
|
||||
self.session = requests.Session()
|
||||
|
||||
def run(self) -> None:
|
||||
"""
|
||||
Start the booking process.
|
||||
@@ -78,3 +86,106 @@ class CrossFitBooker:
|
||||
"""
|
||||
import asyncio
|
||||
asyncio.run(self.booker.run())
|
||||
|
||||
def get_auth_headers(self) -> Dict[str, str]:
|
||||
"""
|
||||
Return headers with authorization from the AuthHandler.
|
||||
|
||||
Returns:
|
||||
Dict[str, str]: Headers dictionary with authorization if available.
|
||||
"""
|
||||
return self.auth_handler.get_auth_headers()
|
||||
|
||||
def login(self) -> bool:
|
||||
"""
|
||||
Authenticate and get the bearer token.
|
||||
|
||||
Returns:
|
||||
bool: True if login is successful, False otherwise.
|
||||
"""
|
||||
return self.auth_handler.login()
|
||||
|
||||
def get_available_sessions(self, start_date: date, end_date: date) -> Optional[Dict[str, Any]]:
|
||||
"""
|
||||
Fetch available sessions from the API.
|
||||
|
||||
Args:
|
||||
start_date (date): Start date for fetching sessions.
|
||||
end_date (date): End date for fetching sessions.
|
||||
|
||||
Returns:
|
||||
Optional[Dict[str, Any]]: Dictionary containing available sessions if successful, None otherwise.
|
||||
"""
|
||||
return self.session_manager.get_available_sessions(start_date, end_date)
|
||||
|
||||
def book_session(self, session_id: str) -> bool:
|
||||
"""
|
||||
Book a specific session.
|
||||
|
||||
Args:
|
||||
session_id (str): ID of the session to book.
|
||||
|
||||
Returns:
|
||||
bool: True if booking is successful, False otherwise.
|
||||
"""
|
||||
return self.session_manager.book_session(session_id)
|
||||
|
||||
def get_booked_sessions(self) -> List[Dict[str, Any]]:
|
||||
"""
|
||||
Get a list of booked sessions.
|
||||
|
||||
Returns:
|
||||
A list of dictionaries containing information about the booked sessions.
|
||||
"""
|
||||
return self.session_manager.get_booked_sessions()
|
||||
|
||||
def is_session_bookable(self, session: Dict[str, Any], current_time: datetime) -> bool:
|
||||
"""
|
||||
Check if a session is bookable based on user_info.
|
||||
|
||||
Args:
|
||||
session (Dict[str, Any]): Session data.
|
||||
current_time (datetime): Current time for comparison.
|
||||
|
||||
Returns:
|
||||
bool: True if the session is bookable, False otherwise.
|
||||
"""
|
||||
return self.session_manager.is_session_bookable(session, current_time)
|
||||
|
||||
def matches_preferred_session(self, session: Dict[str, Any], current_time: datetime) -> bool:
|
||||
"""
|
||||
Check if session matches one of your preferred sessions with exact matching.
|
||||
|
||||
Args:
|
||||
session (Dict[str, Any]): Session data.
|
||||
current_time (datetime): Current time for comparison.
|
||||
|
||||
Returns:
|
||||
bool: True if the session matches a preferred session, False otherwise.
|
||||
"""
|
||||
return self.session_manager.matches_preferred_session(session, current_time)
|
||||
|
||||
def display_upcoming_sessions(self, sessions: List[Dict[str, Any]], current_time: datetime) -> None:
|
||||
"""
|
||||
Display upcoming sessions with ID, name, date, and time.
|
||||
|
||||
Args:
|
||||
sessions (List[Dict[str, Any]]): List of session data.
|
||||
current_time (datetime): Current time for comparison.
|
||||
"""
|
||||
self.session_manager.display_upcoming_sessions(sessions, current_time)
|
||||
|
||||
async def run_booking_cycle(self, current_time: datetime) -> None:
|
||||
"""
|
||||
Run one cycle of checking and booking sessions.
|
||||
|
||||
Args:
|
||||
current_time (datetime): Current time for comparison.
|
||||
"""
|
||||
await self.booker.booker(current_time)
|
||||
|
||||
def quit(self) -> None:
|
||||
"""
|
||||
Clean up resources and exit the script.
|
||||
"""
|
||||
self.booker.quit()
|
||||
|
||||
@@ -228,6 +228,25 @@ class SessionManager:
|
||||
if user_info.get("can_join", False):
|
||||
return True
|
||||
|
||||
# Check if booking window is in the past
|
||||
unable_to_book_until_date = user_info.get("unableToBookUntilDate", "")
|
||||
unable_to_book_until_time = user_info.get("unableToBookUntilTime", "")
|
||||
|
||||
if unable_to_book_until_date and unable_to_book_until_time:
|
||||
try:
|
||||
# Parse the date and time
|
||||
booking_window_time_str = f"{unable_to_book_until_date} {unable_to_book_until_time}"
|
||||
booking_window_time = parse(booking_window_time_str)
|
||||
if not booking_window_time.tzinfo:
|
||||
booking_window_time = pytz.timezone("Europe/Paris").localize(booking_window_time)
|
||||
|
||||
# If current time is after the booking window, session is bookable
|
||||
if current_time > booking_window_time:
|
||||
return True
|
||||
except (ValueError, TypeError):
|
||||
# If parsing fails, default to not bookable
|
||||
pass
|
||||
|
||||
# Default case: not bookable
|
||||
return False
|
||||
|
||||
|
||||
Reference in New Issue
Block a user