Browse Source

Move threads lists to cursor pagination

rafalp 6 years ago
parent
commit
f014c12d38

+ 2 - 1
misago/core/cursorpaginator.py → misago/core/cursorpagination.py

@@ -12,7 +12,8 @@ def get_page(queryset, order_by, per_page, start=0):
     next_cursor = None
     if len(object_list) > per_page:
         next_slice_first_item = object_list.pop(-1)
-        next_cursor = getattr(next_slice_first_item, order_by)
+        attr_name = order_by.lstrip("-")
+        next_cursor = getattr(next_slice_first_item, attr_name)
 
     return CursorPage(start, object_list, next_cursor)
 

+ 1 - 1
misago/core/tests/test_cursor_paginator.py → misago/core/tests/test_cursor_pagination.py

@@ -1,6 +1,6 @@
 import pytest
 
-from ..cursorpaginator import CursorPage, EmptyPage, InvalidPage, get_page
+from ..cursorpagination import CursorPage, EmptyPage, InvalidPage, get_page
 
 
 @pytest.fixture

+ 3 - 3
misago/threads/tests/test_privatethreads_api.py

@@ -37,7 +37,7 @@ class PrivateThreadsListApiTests(PrivateThreadsTestCase):
         self.assertEqual(response.status_code, 200)
 
         response_json = response.json()
-        self.assertEqual(response_json["count"], 0)
+        self.assertEqual(len(response_json["results"]), 0)
 
     @patch_user_acl({"can_use_private_threads": True})
     def test_thread_visibility(self):
@@ -57,7 +57,7 @@ class PrivateThreadsListApiTests(PrivateThreadsTestCase):
         self.assertEqual(response.status_code, 200)
 
         response_json = response.json()
-        self.assertEqual(response_json["count"], 1)
+        self.assertEqual(len(response_json["results"]), 1)
         self.assertEqual(response_json["results"][0]["id"], visible.id)
 
         # threads with reported posts will also show to moderators
@@ -66,7 +66,7 @@ class PrivateThreadsListApiTests(PrivateThreadsTestCase):
             self.assertEqual(response.status_code, 200)
 
             response_json = response.json()
-            self.assertEqual(response_json["count"], 2)
+            self.assertEqual(len(response_json["results"]), 2)
             self.assertEqual(response_json["results"][0]["id"], reported.id)
             self.assertEqual(response_json["results"][1]["id"], visible.id)
 

+ 19 - 30
misago/threads/tests/test_threadslists.py

@@ -136,13 +136,6 @@ class ApiTests(ThreadsListTestCase):
         response = self.client.get("%s?category=%s" % (self.api_link, self.root.pk))
         self.assertEqual(response.status_code, 200)
 
-    def test_explicit_first_page(self):
-        """its possible to access threads endpoint with explicit first page"""
-        response = self.client.get(
-            "%s?category=%s&page=1" % (self.api_link, self.root.pk)
-        )
-        self.assertEqual(response.status_code, 200)
-
     def test_invalid_list_type(self):
         """api returns 404 for invalid list type"""
         response = self.client.get(
@@ -343,38 +336,34 @@ class AllThreadsListTests(ThreadsListTestCase):
         """threads list is paginated for users with js disabled"""
         threads_per_page = settings.MISAGO_THREADS_PER_PAGE
 
+        # post and discard thread to move last_post_id count by one
+        test.post_thread(category=self.first_category).delete()
+
+        # create test threads
         threads = []
-        for _ in range(settings.MISAGO_THREADS_PER_PAGE * 3):
+        for _ in range(settings.MISAGO_THREADS_PER_PAGE * 2):
             threads.append(test.post_thread(category=self.first_category))
 
-        # secondary page renders
-        response = self.client.get("/?page=2")
+        # threads starting with given one are on the list
+        response = self.client.get("/?start=%s" % threads[-2].last_post_id)
         self.assertEqual(response.status_code, 200)
 
-        for thread in threads[:threads_per_page]:
-            self.assertNotContainsThread(response, thread)
-        for thread in threads[threads_per_page : threads_per_page * 2]:
-            self.assertContainsThread(response, thread)
-        for thread in threads[threads_per_page * 2 :]:
-            self.assertNotContainsThread(response, thread)
-
-        self.assertNotContains(response, "/?page=1")
-        self.assertContains(response, "/?page=3")
+        # first thread is skipped by cursor pagination
+        self.assertNotContainsThread(response, threads[-1])
 
-        # third page renders
-        response = self.client.get("/?page=3")
-        self.assertEqual(response.status_code, 200)
+        # starting thread is present
+        self.assertContainsThread(response, threads[-2])
 
-        for thread in threads[threads_per_page:]:
-            self.assertNotContainsThread(response, thread)
-        for thread in threads[:threads_per_page]:
-            self.assertContainsThread(response, thread)
+        # slice contains expected threads
+        for visible_thread in threads[settings.MISAGO_THREADS_PER_PAGE - 1: -1]:
+            self.assertContainsThread(response, visible_thread)
 
-        self.assertContains(response, "/?page=2")
-        self.assertNotContains(response, "/?page=4")
+        # threads after slice are hidden
+        for invisible_thread in threads[:settings.MISAGO_THREADS_PER_PAGE - 1]:
+            self.assertNotContainsThread(response, invisible_thread)
 
-        # excessive page gives 404
-        response = self.client.get("/?page=4")
+        # nonexisting start gives 404
+        response = self.client.get("/?start=%s" % (threads[0].last_post_id - 1))
         self.assertEqual(response.status_code, 404)
 
 

+ 1 - 1
misago/threads/viewmodels/threads.py

@@ -7,7 +7,7 @@ from django.utils.translation import gettext_lazy
 
 from ...acl.objectacl import add_acl_to_obj
 from ...conf import settings
-from ...core.cursorpaginator import get_queryset_slice
+from ...core.cursorpagination import get_page
 from ...readtracker import threadstracker
 from ...readtracker.dates import get_cutoff_date
 from ..models import Post, Thread