Skip to content

Commit

Permalink
✨(api) allow on-demand page size on the order and enrollment endpoints
Browse files Browse the repository at this point in the history
The order and enrollment endpoints are used by the frontend to build
a view mixing both objects. For this, the frontend needs to be able
to customize the number of items returned by page. We fix the max
size of the page to 100 items for security reasons.
  • Loading branch information
sampaccoud authored and jbpenrath committed Feb 28, 2023
1 parent 8ae0988 commit 4d3a04a
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ and this project adheres to

## Added

- Allow on-demand page size on the order and enrollment endpoints
- Add yarn cli to generate joanie api client in TypeScript

### Removed
Expand Down
3 changes: 2 additions & 1 deletion src/backend/joanie/core/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ class Pagination(pagination.PageNumberPagination):
"""Pagination to display no more than 100 objects per page sorted by creation date."""

ordering = "-created_on"
page_size = 100
max_page_size = 100
page_size_query_param = "page_size"


class CourseRunViewSet(mixins.RetrieveModelMixin, viewsets.GenericViewSet):
Expand Down
51 changes: 51 additions & 0 deletions src/backend/joanie/tests/core/test_api_enrollment.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,57 @@ def test_api_enrollment_read_list_authenticated(self):
},
)

def test_api_enrollment_read_list_pagination(self):
"""Pagination should work as expected."""
user = factories.UserFactory()
enrollments = [
factories.EnrollmentFactory(
user=user, course_run=self.create_opened_course_run(is_listed=True)
)
for _ in range(3)
]
enrollment_ids = [str(enrollment.id) for enrollment in enrollments]

# The user can see his/her enrollment
token = self.get_user_token(user.username)

response = self.client.get(
"/api/v1.0/enrollments/?page_size=2",
HTTP_AUTHORIZATION=f"Bearer {token}",
)

self.assertEqual(response.status_code, 200)
content = response.json()
self.assertEqual(content["count"], 3)
self.assertEqual(
content["next"],
"http://testserver/api/v1.0/enrollments/?page=2&page_size=2",
)
self.assertIsNone(content["previous"])

self.assertEqual(len(content["results"]), 2)
for item in content["results"]:
enrollment_ids.remove(item["id"])

# Get page 2
response = self.client.get(
"/api/v1.0/enrollments/?page_size=2&page=2",
HTTP_AUTHORIZATION=f"Bearer {token}",
)

self.assertEqual(response.status_code, 200)
content = response.json()

self.assertEqual(content["count"], 3)
self.assertIsNone(content["next"])
self.assertEqual(
content["previous"], "http://testserver/api/v1.0/enrollments/?page_size=2"
)

self.assertEqual(len(content["results"]), 1)
enrollment_ids.remove(content["results"][0]["id"])
self.assertEqual(enrollment_ids, [])

def test_api_enrollment_read_list_filtered_by_course_run_id(self):
"""
Authenticated users retrieving the list of enrollments should be able to filter
Expand Down
44 changes: 44 additions & 0 deletions src/backend/joanie/tests/core/test_api_order.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,50 @@ def test_api_order_read_list_authenticated(self):
},
)

def test_api_order_read_list_pagination(self):
"""Pagination should work as expected."""
user = factories.UserFactory()
orders = factories.OrderFactory.create_batch(3, owner=user)
order_ids = [str(order.id) for order in orders]

# The owner can see his/her order
token = self.get_user_token(user.username)

response = self.client.get(
"/api/v1.0/orders/?page_size=2",
HTTP_AUTHORIZATION=f"Bearer {token}",
)

self.assertEqual(response.status_code, 200)
content = response.json()
self.assertEqual(content["count"], 3)
self.assertEqual(
content["next"], "http://testserver/api/v1.0/orders/?page=2&page_size=2"
)
self.assertIsNone(content["previous"])

self.assertEqual(len(content["results"]), 2)
for item in content["results"]:
order_ids.remove(item["id"])

# Get page 2
response = self.client.get(
"/api/v1.0/orders/?page_size=2&page=2", HTTP_AUTHORIZATION=f"Bearer {token}"
)

self.assertEqual(response.status_code, 200)
content = response.json()

self.assertEqual(content["count"], 3)
self.assertIsNone(content["next"])
self.assertEqual(
content["previous"], "http://testserver/api/v1.0/orders/?page_size=2"
)

self.assertEqual(len(content["results"]), 1)
order_ids.remove(content["results"][0]["id"])
self.assertEqual(order_ids, [])

def test_api_order_read_list_filtered_by_product_id(self):
"""Authenticated user should be able to filter their orders by product id."""
[product_1, product_2] = factories.ProductFactory.create_batch(2)
Expand Down

0 comments on commit 4d3a04a

Please sign in to comment.