Repository: liqd/adhocracy4

Issue:
comments: make sure blocked comments are not searched or filtered for their category
**URL:** 
**user:** 
**expected behaviour:** when I search for sth. in the comments, I do not expect to find blocked comments, of which I cannot see the comment text
**behaviour:** because the search happens in the backend, blocked comments are also searched, while the comment list from the serializer does not show the comment text of searched comments
**important screensize:**
**device & browser:** 
**Comment/Question:** 

Screenshot?



Discussion:
@Rineee @phillimorland @khamui :rofl: 
Hahahaha :see_no_evil: 
Ok, it is the same for the category filter. :grimacing: 
Also check deleted comments and all filters

Resolving patch:
diff --git a/adhocracy4/comments_async/filters.py b/adhocracy4/comments_async/filters.py
--- a/adhocracy4/comments_async/filters.py
+++ b/adhocracy4/comments_async/filters.py
@@ -8,9 +8,12 @@ class CommentCategoryFilterBackend(BaseFilterBackend):
 
     def filter_queryset(self, request, queryset, view):
 
-        if 'comment_category' in request.GET:
+        if ('comment_category' in request.GET
+                and request.GET['comment_category'] != ''):
             category = request.GET['comment_category']
-            return queryset.filter(comment_categories__contains=category)
+            return queryset.filter(
+                comment_categories__contains=category,
+                is_blocked=False)
 
         return queryset
 
@@ -70,5 +73,6 @@ class CustomSearchFilter(SearchFilter):
     def filter_queryset(self, request, queryset, view):
         qs = super().filter_queryset(request, queryset, view)
         if self.get_search_terms(request):
-            return qs.filter(is_removed=False, is_censored=False)
+            return qs.filter(is_removed=False, is_censored=False,
+                             is_blocked=False)
         return qs


Test patch:
diff --git a/tests/comments/test_async_api.py b/tests/comments/test_async_api.py
--- a/tests/comments/test_async_api.py
+++ b/tests/comments/test_async_api.py
@@ -281,7 +281,8 @@ def test_rating_info(comment, user, another_user, apiclient):
 
 
 @pytest.mark.django_db
