All checks were successful
CI / lint-and-test (push) Successful in 23s
- Introduced new tests for the `import_duty_schedule_cmd` to verify behavior when no message or effective user is present, ensuring proper early returns. - Added tests for admin checks to confirm that only authorized users can initiate duty schedule imports, enhancing security. - Implemented error handling tests for the `handle_handover_time_text` function to ensure appropriate responses for invalid time formats and non-admin users. - Enhanced overall test coverage for the duty schedule import functionality, contributing to improved reliability and maintainability of the codebase. - Updated the `.coverage` file to reflect the latest coverage metrics.
81 lines
2.9 KiB
Python
81 lines
2.9 KiB
Python
"""Tests for duty_teller.handlers.errors (error_handler)."""
|
|
|
|
from unittest.mock import AsyncMock, MagicMock, patch
|
|
|
|
import pytest
|
|
|
|
from duty_teller.handlers.errors import error_handler
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_error_handler_replies_with_generic_message():
|
|
"""error_handler: when update has effective_message, reply_text with errors.generic."""
|
|
|
|
# Handler checks isinstance(update, Update); patch Update so our mock passes.
|
|
class FakeUpdate:
|
|
pass
|
|
|
|
update = FakeUpdate()
|
|
update.effective_message = MagicMock()
|
|
update.effective_message.reply_text = AsyncMock()
|
|
update.effective_user = MagicMock()
|
|
context = MagicMock()
|
|
context.error = Exception("test error")
|
|
|
|
with patch("duty_teller.handlers.errors.Update", FakeUpdate):
|
|
with patch("duty_teller.handlers.errors.get_lang", return_value="en"):
|
|
with patch("duty_teller.handlers.errors.t") as mock_t:
|
|
mock_t.return_value = "An error occurred."
|
|
await error_handler(update, context)
|
|
update.effective_message.reply_text.assert_called_once_with("An error occurred.")
|
|
mock_t.assert_called_with("en", "errors.generic")
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_error_handler_no_effective_message_does_not_send():
|
|
"""error_handler: when update has no effective_message, does not call reply_text."""
|
|
update = MagicMock()
|
|
update.effective_message = None
|
|
update.effective_user = MagicMock()
|
|
context = MagicMock()
|
|
context.error = Exception("test")
|
|
|
|
with patch("duty_teller.handlers.errors.get_lang", return_value="en"):
|
|
with patch("duty_teller.handlers.errors.t") as mock_t:
|
|
await error_handler(update, context)
|
|
mock_t.assert_not_called()
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_error_handler_update_none_does_not_crash():
|
|
"""error_handler: when update is None, does not crash (no reply)."""
|
|
context = MagicMock()
|
|
context.error = Exception("test")
|
|
await error_handler(None, context)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_error_handler_reply_text_raises_does_not_propagate():
|
|
"""error_handler: when reply_text raises, exception is caught and logged; does not propagate."""
|
|
|
|
class FakeUpdate:
|
|
pass
|
|
|
|
update = FakeUpdate()
|
|
update.effective_message = MagicMock()
|
|
update.effective_message.reply_text = AsyncMock(
|
|
side_effect=Exception("reply failed")
|
|
)
|
|
update.effective_user = MagicMock()
|
|
context = MagicMock()
|
|
context.error = Exception("test error")
|
|
|
|
with patch("duty_teller.handlers.errors.Update", FakeUpdate):
|
|
with patch("duty_teller.handlers.errors.get_lang", return_value="en"):
|
|
with patch(
|
|
"duty_teller.handlers.errors.t", return_value="An error occurred."
|
|
):
|
|
await error_handler(update, context)
|
|
# Handler must not raise; reply_text was attempted
|
|
update.effective_message.reply_text.assert_called_once()
|