test: add more coverage
This commit is contained in:
293
test/test_crossfit_booker_functional.py
Normal file
293
test/test_crossfit_booker_functional.py
Normal file
@@ -0,0 +1,293 @@
|
||||
#!/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"])
|
||||
Reference in New Issue
Block a user