def test_is_user_eligible_for_credit(self): credit_course = self.add_credit_course() CreditEligibility.objects.create(course=credit_course, username="******") is_eligible = api.is_user_eligible_for_credit("staff", credit_course.course_key) self.assertTrue(is_eligible) is_eligible = api.is_user_eligible_for_credit("abc", credit_course.course_key) self.assertFalse(is_eligible)
def test_is_user_eligible_for_credit(self): credit_course = self.add_credit_course() CreditEligibility.objects.create( course=credit_course, username="******" ) is_eligible = api.is_user_eligible_for_credit('staff', credit_course.course_key) self.assertTrue(is_eligible) is_eligible = api.is_user_eligible_for_credit('abc', credit_course.course_key) self.assertFalse(is_eligible)
def test_is_user_eligible_for_credit(self): credit_course = self.add_credit_course() CreditEligibility.objects.create( course=credit_course, username="******", provider=CreditProvider.objects.get(provider_id=self.PROVIDER_ID) ) is_eligible = api.is_user_eligible_for_credit('staff', credit_course.course_key) self.assertTrue(is_eligible) is_eligible = api.is_user_eligible_for_credit('abc', credit_course.course_key) self.assertFalse(is_eligible)
def test_satisfy_all_requirements(self): # Configure a course with two credit requirements self.add_credit_course() requirements = [ { "namespace": "grade", "name": "grade", "display_name": "Grade", "criteria": { "min_grade": 0.8 }, }, { "namespace": "reverification", "name": "i4x://edX/DemoX/edx-reverification-block/assessment_uuid", "display_name": "Assessment 1", "criteria": {}, } ] api.set_credit_requirements(self.course_key, requirements) # Satisfy one of the requirements, but not the other with self.assertNumQueries(7): api.set_credit_requirement_status( "bob", self.course_key, requirements[0]["namespace"], requirements[0]["name"] ) # The user should not be eligible (because only one requirement is satisfied) self.assertFalse(api.is_user_eligible_for_credit("bob", self.course_key)) # Satisfy the other requirement with self.assertNumQueries(10): api.set_credit_requirement_status( "bob", self.course_key, requirements[1]["namespace"], requirements[1]["name"] ) # Now the user should be eligible self.assertTrue(api.is_user_eligible_for_credit("bob", self.course_key)) # The user should remain eligible even if the requirement status is later changed api.set_credit_requirement_status( "bob", self.course_key, requirements[0]["namespace"], requirements[0]["name"], status="failed" ) self.assertTrue(api.is_user_eligible_for_credit("bob", self.course_key))
def test_eligibility_email_with_providers(self, providers_list, providers_email_message, expected_subject): """ Test the credit requirements, eligibility notification, email for different providers combinations. """ # Configure a course with two credit requirements self.add_credit_course() CourseFactory.create(org='edX', number='DemoX', display_name='Demo_Course') requirements = [ { "namespace": "grade", "name": "grade", "display_name": "Grade", "criteria": { "min_grade": 0.8 }, }, { "namespace": "reverification", "name": "i4x://edX/DemoX/edx-reverification-block/assessment_uuid", "display_name": "Assessment 1", "criteria": {}, } ] api.set_credit_requirements(self.course_key, requirements) user = UserFactory.create(username=self.USER_INFO['username'], password=self.USER_INFO['password']) # Satisfy one of the requirements, but not the other api.set_credit_requirement_status( user.username, self.course_key, requirements[0]["namespace"], requirements[0]["name"] ) # Satisfy the other requirement. And mocked the api to return different kind of data. with mock.patch('openedx.core.djangoapps.credit.email_utils.get_credit_provider_display_names') as mock_method: mock_method.return_value = providers_list api.set_credit_requirement_status( "bob", self.course_key, requirements[1]["namespace"], requirements[1]["name"] ) # Now the user should be eligible self.assertTrue(api.is_user_eligible_for_credit("bob", self.course_key)) # Credit eligibility email should be sent self.assertEqual(len(mail.outbox), 1) # Verify the email subject self.assertEqual(mail.outbox[0].subject, expected_subject) # Now verify them email content email_payload_first = mail.outbox[0].attachments[0]._payload # pylint: disable=protected-access html_content_first = email_payload_first[0]._payload[1]._payload # pylint: disable=protected-access self.assertIn(providers_email_message, html_content_first) # test text email text_content_first = email_payload_first[0]._payload[0]._payload # pylint: disable=protected-access self.assertIn(providers_email_message, text_content_first)
def test_eligibility_disabled_course(self): # Configure a credit eligibility for a disabled course credit_course = self.add_credit_course() credit_course.enabled = False credit_course.save() CreditEligibility.objects.create(course=credit_course, username="******") # The user should NOT be eligible for credit is_eligible = api.is_user_eligible_for_credit("staff", credit_course.course_key) self.assertFalse(is_eligible) # The eligibility should NOT show up in the user's list of eligibilities eligibilities = api.get_eligibilities_for_user("staff") self.assertEqual(eligibilities, [])
def test_eligibility_expired(self): # Configure a credit eligibility that expired yesterday credit_course = self.add_credit_course() CreditEligibility.objects.create( course=credit_course, username="******", deadline=datetime.datetime.now(pytz.UTC) - datetime.timedelta(days=1) ) # The user should NOT be eligible for credit is_eligible = api.is_user_eligible_for_credit("staff", credit_course.course_key) self.assertFalse(is_eligible) # The eligibility should NOT show up in the user's list of eligibilities eligibilities = api.get_eligibilities_for_user("staff") self.assertEqual(eligibilities, [])
def test_eligibility_disabled_course(self): # Configure a credit eligibility for a disabled course credit_course = self.add_credit_course() credit_course.enabled = False credit_course.save() CreditEligibility.objects.create( course=credit_course, username="******", ) # The user should NOT be eligible for credit is_eligible = api.is_user_eligible_for_credit("staff", credit_course.course_key) self.assertFalse(is_eligible) # The eligibility should NOT show up in the user's list of eligibilities eligibilities = api.get_eligibilities_for_user("staff") self.assertEqual(eligibilities, [])
def test_satisfy_all_requirements(self): """ Test the credit requirements, eligibility notification, email content caching for a credit course. """ # Configure a course with two credit requirements self.add_credit_course() CourseFactory.create(org='edX', number='DemoX', display_name='Demo_Course') requirements = [{ "namespace": "grade", "name": "grade", "display_name": "Grade", "criteria": { "min_grade": 0.8 }, }, { "namespace": "reverification", "name": "i4x://edX/DemoX/edx-reverification-block/assessment_uuid", "display_name": "Assessment 1", "criteria": {}, }] api.set_credit_requirements(self.course_key, requirements) user = UserFactory.create(username=self.USER_INFO['username'], password=self.USER_INFO['password']) # Satisfy one of the requirements, but not the other with self.assertNumQueries(7): api.set_credit_requirement_status(user.username, self.course_key, requirements[0]["namespace"], requirements[0]["name"]) # The user should not be eligible (because only one requirement is satisfied) self.assertFalse( api.is_user_eligible_for_credit("bob", self.course_key)) # Satisfy the other requirement with self.assertNumQueries(11): api.set_credit_requirement_status("bob", self.course_key, requirements[1]["namespace"], requirements[1]["name"]) # Now the user should be eligible self.assertTrue(api.is_user_eligible_for_credit( "bob", self.course_key)) # Credit eligibility email should be sent self.assertEqual(len(mail.outbox), 1) self.assertEqual(mail.outbox[0].subject, 'Course Credit Eligibility') # Now verify them email content email_payload_first = mail.outbox[0].attachments[0]._payload # pylint: disable=protected-access # Test that email has two payloads [multipart (plain text and html # content), attached image] self.assertEqual(len(email_payload_first), 2) # pylint: disable=protected-access self.assertIn('text/plain', email_payload_first[0]._payload[0]['Content-Type']) # pylint: disable=protected-access self.assertIn('text/html', email_payload_first[0]._payload[1]['Content-Type']) self.assertIn('image/png', email_payload_first[1]['Content-Type']) # Now check that html email content has same logo image 'Content-ID' # as the attached logo image 'Content-ID' email_image = email_payload_first[1] html_content_first = email_payload_first[0]._payload[1]._payload # pylint: disable=protected-access # strip enclosing angle brackets from 'logo_image' cache 'Content-ID' image_id = email_image.get('Content-ID', '')[1:-1] self.assertIsNotNone(image_id) self.assertIn(image_id, html_content_first) # Delete the eligibility entries and satisfy the user's eligibility # requirement again to trigger eligibility notification CreditEligibility.objects.all().delete() with self.assertNumQueries(12): api.set_credit_requirement_status("bob", self.course_key, requirements[1]["namespace"], requirements[1]["name"]) # Credit eligibility email should be sent self.assertEqual(len(mail.outbox), 2) # Now check that on sending eligibility notification again cached # logo image is used email_payload_second = mail.outbox[1].attachments[0]._payload # pylint: disable=protected-access html_content_second = email_payload_second[0]._payload[1]._payload # pylint: disable=protected-access self.assertIn(image_id, html_content_second) # The user should remain eligible even if the requirement status is later changed api.set_credit_requirement_status("bob", self.course_key, requirements[0]["namespace"], requirements[0]["name"], status="failed") self.assertTrue(api.is_user_eligible_for_credit( "bob", self.course_key))
def test_satisfy_all_requirements(self): """ Test the credit requirements, eligibility notification, email content caching for a credit course. """ # Configure a course with two credit requirements self.add_credit_course() CourseFactory.create(org='edX', number='DemoX', display_name='Demo_Course') requirements = [ { "namespace": "grade", "name": "grade", "display_name": "Grade", "criteria": { "min_grade": 0.8 }, }, { "namespace": "reverification", "name": "i4x://edX/DemoX/edx-reverification-block/assessment_uuid", "display_name": "Assessment 1", "criteria": {}, } ] api.set_credit_requirements(self.course_key, requirements) user = UserFactory.create(username=self.USER_INFO['username'], password=self.USER_INFO['password']) # Satisfy one of the requirements, but not the other with self.assertNumQueries(11): api.set_credit_requirement_status( user.username, self.course_key, requirements[0]["namespace"], requirements[0]["name"] ) # The user should not be eligible (because only one requirement is satisfied) self.assertFalse(api.is_user_eligible_for_credit("bob", self.course_key)) # Satisfy the other requirement with self.assertNumQueries(15): api.set_credit_requirement_status( "bob", self.course_key, requirements[1]["namespace"], requirements[1]["name"] ) # Now the user should be eligible self.assertTrue(api.is_user_eligible_for_credit("bob", self.course_key)) # Credit eligibility email should be sent self.assertEqual(len(mail.outbox), 1) self.assertEqual(mail.outbox[0].subject, 'Course Credit Eligibility') # Now verify them email content email_payload_first = mail.outbox[0].attachments[0]._payload # pylint: disable=protected-access # Test that email has two payloads [multipart (plain text and html # content), attached image] self.assertEqual(len(email_payload_first), 2) # pylint: disable=protected-access self.assertIn('text/plain', email_payload_first[0]._payload[0]['Content-Type']) # pylint: disable=protected-access self.assertIn('text/html', email_payload_first[0]._payload[1]['Content-Type']) self.assertIn('image/png', email_payload_first[1]['Content-Type']) # Now check that html email content has same logo image 'Content-ID' # as the attached logo image 'Content-ID' email_image = email_payload_first[1] html_content_first = email_payload_first[0]._payload[1]._payload # pylint: disable=protected-access # strip enclosing angle brackets from 'logo_image' cache 'Content-ID' image_id = email_image.get('Content-ID', '')[1:-1] self.assertIsNotNone(image_id) self.assertIn(image_id, html_content_first) # Delete the eligibility entries and satisfy the user's eligibility # requirement again to trigger eligibility notification CreditEligibility.objects.all().delete() with self.assertNumQueries(13): api.set_credit_requirement_status( "bob", self.course_key, requirements[1]["namespace"], requirements[1]["name"] ) # Credit eligibility email should be sent self.assertEqual(len(mail.outbox), 2) # Now check that on sending eligibility notification again cached # logo image is used email_payload_second = mail.outbox[1].attachments[0]._payload # pylint: disable=protected-access html_content_second = email_payload_second[0]._payload[1]._payload # pylint: disable=protected-access self.assertIn(image_id, html_content_second) # The user should remain eligible even if the requirement status is later changed api.set_credit_requirement_status( "bob", self.course_key, requirements[0]["namespace"], requirements[0]["name"], status="failed" ) self.assertTrue(api.is_user_eligible_for_credit("bob", self.course_key))
def test_satisfy_all_requirements(self): # Configure a course with two credit requirements self.add_credit_course() CourseFactory.create(org='edX', number='DemoX', display_name='Demo_Course') requirements = [ { "namespace": "grade", "name": "grade", "display_name": "Grade", "criteria": { "min_grade": 0.8 }, }, { "namespace": "reverification", "name": "i4x://edX/DemoX/edx-reverification-block/assessment_uuid", "display_name": "Assessment 1", "criteria": {}, } ] api.set_credit_requirements(self.course_key, requirements) user = UserFactory.create(username=self.USER_INFO['username'], password=self.USER_INFO['password']) # Satisfy one of the requirements, but not the other with self.assertNumQueries(7): api.set_credit_requirement_status( user.username, self.course_key, requirements[0]["namespace"], requirements[0]["name"] ) # The user should not be eligible (because only one requirement is satisfied) self.assertFalse(api.is_user_eligible_for_credit("bob", self.course_key)) # Satisfy the other requirement with self.assertNumQueries(11): api.set_credit_requirement_status( "bob", self.course_key, requirements[1]["namespace"], requirements[1]["name"] ) # Now the user should be eligible self.assertTrue(api.is_user_eligible_for_credit("bob", self.course_key)) # Credit eligible mail should be sent self.assertEqual(len(mail.outbox), 1) self.assertEqual(mail.outbox[0].subject, 'Course Credit Eligibility') # The user should remain eligible even if the requirement status is later changed api.set_credit_requirement_status( "bob", self.course_key, requirements[0]["namespace"], requirements[0]["name"], status="failed" ) self.assertTrue(api.is_user_eligible_for_credit("bob", self.course_key))