Skip to content

Commit

Permalink
refactor old test cases and write some more test cases for views (#33)
Browse files Browse the repository at this point in the history
  • Loading branch information
sumit4613 committed Sep 13, 2020
1 parent 0af23f2 commit ee5760d
Show file tree
Hide file tree
Showing 5 changed files with 133 additions and 83 deletions.
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,10 @@ format:
black --exclude .+/migrations/.+\.py drf_user

test:
$(PYTHON) -m pytest --ds=tests.settings --cov=drf_user tests/
$(PYTHON) -m pytest --disable-pytest-warnings --ds=tests.settings --cov=drf_user tests/

test-coverage: clean-test
$(PYTHON) -m pytest --ds=tests.settings --cov=drf_user tests/ --cov-report html
$(PYTHON) -m pytest --disable-pytest-warnings --ds=tests.settings --cov=drf_user tests/ --cov-report html

test-all:
tox
Expand Down
6 changes: 6 additions & 0 deletions drf_user/serializers.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Serializers related to drf-user"""
from django.contrib.auth.password_validation import validate_password
from django.utils.text import gettext_lazy as _
from rest_framework import serializers

Expand Down Expand Up @@ -67,6 +68,11 @@ def validate_mobile(self, value: str) -> str:
else:
return value

def validate_password(self, value: str) -> str:
"""Validate whether the password meets all django validator requirements."""
validate_password(value)
return value

class Meta:
"""Passing model metadata"""

Expand Down
2 changes: 1 addition & 1 deletion drf_user/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ def update(self, request, *args, **kwargs):
"""Updates user's password"""

if "password" in request.data.keys():
self.request.user.set_password(request.data.pop("password"))
self.request.user.set_password(request.data["password"])
self.request.user.save()

return super(RetrieveUpdateUserAccountView, self).update(
Expand Down
21 changes: 21 additions & 0 deletions tests/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,24 @@
}

AUTH_USER_MODEL = "drf_user.User"

USER_SETTINGS = {
"DEFAULT_ACTIVE_STATE": False,
"OTP": {
"LENGTH": 7,
"ALLOWED_CHARS": "1234567890",
"VALIDATION_ATTEMPTS": 3,
"SUBJECT": "OTP for Verification",
"COOLING_PERIOD": 3,
},
"MOBILE_VALIDATION": True,
"EMAIL_VALIDATION": True,
"REGISTRATION": {
"SEND_MAIL": False,
"SEND_MESSAGE": False,
"MAIL_SUBJECT": "Welcome to DRF-USER",
"SMS_BODY": "Your account has been created",
"TEXT_MAIL_BODY": "Your account has been created.",
"HTML_MAIL_BODY": "Your account has been created.",
},
}
183 changes: 103 additions & 80 deletions tests/test_views.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,20 @@
"""Tests for drf_user/views.py module"""
import pytest
from django.test import Client
from django.test import TestCase
from django.test.client import RequestFactory
from django.urls import reverse
from model_bakery import baker
from rest_framework import status
from rest_framework.test import force_authenticate
from rest_framework.test import APITestCase

from drf_user.models import AuthTransaction
from drf_user.models import User
from drf_user.views import RetrieveUpdateUserAccountView


class TestLoginView(TestCase):
class TestLoginView(APITestCase):
"""LoginView Test"""

def setUp(self) -> None:
"""Create Client object to call the API"""
self.client = Client()
"""SetUp test data"""
self.url = reverse("Login")

"""Create User object using model_bakery"""
self.user = baker.make(
"drf_user.User",
username="user",
Expand All @@ -30,48 +24,48 @@ def setUp(self) -> None:
is_active=True,
)

"""Setting user's password"""
self.user.set_password("pass123")
self.user.save()

@pytest.mark.django_db
def test_object_created(self):
"""Check if the User object is created or not"""
self.assertEqual(User.objects.count(), 1)
assert User.objects.count() == 1

@pytest.mark.django_db
def test_successful_login_view(self):
"""Check if the credentials are correct"""
response = self.client.post(
reverse("Login"), data={"username": "user", "password": "pass123"}
self.url, data={"username": "user", "password": "pass123"}
)
self.assertEqual(response.status_code, status.HTTP_200_OK)

assert response.status_code == 200

@pytest.mark.django_db
def test_unsuccessful_login_view(self):
"""Check if the credentials are incorrect"""
response = self.client.post(
reverse("Login"), data={"username": "user", "password": "pass1234"}
self.url, data={"username": "user", "password": "pass1234"}
)
self.assertEqual(response.status_code, status.HTTP_422_UNPROCESSABLE_ENTITY)

assert response.status_code == 422


class TestRetrieveUpdateUserAccountView(TestCase):
class TestRetrieveUpdateUserAccountView(APITestCase):
"""RetrieveUpdateUserAccountView Test"""

def setUp(self) -> None:
"""Create RequestFactory object to call the API"""
self.factory = RequestFactory()
"""SetUp test data"""
self.url = reverse("Retrieve Update Profile")

"""Create User object using model_bakery"""
self.user = baker.make(
"drf_user.User",
username="user",
email="user@email.com",
mobile=1234569877,
password="old_password",
)

"""Create auth_transaction object using model_bakery"""
self.auth_transaction = baker.make(
"drf_user.AuthTransaction",
created_by=self.user,
Expand All @@ -80,69 +74,50 @@ def setUp(self) -> None:
@pytest.mark.django_db
def test_object_created(self):
"""Check if AuthTransaction object created or not"""
assert User.objects.count() == 1
assert AuthTransaction.objects.count() == 1

@pytest.mark.django_db
def test_get_object_method(self):
"""Create request object using factory"""
request = self.factory.get(reverse("Retrieve Update Profile"))

"""Simulating that self.user has made the request"""
request.user = self.user

"""Creates and sets up the RetrieveUpdateUserAccountView"""
view = RetrieveUpdateUserAccountView()
view.setup(request)

self.assertEqual(view.get_object(), self.user)

@pytest.mark.django_db
def test_get_user_account_view(self):
"""Create request object using factory"""
request = self.factory.get(reverse("Retrieve Update Profile"))
"""Check Retrieve Update Profile View returns user"""
self.client.force_authenticate(self.user)
response = self.client.get(self.url)

"""Authenticating the request"""
force_authenticate(
request=request, user=self.user, token=self.auth_transaction.token
)
assert response.status_code == 200
assert response.data["username"] == self.user.username

"""Creates and sets up the RetrieveUpdateUserAccountView"""
view = RetrieveUpdateUserAccountView.as_view()
response = view(request)
@pytest.mark.django_db
def test_update_username(self):
"""
Check patch request to Retrieve Update Profile view updates user's username
"""
self.client.force_authenticate(self.user)
response = self.client.patch(self.url, {"username": "updated_username"})

self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data["username"], self.user.username)
assert response.status_code == 200
assert self.user.username == "updated_username"

@pytest.mark.django_db
def test_update_user_account_view(self):
"""Create request object using factory"""
request = self.factory.patch(
reverse("Retrieve Update Profile"),
data={"username": "updated_username"},
content_type="application/json",
)

"""Authenticating the request"""
force_authenticate(
request=request, user=self.user, token=self.auth_transaction.token
)
def test_update_password(self):
"""
Check patch request to Retrieve Update Profile view updates user's password
"""
self.client.force_authenticate(self.user)
assert self.user.password == "old_password"

"""Creates and sets up the RetrieveUpdateUserAccountView"""
view = RetrieveUpdateUserAccountView.as_view()
response = view(request)
response = self.client.patch(self.url, {"password": "my_unique_password"})

self.assertEqual(response.status_code, 200)
self.assertEqual(self.user.username, "updated_username")
assert response.status_code == 200
assert self.user.password == "my_unique_password"


class TestCheckUniqueView(TestCase):
class TestCheckUniqueView(APITestCase):
"""CheckUniqueView Test"""

def setUp(self) -> None:
"""Create Client object to call the API"""
self.client = Client()
"""SetUp test data"""
self.url = reverse("Check Unique")

"""Create User object using model_bakery"""
self.user = baker.make(
"drf_user.User",
username="user",
Expand All @@ -153,24 +128,72 @@ def setUp(self) -> None:
@pytest.mark.django_db
def test_user_object_created(self):
"""Check if User object created or not"""
self.assertEqual(User.objects.count(), 1)
assert User.objects.count() == 1

@pytest.mark.django_db
def test_is_unique(self):
"""Check if the user is unique"""
response = self.client.post(
reverse("Check Unique"), data={"prop": "username", "value": "user7"}
)
self.assertEqual(response.status_code, status.HTTP_200_OK)
response_data = response.json()
self.assertTrue(response_data["data"][0]["unique"])
response = self.client.post(self.url, {"prop": "username", "value": "user7"})
assert response.status_code == 200
self.assertTrue(response.json()["data"][0]["unique"])

@pytest.mark.django_db
def test_is_not_unique(self):
"""Check if the user is non-unique"""
response = self.client.post(
reverse("Check Unique"), data={"prop": "username", "value": "user"}
"""Check if the user is not unique"""
response = self.client.post(self.url, {"prop": "username", "value": "user"})
assert response.status_code == 200
self.assertFalse(response.json()["data"][0]["unique"])

@pytest.mark.django_db
def test_data_invalid(self):
"""Check CheckUniqueView view raises 422 code when passed data is invalid"""
response = self.client.post(self.url, {"prop": "invalid", "value": "user"})
assert response.status_code == 422


class TestRegisterView(APITestCase):
"""RegisterView Test"""

def setUp(self) -> None:
"""SetUp test data"""
# pre validate email
self.validated_email = baker.make(
"drf_user.OTPValidation", destination="random@django.com", is_validated=True
)
# pre validate mobile
self.validated_mobile = baker.make(
"drf_user.OTPValidation", destination="1234567890", is_validated=True
)
self.assertEqual(response.status_code, status.HTTP_200_OK)
response_data = response.json()
self.assertFalse(response_data["data"][0]["unique"])
self.url = reverse("Register")
self.validated_data = {
"username": "my_username",
"password": "test_password",
"name": "random_name",
"email": "random@django.com",
"mobile": 1234567890,
}
self.not_validated_data = {
"username": "random",
"password": "test_password",
"name": "random_name",
"email": "random@example.com",
"mobile": 8800880080,
}

def test_register_with_validated_email_and_mobile(self):
"""Check user creation when validated mobile and email is passed"""

response = self.client.post(self.url, self.validated_data)

assert response.status_code == 201
assert "my_username" in response.json()["username"]
assert "random_name" in response.json()["name"]

def test_raise_validation_error_when_email_mobile_not_validated(self):
"""Check view raises Validation Error when mobile and email is not validated"""

response = self.client.post(self.url, self.not_validated_data)

assert response.status_code == 400
assert "The email must be pre-validated via OTP." in response.json()["email"]
assert "The mobile must be pre-validated via OTP." in response.json()["mobile"]

0 comments on commit ee5760d

Please sign in to comment.