Skip to content

Commit

Permalink
feat(be): connect upvote, downvote, bookmark to forum question fields…
Browse files Browse the repository at this point in the history
…. update tests accordingly
  • Loading branch information
MucahitErdoganUnlu committed Nov 17, 2024
1 parent 6bb9794 commit 2ed45c2
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 21 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Generated by Django 5.1.2 on 2024-11-17 20:02

import django.db.models.deletion
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('core', '0005_rename_date_forumanswer_created_at'),
]

operations = [
migrations.AlterField(
model_name='forumdownvote',
name='forum_question',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='downvotes', to='core.forumquestion'),
),
migrations.AlterField(
model_name='forumupvote',
name='forum_question',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='upvotes', to='core.forumquestion'),
),
migrations.AlterField(
model_name='takequiz',
name='quiz',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='takes', to='core.quiz'),
),
]
6 changes: 3 additions & 3 deletions backend/core/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ def __str__(self):
return self.choice_text

class TakeQuiz(models.Model):
quiz = models.ForeignKey(Quiz, on_delete=models.CASCADE)
quiz = models.ForeignKey(Quiz, on_delete=models.CASCADE, related_name='takes')
user = models.ForeignKey(CustomUser, on_delete=models.CASCADE)
date = models.DateTimeField(auto_now_add=True)

Expand Down Expand Up @@ -122,7 +122,7 @@ def __str__(self):

class ForumUpvote(models.Model):
user = models.ForeignKey(CustomUser, on_delete=models.CASCADE)
forum_question = models.ForeignKey(ForumQuestion, on_delete=models.CASCADE)
forum_question = models.ForeignKey(ForumQuestion, on_delete=models.CASCADE, related_name='upvotes')
created_at = models.DateTimeField(auto_now_add=True)

class Meta:
Expand All @@ -140,7 +140,7 @@ def __str__(self):

class ForumDownvote(models.Model):
user = models.ForeignKey(CustomUser, on_delete=models.CASCADE)
forum_question = models.ForeignKey(ForumQuestion, on_delete=models.CASCADE)
forum_question = models.ForeignKey(ForumQuestion, on_delete=models.CASCADE, related_name='downvotes')
created_at = models.DateTimeField(auto_now_add=True)

class Meta:
Expand Down
32 changes: 24 additions & 8 deletions backend/core/serializers/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
from rest_framework import serializers

from ..models import (CustomUser, ForumQuestion, Quiz, QuizQuestion, QuizQuestionChoice, RateQuiz,
Tag, ForumBookmark, ForumAnswer)
Tag, ForumBookmark, ForumAnswer, ForumUpvote, ForumDownvote, TakeQuiz)
from .forum_vote_serializer import ForumUpvoteSerializer, ForumDownvoteSerializer
from .take_quiz_serializer import TakeQuizSerializer

User = get_user_model()
queryset = User.objects.all()
Expand Down Expand Up @@ -90,16 +92,22 @@ def get_is_bookmarked(self, obj):
return ForumBookmark.objects.filter(user=user, forum_question=obj).exists()

def get_is_upvoted(self, obj):
return Faker().boolean()
user = self.context['request'].user
if not user.is_authenticated:
return False
return ForumUpvote.objects.filter(user=user, forum_question=obj).exists()

def get_upvotes_count(self, obj):
return Faker().random_int(min=0, max=100)
return obj.upvotes.count()

def get_is_downvoted(self, obj):
return Faker().boolean()
user = self.context['request'].user
if not user.is_authenticated:
return False
return ForumDownvote.objects.filter(user=user, forum_question=obj).exists()

def get_downvotes_count(self, obj):
return Faker().random_int(min=0, max=100)
return obj.downvotes.count()

def create(self, validated_data):
# Extract tags from validated_data
Expand Down Expand Up @@ -171,9 +179,8 @@ class QuizSerializer(serializers.ModelSerializer):
author = UserInfoSerializer(read_only=True) # Assuming UserInfoSerializer is defined
tags = TagSerializer(many=True) # Assuming TagSerializer is defined
rating = serializers.SerializerMethodField()

num_taken = serializers.IntegerField(default=0, read_only=True)
is_taken = serializers.BooleanField(default=False, read_only=True)
is_taken = serializers.SerializerMethodField()
num_taken = serializers.SerializerMethodField()


