diff --git a/lms/djangoapps/certificates/models.py b/lms/djangoapps/certificates/models.py index 1158ae120a..ebd2b68ce5 100644 --- a/lms/djangoapps/certificates/models.py +++ b/lms/djangoapps/certificates/models.py @@ -135,7 +135,7 @@ class CertificateAllowlist(TimeStampedModel): @classmethod def get_certificate_allowlist(cls, course_id, student=None): """ - Return the certificate allowlist for the given course as dict object + Return the certificate allowlist for the given course as a list of dict objects with the following key-value pairs: [{ diff --git a/lms/djangoapps/certificates/tests/factories.py b/lms/djangoapps/certificates/tests/factories.py index 45575620c7..b793fabbd2 100644 --- a/lms/djangoapps/certificates/tests/factories.py +++ b/lms/djangoapps/certificates/tests/factories.py @@ -9,6 +9,7 @@ from factory.django import DjangoModelFactory from common.djangoapps.student.models import LinkedInAddToProfileConfiguration from lms.djangoapps.certificates.models import ( + CertificateAllowlist, CertificateHtmlViewConfiguration, CertificateInvalidation, CertificateStatuses, @@ -45,6 +46,21 @@ class CertificateAllowlistFactory(DjangoModelFactory): notes = 'Test Notes' +class TemporaryCertificateAllowlistFactory(DjangoModelFactory): + """ + Temporary certificate allowlist factory. + + This will be removed once the CertificateAllowlistFactory uses the CertificateAllowlist as its model. + """ + + class Meta: + model = CertificateAllowlist + + course_id = None + allowlist = True + notes = 'Test Notes' + + class CertificateInvalidationFactory(DjangoModelFactory): """ CertificateInvalidation factory @@ -70,18 +86,18 @@ class CertificateHtmlViewConfigurationFactory(DjangoModelFactory): "default": { "accomplishment_class_append": "accomplishment-certificate", "platform_name": "edX", - "company_about_url": "http://www.edx.org/about-us", - "company_privacy_url": "http://www.edx.org/edx-privacy-policy", - "company_tos_url": "http://www.edx.org/edx-terms-service", - "company_verified_certificate_url": "http://www.edx.org/verified-certificate", + "company_about_url": "https://www.edx.org/about-us", + "company_privacy_url": "https://www.edx.org/edx-privacy-policy", + "company_tos_url": "https://www.edx.org/edx-terms-service", + "company_verified_certificate_url": "https://www.edx.org/verified-certificate", "document_stylesheet_url_application": "/static/certificates/sass/main-ltr.css", "logo_src": "/static/certificates/images/logo-edx.png", - "logo_url": "http://www.edx.org" + "logo_url": "https://www.edx.org" }, "honor": { "certificate_type": "Honor Code", "certificate_title": "Certificate of Achievement", - "logo_url": "http://www.edx.org/honor_logo.png" + "logo_url": "https://www.edx.org/honor_logo.png" }, "verified": { "certificate_type": "Verified", diff --git a/lms/djangoapps/certificates/tests/test_models.py b/lms/djangoapps/certificates/tests/test_models.py index 8b346d2de1..4481e5ce1f 100644 --- a/lms/djangoapps/certificates/tests/test_models.py +++ b/lms/djangoapps/certificates/tests/test_models.py @@ -16,6 +16,7 @@ from path import Path as path from common.djangoapps.student.tests.factories import AdminFactory, UserFactory from lms.djangoapps.certificates.models import ( + CertificateAllowlist, CertificateGenerationHistory, CertificateHtmlViewConfiguration, CertificateInvalidation, @@ -25,7 +26,11 @@ from lms.djangoapps.certificates.models import ( ExampleCertificateSet, GeneratedCertificate ) -from lms.djangoapps.certificates.tests.factories import CertificateInvalidationFactory, GeneratedCertificateFactory +from lms.djangoapps.certificates.tests.factories import ( + CertificateInvalidationFactory, + GeneratedCertificateFactory, + TemporaryCertificateAllowlistFactory, +) from lms.djangoapps.instructor_task.tests.factories import InstructorTaskFactory from openedx.core.djangoapps.content.course_overviews.tests.factories import CourseOverviewFactory from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase @@ -47,7 +52,7 @@ class ExampleCertificateTest(TestCase): DESCRIPTION = 'test' TEMPLATE = 'test.pdf' - DOWNLOAD_URL = 'http://www.example.com' + DOWNLOAD_URL = 'https://www.example.com' ERROR_REASON = 'Kaboom!' def setUp(self): @@ -105,11 +110,11 @@ class CertificateHtmlViewConfigurationTest(TestCase): super().setUp() self.configuration_string = """{ "default": { - "url": "http://www.edx.org", - "logo_src": "http://www.edx.org/static/images/logo.png" + "url": "https://www.edx.org", + "logo_src": "https://www.edx.org/static/images/logo.png" }, "honor": { - "logo_src": "http://www.edx.org/static/images/honor-logo.png" + "logo_src": "https://www.edx.org/static/images/honor-logo.png" } }""" self.config = CertificateHtmlViewConfiguration(configuration=self.configuration_string) @@ -136,11 +141,11 @@ class CertificateHtmlViewConfigurationTest(TestCase): self.config.save() expected_config = { "default": { - "url": "http://www.edx.org", - "logo_src": "http://www.edx.org/static/images/logo.png" + "url": "https://www.edx.org", + "logo_src": "https://www.edx.org/static/images/logo.png" }, "honor": { - "logo_src": "http://www.edx.org/static/images/honor-logo.png" + "logo_src": "https://www.edx.org/static/images/honor-logo.png" } } assert self.config.get_config() == expected_config @@ -450,3 +455,62 @@ class GeneratedCertificateTest(SharedModuleStoreTestCase): } self._assert_event_data(mock_emit_certificate_event, expected_event_data) + + +class CertificateAllowlistTest(SharedModuleStoreTestCase): + """ + Tests for the CertificateAllowlist model. + """ + + def setUp(self): + super().setUp() + self.username = 'fun_username' + self.user_email = 'a@b.com' + self.user = UserFactory(username=self.username, email=self.user_email) + self.second_user = UserFactory() + + self.course_run = CourseFactory() + self.course_run_key = self.course_run.id # pylint: disable=no-member + + def test_get_allowlist_empty(self): + ret = CertificateAllowlist.get_certificate_allowlist(course_id=None, student=None) + assert len(ret) == 0 + + def test_get_allowlist_multiple_users(self): + TemporaryCertificateAllowlistFactory.create(course_id=self.course_run_key, user=self.user) + TemporaryCertificateAllowlistFactory.create(course_id=self.course_run_key, user=self.second_user) + + ret = CertificateAllowlist.get_certificate_allowlist(course_id=self.course_run_key) + assert len(ret) == 2 + + def test_get_allowlist_no_cert(self): + allowlist_item = TemporaryCertificateAllowlistFactory.create(course_id=self.course_run_key, user=self.user) + TemporaryCertificateAllowlistFactory.create(course_id=self.course_run_key, user=self.second_user) + + ret = CertificateAllowlist.get_certificate_allowlist(course_id=self.course_run_key, student=self.user) + assert len(ret) == 1 + + item = ret[0] + assert item['id'] == allowlist_item.id + assert item['user_id'] == self.user.id + assert item['user_name'] == self.username + assert item['user_email'] == self.user_email + assert item['course_id'] == str(self.course_run_key) + assert item['created'] == allowlist_item.created.strftime("%B %d, %Y") + assert item['certificate_generated'] == '' + assert item['notes'] == allowlist_item.notes + + def test_get_allowlist_cert(self): + allowlist_item = TemporaryCertificateAllowlistFactory.create(course_id=self.course_run_key, user=self.user) + cert = GeneratedCertificateFactory.create( + status=CertificateStatuses.downloadable, + user=self.user, + course_id=self.course_run_key + ) + + ret = CertificateAllowlist.get_certificate_allowlist(course_id=self.course_run_key, student=self.user) + assert len(ret) == 1 + + item = ret[0] + assert item['id'] == allowlist_item.id + assert item['certificate_generated'] == cert.created_date.strftime("%B %d, %Y")