293 lines
12 KiB
Python
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"]) |