Skip to content

Commit

Permalink
Completed end-to-end test for category obj and also completed unit te…
Browse files Browse the repository at this point in the history
…st for post model
  • Loading branch information
riadelimemmedov committed Mar 28, 2024
1 parent 3cdf4e7 commit 2005258
Show file tree
Hide file tree
Showing 7 changed files with 382 additions and 25 deletions.
2 changes: 1 addition & 1 deletion backend/apps/posts/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def __str__(self):

# !Post
class Post(TimeStampedModel):
title = models.CharField(_("Post title"), max_length=250)
title = models.CharField(_("Post title"), max_length=250, unique=True, null=True)
author = models.ForeignKey(
settings.AUTH_USER_MODEL,
verbose_name=_("Author post"),
Expand Down
4 changes: 3 additions & 1 deletion backend/apps/posts/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ class Meta:

# !CategoryWriteSerializer
class CategoryWriteSerializer(serializers.ModelSerializer):
slug = serializers.ReadOnlyField(read_only=True)

class Meta:
model = Category
fields = ["name"]
fields = ["name", "slug"]


# !PostReadSerializer
Expand Down
1 change: 1 addition & 0 deletions backend/config/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
register(factories.PetFactoryEndToEnd)
register(factories.TransactionFactory)
register(factories.CategoryFactory)
register(factories.PostFactory)


# !api_client
Expand Down
22 changes: 21 additions & 1 deletion backend/config/tests/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

from abstract.constants import Genders, GendersPet, Status, Types
from apps.pet.models import Pet
from apps.posts.models import Category
from apps.posts.models import Category, Comment, Post
from apps.transaction.models import Transaction
from apps.user_profile.models import Profile
from config.helpers import generate_metamask_address, generate_session_id
Expand Down Expand Up @@ -148,3 +148,23 @@ class Meta:
model = Category

name = factory.LazyAttribute(lambda _: faker.word())


# !PostFactory
class PostFactory(factory.django.DjangoModelFactory):
class Meta:
model = Post

title = factory.LazyAttribute(lambda _: faker.word())
author = factory.SubFactory(UserFactory)
post_photo_url = factory.LazyAttribute(
lambda _: faker.file_extension(category="image")
)
body = factory.LazyAttribute(lambda _: faker.paragraph())

@factory.post_generation
def categories(self, create, extracted, **kwargs):
if not create:
return
if extracted:
self.categories.add(extracted)
70 changes: 64 additions & 6 deletions backend/config/tests/posts/category/test_post_category.py
Original file line number Diff line number Diff line change
@@ -1,38 +1,96 @@
import factories
import pytest
from django.core.exceptions import ValidationError
from django.core.files.uploadedfile import SimpleUploadedFile
from django.db import IntegrityError

from abstract.constants import GendersPet, ImageExtension
from apps.pet.models import Pet
from infrastructure.test_data_clear import TruncateTestData

# *If you don't declare pytestmark our test class model don't accsess to database table
pytestmark = pytest.mark.django_db


# !TestPostsCategory
class TestPostsCategory:
def test_str_method(self, category_factory):
"""
Test the __str__ method of the Category model.
Args:
category_factory: A factory function to create a Category instance.
Raises:
AssertionError: If the __str__ method does not return the expected value.
Returns:
None.
"""
obj = category_factory()
assert obj.__str__() == obj.name

def test_slug(self, category_factory):
"""
Test the 'slug' attribute of the Category model.
Args:
category_factory: A factory function to create a Category instance.
Raises:
AssertionError: If the 'slug' attribute does not match the expected value.
Returns:
None.
"""
obj = category_factory(name="category_1")
assert obj.slug == obj.name.lower()

def test_unique_name(self, category_factory):
"""
Test the uniqueness constraint of the 'name' field in the Category model.
Args:
category_factory: A factory function to create a Category instance.
Raises:
IntegrityError: If attempting to create a Category with a non-unique name raises an IntegrityError.
Returns:
None.
"""
category_factory(name="category_1")
with pytest.raises(IntegrityError):
category_factory(name="category_1")

def test_unique_slug(self, category_factory):
"""
Test the uniqueness constraint of the 'slug' field in the Category model.
Args:
category_factory: A factory function to create a Category instance.
Raises:
IntegrityError: If attempting to create a Category with a non-unique slug raises an IntegrityError.
Returns:
None.
"""
obj = category_factory(name="category_1")
with pytest.raises(IntegrityError):
category_factory(name=obj.slug)

def test_name_max_length(self, category_factory):
"""
Test the maximum length constraint of the 'name' and 'slug' fields in the Category model.
Args:
category_factory: A factory function to create a Category instance.
Raises:
ValidationError: If the length of 'name' or 'slug' exceeds the maximum allowed length.
Returns:
None.
"""
name = "x" * 220
slug = "y" * 240
obj = category_factory(name=name, slug=slug)
Expand Down
151 changes: 135 additions & 16 deletions backend/config/tests/posts/category/test_post_category_endpoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,48 +16,167 @@ class TestPostsCategoryEndpoints:
endpoint = "/posts/categories/"

def get_register_payload(self):
"""
Returns a dictionary representing the payload for user registration.
Returns:
dict: The payload containing user information.
"""
return {
"username": "User",
"email": "user@mail.ru",
"password": "complexpassword123",
"wallet_address": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
}

@pytest.fixture
def category_response(self, api_client):
payload = {"name": "devops"}
response = api_client().post(f"{self.endpoint}", payload, format="json")
yield payload, response
def get_staff_user(self, user_id):
"""
Retrieves a user by their ID and sets them as a staff user.
Parameters:
user_id (int): The ID of the user.
Returns:
User: The modified user object.
"""
user = User.objects.get(id=user_id)
user.is_staff = True
user.save()
return user

@pytest.fixture
def register_response(self, api_client):
"""
Performs a user registration request using the provided API client.
Parameters:
api_client (function): A callable representing the API client.
Yields:
tuple: A tuple containing the payload and the registration response.
"""
payload = self.get_register_payload()
response = api_client().post("/users/register/", payload, format="json")
yield payload, response

@pytest.fixture
def get_user(self, register_response, api_client):
"""
Retrieves user information using the provided registration response and API client.
Parameters:
register_response (tuple): A tuple containing the payload and registration response.
api_client (function): A callable representing the API client.
Yields:
tuple: A tuple containing the user and request headers.
"""
payload, response = register_response
access_token = response.data["tokens"]["access"]
headers = {"Authorization": f"Bearer {access_token}"}
user = api_client().get("/users/", headers=headers)
yield user, headers

@pytest.fixture
def category_response(self, api_client, get_user):
"""
Performs a category creation request using the provided API client and user information.
Parameters:
api_client (function): A callable representing the API client.
get_user (tuple): A tuple containing the user information and request headers.
Yields:
tuple: A tuple containing the payload and the category creation response.
"""
user, headers = get_user
user = self.get_staff_user(user.data["id"])
if user.is_staff and user.is_authenticated:
payload = {"name": "devops", "slug": "devops"}
response = api_client().post(
f"{self.endpoint}", payload, format="json", headers=headers
)
yield payload, response

def test_return_all_categories(self, category_factory, api_client):
"""
Test case for returning all categories.
Parameters:
category_factory: A factory object for creating categories.
api_client (function): A callable representing the API client.
"""
category_factory.create_batch(4)
response = api_client().get(self.endpoint, format="json")
assert response.status_code == status.HTTP_200_OK
assert len(json.loads(response.content)) == 4

def test_create_category(self, get_user, api_client):
def test_create_category(self, category_response, api_client):
"""
Test case for creating a category.
Parameters:
category_response (tuple): A tuple containing the payload and category creation response.
api_client (function): A callable representing the API client.
"""
payload, response = category_response
assert response.status_code == status.HTTP_201_CREATED
assert json.loads(response.content) == payload

def test_get_category(self, category_response, api_client):
"""
Test case for retrieving a category.
Parameters:
category_response (tuple): A tuple containing the payload and category creation response.
api_client (function): A callable representing the API client.
"""
payload, response = category_response
category = api_client().get(
f"{self.endpoint}{response.data['slug']}/", format="json"
)
assert category.status_code == status.HTTP_200_OK

def test_update_category(self, category_response, get_user, api_client):
"""
Test case for updating a category.
Parameters:
category_response (tuple): A tuple containing the payload and category creation response.
get_user (tuple): A tuple containing the user information and request headers.
api_client (function): A callable representing the API client.
"""
payload, response = category_response
user, headers = get_user
user = User.objects.get(id=user.data["id"])
user.is_staff = True
user.save()
if user.is_superuser and user.is_authenticated:
payload = {"name": "devops"}
response = api_client().post(
f"{self.endpoint}", payload, format="json", headers=headers
)
assert response.status_code == status.HTTP_201_CREATED
assert json.loads(response.content) == payload
updated_category_obj = {"name": "backend"}
updated_category = api_client().put( # patch and put same thing for this process because we have only update one field for each request
f"{self.endpoint}{response.data['slug']}/",
updated_category_obj,
headers=headers,
format="json",
)
assert updated_category.status_code == status.HTTP_200_OK
assert json.loads(updated_category.content) != updated_category_obj
assert (
json.loads(updated_category.content)["name"] == updated_category_obj["name"]
)
assert (
json.loads(updated_category.content)["slug"] == updated_category_obj["name"]
)
assert json.loads(updated_category.content)["slug"] != response.data["slug"]

def test_delete_category(self, category_response, get_user, api_client):
"""
Test case for deleting a category.
Parameters:
category_response (tuple): A tuple containing the payload and category creation response.
get_user (tuple): A tuple containing the user information and request headers.
api_client (function): A callable representing the API client.
"""
payload, response = category_response
user, headers = get_user
category = api_client().delete(
f"{self.endpoint}{response.data['slug']}/", headers=headers, format="json"
)
assert category.status_code == status.HTTP_204_NO_CONTENT
Loading

0 comments on commit 2005258

Please sign in to comment.