diff --git a/common/djangoapps/enrollment/api.py b/common/djangoapps/enrollment/api.py index 1a0043eb0e..25047219f7 100644 --- a/common/djangoapps/enrollment/api.py +++ b/common/djangoapps/enrollment/api.py @@ -133,7 +133,7 @@ def get_enrollment(user_id, course_id): return _data_api().get_course_enrollment(user_id, course_id) -def add_enrollment(user_id, course_id, mode=CourseMode.DEFAULT_MODE_SLUG, is_active=True): +def add_enrollment(user_id, course_id, mode=None, is_active=True): """Enrolls a user in a course. Enrolls a user in a course. If the mode is not specified, this will default to `CourseMode.DEFAULT_MODE_SLUG`. @@ -180,6 +180,8 @@ def add_enrollment(user_id, course_id, mode=CourseMode.DEFAULT_MODE_SLUG, is_act } } """ + if mode is None: + mode = _default_course_mode(course_id) _validate_course_mode(course_id, mode, is_active=is_active) return _data_api().create_course_enrollment(user_id, course_id, mode, is_active) @@ -359,16 +361,37 @@ def get_enrollment_attributes(user_id, course_id): return _data_api().get_enrollment_attributes(user_id, course_id) +def _default_course_mode(course_id): + """Return the default enrollment for a course. + + Special case the default enrollment to return if nothing else is found. + + Arguments: + course_id (str): The course to check against for available course modes. + + Returns: + str + """ + course_enrollment_info = _data_api().get_course_enrollment_info(course_id, include_expired=False) + course_modes = course_enrollment_info["course_modes"] + available_modes = [m['slug'] for m in course_modes] + + if CourseMode.DEFAULT_MODE_SLUG in available_modes: + return CourseMode.DEFAULT_MODE_SLUG + elif 'audit' in available_modes: + return 'audit' + elif 'honor' in available_modes: + return 'honor' + + return CourseMode.DEFAULT_MODE_SLUG + + def _validate_course_mode(course_id, mode, is_active=None): """Checks to see if the specified course mode is valid for the course. If the requested course mode is not available for the course, raise an error with corresponding course enrollment information. - 'honor' is special cased. If there are no course modes configured, and the specified mode is - 'honor', return true, allowing the enrollment to be 'honor' even if the mode is not explicitly - set for the course. - Arguments: course_id (str): The course to check against for available course modes. mode (str): The slug for the course mode specified in the enrollment. diff --git a/common/djangoapps/enrollment/tests/test_api.py b/common/djangoapps/enrollment/tests/test_api.py index 4c11ea0fb0..3d41d24743 100644 --- a/common/djangoapps/enrollment/tests/test_api.py +++ b/common/djangoapps/enrollment/tests/test_api.py @@ -8,6 +8,8 @@ import unittest from django.test import TestCase from django.test.utils import override_settings from django.conf import settings + +from course_modes.models import CourseMode from enrollment import api from enrollment.errors import EnrollmentApiLoadError, EnrollmentNotFoundError, CourseModeNotFoundError from enrollment.tests import fake_data_api @@ -56,6 +58,34 @@ class EnrollmentTest(TestCase): get_result = api.get_enrollment(self.USERNAME, self.COURSE_ID) self.assertEquals(result, get_result) + @ddt.data( + ([CourseMode.DEFAULT_MODE_SLUG, 'verified', 'credit'], CourseMode.DEFAULT_MODE_SLUG), + (['audit', 'verified', 'credit'], 'audit'), + (['honor', 'verified', 'credit'], 'honor'), + ) + @ddt.unpack + def test_enroll_no_mode_success(self, course_modes, expected_mode): + # Add a fake course enrollment information to the fake data API + fake_data_api.add_course(self.COURSE_ID, course_modes=course_modes) + # Enroll in the course and verify the URL we get sent to + result = api.add_enrollment(self.USERNAME, self.COURSE_ID) + self.assertIsNotNone(result) + self.assertEquals(result['student'], self.USERNAME) + self.assertEquals(result['course']['course_id'], self.COURSE_ID) + self.assertEquals(result['mode'], expected_mode) + + @ddt.data( + ['professional'], + ['verified'], + ['verified', 'professional'], + ) + @raises(CourseModeNotFoundError) + def test_enroll_no_mode_error(self, course_modes): + # Add a fake course enrollment information to the fake data API + fake_data_api.add_course(self.COURSE_ID, course_modes=course_modes) + # Enroll in the course and verify that we raise CourseModeNotFoundError + api.add_enrollment(self.USERNAME, self.COURSE_ID) + @raises(CourseModeNotFoundError) def test_prof_ed_enroll(self): # Add a fake course enrollment information to the fake data API