Added Authentica OTP
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
"""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
|
||||
Reference in New Issue
Block a user