def test_retry_until_verification_status_updates(self, user_status_mock, generate_user_certs_mock): course_key = 'course-v1:edX+CS101+2017_T2' student = UserFactory() kwargs = { 'student': student.id, 'course_key': course_key, 'expected_verification_status': IDVerificationAttempt.STATUS.approved } user_status_mock.side_effect = [ {'status': 'pending', 'error': '', 'should_display': True}, {'status': 'approved', 'error': '', 'should_display': True} ] generate_certificate.apply_async(kwargs=kwargs).get() user_status_mock.assert_has_calls([ call(student), call(student) ]) generate_user_certs_mock.assert_called_once_with( student=student, course_key=CourseKey.from_string(course_key) )
def test_retry_until_verification_status_updates(self, user_status_mock, generate_user_certs_mock): course_key = 'course-v1:edX+CS101+2017_T2' student = UserFactory() kwargs = { 'student': student.id, 'course_key': course_key, 'expected_verification_status': IDVerificationAttempt.STATUS.approved } user_status_mock.side_effect = [ {'status': 'pending', 'error': '', 'should_display': True}, {'status': 'approved', 'error': '', 'should_display': True} ] generate_certificate.apply_async(kwargs=kwargs).get() user_status_mock.assert_has_calls([ call(student), call(student) ]) generate_user_certs_mock.assert_called_once_with( student=student, course_key=CourseKey.from_string(course_key) )
def test_missing_args(self, missing_arg): kwargs = {'student': 'a', 'course_key': 'b', 'otherarg': 'c'} del kwargs[missing_arg] with patch('lms.djangoapps.certificates.tasks.User.objects.get'): with self.assertRaisesRegex(KeyError, missing_arg): generate_certificate.apply_async(kwargs=kwargs).get()
def test_generation_mode(self): """ Verify the task handles V2 certificate generation with a generation mode """ course_key = 'course-v1:edX+DemoX+Demo_Course' gen_mode = 'self' with mock.patch( 'lms.djangoapps.certificates.tasks.generate_course_certificate', return_value=None ) as mock_generate_cert: kwargs = { 'student': self.user.id, 'course_key': course_key, 'v2_certificate': True, 'generation_mode': gen_mode } generate_certificate.apply_async(kwargs=kwargs) mock_generate_cert.assert_called_with( user=self.user, course_key=CourseKey.from_string(course_key), status=CertificateStatuses.downloadable, generation_mode=gen_mode )
def test_generation_custom(self): """ Verify the task handles certificate generation custom params """ gen_mode = 'self' status = CertificateStatuses.notpassing enrollment_mode = CourseMode.AUDIT course_grade = '0.89' with mock.patch( 'lms.djangoapps.certificates.tasks.generate_course_certificate', return_value=None) as mock_generate_cert: kwargs = { 'status': status, 'student': self.user.id, 'course_key': self.course_key, 'course_grade': course_grade, 'enrollment_mode': enrollment_mode, 'generation_mode': gen_mode, 'what_about': 'dinosaurs' } generate_certificate.apply_async(kwargs=kwargs) mock_generate_cert.assert_called_with( user=self.user, course_key=CourseKey.from_string(self.course_key), status=status, enrollment_mode=enrollment_mode, course_grade=course_grade, generation_mode=gen_mode)
def test_missing_args(self, missing_arg): kwargs = {'student': 'a', 'course_key': 'b', 'otherarg': 'c'} del kwargs[missing_arg] with patch('lms.djangoapps.certificates.tasks.User.objects.get'): with self.assertRaisesRegexp(KeyError, missing_arg): generate_certificate.apply_async(kwargs=kwargs).get()
def _generate_certificate_task(user, course_key, enrollment_mode, course_grade, status=None, generation_mode=None, delay_seconds=CERTIFICATE_DELAY_SECONDS): """ Create a task to generate a certificate """ log.info( f'About to create a regular certificate task for {user.id} : {course_key}' ) course_grade_val = _get_grade_value(course_grade) kwargs = { 'student': str(user.id), 'course_key': str(course_key), 'enrollment_mode': str(enrollment_mode), 'course_grade': str(course_grade_val) } if status is not None: kwargs['status'] = status if generation_mode is not None: kwargs['generation_mode'] = generation_mode generate_certificate.apply_async(countdown=delay_seconds, kwargs=kwargs) return True
def _fire_ungenerated_certificate_task(user, course_key, expected_verification_status=None): """ Helper function to fire certificate generation task. Auto-generation of certificates is available for following course modes: 1- VERIFIED 2- CREDIT_MODE 3- PROFESSIONAL 4- NO_ID_PROFESSIONAL_MODE Certificate generation task is fired to either generate a certificate when there is no generated certificate for user in a particular course or update a certificate if it has 'unverified' status. Task is fired to attempt an update to a certificate with 'unverified' status as this method is called when a user is successfully verified, any certificate associated with such user can now be verified. NOTE: Purpose of restricting other course modes (HONOR and AUDIT) from auto-generation is to reduce traffic to workers. """ message = u'Entered into Ungenerated Certificate task for {user} : {course}' log.info(message.format(user=user.id, course=course_key)) allowed_enrollment_modes_list = [ CourseMode.VERIFIED, CourseMode.CREDIT_MODE, CourseMode.PROFESSIONAL, CourseMode.NO_ID_PROFESSIONAL_MODE, CourseMode.MASTERS, CourseMode.EXECUTIVE_EDUCATION, ] enrollment_mode, __ = CourseEnrollment.enrollment_mode_for_user( user, course_key) cert = GeneratedCertificate.certificate_for_student(user, course_key) generate_learner_certificate = ( enrollment_mode in allowed_enrollment_modes_list and (cert is None or cert.status == 'unverified')) if generate_learner_certificate: kwargs = { 'student': six.text_type(user.id), 'course_key': six.text_type(course_key) } if expected_verification_status: kwargs['expected_verification_status'] = six.text_type( expected_verification_status) generate_certificate.apply_async(countdown=CERTIFICATE_DELAY_SECONDS, kwargs=kwargs) return True message = u'Certificate Generation task failed for {user} : {course}' log.info(message.format(user=user.id, course=course_key)) return False
def test_missing_args(self, missing_arg): kwargs = { 'student': self.user.id, 'course_key': self.course_key, 'other_arg': 'shiny', 'enrollment_mode': CourseMode.MASTERS } del kwargs[missing_arg] with patch('lms.djangoapps.certificates.tasks.User.objects.get'): with self.assertRaisesRegex(KeyError, missing_arg): generate_certificate.apply_async(kwargs=kwargs).get()
def _generate_certificate_task(user, course_key, generation_mode=None): """ Create a task to generate a certificate """ log.info(f'About to create a V2 certificate task for {user.id} : {course_key}') kwargs = { 'student': str(user.id), 'course_key': str(course_key), 'v2_certificate': True } if generation_mode is not None: kwargs['generation_mode'] = generation_mode generate_certificate.apply_async(countdown=CERTIFICATE_DELAY_SECONDS, kwargs=kwargs) return True
def fire_ungenerated_certificate_task(user, course_key, expected_verification_status=None): """ Helper function to fire certificate generation task. Auto-generation of certificates is available for following course modes: 1- VERIFIED 2- CREDIT_MODE 3- PROFESSIONAL 4- NO_ID_PROFESSIONAL_MODE Certificate generation task is fired to either generate a certificate when there is no generated certificate for user in a particular course or update a certificate if it has 'unverified' status. Task is fired to attempt an update to a certificate with 'unverified' status as this method is called when a user is successfully verified, any certificate associated with such user can now be verified. NOTE: Purpose of restricting other course modes (HONOR and AUDIT) from auto-generation is to reduce traffic to workers. """ allowed_enrollment_modes_list = [ CourseMode.VERIFIED, CourseMode.CREDIT_MODE, CourseMode.PROFESSIONAL, CourseMode.NO_ID_PROFESSIONAL_MODE, CourseMode.MASTERS, ] enrollment_mode, __ = CourseEnrollment.enrollment_mode_for_user(user, course_key) cert = GeneratedCertificate.certificate_for_student(user, course_key) generate_learner_certificate = ( enrollment_mode in allowed_enrollment_modes_list and (cert is None or cert.status == 'unverified') ) if generate_learner_certificate: kwargs = { 'student': unicode(user.id), 'course_key': unicode(course_key) } if expected_verification_status: kwargs['expected_verification_status'] = unicode(expected_verification_status) generate_certificate.apply_async(countdown=CERTIFICATE_DELAY_SECONDS, kwargs=kwargs) return True
def test_generate_user_certs(self, user_get_mock, generate_user_certs_mock): course_key = 'course-v1:edX+CS101+2017_T2' kwargs = { 'student': 'student-id', 'course_key': course_key, 'otherarg': 'c', 'otherotherarg': 'd' } generate_certificate.apply_async(kwargs=kwargs).get() expected_student = user_get_mock.return_value generate_user_certs_mock.assert_called_with( student=expected_student, course_key=CourseKey.from_string(course_key), otherarg='c', otherotherarg='d' ) user_get_mock.assert_called_once_with(id='student-id')
def test_generate_user_certs(self, user_get_mock, generate_user_certs_mock): course_key = 'course-v1:edX+CS101+2017_T2' kwargs = { 'student': 'student-id', 'course_key': course_key, 'otherarg': 'c', 'otherotherarg': 'd' } generate_certificate.apply_async(kwargs=kwargs).get() expected_student = user_get_mock.return_value generate_user_certs_mock.assert_called_with( student=expected_student, course_key=CourseKey.from_string(course_key), otherarg='c', otherotherarg='d' ) user_get_mock.assert_called_once_with(id='student-id')
def _generate_certificate_task(user, course_key, enrollment_mode, course_grade, status=None, generation_mode=None, delay_seconds=CERTIFICATE_DELAY_SECONDS): """ Create a task to generate a certificate """ log.info( f'About to create a regular certificate task for {user.id} : {course_key}' ) course_grade_val = _get_grade_value(course_grade) try: # .. filter_implemented_name: CertificateCreationRequested # .. filter_type: org.openedx.learning.certificate.creation.requested.v1 user, course_key, enrollment_mode, status, course_grade, generation_mode = CertificateCreationRequested.run_filter( # pylint: disable=line-too-long user=user, course_key=course_key, mode=enrollment_mode, status=status, grade=course_grade, generation_mode=generation_mode, ) except CertificateCreationRequested.PreventCertificateCreation as exc: raise CertificateGenerationNotAllowed(str(exc)) from exc kwargs = { 'student': str(user.id), 'course_key': str(course_key), 'enrollment_mode': str(enrollment_mode), 'course_grade': str(course_grade_val) } if status is not None: kwargs['status'] = status if generation_mode is not None: kwargs['generation_mode'] = generation_mode generate_certificate.apply_async(countdown=delay_seconds, kwargs=kwargs) return True
def generate_allowlist_certificate_task(user, course_key): """ Create a task to generate an allowlist certificate for this user in this course run. """ if not can_generate_allowlist_certificate(user, course_key): log.info( 'Cannot generate an allowlist certificate for {user} : {course}'.format(user=user.id, course=course_key)) return False log.info( 'About to create an allowlist certificate task for {user} : {course}'.format(user=user.id, course=course_key)) kwargs = { 'student': str(user.id), 'course_key': str(course_key), 'allowlist_certificate': True } generate_certificate.apply_async(countdown=CERTIFICATE_DELAY_SECONDS, kwargs=kwargs) return True
def generate_regular_certificate_task(user, course_key): """ Create a task to generate a regular (non-allowlist) certificate for this user in this course run, if the user is eligible and a certificate can be generated. """ if not _can_generate_v2_certificate(user, course_key): log.info( f'Cannot generate a v2 course certificate for {user.id} : {course_key}' ) return False log.info( f'About to create a v2 course certificate task for {user.id} : {course_key}' ) kwargs = { 'student': str(user.id), 'course_key': str(course_key), 'v2_certificate': True } generate_certificate.apply_async(countdown=CERTIFICATE_DELAY_SECONDS, kwargs=kwargs) return True
def test_generation(self): """ Verify the task handles certificate generation """ enrollment_mode = CourseMode.VERIFIED with mock.patch( 'lms.djangoapps.certificates.tasks.generate_course_certificate', return_value=None) as mock_generate_cert: kwargs = { 'student': self.user.id, 'course_key': self.course_key, 'enrollment_mode': enrollment_mode } generate_certificate.apply_async(kwargs=kwargs) mock_generate_cert.assert_called_with( user=self.user, course_key=CourseKey.from_string(self.course_key), status=CertificateStatuses.downloadable, enrollment_mode=enrollment_mode, course_grade='', generation_mode='batch')