class Meta:
Expand All @@ -184,6 +191,15 @@ class Meta:
)
read_only_fields = ("difficulty", 'created_at', 'num_taken', 'is_taken', 'rating', "author")

def get_is_taken(self, obj):
user = self.context['request'].user
if not user.is_authenticated:
return False
return TakeQuiz.objects.filter(quiz=obj, user=user).exists()

def get_num_taken(self, obj):
return obj.takes.count()

def get_rating(self, obj):
from django.db.models import Avg, Count

Expand Down
10 changes: 8 additions & 2 deletions backend/core/tests/test_forum_bookmark.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,22 +43,28 @@ def test_create_forum_bookmark(self):
"""Test creating a forum bookmark"""
# Delete the existing bookmark to test creation
self.forum_bookmark.delete()

response = self.client.get(reverse('forum-question-detail', args=[self.forum_question.id]), format='json')
self.assertFalse(response.data['is_bookmarked'])
# Send POST request to create a new bookmark
response = self.client.post(reverse('forumbookmark-list'), self.data, format='json')

# Assertions
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
self.assertTrue(ForumBookmark.objects.filter(user=self.user, forum_question=self.forum_question).exists())

response = self.client.get(reverse('forum-question-detail', args=[self.forum_question.id]), format='json')
self.assertTrue(response.data['is_bookmarked'])


def test_delete_forum_bookmark(self):
"""Test deleting a forum bookmark"""
# Send DELETE request to remove the bookmark
self.assertTrue(self.client.get(reverse('forum-question-detail', args=[self.forum_question.id]), format='json').data['is_bookmarked'])
response = self.client.delete(reverse('forumbookmark-detail', args=[self.forum_bookmark.id]))

# Assertions
self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
self.assertFalse(ForumBookmark.objects.filter(id=self.forum_bookmark.id).exists())
self.assertFalse(self.client.get(reverse('forum-question-detail', args=[self.forum_question.id]), format='json').data['is_bookmarked'])

def test_cannot_bookmark_same_forum_question_twice(self):
"""Test that the same forum question cannot be bookmarked twice"""
Expand Down
33 changes: 26 additions & 7 deletions backend/core/tests/test_forum_upvote_downvote.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,31 +26,46 @@ def setUp(self):
self.client.credentials(HTTP_AUTHORIZATION=f'Bearer {str(refresh.access_token)}')

# Create a ForumQuestion
self.forum_question = ForumQuestion.objects.create(
title="Test Forum Question",
question="This is a test question for votes.",
author=self.user
)

# self.forum_question = ForumQuestion.objects.create(
# title="Test Forum Question",
# question="This is a test question for votes.",
# author=self.user
# )
self.forum_question_response = self.client.post(reverse('forum-question-list'), {
"title": "Test Forum Question",
"question": "This is a test question for votes.",
"tags": [
{"name": "Django", "linked_data_id": "123", "description": "A web framework."},
{"name": "DRF", "linked_data_id": "456", "description": "Django Rest Framework."}
]
}, format='json').data


self.forum_question = ForumQuestion.objects.get(title='Test Forum Question')
# Vote data
self.data = {"forum_question": self.forum_question.id}

def test_create_forum_upvote(self):
question_response = self.client.get(reverse("forum-question-detail", args=[self.forum_question.id]))
upvotes_count = question_response.data['upvotes_count']
"""Test creating a forum vote"""
# Send POST request to create a new vote
response = self.client.post(reverse('forum-upvote-list'), self.data, format='json')

# Assertions
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
self.assertTrue(ForumUpvote.objects.filter(user=self.user, forum_question=self.forum_question).exists())
self.assertIn("id", response.data)
self.assertIn("user", response.data)
self.assertIn("forum_question", response.data)
response = self.client.get(reverse("forum-question-detail", args=[self.forum_question.id]))
self.assertEqual(upvotes_count + 1, response.data['upvotes_count'])

def test_delete_forum_upvote(self):
"""Test deleting a forum vote"""
# Create a vote to delete
self.client.post(reverse('forum-upvote-list'), self.data, format='json')
response = self.client.get(reverse("forum-question-detail", args=[self.forum_question.id]))
upvotes_count = response.data['upvotes_count']
forum_vote = ForumUpvote.objects.get(user=self.user, forum_question=self.forum_question)

# Send DELETE request to remove the vote
Expand All @@ -60,6 +75,10 @@ def test_delete_forum_upvote(self):
self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
self.assertFalse(ForumUpvote.objects.filter(id=forum_vote.id).exists())

