Skip to content

Commit

Permalink
refactor login/username test cases into pytest TestUsernameLoginFields
Browse files Browse the repository at this point in the history
  • Loading branch information
tomwojcik committed Jun 7, 2024
1 parent 7bed216 commit 95ae2a7
Show file tree
Hide file tree
Showing 3 changed files with 139 additions and 215 deletions.
3 changes: 3 additions & 0 deletions djoser/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,9 @@ def __init__(self, *args, **kwargs):

def validate(self, attrs):
password = attrs.get("password")
# https://github.com/sunscrapers/djoser/issues/389
# https://github.com/sunscrapers/djoser/issues/429
# https://github.com/sunscrapers/djoser/issues/795
params = {"username": attrs.get(settings.LOGIN_FIELD)}
self.user = authenticate(
request=self.context.get("request"), **params, password=password
Expand Down
215 changes: 0 additions & 215 deletions testproject/testapp/tests/test_token_create.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
from django.conf import settings as django_settings
from unittest import mock

from django.contrib.auth import user_logged_in, user_login_failed
from django.contrib.auth.backends import ModelBackend
from django.test import override_settings
from djet import assertions
from rest_framework import status
from rest_framework.reverse import reverse
Expand Down Expand Up @@ -39,216 +34,6 @@ def test_post_should_login_user(self):
self.assertNotEqual(user.last_login, previous_last_login)
self.assertTrue(self.signal_sent)

@override_settings(
AUTHENTICATION_BACKENDS=[
"django.contrib.auth.backends.ModelBackend",
],
DJOSER=dict(django_settings.DJOSER, **{"LOGIN_FIELD": "username"}),
)
def test_login__LOGIN_FIELD_username__USERNAME_FIELD_username(
self,
):
user = create_user()
user_logged_in.connect(self.signal_receiver)
previous_last_login = user.last_login

with mock.patch("djoser.serializers.User.USERNAME_FIELD", "username"):
with mock.patch.object(
ModelBackend, "user_can_authenticate", return_value=True
):
response = self.client.post(
self.base_url,
{"username": user.username, "password": user.raw_password},
)
self.assert_status_equal(response, status.HTTP_200_OK)

user.refresh_from_db()
self.assertEqual(response.data["auth_token"], user.auth_token.key)
self.assertNotEqual(user.last_login, previous_last_login)
self.assertTrue(self.signal_sent)

with mock.patch.object(
ModelBackend, "user_can_authenticate", return_value=False
):
response = self.client.post(
self.base_url,
{"username": user.username, "password": user.raw_password},
)
self.assert_status_equal(response, status.HTTP_400_BAD_REQUEST)

with mock.patch.object(
ModelBackend, "user_can_authenticate", return_value=True
):
response = self.client.post(
self.base_url, {"email": user.email, "password": user.raw_password}
)
self.assert_status_equal(response, status.HTTP_400_BAD_REQUEST)

with mock.patch.object(
ModelBackend, "user_can_authenticate", return_value=False
):
response = self.client.post(
self.base_url, {"email": user.email, "password": user.raw_password}
)
self.assert_status_equal(response, status.HTTP_400_BAD_REQUEST)

@override_settings(
AUTHENTICATION_BACKENDS=[
"django.contrib.auth.backends.ModelBackend",
],
DJOSER=dict(django_settings.DJOSER, **{"LOGIN_FIELD": "email"}),
)
def test_login__LOGIN_FIELD_email__USERNAME_FIELD_username(
self,
):
user = create_user()
user_logged_in.connect(self.signal_receiver)
previous_last_login = user.last_login

with mock.patch("djoser.serializers.User.USERNAME_FIELD", "username"):
with mock.patch.object(
ModelBackend, "user_can_authenticate", return_value=True
):
response = self.client.post(
self.base_url,
{"username": user.username, "password": user.raw_password},
)
self.assert_status_equal(response, status.HTTP_400_BAD_REQUEST)

with mock.patch.object(
ModelBackend, "user_can_authenticate", return_value=False
):
response = self.client.post(
self.base_url,
{"username": user.username, "password": user.raw_password},
)
self.assert_status_equal(response, status.HTTP_400_BAD_REQUEST)

with mock.patch.object(
ModelBackend, "user_can_authenticate", return_value=True
):
response = self.client.post(
self.base_url, {"email": user.email, "password": user.raw_password}
)
self.assert_status_equal(response, status.HTTP_400_BAD_REQUEST)

with mock.patch.object(
ModelBackend, "user_can_authenticate", return_value=False
):
response = self.client.post(
self.base_url, {"email": user.email, "password": user.raw_password}
)
self.assert_status_equal(response, status.HTTP_400_BAD_REQUEST)

user.refresh_from_db()
self.assertEqual(user.last_login, previous_last_login)
self.assertFalse(self.signal_sent)

@override_settings(
AUTHENTICATION_BACKENDS=[
"django.contrib.auth.backends.ModelBackend",
],
DJOSER=dict(django_settings.DJOSER, **{"LOGIN_FIELD": "username"}),
)
def test_login__LOGIN_FIELD_username__USERNAME_FIELD_email(
self,
):
user = create_user()
user_logged_in.connect(self.signal_receiver)
previous_last_login = user.last_login

with mock.patch("djoser.serializers.User.USERNAME_FIELD", "email"):
with mock.patch.object(
ModelBackend, "user_can_authenticate", return_value=True
):
response = self.client.post(
self.base_url,
{"username": user.username, "password": user.raw_password},
)
self.assert_status_equal(response, status.HTTP_400_BAD_REQUEST)

with mock.patch.object(
ModelBackend, "user_can_authenticate", return_value=False
):
response = self.client.post(
self.base_url,
{"username": user.username, "password": user.raw_password},
)
self.assert_status_equal(response, status.HTTP_400_BAD_REQUEST)

with mock.patch.object(
ModelBackend, "user_can_authenticate", return_value=True
):
response = self.client.post(
self.base_url, {"email": user.email, "password": user.raw_password}
)
self.assert_status_equal(response, status.HTTP_400_BAD_REQUEST)

with mock.patch.object(
ModelBackend, "user_can_authenticate", return_value=False
):
response = self.client.post(
self.base_url, {"email": user.email, "password": user.raw_password}
)
self.assert_status_equal(response, status.HTTP_400_BAD_REQUEST)

user.refresh_from_db()
self.assertEqual(user.last_login, previous_last_login)
self.assertFalse(self.signal_sent)

@override_settings(
AUTHENTICATION_BACKENDS=[
"django.contrib.auth.backends.ModelBackend",
],
DJOSER=dict(django_settings.DJOSER, **{"LOGIN_FIELD": "email"}),
)
def test_login__LOGIN_FIELD_email__USERNAME_FIELD_email(
self,
):
user = create_user()
user_logged_in.connect(self.signal_receiver)
previous_last_login = user.last_login

with mock.patch("djoser.serializers.User.USERNAME_FIELD", "email"):
with mock.patch.object(
ModelBackend, "user_can_authenticate", return_value=True
):
response = self.client.post(
self.base_url,
{"username": user.username, "password": user.raw_password},
)
self.assert_status_equal(response, status.HTTP_400_BAD_REQUEST)

with mock.patch.object(
ModelBackend, "user_can_authenticate", return_value=False
):
response = self.client.post(
self.base_url,
{"username": user.username, "password": user.raw_password},
)
self.assert_status_equal(response, status.HTTP_400_BAD_REQUEST)

with mock.patch.object(
ModelBackend, "user_can_authenticate", return_value=True
):
response = self.client.post(
self.base_url, {"email": user.email, "password": user.raw_password}
)
self.assert_status_equal(response, status.HTTP_200_OK)

user.refresh_from_db()
self.assertEqual(response.data["auth_token"], user.auth_token.key)
self.assertNotEqual(user.last_login, previous_last_login)
self.assertTrue(self.signal_sent)

with mock.patch.object(
ModelBackend, "user_can_authenticate", return_value=False
):
response = self.client.post(
self.base_url, {"email": user.email, "password": user.raw_password}
)
self.assert_status_equal(response, status.HTTP_400_BAD_REQUEST)

def test_post_should_not_login_if_user_is_not_active(self):
"""In Django >= 1.10 authenticate() returns None if user is inactive,
while in Django < 1.10 authenticate() succeeds if user is inactive."""
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
from unittest import mock

import pytest
from django.contrib.auth import user_logged_in, user_login_failed
from django.contrib.auth.backends import ModelBackend
from rest_framework import status
from rest_framework.reverse import reverse

from testapp.tests.common import create_user


@pytest.mark.django_db
class TestUsernameLoginFields:
url = reverse("login")

@pytest.fixture(autouse=True)
def settings(self, settings):
settings.AUTHENTICATION_BACKENDS = [
"django.contrib.auth.backends.ModelBackend",
]
return settings

@pytest.fixture
def user(self):
return create_user()

@pytest.fixture
def signal_user_logged_in_patched(self):
signal_handler = mock.MagicMock()
user_logged_in.connect(signal_handler)
return signal_handler

@pytest.fixture
def signal_user_login_failed_patched(self):
signal_handler = mock.MagicMock()
user_login_failed.connect(signal_handler)
return signal_handler

def configure_djoser_settings(
self, settings, mocker, login_field, username_field, user_can_authenticate
):
settings.DJOSER["LOGIN_FIELD"] = login_field
mocker.patch("djoser.serializers.settings.LOGIN_FIELD", login_field)
mocker.patch("djoser.serializers.User.USERNAME_FIELD", username_field)
mocker.patch.object(
ModelBackend, "user_can_authenticate", return_value=user_can_authenticate
)

@pytest.mark.parametrize(
"login_field, username_field, send_field",
[
("username", "username", "username"),
("email", "email", "email"),
],
)
def test_successful_login(
self,
user,
client,
settings,
mocker,
signal_user_logged_in_patched,
login_field,
username_field,
send_field,
):
self.configure_djoser_settings(
settings=settings,
mocker=mocker,
login_field=login_field,
username_field=username_field,
user_can_authenticate=True,
)

if send_field == "username":
data = {"username": user.username, "password": user.raw_password}
else:
data = {"email": user.email, "password": user.raw_password}

previous_last_login = user.last_login
response = client.post(self.url, data)

assert response.status_code == status.HTTP_200_OK
user.refresh_from_db()

assert response.data["auth_token"] == user.auth_token.key
assert user.last_login != previous_last_login
signal_user_logged_in_patched.assert_called_once()

@pytest.mark.parametrize(
"login_field, username_field, user_can_authenticate, send_field",
[
("username", "username", False, "username"),
("username", "username", True, "email"),
("username", "email", True, "username"),
("username", "email", False, "username"),
("email", "username", False, "username"),
("email", "username", True, "email"),
("email", "email", True, "username"),
("email", "email", False, "username"),
("username", "email", True, "email"),
("email", "username", True, "username"),
],
)
def test_failing_login(
self,
user,
client,
settings,
mocker,
signal_user_login_failed_patched,
login_field,
username_field,
send_field,
user_can_authenticate,
):
self.configure_djoser_settings(
settings=settings,
mocker=mocker,
login_field=login_field,
username_field=username_field,
user_can_authenticate=user_can_authenticate,
)
if send_field == "username":
data = {"username": user.username, "password": user.raw_password}
else:
data = {"email": user.email, "password": user.raw_password}

previous_last_login = user.last_login
response = client.post(self.url, data)

assert response.status_code == status.HTTP_400_BAD_REQUEST
user.refresh_from_db()

assert user.last_login == previous_last_login
signal_user_login_failed_patched.assert_called_once()

0 comments on commit 95ae2a7

Please sign in to comment.