Files
crossfit/test/test_crossfit_booker_functional.py
2025-07-25 14:09:03 +02:00

293 lines
12 KiB
Python

#!/usr/bin/env python3
"""
Unit tests for CrossFitBooker functional methods
"""
import pytest
import os
import sys
from unittest.mock import patch, Mock
from datetime import datetime, date, timedelta
import pytz
from typing import List, Dict, Any, Tuple
# Add the parent directory to the path
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from crossfit_booker_functional import (
get_auth_headers,
is_session_bookable,
matches_preferred_session,
prepare_booking_data,
is_bookable_and_preferred,
filter_bookable_sessions,
is_upcoming_preferred,
filter_upcoming_sessions,
filter_preferred_sessions,
format_session_details,
categorize_sessions,
process_booking_results
)
# Mock preferred sessions
MOCK_PREFERRED_SESSIONS = [
(2, "18:30", "CONDITIONING"), # Wednesday 18:30 CONDITIONING
(4, "17:00", "WEIGHTLIFTING"), # Friday 17:00 WEIGHTLIFTING
(5, "12:30", "HYROX"), # Saturday 12:30 HYROX
]
class TestCrossFitBookerFunctional:
"""Test cases for CrossFitBooker functional methods"""
def test_get_auth_headers_without_token(self):
"""Test headers without auth token"""
base_headers = {"User-Agent": "test-agent"}
headers = get_auth_headers(base_headers, None)
assert "Authorization" not in headers
assert headers["User-Agent"] == "test-agent"
def test_get_auth_headers_with_token(self):
"""Test headers with auth token"""
base_headers = {"User-Agent": "test-agent"}
headers = get_auth_headers(base_headers, "test_token_123")
assert headers["Authorization"] == "Bearer test_token_123"
assert headers["User-Agent"] == "test-agent"
def test_is_session_bookable_can_join_true(self):
"""Test session bookable with can_join=True"""
session = {"user_info": {"can_join": True}}
current_time = datetime.now(pytz.timezone("Europe/Paris"))
assert is_session_bookable(session, current_time, "Europe/Paris") is True
def test_is_session_bookable_booking_window_past(self):
"""Test session bookable with booking window in past"""
session = {
"user_info": {
"can_join": False,
"unableToBookUntilDate": "01-01-2020",
"unableToBookUntilTime": "10:00"
}
}
current_time = datetime.now(pytz.timezone("Europe/Paris"))
assert is_session_bookable(session, current_time, "Europe/Paris") is True
def test_is_session_bookable_booking_window_future(self):
"""Test session not bookable with booking window in future"""
session = {
"user_info": {
"can_join": False,
"unableToBookUntilDate": "01-01-2030",
"unableToBookUntilTime": "10:00"
}
}
current_time = datetime.now(pytz.timezone("Europe/Paris"))
assert is_session_bookable(session, current_time, "Europe/Paris") is False
def test_matches_preferred_session_exact_match(self):
"""Test exact match with preferred session"""
session = {
"start_timestamp": "2025-07-30 18:30:00",
"name_activity": "CONDITIONING"
}
current_time = datetime(2025, 7, 30, 12, 0, 0, tzinfo=pytz.timezone("Europe/Paris"))
with patch('crossfit_booker_functional.PREFERRED_SESSIONS', MOCK_PREFERRED_SESSIONS):
assert matches_preferred_session(session, MOCK_PREFERRED_SESSIONS, "Europe/Paris") is True
def test_matches_preferred_session_fuzzy_match(self):
"""Test fuzzy match with preferred session"""
session = {
"start_timestamp": "2025-07-30 18:30:00",
"name_activity": "CONDITIONING WORKOUT"
}
current_time = datetime(2025, 7, 30, 12, 0, 0, tzinfo=pytz.timezone("Europe/Paris"))
with patch('crossfit_booker_functional.PREFERRED_SESSIONS', MOCK_PREFERRED_SESSIONS):
assert matches_preferred_session(session, MOCK_PREFERRED_SESSIONS, "Europe/Paris") is True
def test_matches_preferred_session_no_match(self):
"""Test no match with preferred session"""
session = {
"start_timestamp": "2025-07-30 18:30:00",
"name_activity": "YOGA"
}
current_time = datetime(2025, 7, 30, 12, 0, 0, tzinfo=pytz.timezone("Europe/Paris"))
with patch('crossfit_booker_functional.PREFERRED_SESSIONS', MOCK_PREFERRED_SESSIONS):
assert matches_preferred_session(session, MOCK_PREFERRED_SESSIONS, "Europe/Paris") is False
def test_prepare_booking_data(self):
"""Test prepare_booking_data function"""
mandatory_params = {"app_version": "1.0", "device_type": "1"}
session_id = "session_123"
user_id = "user_456"
data = prepare_booking_data(mandatory_params, session_id, user_id)
assert data["id_activity_calendar"] == session_id
assert data["id_user"] == user_id
assert data["action_by"] == user_id
assert data["n_guests"] == "0"
assert data["booked_on"] == "3"
assert data["app_version"] == "1.0"
assert data["device_type"] == "1"
def test_is_bookable_and_preferred(self):
"""Test is_bookable_and_preferred function"""
session = {
"start_timestamp": "2025-07-30 18:30:00",
"name_activity": "CONDITIONING",
"user_info": {"can_join": True}
}
current_time = datetime.now(pytz.timezone("Europe/Paris"))
with patch('crossfit_booker_functional.PREFERRED_SESSIONS', MOCK_PREFERRED_SESSIONS):
assert is_bookable_and_preferred(session, current_time, MOCK_PREFERRED_SESSIONS, "Europe/Paris") is True
def test_filter_bookable_sessions(self):
"""Test filter_bookable_sessions function"""
current_time = datetime.now(pytz.timezone("Europe/Paris"))
# Create test sessions
sessions = [
{
"start_timestamp": "2025-07-30 18:30:00", # Wednesday
"name_activity": "CONDITIONING",
"user_info": {"can_join": True}
},
{
"start_timestamp": "2025-07-31 18:30:00", # Thursday
"name_activity": "YOGA",
"user_info": {"can_join": True}
}
]
with patch('crossfit_booker_functional.PREFERRED_SESSIONS', MOCK_PREFERRED_SESSIONS):
bookable_sessions = filter_bookable_sessions(sessions, current_time, MOCK_PREFERRED_SESSIONS, "Europe/Paris")
assert len(bookable_sessions) == 1
assert bookable_sessions[0]["name_activity"] == "CONDITIONING"
def test_is_upcoming_preferred(self):
"""Test is_upcoming_preferred function"""
# Test with a session that is tomorrow
session = {
"start_timestamp": "2025-07-31 18:30:00", # Tomorrow
"name_activity": "CONDITIONING"
}
current_time = datetime(2025, 7, 30, 12, 0, 0, tzinfo=pytz.timezone("Europe/Paris"))
with patch('crossfit_booker_functional.PREFERRED_SESSIONS', MOCK_PREFERRED_SESSIONS):
assert is_upcoming_preferred(session, current_time, MOCK_PREFERRED_SESSIONS, "Europe/Paris") is True
# Test with a session that is today
session = {
"start_timestamp": "2025-07-30 18:30:00", # Today
"name_activity": "CONDITIONING"
}
current_time = datetime(2025, 7, 30, 12, 0, 0, tzinfo=pytz.timezone("Europe/Paris"))
with patch('crossfit_booker_functional.PREFERRED_SESSIONS', MOCK_PREFERRED_SESSIONS):
assert is_upcoming_preferred(session, current_time, MOCK_PREFERRED_SESSIONS, "Europe/Paris") is False
def test_filter_upcoming_sessions(self):
"""Test filter_upcoming_sessions function"""
current_time = datetime(2025, 7, 30, 12, 0, 0, tzinfo=pytz.timezone("Europe/Paris"))
# Create test sessions
sessions = [
{
"start_timestamp": "2025-07-30 18:30:00", # Today
"name_activity": "CONDITIONING",
"user_info": {"can_join": True}
},
{
"start_timestamp": "2025-07-31 18:30:00", # Tomorrow
"name_activity": "CONDITIONING",
"user_info": {"can_join": True}
}
]
with patch('crossfit_booker_functional.PREFERRED_SESSIONS', MOCK_PREFERRED_SESSIONS):
upcoming_sessions = filter_upcoming_sessions(sessions, current_time, MOCK_PREFERRED_SESSIONS, "Europe/Paris")
assert len(upcoming_sessions) == 1
assert upcoming_sessions[0]["name_activity"] == "CONDITIONING"
def test_filter_preferred_sessions(self):
"""Test filter_preferred_sessions function"""
# Create test sessions
sessions = [
{
"start_timestamp": "2025-07-30 18:30:00",
"name_activity": "CONDITIONING"
},
{
"start_timestamp": "2025-07-31 18:30:00",
"name_activity": "YOGA"
}
]
with patch('crossfit_booker_functional.PREFERRED_SESSIONS', MOCK_PREFERRED_SESSIONS):
preferred_sessions = filter_preferred_sessions(sessions, MOCK_PREFERRED_SESSIONS, "Europe/Paris")
assert len(preferred_sessions) == 1
assert preferred_sessions[0]["name_activity"] == "CONDITIONING"
def test_format_session_details(self):
"""Test format_session_details function"""
# Test with valid session
session = {
"start_timestamp": "2025-07-30 18:30:00",
"name_activity": "CONDITIONING"
}
formatted = format_session_details(session, "Europe/Paris")
assert "CONDITIONING" in formatted
assert "2025-07-30 18:30" in formatted
# Test with missing data
session = {
"name_activity": "WEIGHTLIFTING"
}
formatted = format_session_details(session, "Europe/Paris")
assert "WEIGHTLIFTING" in formatted
assert "Unknown time" in formatted
def test_categorize_sessions(self):
"""Test categorize_sessions function"""
current_time = datetime(2025, 7, 30, 12, 0, 0, tzinfo=pytz.timezone("Europe/Paris"))
# Create test sessions
sessions = [
{
"start_timestamp": "2025-07-30 18:30:00", # Today
"name_activity": "CONDITIONING",
"user_info": {"can_join": True}
},
{
"start_timestamp": "2025-07-31 18:30:00", # Tomorrow
"name_activity": "CONDITIONING",
"user_info": {"can_join": True}
}
]
with patch('crossfit_booker_functional.PREFERRED_SESSIONS', MOCK_PREFERRED_SESSIONS):
categorized = categorize_sessions(sessions, current_time, MOCK_PREFERRED_SESSIONS, "Europe/Paris")
assert "bookable" in categorized
assert "upcoming" in categorized
assert "all_preferred" in categorized
assert len(categorized["bookable"]) == 1
assert len(categorized["upcoming"]) == 1
assert len(categorized["all_preferred"]) == 1
def test_process_booking_results(self):
"""Test process_booking_results function"""
session = {
"start_timestamp": "2025-07-30 18:30:00",
"name_activity": "CONDITIONING"
}
result = process_booking_results(session, True, "Europe/Paris")
assert result["session"] == session
assert result["success"] is True
assert "CONDITIONING" in result["details"]
assert "2025-07-30 18:30" in result["details"]
if __name__ == "__main__":
pytest.main([__file__, "-v"])