Skip to content

Commit

Permalink
- write unit tests for the errors
Browse files Browse the repository at this point in the history
- implement the error messages on the register api
[Finishes #161967009]
  • Loading branch information
mashafrancis committed Dec 3, 2018
1 parent 7c622a2 commit 716c688
Show file tree
Hide file tree
Showing 2 changed files with 166 additions and 9 deletions.
52 changes: 49 additions & 3 deletions authors/apps/authentication/serializers.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from django.contrib.auth import authenticate

from rest_framework import serializers
from rest_framework.validators import UniqueValidator

from authors.apps.authentication.backends import JWTAuthentication
from .models import User
Expand All @@ -9,13 +10,58 @@
class RegistrationSerializer(serializers.ModelSerializer):
"""Serializers registration requests and creates a new user."""

def __init__(self, *args, **kwargs):
super(RegistrationSerializer, self).__init__(*args, **kwargs)

# Override the default error_messages with a custom field error
for field in self.fields:
error_messages = self.fields[field].error_messages
error_messages['null'] = error_messages['blank'] \
= error_messages['required'] \
= 'Please fill in the {}.'.format(field)

# Ensure the username entered is unique and has a descriptive error message
# when a duplicate username is entered and an invalid username.
username = serializers.RegexField(
regex='^(?!.*\ )[A-Za-z\d\-\_]+$',
min_length=4,
max_length=30,
required=True,
validators=[UniqueValidator(
queryset=User.objects.all(),
message='The username already exists. Kindly try another.'
)],
error_messages={
'min_length': 'Username must have a minimum of 4 characters.',
'max_length': 'Username must have a maximum of 30 characters.',
'invalid': 'Username cannot have blank spaces.'
}
)

# Ensure the email entered is unique and has a descriptive error message
# when a duplicate email is entered and an invalid email address.
email = serializers.EmailField(
validators=[UniqueValidator(
queryset=User.objects.all(),
message='User with this email already exists. Sign in instead or try another.'
)],
error_messages={
'invalid': 'You have input an invalid email. Kindly check again.'
}
)

# Ensure passwords are at least 8 characters long, no longer than 128
# characters, and can not be read by the client.
password = serializers.CharField(
password = serializers.RegexField(
regex=r'^(?=.*[a-zA-Z])(?=.*[0-9]).*',
max_length=128,
min_length=8,
write_only=True
)
write_only=True,
error_messages={
'max_length': 'Password must have a maximum of 128 characters.',
'min_length': 'Password must have a minimum of 8 characters.',
'invalid': 'Password must contain a letter and a number.'
})

token = serializers.SerializerMethodField()
refresh_token = serializers.SerializerMethodField()
Expand Down
123 changes: 117 additions & 6 deletions authors/apps/authentication/tests/test_registration.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import random
import string

import pytest
from faker import Factory
from rest_framework import status
from rest_framework.reverse import reverse

from authors.apps.authentication.models import User
Expand All @@ -22,38 +26,145 @@ class TestRegistration:
}

def test_user_instance(self):
"""
test user model methods
:return:
"""
"""Test user model methods"""
assert self.test_user.__str__() == self.test_user.email
assert self.test_user.get_full_name == self.test_user.username
assert self.test_user.get_short_name() == self.test_user.username

def test_create_super_user(self):
"""Test super user can be created"""
su = User.objects.create_superuser(**self.user['user'])
assert su.is_active is True
assert su.is_staff is True
assert su.is_superuser is True

def test_user_registration(self, test_client):
"""Test successful user registration"""
response = test_client.post(reverse('register'), data=self.user, format='json')
assert response.status_code is 201
assert User.objects.count() > 0

def test_token_in_response(self, test_client):
"""Test token is generated and is at the response"""
response = test_client.post(reverse('register'), self.user, format='json')

assert isinstance(response.data, dict)
assert 'username' in response.data
assert 'token' in response.data

def test_add_existing_user(self, test_client):
"""Test API cannot add an existing user"""
response = test_client.post(reverse('register'), self.user, format='json')
response2 = test_client.post(reverse('register'), self.user, format='json')

assert response2.status_code == 400
assert 'errors' in response2.data

assert response2.data['errors']['email'][0] == "user with this email already exists."
assert response2.data['errors']['username'][0] == "user with this username already exists."
assert response2.data['errors']['email'][0] == "User with this email already exists. Sign in instead or try " \
"another."
assert response2.data['errors']['username'][0] == "The username already exists. Kindly try another."

def test_user_cannot_register_with_a_blank_email_field(self, test_client):
"""Test the API cannot register a user with blank password field"""
del self.user['user']['email']
response = test_client.post(reverse('register'), self.user, format='json')

