From cc6e63dd222902a4cdc7ddc6655fbbddd2b16282 Mon Sep 17 00:00:00 2001 From: Renzo Lucioni <renzo@renzolucioni.com> Date: Thu, 11 Sep 2014 15:36:34 -0400 Subject: [PATCH] Prepare track selection page for new audit track --- .../course_modes/tests/test_views.py | 53 +++++++------- common/djangoapps/course_modes/views.py | 65 +++++++++++------- common/templates/course_modes/choose.html | 60 ++++------------ .../courseware/features/certificates.feature | 7 -- .../courseware/features/certificates.py | 40 ++--------- lms/static/images/honor-ribbon.png | Bin 0 -> 5956 bytes lms/static/sass/views/_verification.scss | 15 +++- 7 files changed, 101 insertions(+), 139 deletions(-) create mode 100644 lms/static/images/honor-ribbon.png diff --git a/common/djangoapps/course_modes/tests/test_views.py b/common/djangoapps/course_modes/tests/test_views.py index 72320ebca8b..74e3b4b1b5c 100644 --- a/common/djangoapps/course_modes/tests/test_views.py +++ b/common/djangoapps/course_modes/tests/test_views.py @@ -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) diff --git a/common/djangoapps/course_modes/views.py b/common/djangoapps/course_modes/views.py index 249aff95683..79e12a452e6 100644 --- a/common/djangoapps/course_modes/views.py +++ b/common/djangoapps/course_modes/views.py @@ -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): - """ - Given the request object of `user_choice`, return the - corresponding course mode slug + 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. + """ - 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 diff --git a/common/templates/course_modes/choose.html b/common/templates/course_modes/choose.html index 0d4c4993f6d..1d28a4d9724 100644 --- a/common/templates/course_modes/choose.html +++ b/common/templates/course_modes/choose.html @@ -120,50 +120,14 @@ $(document).ready(function() { %endif <%include file="_contribution.html" args="suggested_prices=suggested_prices, currency=currency, chosen_price=chosen_price, min_price=min_price"/> - - <div class="help-tip is-expandable"> - <h5 class="title title-expand" tabindex="0" aria-expanded="false" role="link"> - <i class="icon-caret-down expandable-icon"></i> - ${_("Why do I have to pay? What if I want a free honor code certificate?")} - </h5> - - <div class="copy expandable-area"> - <dl class="list-faq"> - <dt class="faq-question">${_("Why do I have to pay?")}</dt> - <dd class="faq-answer"> - <p>${_("As a not-for-profit, edX uses your contribution to support our mission to provide quality education to everyone around the world, and to improve learning through research. While we have established a minimum fee, we ask that you contribute as much as you can.")}</p> - </dd> - - <dt class="faq-question">${_("I'd like to pay more than the minimum. Is my contribution tax deductible?")}</dt> - <dd class="faq-answer"> - <p>${_("Please check with your tax advisor to determine whether your contribution is tax deductible.")}</p> - </dd> - - % if "honor" in modes: - <dt class="faq-question">${_("What if I can't afford it or don't have the necessary equipment?")}</dt> - <dd class="faq-answer"> - <p>${_("If you can't afford the minimum fee or don't meet the requirements, you can audit the course or elect to pursue an honor code certificate at no cost.")} - ${_("If you would like to pursue the honor code certificate, please check the honor code certificate box and then click the 'Select Certificate' button to complete your registration.")}</p> - - <ul class="list-fields"> - <li class="field field-honor-code checkbox"> - <input type="checkbox" name="honor-code" id="honor-code"> - <label for="honor-code">${_("Select Honor Code Certificate")}</label> - </li> - </ul> - </dd> - % endif - </dl> - </div> - </div> </div> <ul class="list-actions"> <li class="action action-select"> %if upgrade: - <input type="submit" name="certificate_mode" value="${_('Upgrade Your Registration')}" /> + <input type="submit" name="verified_mode" value="${_('Upgrade Your Registration')}" /> %else: - <input type="submit" name="certificate_mode" value="${_('Select Certificate')}" /> + <input type="submit" name="verified_mode" value="${_('Select Certificate')}" /> %endif </li> @@ -192,21 +156,22 @@ $(document).ready(function() { %if not upgrade: - % if "audit" in modes: + % if "honor" in modes: <span class="deco-divider"> <span class="copy">${_("or")}</span> </span> <div class="register-choice register-choice-audit"> <div class="wrapper-copy"> + <span class="deco-ribbon"></span> <h4 class="title">${_("Audit This Course")}</h4> <div class="copy"> - <p>${_("Sign up to audit this course for free and track your own progress.")}</p> + <p>${_("Audit this course for free and have complete access to all the course material, activities, tests, and forums. If your work is satisfactory and you abide by the Honor Code, you'll receive a personalized Honor Code Certificate to showcase your achievement.")}</p> </div> </div> <ul class="list-actions"> <li class="action action-select"> - <input type="submit" name="audit_mode" value="${_('Select Audit')}" /> + <input type="submit" name="honor_mode" value="${_('Select Audit')}" /> </li> </ul> </div> @@ -263,9 +228,9 @@ $(document).ready(function() { <ul class="list-actions"> <li class="action action-select"> %if upgrade: - <input type="submit" name="certificate_mode" value="${_('Upgrade Your Registration')}" /> + <input type="submit" name="verified_mode" value="${_('Upgrade Your Registration')}" /> %else: - <input type="submit" name="certificate_mode" value="${_('Pursue a Verified Certificate')}" /> + <input type="submit" name="verified_mode" value="${_('Pursue a Verified Certificate')}" /> %endif </li> @@ -275,23 +240,22 @@ $(document).ready(function() { % endif %if not upgrade: -## TODO (ECOM-16): For the duration of the experiment, audit track enrollment is skipped -## to keep the user on the honor track - % if "audit" in modes: + % if "honor" in modes: <span class="deco-divider"> <span class="copy">${_("or")}</span> </span> <div class="register-choice register-choice-audit"> <div class="wrapper-copy"> + <span class="deco-ribbon"></span> <h4 class="title">${_("Audit This Course")}</h4> <div class="copy"> - <p>${_("You can audit this course and still have complete access to the course material. If you complete and pass the course you will automatically earn an Honor Code Certificate free of charge.")}</p> + <p>${_("Audit this course for free and have complete access to all the course material, activities, tests, and forums. If your work is satisfactory and you abide by the Honor Code, you'll receive a personalized Honor Code Certificate to showcase your achievement.")}</p> </div> </div> <ul class="list-actions"> <li class="action action-select"> - <input type="submit" name="audit_mode" value="${_('Pursue an Honor Code Certificate')}" /> + <input type="submit" name="honor_mode" value="${_('Pursue an Honor Code Certificate')}" /> </li> </ul> </div> diff --git a/lms/djangoapps/courseware/features/certificates.feature b/lms/djangoapps/courseware/features/certificates.feature index ffcb77f5482..369905c1a63 100644 --- a/lms/djangoapps/courseware/features/certificates.feature +++ b/lms/djangoapps/courseware/features/certificates.feature @@ -68,13 +68,6 @@ Feature: LMS.Verified certificates # And I press the payment button # Then I am at the payment page - Scenario: I can take a verified certificate course for free - Given I am logged in - And the course has an honor mode - When I select the honor code option - Then I should see the course on my dashboard - And a "edx.course.enrollment.activated" server event is emitted - Scenario: The upsell offer is on the dashboard if I am auditing Given I am logged in When I select the audit track diff --git a/lms/djangoapps/courseware/features/certificates.py b/lms/djangoapps/courseware/features/certificates.py index 089cf4cf730..fe995c9a3a0 100644 --- a/lms/djangoapps/courseware/features/certificates.py +++ b/lms/djangoapps/courseware/features/certificates.py @@ -20,13 +20,12 @@ def create_cert_course(): world.scenario_dict['COURSE'] = world.CourseFactory.create( org=org, number=number, display_name=name) - audit_mode = world.CourseModeFactory.create( - course_id=course_id, - mode_slug='audit', - mode_display_name='audit course', + honor_mode = world.CourseModeFactory.create( + course_id=world.scenario_dict['course_id'], + mode_slug='honor', + mode_display_name='honor mode', min_price=0, - ) - assert isinstance(audit_mode, CourseMode) + ) verfied_mode = world.CourseModeFactory.create( course_id=course_id, @@ -36,7 +35,6 @@ def create_cert_course(): suggested_prices='32,64,128', currency='usd', ) - assert isinstance(verfied_mode, CourseMode) def register(): @@ -48,23 +46,11 @@ def register(): assert world.is_css_present('section.wrapper h3.title') -@step(u'the course has an honor mode') -def the_course_has_an_honor_mode(step): - create_cert_course() - honor_mode = world.CourseModeFactory.create( - course_id=world.scenario_dict['course_id'], - mode_slug='honor', - mode_display_name='honor mode', - min_price=0, - ) - assert isinstance(honor_mode, CourseMode) - - @step(u'I select the audit track$') def select_the_audit_track(step): create_cert_course() register() - btn_css = 'input[value="Select Audit"]' + btn_css = 'input[name="honor_mode"]' world.wait(1) # TODO remove this after troubleshooting JZ world.css_find(btn_css) world.css_click(btn_css) @@ -293,17 +279,3 @@ def see_the_payment_page(step): def edit_my_name(step): btn_css = 'a.retake-photos' world.css_click(btn_css) - - -@step(u'I select the honor code option$') -def give_a_reason_why_i_cannot_pay(step): - register() - - link_css = 'h5 i.expandable-icon' - world.css_click(link_css) - - cb_css = 'input#honor-code' - world.css_click(cb_css) - - btn_css = 'input[value="Select Certificate"]' - world.css_click(btn_css) diff --git a/lms/static/images/honor-ribbon.png b/lms/static/images/honor-ribbon.png new file mode 100644 index 0000000000000000000000000000000000000000..a2fc5ab871358e7130570fa168e2af8b7aba9367 GIT binary patch literal 5956 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 literal 0 HcmV?d00001 diff --git a/lms/static/sass/views/_verification.scss b/lms/static/sass/views/_verification.scss index 8de9b48bc94..6fa3b7bc50e 100644 --- a/lms/static/sass/views/_verification.scss +++ b/lms/static/sass/views/_verification.scss @@ -1250,12 +1250,24 @@ .register-choice-audit { border-color: $m-blue-d1; + .deco-ribbon { + position: relative; + top: -($baseline*2.5); + right: -($baseline*0.35); + float: right; + display: block; + width: ($baseline*2.9); + height: ($baseline*4.2); + background: transparent url('../images/honor-ribbon.png') no-repeat 0 0; + } + .wrapper-copy { width: flex-grid(8,8); } .list-actions { width: flex-grid(8,8); + margin: ($baseline/3) 0; } .action-select input { @@ -1278,8 +1290,7 @@ } .list-actions { - margin: ($baseline/2) 0; - border-top: ($baseline/10) solid $m-gray-t1; + margin: ($baseline/3) 0; } .action-intro, .action-select { -- GitLab