Commit 60fc3f57 by Bill DeRusha

Conditionally show unenroll action based on certificat status

parent f6a1a0df
......@@ -18,6 +18,11 @@ VERIFY_STATUS_APPROVED = "verify_approved"
VERIFY_STATUS_MISSED_DEADLINE = "verify_missed_deadline"
VERIFY_STATUS_NEED_TO_REVERIFY = "verify_need_to_reverify"
DISABLE_UNENROLL_CERT_STATES = [
'generating',
'ready',
]
def check_verify_status_by_course(user, course_enrollments):
"""
......
"""
Test the student dashboard view.
"""
import ddt
import unittest
from mock import patch
from pyquery import PyQuery as pq
from django.core.urlresolvers import reverse
from django.conf import settings
from student.tests.factories import UserFactory, CourseEnrollmentFactory
from student.models import CourseEnrollment
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory
@ddt.ddt
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms')
class TestStudentDashboardUnenrollments(ModuleStoreTestCase):
"""
Test to ensure that the student dashboard does not show the unenroll button for users with certificates.
"""
USERNAME = "Bob"
EMAIL = "bob@example.com"
PASSWORD = "edx"
UNENROLL_ELEMENT_ID = "#actions-item-unenroll-0"
def setUp(self):
""" Create a course and user, then log in. """
super(TestStudentDashboardUnenrollments, self).setUp()
self.course = CourseFactory.create()
self.user = UserFactory.create(username=self.USERNAME, email=self.EMAIL, password=self.PASSWORD)
CourseEnrollmentFactory(course_id=self.course.id, user=self.user)
self.cert_status = None
self.client.login(username=self.USERNAME, password=self.PASSWORD)
def mock_cert(self, _user, _course_overview, _course_mode): # pylint: disable=unused-argument
""" Return a preset certificate status. """
if self.cert_status is not None:
return {'status': self.cert_status}
else:
return {}
@ddt.data(
('notpassing', 1),
('restricted', 1),
('processing', 1),
(None, 1),
('generating', 0),
('ready', 0),
)
@ddt.unpack
def test_unenroll_available(self, cert_status, unenroll_action_count):
""" Assert that the unenroll action is shown or not based on the cert status."""
self.cert_status = cert_status
with patch('student.views.cert_info', side_effect=self.mock_cert):
response = self.client.get(reverse('dashboard'))
self.assertEqual(pq(response.content)(self.UNENROLL_ELEMENT_ID).length, unenroll_action_count)
@ddt.data(
('notpassing', 200),
('restricted', 200),
('processing', 200),
(None, 200),
('generating', 400),
('ready', 400),
)
@ddt.unpack
@patch.object(CourseEnrollment, 'unenroll')
def test_unenroll_request(self, cert_status, status_code, course_enrollment):
""" Assert that the unenroll method is called or not based on the cert status"""
self.cert_status = cert_status
with patch('student.views.cert_info', side_effect=self.mock_cert):
response = self.client.post(
reverse('change_enrollment'),
{'enrollment_action': 'unenroll', 'course_id': self.course.id}
)
self.assertEqual(response.status_code, status_code)
if status_code == 200:
course_enrollment.assert_called_with(self.user, self.course.id)
else:
course_enrollment.assert_not_called()
......@@ -106,7 +106,8 @@ import third_party_auth
from third_party_auth import pipeline, provider
from student.helpers import (
check_verify_status_by_course,
auth_pipeline_urls, get_next_url_for_login_page
auth_pipeline_urls, get_next_url_for_login_page,
DISABLE_UNENROLL_CERT_STATES,
)
from student.cookies import set_logged_in_cookies, delete_logged_in_cookies
from student.models import anonymous_id_for_user
......@@ -1014,8 +1015,14 @@ def change_enrollment(request, check_access=True):
# Otherwise, there is only one mode available (the default)
return HttpResponse()
elif action == "unenroll":
if not CourseEnrollment.is_enrolled(user, course_id):
enrollment = CourseEnrollment.get_enrollment(user, course_id)
if not enrollment:
return HttpResponseBadRequest(_("You are not enrolled in this course"))
certicifate_info = cert_info(user, enrollment.course_overview, enrollment.mode)
if certicifate_info.get('status') in DISABLE_UNENROLL_CERT_STATES:
return HttpResponseBadRequest(_("Your certificate prevents you from unenrolling from this course"))
CourseEnrollment.unenroll(user, course_id)
return HttpResponse()
else:
......
......@@ -14,7 +14,8 @@ from student.helpers import (
VERIFY_STATUS_SUBMITTED,
VERIFY_STATUS_APPROVED,
VERIFY_STATUS_MISSED_DEADLINE,
VERIFY_STATUS_NEED_TO_REVERIFY
VERIFY_STATUS_NEED_TO_REVERIFY,
DISABLE_UNENROLL_CERT_STATES,
)
%>
......@@ -171,7 +172,8 @@ from student.helpers import (
</a>
<div class="actions-dropdown" id="actions-dropdown-${dashboard_index}" aria-label="${_('Additional Actions Menu')}">
<ul class="actions-dropdown-list" id="actions-dropdown-list-${dashboard_index}" aria-label="${_('Available Actions')}" role="menu">
<li class="actions-item" id="actions-item-unenroll-${dashboard_index}">
% if cert_status.get('status') not in DISABLE_UNENROLL_CERT_STATES:
<li class="actions-item" id="actions-item-unenroll-${dashboard_index}">
% if is_paid_course and show_refund_option:
## Translators: The course name will be added to the end of this sentence.
% if not is_course_blocked:
......@@ -255,6 +257,7 @@ from student.helpers import (
% endif
% endif
</li>
% endif
<li class="actions-item" id="actions-item-email-settings-${dashboard_index}">
% if show_email_settings:
% if not is_course_blocked:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment