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', ) CertificateAllowlistFactory( 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', ) CertificateAllowlistFactory( user=self.user, course_id=self.audit_course_key )
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 ) CertificateAllowlistFactory.create(course_id=key, user=u) CertificateInvalidationFactory.create( generated_certificate=cert, invalidated_by=self.user, active=True ) assert not _can_generate_allowlist_certificate(u, key) assert _set_allowlist_cert_status(u, key) == CertificateStatuses.unavailable
def test_generate_allowlist_honor_cert(self): """ Test that verifies we can generate an Honor cert for an Open edX installation configured to support Honor certificates. """ course_run = CourseFactory() course_run_key = course_run.id # pylint: disable=no-member enrollment_mode = CourseMode.HONOR CourseEnrollmentFactory( user=self.user, course_id=course_run_key, is_active=True, mode=enrollment_mode, ) CertificateAllowlistFactory.create(course_id=course_run_key, user=self.user) # Enable Honor Certificates and verify we can generate an AllowList certificate with override_settings( FEATURES={ **settings.FEATURES, 'DISABLE_HONOR_CERTIFICATES': False }): assert _can_generate_allowlist_certificate(self.user, course_run_key, enrollment_mode) # Disable Honor Certificates and verify we cannot generate an AllowList certificate with override_settings( FEATURES={ **settings.FEATURES, 'DISABLE_HONOR_CERTIFICATES': True }): assert not _can_generate_allowlist_certificate( self.user, course_run_key, enrollment_mode)
def test_is_on_allowlist_entry_disabled(self): """ Test to verify that we will return False when the allowlist entry if it is disabled. """ CertificateAllowlistFactory.create(course_id=self.course_run_key, user=self.user, allowlist=False) result = is_on_allowlist(self.user, self.course_run_key) assert not 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. """ CertificateAllowlistFactory.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(self): """ Test to verify that we return True when an allowlist entry exists. """ CertificateAllowlistFactory.create(course_id=self.course_run_key, user=self.user) result = is_on_allowlist(self.user, self.course_run_key) assert result
def test_get_allowlist_multiple_users(self): CertificateAllowlistFactory.create(course_id=self.course_run_key, user=self.user) CertificateAllowlistFactory.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_remove_allowlist_entry(self): """ Test for removing an allowlist entry for a user in a given course-run. """ CertificateAllowlistFactory.create(course_id=self.course_run_key, user=self.user) assert is_on_allowlist(self.user, self.course_run_key) result = remove_allowlist_entry(self.user, self.course_run_key) assert result assert not is_on_allowlist(self.user, self.course_run_key)
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 CertificateAllowlistFactory.create(course_id=key, user=u) assert not _can_generate_allowlist_certificate(u, key) assert _set_allowlist_cert_status(u, key) is None
def test_allowlist_removal(self): """ Verify an allowlist entry can be removed using the management command. """ CertificateAllowlistFactory.create(course_id=self.course_run_key, user=self.user) assert is_on_allowlist(self.user, self.course_run_key) call_command("cert_whitelist", "--del", f"{self.user.username}", "-c", f"{self.course_run_key}") assert not is_on_allowlist(self.user, self.course_run_key)
def test_is_on_allowlist_false(self): """ Test the absence of the user on the allowlist """ u = UserFactory() CourseEnrollmentFactory( user=u, course_id=self.course_run_key, is_active=True, mode=CourseMode.VERIFIED, ) CertificateAllowlistFactory.create(course_id=self.course_run_key, user=u, allowlist=False) assert not is_on_certificate_allowlist(u, self.course_run_key)
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", ) CertificateAllowlistFactory.create(course_id=self.course_run_key, user=u, whitelist=False) assert not is_using_certificate_allowlist_and_is_on_allowlist(u, self.course_run_key)
def test_remove_allowlist_entry(self): """ Test for removing an allowlist entry for a user in a given course-run. """ CertificateAllowlistFactory.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_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) assert cert.status == CertificateStatuses.notpassing # User who is on the allowlist u = UserFactory.create() c = CourseFactory() course_key = c.id # pylint: disable=no-member CertificateAllowlistFactory( 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) assert cert.status == CertificateStatuses.downloadable
def test_can_generate_not_verified_not_passing_allowlist( self, enable_idv_requirement): """ Test handling when the user's id is not verified and the user is not passing but is on the allowlist """ u = UserFactory() CourseEnrollmentFactory( user=u, course_id=self.course_run_key, is_active=True, mode=CourseMode.VERIFIED, ) GeneratedCertificateFactory(user=u, course_id=self.course_run_key, mode=GeneratedCertificate.MODES.verified, status=CertificateStatuses.generating) CertificateAllowlistFactory(course_id=self.course_run_key, user=u) with mock.patch(ID_VERIFIED_METHOD, return_value=False), \ mock.patch.dict(settings.FEATURES, ENABLE_CERTIFICATES_IDV_REQUIREMENT=enable_idv_requirement), \ mock.patch(PASSING_GRADE_METHOD, return_value=False): assert not _can_generate_regular_certificate( u, self.course_run_key, self.enrollment_mode, self.grade) if enable_idv_requirement: assert _set_regular_cert_status( u, self.course_run_key, self.enrollment_mode, self.grade) == CertificateStatuses.unverified else: assert _set_regular_cert_status( u, self.course_run_key, self.enrollment_mode, self.grade) == CertificateStatuses.notpassing
def test_can_generate_not_verified_not_passing_allowlist(self, idv_retired): """ Test handling when the user's id is not verified and the user is not passing but is on the allowlist """ u = UserFactory() CourseEnrollmentFactory( user=u, course_id=self.course_run_key, is_active=True, mode=CourseMode.VERIFIED, ) GeneratedCertificateFactory( user=u, course_id=self.course_run_key, mode=GeneratedCertificate.MODES.verified, status=CertificateStatuses.generating ) CertificateAllowlistFactory(course_id=self.course_run_key, user=u) with mock.patch(ID_VERIFIED_METHOD, return_value=False), \ mock.patch(INTEGRITY_ENABLED_METHOD, return_value=idv_retired), \ mock.patch(PASSING_GRADE_METHOD, return_value=False): assert not _can_generate_regular_certificate(u, self.course_run_key, self.enrollment_mode, self.grade) if idv_retired: assert _set_regular_cert_status(u, self.course_run_key, self.enrollment_mode, self.grade) == CertificateStatuses.notpassing else: assert _set_regular_cert_status(u, self.course_run_key, self.enrollment_mode, self.grade) == CertificateStatuses.unverified
def test_ineligible_cert_allowlisted(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') # Add student to the allowlist CertificateAllowlistFactory(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) assert certificate is not None assert certificate.mode == 'audit' assert certificate.status == status
def setUp(self): super().setUp() # Create user, a course run, and an enrollment 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", ) # Whitelist user CertificateAllowlistFactory.create(course_id=self.course_run_key, user=self.user)
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, 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, 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') CertificateAllowlistFactory(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_allowlist_removal(self): """ Verify an allowlist entry can be removed using the management command. """ CertificateAllowlistFactory.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_passing_grade_allowlist(self): with override_waffle_switch(AUTO_CERTIFICATE_GENERATION, 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_certificate_task', return_value=None) as mock_cert_task: CourseGradeFactory().update(self.user, self.course) mock_cert_task.assert_called_with(self.user, self.course.id) # User who is on the allowlist u = UserFactory.create() c = CourseFactory() course_key = c.id # pylint: disable=no-member CertificateAllowlistFactory(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_certificate_task', return_value=None) as mock_cert_task: CourseGradeFactory().update(u, c) mock_cert_task.assert_called_with(u, course_key)
def setUp(self): super().setUp() # Create user, a course run, and an enrollment 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=GeneratedCertificate.MODES.verified, ) # Add user to the allowlist CertificateAllowlistFactory.create(course_id=self.course_run_key, user=self.user)
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", ) CertificateAllowlistFactory.create(course_id=key, user=u) assert not _can_generate_allowlist_certificate(u, key) assert _set_allowlist_cert_status(u, key) is None
def setUp(self): super().setUp() # Create user, a course run, and an enrollment self.user = UserFactory() self.course_run = CourseFactory() self.course_run_key = self.course_run.id # pylint: disable=no-member self.enrollment_mode = CourseMode.VERIFIED self.grade = CourseGradeFactory().read(self.user, self.course_run) self.enrollment = CourseEnrollmentFactory( user=self.user, course_id=self.course_run_key, is_active=True, mode=self.enrollment_mode, ) # Add user to the allowlist CertificateAllowlistFactory.create(course_id=self.course_run_key, user=self.user)
def test_generate_allowlist_certificate_fail(self): """ Test stop certificate process by raising a filter exception when the user is in the allow list. Expected result: - CertificateCreationRequested is triggered and executes TestStopCertificateGenerationStep. - The certificate is not generated. """ CertificateAllowlistFactory.create(course_id=self.course_run.id, user=self.user) certificate_generated = generate_allowlist_certificate_task(self.user, self.course_run.id) self.assertFalse(certificate_generated) self.assertFalse( GeneratedCertificate.objects.filter( user=self.user, course_id=self.course_run.id, mode=CourseMode.HONOR, ) )
def test_get_allowlist_no_cert(self): allowlist_item = CertificateAllowlistFactory.create( course_id=self.course_run_key, user=self.user) CertificateAllowlistFactory.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_remove_allowlist_entry_with_certificate(self): """ Test for removing an allowlist entry. Verify that we also invalidate the certificate for the student. """ CertificateAllowlistFactory.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' ) assert is_on_allowlist(self.user, self.course_run_key) 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 assert not is_on_allowlist(self.user, self.course_run_key)
def test_get_allowlist_entry(self): """ Test to verify that we can retrieve an allowlist entry for a learner. """ allowlist_entry = CertificateAllowlistFactory.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_fire_task_allowlist_auto_disabled(self): """ Test that the allowlist generation is not invoked if automatic generation is disabled """ 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, active=False): CertificateAllowlistFactory(user=self.user, course_id=self.ip_course.id) mock_generate_allowlist_task.assert_not_called()
def test_get_users_allowlist(self): """ Test that allowlisted users are returned correctly """ u1 = UserFactory() u2 = UserFactory() u3 = UserFactory() u4 = UserFactory() cr1 = CourseFactory() key1 = cr1.id # pylint: disable=no-member cr2 = CourseFactory() key2 = cr2.id # pylint: disable=no-member cr3 = CourseFactory() key3 = cr3.id # pylint: disable=no-member CourseEnrollmentFactory( user=u1, course_id=key1, is_active=True, mode="verified", ) CourseEnrollmentFactory( user=u2, course_id=key1, is_active=True, mode="verified", ) CourseEnrollmentFactory( user=u3, course_id=key1, is_active=True, mode="verified", ) CourseEnrollmentFactory( user=u4, course_id=key2, is_active=True, mode="verified", ) # Add user to the allowlist CertificateAllowlistFactory.create(course_id=key1, user=u1) # Add user to the allowlist, but set allowlist to false CertificateAllowlistFactory.create(course_id=key1, user=u2, allowlist=False) # Add user to the allowlist in the other course CertificateAllowlistFactory.create(course_id=key2, user=u4) users = get_allowlisted_users(key1) assert 1 == users.count() assert users[0].id == u1.id users = get_allowlisted_users(key2) assert 1 == users.count() assert users[0].id == u4.id users = get_allowlisted_users(key3) assert 0 == users.count()