Commit 2d408543 by Andy Armstrong Committed by GitHub

Merge pull request #15957 from edx/andya/learner-certificate-filtering

Only show passing certificates on a learner profile
parents d342a562 d05b62a2
...@@ -513,8 +513,6 @@ def certificate_status(generated_certificate): ...@@ -513,8 +513,6 @@ def certificate_status(generated_certificate):
certificate generation yet. certificate generation yet.
generating - A request has been made to generate a certificate, generating - A request has been made to generate a certificate,
but it has not been generated yet. but it has not been generated yet.
regenerating - A request has been made to regenerate a certificate,
but it has not been generated yet.
deleting - A request has been made to delete a certificate. deleting - A request has been made to delete a certificate.
deleted - The certificate has been deleted. deleted - The certificate has been deleted.
......
...@@ -9,6 +9,8 @@ from course_modes.models import CourseMode ...@@ -9,6 +9,8 @@ from course_modes.models import CourseMode
from django.conf import settings from django.conf import settings
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.test.client import RequestFactory from django.test.client import RequestFactory
from lms.djangoapps.certificates.api import is_passing_status
from opaque_keys.edx.locator import CourseLocator
from openedx.core.djangoapps.waffle_utils.testutils import override_waffle_flag from openedx.core.djangoapps.waffle_utils.testutils import override_waffle_flag
from openedx.features.learner_profile.views.learner_profile import learner_profile_context from openedx.features.learner_profile.views.learner_profile import learner_profile_context
from student.tests.factories import CourseEnrollmentFactory, UserFactory from student.tests.factories import CourseEnrollmentFactory, UserFactory
...@@ -118,15 +120,15 @@ class LearnerProfileViewTest(UrlResetMixin, ModuleStoreTestCase): ...@@ -118,15 +120,15 @@ class LearnerProfileViewTest(UrlResetMixin, ModuleStoreTestCase):
response = self.client.get(path=profile_path) response = self.client.get(path=profile_path)
self.assertEqual(404, response.status_code) self.assertEqual(404, response.status_code)
def _create_certificate(self, enrollment_mode): def _create_certificate(self, course_key=None, enrollment_mode=CourseMode.HONOR, status='downloadable'):
"""Simulate that the user has a generated certificate. """ """Simulate that the user has a generated certificate. """
CourseEnrollmentFactory.create(user=self.user, course_id=self.course.id, mode=enrollment_mode) CourseEnrollmentFactory.create(user=self.user, course_id=self.course.id, mode=enrollment_mode)
return GeneratedCertificateFactory( return GeneratedCertificateFactory(
user=self.user, user=self.user,
course_id=self.course.id, course_id=course_key or self.course.id,
mode=enrollment_mode, mode=enrollment_mode,
download_url=self.DOWNLOAD_URL, download_url=self.DOWNLOAD_URL,
status="downloadable" status=status,
) )
@ddt.data(CourseMode.HONOR, CourseMode.PROFESSIONAL, CourseMode.VERIFIED) @ddt.data(CourseMode.HONOR, CourseMode.PROFESSIONAL, CourseMode.VERIFIED)
...@@ -136,13 +138,50 @@ class LearnerProfileViewTest(UrlResetMixin, ModuleStoreTestCase): ...@@ -136,13 +138,50 @@ class LearnerProfileViewTest(UrlResetMixin, ModuleStoreTestCase):
Verify that certificates are displayed with the correct card mode. Verify that certificates are displayed with the correct card mode.
""" """
# Add new certificate # Add new certificate
cert = self._create_certificate(cert_mode) cert = self._create_certificate(enrollment_mode=cert_mode)
cert.save() cert.save()
response = self.client.get('/u/{username}'.format(username=self.user.username)) response = self.client.get('/u/{username}'.format(username=self.user.username))
self.assertContains(response, 'card certificate-card mode-{cert_mode}'.format(cert_mode=cert_mode)) self.assertContains(response, 'card certificate-card mode-{cert_mode}'.format(cert_mode=cert_mode))
@ddt.data(
['downloadable', True],
['notpassing', False],
)
@ddt.unpack
@override_waffle_flag(SHOW_ACHIEVEMENTS_FLAG, active=True)
def test_certificate_status_visibility(self, status, is_passed_status):
"""
Verify that certificates are only displayed for passing status.
"""
# Add new certificate
cert = self._create_certificate(status=status)
cert.save()
# Ensure that this test is actually using both passing and non-passing certs.
self.assertEqual(is_passing_status(cert.status), is_passed_status)
response = self.client.get('/u/{username}'.format(username=self.user.username))
if is_passed_status:
self.assertContains(response, 'card certificate-card mode-{cert_mode}'.format(cert_mode=cert.mode))
else:
self.assertNotContains(response, 'card certificate-card mode-{cert_mode}'.format(cert_mode=cert.mode))
@override_waffle_flag(SHOW_ACHIEVEMENTS_FLAG, active=True)
def test_certificate_for_missing_course(self):
"""
Verify that a certificate is not shown for a missing course.
"""
# Add new certificate
cert = self._create_certificate(course_key=CourseLocator.from_string('course-v1:edX+INVALID+1'))
cert.save()
response = self.client.get('/u/{username}'.format(username=self.user.username))
self.assertNotContains(response, 'card certificate-card mode-{cert_mode}'.format(cert_mode=cert.mode))
@ddt.data(True, False) @ddt.data(True, False)
@override_waffle_flag(SHOW_ACHIEVEMENTS_FLAG, active=True) @override_waffle_flag(SHOW_ACHIEVEMENTS_FLAG, active=True)
def test_no_certificate_visibility(self, own_profile): def test_no_certificate_visibility(self, own_profile):
......
...@@ -2,9 +2,9 @@ ...@@ -2,9 +2,9 @@
Views to render a learner's achievements. Views to render a learner's achievements.
""" """
from courseware.courses import get_course_overview_with_access
from django.template.loader import render_to_string from django.template.loader import render_to_string
from lms.djangoapps.certificates import api as certificate_api from lms.djangoapps.certificates import api as certificate_api
from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
from openedx.core.djangoapps.plugin_api.views import EdxFragmentView from openedx.core.djangoapps.plugin_api.views import EdxFragmentView
from web_fragments.fragment import Fragment from web_fragments.fragment import Fragment
...@@ -34,9 +34,18 @@ class LearnerAchievementsFragmentView(EdxFragmentView): ...@@ -34,9 +34,18 @@ class LearnerAchievementsFragmentView(EdxFragmentView):
Returns a user's certificates sorted by course name. Returns a user's certificates sorted by course name.
""" """
course_certificates = certificate_api.get_certificates_for_user(username) course_certificates = certificate_api.get_certificates_for_user(username)
passing_certificates = []
for course_certificate in course_certificates: for course_certificate in course_certificates:
if course_certificate.get('is_passing', False):
course_key = course_certificate['course_key'] course_key = course_certificate['course_key']
course_overview = get_course_overview_with_access(request.user, 'load', course_key) try:
course_overview = CourseOverview.get_from_id(course_key)
course_certificate['course'] = course_overview course_certificate['course'] = course_overview
course_certificates.sort(key=lambda certificate: certificate['course'].display_name_with_default) passing_certificates.append(course_certificate)
return course_certificates except CourseOverview.DoesNotExist:
# This is unlikely to fail as the course should exist.
# Ideally the cert should have all the information that
# it needs. This might be solved by the Credentials API.
pass
passing_certificates.sort(key=lambda certificate: certificate['course'].display_name_with_default)
return passing_certificates
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