def setUp(self): super().setUp() # Create users, a course run, and enrollments self.user = UserFactory() self.course_run = CourseFactory() self.course_run_key = self.course_run.id # pylint: disable=no-member self.enrollment = CourseEnrollmentFactory( user=self.user, course_id=self.course_run_key, is_active=True, mode="verified", ) self.user2 = UserFactory() self.enrollment2 = CourseEnrollmentFactory( user=self.user2, course_id=self.course_run_key, is_active=True, mode="verified", ) # Whitelist users CertificateWhitelistFactory.create(course_id=self.course_run_key, user=self.user) CertificateWhitelistFactory.create(course_id=self.course_run_key, user=self.user2)
def test_cert_generation_on_whitelist_append_self_paced(self): """ Verify that signal is sent, received, and fires task based on 'AUTO_CERTIFICATE_GENERATION' flag """ with mock.patch( 'lms.djangoapps.certificates.signals.generate_certificate.apply_async', return_value=None ) as mock_generate_certificate_apply_async: with override_waffle_switch(AUTO_CERTIFICATE_GENERATION_SWITCH, active=False): CertificateWhitelistFactory( user=self.user, course_id=self.course.id ) mock_generate_certificate_apply_async.assert_not_called() with override_waffle_switch(AUTO_CERTIFICATE_GENERATION_SWITCH, active=True): CertificateWhitelistFactory( user=self.user, course_id=self.course.id ) mock_generate_certificate_apply_async.assert_called_with( countdown=CERTIFICATE_DELAY_SECONDS, kwargs={ 'student': six.text_type(self.user.id), 'course_key': six.text_type(self.course.id), } )
def test_can_generate_invalidated(self): """ Test handling when user is on the invalidate list """ u = UserFactory() cr = CourseFactory() key = cr.id # pylint: disable=no-member CourseEnrollmentFactory( user=u, course_id=key, is_active=True, mode="verified", ) cert = GeneratedCertificateFactory( user=u, course_id=key, mode=GeneratedCertificate.MODES.verified, status=CertificateStatuses.downloadable ) CertificateWhitelistFactory.create(course_id=key, user=u) CertificateInvalidationFactory.create( generated_certificate=cert, invalidated_by=self.user, active=True ) self.assertFalse(can_generate_allowlist_certificate(u, key))
def test_is_on_allowlist(self): """ Test to verify that we return True when an allowlist entry exists. """ CertificateWhitelistFactory.create(course_id=self.course_run_key, user=self.user) result = is_on_allowlist(self.user, self.course_run_key) assert result
def test_can_be_added_to_allowlist_is_already_on_allowlist(self): """ Test to verify that a learner will be rejected from the allowlist if they currently already appear on the allowlist. """ CertificateWhitelistFactory.create(course_id=self.course_run_key, user=self.user) assert not can_be_added_to_allowlist(self.user, self.course_run_key)
def test_is_on_allowlist_entry_disabled(self): """ Test to verify that we will return False when the allowlist entry if it is disabled. """ CertificateWhitelistFactory.create(course_id=self.course_run_key, user=self.user, whitelist=False) result = is_on_allowlist(self.user, self.course_run_key) assert not result
def test_can_generate_not_enrolled(self): """ Test handling when user is not enrolled """ u = UserFactory() cr = CourseFactory() key = cr.id # pylint: disable=no-member CertificateWhitelistFactory.create(course_id=key, user=u) assert not _can_generate_allowlist_certificate(u, key)
def test_remove_allowlist_entry(self): """ Test for removing an allowlist entry for a user in a given course-run. """ CertificateWhitelistFactory.create(course_id=self.course_run_key, user=self.user) result = remove_allowlist_entry(self.user, self.course_run_key) assert result with pytest.raises(ObjectDoesNotExist) as error: CertificateWhitelist.objects.get(user=self.user, course_id=self.course_run_key) assert str(error.value) == "CertificateWhitelist matching query does not exist."
def test_is_using_allowlist_and_is_on_list_true(self): """ Test the allowlist flag and the presence of the user on the list when the user is not on the list """ u = UserFactory() CourseEnrollmentFactory( user=u, course_id=self.course_run_key, is_active=True, mode="verified", ) CertificateWhitelistFactory.create(course_id=self.course_run_key, user=u, whitelist=False) self.assertFalse(is_using_certificate_allowlist_and_is_on_allowlist(u, self.course_run_key))
def test_allowlist_removal(self): """ Verify an allowlist entry can be removed using the management command. """ CertificateWhitelistFactory.create(course_id=self.course_run_key, user=self.user) call_command("cert_whitelist", "--del", f"{self.user.username}", "-c", f"{self.course_run_key}") with pytest.raises(ObjectDoesNotExist) as error: CertificateWhitelist.objects.get(user=self.user, course_id=self.course_run_key) assert str(error.value ) == "CertificateWhitelist matching query does not exist."
def test_failing_grade_allowlist(self): # User who is not on the allowlist GeneratedCertificateFactory( user=self.user, course_id=self.course.id, status=CertificateStatuses.downloadable ) CourseGradeFactory().update(self.user, self.course) cert = GeneratedCertificate.certificate_for_student(self.user, self.course.id) self.assertEqual(cert.status, CertificateStatuses.notpassing) # User who is on the allowlist u = UserFactory.create() c = CourseFactory() course_key = c.id # pylint: disable=no-member CertificateWhitelistFactory( user=u, course_id=course_key ) GeneratedCertificateFactory( user=u, course_id=course_key, status=CertificateStatuses.downloadable ) CourseGradeFactory().update(u, c) cert = GeneratedCertificate.certificate_for_student(u, course_key) self.assertEqual(cert.status, CertificateStatuses.downloadable)
def test_can_generate_audit(self): """ Test handling when user is enrolled in audit mode """ u = UserFactory() cr = CourseFactory() key = cr.id # pylint: disable=no-member CourseEnrollmentFactory( user=u, course_id=key, is_active=True, mode="audit", ) CertificateWhitelistFactory.create(course_id=key, user=u) assert not _can_generate_allowlist_certificate(u, key)
def test_ineligible_cert_whitelisted(self, disable_audit_cert, status): """ Test that audit mode students receive a certificate if DISABLE_AUDIT_CERTIFICATES feature is set to false """ # Enroll as audit CourseEnrollmentFactory(user=self.user_2, course_id=self.course.id, is_active=True, mode='audit') # Whitelist student CertificateWhitelistFactory(course_id=self.course.id, user=self.user_2) features = settings.FEATURES features['DISABLE_AUDIT_CERTIFICATES'] = disable_audit_cert with override_settings(FEATURES=features) and mock_passing_grade(): with patch.object(XQueueInterface, 'send_to_queue') as mock_send: mock_send.return_value = (0, None) self.xqueue.add_cert(self.user_2, self.course.id) certificate = GeneratedCertificate.certificate_for_student( self.user_2, self.course.id) self.assertIsNotNone(certificate) self.assertEqual(certificate.mode, 'audit') self.assertEqual(certificate.status, status)
def test_fire_task_allowlist_disabled(self): """ Test that the normal logic is followed if the allowlist is disabled for a user on the list """ with mock.patch( 'lms.djangoapps.certificates.signals.generate_certificate.apply_async', return_value=None ) as mock_generate_certificate_apply_async: with mock.patch( 'lms.djangoapps.certificates.signals.generate_allowlist_certificate_task', return_value=None ) as mock_generate_allowlist_task: CertificateWhitelistFactory( user=self.user, course_id=self.ip_course.id, whitelist=True ) fire_ungenerated_certificate_task(self.user, self.ip_course.id) mock_generate_certificate_apply_async.assert_called_with( countdown=CERTIFICATE_DELAY_SECONDS, kwargs={ 'student': six.text_type(self.user.id), 'course_key': six.text_type(self.ip_course.id), } ) mock_generate_allowlist_task.assert_not_called()
def test_id_verification_allowlist(self): # User is not on the allowlist with mock.patch( 'lms.djangoapps.certificates.signals.generate_allowlist_certificate_task', return_value=None) as mock_allowlist_task: with override_waffle_switch(AUTO_CERTIFICATE_GENERATION_SWITCH, active=True): attempt = SoftwareSecurePhotoVerification.objects.create( user=self.user_two, status='submitted') attempt.approve() mock_allowlist_task.assert_not_called() # User is on the allowlist with mock.patch( 'lms.djangoapps.certificates.signals.generate_allowlist_certificate_task', return_value=None) as mock_allowlist_task: with override_waffle_switch(AUTO_CERTIFICATE_GENERATION_SWITCH, active=True): u = UserFactory.create() c = CourseFactory() course_key = c.id # pylint: disable=no-member CourseEnrollmentFactory(user=u, course_id=course_key, is_active=True, mode='verified') CertificateWhitelistFactory(user=u, course_id=course_key) attempt = SoftwareSecurePhotoVerification.objects.create( user=u, status='submitted') attempt.approve() mock_allowlist_task.assert_called_with(u, course_key)
def test_passing_grade_allowlist(self): with override_waffle_switch(AUTO_CERTIFICATE_GENERATION_SWITCH, active=True): # User who is not on the allowlist GeneratedCertificateFactory(user=self.user, course_id=self.course.id, status=CertificateStatuses.error) with mock_passing_grade(): with mock.patch( 'lms.djangoapps.certificates.signals.generate_allowlist_certificate_task', return_value=None) as mock_allowlist_task: CourseGradeFactory().update(self.user, self.course) mock_allowlist_task.assert_not_called() # User who is on the allowlist u = UserFactory.create() c = CourseFactory() course_key = c.id # pylint: disable=no-member CertificateWhitelistFactory(user=u, course_id=course_key) GeneratedCertificateFactory(user=u, course_id=course_key, status=CertificateStatuses.error) with mock_passing_grade(): with mock.patch( 'lms.djangoapps.certificates.signals.generate_allowlist_certificate_task', return_value=None) as mock_allowlist_task: CourseGradeFactory().update(u, c) mock_allowlist_task.assert_called_with(u, course_key)
def test_get_allowlist_entry(self): """ Test to verify that we can retrieve an allowlist entry for a learner. """ allowlist_entry = CertificateWhitelistFactory.create(course_id=self.course_run_key, user=self.user) retrieved_entry = get_allowlist_entry(self.user, self.course_run_key) assert retrieved_entry.id == allowlist_entry.id assert retrieved_entry.course_id == allowlist_entry.course_id assert retrieved_entry.user == allowlist_entry.user
def test_remove_allowlist_entry_with_certificate(self): """ Test for removing an allowlist entry. Verify that we also invalidate the certificate for the student. """ CertificateWhitelistFactory.create(course_id=self.course_run_key, user=self.user) GeneratedCertificateFactory.create( user=self.user, course_id=self.course_run_key, status=CertificateStatuses.downloadable, mode='verified' ) result = remove_allowlist_entry(self.user, self.course_run_key) assert result certificate = GeneratedCertificate.objects.get(user=self.user, course_id=self.course_run_key) assert certificate.status == CertificateStatuses.unavailable with pytest.raises(ObjectDoesNotExist) as error: CertificateWhitelist.objects.get(user=self.user, course_id=self.course_run_key) assert str(error.value) == "CertificateWhitelist matching query does not exist."
def test_cert_generation_on_allowlist_append_self_paced_auto_cert_generation_disabled( self): """ Verify that signal is sent, received, and fires task based on 'AUTO_CERTIFICATE_GENERATION' flag """ with mock.patch( 'lms.djangoapps.certificates.signals.generate_certificate.apply_async', return_value=None) as mock_generate_certificate_apply_async: with override_waffle_switch(AUTO_CERTIFICATE_GENERATION_SWITCH, active=False): CertificateWhitelistFactory(user=self.user, course_id=self.course.id) mock_generate_certificate_apply_async.assert_not_called()
def setUp(self): super().setUp() self.user = UserFactory.create() self.verified_course = CourseFactory.create(self_paced=True, ) self.verified_course_key = self.verified_course.id # pylint: disable=no-member self.verified_enrollment = CourseEnrollmentFactory( user=self.user, course_id=self.verified_course_key, is_active=True, mode='verified', ) CertificateWhitelistFactory(user=self.user, course_id=self.verified_course_key) self.audit_course = CourseFactory.create(self_paced=False) self.audit_course_key = self.audit_course.id # pylint: disable=no-member self.audit_enrollment = CourseEnrollmentFactory( user=self.user, course_id=self.audit_course_key, is_active=True, mode='audit', ) CertificateWhitelistFactory(user=self.user, course_id=self.audit_course_key)
def test_fire_task_allowlist_enabled(self): """ Test that the allowlist generation is invoked if the allowlist is enabled for a user on the list """ with mock.patch( 'lms.djangoapps.certificates.signals.generate_certificate.apply_async', return_value=None) as mock_generate_certificate_apply_async: with mock.patch( 'lms.djangoapps.certificates.signals.generate_allowlist_certificate_task', return_value=None) as mock_generate_allowlist_task: CertificateWhitelistFactory(user=self.user, course_id=self.ip_course.id, whitelist=True) fire_ungenerated_certificate_task(self.user, self.ip_course.id) mock_generate_certificate_apply_async.assert_not_called() mock_generate_allowlist_task.assert_called_with( self.user, self.ip_course.id)
def test_fire_task_allowlist_enabled(self): """ Test that the allowlist generation is invoked if the allowlist is enabled for a user on the list """ with mock.patch( 'lms.djangoapps.certificates.signals.generate_certificate.apply_async', return_value=None) as mock_generate_certificate_apply_async: with mock.patch( 'lms.djangoapps.certificates.signals.generate_allowlist_certificate_task', return_value=None) as mock_generate_allowlist_task: with override_waffle_switch(AUTO_CERTIFICATE_GENERATION_SWITCH, active=True): CertificateWhitelistFactory(user=self.user, course_id=self.ip_course.id, whitelist=True) mock_generate_certificate_apply_async.assert_not_called() mock_generate_allowlist_task.assert_called_with( self.user, self.ip_course.id)
def setUp(self): super().setUp() # Create users, a course run, and enrollments self.user = UserFactory() self.user2 = UserFactory() self.user3 = UserFactory() self.user4 = UserFactory() self.course_run = CourseFactory() self.course_run_key = self.course_run.id # pylint: disable=no-member self.second_course_run = CourseFactory() self.second_course_run_key = self.second_course_run.id # pylint: disable=no-member self.third_course_run = CourseFactory() self.third_course_run_key = self.third_course_run.id # pylint: disable=no-member CourseEnrollmentFactory( user=self.user, course_id=self.course_run_key, is_active=True, mode="verified", ) CourseEnrollmentFactory( user=self.user2, course_id=self.course_run_key, is_active=True, mode="verified", ) CourseEnrollmentFactory( user=self.user3, course_id=self.course_run_key, is_active=True, mode="verified", ) CourseEnrollmentFactory( user=self.user4, course_id=self.second_course_run_key, is_active=True, mode="verified", ) # Add user to the allowlist CertificateWhitelistFactory.create(course_id=self.course_run_key, user=self.user) # Add user to the allowlist, but set whitelist to false CertificateWhitelistFactory.create(course_id=self.course_run_key, user=self.user2, whitelist=False) # Add user to the allowlist in the other course CertificateWhitelistFactory.create( course_id=self.second_course_run_key, user=self.user4)
def test_invalidate_certificate_allowlist(self): """ Verify that CertificateService does not invalidate the certificate if it is allowlisted """ u = UserFactory.create() c = CourseFactory() course_key = c.id # pylint: disable=no-member GeneratedCertificateFactory.create( status=CertificateStatuses.downloadable, user=u, course_id=course_key, grade=1.0) CertificateWhitelistFactory(user=u, course_id=course_key) success = self.service.invalidate_certificate(u.id, course_key) self.assertFalse(success) cert = GeneratedCertificate.objects.get(user=u.id, course_id=course_key) self.assertEqual(cert.status, CertificateStatuses.downloadable)
def test_ineligible_cert_whitelisted(self): """Test that audit mode students can receive a certificate if they are whitelisted.""" # Enroll as audit CourseEnrollmentFactory(user=self.user_2, course_id=self.course.id, is_active=True, mode='audit') # Whitelist student CertificateWhitelistFactory(course_id=self.course.id, user=self.user_2) # Generate certs with mock_passing_grade(): with patch.object(XQueueInterface, 'send_to_queue') as mock_send: mock_send.return_value = (0, None) self.xqueue.add_cert(self.user_2, self.course.id) # Assert cert generated correctly self.assertTrue(mock_send.called) certificate = GeneratedCertificate.certificate_for_student( self.user_2, self.course.id) self.assertIsNotNone(certificate) self.assertEqual(certificate.mode, 'audit')