response = self.client.get(reverse("forum-question-detail", args=[self.forum_question.id]))
self.assertEqual(response.data['upvotes_count'], upvotes_count - 1)


def test_cannot_upvote_same_forum_question_twice(self):
"""Test that the same forum question cannot be voted twice"""
# Create the first vote
Expand Down
49 changes: 48 additions & 1 deletion backend/core/tests/test_take_quiz.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ def test_take_quiz(self):
}
]
}
response = self.client.get(reverse('quiz-detail', kwargs={'pk': self.quiz.id}))
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertFalse(response.data["is_taken"])
self.assertEqual(response.data["num_taken"], 0)

response = self.client.post(reverse('take-quiz-list'), data, format='json')
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
self.assertEqual(response.data["user"], self.user.id)
Expand All @@ -31,8 +36,16 @@ def test_take_quiz(self):
self.assertIn("date", response.data)
self.assertEqual(response.data["answers"][0]["question"], data["answers"][0]["question"])
self.assertEqual(response.data["answers"][0]["answer"], data["answers"][0]["answer"])
response = self.client.get(reverse('quiz-detail', kwargs={'pk': self.quiz.id}))
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertTrue(response.data["is_taken"])
self.assertEqual(response.data["num_taken"], 1)

def test_take_quiz_already_taken(self):
response = self.client.get(reverse('quiz-detail', kwargs={'pk': self.quiz.id}))
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertFalse(response.data["is_taken"])
self.assertEqual(response.data["num_taken"], 0)

data = {
"quiz": self.quiz.id,
Expand All @@ -44,9 +57,18 @@ def test_take_quiz_already_taken(self):
]
}
self.client.post(reverse('take-quiz-list'), data, format='json')
response = self.client.get(reverse('quiz-detail', kwargs={'pk': self.quiz.id}))
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertTrue(response.data["is_taken"])
self.assertEqual(response.data["num_taken"], 1)

response = self.client.post(reverse('take-quiz-list'), data, format='json')
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertEqual(response.data[0], "You have already taken this quiz.")
response = self.client.get(reverse('quiz-detail', kwargs={'pk': self.quiz.id}))
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertTrue(response.data["is_taken"])
self.assertEqual(response.data["num_taken"], 1)

def test_take_quiz_invalid_answer(self):

Expand Down Expand Up @@ -101,6 +123,9 @@ def test_take_quiz_invalid_answer(self):
str(response.data[0]),
"['The answer must belong to the same question.']"
)
response = self.client.get(reverse('quiz-detail', kwargs={'pk': self.quiz.id}))
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertFalse(response.data["is_taken"])


def test_take_quiz_invalid_question(self):
Expand Down Expand Up @@ -155,8 +180,19 @@ def test_take_quiz_invalid_question(self):
str(response.data[0]),
"['The question must belong to the same quiz.']"
)
response = self.client.get(reverse('quiz-detail', kwargs={'pk': self.quiz.id}))
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertFalse(response.data["is_taken"])
self.assertEqual(response.data["num_taken"], 0)


def test_take_quiz_delete(self):

response = self.client.get(reverse('quiz-detail', kwargs={'pk': self.quiz.id}))
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertFalse(response.data["is_taken"])
self.assertEqual(response.data["num_taken"], 0)

data = {
"quiz": self.quiz.id,
"answers": [
Expand All @@ -167,9 +203,20 @@ def test_take_quiz_delete(self):
]
}
response = self.client.post(reverse('take-quiz-list'), data, format='json')
response_id = response.data['id']
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
response = self.client.delete(reverse('take-quiz-detail', kwargs={'pk': response.data['id']}))
response = self.client.get(reverse('quiz-detail', kwargs={'pk': self.quiz.id}))
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertTrue(response.data["is_taken"])
self.assertEqual(response.data["num_taken"], 1)

response = self.client.delete(reverse('take-quiz-detail', kwargs={'pk': response_id}))
self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
response = self.client.get(reverse('quiz-detail', kwargs={'pk': self.quiz.id}))
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertFalse(response.data["is_taken"])
self.assertEqual(response.data["num_taken"], 0)


def test_take_quiz_patch(self):
data = {
Expand Down

0 comments on commit 2ed45c2

Please sign in to comment.