Реализована интеграция с СМС провайдером
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
import pytest
|
||||
|
||||
from app.db import DeliveryStatus
|
||||
from app.domain import (
|
||||
DomainError,
|
||||
delivery_transition,
|
||||
normalize_phone,
|
||||
render_template,
|
||||
request_fingerprint,
|
||||
sms_parts,
|
||||
)
|
||||
|
||||
|
||||
def test_phone_is_canonical_and_masked() -> None:
|
||||
e164, digits, masked = normalize_phone("+79001234567")
|
||||
assert e164 == "+79001234567"
|
||||
assert digits == "79001234567"
|
||||
assert masked == "+7******4567"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("phone", ["79001234567", "+012345678", "+7900", "+7999999999999999"])
|
||||
def test_invalid_phone_is_rejected(phone: str) -> None:
|
||||
with pytest.raises(DomainError) as error:
|
||||
normalize_phone(phone)
|
||||
assert error.value.code == "sms_request_invalid"
|
||||
|
||||
|
||||
def test_strict_template_render() -> None:
|
||||
result = render_template(
|
||||
"Код входа: {code}. Действителен {ttl_min} мин.",
|
||||
["code", "ttl_min"],
|
||||
{"code": "482193", "ttl_min": 1},
|
||||
1,
|
||||
)
|
||||
assert result == "Код входа: 482193. Действителен 1 мин."
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"substitutions",
|
||||
[
|
||||
{"code": "482193"},
|
||||
{"code": "482193", "ttl_min": 1, "extra": "forbidden"},
|
||||
],
|
||||
)
|
||||
def test_template_rejects_placeholder_mismatch(substitutions) -> None:
|
||||
with pytest.raises(DomainError):
|
||||
render_template(
|
||||
"Код: {code}; TTL: {ttl_min}",
|
||||
["code", "ttl_min"],
|
||||
substitutions,
|
||||
1,
|
||||
)
|
||||
|
||||
|
||||
def test_template_rejects_format_expressions() -> None:
|
||||
with pytest.raises(DomainError):
|
||||
render_template("{code!r}", ["code"], {"code": "123456"}, 1)
|
||||
|
||||
|
||||
def test_sms_parts_supports_gsm_and_unicode() -> None:
|
||||
assert sms_parts("A" * 160) == 1
|
||||
assert sms_parts("A" * 161) == 2
|
||||
assert sms_parts("Я" * 70) == 1
|
||||
assert sms_parts("Я" * 71) == 2
|
||||
|
||||
|
||||
def test_fingerprint_is_canonical() -> None:
|
||||
first = request_fingerprint({"b": 2, "a": {"y": 2, "x": 1}})
|
||||
second = request_fingerprint({"a": {"x": 1, "y": 2}, "b": 2})
|
||||
assert first == second
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("current", "incoming", "expected"),
|
||||
[
|
||||
(DeliveryStatus.UNKNOWN, "sent", DeliveryStatus.SENT),
|
||||
(DeliveryStatus.SENT, "delivered", DeliveryStatus.DELIVERED),
|
||||
(DeliveryStatus.DELIVERED, "sent", DeliveryStatus.DELIVERED),
|
||||
(DeliveryStatus.UNDELIVERED, "sent", DeliveryStatus.UNDELIVERED),
|
||||
(DeliveryStatus.DELIVERED, "unsent", DeliveryStatus.DELIVERED),
|
||||
(DeliveryStatus.UNKNOWN, "bogus", None),
|
||||
],
|
||||
)
|
||||
def test_delivery_status_is_monotonic(current, incoming, expected) -> None:
|
||||
assert delivery_transition(current, incoming) == expected
|
||||
Reference in New Issue
Block a user