Commit 7afd9918 by Dave Chamberlain

Added simple endpoint for PATCH for course_runs api to allow the…

    Added simple endpoint for PATCH for course_runs api to allow the modification of existing fields.
    Changed the way permissions are handled
    inccoporated feedback
    Fixed a bunch of unit tests to use the pytest style assertions

    ECOM-7024
parent 8329583e
......@@ -39,7 +39,7 @@ class CourseRunViewSetTests(SerializationMixin, ElasticsearchTestMixin, APITestC
""" Verify the endpoint returns the details for a single course. """
url = reverse('api:v1:course_run-detail', kwargs={'key': self.course_run.key})
with self.assertNumQueries(9):
with self.assertNumQueries(10):
response = self.client.get(url)
assert response.status_code == 200
......@@ -51,7 +51,7 @@ class CourseRunViewSetTests(SerializationMixin, ElasticsearchTestMixin, APITestC
url = reverse('api:v1:course_run-detail', kwargs={'key': self.course_run.key})
with self.assertNumQueries(12):
with self.assertNumQueries(13):
response = self.client.get(url)
assert response.status_code == 200
assert response.data.get('programs') == []
......@@ -66,7 +66,7 @@ class CourseRunViewSetTests(SerializationMixin, ElasticsearchTestMixin, APITestC
url = reverse('api:v1:course_run-detail', kwargs={'key': self.course_run.key})
url += '?include_deleted_programs=1'
with self.assertNumQueries(12):
with self.assertNumQueries(13):
response = self.client.get(url)
assert response.status_code == 200
assert response.data == \
......@@ -78,10 +78,10 @@ class CourseRunViewSetTests(SerializationMixin, ElasticsearchTestMixin, APITestC
url = reverse('api:v1:course_run-detail', kwargs={'key': self.course_run.key})
with self.assertNumQueries(12):
with self.assertNumQueries(13):
response = self.client.get(url)
assert response.status_code == 200
self.assertEqual(response.data.get('programs'), [])
assert response.data.get('programs') == []
def test_get_include_unpublished_programs(self):
"""
......@@ -93,17 +93,47 @@ class CourseRunViewSetTests(SerializationMixin, ElasticsearchTestMixin, APITestC
url = reverse('api:v1:course_run-detail', kwargs={'key': self.course_run.key})
url += '?include_unpublished_programs=1'
with self.assertNumQueries(12):
with self.assertNumQueries(13):
response = self.client.get(url)
assert response.status_code == 200
assert response.data == \
self.serialize_course_run(self.course_run, extra_context={'include_unpublished_programs': True})
def test_partial_update(self):
""" Verify the endpoint supports partially updating a course_run's fields, provided user has permission. """
url = reverse('api:v1:course_run-detail', kwargs={'key': self.course_run.key})
expected_min_effort = 867
expected_max_effort = 5309
data = {
'max_effort': expected_max_effort,
'min_effort': expected_min_effort,
}
# Update this course_run with the new info
response = self.client.patch(url, data, format='json')
assert response.status_code == 200
# refresh and make sure we have the new effort levels
self.course_run.refresh_from_db()
assert self.course_run.max_effort == expected_max_effort
assert self.course_run.min_effort == expected_min_effort
def test_partial_update_bad_permission(self):
""" Verify partially updating will fail if user doesn't have permission. """
user = UserFactory(is_staff=False, is_superuser=False)
self.client.force_authenticate(user)
url = reverse('api:v1:course_run-detail', kwargs={'key': self.course_run.key})
response = self.client.patch(url, {}, format='json')
assert response.status_code == 403
def test_list(self):
""" Verify the endpoint returns a list of all catalogs. """
url = reverse('api:v1:course_run-list')
with self.assertNumQueries(11):
with self.assertNumQueries(12):
response = self.client.get(url)
assert response.status_code == 200
......@@ -116,7 +146,7 @@ class CourseRunViewSetTests(SerializationMixin, ElasticsearchTestMixin, APITestC
""" Verify the endpoint returns a list of all catalogs sorted by course start date. """
url = '{root}?ordering=start'.format(root=reverse('api:v1:course_run-list'))
with self.assertNumQueries(11):
with self.assertNumQueries(12):
response = self.client.get(url)
assert response.status_code == 200
......@@ -132,7 +162,7 @@ class CourseRunViewSetTests(SerializationMixin, ElasticsearchTestMixin, APITestC
query = 'title:Some random title'
url = '{root}?q={query}'.format(root=reverse('api:v1:course_run-list'), query=query)
with self.assertNumQueries(37):
with self.assertNumQueries(38):
response = self.client.get(url)
actual_sorted = sorted(response.data['results'], key=lambda course_run: course_run['key'])
......@@ -248,7 +278,7 @@ class CourseRunViewSetTests(SerializationMixin, ElasticsearchTestMixin, APITestC
url = '{}?{}'.format(reverse('api:v1:course_run-contains'), qs)
response = self.client.get(url)
self.assertEqual(response.status_code, 400)
assert response.status_code == 400
def test_contains_multiple_course_runs(self):
qs = urllib.parse.urlencode({
......@@ -281,4 +311,4 @@ class CourseRunViewSetTests(SerializationMixin, ElasticsearchTestMixin, APITestC
url = '{}?{}'.format(reverse('api:v1:course_run-contains'), qs)
response = self.client.get(url)
self.assertEqual(response.status_code, 400)
assert response.status_code == 400
......@@ -2,7 +2,7 @@ from django.db.models.functions import Lower
from rest_framework import viewsets, status
from rest_framework.decorators import list_route
from rest_framework.filters import DjangoFilterBackend, OrderingFilter
from rest_framework.permissions import IsAuthenticated
from rest_framework.permissions import IsAuthenticated, DjangoModelPermissions
from rest_framework.response import Response
from course_discovery.apps.api import filters, serializers
......@@ -14,14 +14,14 @@ from course_discovery.apps.course_metadata.models import CourseRun
# pylint: disable=no-member
class CourseRunViewSet(PartnerMixin, viewsets.ReadOnlyModelViewSet):
class CourseRunViewSet(PartnerMixin, viewsets.ModelViewSet):
""" CourseRun resource. """
filter_backends = (DjangoFilterBackend, OrderingFilter)
filter_class = filters.CourseRunFilter
lookup_field = 'key'
lookup_value_regex = COURSE_RUN_ID_REGEX
ordering_fields = ('start',)
permission_classes = (IsAuthenticated,)
permission_classes = (IsAuthenticated, DjangoModelPermissions)
queryset = CourseRun.objects.all().order_by(Lower('key'))
serializer_class = serializers.CourseRunWithProgramsSerializer
......@@ -127,6 +127,10 @@ class CourseRunViewSet(PartnerMixin, viewsets.ReadOnlyModelViewSet):
"""
return super(CourseRunViewSet, self).list(request, *args, **kwargs)
def partial_update(self, request, *args, **kwargs):
""" Update one, or more, fields for a course run. """
return super(CourseRunViewSet, self).partial_update(request, *args, **kwargs)
def retrieve(self, request, *args, **kwargs):
""" Retrieve details for a course run. """
return super(CourseRunViewSet, self).retrieve(request, *args, **kwargs)
......
......@@ -9,6 +9,8 @@ INSTALLED_APPS += [
'course_discovery.apps.edx_catalog_extensions',
]
DEFAULT_PARTNER_ID = 1
TEST_NON_SERIALIZED_APPS = [
# Prevents the issue described at https://code.djangoproject.com/ticket/23727.
'django.contrib.contenttypes',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment