Prepare track selection page for new audit track

This commit is contained in:
Renzo Lucioni
2014-09-11 15:36:34 -04:00
parent dedd88ccf4
commit cc6e63dd22
7 changed files with 101 additions and 139 deletions

View File

@@ -32,7 +32,7 @@ class CourseModeViewTest(ModuleStoreTestCase):
self.client.login(username=self.user.username, password="edx")
@ddt.data(
# is_active?, enrollment_mode, upgrade?, redirect? auto_register?
# is_active?, enrollment_mode, upgrade?, redirect?, auto_register?
(True, 'verified', True, True, False), # User is already verified
(True, 'verified', False, True, False), # User is already verified
(True, 'honor', True, False, False), # User isn't trying to upgrade
@@ -162,9 +162,9 @@ class CourseModeViewTest(ModuleStoreTestCase):
# Mapping of course modes to the POST parameters sent
# when the user chooses that mode.
POST_PARAMS_FOR_COURSE_MODE = {
'audit': {'audit_mode': True},
'honor': {'honor-code': True},
'verified': {'certificate_mode': True, 'contribution': '1.23'}
'honor': {'honor_mode': True},
'verified': {'verified_mode': True, 'contribution': '1.23'},
'unsupported': {'unsupported_mode': True},
}
# TODO (ECOM-16): Remove the auto-register flag once the AB-test completes
@@ -172,10 +172,8 @@ class CourseModeViewTest(ModuleStoreTestCase):
@ddt.data(
(False, 'honor', 'dashboard'),
(False, 'verified', 'show_requirements'),
(False, 'audit', 'dashboard'),
(True, 'honor', 'dashboard'),
(True, 'verified', 'show_requirements'),
(True, 'audit', 'dashboard'),
)
@ddt.unpack
def test_choose_mode_redirect(self, auto_register, course_mode, expected_redirect):
@@ -191,7 +189,7 @@ class CourseModeViewTest(ModuleStoreTestCase):
# Choose the mode (POST request)
choose_track_url = reverse('course_modes_choose', args=[unicode(self.course.id)])
resp = self.client.post(choose_track_url, self.POST_PARAMS_FOR_COURSE_MODE[course_mode])
response = self.client.post(choose_track_url, self.POST_PARAMS_FOR_COURSE_MODE[course_mode])
# Verify the redirect
if expected_redirect == 'dashboard':
@@ -204,11 +202,11 @@ class CourseModeViewTest(ModuleStoreTestCase):
else:
self.fail("Must provide a valid redirect URL name")
self.assertRedirects(resp, redirect_url)
self.assertRedirects(response, redirect_url)
def test_remember_donation_for_course(self):
# Create the course modes
for mode in ('audit', 'honor', 'verified'):
for mode in ('honor', 'verified'):
CourseModeFactory(mode_slug=mode, course_id=self.course.id)
# Choose the mode (POST request)
@@ -223,29 +221,34 @@ class CourseModeViewTest(ModuleStoreTestCase):
expected_amount = decimal.Decimal(self.POST_PARAMS_FOR_COURSE_MODE['verified']['contribution'])
self.assertEqual(actual_amount, expected_amount)
def test_enrollment_skipped_if_autoreg(self):
# TODO (ECOM-16): Remove auto-register booleans once the AB-test completes
@ddt.data(False, True)
def test_successful_honor_enrollment(self, auto_register):
# TODO (ECOM-16): Remove once we complete the auto-reg AB test.
session = self.client.session
session['auto_register'] = True
session.save()
if auto_register:
self.client.session['auto_register'] = True
self.client.session.save()
# Create the course modes
for mode in ('audit', 'honor', 'verified'):
for mode in ('honor', 'verified'):
CourseModeFactory(mode_slug=mode, course_id=self.course.id)
# Now enroll in the course
CourseEnrollmentFactory(
user=self.user,
is_active=True,
mode="honor",
course_id=unicode(self.course.id),
)
# Choose the mode (POST request)
choose_track_url = reverse('course_modes_choose', args=[unicode(self.course.id)])
self.client.post(choose_track_url, self.POST_PARAMS_FOR_COURSE_MODE['audit'])
self.client.post(choose_track_url, self.POST_PARAMS_FOR_COURSE_MODE['honor'])
# Verify that enrollment mode is still honor
# Verify the enrollment
mode, is_active = CourseEnrollment.enrollment_mode_for_user(self.user, self.course.id)
self.assertEqual(mode, "honor")
self.assertEqual(mode, 'honor')
self.assertEqual(is_active, True)
def test_unsupported_enrollment_mode_failure(self):
# Create the supported course modes
for mode in ('honor', 'verified'):
CourseModeFactory(mode_slug=mode, course_id=self.course.id)
# Choose an unsupported mode (POST request)
choose_track_url = reverse('course_modes_choose', args=[unicode(self.course.id)])
response = self.client.post(choose_track_url, self.POST_PARAMS_FOR_COURSE_MODE['unsupported'])
self.assertEqual(400, response.status_code)

View File

@@ -21,18 +21,19 @@ from xmodule.modulestore.django import modulestore
class ChooseModeView(View):
"""
View used when the user is asked to pick a mode
"""View used when the user is asked to pick a mode.
When a get request is used, shows the selection page.
When a post request is used, assumes that it is a form submission
from the selection page, parses the response, and then sends user
to the next step in the flow
When a post request is used, assumes that it is a form submission
from the selection page, parses the response, and then sends user
to the next step in the flow.
"""
@method_decorator(login_required)
def get(self, request, course_id, error=None):
""" Displays the course mode choice page
"""Displays the course mode choice page.
Args:
request (`Request`): The Django Request object.
@@ -121,7 +122,19 @@ class ChooseModeView(View):
@method_decorator(login_required)
def post(self, request, course_id):
""" Takes the form submission from the page and parses it """
"""Takes the form submission from the page and parses it.
Args:
request (`Request`): The Django Request object.
course_id (unicode): The slash-separated course key.
Returns:
Status code 400 when the requested mode is unsupported. When the honor mode
is selected, redirects to the dashboard. When the verified mode is selected,
returns error messages if the indicated contribution amount is invalid or
below the minimum, otherwise redirects to the verification flow.
"""
course_key = SlashSeparatedCourseKey.from_deprecated_string(course_id)
user = request.user
@@ -134,26 +147,26 @@ class ChooseModeView(View):
upgrade = request.GET.get('upgrade', False)
requested_mode = self.get_requested_mode(request.POST)
requested_mode = self._get_requested_mode(request.POST)
allowed_modes = CourseMode.modes_for_course_dict(course_key)
if requested_mode not in allowed_modes:
return HttpResponseBadRequest(_("Enrollment mode not supported"))
if requested_mode in ("audit", "honor"):
# TODO (ECOM-16): Skip enrollment if we're in the experimental branch
if not request.session.get('auto_register', False):
CourseEnrollment.enroll(user, course_key, requested_mode)
# TODO (ECOM-16): Remove if the experimental variant wins. Functionally,
# it doesn't matter, but it will avoid hitting the database.
if requested_mode == 'honor':
CourseEnrollment.enroll(user, course_key, requested_mode)
return redirect('dashboard')
mode_info = allowed_modes[requested_mode]
if requested_mode == "verified":
if requested_mode == 'verified':
amount = request.POST.get("contribution") or \
request.POST.get("contribution-other-amt") or 0
try:
# validate the amount passed in and force it into two digits
# Validate the amount passed in and force it into two digits
amount_value = decimal.Decimal(amount).quantize(decimal.Decimal('.01'), rounding=decimal.ROUND_DOWN)
except decimal.InvalidOperation:
error_msg = _("Invalid amount selected.")
@@ -172,14 +185,20 @@ class ChooseModeView(View):
reverse('verify_student_show_requirements',
kwargs={'course_id': course_key.to_deprecated_string()}) + "?upgrade={}".format(upgrade))
def get_requested_mode(self, request_dict):
def _get_requested_mode(self, request_dict):
"""Get the user's requested mode
Args:
request_dict (`QueryDict`): A dictionary-like object containing all given HTTP POST parameters.
Returns:
The course mode slug corresponding to the choice in the POST parameters,
None if the choice in the POST parameters is missing or is an unsupported mode.
"""
Given the request object of `user_choice`, return the
corresponding course mode slug
"""
if 'audit_mode' in request_dict:
return 'audit'
if 'certificate_mode' and request_dict.get("honor-code"):
return 'honor'
if 'certificate_mode' in request_dict:
if 'verified_mode' in request_dict:
return 'verified'
if 'honor_mode' in request_dict:
return 'honor'
else:
return None