Like/dislike + report under every question and lesson, lesson reports and vote columns in admin; practice islands refresh from file; audit fixes
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
52
content/tests_feedback.py
Normal file
52
content/tests_feedback.py
Normal file
@@ -0,0 +1,52 @@
|
||||
"""لایک/دیسلایک و گزارشِ درس/سوال: API و ستونهای ادمین."""
|
||||
from django.core.cache import cache
|
||||
from django.test import TestCase
|
||||
|
||||
from accounts.authentication import issue_access_token
|
||||
from accounts.models import User
|
||||
from content.models import Choice, ContentVote, Grade, Lesson, LessonReport, Node, Question, Unit
|
||||
|
||||
|
||||
class FeedbackTests(TestCase):
|
||||
def setUp(self):
|
||||
cache.clear()
|
||||
g = Grade.objects.create(title='پایه نهم', icon='', color='')
|
||||
u = Unit.objects.create(grade=g, title='فصل ۱', order=1)
|
||||
n = Node.objects.create(unit=u, title='مبحث', order=1)
|
||||
self.lesson = Lesson.objects.create(node=n, title='درس')
|
||||
self.q = Question.objects.create(lesson=self.lesson, type='multiple_choice', prompt='؟')
|
||||
Choice.objects.create(question=self.q, value='الف', is_correct=True)
|
||||
Choice.objects.create(question=self.q, value='ب', is_correct=False)
|
||||
self.user = User.objects.create(phone='09120000051')
|
||||
self.auth = {'HTTP_AUTHORIZATION': f'Bearer {issue_access_token(self.user.id)}'}
|
||||
|
||||
def _post(self, url, body):
|
||||
return self.client.post(url, body, content_type='application/json', **self.auth)
|
||||
|
||||
def test_vote_toggle_and_retract(self):
|
||||
url = f'/api/questions/{self.q.pk}/vote'
|
||||
self.assertEqual(self._post(url, {'value': 1}).status_code, 200)
|
||||
self.assertEqual(self._post(url, {'value': -1}).status_code, 200)
|
||||
self.assertEqual(ContentVote.objects.get().value, -1)
|
||||
self._post(url, {'value': 0})
|
||||
self.assertEqual(ContentVote.objects.count(), 0)
|
||||
|
||||
def test_vote_rejects_bad_value_and_anonymous(self):
|
||||
url = f'/api/lessons/{self.lesson.pk}/vote'
|
||||
self.assertEqual(self._post(url, {'value': 5}).status_code, 400)
|
||||
self.assertEqual(self.client.post(url, {'value': 1}, content_type='application/json').status_code, 401)
|
||||
|
||||
def test_lesson_report_is_deduplicated(self):
|
||||
url = f'/api/lessons/{self.lesson.pk}/report'
|
||||
r1 = self._post(url, {'reason': 'typo', 'note': 'غلط'})
|
||||
r2 = self._post(url, {'reason': 'typo'})
|
||||
self.assertEqual((r1.status_code, r2.status_code), (201, 200))
|
||||
self.assertEqual(LessonReport.objects.count(), 1)
|
||||
|
||||
def test_admin_lists_show_votes(self):
|
||||
ContentVote.objects.create(kind='question', target_id=self.q.pk, user_id=self.user.id, value=-1)
|
||||
from django.contrib.auth.models import User as DjUser
|
||||
DjUser.objects.create_superuser('root', 'r@x.ir', 'pw')
|
||||
self.client.login(username='root', password='pw')
|
||||
for path in ('/admin/content/question/', '/admin/content/lesson/', '/admin/content/lessonreport/'):
|
||||
self.assertEqual(self.client.get(path).status_code, 200, path)
|
||||
Reference in New Issue
Block a user