Files
duty-teller/tests/test_api_dependencies.py
Nikolay Tatarinov e3240d0981 feat: enhance duty information handling with contact details and current duty view
- Added `bot_username` to settings for dynamic retrieval of the bot's username.
- Implemented `_resolve_bot_username` function to fetch the bot's username if not set, improving user experience in group chats.
- Updated `DutyWithUser` schema to include optional `phone` and `username` fields for enhanced duty information.
- Enhanced API responses to include contact details for users, ensuring better communication.
- Introduced a new current duty view in the web app, displaying active duty information along with contact options.
- Updated CSS styles for better presentation of contact information in duty cards.
- Added unit tests to verify the inclusion of contact details in API responses and the functionality of the current duty view.
2026-03-02 16:09:08 +03:00

102 lines
3.9 KiB
Python

"""Tests for duty_teller.api.dependencies (lang, auth error, date validation, private client)."""
from unittest.mock import patch
import pytest
from fastapi import HTTPException
import duty_teller.api.dependencies as deps
import duty_teller.config as config
class TestLangFromAcceptLanguage:
"""Tests for _lang_from_accept_language."""
def test_none_returns_default(self):
assert deps._lang_from_accept_language(None) == config.DEFAULT_LANGUAGE
def test_empty_string_returns_default(self):
assert deps._lang_from_accept_language("") == config.DEFAULT_LANGUAGE
assert deps._lang_from_accept_language(" ") == config.DEFAULT_LANGUAGE
def test_ru_ru_returns_ru(self):
assert deps._lang_from_accept_language("ru-RU,ru;q=0.9") == "ru"
def test_en_us_returns_en(self):
assert deps._lang_from_accept_language("en-US") == "en"
def test_invalid_fallback_to_en(self):
assert deps._lang_from_accept_language("zz") == "en"
assert deps._lang_from_accept_language("x") == "en"
class TestAuthErrorDetail:
"""Tests for _auth_error_detail."""
def test_hash_mismatch_uses_bad_signature_key(self):
with patch("duty_teller.api.dependencies.t") as mock_t:
mock_t.return_value = "Bad signature"
result = deps._auth_error_detail("hash_mismatch", "en")
assert result == "Bad signature"
mock_t.assert_called_once_with("en", "api.auth_bad_signature")
def test_other_reason_uses_auth_invalid_key(self):
with patch("duty_teller.api.dependencies.t") as mock_t:
mock_t.return_value = "Invalid auth"
result = deps._auth_error_detail("expired", "ru")
assert result == "Invalid auth"
mock_t.assert_called_once_with("ru", "api.auth_invalid")
class TestValidateDutyDates:
"""Tests for _validate_duty_dates."""
def test_valid_range_no_exception(self):
deps._validate_duty_dates("2025-01-01", "2025-01-31", "en")
def test_bad_format_raises_400_with_i18n(self):
with patch("duty_teller.api.dependencies.t") as mock_t:
mock_t.return_value = "Bad format message"
with pytest.raises(HTTPException) as exc_info:
deps._validate_duty_dates("01-01-2025", "2025-01-31", "en")
assert exc_info.value.status_code == 400
assert exc_info.value.detail == "Bad format message"
mock_t.assert_called_with("en", "dates.bad_format")
def test_from_after_to_raises_400_with_i18n(self):
with patch("duty_teller.api.dependencies.t") as mock_t:
mock_t.return_value = "From after to message"
with pytest.raises(HTTPException) as exc_info:
deps._validate_duty_dates("2025-02-01", "2025-01-01", "ru")
assert exc_info.value.status_code == 400
assert exc_info.value.detail == "From after to message"
mock_t.assert_called_with("ru", "dates.from_after_to")
class TestFetchDutiesResponse:
"""Tests for fetch_duties_response (DutyWithUser list with phone, username)."""
def test_fetch_duties_response_includes_phone_and_username(self):
"""get_duties returns (Duty, full_name, phone, username); response has phone, username."""
from types import SimpleNamespace
from duty_teller.db.schemas import DutyWithUser
duty = SimpleNamespace(
id=1,
user_id=10,
start_at="2025-01-15T09:00:00Z",
end_at="2025-01-15T18:00:00Z",
event_type="duty",
)
rows = [(duty, "Alice", "+79001234567", "alice_dev")]
with patch.object(deps, "get_duties", return_value=rows):
result = deps.fetch_duties_response(
type("Session", (), {})(), "2025-01-01", "2025-01-31"
)
assert len(result) == 1
assert isinstance(result[0], DutyWithUser)
assert result[0].full_name == "Alice"
assert result[0].phone == "+79001234567"
assert result[0].username == "alice_dev"