Commit 8a5782eb by Clinton Blackburn

Updated Studio API to expose course run pacing type

The pacing type can now be read and updated.

EDUCATOR-1464
parent 612c99ba
......@@ -85,6 +85,14 @@ class CourseRunImageField(serializers.ImageField):
return request.build_absolute_uri(value)
class CourseRunPacingTypeField(serializers.ChoiceField):
def to_representation(self, value):
return 'self_paced' if value else 'instructor_paced'
def to_internal_value(self, data):
return data == 'self_paced'
class CourseRunImageSerializer(serializers.Serializer):
# We set an empty default to prevent the parent serializer from attempting
# to save this value to the Course object.
......@@ -100,10 +108,15 @@ class CourseRunImageSerializer(serializers.Serializer):
return instance
class CourseRunSerializer(CourseRunTeamSerializerMixin, serializers.Serializer):
class CourseRunSerializerCommonFieldsMixin(serializers.Serializer):
schedule = CourseRunScheduleSerializer(source='*', required=False)
pacing_type = CourseRunPacingTypeField(source='self_paced', required=False,
choices=(('instructor_paced', False), ('self_paced', True),))
class CourseRunSerializer(CourseRunSerializerCommonFieldsMixin, CourseRunTeamSerializerMixin, serializers.Serializer):
id = serializers.CharField(read_only=True)
title = serializers.CharField(source='display_name')
schedule = CourseRunScheduleSerializer(source='*', required=False)
images = CourseRunImageSerializer(source='*', required=False)
def update(self, instance, validated_data):
......@@ -135,10 +148,10 @@ class CourseRunCreateSerializer(CourseRunSerializer):
return instance
class CourseRunRerunSerializer(CourseRunTeamSerializerMixin, serializers.Serializer):
class CourseRunRerunSerializer(CourseRunSerializerCommonFieldsMixin, CourseRunTeamSerializerMixin,
serializers.Serializer):
title = serializers.CharField(source='display_name', required=False)
run = serializers.CharField(source='id.run')
schedule = CourseRunScheduleSerializer(source='*', required=False)
def validate_run(self, value):
course_run_key = self.instance.id
......
import datetime
import ddt
import pytz
from django.test import RequestFactory
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
......@@ -12,14 +13,27 @@ from ..utils import serialize_datetime
from ...serializers.course_runs import CourseRunSerializer
@ddt.ddt
class CourseRunSerializerTests(ModuleStoreTestCase):
def test_data(self):
@ddt.data(
('instructor_paced', False),
('self_paced', True),
)
@ddt.unpack
def test_data(self, expected_pacing_type, self_paced):
start = datetime.datetime.now(pytz.UTC)
end = start + datetime.timedelta(days=30)
enrollment_start = start - datetime.timedelta(days=7)
enrollment_end = end - datetime.timedelta(days=14)
course = CourseFactory(start=start, end=end, enrollment_start=enrollment_start, enrollment_end=enrollment_end)
course = CourseFactory(
start=start,
end=end,
enrollment_start=enrollment_start,
enrollment_end=enrollment_end,
self_paced=self_paced
)
instructor = UserFactory()
CourseInstructorRole(course.id).add_users(instructor)
staff = UserFactory()
......@@ -48,6 +62,7 @@ class CourseRunSerializerTests(ModuleStoreTestCase):
],
'images': {
'card_image': request.build_absolute_uri(course_image_url(course)),
}
},
'pacing_type': expected_pacing_type,
}
assert serializer.data == expected
import datetime
import ddt
import pytz
from django.core.files.uploadedfile import SimpleUploadedFile
from django.core.urlresolvers import reverse
......@@ -20,6 +21,7 @@ from ..utils import serialize_datetime
from ...serializers.course_runs import CourseRunSerializer
@ddt.ddt
class CourseRunViewSetTests(ModuleStoreTestCase):
list_url = reverse('api:v1:course_run-list')
......@@ -139,7 +141,7 @@ class CourseRunViewSetTests(ModuleStoreTestCase):
def test_partial_update(self):
role = 'staff'
start = datetime.datetime.now(pytz.UTC).replace(microsecond=0)
course_run = CourseFactory(start=start, end=None, enrollment_start=None, enrollment_end=None)
course_run = CourseFactory(start=start, end=None, enrollment_start=None, enrollment_end=None, self_paced=False)
# The request should only update or create new team members
existing_user = UserFactory()
......@@ -159,6 +161,7 @@ class CourseRunViewSetTests(ModuleStoreTestCase):
'role': role,
},
],
'pacing_type': 'self_paced',
}
url = reverse('api:v1:course_run-detail', kwargs={'pk': str(course_run.id)})
......@@ -169,9 +172,15 @@ class CourseRunViewSetTests(ModuleStoreTestCase):
self.assert_course_access_role_count(course_run, 2)
course_run = modulestore().get_course(course_run.id)
assert course_run.self_paced is True
self.assert_course_run_schedule(course_run, start, None, None, None)
def test_create(self):
@ddt.data(
('instructor_paced', False),
('self_paced', True),
)
@ddt.unpack
def test_create(self, pacing_type, expected_self_paced_value):
start = datetime.datetime.now(pytz.UTC).replace(microsecond=0)
end = start + datetime.timedelta(days=30)
enrollment_start = start - datetime.timedelta(days=7)
......@@ -195,6 +204,7 @@ class CourseRunViewSetTests(ModuleStoreTestCase):
'role': role,
}
],
'pacing_type': pacing_type,
}
response = self.client.post(self.list_url, data, format='json')
assert response.status_code == 201
......@@ -205,6 +215,7 @@ class CourseRunViewSetTests(ModuleStoreTestCase):
assert course_run.id.org == data['org']
assert course_run.id.course == data['number']
assert course_run.id.run == data['run']
assert course_run.self_paced is expected_self_paced_value
self.assert_course_run_schedule(course_run, start, end, enrollment_start, enrollment_end)
self.assert_access_role(course_run, user, role)
self.assert_course_access_role_count(course_run, 1)
......@@ -242,7 +253,12 @@ class CourseRunViewSetTests(ModuleStoreTestCase):
# There should now be an image stored
contentstore().find(content_key)
def test_rerun(self):
@ddt.data(
('instructor_paced', False),
('self_paced', True),
)
@ddt.unpack
def test_rerun(self, pacing_type, expected_self_paced_value):
course_run = ToyCourseFactory()
start = datetime.datetime.now(pytz.UTC).replace(microsecond=0)
end = start + datetime.timedelta(days=30)
......@@ -264,6 +280,7 @@ class CourseRunViewSetTests(ModuleStoreTestCase):
'role': role,
}
],
'pacing_type': pacing_type,
}
response = self.client.post(url, data, format='json')
assert response.status_code == 201
......@@ -271,6 +288,7 @@ class CourseRunViewSetTests(ModuleStoreTestCase):
course_run_key = CourseKey.from_string(response.data['id'])
course_run = modulestore().get_course(course_run_key)
assert course_run.id.run == run
assert course_run.self_paced is expected_self_paced_value
self.assert_course_run_schedule(course_run, start, end, None, None)
self.assert_access_role(course_run, user, role)
self.assert_course_access_role_count(course_run, 1)
......
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