54 lines
1.6 KiB
Python
54 lines
1.6 KiB
Python
import pytest
|
|
from pydantic import ValidationError
|
|
|
|
from app.domain import DomainError
|
|
from app.schemas import CallbackItem, SendRequest
|
|
from app.service import validate_otp_request
|
|
|
|
|
|
def valid_send(**overrides) -> SendRequest:
|
|
payload = {
|
|
"idempotency_key": "keycloak:challenge:01JABCDEF",
|
|
"template_code": "auth_otp",
|
|
"locale": "ru",
|
|
"phone_e164": "+79001234567",
|
|
"substitutions": {"code": "482193", "ttl_min": "1"},
|
|
"customer_ref": "01JABCDEF",
|
|
"message_ttl_sec": 60,
|
|
}
|
|
payload.update(overrides)
|
|
return SendRequest.model_validate(payload)
|
|
|
|
|
|
def test_send_request_is_strict() -> None:
|
|
with pytest.raises(ValidationError):
|
|
valid_send(extra="forbidden")
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("substitutions", "ttl"),
|
|
[
|
|
({"code": "12ab", "ttl_min": "1"}, 60),
|
|
({"code": "123456", "ttl_min": "2"}, 60),
|
|
({"code": "123456", "ttl_min": "1"}, 61),
|
|
],
|
|
)
|
|
def test_otp_substitutions_match_ttl(substitutions, ttl) -> None:
|
|
with pytest.raises(DomainError):
|
|
validate_otp_request(valid_send(substitutions=substitutions, message_ttl_sec=ttl))
|
|
|
|
|
|
def test_callback_accepts_provider_camel_case() -> None:
|
|
item = CallbackItem.model_validate(
|
|
{
|
|
"channelType": "SMS",
|
|
"messageUuid": "provider-id",
|
|
"externalMessageId": "internal-id",
|
|
"callbackEvent": "delivered",
|
|
"status": "delivered",
|
|
"statusTime": "2026-07-22T12:00:00Z",
|
|
}
|
|
)
|
|
assert item.channel_type == "SMS"
|
|
assert item.status_time.tzinfo is not None
|