diff --git a/lms/djangoapps/course_api/serializers.py b/lms/djangoapps/course_api/serializers.py index 24e5d43267..f891365853 100644 --- a/lms/djangoapps/course_api/serializers.py +++ b/lms/djangoapps/course_api/serializers.py @@ -11,6 +11,7 @@ from rest_framework import serializers from lms.djangoapps.courseware.courses import get_course_about_section from openedx.core.lib.courses import course_image_url +from openedx.core.djangoapps.models.course_details import CourseDetails from xmodule.course_module import DEFAULT_START_DATE @@ -36,6 +37,10 @@ class _CourseApiMediaCollectionSerializer(serializers.Serializer): # pylint: di Nested serializer to represent a collection of media objects """ course_image = _MediaSerializer(source='*', uri_parser=course_image_url) + course_video = _MediaSerializer( + source='*', + uri_parser=lambda course: CourseDetails.fetch_video_url(course.id), + ) class CourseSerializer(serializers.Serializer): # pylint: disable=abstract-method @@ -47,14 +52,19 @@ class CourseSerializer(serializers.Serializer): # pylint: disable=abstract-meth name = serializers.CharField(source='display_name_with_default') number = serializers.CharField(source='display_number_with_default') org = serializers.CharField(source='display_org_with_default') - description = serializers.SerializerMethodField() + short_description = serializers.SerializerMethodField() + effort = serializers.SerializerMethodField() + media = _CourseApiMediaCollectionSerializer(source='*') + start = serializers.DateTimeField() start_type = serializers.SerializerMethodField() start_display = serializers.SerializerMethodField() end = serializers.DateTimeField() + enrollment_start = serializers.DateTimeField() enrollment_end = serializers.DateTimeField() + blocks_url = serializers.SerializerMethodField() def get_start_type(self, course): @@ -79,9 +89,9 @@ class CourseSerializer(serializers.Serializer): # pylint: disable=abstract-meth else: return None - def get_description(self, course): + def get_short_description(self, course): """ - Get the representation for SerializerMethodField `description` + Get the representation for SerializerMethodField `short_description` """ return get_course_about_section(self.context['request'], course, 'short_description').strip() @@ -94,3 +104,9 @@ class CourseSerializer(serializers.Serializer): # pylint: disable=abstract-meth urllib.urlencode({'course_id': course.id}), ]) return self.context['request'].build_absolute_uri(base_url) + + def get_effort(self, course): + """ + Get the representation for SerializerMethodField `effort` + """ + return CourseDetails.fetch_effort(course.id) diff --git a/lms/djangoapps/course_api/tests/test_api.py b/lms/djangoapps/course_api/tests/test_api.py index d5b0413367..bf77026518 100644 --- a/lms/djangoapps/course_api/tests/test_api.py +++ b/lms/djangoapps/course_api/tests/test_api.py @@ -19,44 +19,18 @@ class CourseApiTestMixin(CourseApiFactoryMixin): """ Establish basic functionality for Course API tests """ - - maxDiff = 5000 # long enough to show mismatched dicts - - expected_course_data = { - 'course_id': u'edX/toy/2012_Fall', - 'name': u'Toy Course', - 'number': u'toy', - 'org': u'edX', - 'description': u'A course about toys.', - 'media': { - 'course_image': { - 'uri': u'/c4x/edX/toy/asset/just_a_test.jpg', - } - }, - 'start': u'2015-07-17T12:00:00Z', - 'start_type': u'timestamp', - 'start_display': u'July 17, 2015', - 'end': u'2015-09-19T18:00:00Z', - 'enrollment_start': u'2015-06-15T00:00:00Z', - 'enrollment_end': u'2015-07-15T00:00:00Z', - 'blocks_url': '/api/courses/v1/blocks/?course_id=edX%2Ftoy%2F2012_Fall', - } - - def verify_course(self, course, course_id=None): - """ - Ensure that the returned course is the course we just created - """ - - if course_id is None: - course_id = self.expected_course_data['course_id'] - self.assertIsInstance(course, CourseDescriptor) - self.assertEqual(course_id, str(course.id)) - @classmethod def setUpClass(cls): super(CourseApiTestMixin, cls).setUpClass() cls.request_factory = APIRequestFactory() + def verify_course(self, course, course_id=u'edX/toy/2012_Fall'): + """ + Ensure that the returned course is the course we just created + """ + self.assertIsInstance(course, CourseDescriptor) + self.assertEqual(course_id, str(course.id)) + class CourseDetailTestMixin(CourseApiTestMixin): """ diff --git a/lms/djangoapps/course_api/tests/test_serializers.py b/lms/djangoapps/course_api/tests/test_serializers.py index 936dc42b8a..093e8131d9 100644 --- a/lms/djangoapps/course_api/tests/test_serializers.py +++ b/lms/djangoapps/course_api/tests/test_serializers.py @@ -4,6 +4,7 @@ Test data created by CourseSerializer from datetime import datetime +from openedx.core.djangoapps.models.course_details import CourseDetails from rest_framework.test import APIRequestFactory from rest_framework.request import Request @@ -18,6 +19,7 @@ class TestCourseSerializerFields(CourseApiFactoryMixin, ModuleStoreTestCase): """ Test variations of start_date field responses """ + maxDiff = 5000 # long enough to show mismatched dicts, in case of error def setUp(self): super(TestCourseSerializerFields, self).setUp() @@ -35,6 +37,35 @@ class TestCourseSerializerFields(CourseApiFactoryMixin, ModuleStoreTestCase): request.user = user return request + def test_basic(self): + expected_data = { + 'course_id': u'edX/toy/2012_Fall', + 'name': u'Toy Course', + 'number': u'toy', + 'org': u'edX', + 'short_description': u'A course about toys.', + 'media': { + 'course_image': { + 'uri': u'/c4x/edX/toy/asset/just_a_test.jpg', + }, + 'course_video': { + 'uri': u'http://www.youtube.com/watch?v=test_youtube_id', + } + }, + 'start': u'2015-07-17T12:00:00Z', + 'start_type': u'timestamp', + 'start_display': u'July 17, 2015', + 'end': u'2015-09-19T18:00:00', + 'enrollment_start': u'2015-06-15T00:00:00', + 'enrollment_end': u'2015-07-15T00:00:00', + 'blocks_url': u'http://testserver/api/courses/v1/blocks/?course_id=edX%2Ftoy%2F2012_Fall', + 'effort': u'6 hours', + } + course = self.create_course() + CourseDetails.update_about_video(course, 'test_youtube_id', self.staff_user.id) # pylint: disable=no-member + result = CourseSerializer(course, context={'request': self._get_request()}).data + self.assertDictEqual(result, expected_data) + def test_advertised_start(self): course = self.create_course( course=u'custom', @@ -52,16 +83,3 @@ class TestCourseSerializerFields(CourseApiFactoryMixin, ModuleStoreTestCase): self.assertEqual(result['course_id'], u'edX/custom/2012_Fall') self.assertEqual(result['start_type'], u'empty') self.assertIsNone(result['start_display']) - - def test_description(self): - course = self.create_course() - result = CourseSerializer(course, context={'request': self._get_request()}).data - self.assertEqual(result['description'], u'A course about toys.') - - def test_blocks_url(self): - course = self.create_course() - result = CourseSerializer(course, context={'request': self._get_request()}).data - self.assertEqual( - result['blocks_url'], - u'http://testserver/api/courses/v1/blocks/?course_id=edX%2Ftoy%2F2012_Fall' - )