Files
Salon/backend/apps/accounts/tests/test_authentica_provider.py
2026-02-28 16:58:50 +03:00

104 lines
3.2 KiB
Python

"""Tests for Authentica OTP provider implementation."""
import os
from unittest.mock import MagicMock, patch
import pytest
from django.contrib.auth.hashers import make_password
from apps.accounts.models import OtpChannel, OtpPurpose, PhoneOTP
from apps.accounts.services.otp import AuthenticaOtpProvider, verify_otp
@patch("requests.post")
def test_authentica_send_otp_sms_calls_api(mock_post):
mock_response = MagicMock(ok=True)
mock_response.json.return_value = {"success": True}
mock_post.return_value = mock_response
with patch.dict(
os.environ,
{
"AUTHENTICA_API_KEY": "api-key",
"AUTHENTICA_BASE_URL": "https://api.authentica.sa",
"AUTHENTICA_TIMEOUT_SECONDS": "7",
},
):
provider = AuthenticaOtpProvider()
provider.send_otp("+966512345678", OtpChannel.SMS)
mock_post.assert_called_once()
url = mock_post.call_args[0][0]
kwargs = mock_post.call_args[1]
assert url == "https://api.authentica.sa/api/v2/send-otp"
assert kwargs["json"] == {"method": "sms", "phone": "+966512345678"}
assert kwargs["headers"]["X-Authorization"] == "api-key"
assert kwargs["timeout"] == 7.0
@patch("requests.post")
def test_authentica_send_sms_calls_api(mock_post):
mock_response = MagicMock(ok=True)
mock_response.json.return_value = {"success": True}
mock_post.return_value = mock_response
with patch.dict(
os.environ,
{
"AUTHENTICA_API_KEY": "api-key",
"AUTHENTICA_SENDER_NAME": "Salon",
},
):
provider = AuthenticaOtpProvider()
provider.send_sms("+966512345678", "Hello")
mock_post.assert_called_once()
url = mock_post.call_args[0][0]
kwargs = mock_post.call_args[1]
assert url == "https://api.authentica.sa/api/v2/send-sms"
assert kwargs["json"] == {
"phone": "+966512345678",
"message": "Hello",
"sender_name": "Salon",
}
@patch("requests.post")
def test_authentica_verify_otp_calls_api(mock_post):
mock_response = MagicMock(ok=True)
mock_response.json.return_value = {"verified": True}
mock_post.return_value = mock_response
with patch.dict(os.environ, {"AUTHENTICA_API_KEY": "api-key"}):
provider = AuthenticaOtpProvider()
assert provider.verify_otp("+966512345678", "123456") is True
mock_post.assert_called_once()
url = mock_post.call_args[0][0]
kwargs = mock_post.call_args[1]
assert url == "https://api.authentica.sa/api/v2/verify-otp"
assert kwargs["json"] == {"phone": "+966512345678", "otp": "123456"}
@pytest.mark.django_db
def test_verify_otp_uses_provider_for_authentica():
otp = PhoneOTP.objects.create(
phone_number="+966512345678",
channel=OtpChannel.SMS,
purpose=OtpPurpose.AUTH,
provider="authentica",
code_hash=make_password("unused"),
expires_at=PhoneOTP.expiry_at(),
)
with patch("apps.accounts.services.otp.AuthenticaOtpProvider.verify_otp", return_value=True) as mock_verify:
assert verify_otp(otp, "123456") is True
mock_verify.assert_called_once_with("+966512345678", "123456")
otp.refresh_from_db()
assert otp.verified_at is not None
assert otp.attempt_count == 1