diff --git a/src/newsreader/core/pagination.py b/src/newsreader/core/pagination.py
index 5e19771..b44c862 100644
--- a/src/newsreader/core/pagination.py
+++ b/src/newsreader/core/pagination.py
@@ -1,7 +1,7 @@
-from rest_framework.pagination import PageNumberPagination
+from rest_framework import pagination
-class ResultSetPagination(PageNumberPagination):
+class ResultSetPagination(pagination.PageNumberPagination):
page_size_query_param = "count"
max_page_size = 50
page_size = 30
@@ -10,3 +10,9 @@ class ResultSetPagination(PageNumberPagination):
class LargeResultSetPagination(ResultSetPagination):
max_page_size = 100
page_size = 50
+
+
+class CursorPagination(pagination.CursorPagination):
+ page_size_query_param = "count"
+ ordering = "-publication_date"
+ page_size = 30
diff --git a/src/newsreader/js/pages/homepage/actions/posts.js b/src/newsreader/js/pages/homepage/actions/posts.js
index f04f3e1..826512f 100644
--- a/src/newsreader/js/pages/homepage/actions/posts.js
+++ b/src/newsreader/js/pages/homepage/actions/posts.js
@@ -64,7 +64,7 @@ export const markPostRead = (post, token) => {
};
};
-export const fetchPostsBySection = (section, page = false) => {
+export const fetchPostsBySection = (section, next = false) => {
return dispatch => {
if (section.unread === 0) {
return;
@@ -76,10 +76,10 @@ export const fetchPostsBySection = (section, page = false) => {
switch (section.type) {
case RULE_TYPE:
- url = page ? page : `/api/rules/${section.id}/posts/?read=false`;
+ url = next ? next : `/api/rules/${section.id}/posts/?read=false`;
break;
case CATEGORY_TYPE:
- url = page ? page : `/api/categories/${section.id}/posts/?read=false`;
+ url = next ? next : `/api/categories/${section.id}/posts/?read=false`;
break;
}
diff --git a/src/newsreader/js/pages/homepage/components/postlist/PostList.js b/src/newsreader/js/pages/homepage/components/postlist/PostList.js
index 66e3b7f..282300b 100644
--- a/src/newsreader/js/pages/homepage/components/postlist/PostList.js
+++ b/src/newsreader/js/pages/homepage/components/postlist/PostList.js
@@ -90,7 +90,7 @@ const mapStateToProps = state => ({
});
const mapDispatchToProps = dispatch => ({
- fetchPostsBySection: (rule, page = false) => dispatch(fetchPostsBySection(rule, page)),
+ fetchPostsBySection: (rule, next = false) => dispatch(fetchPostsBySection(rule, next)),
});
export default connect(mapStateToProps, mapDispatchToProps)(PostList);
diff --git a/src/newsreader/js/pages/homepage/index.js b/src/newsreader/js/pages/homepage/index.js
index b934ad3..86cdd09 100644
--- a/src/newsreader/js/pages/homepage/index.js
+++ b/src/newsreader/js/pages/homepage/index.js
@@ -14,7 +14,7 @@ if (page) {
const settings = JSON.parse(document.getElementById('homepageSettings').textContent);
const { feedUrl, subredditUrl, timelineUrl, categoriesUrl } = settings;
- ReactDOM.render(
+ const app = (
- ,
- page
+
);
+
+ ReactDOM.render(app, page);
}
diff --git a/src/newsreader/news/collection/endpoints.py b/src/newsreader/news/collection/endpoints.py
index 7f2ede0..623283d 100644
--- a/src/newsreader/news/collection/endpoints.py
+++ b/src/newsreader/news/collection/endpoints.py
@@ -2,12 +2,16 @@ from rest_framework import status
from rest_framework.generics import (
GenericAPIView,
ListAPIView,
- RetrieveUpdateDestroyAPIView,
+ RetrieveUpdateAPIView,
get_object_or_404,
)
from rest_framework.response import Response
-from newsreader.core.pagination import LargeResultSetPagination, ResultSetPagination
+from newsreader.core.pagination import (
+ CursorPagination,
+ LargeResultSetPagination,
+ ResultSetPagination,
+)
from newsreader.news.collection.models import CollectionRule
from newsreader.news.collection.serializers import RuleSerializer
from newsreader.news.core.filters import ReadFilter
@@ -15,26 +19,15 @@ from newsreader.news.core.models import Post
from newsreader.news.core.serializers import PostSerializer
-class ListRuleView(ListAPIView):
+class DetailRuleView(RetrieveUpdateAPIView):
queryset = CollectionRule.objects.all()
serializer_class = RuleSerializer
- pagination_class = ResultSetPagination
-
- def get_queryset(self):
- user = self.request.user
- return self.queryset.filter(user=user).order_by("-created")
-
-
-class DetailRuleView(RetrieveUpdateDestroyAPIView):
- queryset = CollectionRule.objects.all()
- serializer_class = RuleSerializer
- pagination_class = ResultSetPagination
class NestedRuleView(ListAPIView):
queryset = CollectionRule.objects.prefetch_related("posts").all()
serializer_class = PostSerializer
- pagination_class = LargeResultSetPagination
+ pagination_class = CursorPagination
filter_backends = [ReadFilter]
def get_queryset(self):
diff --git a/src/newsreader/news/collection/tests/endpoints/rule/detail/tests.py b/src/newsreader/news/collection/tests/endpoints/rule/detail/tests.py
index 8dfe6ed..0e1bc7e 100644
--- a/src/newsreader/news/collection/tests/endpoints/rule/detail/tests.py
+++ b/src/newsreader/news/collection/tests/endpoints/rule/detail/tests.py
@@ -121,15 +121,6 @@ class CollectionRuleDetailViewTestCase(TestCase):
self.assertEquals(response.status_code, 200)
self.assertEquals(data["name"], "BBC")
- def test_delete(self):
- rule = FeedFactory(user=self.user)
-
- response = self.client.delete(
- reverse("api:news:collection:rules-detail", args=[rule.pk])
- )
-
- self.assertEquals(response.status_code, 204)
-
def test_rule_with_unauthenticated_user(self):
self.client.logout()
diff --git a/src/newsreader/news/collection/tests/endpoints/rule/list/tests.py b/src/newsreader/news/collection/tests/endpoints/rule/list/tests.py
index 44e3eaa..5a34dbc 100644
--- a/src/newsreader/news/collection/tests/endpoints/rule/list/tests.py
+++ b/src/newsreader/news/collection/tests/endpoints/rule/list/tests.py
@@ -12,137 +12,6 @@ from newsreader.news.collection.tests.factories import FeedFactory
from newsreader.news.core.tests.factories import CategoryFactory, FeedPostFactory
-class RuleListViewTestCase(TestCase):
- def setUp(self):
- self.user = UserFactory(password="test")
- self.client.force_login(self.user)
-
- def test_simple(self):
- FeedFactory.create_batch(size=3, user=self.user)
-
- response = self.client.get(reverse("api:news:collection:rules-list"))
- data = response.json()
-
- self.assertEquals(response.status_code, 200)
- self.assertTrue("results" in data)
- self.assertTrue("count" in data)
- self.assertEquals(data["count"], 3)
-
- def test_ordering(self):
- rules = [
- FeedFactory(
- created=datetime.combine(
- date(2019, 5, 20), time(hour=16, minute=7, second=37), pytz.utc
- ),
- user=self.user,
- ),
- FeedFactory(
- created=datetime.combine(
- date(2019, 7, 20), time(hour=18, minute=7, second=37), pytz.utc
- ),
- user=self.user,
- ),
- FeedFactory(
- created=datetime.combine(
- date(2019, 7, 20), time(hour=16, minute=7, second=37), pytz.utc
- ),
- user=self.user,
- ),
- ]
-
- response = self.client.get(reverse("api:news:collection:rules-list"))
- data = response.json()
-
- self.assertEquals(response.status_code, 200)
- self.assertTrue("results" in data)
- self.assertTrue("count" in data)
- self.assertEquals(data["count"], 3)
-
- self.assertEquals(data["results"][0]["id"], rules[1].pk)
- self.assertEquals(data["results"][1]["id"], rules[2].pk)
- self.assertEquals(data["results"][2]["id"], rules[0].pk)
-
- def test_pagination_count(self):
- FeedFactory.create_batch(size=80, user=self.user)
-
- response = self.client.get(
- reverse("api:news:collection:rules-list"), {"count": 30}
- )
- data = response.json()
-
- self.assertEquals(response.status_code, 200)
- self.assertEquals(data["count"], 80)
- self.assertEquals(len(data["results"]), 30)
-
- def test_empty(self):
- response = self.client.get(reverse("api:news:collection:rules-list"))
- data = response.json()
-
- self.assertEquals(response.status_code, 200)
- self.assertTrue("results" in data)
- self.assertTrue("count" in data)
-
- self.assertEquals(data["count"], 0)
- self.assertEquals(len(data["results"]), 0)
-
- def test_post(self):
- category = CategoryFactory(user=self.user)
-
- data = {"name": "BBC", "url": "https://www.bbc.co.uk", "category": category.pk}
-
- response = self.client.post(
- reverse("api:news:collection:rules-list"),
- data=json.dumps(data),
- content_type="application/json",
- )
- data = response.json()
-
- self.assertEquals(response.status_code, 405)
- self.assertEquals(data["detail"], 'Method "POST" not allowed.')
-
- def test_patch(self):
- response = self.client.patch(reverse("api:news:collection:rules-list"))
- data = response.json()
-
- self.assertEquals(response.status_code, 405)
- self.assertEquals(data["detail"], 'Method "PATCH" not allowed.')
-
- def test_put(self):
- response = self.client.put(reverse("api:news:collection:rules-list"))
- data = response.json()
-
- self.assertEquals(response.status_code, 405)
- self.assertEquals(data["detail"], 'Method "PUT" not allowed.')
-
- def test_delete(self):
- response = self.client.delete(reverse("api:news:collection:rules-list"))
- data = response.json()
-
- self.assertEquals(response.status_code, 405)
- self.assertEquals(data["detail"], 'Method "DELETE" not allowed.')
-
- def test_rules_with_unauthenticated_user(self):
- self.client.logout()
-
- FeedFactory.create_batch(size=3, user=self.user)
-
- response = self.client.get(reverse("api:news:collection:rules-list"))
-
- self.assertEquals(response.status_code, 403)
-
- def test_rules_with_unauthorized_user(self):
- other_user = UserFactory()
- FeedFactory.create_batch(size=3, user=other_user)
-
- response = self.client.get(reverse("api:news:collection:rules-list"))
- data = response.json()
-
- self.assertEquals(response.status_code, 200)
-
- self.assertEquals(data["count"], 0)
- self.assertEquals(len(data["results"]), 0)
-
-
class NestedRuleListViewTestCase(TestCase):
def setUp(self):
self.user = UserFactory(password="test")
@@ -157,11 +26,10 @@ class NestedRuleListViewTestCase(TestCase):
)
data = response.json()
- self.assertEquals(response.status_code, 200)
-
- self.assertTrue("results" in data)
- self.assertTrue("count" in data)
- self.assertEquals(data["count"], 5)
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(len(data["results"]), 5)
+ self.assertEqual(data["next"], None)
+ self.assertEqual(data["previous"], None)
def test_pagination(self):
rule = FeedFactory.create(user=self.user)
@@ -178,11 +46,12 @@ class NestedRuleListViewTestCase(TestCase):
)
data = response.json()
- self.assertEquals(response.status_code, 200)
- self.assertEquals(data["count"], 80)
- self.assertEquals(len(data["results"]), 30)
+ self.assertEqual(response.status_code, 200)
+ self.assertTrue(data["next"])
+ self.assertFalse(data["previous"])
- self.assertEquals(
+ self.assertEqual(len(data["results"]), 30)
+ self.assertEqual(
[post["id"] for post in data["results"]], [post.id for post in posts[:30]]
)
@@ -194,16 +63,15 @@ class NestedRuleListViewTestCase(TestCase):
)
data = response.json()
- self.assertEquals(response.status_code, 200)
- self.assertEquals(data["count"], 0)
- self.assertEquals(len(data["results"]), 0)
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(len(data["results"]), 0)
def test_not_known(self):
response = self.client.get(
reverse("api:news:collection:rules-nested-posts", kwargs={"pk": 0})
)
- self.assertEquals(response.status_code, 404)
+ self.assertEqual(response.status_code, 404)
def test_post(self):
rule = FeedFactory.create(user=self.user)
@@ -215,8 +83,8 @@ class NestedRuleListViewTestCase(TestCase):
)
data = response.json()
- self.assertEquals(response.status_code, 405)
- self.assertEquals(data["detail"], 'Method "POST" not allowed.')
+ self.assertEqual(response.status_code, 405)
+ self.assertEqual(data["detail"], 'Method "POST" not allowed.')
def test_patch(self):
rule = FeedFactory.create(user=self.user)
@@ -228,8 +96,8 @@ class NestedRuleListViewTestCase(TestCase):
)
data = response.json()
- self.assertEquals(response.status_code, 405)
- self.assertEquals(data["detail"], 'Method "PATCH" not allowed.')
+ self.assertEqual(response.status_code, 405)
+ self.assertEqual(data["detail"], 'Method "PATCH" not allowed.')
def test_put(self):
rule = FeedFactory.create(user=self.user)
@@ -241,8 +109,8 @@ class NestedRuleListViewTestCase(TestCase):
)
data = response.json()
- self.assertEquals(response.status_code, 405)
- self.assertEquals(data["detail"], 'Method "PUT" not allowed.')
+ self.assertEqual(response.status_code, 405)
+ self.assertEqual(data["detail"], 'Method "PUT" not allowed.')
def test_delete(self):
rule = FeedFactory.create(user=self.user)
@@ -254,8 +122,8 @@ class NestedRuleListViewTestCase(TestCase):
)
data = response.json()
- self.assertEquals(response.status_code, 405)
- self.assertEquals(data["detail"], 'Method "DELETE" not allowed.')
+ self.assertEqual(response.status_code, 405)
+ self.assertEqual(data["detail"], 'Method "DELETE" not allowed.')
def test_rule_with_unauthenticated_user(self):
self.client.logout()
@@ -266,7 +134,7 @@ class NestedRuleListViewTestCase(TestCase):
reverse("api:news:collection:rules-nested-posts", kwargs={"pk": rule.pk})
)
- self.assertEquals(response.status_code, 403)
+ self.assertEqual(response.status_code, 403)
def test_rule_with_unauthorized_user(self):
other_user = UserFactory()
@@ -276,7 +144,7 @@ class NestedRuleListViewTestCase(TestCase):
reverse("api:news:collection:rules-nested-posts", kwargs={"pk": rule.pk})
)
- self.assertEquals(response.status_code, 403)
+ self.assertEqual(response.status_code, 403)
def test_posts_ordering(self):
rule = FeedFactory(user=self.user, category=CategoryFactory(user=self.user))
@@ -310,14 +178,12 @@ class NestedRuleListViewTestCase(TestCase):
)
data = response.json()
- self.assertEquals(response.status_code, 200)
- self.assertTrue("results" in data)
- self.assertTrue("count" in data)
- self.assertEquals(data["count"], 3)
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(len(data["results"]), 3)
- self.assertEquals(data["results"][0]["id"], posts[1].pk)
- self.assertEquals(data["results"][1]["id"], posts[2].pk)
- self.assertEquals(data["results"][2]["id"], posts[0].pk)
+ self.assertEqual(data["results"][0]["id"], posts[1].pk)
+ self.assertEqual(data["results"][1]["id"], posts[2].pk)
+ self.assertEqual(data["results"][2]["id"], posts[0].pk)
def test_only_posts_from_rule_are_returned(self):
rule = FeedFactory.create(user=self.user)
@@ -331,14 +197,12 @@ class NestedRuleListViewTestCase(TestCase):
)
data = response.json()
- self.assertEquals(response.status_code, 200)
-
- self.assertTrue("results" in data)
- self.assertTrue("count" in data)
- self.assertEquals(data["count"], 5)
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(len(data["results"]), 5)
for post in data["results"]:
- self.assertEquals(post["rule"], rule.pk)
+ with self.subTest(post=post):
+ self.assertEqual(post["rule"], rule.pk)
def test_unread_posts(self):
rule = FeedFactory.create(user=self.user)
@@ -352,13 +216,13 @@ class NestedRuleListViewTestCase(TestCase):
)
data = response.json()
- posts = data["results"]
- self.assertEquals(response.status_code, 200)
- self.assertEquals(data["count"], 10)
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(len(data["results"]), 10)
- for post in posts:
- self.assertEquals(post["read"], False)
+ for post in data["results"]:
+ with self.subTest(post=post):
+ self.assertEqual(post["read"], False)
def test_read_posts(self):
rule = FeedFactory.create(user=self.user)
@@ -372,10 +236,10 @@ class NestedRuleListViewTestCase(TestCase):
)
data = response.json()
- posts = data["results"]
- self.assertEquals(response.status_code, 200)
- self.assertEquals(data["count"], 10)
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(len(data["results"]), 10)
- for post in posts:
- self.assertEquals(post["read"], True)
+ for post in data["results"]:
+ with self.subTest(post=post):
+ self.assertEqual(post["read"], True)
diff --git a/src/newsreader/news/collection/urls.py b/src/newsreader/news/collection/urls.py
index 7d883f2..e5276cb 100644
--- a/src/newsreader/news/collection/urls.py
+++ b/src/newsreader/news/collection/urls.py
@@ -3,7 +3,6 @@ from django.urls import path
from newsreader.news.collection.endpoints import (
DetailRuleView,
- ListRuleView,
NestedRuleView,
RuleReadView,
)
@@ -26,7 +25,6 @@ endpoints = [
path("rules//", DetailRuleView.as_view(), name="rules-detail"),
path("rules//posts/", NestedRuleView.as_view(), name="rules-nested-posts"),
path("rules//read/", RuleReadView.as_view(), name="rules-read"),
- path("rules/", ListRuleView.as_view(), name="rules-list"),
]
urlpatterns = [
diff --git a/src/newsreader/news/core/endpoints.py b/src/newsreader/news/core/endpoints.py
index f5a48bc..ab47cca 100644
--- a/src/newsreader/news/core/endpoints.py
+++ b/src/newsreader/news/core/endpoints.py
@@ -1,5 +1,3 @@
-from django.db.models import Q
-
from rest_framework import status
from rest_framework.generics import (
GenericAPIView,
@@ -13,30 +11,13 @@ from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from newsreader.accounts.permissions import IsPostOwner
-from newsreader.core.pagination import LargeResultSetPagination
+from newsreader.core.pagination import CursorPagination
from newsreader.news.collection.serializers import RuleSerializer
from newsreader.news.core.filters import ReadFilter
from newsreader.news.core.models import Category, Post
from newsreader.news.core.serializers import CategorySerializer, PostSerializer
-class ListPostView(ListAPIView):
- queryset = Post.objects.all()
- serializer_class = PostSerializer
- pagination_class = LargeResultSetPagination
- filter_backends = [ReadFilter]
-
- def get_queryset(self):
- user = self.request.user
- queryset = (
- self.queryset.filter(rule__user=user)
- .filter(Q(rule__category=None) | Q(rule__category__user=user))
- .order_by("rule", "-publication_date", "-created")
- )
-
- return queryset
-
-
class DetailPostView(RetrieveUpdateAPIView):
queryset = Post.objects.all()
serializer_class = PostSerializer
@@ -77,7 +58,7 @@ class NestedRuleCategoryView(ListAPIView):
class NestedPostCategoryView(ListAPIView):
queryset = Category.objects.prefetch_related("rules", "rules__posts").all()
serializer_class = PostSerializer
- pagination_class = LargeResultSetPagination
+ pagination_class = CursorPagination
filter_backends = [ReadFilter]
def get_queryset(self):
@@ -90,9 +71,8 @@ class NestedPostCategoryView(ListAPIView):
category = get_object_or_404(self.queryset, **filter_kwargs)
self.check_object_permissions(self.request, category)
- queryset = Post.objects.filter(
- rule__in=category.rules.values_list("id", flat=True)
- ).order_by("-publication_date", "rule__name")
+ rules = category.rules.values_list("id", flat=True)
+ queryset = Post.objects.filter(rule__in=rules)
return queryset
diff --git a/src/newsreader/news/core/tests/endpoints/category/list/tests.py b/src/newsreader/news/core/tests/endpoints/category/list/tests.py
index 15fb166..c822950 100644
--- a/src/newsreader/news/core/tests/endpoints/category/list/tests.py
+++ b/src/newsreader/news/core/tests/endpoints/category/list/tests.py
@@ -1,6 +1,6 @@
import json
-from datetime import date, datetime, time
+from datetime import datetime
from django.test import TestCase
from django.urls import reverse
@@ -23,27 +23,21 @@ class CategoryListViewTestCase(TestCase):
response = self.client.get(reverse("api:news:core:categories-list"))
data = response.json()
- self.assertEquals(response.status_code, 200)
- self.assertEquals(len(data), 3)
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(len(data), 3)
def test_ordering(self):
categories = [
CategoryFactory(
- created=datetime.combine(
- date(2019, 5, 20), time(hour=16, minute=7, second=37), pytz.utc
- ),
+ created=datetime(2019, 5, 20, 16, 7, 37, tzinfo=pytz.utc),
user=self.user,
),
CategoryFactory(
- created=datetime.combine(
- date(2019, 7, 20), time(hour=18, minute=7, second=37), pytz.utc
- ),
+ created=datetime(2019, 7, 20, 18, 7, 37, tzinfo=pytz.utc),
user=self.user,
),
CategoryFactory(
- created=datetime.combine(
- date(2019, 7, 20), time(hour=16, minute=7, second=37), pytz.utc
- ),
+ created=datetime(2019, 7, 20, 16, 7, 37, tzinfo=pytz.utc),
user=self.user,
),
]
@@ -51,18 +45,18 @@ class CategoryListViewTestCase(TestCase):
response = self.client.get(reverse("api:news:core:categories-list"))
data = response.json()
- self.assertEquals(response.status_code, 200)
+ self.assertEqual(response.status_code, 200)
- self.assertEquals(data[0]["id"], categories[1].pk)
- self.assertEquals(data[1]["id"], categories[2].pk)
- self.assertEquals(data[2]["id"], categories[0].pk)
+ self.assertEqual(data[0]["id"], categories[1].pk)
+ self.assertEqual(data[1]["id"], categories[2].pk)
+ self.assertEqual(data[2]["id"], categories[0].pk)
def test_empty(self):
response = self.client.get(reverse("api:news:core:categories-list"))
data = response.json()
- self.assertEquals(response.status_code, 200)
- self.assertEquals(len(data), 0)
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(len(data), 0)
def test_post(self):
data = {"name": "Tech"}
@@ -74,29 +68,29 @@ class CategoryListViewTestCase(TestCase):
)
response_data = response.json()
- self.assertEquals(response.status_code, 405)
- self.assertEquals(response_data["detail"], 'Method "POST" not allowed.')
+ self.assertEqual(response.status_code, 405)
+ self.assertEqual(response_data["detail"], 'Method "POST" not allowed.')
def test_patch(self):
response = self.client.patch(reverse("api:news:core:categories-list"))
data = response.json()
- self.assertEquals(response.status_code, 405)
- self.assertEquals(data["detail"], 'Method "PATCH" not allowed.')
+ self.assertEqual(response.status_code, 405)
+ self.assertEqual(data["detail"], 'Method "PATCH" not allowed.')
def test_put(self):
response = self.client.put(reverse("api:news:core:categories-list"))
data = response.json()
- self.assertEquals(response.status_code, 405)
- self.assertEquals(data["detail"], 'Method "PUT" not allowed.')
+ self.assertEqual(response.status_code, 405)
+ self.assertEqual(data["detail"], 'Method "PUT" not allowed.')
def test_delete(self):
response = self.client.delete(reverse("api:news:core:categories-list"))
data = response.json()
- self.assertEquals(response.status_code, 405)
- self.assertEquals(data["detail"], 'Method "DELETE" not allowed.')
+ self.assertEqual(response.status_code, 405)
+ self.assertEqual(data["detail"], 'Method "DELETE" not allowed.')
def test_categories_with_unauthenticated_user(self):
self.client.logout()
@@ -105,7 +99,7 @@ class CategoryListViewTestCase(TestCase):
response = self.client.get(reverse("api:news:core:categories-list"))
- self.assertEquals(response.status_code, 403)
+ self.assertEqual(response.status_code, 403)
def test_categories_with_unauthorized_user(self):
other_user = UserFactory()
@@ -114,8 +108,8 @@ class CategoryListViewTestCase(TestCase):
response = self.client.get(reverse("api:news:core:categories-list"))
data = response.json()
- self.assertEquals(response.status_code, 200)
- self.assertEquals(len(data), 0)
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(len(data), 0)
class NestedCategoryListViewTestCase(TestCase):
@@ -132,8 +126,8 @@ class NestedCategoryListViewTestCase(TestCase):
)
data = response.json()
- self.assertEquals(response.status_code, 200)
- self.assertEquals(len(data), 5)
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(len(data), 5)
self.assertTrue("id" in data[0])
self.assertTrue("name" in data[0])
@@ -149,16 +143,16 @@ class NestedCategoryListViewTestCase(TestCase):
)
data = response.json()
- self.assertEquals(response.status_code, 200)
- self.assertEquals(len(data), 0)
- self.assertEquals(data, [])
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(len(data), 0)
+ self.assertEqual(data, [])
def test_not_known(self):
response = self.client.get(
reverse("api:news:core:categories-nested-rules", kwargs={"pk": 100})
)
- self.assertEquals(response.status_code, 404)
+ self.assertEqual(response.status_code, 404)
def test_post(self):
response = self.client.post(
@@ -168,8 +162,8 @@ class NestedCategoryListViewTestCase(TestCase):
)
data = response.json()
- self.assertEquals(response.status_code, 405)
- self.assertEquals(data["detail"], 'Method "POST" not allowed.')
+ self.assertEqual(response.status_code, 405)
+ self.assertEqual(data["detail"], 'Method "POST" not allowed.')
def test_patch(self):
category = CategoryFactory.create(user=self.user)
@@ -183,8 +177,8 @@ class NestedCategoryListViewTestCase(TestCase):
)
data = response.json()
- self.assertEquals(response.status_code, 405)
- self.assertEquals(data["detail"], 'Method "PATCH" not allowed.')
+ self.assertEqual(response.status_code, 405)
+ self.assertEqual(data["detail"], 'Method "PATCH" not allowed.')
def test_put(self):
category = CategoryFactory.create(user=self.user)
@@ -198,8 +192,8 @@ class NestedCategoryListViewTestCase(TestCase):
)
data = response.json()
- self.assertEquals(response.status_code, 405)
- self.assertEquals(data["detail"], 'Method "PUT" not allowed.')
+ self.assertEqual(response.status_code, 405)
+ self.assertEqual(data["detail"], 'Method "PUT" not allowed.')
def test_delete(self):
category = CategoryFactory.create(user=self.user)
@@ -212,8 +206,8 @@ class NestedCategoryListViewTestCase(TestCase):
)
data = response.json()
- self.assertEquals(response.status_code, 405)
- self.assertEquals(data["detail"], 'Method "DELETE" not allowed.')
+ self.assertEqual(response.status_code, 405)
+ self.assertEqual(data["detail"], 'Method "DELETE" not allowed.')
def test_with_unauthenticated_user(self):
self.client.logout()
@@ -225,7 +219,7 @@ class NestedCategoryListViewTestCase(TestCase):
reverse("api:news:core:categories-nested-rules", kwargs={"pk": category.pk})
)
- self.assertEquals(response.status_code, 403)
+ self.assertEqual(response.status_code, 403)
def test_with_unauthorized_user(self):
other_user = UserFactory.create()
@@ -237,7 +231,7 @@ class NestedCategoryListViewTestCase(TestCase):
reverse("api:news:core:categories-nested-rules", kwargs={"pk": category.pk})
)
- self.assertEquals(response.status_code, 403)
+ self.assertEqual(response.status_code, 403)
def test_ordering(self):
category = CategoryFactory.create(user=self.user)
@@ -252,12 +246,12 @@ class NestedCategoryListViewTestCase(TestCase):
)
data = response.json()
- self.assertEquals(response.status_code, 200)
- self.assertEquals(len(data), 3)
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(len(data), 3)
- self.assertEquals(data[0]["id"], rules[2].pk)
- self.assertEquals(data[1]["id"], rules[0].pk)
- self.assertEquals(data[2]["id"], rules[1].pk)
+ self.assertEqual(data[0]["id"], rules[2].pk)
+ self.assertEqual(data[1]["id"], rules[0].pk)
+ self.assertEqual(data[2]["id"], rules[1].pk)
def test_only_rules_from_category_are_returned(self):
other_category = CategoryFactory(user=self.user)
@@ -275,12 +269,12 @@ class NestedCategoryListViewTestCase(TestCase):
)
data = response.json()
- self.assertEquals(response.status_code, 200)
- self.assertEquals(len(data), 3)
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(len(data), 3)
- self.assertEquals(data[0]["id"], rules[2].pk)
- self.assertEquals(data[1]["id"], rules[0].pk)
- self.assertEquals(data[2]["id"], rules[1].pk)
+ self.assertEqual(data[0]["id"], rules[2].pk)
+ self.assertEqual(data[1]["id"], rules[0].pk)
+ self.assertEqual(data[2]["id"], rules[1].pk)
class NestedCategoryPostView(TestCase):
@@ -301,16 +295,15 @@ class NestedCategoryPostView(TestCase):
reverse("api:news:core:categories-nested-posts", kwargs={"pk": category.pk})
)
data = response.json()
- posts = data["results"]
- self.assertEquals(response.status_code, 200)
- self.assertEquals(data["count"], 25)
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(len(data["results"]), 25)
- self.assertTrue("id" in posts[0])
- self.assertTrue("title" in posts[0])
- self.assertTrue("body" in posts[0])
- self.assertTrue("rule" in posts[0])
- self.assertTrue("url" in posts[0])
+ self.assertTrue("id" in data["results"][0])
+ self.assertTrue("title" in data["results"][0])
+ self.assertTrue("body" in data["results"][0])
+ self.assertTrue("rule" in data["results"][0])
+ self.assertTrue("url" in data["results"][0])
def test_no_rules(self):
category = CategoryFactory.create(user=self.user)
@@ -321,9 +314,9 @@ class NestedCategoryPostView(TestCase):
data = response.json()
posts = data["results"]
- self.assertEquals(response.status_code, 200)
- self.assertEquals(data["count"], 0)
- self.assertEquals(posts, [])
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(len(data["results"]), 0)
+ self.assertEqual(posts, [])
def test_no_posts(self):
category = CategoryFactory.create(user=self.user)
@@ -335,16 +328,16 @@ class NestedCategoryPostView(TestCase):
data = response.json()
posts = data["results"]
- self.assertEquals(response.status_code, 200)
- self.assertEquals(data["count"], 0)
- self.assertEquals(posts, [])
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(len(data["results"]), 0)
+ self.assertEqual(posts, [])
def test_not_known(self):
response = self.client.get(
reverse("api:news:core:categories-nested-posts", kwargs={"pk": 100})
)
- self.assertEquals(response.status_code, 404)
+ self.assertEqual(response.status_code, 404)
def test_post(self):
response = self.client.post(
@@ -354,8 +347,8 @@ class NestedCategoryPostView(TestCase):
)
data = response.json()
- self.assertEquals(response.status_code, 405)
- self.assertEquals(data["detail"], 'Method "POST" not allowed.')
+ self.assertEqual(response.status_code, 405)
+ self.assertEqual(data["detail"], 'Method "POST" not allowed.')
def test_patch(self):
category = CategoryFactory.create(user=self.user)
@@ -369,8 +362,8 @@ class NestedCategoryPostView(TestCase):
)
data = response.json()
- self.assertEquals(response.status_code, 405)
- self.assertEquals(data["detail"], 'Method "PATCH" not allowed.')
+ self.assertEqual(response.status_code, 405)
+ self.assertEqual(data["detail"], 'Method "PATCH" not allowed.')
def test_put(self):
category = CategoryFactory.create(user=self.user)
@@ -384,8 +377,8 @@ class NestedCategoryPostView(TestCase):
)
data = response.json()
- self.assertEquals(response.status_code, 405)
- self.assertEquals(data["detail"], 'Method "PUT" not allowed.')
+ self.assertEqual(response.status_code, 405)
+ self.assertEqual(data["detail"], 'Method "PUT" not allowed.')
def test_delete(self):
category = CategoryFactory.create(user=self.user)
@@ -398,8 +391,8 @@ class NestedCategoryPostView(TestCase):
)
data = response.json()
- self.assertEquals(response.status_code, 405)
- self.assertEquals(data["detail"], 'Method "DELETE" not allowed.')
+ self.assertEqual(response.status_code, 405)
+ self.assertEqual(data["detail"], 'Method "DELETE" not allowed.')
def test_with_unauthenticated_user(self):
self.client.logout()
@@ -410,7 +403,7 @@ class NestedCategoryPostView(TestCase):
reverse("api:news:core:categories-nested-posts", kwargs={"pk": category.pk})
)
- self.assertEquals(response.status_code, 403)
+ self.assertEqual(response.status_code, 403)
def test_with_unauthorized_user(self):
other_user = UserFactory.create()
@@ -420,7 +413,7 @@ class NestedCategoryPostView(TestCase):
reverse("api:news:core:categories-nested-posts", kwargs={"pk": category.pk})
)
- self.assertEquals(response.status_code, 403)
+ self.assertEqual(response.status_code, 403)
def test_ordering(self):
category = CategoryFactory.create(user=self.user)
@@ -437,16 +430,12 @@ class NestedCategoryPostView(TestCase):
FeedPostFactory.create(
title="Second Reuters post",
rule=reuters_rule,
- publication_date=datetime.combine(
- date(2019, 5, 21), time(hour=16, minute=7, second=37), pytz.utc
- ),
+ publication_date=datetime(2019, 5, 21, 15, tzinfo=pytz.utc),
),
FeedPostFactory.create(
title="First Reuters post",
rule=reuters_rule,
- publication_date=datetime.combine(
- date(2019, 5, 20), time(hour=16, minute=7, second=37), pytz.utc
- ),
+ publication_date=datetime(2019, 5, 20, 12, tzinfo=pytz.utc),
),
]
@@ -454,16 +443,12 @@ class NestedCategoryPostView(TestCase):
FeedPostFactory.create(
title="Second Guardian post",
rule=guardian_rule,
- publication_date=datetime.combine(
- date(2019, 5, 21), time(hour=16, minute=7, second=37), pytz.utc
- ),
+ publication_date=datetime(2019, 5, 21, 14, tzinfo=pytz.utc),
),
FeedPostFactory.create(
title="First Guardian post",
rule=guardian_rule,
- publication_date=datetime.combine(
- date(2019, 5, 20), time(hour=16, minute=7, second=37), pytz.utc
- ),
+ publication_date=datetime(2019, 5, 20, 11, tzinfo=pytz.utc),
),
]
@@ -471,16 +456,12 @@ class NestedCategoryPostView(TestCase):
FeedPostFactory.create(
title="Second BBC post",
rule=bbc_rule,
- publication_date=datetime.combine(
- date(2019, 5, 21), time(hour=16, minute=7, second=37), pytz.utc
- ),
+ publication_date=datetime(2019, 5, 21, 16, tzinfo=pytz.utc),
),
FeedPostFactory.create(
title="First BBC post",
rule=bbc_rule,
- publication_date=datetime.combine(
- date(2019, 5, 20), time(hour=16, minute=7, second=37), pytz.utc
- ),
+ publication_date=datetime(2019, 5, 20, 13, tzinfo=pytz.utc),
),
]
@@ -490,16 +471,16 @@ class NestedCategoryPostView(TestCase):
data = response.json()
posts = data["results"]
- self.assertEquals(response.status_code, 200)
- self.assertEquals(data["count"], 6)
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(len(data["results"]), 6)
- self.assertEquals(posts[0]["title"], "Second BBC post")
- self.assertEquals(posts[1]["title"], "Second Reuters post")
- self.assertEquals(posts[2]["title"], "Second Guardian post")
+ self.assertEqual(posts[0]["title"], "Second BBC post")
+ self.assertEqual(posts[1]["title"], "Second Reuters post")
+ self.assertEqual(posts[2]["title"], "Second Guardian post")
- self.assertEquals(posts[3]["title"], "First BBC post")
- self.assertEquals(posts[4]["title"], "First Reuters post")
- self.assertEquals(posts[5]["title"], "First Guardian post")
+ self.assertEqual(posts[3]["title"], "First BBC post")
+ self.assertEqual(posts[4]["title"], "First Reuters post")
+ self.assertEqual(posts[5]["title"], "First Guardian post")
def test_only_posts_from_category_are_returned(self):
category = CategoryFactory.create(user=self.user)
@@ -526,11 +507,11 @@ class NestedCategoryPostView(TestCase):
data = response.json()
posts = data["results"]
- self.assertEquals(response.status_code, 200)
- self.assertEquals(data["count"], 2)
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(len(data["results"]), 2)
- self.assertEquals(posts[0]["rule"], guardian_rule.pk)
- self.assertEquals(posts[1]["rule"], guardian_rule.pk)
+ self.assertEqual(posts[0]["rule"], guardian_rule.pk)
+ self.assertEqual(posts[1]["rule"], guardian_rule.pk)
def test_unread_posts(self):
category = CategoryFactory.create(user=self.user)
@@ -549,11 +530,11 @@ class NestedCategoryPostView(TestCase):
data = response.json()
posts = data["results"]
- self.assertEquals(response.status_code, 200)
- self.assertEquals(data["count"], 10)
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(len(data["results"]), 10)
for post in posts:
- self.assertEquals(post["read"], False)
+ self.assertEqual(post["read"], False)
def test_read_posts(self):
category = CategoryFactory.create(user=self.user)
@@ -572,8 +553,8 @@ class NestedCategoryPostView(TestCase):
data = response.json()
posts = data["results"]
- self.assertEquals(response.status_code, 200)
- self.assertEquals(data["count"], 10)
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(len(data["results"]), 10)
for post in posts:
- self.assertEquals(post["read"], True)
+ self.assertEqual(post["read"], True)
diff --git a/src/newsreader/news/core/tests/endpoints/post/list/__init__.py b/src/newsreader/news/core/tests/endpoints/post/list/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/src/newsreader/news/core/tests/endpoints/post/list/tests.py b/src/newsreader/news/core/tests/endpoints/post/list/tests.py
deleted file mode 100644
index 3bf9d17..0000000
--- a/src/newsreader/news/core/tests/endpoints/post/list/tests.py
+++ /dev/null
@@ -1,234 +0,0 @@
-from datetime import date, datetime, time
-
-from django.test import TestCase
-from django.urls import reverse
-
-import pytz
-
-from newsreader.accounts.tests.factories import UserFactory
-from newsreader.news.collection.tests.factories import FeedFactory
-from newsreader.news.core.tests.factories import CategoryFactory, FeedPostFactory
-
-
-class PostListViewTestCase(TestCase):
- def setUp(self):
- self.user = UserFactory(is_staff=True, password="test")
- self.client.force_login(self.user)
-
- def test_simple(self):
- rule = FeedFactory(user=self.user, category=CategoryFactory(user=self.user))
- FeedPostFactory.create_batch(size=3, rule=rule)
-
- response = self.client.get(reverse("api:news:core:posts-list"))
- data = response.json()
-
- self.assertEquals(response.status_code, 200)
- self.assertTrue("results" in data)
- self.assertTrue("count" in data)
- self.assertEquals(data["count"], 3)
-
- def test_ordering(self):
- rule = FeedFactory(user=self.user, category=CategoryFactory(user=self.user))
-
- posts = [
- FeedPostFactory(
- title="I'm the first post",
- rule=rule,
- publication_date=datetime.combine(
- date(2019, 5, 20), time(hour=16, minute=7, second=37), pytz.utc
- ),
- ),
- FeedPostFactory(
- title="I'm the second post",
- rule=rule,
- publication_date=datetime.combine(
- date(2019, 7, 20), time(hour=18, minute=7, second=37), pytz.utc
- ),
- ),
- FeedPostFactory(
- title="I'm the third post",
- rule=rule,
- publication_date=datetime.combine(
- date(2019, 7, 20), time(hour=16, minute=7, second=37), pytz.utc
- ),
- ),
- ]
-
- response = self.client.get(reverse("api:news:core:posts-list"))
- data = response.json()
-
- self.assertEquals(response.status_code, 200)
- self.assertTrue("results" in data)
- self.assertTrue("count" in data)
- self.assertEquals(data["count"], 3)
-
- self.assertEquals(data["results"][0]["id"], posts[1].pk)
- self.assertEquals(data["results"][1]["id"], posts[2].pk)
- self.assertEquals(data["results"][2]["id"], posts[0].pk)
-
- def test_pagination_count(self):
- rule = FeedFactory(user=self.user, category=CategoryFactory(user=self.user))
- FeedPostFactory.create_batch(size=80, rule=rule)
- page_size = 50
-
- response = self.client.get(reverse("api:news:core:posts-list"), {"count": 50})
- data = response.json()
-
- self.assertEquals(response.status_code, 200)
- self.assertEquals(data["count"], 80)
- self.assertEquals(len(data["results"]), page_size)
-
- def test_empty(self):
- response = self.client.get(reverse("api:news:core:posts-list"))
- data = response.json()
-
- self.assertEquals(response.status_code, 200)
- self.assertTrue("results" in data)
- self.assertTrue("count" in data)
-
- self.assertEquals(data["count"], 0)
- self.assertEquals(len(data["results"]), 0)
-
- def test_post(self):
- response = self.client.post(reverse("api:news:core:posts-list"))
- data = response.json()
-
- self.assertEquals(response.status_code, 405)
- self.assertEquals(data["detail"], 'Method "POST" not allowed.')
-
- def test_patch(self):
- response = self.client.patch(reverse("api:news:core:posts-list"))
- data = response.json()
-
- self.assertEquals(response.status_code, 405)
- self.assertEquals(data["detail"], 'Method "PATCH" not allowed.')
-
- def test_put(self):
- response = self.client.put(reverse("api:news:core:posts-list"))
- data = response.json()
-
- self.assertEquals(response.status_code, 405)
- self.assertEquals(data["detail"], 'Method "PUT" not allowed.')
-
- def test_delete(self):
- response = self.client.delete(reverse("api:news:core:posts-list"))
- data = response.json()
-
- self.assertEquals(response.status_code, 405)
- self.assertEquals(data["detail"], 'Method "DELETE" not allowed.')
-
- def test_posts_with_unauthenticated_user_without_category(self):
- self.client.logout()
-
- FeedPostFactory.create_batch(size=3, rule=FeedFactory(user=self.user))
-
- response = self.client.get(reverse("api:news:core:posts-list"))
-
- self.assertEquals(response.status_code, 403)
-
- def test_posts_with_unauthenticated_user_with_category(self):
- self.client.logout()
-
- category = CategoryFactory(user=self.user)
-
- FeedPostFactory.create_batch(
- size=3, rule=FeedFactory(user=self.user, category=category)
- )
-
- response = self.client.get(reverse("api:news:core:posts-list"))
-
- self.assertEquals(response.status_code, 403)
-
- def test_posts_with_unauthorized_user_without_category(self):
- other_user = UserFactory()
-
- rule = FeedFactory(user=other_user, category=None)
- FeedPostFactory.create_batch(size=3, rule=rule)
-
- response = self.client.get(reverse("api:news:core:posts-list"))
- data = response.json()
-
- self.assertEquals(response.status_code, 200)
- self.assertEquals(len(data["results"]), 0)
- self.assertEquals(data["count"], 0)
-
- def test_posts_with_unauthorized_user_with_category(self):
- other_user = UserFactory()
- category = CategoryFactory(user=other_user)
-
- FeedPostFactory.create_batch(
- size=3, rule=FeedFactory(user=other_user, category=category)
- )
-
- response = self.client.get(reverse("api:news:core:posts-list"))
- data = response.json()
-
- self.assertEquals(response.status_code, 200)
- self.assertEquals(len(data["results"]), 0)
- self.assertEquals(data["count"], 0)
-
- # Note that this situation should not be possible, due to the user not being able
- # to specify the user when creating categories/rules
- def test_posts_with_authorized_rule_unauthorized_category(self):
- other_user = UserFactory()
-
- rule = FeedFactory(user=self.user, category=CategoryFactory(user=other_user))
- FeedPostFactory.create_batch(size=3, rule=rule)
-
- response = self.client.get(reverse("api:news:core:posts-list"))
- data = response.json()
-
- self.assertEquals(response.status_code, 200)
- self.assertTrue("results" in data)
- self.assertTrue("count" in data)
- self.assertEquals(data["count"], 0)
-
- def test_posts_with_authorized_user_without_category(self):
- rule = FeedFactory(user=self.user, category=None)
- FeedPostFactory.create_batch(size=3, rule=rule)
-
- response = self.client.get(reverse("api:news:core:posts-list"))
- data = response.json()
-
- self.assertEquals(response.status_code, 200)
- self.assertTrue("results" in data)
- self.assertTrue("count" in data)
- self.assertEquals(data["count"], 3)
-
- def test_unread_posts(self):
- rule = FeedFactory(user=self.user, category=CategoryFactory(user=self.user))
-
- FeedPostFactory.create_batch(size=10, rule=rule, read=False)
- FeedPostFactory.create_batch(size=10, rule=rule, read=True)
-
- response = self.client.get(
- reverse("api:news:core:posts-list"), {"read": "false"}
- )
-
- data = response.json()
- posts = data["results"]
-
- self.assertEquals(response.status_code, 200)
- self.assertEquals(data["count"], 10)
-
- for post in posts:
- self.assertEquals(post["read"], False)
-
- def test_read_posts(self):
- rule = FeedFactory(user=self.user, category=CategoryFactory(user=self.user))
-
- FeedPostFactory.create_batch(size=20, rule=rule, read=False)
- FeedPostFactory.create_batch(size=10, rule=rule, read=True)
-
- response = self.client.get(
- reverse("api:news:core:posts-list"), {"read": "true"}
- )
-
- data = response.json()
- posts = data["results"]
-
- self.assertEquals(response.status_code, 200)
- self.assertEquals(data["count"], 10)
-
- for post in posts:
- self.assertEquals(post["read"], True)
diff --git a/src/newsreader/news/core/urls.py b/src/newsreader/news/core/urls.py
index 8096cf8..21db59d 100644
--- a/src/newsreader/news/core/urls.py
+++ b/src/newsreader/news/core/urls.py
@@ -6,7 +6,6 @@ from newsreader.news.core.endpoints import (
DetailCategoryView,
DetailPostView,
ListCategoryView,
- ListPostView,
NestedPostCategoryView,
NestedRuleCategoryView,
)
@@ -33,7 +32,6 @@ urlpatterns = [
]
endpoints = [
- path("posts/", ListPostView.as_view(), name="posts-list"),
path("posts//", DetailPostView.as_view(), name="posts-detail"),
path("categories/", ListCategoryView.as_view(), name="categories-list"),
path(