Merge pull request #7756 from edx/will/ecom-1408-take-two
Expose course start/end date in the enrollment API
This commit is contained in:
@@ -36,7 +36,10 @@ def get_enrollments(user_id):
|
||||
"user": "Bob",
|
||||
"course": {
|
||||
"course_id": "edX/DemoX/2014T2",
|
||||
"enrollment_end": 2014-12-20T20:18:00Z,
|
||||
"enrollment_end": "2014-12-20T20:18:00Z",
|
||||
"enrollment_start": "2014-10-15T20:18:00Z",
|
||||
"course_start": "2015-02-03T00:00:00Z",
|
||||
"course_end": "2015-05-06T00:00:00Z",
|
||||
"course_modes": [
|
||||
{
|
||||
"slug": "honor",
|
||||
@@ -49,7 +52,6 @@ def get_enrollments(user_id):
|
||||
"sku": null
|
||||
}
|
||||
],
|
||||
"enrollment_start": 2014-10-15T20:18:00Z,
|
||||
"invite_only": False
|
||||
}
|
||||
},
|
||||
@@ -60,7 +62,10 @@ def get_enrollments(user_id):
|
||||
"user": "Bob",
|
||||
"course": {
|
||||
"course_id": "edX/edX-Insider/2014T2",
|
||||
"enrollment_end": 2014-12-20T20:18:00Z,
|
||||
"enrollment_end": "2014-12-20T20:18:00Z",
|
||||
"enrollment_start": "2014-10-15T20:18:00Z",
|
||||
"course_start": "2015-02-03T00:00:00Z",
|
||||
"course_end": "2015-05-06T00:00:00Z",
|
||||
"course_modes": [
|
||||
{
|
||||
"slug": "honor",
|
||||
@@ -73,7 +78,6 @@ def get_enrollments(user_id):
|
||||
"sku": null
|
||||
}
|
||||
],
|
||||
"enrollment_start": 2014-10-15T20:18:00Z,
|
||||
"invite_only": True
|
||||
}
|
||||
}
|
||||
@@ -104,7 +108,10 @@ def get_enrollment(user_id, course_id):
|
||||
"user": "Bob",
|
||||
"course": {
|
||||
"course_id": "edX/DemoX/2014T2",
|
||||
"enrollment_end": 2014-12-20T20:18:00Z,
|
||||
"enrollment_end": "2014-12-20T20:18:00Z",
|
||||
"enrollment_start": "2014-10-15T20:18:00Z",
|
||||
"course_start": "2015-02-03T00:00:00Z",
|
||||
"course_end": "2015-05-06T00:00:00Z",
|
||||
"course_modes": [
|
||||
{
|
||||
"slug": "honor",
|
||||
@@ -117,7 +124,6 @@ def get_enrollment(user_id, course_id):
|
||||
"sku": null
|
||||
}
|
||||
],
|
||||
"enrollment_start": 2014-10-15T20:18:00Z,
|
||||
"invite_only": False
|
||||
}
|
||||
}
|
||||
@@ -151,7 +157,10 @@ def add_enrollment(user_id, course_id, mode='honor', is_active=True):
|
||||
"user": "Bob",
|
||||
"course": {
|
||||
"course_id": "edX/DemoX/2014T2",
|
||||
"enrollment_end": 2014-12-20T20:18:00Z,
|
||||
"enrollment_end": "2014-12-20T20:18:00Z",
|
||||
"enrollment_start": "2014-10-15T20:18:00Z",
|
||||
"course_start": "2015-02-03T00:00:00Z",
|
||||
"course_end": "2015-05-06T00:00:00Z",
|
||||
"course_modes": [
|
||||
{
|
||||
"slug": "honor",
|
||||
@@ -164,7 +173,6 @@ def add_enrollment(user_id, course_id, mode='honor', is_active=True):
|
||||
"sku": null
|
||||
}
|
||||
],
|
||||
"enrollment_start": 2014-10-15T20:18:00Z,
|
||||
"invite_only": False
|
||||
}
|
||||
}
|
||||
@@ -196,7 +204,10 @@ def update_enrollment(user_id, course_id, mode=None, is_active=None):
|
||||
"user": "Bob",
|
||||
"course": {
|
||||
"course_id": "edX/DemoX/2014T2",
|
||||
"enrollment_end": 2014-12-20T20:18:00Z,
|
||||
"enrollment_end": "2014-12-20T20:18:00Z",
|
||||
"enrollment_start": "2014-10-15T20:18:00Z",
|
||||
"course_start": "2015-02-03T00:00:00Z",
|
||||
"course_end": "2015-05-06T00:00:00Z",
|
||||
"course_modes": [
|
||||
{
|
||||
"slug": "honor",
|
||||
@@ -209,7 +220,6 @@ def update_enrollment(user_id, course_id, mode=None, is_active=None):
|
||||
"sku": null
|
||||
}
|
||||
],
|
||||
"enrollment_start": 2014-10-15T20:18:00Z,
|
||||
"invite_only": False
|
||||
}
|
||||
}
|
||||
@@ -239,7 +249,10 @@ def get_course_enrollment_details(course_id):
|
||||
>>> get_course_enrollment_details("edX/DemoX/2014T2")
|
||||
{
|
||||
"course_id": "edX/DemoX/2014T2",
|
||||
"enrollment_end": 2014-12-20T20:18:00Z,
|
||||
"enrollment_end": "2014-12-20T20:18:00Z",
|
||||
"enrollment_start": "2014-10-15T20:18:00Z",
|
||||
"course_start": "2015-02-03T00:00:00Z",
|
||||
"course_end": "2015-05-06T00:00:00Z",
|
||||
"course_modes": [
|
||||
{
|
||||
"slug": "honor",
|
||||
@@ -252,7 +265,6 @@ def get_course_enrollment_details(course_id):
|
||||
"sku": null
|
||||
}
|
||||
],
|
||||
"enrollment_start": 2014-10-15T20:18:00Z,
|
||||
"invite_only": False
|
||||
}
|
||||
|
||||
|
||||
@@ -46,6 +46,8 @@ class CourseField(serializers.RelatedField):
|
||||
"course_id": course_id,
|
||||
"enrollment_start": course.enrollment_start,
|
||||
"enrollment_end": course.enrollment_end,
|
||||
"course_start": course.start,
|
||||
"course_end": course.end,
|
||||
"invite_only": course.invitation_only,
|
||||
"course_modes": course_modes,
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ Tests for user enrollment.
|
||||
"""
|
||||
import json
|
||||
import unittest
|
||||
import datetime
|
||||
|
||||
import ddt
|
||||
from django.core.cache import cache
|
||||
@@ -305,6 +306,46 @@ class EnrollmentTest(EnrollmentTestMixin, ModuleStoreTestCase, APITestCase):
|
||||
self.assertEqual(mode['sku'], '123')
|
||||
self.assertEqual(mode['name'], CourseMode.HONOR)
|
||||
|
||||
@ddt.data(
|
||||
# NOTE: Studio requires a start date, but this is not
|
||||
# enforced at the data layer, so we need to handle the case
|
||||
# in which no dates are specified.
|
||||
(None, None, None, None),
|
||||
(datetime.datetime(2015, 1, 2, 3, 4, 5), None, "2015-01-02T03:04:05Z", None),
|
||||
(None, datetime.datetime(2015, 1, 2, 3, 4, 5), None, "2015-01-02T03:04:05Z"),
|
||||
(datetime.datetime(2014, 6, 7, 8, 9, 10), datetime.datetime(2015, 1, 2, 3, 4, 5), "2014-06-07T08:09:10Z", "2015-01-02T03:04:05Z"),
|
||||
)
|
||||
@ddt.unpack
|
||||
def test_get_course_details_course_dates(self, start_datetime, end_datetime, expected_start, expected_end):
|
||||
course = CourseFactory.create(start=start_datetime, end=end_datetime)
|
||||
self.assert_enrollment_status(course_id=unicode(course.id))
|
||||
|
||||
# Check course details
|
||||
url = reverse('courseenrollmentdetails', kwargs={"course_id": unicode(course.id)})
|
||||
resp = self.client.get(url)
|
||||
self.assertEqual(resp.status_code, status.HTTP_200_OK)
|
||||
|
||||
data = json.loads(resp.content)
|
||||
self.assertEqual(data['course_start'], expected_start)
|
||||
self.assertEqual(data['course_end'], expected_end)
|
||||
|
||||
# Check enrollment course details
|
||||
url = reverse('courseenrollment', kwargs={"course_id": unicode(course.id)})
|
||||
resp = self.client.get(url)
|
||||
self.assertEqual(resp.status_code, status.HTTP_200_OK)
|
||||
|
||||
data = json.loads(resp.content)
|
||||
self.assertEqual(data['course_details']['course_start'], expected_start)
|
||||
self.assertEqual(data['course_details']['course_end'], expected_end)
|
||||
|
||||
# Check enrollment list course details
|
||||
resp = self.client.get(reverse('courseenrollments'))
|
||||
self.assertEqual(resp.status_code, status.HTTP_200_OK)
|
||||
|
||||
data = json.loads(resp.content)
|
||||
self.assertEqual(data[0]['course_details']['course_start'], expected_start)
|
||||
self.assertEqual(data[0]['course_details']['course_end'], expected_end)
|
||||
|
||||
def test_with_invalid_course_id(self):
|
||||
self.assert_enrollment_status(course_id='entirely/fake/course', expected_status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
|
||||
@@ -86,7 +86,13 @@ class EnrollmentView(APIView, ApiKeyPermissionMixIn):
|
||||
|
||||
* course_id: The unique identifier for the course.
|
||||
|
||||
* enrollment_end: The date and time after which users cannot enroll for the course.
|
||||
* enrollment_start: The date and time that users can begin enrolling in the course. If null, enrollment opens immediately when the course is created.
|
||||
|
||||
* enrollment_end: The date and time after which users cannot enroll for the course. If null, the enrollment period never ends.
|
||||
|
||||
* course_start: The date and time at which the course opens. If null, the course opens immediately when created.
|
||||
|
||||
* course_end: The date and time at which the course closes. If null, the course never ends.
|
||||
|
||||
* course_modes: An array of data about the enrollment modes supported for the course. Each enrollment mode collection includes:
|
||||
|
||||
@@ -98,8 +104,6 @@ class EnrollmentView(APIView, ApiKeyPermissionMixIn):
|
||||
* expiration_datetime: The date and time after which users cannot enroll in the course in this mode.
|
||||
* description: A description of this mode.
|
||||
|
||||
* enrollment_start: The date and time that users can begin enrolling in the course.
|
||||
|
||||
* invite_only: Whether students must be invited to enroll in the course; true or false.
|
||||
|
||||
* user: The ID of the user.
|
||||
@@ -170,7 +174,13 @@ class EnrollmentCourseDetailView(APIView):
|
||||
|
||||
* course_id: The unique identifier of the course.
|
||||
|
||||
* enrollment_end: The date and time after which users cannot enroll for the course.
|
||||
* enrollment_start: The date and time that users can begin enrolling in the course. If null, enrollment opens immediately when the course is created.
|
||||
|
||||
* enrollment_end: The date and time after which users cannot enroll for the course. If null, the enrollment period never ends.
|
||||
|
||||
* course_start: The date and time at which the course opens. If null, the course opens immediately when created.
|
||||
|
||||
* course_end: The date and time at which the course closes. If null, the course never ends.
|
||||
|
||||
* course_modes: An array of data about the enrollment modes supported for the course. Each enrollment mode collection includes:
|
||||
|
||||
@@ -182,8 +192,6 @@ class EnrollmentCourseDetailView(APIView):
|
||||
* expiration_datetime: The date and time after which users cannot enroll in the course in this mode.
|
||||
* description: A description of this mode.
|
||||
|
||||
* enrollment_start: The date and time that users can begin enrolling in the course.
|
||||
|
||||
* invite_only: Whether students must be invited to enroll in the course; true or false.
|
||||
"""
|
||||
|
||||
@@ -270,7 +278,13 @@ class EnrollmentListView(APIView, ApiKeyPermissionMixIn):
|
||||
|
||||
* course_id: The unique identifier for the course.
|
||||
|
||||
* enrollment_end: The date and time after which users cannot enroll for the course.
|
||||
* enrollment_start: The date and time that users can begin enrolling in the course. If null, enrollment opens immediately when the course is created.
|
||||
|
||||
* enrollment_end: The date and time after which users cannot enroll for the course. If null, the enrollment period never ends.
|
||||
|
||||
* course_start: The date and time at which the course opens. If null, the course opens immediately when created.
|
||||
|
||||
* course_end: The date and time at which the course closes. If null, the course never ends.
|
||||
|
||||
* course_modes: An array of data about the enrollment modes supported for the course. Each enrollment mode collection includes:
|
||||
|
||||
@@ -282,7 +296,6 @@ class EnrollmentListView(APIView, ApiKeyPermissionMixIn):
|
||||
* expiration_datetime: The date and time after which users cannot enroll in the course in this mode.
|
||||
* description: A description of this mode.
|
||||
|
||||
* enrollment_start: The date and time that users can begin enrolling in the course.
|
||||
|
||||
* invite_only: Whether students must be invited to enroll in the course; true or false.
|
||||
|
||||
|
||||
@@ -8,6 +8,8 @@ from unittest import skip
|
||||
from nose.plugins.attrib import attr
|
||||
from selenium.webdriver.support.ui import Select
|
||||
|
||||
from flaky import flaky
|
||||
|
||||
from xmodule.partitions.partitions import Group
|
||||
from bok_choy.promise import Promise, EmptyPromise
|
||||
|
||||
@@ -1044,6 +1046,7 @@ class GroupConfigurationsTest(ContainerBase, SplitTestMixin):
|
||||
rendered_group_names = self.get_select_options(page=courseware_page, selector=".split-test-select")
|
||||
self.assertListEqual(group_names, rendered_group_names)
|
||||
|
||||
@flaky # TODO fix this, see TNL-2035
|
||||
def test_split_test_LMS_staff_view(self):
|
||||
"""
|
||||
Scenario: Ensure that split test is correctly rendered in LMS staff mode as it is
|
||||
|
||||
Reference in New Issue
Block a user