-def test_comment_id_in_list(user, apiclient, question_ct, question):
+def test_pagination_comment_link(user, apiclient, question_ct, question,
+                                 comment_factory):
     url = reverse(
         'comments_async-list',
         kwargs={'content_type': question_ct.pk,
@@ -320,6 +321,18 @@ def test_comment_id_in_list(user, apiclient, question_ct, question):
     assert response.status_code == status.HTTP_200_OK
     assert response.data['comment_found']
 
+    comment = comment_factory(content_object=question)
+    child_comment = comment_factory(content_object=comment)
+    url = reverse(
+        'comments_async-list',
+        kwargs={'content_type': question_ct.pk,
+                'object_pk': question.pk})
+    url += '?commentID={}'.format(child_comment.id)
+    response = apiclient.get(url)
+    assert response.status_code == status.HTTP_200_OK
+    assert response.data['comment_found']
+    assert response.data['comment_parent'] == comment.id
+
 
 @pytest.mark.django_db
 def test_fields(user, apiclient, question_ct, question):
diff --git a/tests/comments/test_async_filters.py b/tests/comments/test_async_filters.py
new file mode 100644
--- /dev/null
+++ b/tests/comments/test_async_filters.py
@@ -0,0 +1,290 @@
+import pytest
+from django.contrib.contenttypes.models import ContentType
+from django.urls import reverse
+
+from tests.apps.questions.models import Question
+
+
+@pytest.mark.django_db
+def test_category_filter(apiclient, question, comment_factory, user):
+    question_ct = ContentType.objects.get_for_model(Question)
+
+    comment_factory(pk=1, content_object=question,
+                    comment_categories='QUE, REM')
+    comment_factory(pk=2, content_object=question,
+                    comment_categories='QUE')
+    comment_factory(pk=3, content_object=question,
+                    is_blocked=True, comment_categories='QUE')
+    comment_factory(pk=4, content_object=question,
+                    is_censored=True, comment_categories='REM')
+    comment_factory(pk=5, content_object=question,
+                    is_removed=True, comment_categories='QUE, REM')
+    comment_factory(pk=6, content_object=question,
+                    comment_categories='REM')
+    comment = comment_factory(pk=7, content_object=question,
+                              comment_categories='QUE')
+    comment_factory(pk=8, content_object=comment, creator=user)
+
+    apiclient.force_authenticate(user=user)
+    url = reverse(
+        'comments_async-list',
+        kwargs={'content_type': question_ct.pk,
+                'object_pk': question.pk})
+    response = apiclient.get(url)
+
+    comment_data = response.data['results']
+    assert len(comment_data) == 7
+
+    url = reverse(
+        'comments_async-list',
+        kwargs={'content_type': question_ct.pk,
+                'object_pk': question.pk})
+    url += '?comment_category=que'
+    response = apiclient.get(url)
+
+    comment_data = response.data['results']
+    assert len(comment_data) == 3
+    assert comment_data[2]['id'] == 1
+    assert comment_data[1]['id'] == 2
+    assert comment_data[0]['id'] == 7
+
+    url = reverse(
+        'comments_async-list',
+        kwargs={'content_type': question_ct.pk,
+                'object_pk': question.pk})
+    url += '?comment_category=rem'
+    response = apiclient.get(url)
+
+    comment_data = response.data['results']
+    assert len(comment_data) == 2
+    assert comment_data[1]['id'] == 1
+    assert comment_data[0]['id'] == 6
+
+    url = reverse(
+        'comments_async-list',
+        kwargs={'content_type': question_ct.pk,
+                'object_pk': question.pk})
+    url += '?comment_category='
+    response = apiclient.get(url)
+
+    comment_data = response.data['results']
+    assert len(comment_data) == 7
+
+
+@pytest.mark.django_db
+def test_search_filter(apiclient, question, comment_factory, user):
+    question_ct = ContentType.objects.get_for_model(Question)
+
+    comment_factory(pk=1, content_object=question,
+                    comment='Lorem ipsum')
+    comment_factory(pk=2, content_object=question,
+                    comment='dolor sit amet')
+    comment_factory(pk=3, content_object=question,
+                    is_blocked=True,
+                    comment='Lorem ipsum')
+    comment_factory(pk=4, content_object=question,
+                    is_censored=True,
+                    comment='Lorem ipsum')
+    comment_factory(pk=5, content_object=question,
+                    is_removed=True,
+                    comment='Lorem ipsum')
+    comment_factory(pk=6, content_object=question,
+                    comment='Lorem ipsum dolor sit amet')
+    comment = comment_factory(pk=7, content_object=question,
+                              comment='ipsum dolor sit amet')
+    comment_factory(pk=8, content_object=comment, creator=user,
+                    comment='Lorem ipsum')
+
+    apiclient.force_authenticate(user=user)
+    url = reverse(
+        'comments_async-list',
+        kwargs={'content_type': question_ct.pk,
+                'object_pk': question.pk})
+    response = apiclient.get(url)
+    comment_data = response.data['results']
+    assert len(comment_data) == 7
+
+    url = reverse(
+        'comments_async-list',
+        kwargs={'content_type': question_ct.pk,
+                'object_pk': question.pk})
+    url += '?search=lorem+ipsum'
+    response = apiclient.get(url)
+    comment_data = response.data['results']
+    assert len(comment_data) == 2
+    assert comment_data[1]['id'] == 1
+    assert comment_data[0]['id'] == 6
+
+    url = reverse(
+        'comments_async-list',
+        kwargs={'content_type': question_ct.pk,
+                'object_pk': question.pk})
+    url += '?search=lorem'
+    response = apiclient.get(url)
+    comment_data = response.data['results']
+    assert len(comment_data) == 2
+    assert comment_data[1]['id'] == 1
+    assert comment_data[0]['id'] == 6
+
+    url = reverse(
+        'comments_async-list',
+        kwargs={'content_type': question_ct.pk,
+                'object_pk': question.pk})
+    url += '?search=ipsum'
+    response = apiclient.get(url)
+    comment_data = response.data['results']
+    assert len(comment_data) == 3
+    assert comment_data[2]['id'] == 1
+    assert comment_data[1]['id'] == 6
+    assert comment_data[0]['id'] == 7
+
+    url = reverse(
+        'comments_async-list',
+        kwargs={'content_type': question_ct.pk,
+                'object_pk': question.pk})
+    url += '?search=lirum'
+    response = apiclient.get(url)
+    comment_data = response.data['results']
+    assert len(comment_data) == 0
+
+    url = reverse(
+        'comments_async-list',
+        kwargs={'content_type': question_ct.pk,
+                'object_pk': question.pk})
+    url += '?search='
+    response = apiclient.get(url)
+    comment_data = response.data['results']
+    assert len(comment_data) == 7
+
+
+@pytest.mark.django_db
+def test_ordering_filter(apiclient, question, comment_factory, rating_factory,
+                         user):
+    question_ct = ContentType.objects.get_for_model(Question)
+
+    comment1 = comment_factory(pk=1, content_object=question)
+    comment2 = comment_factory(pk=2, content_object=question,
+                               is_moderator_marked=True)
+    comment3 = comment_factory(pk=3, content_object=question)
+    comment4 = comment_factory(pk=4, content_object=question,
+                               is_moderator_marked=True)
+    comment_factory(pk=5, content_object=comment1)
+    comment_factory(pk=6, content_object=comment1)
+    comment_factory(pk=7, content_object=comment1)
+    comment_factory(pk=8, content_object=comment2)
+    comment_factory(pk=9, content_object=comment2)
+    comment_factory(pk=10, content_object=comment3)
+
+    rating_factory(content_object=comment2, value=1)
+    rating_factory(content_object=comment2, value=-1)
+    rating_factory(content_object=comment2, value=-1)
+    rating_factory(content_object=comment1, value=1)
+    rating_factory(content_object=comment1, value=1)
+    rating_factory(content_object=comment3, value=1)
+    rating_factory(content_object=comment4, value=-1)
+
+    apiclient.force_authenticate(user=user)
+    url = reverse(
+        'comments_async-list',
+        kwargs={'content_type': question_ct.pk,
+                'object_pk': question.pk})
+    response = apiclient.get(url)
+    comment_data = response.data['results']
+    assert len(comment_data) == 4
+    assert comment_data[3]['id'] == 1
+    assert comment_data[2]['id'] == 2
+    assert comment_data[1]['id'] == 3
+    assert comment_data[0]['id'] == 4
+
+    apiclient.force_authenticate(user=user)
+    url = reverse(
+        'comments_async-list',
+        kwargs={'content_type': question_ct.pk,
+                'object_pk': question.pk})
+    url += '?ordering='
+    response = apiclient.get(url)
+    comment_data = response.data['results']
+    assert len(comment_data) == 4
+    assert comment_data[3]['id'] == 1
+    assert comment_data[2]['id'] == 2
+    assert comment_data[1]['id'] == 3
+    assert comment_data[0]['id'] == 4
+
+    apiclient.force_authenticate(user=user)
+    url = reverse(
+        'comments_async-list',
+        kwargs={'content_type': question_ct.pk,
+                'object_pk': question.pk})
+    url += '?ordering=new'
+    response = apiclient.get(url)
+    comment_data = response.data['results']
+    assert len(comment_data) == 4
+    assert comment_data[3]['id'] == 1
+    assert comment_data[2]['id'] == 2
+    assert comment_data[1]['id'] == 3
+    assert comment_data[0]['id'] == 4
+
+    url = reverse(
+        'comments_async-list',
+        kwargs={'content_type': question_ct.pk,
+                'object_pk': question.pk})
+    url += '?ordering=ans'
+    response = apiclient.get(url)
+    comment_data = response.data['results']
+    assert len(comment_data) == 4
+    assert comment_data[3]['id'] == 4
+    assert comment_data[2]['id'] == 3
+    assert comment_data[1]['id'] == 2
+    assert comment_data[0]['id'] == 1
+
+    url = reverse(
+        'comments_async-list',
+        kwargs={'content_type': question_ct.pk,
+                'object_pk': question.pk})
+    url += '?ordering=pos'
+    response = apiclient.get(url)
+    comment_data = response.data['results']
+    assert len(comment_data) == 4
+    assert comment_data[3]['id'] == 4
+    assert comment_data[2]['id'] == 2
+    assert comment_data[1]['id'] == 3
+    assert comment_data[0]['id'] == 1
+
+    url = reverse(
+        'comments_async-list',
+        kwargs={'content_type': question_ct.pk,
+                'object_pk': question.pk})
+    url += '?ordering=neg'
+    response = apiclient.get(url)
+    comment_data = response.data['results']
+    assert len(comment_data) == 4
+    assert comment_data[3]['id'] == 1
+    assert comment_data[2]['id'] == 3
+    assert comment_data[1]['id'] == 4
+    assert comment_data[0]['id'] == 2
+
+    url = reverse(
+        'comments_async-list',
+        kwargs={'content_type': question_ct.pk,
+                'object_pk': question.pk})
+    url += '?ordering=dis'
+    response = apiclient.get(url)
+    comment_data = response.data['results']
+    assert len(comment_data) == 4
+    assert comment_data[3]['id'] == 1
+    assert comment_data[2]['id'] == 2
+    assert comment_data[1]['id'] == 3
+    assert comment_data[0]['id'] == 4
+
+    url = reverse(
+        'comments_async-list',
+        kwargs={'content_type': question_ct.pk,
+                'object_pk': question.pk})
+    url += '?ordering=mom'
+    response = apiclient.get(url)
+    comment_data = response.data['results']
+    assert len(comment_data) == 4
+    assert comment_data[3]['id'] == 1
+    assert comment_data[2]['id'] == 3
+    assert comment_data[1]['id'] == 2
+    assert comment_data[0]['id'] == 4
diff --git a/tests/comments/test_async_serializer.py b/tests/comments/test_async_serializer.py
--- a/tests/comments/test_async_serializer.py
+++ b/tests/comments/test_async_serializer.py
@@ -43,6 +43,7 @@ def test_serializer(apiclient, question, comment_factory, user):
     assert comment_1['user_name'] == ''
     # django auth user model does not define get_absolute_url()
     assert comment_1['user_profile_url'] == ''
+    assert comment_1['user_image'] is None
     assert comment_1['is_deleted'] is False
     assert comment_1['author_is_moderator'] is False
     assert len(comment_1['child_comments']) == 0
@@ -61,6 +62,7 @@ def test_serializer(apiclient, question, comment_factory, user):
     assert comment_2['id'] == 2
     assert comment_2['user_name'] == ''
     assert comment_2['user_profile_url'] == ''
+    assert comment_2['user_image'] is None
     assert comment_2['is_deleted'] is False
     assert comment_2['author_is_moderator'] is False
     assert len(comment_2['child_comments']) == 0
@@ -80,6 +82,7 @@ def test_serializer(apiclient, question, comment_factory, user):
     assert comment_3['id'] == 3
     assert comment_3['user_name'] == 'unknown user'
     assert comment_3['user_profile_url'] == ''
+    assert comment_3['user_image'] is None
     assert comment_3['is_deleted'] is True
     assert comment_3['author_is_moderator'] is False
     assert len(comment_3['child_comments']) == 0
@@ -99,6 +102,7 @@ def test_serializer(apiclient, question, comment_factory, user):
     assert comment_4['id'] == 4
     assert comment_4['user_name'] == 'unknown user'
     assert comment_4['user_profile_url'] == ''
+    assert comment_4['user_image'] is None
     assert comment_4['is_deleted'] is True
     assert comment_4['author_is_moderator'] is False
     assert len(comment_4['child_comments']) == 0
@@ -118,6 +122,7 @@ def test_serializer(apiclient, question, comment_factory, user):
     assert comment_5['id'] == 5
     assert comment_5['user_name'] == 'unknown user'
     assert comment_5['user_profile_url'] == ''
+    assert comment_5['user_image'] is None
     assert comment_5['is_deleted'] is True
     assert comment_5['author_is_moderator'] is False
     assert len(comment_5['child_comments']) == 0
@@ -137,6 +142,7 @@ def test_serializer(apiclient, question, comment_factory, user):
     assert comment_6['id'] == 6
     assert comment_6['user_name'] == ''
     assert comment_6['user_profile_url'] == ''
+    assert comment_6['user_image'] is None
     assert comment_6['is_deleted'] is False
     assert comment_6['author_is_moderator'] is False
     assert len(comment_6['child_comments']) == 0
@@ -155,6 +161,7 @@ def test_serializer(apiclient, question, comment_factory, user):
     assert comment_7['id'] == 7
     assert comment_7['is_deleted'] is False
     assert comment_7['author_is_moderator'] is True
+    assert comment_7['user_image'] is None
     assert len(comment_7['child_comments']) == 1
     assert comment_7['comment'] == Comment.objects.get(pk=7).comment
     assert comment_7['object_pk'] == question.pk
@@ -171,6 +178,7 @@ def test_serializer(apiclient, question, comment_factory, user):
     assert comment_8['id'] == 8
     assert comment_8['is_deleted'] is False
     assert comment_8['author_is_moderator'] is False
+    assert comment_8['user_image'] is None
     assert comment_8['comment'] == Comment.objects.get(pk=8).comment
     assert comment_8['object_pk'] == comment.pk
     assert comment_8['is_removed'] is False