def setUpTestData(cls): super().setUpTestData() with mute_signals(post_save): staff_profile = ProfileFactory.create(user__email='*****@*****.**') recipient_profile = ProfileFactory.create( user__email='*****@*****.**', email_optin=True, ) cls.staff_user = staff_profile.user cls.recipient_user = recipient_profile.user cls.program = ProgramFactory.create(financial_aid_availability=False) ProgramEnrollmentFactory.create( user=cls.recipient_user, program=cls.program ) Role.objects.create( user=cls.staff_user, program=cls.program, role=Staff.ROLE_ID ) cls.url_name = 'learner_mail_api' cls.request_data = { 'email_subject': 'email subject', 'email_body': 'email body' }
def test_add_moderators_to_channel(mocker, patched_users_api): """add_moderators_to_channel should add staff or instructors as moderators and subscribers""" channel = ChannelFactory.create() mods = [] for _ in range(3): program = ChannelProgramFactory.create(channel=channel).program with mute_signals(post_save): mods += [ RoleFactory.create( program=program, user=ProfileFactory.create().user ).user for _ in range(5) ] for __ in range(5): # Add some users to the channel to show that being part of the channel is not enough to be added as a mod ProgramEnrollmentFactory.create(program=program) create_stub, _ = patched_users_api create_stub.reset_mock() add_subscriber_stub = mocker.patch('discussions.api.add_subscriber_to_channel', autospec=True) add_moderator_stub = mocker.patch('discussions.api.add_moderator_to_channel', autospec=True) api.add_moderators_to_channel(channel.name) for mod in mods: add_subscriber_stub.assert_any_call(channel.name, mod.discussion_user.username) add_moderator_stub.assert_any_call(channel.name, mod.discussion_user.username) create_stub.assert_any_call(mod.discussion_user) assert add_subscriber_stub.call_count == len(mods) assert add_moderator_stub.call_count == len(mods) assert create_stub.call_count == len(mods)
def setUpTestData(cls): super(SearchTests, cls).setUpTestData() # create some students with mute_signals(post_save): cls.students = [(ProfileFactory.create(filled_out=True)).user for _ in range(30)] # create the programs cls.program1 = ProgramFactory.create(live=True) cls.program2 = ProgramFactory.create(live=True) cls.program3 = ProgramFactory.create(live=True) # enroll the users in the programs for num, student in enumerate(cls.students): if num % 3 == 0: program = cls.program1 elif num % 3 == 1: program = cls.program2 else: program = cls.program3 ProgramEnrollmentFactory.create( user=student, program=program ) # create an user with a role for one program cls.staff = UserFactory.create() Role.objects.create( user=cls.staff, program=cls.program1, role=Staff.ROLE_ID ) # search URL cls.search_url = reverse('search_api', kwargs={'elastic_url': ''})
def test_learner_view_needs_paid_learner(self, mock_mailgun_client): """ Test that a learner attempting to email another learner will only succeed if the sender has paid for a course run in a program that the recipient is enrolled in """ mock_mailgun_client.send_individual_email.return_value = Mock( spec=Response, status_code=status.HTTP_200_OK, json=mocked_json() ) with mute_signals(post_save): learner_profile = ProfileFactory.create( user__email='*****@*****.**', email_optin=True, ) learner_user = learner_profile.user ProgramEnrollmentFactory.create(user=learner_user, program=self.program) CachedEnrollment.objects.filter(user=learner_user).delete() self.client.force_login(learner_user) url = reverse(self.url_name, kwargs={'student_id': self.recipient_user.profile.student_id}) resp_post = self.client.post(url, data=self.request_data, format='json') assert resp_post.status_code == status.HTTP_403_FORBIDDEN CachedEnrollmentFactory.create(user=learner_user, course_run__course__program=self.program, verified=True) resp_post = self.client.post(url, data=self.request_data, format='json') assert resp_post.status_code == status.HTTP_200_OK
def test_multiple_success(self): """test retire_users command success with more than one user""" user_names = ["foo", "bar", "baz"] for user_name in user_names: user = UserFactory.create(username=user_name, is_active=True) user.profile.email_optin = True user.profile.save() UserSocialAuthFactory.create(user=user, provider='not_edx') for _ in range(TOTAL_PROGRAMS): ProgramEnrollmentFactory.create(user=user) assert user.is_active is True assert user.profile.email_optin is True assert UserSocialAuth.objects.filter(user=user).count() == 1 assert ProgramEnrollment.objects.filter(user=user).count() == TOTAL_PROGRAMS self.command.handle("retire_users", users=user_names) for user_name in user_names: user = User.objects.get(username=user_name) assert user.is_active is False assert user.profile.email_optin is False assert UserSocialAuth.objects.filter(user=user).count() == 0 assert ProgramEnrollment.objects.filter(user=user).count() == 0
def test_financial_aid_with_application_with_full_profile(self): """ Test that financialAid request serializer works when profile is filled out. """ with mute_signals(post_save): profile = ProfileFactory.create() ProgramEnrollmentFactory.create(user=profile.user, program=self.program) original_currency = 'USD' original_income = 1000.0 serializer = FinancialAidRequestSerializer( data={ 'program_id': self.program.id, 'tier_program': self.min_tier_program, 'date_documents_sent': None, 'original_currency': original_currency, 'original_income': original_income }, context={ 'request': MagicMock(user=profile.user) } ) serializer.is_valid(raise_exception=True) serializer.save() assert serializer.data == { 'original_currency': original_currency, 'original_income': original_income, 'program_id': self.program.id }
def test_course_team_email_unpaid(self): """ Test that an attempt to send an email to the course team of an unpaid course will fail """ self.client.force_login(self.staff_user) new_course = CourseFactory.create(contact_email='*****@*****.**') ProgramEnrollmentFactory.create(user=self.staff_user, program=new_course.program) url = reverse(self.url_name, kwargs={'course_id': new_course.id}) resp = self.client.post(url, data=self.request_data, format='json') assert resp.status_code == status.HTTP_403_FORBIDDEN
def test_bulk_authorize_for_exam_run_multiple(self): """Test that we check all program enrollments""" ProgramEnrollmentFactory.create(program=self.program) exam_run = ExamRunFactory.create(course=self.course_run.course) assert ExamAuthorization.objects.filter( course=exam_run.course, ).count() == 0 bulk_authorize_for_exam_run(exam_run) assert ExamAuthorization.objects.filter( course=exam_run.course, user=self.user ).count() == 1
def test_role_delete(self, role, index_type, mock_on_commit): """ Test that `is_learner` status is restore once role is removed for a user. """ program_enrollment = ProgramEnrollmentFactory.create() assert es.search(index_type)['total'] == DOC_TYPES_PER_ENROLLMENT sources = get_sources(es.search(index_type)) # user is learner assert sources[0]['program']['is_learner'] is True Role.objects.create( user=program_enrollment.user, program=program_enrollment.program, role=role ) assert es.search(index_type)['total'] == DOC_TYPES_PER_ENROLLMENT # user is not learner sources = get_sources(es.search(index_type)) assert sources[0]['program']['is_learner'] is False # when staff role is deleted Role.objects.filter( user=program_enrollment.user, program=program_enrollment.program, role=role ).delete() assert es.search(index_type)['total'] == DOC_TYPES_PER_ENROLLMENT sources = get_sources(es.search(index_type)) # user is learner assert sources[0]['program']['is_learner'] is True
def test_update_during_recreate_index(self): """ If an indexing action happens during a recreate_index it should update all active indices """ conn = get_conn(verify=False) recreate_index() temp_aliases = {} index_types = [PRIVATE_ENROLLMENT_INDEX_TYPE, PUBLIC_ENROLLMENT_INDEX_TYPE] for index_type in index_types: # create temporary index temp_index = make_backing_index_name() temp_alias = make_alias_name(index_type=index_type, is_reindexing=True) clear_and_create_index(temp_index, index_type=index_type) conn.indices.put_alias(index=temp_index, name=temp_alias) temp_aliases[index_type] = temp_alias with patch('search.signals.transaction.on_commit', side_effect=lambda callback: callback()): program_enrollment = ProgramEnrollmentFactory.create() for index_type in index_types: assert_search(es.search(index_type), [program_enrollment], index_type=index_type) # Temp alias should get updated temp_alias = temp_aliases[index_type] refresh_index(temp_alias) temp_hits = conn.search(index=temp_alias)['hits'] assert_search(temp_hits, [program_enrollment], index_type=index_type)
def test_program_enrollment_add(self, index_type, mock_on_commit): """ Test that a newly created ProgramEnrollment is indexed properly """ assert es.search(index_type)['total'] == 0 program_enrollment = ProgramEnrollmentFactory.create() assert_search(es.search(index_type), [program_enrollment], index_type=index_type)
def setUpTestData(cls): cls.program, _ = create_program(past=True) cls.course_run = cls.program.course_set.first().courserun_set.first() cls.course = cls.course_run.course cls.program_enrollment = ProgramEnrollmentFactory.create(program=cls.program) cls.user = cls.program_enrollment.user with mute_signals(post_save): cls.final_grades = sorted([ FinalGradeFactory.create( user=cls.user, course_run=cls.course_run, passed=False, status=FinalGradeStatus.PENDING ), FinalGradeFactory.create( user=cls.user, course_run__course=cls.course, passed=True, status=FinalGradeStatus.COMPLETE ), FinalGradeFactory.create( user=cls.user, course_run__course=cls.course, passed=True, status=FinalGradeStatus.COMPLETE ), ], key=lambda final_grade: final_grade.course_run.end_date, reverse=True)
def test_update_percolate_memberships(self, source_type, is_member, query_matches, mock_on_commit): """ Tests that existing memberships are updated where appropriate """ with mute_signals(post_save): query = PercolateQueryFactory.create(source_type=source_type) profile = ProfileFactory.create(filled_out=True) program_enrollment = ProgramEnrollmentFactory.create(user=profile.user) membership = PercolateQueryMembershipFactory.create( user=profile.user, query=query, is_member=is_member, needs_update=False ) with patch( 'search.api._search_percolate_queries', return_value=[query.id] if query_matches else [] ) as search_percolate_queries_mock: update_percolate_memberships(profile.user, source_type) search_percolate_queries_mock.assert_called_once_with(program_enrollment) membership.refresh_from_db() assert membership.needs_update is (is_member is not query_matches)
def test_document_needs_update_missing(self): """ If a document doesn't exist on Elasticsearch, document_needs_update should return true """ with mute_signals(post_save): enrollment = ProgramEnrollmentFactory.create() assert document_needs_updating(enrollment) is True
def test_program_enrollment_delete(self, index_type, mock_on_commit): """ Test that ProgramEnrollment is removed from index after the user is removed """ program_enrollment = ProgramEnrollmentFactory.create() assert es.search(index_type)['total'] == DOC_TYPES_PER_ENROLLMENT program_enrollment.user.delete() assert es.search(index_type)['total'] == 0
def setUpTestData(cls): super().setUpTestData() with mute_signals(post_save): staff_profile = ProfileFactory.create() cls.staff_user = staff_profile.user cls.course = CourseFactory.create( contact_email='*****@*****.**', program__financial_aid_availability=False ) course_run = CourseRunFactory.create(course=cls.course) ProgramEnrollmentFactory.create(user=cls.staff_user, program=cls.course.program) CachedEnrollmentFactory.create(user=cls.staff_user, course_run=course_run) cls.url_name = 'course_team_mail_api' cls.request_data = { 'email_subject': 'email subject', 'email_body': 'email body' }
def test_remove_program_enrolled_user(self, index_type, mock_on_commit): """ Test that remove_program_enrolled_user removes the user from the index for that program """ program_enrollment = ProgramEnrollmentFactory.create() assert_search(es.search(index_type), [program_enrollment], index_type=index_type) remove_program_enrolled_user(program_enrollment.id) assert_search(es.search(index_type), [], index_type=index_type)
def test_employment_add(self, index_type, mock_on_commit): """ Test that Employment is indexed after being added """ program_enrollment = ProgramEnrollmentFactory.create() assert es.search(index_type)['total'] == DOC_TYPES_PER_ENROLLMENT EmploymentFactory.create(profile=program_enrollment.user.profile, end_date=None) assert_search(es.search(index_type), [program_enrollment], index_type=index_type)
def test_populate_query_inactive_memberships(self, is_active, has_profile, mock_on_commit): """ Tests that memberships are handled correctly for users who are inactive or have no profiles """ with mute_signals(post_save): query = PercolateQueryFactory.create(source_type=PercolateQuery.DISCUSSION_CHANNEL_TYPE) user = UserFactory.create(is_active=is_active) if has_profile: ProfileFactory.create(user=user, filled_out=True) ProgramEnrollmentFactory.create(user=user) with patch('search.api.get_conn') as es_mock: populate_query_memberships(query.id) assert es_mock.return_value.percolate.call_count == (1 if has_profile and is_active else 0) assert PercolateQueryMembership.objects.filter(user=user, query=query).count() == ( 1 if is_active else 0 )
def test_education_delete(self, index_type, mock_on_commit): """ Test that Education is removed from index after being deleted """ program_enrollment = ProgramEnrollmentFactory.create() education = EducationFactory.create(profile=program_enrollment.user.profile) assert_search(es.search(index_type), [program_enrollment], index_type=index_type) education.delete() assert_search(es.search(index_type), [program_enrollment], index_type=index_type)
def test_staff_and_instructor_in_other_program_no_results(self, role, is_enrolled): """A user with staff or instructor role in another program gets no results""" user = UserFactory.create() Role.objects.create( user=user, program=self.program2, role=role, ) if is_enrolled: ProgramEnrollmentFactory.create(user=user, program=self.program1) params = { "post_filter": { "term": {"program.id": self.program1.id} } } self.client.force_login(user) resp = self.assert_status_code(json=params) assert len(resp.data['hits']['hits']) == 0
def test_employment_delete(self, index_type, mock_on_commit): """ Test that Employment is removed from index after being deleted """ program_enrollment = ProgramEnrollmentFactory.create() employment = EmploymentFactory.create(profile=program_enrollment.user.profile, end_date=None) assert_search(es.search(index_type), [program_enrollment], index_type=index_type) employment.delete() assert_search(es.search(index_type), [program_enrollment], index_type=index_type)
def test_past_employment_add(self, index_type, mock_on_commit): """ Test that past work history is not indexed """ program_enrollment = ProgramEnrollmentFactory.create() EmploymentFactory.create(profile=program_enrollment.user.profile, end_date=None) EmploymentFactory.create(profile=program_enrollment.user.profile) search_result = es.search(index_type)['hits'][0]['_source']['profile']['work_history'] assert len(search_result) == 1 self.assertFalse(search_result[0]['end_date'])
def test_education_update(self, index_type, mock_on_commit): """ Test that Education is reindexed after being updated """ program_enrollment = ProgramEnrollmentFactory.create() assert es.search(index_type)['total'] == DOC_TYPES_PER_ENROLLMENT education = EducationFactory.create(profile=program_enrollment.user.profile) education.school_city = 'city' education.save() assert_search(es.search(index_type), [program_enrollment], index_type=index_type)
def test_profile_update(self, index_type, mock_on_commit): """ Test that ProgramEnrollment is reindexed after the User's Profile has been updated """ program_enrollment = ProgramEnrollmentFactory.create() assert es.search(index_type)['total'] == DOC_TYPES_PER_ENROLLMENT profile = program_enrollment.user.profile profile.first_name = 'updated' profile.save() assert_search(es.search(index_type), [program_enrollment], index_type=index_type)
def test_education_update(self): """ Test that Education is reindexed after being updated """ program_enrollment = ProgramEnrollmentFactory.create() assert es.search()['total'] == 1 education = EducationFactory.create( profile=program_enrollment.user.profile) education.school_city = 'city' education.save() assert_search(es.search(), [program_enrollment])
def test_employment_update(self): """ Test that Employment is reindexed after being updated """ program_enrollment = ProgramEnrollmentFactory.create() assert es.search()['total'] == 1 employment = EmploymentFactory.create( profile=program_enrollment.user.profile) employment.city = 'city' employment.save() assert_search(es.search(), [program_enrollment])
def test_populate_query_inactive_memberships(self, is_active, has_profile, mock_on_commit): """ Tests that memberships are handled correctly for users who are inactive or have no profiles """ with mute_signals(post_save): query = PercolateQueryFactory.create( source_type=PercolateQuery.DISCUSSION_CHANNEL_TYPE) user = UserFactory.create(is_active=is_active) if has_profile: ProfileFactory.create(user=user, filled_out=True) ProgramEnrollmentFactory.create(user=user) with patch('search.api.get_conn') as es_mock: populate_query_memberships(query.id) assert es_mock.return_value.percolate.call_count == ( 1 if has_profile and is_active else 0) assert PercolateQueryMembership.objects.filter( user=user, query=query).count() == (1 if is_active else 0)
def test_update_index(self): # pylint: disable=no-self-use """ Test that recreate_index will clear old data and index all profiles """ recreate_index() program_enrollment = ProgramEnrollmentFactory.create() assert_search(es.search(), [program_enrollment]) remove_program_enrolled_user(program_enrollment) assert_search(es.search(), []) # recreate_index should index the program-enrolled user recreate_index() assert_search(es.search(), [program_enrollment])
def test_document_needs_update(self, mocked_on_commit): """ If a document on ES is out of date with the database, document_needs_update should return true """ enrollment = ProgramEnrollmentFactory.create() assert document_needs_updating(enrollment) is False with mute_signals(post_save): enrollment.user.profile.first_name = "Changed" enrollment.user.profile.save() assert document_needs_updating(enrollment) is True
def test_past_employment_add(self, index_type, mock_on_commit): """ Test that past work history is not indexed """ program_enrollment = ProgramEnrollmentFactory.create() EmploymentFactory.create(profile=program_enrollment.user.profile, end_date=None) EmploymentFactory.create(profile=program_enrollment.user.profile) search_result = es.search( index_type)['hits'][0]['_source']['profile']['work_history'] assert len(search_result) == 1 self.assertFalse(search_result[0]['end_date'])
def test_update_index(self, index_type): """ Test that recreate_index will clear old data and index all profiles """ with patch('search.signals.transaction.on_commit', side_effect=lambda callback: callback()): program_enrollment = ProgramEnrollmentFactory.create() assert_search(es.search(index_type), [program_enrollment], index_type=index_type) remove_program_enrolled_user(program_enrollment.id) assert_search(es.search(index_type), [], index_type=index_type) # recreate_index should index the program-enrolled user recreate_index() assert_search(es.search(index_type), [program_enrollment], index_type=index_type)
def test_add_edx_record(self, index_type, mock_on_commit): """ Test that cached edX records are indexed after being added """ program_enrollment = ProgramEnrollmentFactory.create() for edx_cached_model_factory in [CachedCertificateFactory, CachedEnrollmentFactory, CachedCurrentGradeFactory]: assert es.search(index_type)['total'] == DOC_TYPES_PER_ENROLLMENT course = CourseFactory.create(program=program_enrollment.program) course_run = CourseRunFactory.create(course=course) edx_cached_model_factory.create(user=program_enrollment.user, course_run=course_run) index_program_enrolled_users([program_enrollment]) assert_search(es.search(index_type), [program_enrollment], index_type=index_type)
def test_employment_update(self, index_type, mock_on_commit): """ Test that Employment is reindexed after being updated """ program_enrollment = ProgramEnrollmentFactory.create() assert es.search(index_type)['total'] == DOC_TYPES_PER_ENROLLMENT employment = EmploymentFactory.create( profile=program_enrollment.user.profile, end_date=None) employment.city = 'city' employment.save() assert_search(es.search(index_type), [program_enrollment], index_type=index_type)
def test_employment_delete(self, index_type, mock_on_commit): """ Test that Employment is removed from index after being deleted """ program_enrollment = ProgramEnrollmentFactory.create() employment = EmploymentFactory.create( profile=program_enrollment.user.profile, end_date=None) assert_search(es.search(index_type), [program_enrollment], index_type=index_type) employment.delete() assert_search(es.search(index_type), [program_enrollment], index_type=index_type)
def test_education_delete(self, index_type, mock_on_commit): """ Test that Education is removed from index after being deleted """ program_enrollment = ProgramEnrollmentFactory.create() education = EducationFactory.create( profile=program_enrollment.user.profile) assert_search(es.search(index_type), [program_enrollment], index_type=index_type) education.delete() assert_search(es.search(index_type), [program_enrollment], index_type=index_type)
def test_education_update(self, index_type, mock_on_commit): """ Test that Education is reindexed after being updated """ program_enrollment = ProgramEnrollmentFactory.create() assert es.search(index_type)['total'] == DOC_TYPES_PER_ENROLLMENT education = EducationFactory.create( profile=program_enrollment.user.profile) education.school_city = 'city' education.save() assert_search(es.search(index_type), [program_enrollment], index_type=index_type)
def test_percolate_failure_user_unenroll_program(self, mock_on_commit): """ If search_percolate fails we should raise an Exception with some useful information for Sentry Case when there is not program enrollment. """ with mute_signals(post_save): profile = ProfileFactory.create(filled_out=True) program_enrollment = ProgramEnrollmentFactory.create(user=profile.user) program_enrollment_id = program_enrollment.id program_enrollment.delete() with self.assertRaises(ProgramEnrollment.DoesNotExist): search_percolate_queries(program_enrollment_id, "doesnt_matter")
def test_index_users_check_if_changed(self, enrollment1_needs_update, enrollment2_needs_update): """ If check_if_changed is true we should only update documents which need updating """ enrollment1 = ProgramEnrollmentFactory.create() enrollment2 = ProgramEnrollmentFactory.create() needs_update_list = [] if enrollment1_needs_update: needs_update_list.append(enrollment1) if enrollment2_needs_update: needs_update_list.append(enrollment2) def fake_needs_updating(_enrollment): """Fake document_needs_update to conform to test data""" return _enrollment in needs_update_list self.document_needs_updating_mock.side_effect = fake_needs_updating index_users([enrollment1.user.id, enrollment2.user.id], check_if_changed=True) expected_enrollments = [] if enrollment1_needs_update: expected_enrollments.append(enrollment1) if enrollment2_needs_update: expected_enrollments.append(enrollment2) self.document_needs_updating_mock.assert_any_call(enrollment1) self.document_needs_updating_mock.assert_any_call(enrollment2) if len(needs_update_list) > 0: self.index_program_enrolled_users_mock.assert_called_once_with( needs_update_list) for enrollment in needs_update_list: self.send_automatic_emails_mock.assert_any_call(enrollment) self.update_percolate_memberships_mock.assert_any_call( enrollment.user, PercolateQuery.DISCUSSION_CHANNEL_TYPE) else: assert self.index_program_enrolled_users_mock.called is False assert self.send_automatic_emails_mock.called is False
def setUpTestData(cls): super().setUpTestData() with mute_signals(post_save): staff_profile = ProfileFactory.create( user__email='*****@*****.**') recipient_profile = ProfileFactory.create( user__email='*****@*****.**', email_optin=True, ) cls.staff_user = staff_profile.user cls.recipient_user = recipient_profile.user cls.program = ProgramFactory.create(financial_aid_availability=False) ProgramEnrollmentFactory.create(user=cls.recipient_user, program=cls.program) Role.objects.create(user=cls.staff_user, program=cls.program, role=Staff.ROLE_ID) cls.url_name = 'learner_mail_api' cls.request_data = { 'email_subject': 'email subject', 'email_body': 'email body' }
def test_not_analyzed(self): """ At the moment no string fields in the mapping should be 'analyzed' since there's no field supporting full text search. """ program_enrollment = ProgramEnrollmentFactory.create() EducationFactory.create(profile=program_enrollment.user.profile) EmploymentFactory.create(profile=program_enrollment.user.profile) mapping = es.get_mappings() nodes = list(traverse_mapping(mapping)) for node in nodes: if node.get('type') == 'string': assert node['index'] == 'not_analyzed'
def test_financial_aid_with_application_with_no_residence(self): """ Test that financialAid request serializer throws exception when profile is not filled out. """ user = UserFactory.create() assert user.profile.filled_out is False ProgramEnrollmentFactory.create(user=user, program=self.program) serializer = FinancialAidRequestSerializer( data={ 'program_id': self.program.id, 'tier_program': self.min_tier_program, 'date_documents_sent': None, 'original_currency': 'USD', 'original_income': 1000 }, context={'request': MagicMock(user=user)}) with self.assertRaises(ValidationError) as ex: serializer.is_valid(raise_exception=True) serializer.save() assert ex.exception.detail == { 'non_field_errors': ['Profile is not complete'] }
def test_single_success_user_with_email(self): """test retire_users command with email success""" user = UserFactory.create(email='*****@*****.**', is_active=True) user.profile.email_optin = True user.profile.save() UserSocialAuthFactory.create(user=user, provider='not_edx') for _ in range(TOTAL_PROGRAMS): ProgramEnrollmentFactory.create(user=user) assert user.is_active is True assert user.profile.email_optin is True assert UserSocialAuth.objects.filter(user=user).count() == 1 assert ProgramEnrollment.objects.filter(user=user).count() == TOTAL_PROGRAMS self.command.handle("retire_users", users=["*****@*****.**"]) user.refresh_from_db() assert user.is_active is False assert user.profile.email_optin is False assert UserSocialAuth.objects.filter(user=user).count() == 0 assert ProgramEnrollment.objects.filter(user=user).count() == 0
def test_add_edx_record(self): """ Test that cached edX records are indexed after being added """ program_enrollment = ProgramEnrollmentFactory.create() for edx_cached_model_factory in [ CachedCertificateFactory, CachedEnrollmentFactory ]: assert es.search()['total'] == 1 course_run = CourseRunFactory.create( program=program_enrollment.program) edx_cached_model_factory.create(user=program_enrollment.user, course_run=course_run) assert_search(es.search(), [program_enrollment])
def setUpTestData(cls): cls.program, _ = create_program(past=True) cls.course_run = cls.program.course_set.first().courserun_set.first() cls.program_enrollment = ProgramEnrollmentFactory.create(program=cls.program) cls.user = cls.program_enrollment.user create_order(cls.user, cls.course_run) with mute_signals(post_save): CachedEnrollmentFactory.create(user=cls.user, course_run=cls.course_run) cls.final_grade = FinalGradeFactory.create( user=cls.user, course_run=cls.course_run, passed=True, course_run_paid_on_edx=False, )
def test_delete_edx_record(self, index_type, mock_on_commit): """ Test that a cached edX record is removed from index after being deleted """ program_enrollment = ProgramEnrollmentFactory.create() for edx_cached_model_factory in [CachedCertificateFactory, CachedEnrollmentFactory, CachedCurrentGradeFactory]: course = CourseFactory.create(program=program_enrollment.program) course_run = CourseRunFactory.create(course=course) edx_record = edx_cached_model_factory.create(user=program_enrollment.user, course_run=course_run) index_program_enrolled_users([program_enrollment]) assert_search(es.search(index_type), [program_enrollment], index_type=index_type) edx_record.delete() index_program_enrolled_users([program_enrollment]) assert_search(es.search(index_type), [program_enrollment], index_type=index_type)
def test_filled_out(self): """ Search results should only include profiles which are filled out """ program = self.program1 filled_out_ids = list(ProgramEnrollment.objects.filter(program=program).values_list('user_id', flat=True)) enrollment_not_filled_out = ProgramEnrollmentFactory.create( user__profile__filled_out=False, program=program, ) resp = self.assert_status_code() user_ids_in_hits = self.get_user_ids_in_hits(resp.data['hits']['hits']) assert sorted(user_ids_in_hits) == sorted(filled_out_ids) assert enrollment_not_filled_out.user.id not in user_ids_in_hits
def test_delete_edx_record(self): """ Test that a cached edX record is removed from index after being deleted """ program_enrollment = ProgramEnrollmentFactory.create() for edx_cached_model_factory in [ CachedCertificateFactory, CachedEnrollmentFactory ]: course_run = CourseRunFactory.create( program=program_enrollment.program) edx_record = edx_cached_model_factory.create( user=program_enrollment.user, course_run=course_run) assert_search(es.search(), [program_enrollment]) edx_record.delete() assert_search(es.search(), [program_enrollment])
def test_index_program_enrolled_users(self): """ When we run the index_program_enrolled_users task we should index them and send them automatic emails """ enrollments = [ProgramEnrollmentFactory.create() for _ in range(2)] enrollment_ids = [enrollment.id for enrollment in enrollments] index_program_enrolled_users(enrollment_ids) assert list( self.index_program_enrolled_users_mock.call_args[0][0].values_list( 'id', flat=True)) == enrollment_ids for enrollment in enrollments: self.send_automatic_emails_mock.assert_any_call(enrollment) self.update_percolate_memberships_mock.assert_any_call( enrollment.user, PercolateQuery.DISCUSSION_CHANNEL_TYPE) self.refresh_index_mock.assert_called_with()
def test_update_edx_record(self): """ Test that a cached edX record is reindexed after being updated """ program_enrollment = ProgramEnrollmentFactory.create() for edx_cached_model_factory in [ CachedCertificateFactory, CachedEnrollmentFactory ]: assert es.search()['total'] == 1 course_run = CourseRunFactory.create( program=program_enrollment.program) edx_record = edx_cached_model_factory.create( user=program_enrollment.user, course_run=course_run) edx_record.data.update({'new': 'data'}) edx_record.save() assert_search(es.search(), [program_enrollment])
def test_program_record(client): """Test that a request for program record results in 200""" enrollment = ProgramEnrollmentFactory.create() resp = client.get( reverse("grade_records", kwargs=dict(record_hash=enrollment.hash))) assert resp.status_code == status.HTTP_200_OK assert is_subset_dict( { 'record_hash': enrollment.hash, 'program_title': enrollment.program.title, 'program_status': 'partially', 'profile': { 'username': enrollment.user.username }, 'last_updated': '' }, resp.context_data)
def test_analyzed(self, mock_on_commit): """ Most string fields in the mapping should be 'analyzed' since we don't want to tokenize strings arbitrarily when filtering on fields. """ program_enrollment = ProgramEnrollmentFactory.create() EducationFactory.create(profile=program_enrollment.user.profile) EmploymentFactory.create(profile=program_enrollment.user.profile) for index_type in ALL_INDEX_TYPES: mapping = es.get_mappings(index_type) nodes = list(traverse_mapping(mapping, "")) for key, node in nodes: if key == "folded": assert node['analyzer'] == "folding" elif node.get('type') == 'string': assert node['index'] == 'not_analyzed'
def test_add_edx_record(self, index_type, mock_on_commit): """ Test that cached edX records are indexed after being added """ program_enrollment = ProgramEnrollmentFactory.create() for edx_cached_model_factory in [ CachedCertificateFactory, CachedEnrollmentFactory, CachedCurrentGradeFactory ]: assert es.search(index_type)['total'] == DOC_TYPES_PER_ENROLLMENT course = CourseFactory.create(program=program_enrollment.program) course_run = CourseRunFactory.create(course=course) edx_cached_model_factory.create(user=program_enrollment.user, course_run=course_run) index_program_enrolled_users([program_enrollment]) assert_search(es.search(index_type), [program_enrollment], index_type=index_type)
def test_role_add(self, role, index_type, mock_on_commit): """ Test that `is_learner` status is change when role is save """ program_enrollment = ProgramEnrollmentFactory.create() assert es.search(index_type)['total'] == DOC_TYPES_PER_ENROLLMENT sources = get_sources(es.search(index_type)) # user is learner assert sources[0]['program']['is_learner'] is True Role.objects.create(user=program_enrollment.user, program=program_enrollment.program, role=role) assert es.search(index_type)['total'] == DOC_TYPES_PER_ENROLLMENT # user is not learner sources = get_sources(es.search(index_type)) assert sources[0]['program']['is_learner'] is False
def test_program_record(client): """Test that a request for program record results in 200""" user = UserFactory.create() enrollment = ProgramEnrollmentFactory.create(user=user) client.force_login(user) resp = client.get( reverse("grade_records", kwargs=dict(enrollment_id=enrollment.id))) assert resp.status_code == status.HTTP_200_OK assert is_subset_dict( { 'is_public': False, 'is_owner': True, 'program_title': enrollment.program.title, 'program_status': 'partially', 'profile': { 'username': enrollment.user.username } }, resp.context_data)
def test_delete_edx_record(self, index_type, mock_on_commit): """ Test that a cached edX record is removed from index after being deleted """ program_enrollment = ProgramEnrollmentFactory.create() for edx_cached_model_factory in [ CachedCertificateFactory, CachedEnrollmentFactory, CachedCurrentGradeFactory ]: course = CourseFactory.create(program=program_enrollment.program) course_run = CourseRunFactory.create(course=course) edx_record = edx_cached_model_factory.create( user=program_enrollment.user, course_run=course_run) index_program_enrolled_users([program_enrollment]) assert_search(es.search(index_type), [program_enrollment], index_type=index_type) edx_record.delete() index_program_enrolled_users([program_enrollment]) assert_search(es.search(index_type), [program_enrollment], index_type=index_type)
def test_search_percolate_queries(self, mock_on_commit): """search_percolate_queries should find all PercolateQuery which match the given ProgramEnrollment""" with mute_signals(post_save): profile = ProfileFactory.create(filled_out=True) program_enrollment = ProgramEnrollmentFactory.create(user=profile.user) matching_query = { "query": { "match": { "profile.first_name": profile.first_name, } } } query = PercolateQuery.objects.create( query=matching_query, original_query={}, source_type=PercolateQuery.AUTOMATIC_EMAIL_TYPE, ) # Another query which matches but has a different source_type PercolateQuery.objects.create( query=matching_query, original_query={}, source_type=PercolateQuery.DISCUSSION_CHANNEL_TYPE, ) # Another query that doesn't match PercolateQuery.objects.create( query={"query": { "match": { "profile.first_name": "missing", } }}, original_query={}, source_type=PercolateQuery.AUTOMATIC_EMAIL_TYPE) # Only the first appears in the results assert list( search_percolate_queries( program_enrollment.id, PercolateQuery.AUTOMATIC_EMAIL_TYPE, ).values_list("id", flat=True)) == [query.id]