Files
crossfit/test/test_session_notifier.py
kbe a7f9e6bacd 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
2025-08-12 01:38:50 +02:00

186 lines
7.7 KiB
Python

#!/usr/bin/env python3
"""
Unit tests for SessionNotifier class
"""
import pytest
import os
import asyncio
from unittest.mock import patch, MagicMock
# Add the parent directory to the path
import sys
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from src.session_notifier import SessionNotifier
@pytest.fixture
def email_credentials():
return {
"from": "test@example.com",
"to": "recipient@example.com",
"password": "password123"
}
@pytest.fixture
def telegram_credentials():
return {
"token": "telegram_token",
"chat_id": "123456789"
}
@pytest.fixture
def session_notifier(email_credentials, telegram_credentials):
return SessionNotifier(
email_credentials=email_credentials,
telegram_credentials=telegram_credentials,
enable_email=True,
enable_telegram=True
)
@pytest.mark.asyncio
async def test_notify_session_booking(session_notifier, email_credentials, telegram_credentials):
"""Test session booking notification with both email and Telegram enabled"""
# Mock the email and Telegram notification methods
with patch.object(session_notifier, 'send_email_notification') as mock_email, \
patch.object(session_notifier, 'send_telegram_notification', new=MagicMock()) as mock_telegram:
# Set up the mock for the async method
mock_telegram.return_value = asyncio.Future()
mock_telegram.return_value.set_result(None)
# Call the method to test
await session_notifier.notify_session_booking("Test session")
# Verify both notification methods were called
mock_email.assert_called_once_with("Session booked: Test session")
mock_telegram.assert_called_once_with("Session booked: Test session")
@pytest.mark.asyncio
async def test_notify_session_booking_email_only(session_notifier, email_credentials):
"""Test session booking notification with only email enabled"""
# Disable Telegram notifications
session_notifier.enable_telegram = False
# Mock the email notification method
with patch.object(session_notifier, 'send_email_notification') as mock_email, \
patch.object(session_notifier, 'send_telegram_notification') as mock_telegram:
# Call the method to test
await session_notifier.notify_session_booking("Test session")
# Verify only email notification was called
mock_email.assert_called_once_with("Session booked: Test session")
mock_telegram.assert_not_called()
@pytest.mark.asyncio
async def test_notify_session_booking_telegram_only(session_notifier, telegram_credentials):
"""Test session booking notification with only Telegram enabled"""
# Disable email notifications
session_notifier.enable_email = False
# Mock the Telegram notification method
with patch.object(session_notifier, 'send_telegram_notification', new=MagicMock()) as mock_telegram:
# Set up the mock for the async method
mock_telegram.return_value = asyncio.Future()
mock_telegram.return_value.set_result(None)
# Call the method to test
await session_notifier.notify_session_booking("Test session")
# Verify only Telegram notification was called
mock_telegram.assert_called_once_with("Session booked: Test session")
@pytest.mark.asyncio
async def test_notify_upcoming_session(session_notifier, email_credentials, telegram_credentials):
"""Test upcoming session notification with both email and Telegram enabled"""
# Mock the email and Telegram notification methods
with patch.object(session_notifier, 'send_email_notification') as mock_email, \
patch.object(session_notifier, 'send_telegram_notification', new=MagicMock()) as mock_telegram:
# Set up the mock for the async method
mock_telegram.return_value = asyncio.Future()
mock_telegram.return_value.set_result(None)
# Call the method to test
await session_notifier.notify_upcoming_session("Test session", 3)
# Verify both notification methods were called
mock_email.assert_called_once_with("Session available soon: Test session (in 3 days)")
mock_telegram.assert_called_once_with("Session available soon: Test session (in 3 days)")
@pytest.mark.asyncio
async def test_notify_impossible_booking_enabled(session_notifier, email_credentials, telegram_credentials):
"""Test impossible booking notification when notifications are enabled"""
# Set the notify_impossible attribute to True
session_notifier.notify_impossible = True
# Mock the email and Telegram notification methods
with patch.object(session_notifier, 'send_email_notification') as mock_email, \
patch.object(session_notifier, 'send_telegram_notification', new=MagicMock()) as mock_telegram:
# Set up the mock for the async method
mock_telegram.return_value = asyncio.Future()
mock_telegram.return_value.set_result(None)
# Call the method to test
await session_notifier.notify_impossible_booking("Test session")
# Verify both notification methods were called
mock_email.assert_called_once_with("Failed to book session: Test session")
mock_telegram.assert_called_once_with("Failed to book session: Test session")
@pytest.mark.asyncio
async def test_notify_impossible_booking_disabled(session_notifier, email_credentials, telegram_credentials):
"""Test impossible booking notification when notifications are disabled"""
# Mock the email and Telegram notification methods
with patch.object(session_notifier, 'send_email_notification') as mock_email, \
patch.object(session_notifier, 'send_telegram_notification', new=MagicMock()) as mock_telegram:
# Set up the mock for the async method
mock_telegram.return_value = asyncio.Future()
mock_telegram.return_value.set_result(None)
# Call the method to test with notify_if_impossible=False
await session_notifier.notify_impossible_booking("Test session", notify_if_impossible=False)
# Verify neither notification method was called
mock_email.assert_not_called()
mock_telegram.assert_not_called()
@pytest.mark.asyncio
async def test_send_email_notification_success(session_notifier, email_credentials):
"""Test successful email notification"""
# Mock the smtplib.SMTP_SSL class
with patch('smtplib.SMTP_SSL') as mock_smtp:
# Set up the mock to return a context manager
mock_smtp_instance = MagicMock()
mock_smtp.return_value.__enter__.return_value = mock_smtp_instance
# Set up environment variable for SMTP server
with patch.dict(os.environ, {"SMTP_SERVER": "smtp.example.com"}):
# Call the method to test
session_notifier.send_email_notification("Test email")
# Verify SMTP methods were called
mock_smtp.assert_called_once_with("smtp.example.com", 465)
mock_smtp_instance.login.assert_called_once_with(
email_credentials["from"],
email_credentials["password"]
)
mock_smtp_instance.send_message.assert_called_once()
@pytest.mark.asyncio
async def test_send_email_notification_failure(session_notifier, email_credentials):
"""Test email notification failure"""
# Mock the smtplib.SMTP_SSL class to raise an exception
with patch('smtplib.SMTP_SSL', side_effect=Exception("SMTP error")):
# Set up environment variable for SMTP server
with patch.dict(os.environ, {"SMTP_SERVER": "smtp.example.com"}):
# Verify the method raises an exception
with pytest.raises(Exception):
session_notifier.send_email_notification("Test email")
if __name__ == "__main__":
pytest.main([__file__, "-v"])