refactor: Replace PDF course certificate view code (#30397)

Co-authored-by: ruzniaievdm <ruzniaievdm@gmail.com>
This commit is contained in:
ruzniaievdm
2022-06-13 16:43:02 +03:00
committed by GitHub
parent b9131ac1af
commit 116431cb81
8 changed files with 31 additions and 236 deletions

View File

@@ -15,7 +15,6 @@ from xmodule.modulestore.tests.django_utils import TEST_DATA_MONGO_AMNESTY_MODUL
from xmodule.modulestore.tests.factories import CourseFactory
from xmodule.data import CertificatesDisplayBehaviors
from common.djangoapps.course_modes.models import CourseMode
from common.djangoapps.student.tests.factories import CourseEnrollmentFactory, UserFactory
from lms.djangoapps.certificates.api import get_certificate_url
from lms.djangoapps.certificates.data import CertificateStatuses
@@ -36,7 +35,6 @@ class CertificateDisplayTestBase(SharedModuleStoreTestCase):
MODULESTORE = TEST_DATA_MONGO_AMNESTY_MODULESTORE
USERNAME = "test_user"
PASSWORD = "password"
DOWNLOAD_URL = "http://www.example.com/certificate.pdf"
@classmethod
def setUpClass(cls):
@@ -63,7 +61,7 @@ class CertificateDisplayTestBase(SharedModuleStoreTestCase):
else:
self.assertNotContains(response, 'Add Certificate to LinkedIn Profile')
def _create_certificate(self, enrollment_mode, download_url=DOWNLOAD_URL):
def _create_certificate(self, enrollment_mode):
"""Simulate that the user has a generated certificate. """
CourseEnrollmentFactory.create(
user=self.user,
@@ -73,38 +71,10 @@ class CertificateDisplayTestBase(SharedModuleStoreTestCase):
user=self.user,
course_id=self.course.id,
mode=enrollment_mode,
download_url=download_url,
status=CertificateStatuses.downloadable,
grade=0.98,
)
def _check_can_download_certificate(self):
"""
Inspect the dashboard to see if a certificate can be downloaded.
"""
response = self.client.get(reverse('dashboard'))
self.assertContains(response, 'Download my')
self.assertContains(response, self.DOWNLOAD_URL)
def _check_can_download_certificate_no_id(self):
"""
Inspects the dashboard to see if a certificate for a non verified course enrollment
is present
"""
response = self.client.get(reverse('dashboard'))
self.assertContains(response, 'Download')
self.assertContains(response, self.DOWNLOAD_URL)
def _check_can_not_download_certificate(self):
"""
Make sure response does not have any of the download certificate buttons
"""
response = self.client.get(reverse('dashboard'))
self.assertNotContains(response, 'View Test_Certificate')
self.assertNotContains(response, 'Download my Test_Certificate')
self.assertNotContains(response, 'Download my Test_Certificate')
self.assertNotContains(response, self.DOWNLOAD_URL)
@ddt.ddt
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms')
@@ -131,7 +101,6 @@ class CertificateDashboardMessageDisplayTest(CertificateDisplayTestBase):
if is_past:
self.assertNotContains(response, test_message)
self.assertNotContains(response, "View Test_Certificate")
self._check_can_download_certificate()
else:
self.assertContains(response, test_message)
@@ -175,27 +144,6 @@ class CertificateDisplayTest(CertificateDisplayTestBase):
Tests of certificate display.
"""
@ddt.data('verified', 'professional')
@patch.dict('django.conf.settings.FEATURES', {'CERTIFICATES_HTML_VIEW': False})
def test_display_verified_certificate(self, enrollment_mode):
self._create_certificate(enrollment_mode)
self._check_can_download_certificate()
@patch.dict('django.conf.settings.FEATURES', {'CERTIFICATES_HTML_VIEW': False})
def test_no_certificate_status_no_problem(self):
with patch('common.djangoapps.student.views.dashboard.cert_info', return_value={}):
self._create_certificate('honor')
self._check_can_not_download_certificate()
@patch.dict('django.conf.settings.FEATURES', {'CERTIFICATES_HTML_VIEW': False})
def test_display_verified_certificate_no_id(self):
"""
Confirm that if we get a certificate with a no-id-professional mode
we still can download our certificate
"""
self._create_certificate(CourseMode.NO_ID_PROFESSIONAL_MODE)
self._check_can_download_certificate_no_id()
@ddt.data('verified', 'honor', 'professional')
def test_unverified_certificate_message(self, enrollment_mode):
cert = self._create_certificate(enrollment_mode)
@@ -225,34 +173,6 @@ class CertificateDisplayTest(CertificateDisplayTestBase):
self._check_linkedin_visibility(True)
@ddt.ddt
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms')
class CertificateDisplayTestHtmlView(CertificateDisplayTestBase):
"""
Tests of webview certificate display
"""
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.course.cert_html_view_enabled = True
cls.course.save()
cls.store.update_item(cls.course, cls.USERNAME)
@ddt.data('verified', 'honor')
@override_settings(CERT_NAME_SHORT='Test_Certificate')
@patch.dict('django.conf.settings.FEATURES', {'CERTIFICATES_HTML_VIEW': True})
def test_display_download_certificate_button(self, enrollment_mode):
"""
Tests if CERTIFICATES_HTML_VIEW is True
and course has enabled web certificates via cert_html_view_enabled setting
and no active certificate configuration available
then any of the web view certificate Download button should not be visible.
"""
self._create_certificate(enrollment_mode, download_url='')
self._check_can_not_download_certificate()
@ddt.ddt
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms')
class CertificateDisplayTestLinkedHtmlView(CertificateDisplayTestBase):

View File

@@ -1427,7 +1427,6 @@ class ProgressPageTests(ProgressPageBaseTests):
user=self.user,
course_id=self.course.id,
status=CertificateStatuses.downloadable,
download_url="http://www.example.com/certificate.pdf",
mode='honor'
)
@@ -1478,34 +1477,6 @@ class ProgressPageTests(ProgressPageBaseTests):
self.assertContains(resp, "Your certificate is available")
self.assertContains(resp, "earned a certificate for this course.")
@patch.dict('django.conf.settings.FEATURES', {'CERTIFICATES_HTML_VIEW': False})
def test_view_certificate_link_hidden(self):
"""
If certificate web view is disabled then certificate web view button should not appear for user who certificate
is available/generated
"""
GeneratedCertificateFactory.create(
user=self.user,
course_id=self.course.id,
status=CertificateStatuses.downloadable,
download_url="http://www.example.com/certificate.pdf",
mode='honor'
)
# Enable the feature, but do not enable it for this course
CertificateGenerationConfiguration(enabled=True).save()
# Enable certificate generation for this course
certs_api.set_cert_generation_enabled(self.course.id, True)
with patch('lms.djangoapps.grades.course_grade_factory.CourseGradeFactory.read') as mock_create:
course_grade = mock_create.return_value
course_grade.passed = True
course_grade.summary = {'grade': 'Pass', 'percent': 0.75, 'section_breakdown': [], 'grade_breakdown': {}}
resp = self._get_progress_page()
self.assertContains(resp, "Download Your Certificate")
@ddt.data(
(True, 52),
(False, 52),
@@ -1585,9 +1556,7 @@ class ProgressPageTests(ProgressPageBaseTests):
Verify that for html certs if certificate is marked as invalidated than
re-generate button should not appear on progress page.
"""
generated_certificate = self.generate_certificate(
"http://www.example.com/certificate.pdf", "honor"
)
generated_certificate = self.generate_certificate("honor")
# Course certificate configurations
certificates = [
@@ -1622,9 +1591,7 @@ class ProgressPageTests(ProgressPageBaseTests):
"""
Verify that view certificate appears for an allowlisted user
"""
generated_certificate = self.generate_certificate(
"http://www.example.com/certificate.pdf", "honor"
)
generated_certificate = self.generate_certificate("honor")
# Course certificate configurations
certificates = [
@@ -1658,24 +1625,6 @@ class ProgressPageTests(ProgressPageBaseTests):
self.assertContains(resp, "View Certificate")
self.assert_invalidate_certificate(generated_certificate)
def test_page_with_invalidated_certificate_with_pdf(self):
"""
Verify that for pdf certs if certificate is marked as invalidated than
re-generate button should not appear on progress page.
"""
generated_certificate = self.generate_certificate(
"http://www.example.com/certificate.pdf", "honor"
)
with patch('lms.djangoapps.grades.course_grade_factory.CourseGradeFactory.read') as mock_create:
course_grade = mock_create.return_value
course_grade.passed = True
course_grade.summary = {'grade': 'Pass', 'percent': 0.75, 'section_breakdown': [], 'grade_breakdown': {}}
resp = self._get_progress_page()
self.assertContains(resp, 'Download Your Certificate')
self.assert_invalidate_certificate(generated_certificate)
@ddt.data(
*itertools.product(
(
@@ -1766,9 +1715,7 @@ class ProgressPageTests(ProgressPageBaseTests):
"""
Verify that invalidated cert data is returned if cert is invalidated.
"""
generated_certificate = self.generate_certificate(
"http://www.example.com/certificate.pdf", "honor"
)
generated_certificate = self.generate_certificate("honor")
CertificateInvalidationFactory.create(
generated_certificate=generated_certificate,
@@ -1786,9 +1733,7 @@ class ProgressPageTests(ProgressPageBaseTests):
Verify that downloadable cert data is returned if cert is downloadable even
when DISABLE_HONOR_CERTIFICATES feature flag is turned ON.
"""
self.generate_certificate(
"http://www.example.com/certificate.pdf", "honor"
)
self.generate_certificate("honor")
response = views.get_cert_data(
self.user, self.course, CourseMode.HONOR, MagicMock(passed=True)
)
@@ -1800,9 +1745,7 @@ class ProgressPageTests(ProgressPageBaseTests):
"""
Verify that generating cert data is returned if cert is generating.
"""
self.generate_certificate(
"http://www.example.com/certificate.pdf", "honor"
)
self.generate_certificate("honor")
with patch('lms.djangoapps.certificates.api.certificate_downloadable_status',
return_value=self.mock_certificate_downloadable_status(is_generating=True)):
response = views.get_cert_data(self.user, self.course, CourseMode.HONOR, MagicMock(passed=True))
@@ -1814,9 +1757,7 @@ class ProgressPageTests(ProgressPageBaseTests):
"""
Verify that unverified cert data is returned if cert is unverified.
"""
self.generate_certificate(
"http://www.example.com/certificate.pdf", "honor"
)
self.generate_certificate("honor")
with patch('lms.djangoapps.certificates.api.certificate_downloadable_status',
return_value=self.mock_certificate_downloadable_status(is_unverified=True)):
response = views.get_cert_data(self.user, self.course, CourseMode.HONOR, MagicMock(passed=True))
@@ -1828,9 +1769,7 @@ class ProgressPageTests(ProgressPageBaseTests):
"""
Verify that requested cert data is returned if cert is to be requested.
"""
self.generate_certificate(
"http://www.example.com/certificate.pdf", "honor"
)
self.generate_certificate("honor")
with patch('lms.djangoapps.certificates.api.certificate_downloadable_status',
return_value=self.mock_certificate_downloadable_status()):
response = views.get_cert_data(self.user, self.course, CourseMode.HONOR, MagicMock(passed=True))
@@ -1842,9 +1781,7 @@ class ProgressPageTests(ProgressPageBaseTests):
"""
Verify that earned but not available cert data is returned if cert has been earned, but isn't available.
"""
self.generate_certificate(
"http://www.example.com/certificate.pdf", "verified"
)
self.generate_certificate("verified")
with patch('lms.djangoapps.certificates.api.certificate_downloadable_status',
return_value=self.mock_certificate_downloadable_status(earned_but_not_available=True)):
response = views.get_cert_data(self.user, self.course, CourseMode.VERIFIED, MagicMock(passed=True))
@@ -1890,16 +1827,14 @@ class ProgressPageTests(ProgressPageBaseTests):
self.assertContains(resp, 'Your certificate has been invalidated')
self.assertContains(resp, 'Please contact your course team if you have any questions.')
self.assertNotContains(resp, 'View my Certificate')
self.assertNotContains(resp, 'Download my Certificate')
def generate_certificate(self, url, mode):
def generate_certificate(self, mode):
""" Dry method to generate certificate. """
generated_certificate = GeneratedCertificateFactory.create(
user=self.user,
course_id=self.course.id,
status=CertificateStatuses.downloadable,
download_url=url,
mode=mode
)
CertificateGenerationConfiguration(enabled=True).save()
@@ -1907,7 +1842,7 @@ class ProgressPageTests(ProgressPageBaseTests):
return generated_certificate
def mock_certificate_downloadable_status(
self, is_downloadable=False, is_generating=False, is_unverified=False, uuid=None, download_url=None,
self, is_downloadable=False, is_generating=False, is_unverified=False, uuid=None,
earned_but_not_available=None,
):
"""Dry method to mock certificate downloadable status response."""
@@ -1915,8 +1850,7 @@ class ProgressPageTests(ProgressPageBaseTests):
'is_downloadable': is_downloadable,
'is_generating': is_generating,
'is_unverified': is_unverified,
'download_url': uuid,
'uuid': download_url,
'uuid': uuid,
'earned_but_not_available': earned_but_not_available,
}

View File

@@ -7,7 +7,6 @@
course_key: null,
type: null,
status: null,
download_url: null,
grade: null,
created: null,
modified: null

View File

@@ -16,7 +16,6 @@ define([
grade: '0.0',
type: 'honor',
course_key: 'course-v1:edX+DemoX+Demo_Course',
download_url: null,
modified: '2015-08-06T19:47:07+00:00',
regenerate: true
},
@@ -27,7 +26,6 @@ define([
grade: '1.0',
type: 'verified',
course_key: 'edx/test/2015',
download_url: 'http://www.example.com/certificate.pdf',
modified: '2015-08-06T19:47:05+00:00',
regenerate: true
}
@@ -41,7 +39,6 @@ define([
grade: '',
type: '',
course_key: 'edx/test1/2016',
download_url: null,
modified: '',
regenerate: false
}
@@ -117,17 +114,15 @@ define([
expect(results[0][0]).toEqual(REGENERATE_SEARCH_RESULTS[0].course_key);
expect(results[0][1]).toEqual(REGENERATE_SEARCH_RESULTS[0].type);
expect(results[0][2]).toEqual(REGENERATE_SEARCH_RESULTS[0].status);
expect(results[0][3]).toContain('Not available');
expect(results[0][4]).toEqual(REGENERATE_SEARCH_RESULTS[0].grade);
expect(results[0][5]).toEqual(REGENERATE_SEARCH_RESULTS[0].modified);
expect(results[0][3]).toEqual(REGENERATE_SEARCH_RESULTS[0].grade);
expect(results[0][4]).toEqual(REGENERATE_SEARCH_RESULTS[0].modified);
// Check the second row of results
expect(results[1][0]).toEqual(REGENERATE_SEARCH_RESULTS[1].course_key);
expect(results[1][1]).toEqual(REGENERATE_SEARCH_RESULTS[1].type);
expect(results[1][2]).toEqual(REGENERATE_SEARCH_RESULTS[1].status);
expect(results[1][3]).toContain(REGENERATE_SEARCH_RESULTS[1].download_url);
expect(results[1][4]).toEqual(REGENERATE_SEARCH_RESULTS[1].grade);
expect(results[1][5]).toEqual(REGENERATE_SEARCH_RESULTS[1].modified);
expect(results[1][3]).toEqual(REGENERATE_SEARCH_RESULTS[1].grade);
expect(results[1][4]).toEqual(REGENERATE_SEARCH_RESULTS[1].modified);
searchFor('student@example.com', 'edx/test1/2016', requests, GENERATE_SEARCH_RESULTS);
@@ -138,9 +133,8 @@ define([
expect(results[0][0]).toEqual(GENERATE_SEARCH_RESULTS[0].course_key);
expect(results[0][1]).toEqual(GENERATE_SEARCH_RESULTS[0].type);
expect(results[0][2]).toEqual(GENERATE_SEARCH_RESULTS[0].status);
expect(results[0][3]).toContain('Not available');
expect(results[0][4]).toEqual(GENERATE_SEARCH_RESULTS[0].grade);
expect(results[0][5]).toEqual(GENERATE_SEARCH_RESULTS[0].modified);
expect(results[0][3]).toEqual(GENERATE_SEARCH_RESULTS[0].grade);
expect(results[0][4]).toEqual(GENERATE_SEARCH_RESULTS[0].modified);
});
it('searches for certificates and displays a message when there are no results', function() {

View File

@@ -6,7 +6,6 @@
<th><%- gettext("Course Key") %></th>
<th><%- gettext("Type") %></th>
<th><%- gettext("Status") %></th>
<th><%- gettext("Download URL") %></th>
<th><%- gettext("Grade") %></th>
<th><%- gettext("Last Updated") %></th>
<th></th>
@@ -18,14 +17,6 @@
<td><%- cert.get("course_key") %></td>
<td><%- cert.get("type") %></td>
<td><%- cert.get("status") %></td>
<td>
<% if (cert.get("download_url")) { %>
<a href="<%- cert.get("download_url") %>">Download</a>
<span class="sr"><%- gettext("Download the user's certificate") %></span>
<% } else { %>
<%- gettext("Not available") %>
<% } %>
</td>
<td><%- cert.get("grade") %></td>
<td><%- cert.get("modified") %></td>
<td>

View File

@@ -83,8 +83,6 @@ username = get_enterprise_learner_generic_name(request) or student.username
<div class="msg-actions">
%if certificate_data.cert_web_view_url:
<a class="btn" href="${certificate_data.cert_web_view_url}" rel="noopener" target="_blank">${_("View Certificate")} <span class="sr">${_("Opens in a new browser window")}</span></a>
%elif certificate_data.cert_status == CertificateStatuses.downloadable and certificate_data.download_url:
<a class="btn" href="${certificate_data.download_url}" rel="noopener" target="_blank">${_("Download Your Certificate")} <span class="sr">${_("Opens in a new browser window")}</span></a>
%elif certificate_data.cert_status == CertificateStatuses.requesting:
<button class="btn generate_certs" data-endpoint="${post_url}" id="btn_generate_cert">${_('Request Certificate')}</button>
%endif

View File

@@ -107,27 +107,6 @@ else:
${_("View my {cert_name_short}").format(cert_name_short=cert_name_short)}
</a>
</li>
% elif cert_status['status'] == CertificateStatuses.downloadable and enrollment.mode in CourseMode.NON_VERIFIED_MODES:
<li>
<a class="btn btn-primary" href="${cert_status['download_url']}"
title="${_('This link will open/download a PDF document')}">
${_("Download my {cert_name_short}").format(cert_name_short=cert_name_short,)}
</a>
</li>
% elif cert_status['status'] == CertificateStatuses.downloadable and enrollment.mode == 'verified' and cert_status['mode'] == 'honor':
<li>
<a class="btn btn-primary" href="${cert_status['download_url']}"
title="${_('This link will open/download a PDF document')}">
${_("Download my {cert_name_short}").format(cert_name_short=cert_name_short)}
</a>
</li>
% elif cert_status['status'] == CertificateStatuses.downloadable and enrollment.mode in CourseMode.VERIFIED_MODES:
<li>
<a class="btn btn-primary" href="${cert_status['download_url']}"
title="${_('This link will open/download a PDF document of your verified {cert_name_long}.').format(cert_name_long=cert_name_long)}">
${_("Download my {cert_name_short}").format(cert_name_short=cert_name_short)}
</a>
</li>
% endif
% if cert_status['show_survey_button']:

View File

@@ -15,7 +15,6 @@ from openedx.core.djangolib.markup import HTML, Text
% if course_certificates:
% for certificate in course_certificates:
<%
certificate_url = certificate['download_url']
course = certificate['course']
completion_date_message_html = Text(_('Completed {completion_date_html}')).format(
@@ -34,39 +33,20 @@ from openedx.core.djangolib.markup import HTML, Text
),
)
%>
% if certificate_url:
<a href="${certificate_url}" rel="noopener" target="_blank">
<div class="card certificate-card mode-${certificate['type']}">
<div class="card-logo">
<h4 class="sr-only">
${_('{course_mode} certificate').format(
course_mode=certificate['type'],
)}
</h4>
</div>
<div class="card-content">
<div class="card-supertitle">${course.display_org_with_default}</div>
<div class="card-title">${course.display_name_with_default}</div>
<p class="card-text">${completion_date_message_html}</p>
</div>
</div>
</a>
% else:
<div class="card certificate-card mode-${certificate['type']}">
<div class="card-logo">
<h4 class="sr-only">
${_('{course_mode} certificate').format(
course_mode=certificate['type'],
)}
</h4>
</div>
<div class="card-content">
<div class="card-supertitle">${course.display_org_with_default}</div>
<div class="card-title">${course.display_name_with_default}</div>
<p class="card-text">${completion_date_message_html}</p>
</div>
<div class="card certificate-card mode-${certificate['type']}">
<div class="card-logo">
<h4 class="sr-only">
${_('{course_mode} certificate').format(
course_mode=certificate['type'],
)}
</h4>
</div>
% endif
<div class="card-content">
<div class="card-supertitle">${course.display_org_with_default}</div>
<div class="card-title">${course.display_name_with_default}</div>
<p class="card-text">${completion_date_message_html}</p>
</div>
</div>
% endfor
% elif own_profile:
<div class="learner-message">