assert response.status_code == status.HTTP_400_BAD_REQUEST
assert 'errors' in response.data
assert response.data['errors']['email'][0] == "Please fill in the email."

def test_user_cannot_register_with_an_invalid_email(self, test_client):
"""Test the API cannot register a user with an invalid email"""
self.user['user']['email'] = 'WRONG_EMAIL'
response = test_client.post(reverse('register'), self.user, format='json')

assert response.status_code == status.HTTP_400_BAD_REQUEST
assert 'errors' in response.data
assert response.data['errors']['email'][0] == "You have input an invalid email. Kindly check again."

def test_user_cannot_register_with_a_short_username(self, test_client):
"""Test the API cannot register a user with a short username"""
self.user['user']['username'] = 'abc'
response = test_client.post(reverse('register'), self.user, format='json')

assert response.status_code == status.HTTP_400_BAD_REQUEST
assert 'errors' in response.data
assert response.data['errors']['username'][0] == "Username must have a minimum of 4 characters."

def test_user_cannot_register_with_a_long_username(self, test_client):
"""Test the API cannot register a user with a long password"""
chars = string.ascii_letters + string.digits
uname_size = 31
username = ''.join((random.choice(chars)) for x in range(uname_size))
self.user['user']['username'] = username
response = test_client.post(reverse('register'), self.user, format='json')

assert response.status_code == status.HTTP_400_BAD_REQUEST
assert 'errors' in response.data
assert response.data['errors']['username'][0] == "Username must have a maximum of 30 characters."

def test_user_cannot_register_with_a_blank_username_field(self, test_client):
"""Test the API cannot register a user with blank username field"""
del self.user['user']['username']
response = test_client.post(reverse('register'), self.user, format='json')

assert response.status_code == status.HTTP_400_BAD_REQUEST
assert 'errors' in response.data
assert response.data['errors']['username'][0] == "Please fill in the username."

def test_user_cannot_register_with_wrong_username(self, test_client):
"""Test the API cannot register a user with an wrong username format"""
self.user['user']['username'] = 'wrong username'
response = test_client.post(reverse('register'), self.user, format='json')

assert response.status_code == status.HTTP_400_BAD_REQUEST
assert 'errors' in response.data
assert response.data['errors']['username'][0] == "Username cannot have blank spaces."

def test_user_cannot_register_with_a_blank_password_field(self, test_client):
"""Test the API cannot register a user with blank password field"""
del self.user['user']['password']
response = test_client.post(reverse('register'), self.user, format='json')

assert response.status_code == status.HTTP_400_BAD_REQUEST
assert 'errors' in response.data
assert response.data['errors']['password'][0] == "Please fill in the password."

def test_user_cannot_register_with_a_short_password(self, test_client):
"""Test the API cannot register a user with a short password"""
self.user['user']['password'] = 'abc'
response = test_client.post(reverse('register'), self.user, format='json')

assert response.status_code == status.HTTP_400_BAD_REQUEST
assert 'errors' in response.data
assert response.data['errors']['password'][0] == "Password must have a minimum of 8 characters."

def test_user_cannot_register_with_a_long_password(self, test_client):
"""Test the API cannot register a user with a long password greater than 128 characters"""
chars = string.ascii_letters + string.digits
pwd_size = 129
password = ''.join((random.choice(chars)) for x in range(pwd_size))
self.user['user']['password'] = password
response = test_client.post(reverse('register'), self.user, format='json')

assert response.status_code == status.HTTP_400_BAD_REQUEST
assert 'errors' in response.data
assert response.data['errors']['password'][0] == "Password must have a maximum of 128 characters."

def test_unsuccessful_registration_due_to_all_letters_password(self, test_client):
"""Test the API cannot register a user with all letters password"""
self.user['user']['password'] = 'abcdefgh'
response = test_client.post(reverse('register'), self.user, format='json')

assert response.status_code == status.HTTP_400_BAD_REQUEST
assert 'errors' in response.data
assert response.data['errors']['password'][0] == "Password must contain a letter and a number."

def test_unsuccessful_registration_due_to_all_numeric_password(self, test_client):
"""Test the API cannot register a user with all numeric password"""
self.user['user']['password'] = 12345678
response = test_client.post(reverse('register'), self.user, format='json')

assert response.status_code == status.HTTP_400_BAD_REQUEST
assert 'errors' in response.data
assert response.data['errors']['password'][0] == "Password must contain a letter and a number."

0 comments on commit 716c688

Please sign in to comment.