tests/views: deprecate httmock (#85304)

This commit is contained in:
Paul Marillonnet 2024-01-11 16:17:18 +01:00
parent fc5ec7d69e
commit 37c5ffb013
1 changed files with 88 additions and 99 deletions

View File

@ -20,12 +20,10 @@ from unittest import mock
from urllib.parse import urlparse
import pytest
import responses
from django.urls import reverse
from django.utils.html import escape
from django.utils.timezone import now
from httmock import HTTMock, remember_called
from httmock import response as httmock_response
from httmock import urlmatch
from authentic2.apps.authenticators.models import LoginPasswordAuthenticator
from authentic2.custom_user.models import DeletedUser, User
@ -38,18 +36,6 @@ from .utils import assert_event, get_link_from_mail, login, logout
pytestmark = pytest.mark.django_db
@urlmatch(netloc='foo.whatever.none')
@remember_called
def sms_service_mock(url, request):
return {
'content': {},
'headers': {
'content-type': 'application/json',
},
'status_code': 200,
}
def test_profile(app, simple_user):
page = login(app, simple_user, path=reverse('account_management'))
assert simple_user.first_name in page
@ -354,8 +340,10 @@ class TestDeleteAccountEmailNotVerified:
assert urlparse(response.location).path == '/'
@responses.activate
def test_delete_account_phone_identifier(app, nomail_user, settings, phone_activated_authn):
settings.SMS_URL = 'https://foo.whatever.none/'
responses.post('https://foo.whatever.none/', status=200)
nomail_user.attributes.phone = '+33122446666'
nomail_user.phone_verified_on = now()
@ -366,8 +354,7 @@ def test_delete_account_phone_identifier(app, nomail_user, settings, phone_activ
)
resp = app.get('/accounts/delete/')
assert 'A validation code will be sent to +33122446666' in resp.text
with HTTMock(sms_service_mock):
resp = resp.form.submit().follow()
resp = resp.form.submit().follow()
code = SMSCode.objects.get()
assert not Token.objects.count()
resp.form.set('sms_code', code.value)
@ -377,8 +364,10 @@ def test_delete_account_phone_identifier(app, nomail_user, settings, phone_activ
User.objects.get(id=nomail_user_id)
@responses.activate
def test_delete_account_phone_identifier_deactivated_user(app, nomail_user, settings, phone_activated_authn):
settings.SMS_URL = 'https://foo.whatever.none/'
responses.post('https://foo.whatever.none/', status=200)
nomail_user.attributes.phone = '+33122446666'
nomail_user.phone_verified_on = now()
@ -388,8 +377,7 @@ def test_delete_account_phone_identifier_deactivated_user(app, nomail_user, sett
app, nomail_user, login=nomail_user.attributes.phone, path='/accounts/', password=nomail_user.username
)
resp = app.get('/accounts/delete/')
with HTTMock(sms_service_mock):
resp = resp.form.submit().follow()
resp = resp.form.submit().follow()
code = SMSCode.objects.get()
resp.form.set('sms_code', code.value)
nomail_user.is_active = False
@ -419,10 +407,12 @@ def test_delete_account_phone_verified_yet_missing(app, nomail_user, settings, p
assert '+33122446666' not in resp.html
@responses.activate
def test_delete_account_verified_email_precedence_over_verified_phone(
app, simple_user, settings, phone_activated_authn
):
settings.SMS_URL = 'https://foo.whatever.none/'
responses.post('https://foo.whatever.none/', status=200)
simple_user.attributes.phone = '+33122446666'
simple_user.email_verified = True
@ -434,15 +424,16 @@ def test_delete_account_verified_email_precedence_over_verified_phone(
resp = app.get('/accounts/delete/')
# email is verified and defaults as deletion code exchange means
assert 'A validation message will be sent to user@example.net.' in resp.text
with HTTMock(sms_service_mock):
resp = resp.form.submit().follow()
resp.form.submit().follow()
assert not SMSCode.objects.count()
@responses.activate
def test_delete_account_verified_phone_precedence_over_unverified_email(
app, simple_user, settings, phone_activated_authn
):
settings.SMS_URL = 'https://foo.whatever.none/'
responses.post('https://foo.whatever.none/', status=200)
simple_user.attributes.phone = '+33122446666'
simple_user.email_verified = False
@ -455,15 +446,16 @@ def test_delete_account_verified_phone_precedence_over_unverified_email(
# email is unverified and skipped as deletion code exchange means
# fallback on phone
assert 'A validation code will be sent to +33122446666' in resp.text
with HTTMock(sms_service_mock):
resp = resp.form.submit().follow()
resp.form.submit().follow()
assert SMSCode.objects.get()
@responses.activate
def test_delete_account_unverified_identifiers_direct_deletion(
app, simple_user, settings, phone_activated_authn
):
settings.SMS_URL = 'https://foo.whatever.none/'
responses.post('https://foo.whatever.none/', status=200)
simple_user.attributes.phone = '+33122446666'
simple_user.email_verified = False
@ -478,18 +470,19 @@ def test_delete_account_unverified_identifiers_direct_deletion(
# deletion process is direct
assert 'A validation message' not in resp.text
assert 'A validation code' not in resp.text
with HTTMock(sms_service_mock):
resp.form.submit().follow()
resp.form.submit().follow()
assert not SMSCode.objects.count()
assert not Token.objects.count()
with pytest.raises(User.DoesNotExist):
User.objects.get(id=simple_user_id)
@responses.activate
def test_delete_account_phone_identifier_changed_in_between(
app, nomail_user, settings, phone_activated_authn
):
settings.SMS_URL = 'https://foo.whatever.none/'
responses.post('https://foo.whatever.none/', status=200)
nomail_user.attributes.phone = '+33122446666'
nomail_user.phone_verified_on = now()
@ -500,8 +493,7 @@ def test_delete_account_phone_identifier_changed_in_between(
)
resp = app.get('/accounts/delete/')
assert 'A validation code will be sent to +33122446666' in resp.text
with HTTMock(sms_service_mock):
resp = resp.form.submit().follow()
resp = resp.form.submit().follow()
code = SMSCode.objects.get()
nomail_user.attributes.phone = '+33122446688'
nomail_user.save()
@ -525,73 +517,50 @@ def test_custom_account(settings, app, simple_user):
@pytest.mark.parametrize('view_name', ['registration_register', 'password_reset', 'phone-change'])
@responses.activate
def test_views_sms_ratelimit(app, db, simple_user, settings, freezer, view_name, phone_activated_authn):
freezer.move_to('2020-01-01')
LoginPasswordAuthenticator.objects.update(sms_ip_ratelimit='10/h', sms_number_ratelimit='3/d')
settings.SMS_SENDER = 'EO'
settings.SMS_URL = 'https://www.example.com/send'
responses.post('https://www.example.com/send', status=200)
@urlmatch(scheme='https', netloc='www.example.com', path='/send')
def sms_endpoint_response(url, request):
return httmock_response(200, {})
with HTTMock(sms_endpoint_response):
if view_name in ('phone-change',):
login(app, simple_user)
if view_name in ('phone-change',):
login(app, simple_user)
response = app.get(reverse(view_name))
response.form.set('phone_0', '33')
response.form.set('phone_1', '0612345678')
if view_name in ('phone-change',):
response.form.set('password', simple_user.username)
response = response.form.submit()
assert 'try again later' not in response.text
for _ in range(2):
response = app.get(reverse(view_name))
response.form.set('phone_0', '33')
response.form.set('phone_1', '0612345678')
if view_name in ('phone-change',):
response.form.set('password', simple_user.username)
response = response.form.submit()
assert 'An SMS code has already been sent' in response.text
if view_name in ('phone-change',):
response.form.set('password', simple_user.username)
response = response.form.submit()
assert 'try again later' not in response.text
for _ in range(2):
response = app.get(reverse(view_name))
response.form.set('phone_0', '33')
response.form.set('phone_1', '0612345678')
if view_name in ('phone-change',):
response.form.set('password', simple_user.username)
response = response.form.submit()
assert 'An SMS code has already been sent' in response.text
if view_name in ('phone-change',):
response.form.set('password', simple_user.username)
response = response.form.submit()
assert 'try again later' not in response.text
response = app.get(reverse(view_name))
response.form.set('phone_0', '33')
response.form.set('phone_1', '0612345678')
if view_name in ('phone-change',):
response.form.set('password', simple_user.username)
response = response.form.submit()
if view_name in ('phone-change',):
response.form.set('password', simple_user.username)
response = response.form.submit()
assert 'try again later' in response.text
response = app.get(reverse(view_name))
response.form.set('phone_0', '33')
response.form.set('phone_1', '0612345678')
if view_name in ('phone-change',):
response.form.set('password', simple_user.username)
response = response.form.submit()
if view_name in ('phone-change',):
response.form.set('password', simple_user.username)
response = response.form.submit()
assert 'try again later' in response.text
suffixes = iter(range(6000, 9999))
# reach ip limit
for _ in range(7):
response = app.get(reverse(view_name))
random_suffix = next(suffixes)
response.form.set('phone_0', '33')
response.form.set('phone_1', f'061234{random_suffix:04d}')
if view_name in ('phone-change',):
response.form.set('password', simple_user.username)
response = response.form.submit()
assert 'try again later' not in response.text
response = app.get(reverse(view_name))
random_suffix = next(suffixes)
response.form.set('phone_0', '33')
response.form.set('phone_1', f'061234{random_suffix:04d}')
if view_name in ('phone-change',):
response.form.set('password', simple_user.username)
response = response.form.submit()
assert 'try again later' in response.text
# ip ratelimits are lifted after an hour
freezer.tick(datetime.timedelta(hours=1))
suffixes = iter(range(6000, 9999))
# reach ip limit
for _ in range(7):
response = app.get(reverse(view_name))
random_suffix = next(suffixes)
response.form.set('phone_0', '33')
@ -601,27 +570,47 @@ def test_views_sms_ratelimit(app, db, simple_user, settings, freezer, view_name,
response = response.form.submit()
assert 'try again later' not in response.text
# identifier ratelimits are lifted after a day
response = app.get(reverse(view_name))
response.form.set('phone_0', '33')
response.form.set('phone_1', '0612345678')
if view_name in ('phone-change',):
response.form.set('password', simple_user.username)
response = response.form.submit()
assert 'Multiple SMSs have already been sent to this number.' in response.text
if view_name in ('phone-change',):
response.form.set('password', simple_user.username)
response = response.form.submit()
assert 'try again later' in response.text
response = app.get(reverse(view_name))
random_suffix = next(suffixes)
response.form.set('phone_0', '33')
response.form.set('phone_1', f'061234{random_suffix:04d}')
if view_name in ('phone-change',):
response.form.set('password', simple_user.username)
response = response.form.submit()
assert 'try again later' in response.text
freezer.tick(datetime.timedelta(days=1))
response = app.get(reverse(view_name))
response.form.set('phone_0', '33')
response.form.set('phone_1', '0612345678')
if view_name in ('phone-change',):
response.form.set('password', simple_user.username)
response = response.form.submit()
assert 'try again later' not in response.text
# ip ratelimits are lifted after an hour
freezer.tick(datetime.timedelta(hours=1))
response = app.get(reverse(view_name))
random_suffix = next(suffixes)
response.form.set('phone_0', '33')
response.form.set('phone_1', f'061234{random_suffix:04d}')
if view_name in ('phone-change',):
response.form.set('password', simple_user.username)
response = response.form.submit()
assert 'try again later' not in response.text
# identifier ratelimits are lifted after a day
response = app.get(reverse(view_name))
response.form.set('phone_0', '33')
response.form.set('phone_1', '0612345678')
if view_name in ('phone-change',):
response.form.set('password', simple_user.username)
response = response.form.submit()
assert 'Multiple SMSs have already been sent to this number.' in response.text
if view_name in ('phone-change',):
response.form.set('password', simple_user.username)
response = response.form.submit()
assert 'try again later' in response.text
freezer.tick(datetime.timedelta(days=1))
response = app.get(reverse(view_name))
response.form.set('phone_0', '33')
response.form.set('phone_1', '0612345678')
if view_name in ('phone-change',):
response.form.set('password', simple_user.username)
response = response.form.submit()
assert 'try again later' not in response.text
@pytest.mark.parametrize('view_name', ['registration_register', 'password_reset'])