def test_test_entry_review_verify_control_migrations(self): migration_file = importlib.import_module('entry.migrations.0031_entry-migrate-verify-to-review-comment') # 3 normal users + Additional non-active user user1, user2, user3, _ = UserFactory.create_batch(4) af = AnalysisFrameworkFactory.create() project = ProjectFactory.create(analysis_framework=af) lead = LeadFactory.create(project=project) # Create entry before data migrate EntryFactory.create(lead=lead, controlled=True, controlled_changed_by=user1) EntryFactory.create(lead=lead, controlled=True, controlled_changed_by=user2) EntryFactory.create(lead=lead, controlled=False, controlled_changed_by=user3) EntryFactory.create(lead=lead, controlled=True, controlled_changed_by=None) EntryFactory.create(lead=lead, controlled=False, controlled_changed_by=None) # Apply the migration logic migration_file.migrate_entry_controlled_to_review_comment_(Entry, EntryReviewComment) assert Entry.objects.count() == 5 # 2 verified review comment are created and 1 unverified review comment is created assert EntryReviewComment.objects.count() == 3 # Related review comment are created by user last action on entry. assert set(EntryReviewComment.objects.values_list('created_by_id', flat=True)) == set([user1.pk, user2.pk, user3.pk]) assert EntryReviewComment.objects.filter(comment_type=EntryReviewComment.CommentType.VERIFY).count() == 2 assert EntryReviewComment.objects.filter(comment_type=EntryReviewComment.CommentType.UNVERIFY).count() == 1 assert set( EntryReviewComment.objects.filter( comment_type=EntryReviewComment.CommentType.VERIFY, ).values_list('created_by_id', flat=True) ) == set([user1.pk, user2.pk]) assert set( EntryReviewComment.objects.filter( comment_type=EntryReviewComment.CommentType.UNVERIFY, ).values_list('created_by_id', flat=True) ) == set([user3.pk]) # All controlled, controlled_changed_by should be reset. assert Entry.objects.filter(controlled=True).count() == 0 assert Entry.objects.filter(controlled_changed_by__isnull=False).count() == 0
def test_create_assignment_create_on_entry_review_comment( self, get_user_mocked_func): af = AnalysisFrameworkFactory.create() project = ProjectFactory.create(analysis_framework=af) user1, user2 = UserFactory.create_batch(2) get_user_mocked_func.return_value = user2 entry = EntryFactory.create(lead=LeadFactory.create(project=project)) old_assignment_count = Assignment.objects.count() entry_review_comment = EntryReviewCommentFactory.create( entry=entry, entry_comment=None, created_by=user1) new_assignment_count = Assignment.objects.count() self.assertEqual(old_assignment_count, new_assignment_count) entry_review_comment.mentioned_users.add(user1) new_assignment_count = Assignment.objects.count() self.assertEqual(old_assignment_count + 1, new_assignment_count) # try to change the assigne for the entry_review_comment and test for the change in assignment entry_review_comment.mentioned_users.remove(user1) entry_review_comment.mentioned_users.add(user2) self.assertEqual(old_assignment_count + 1, new_assignment_count) assignment = Assignment.objects.get( entry_review_comment__id=entry_review_comment.id) self.assertEqual(assignment.created_for, user2) # should represent the new user2 # try to add another user and remove both from assignee entry_review_comment.mentioned_users.add(user1) new_assignment_count = Assignment.objects.count() self.assertEqual(old_assignment_count + 2, new_assignment_count) # try to get the assignment for user entry_review_comment.mentioned_users.add(user1, user2) assignment = Assignment.get_for(user1) assert assignment.count() == 1 # for only the user assert get_user_mocked_func.called
def test_review_comments_query(self): query = ''' query MyQuery ($projectId: ID! $entryId: ID!) { project(id: $projectId) { entry (id: $entryId) { id verifiedBy { displayName id } controlled controlledChangedBy { id displayName } reviewCommentsCount } reviewComments (entry: $entryId, ordering: DESC_ID) { totalCount results { id text commentType createdAt mentionedUsers { displayName id } } } } } ''' user = UserFactory.create() user2, user3 = UserFactory.create_batch(2) analysis_framework = AnalysisFrameworkFactory.create() project = ProjectFactory.create(analysis_framework=analysis_framework) lead = LeadFactory.create(project=project) entry = EntryFactory.create(project=project, analysis_framework=analysis_framework, lead=lead, controlled=True, controlled_changed_by=user2, verified_by=[user2, user3]) entry1 = EntryFactory.create( project=project, analysis_framework=analysis_framework, lead=lead, ) review_comment1, review_comment2 = EntryReviewCommentFactory.create_batch( 2, entry=entry, created_by=user) EntryReviewCommentFactory.create(entry=entry1, created_by=user) review_text1 = EntryReviewCommentTextFactory.create( comment=review_comment1) # -- Without login self.query_check(query, assert_for_error=True, variables={ 'projectId': project.id, 'entryId': entry.id }) # -- With login self.force_login(user) # --- non-member user content = self.query_check(query, variables={ 'projectId': project.id, 'entryId': entry.id }) self.assertEqual(content['data']['project']['entry'], None, content) # --- add-member in project project.add_member(user) content = self.query_check(query, variables={ 'projectId': project.id, 'entryId': entry.id }) self.assertEqual( content['data']['project']['entry']['reviewCommentsCount'], 2, content) self.assertEqual( content['data']['project']['reviewComments']['totalCount'], 2, content) self.assertListIds( content['data']['project']['reviewComments']['results'], [review_comment1, review_comment2], content) self.assertEqual( content['data']['project']['reviewComments']['results'][1]['text'], review_text1.text, content) # add another review_text for same review_comment review_text2 = EntryReviewCommentTextFactory.create( comment=review_comment1) content = self.query_check(query, variables={ 'projectId': project.id, 'entryId': entry.id }) self.assertEqual( content['data']['project']['entry']['reviewCommentsCount'], 2, content) self.assertEqual( content['data']['project']['reviewComments']['results'][1]['text'], review_text2.text, # here latest text should be present content) # lets check for the contolled in entry self.assertEqual(content['data']['project']['entry']['controlled'], True, content) self.assertEqual( content['data']['project']['entry']['controlledChangedBy']['id'], str(user2.id), content) self.assertEqual( len(content['data']['project']['entry']['verifiedBy']), 2, content) # lets query for another entry content = self.query_check(query, variables={ 'projectId': project.id, 'entryId': entry1.id }) self.assertEqual( content['data']['project']['entry']['reviewCommentsCount'], 1, content) self.assertEqual( content['data']['project']['reviewComments']['totalCount'], 1, content)
def test_project(self): query = ''' query MyQuery ($id: ID!, $user_search: String, $usergroup_search: String) { project(id: $id) { userMembers(search: $user_search) { totalCount results { member { id displayName } role { id level title } } } userGroupMembers(search: $usergroup_search) { totalCount results { id usergroup { id title } role { id level title } badges } } } } ''' user, user1, user2, user3, _ = UserFactory.create_batch( 5, first_name='Ram') usergroup1, usergroup2, _ = UserGroupFactory.create_batch( 3, title='UserGroup YYY') usergroup4 = UserGroupFactory.create(title='UserGroup ZZZ') user5 = UserFactory.create(first_name='Nam') project = ProjectFactory.create() # Add user to project1 only (one normal + one private) project.add_member(user) project.add_member(user1) project.add_member(user2) project.add_member(user3) project.add_member(user5) for usergroup in [usergroup1, usergroup2, usergroup4]: ProjectUserGroupMembership.objects.create(project=project, usergroup=usergroup) # -- With login self.force_login(user) # project without membership content = self.query_check(query, variables={ 'id': project.id, 'user_search': user.first_name }) self.assertEqual( content['data']['project']['userMembers']['totalCount'], 4, content) self.assertEqual( len(content['data']['project']['userMembers']['results']), 4, content) self.assertEqual( content['data']['project']['userGroupMembers']['totalCount'], 3, content) self.assertEqual( len(content['data']['project']['userGroupMembers']['results']), 3, content) # project without membership content = self.query_check(query, variables={ 'id': project.id, 'usergroup_search': usergroup1.title }) self.assertEqual( content['data']['project']['userGroupMembers']['totalCount'], 2, content) self.assertEqual( len(content['data']['project']['userGroupMembers']['results']), 2, content) self.assertEqual( content['data']['project']['userMembers']['totalCount'], 5, content) self.assertEqual( len(content['data']['project']['userMembers']['results']), 5, content)
def test_project_query(self): """ Test private + non-private project behaviour """ query = ''' query MyQuery ($id: ID!) { project(id: $id) { id title currentUserRole startDate status isVisualizationEnabled isPrivate endDate description data stats { entriesActivity { count date } numberOfLeads numberOfLeadsNotTagged numberOfLeadsInProgress numberOfLeadsTagged numberOfEntries numberOfEntriesVerified numberOfEntriesControlled numberOfUsers leadsActivity { count date } } membershipPending isRejected regions { id title } } } ''' user = UserFactory.create() analysis_framework = AnalysisFrameworkFactory.create() public_project, public_project2, public_project3, public_project4 = ProjectFactory.create_batch( 4, analysis_framework=analysis_framework) now = timezone.now() lead1_1 = self.update_obj(LeadFactory.create(project=public_project), created_at=now + relativedelta(months=-1)) lead1_2 = self.update_obj(LeadFactory.create(project=public_project), created_at=now + relativedelta(months=-2)) lead1_3 = self.update_obj(LeadFactory.create(project=public_project), created_at=now + relativedelta(months=-2)) lead1_4 = self.update_obj(LeadFactory.create(project=public_project), created_at=now + relativedelta(months=-1)) self.update_obj(LeadFactory.create(project=public_project), created_at=now + relativedelta(months=-1)) data = [ { "lead": lead1_1, "controlled": False, "months": -1, }, { "lead": lead1_1, "controlled": False, "months": -3, }, { "lead": lead1_2, "controlled": True, "months": -3, }, { "lead": lead1_2, "controlled": False, "months": -2, }, { "lead": lead1_2, "controlled": True, "months": -2, }, { "lead": lead1_3, "controlled": True, "months": -3, }, { "lead": lead1_3, "controlled": True, "months": -3, }, ] now = timezone.now() for item in data: self.update_obj( EntryFactory.create(lead=item['lead'], controlled=item['controlled'], project=public_project, analysis_framework=analysis_framework), created_at=now + relativedelta(months=item['months'])) EntryFactory.create(lead=lead1_3, project=public_project, controlled=True, analysis_framework=analysis_framework) EntryFactory.create(lead=lead1_4, project=public_project, controlled=True, analysis_framework=analysis_framework) lead2 = LeadFactory.create(project=public_project2) lead3 = LeadFactory.create(project=public_project3) EntryFactory.create(lead=lead2, project=public_project2, controlled=False, analysis_framework=analysis_framework) EntryFactory.create(lead=lead3, project=public_project3, controlled=False, analysis_framework=analysis_framework) user2, user3, request_user, non_member_user = UserFactory.create_batch( 4) public_project = ProjectFactory.create( analysis_framework=analysis_framework) private_project = ProjectFactory.create( is_private=True, analysis_framework=analysis_framework) ProjectJoinRequestFactory.create(project=public_project, requested_by=request_user, status='pending', role=self.project_role_admin) # create projectJoinRequest(status='rejected') ProjectJoinRequestFactory.create(project=public_project4, requested_by=request_user, status='rejected', role=self.project_role_admin) # add some project member public_project.add_member(user) public_project.add_member(user2) public_project.add_member(user3) # add some lead for the project lead = LeadFactory.create(project=public_project) lead2 = LeadFactory.create(project=public_project) LeadFactory.create_batch(3, project=public_project) LeadFactory.create(project=private_project) # add some entry for the project EntryFactory.create_batch(4, project=public_project, analysis_framework=analysis_framework, lead=lead) entry2_1 = EntryFactory.create(project=public_project, analysis_framework=analysis_framework, lead=lead2, controlled=True) entry2_2 = EntryFactory.create(project=public_project, analysis_framework=analysis_framework, lead=lead2) EntryFactory.create(project=private_project, analysis_framework=analysis_framework, lead=lead) # Verify entries entry2_1.verified_by.add(user) entry2_1.verified_by.add(user3) entry2_2.verified_by.add(user) # NOTE: Right noe only IN_PROGRESS status is set automatically # Control one lead lead2.status = Lead.Status.TAGGED lead2.save(update_fields=('status', )) # lets add some regions to project region1, region2, region3 = RegionFactory.create_batch(3) public_project.regions.add(region1) public_project.regions.add(region2) private_project.regions.add(region3) # Generate project cache _generate_project_stats_cache() # -- Without login self.query_check(query, assert_for_error=True, variables={'id': public_project.id}) self.query_check(query, assert_for_error=True, variables={'id': private_project.id}) # -- With login self.force_login(user) # --- non-member user content = self.query_check(query, variables={'id': public_project.id}) self.assertNotEqual(content['data']['project'], None, content) content = self.query_check(query, variables={'id': private_project.id}) self.assertEqual(content['data']['project'], None, content) # login with non_member self.force_login(non_member_user) content = self.query_check(query, variables={'id': public_project.id}) self.assertNotEqual(content['data']['project'], None, content) self.assertEqual(content['data']['project']['membershipPending'], False) # login with request_user self.force_login(request_user) content = self.query_check(query, variables={'id': public_project4.id}) self.assertNotEqual(content['data']['project'], None, content) self.assertEqual(content['data']['project']['isRejected'], True) # --- member user # ---- (public-project) self.force_login(user) content = self.query_check(query, variables={'id': public_project.id}) self.assertNotEqual(content['data']['project'], None, content) self.assertEqual(content['data']['project']['stats']['numberOfLeads'], 5, content) self.assertEqual( content['data']['project']['stats']['numberOfLeadsNotTagged'], 3, content) self.assertEqual( content['data']['project']['stats']['numberOfLeadsInProgress'], 1, content) self.assertEqual( content['data']['project']['stats']['numberOfLeadsTagged'], 1, content) self.assertEqual( content['data']['project']['stats']['numberOfEntries'], 6, content) self.assertEqual( content['data']['project']['stats']['numberOfEntriesVerified'], 2, content) self.assertEqual( content['data']['project']['stats']['numberOfEntriesControlled'], 1, content) self.assertEqual(content['data']['project']['stats']['numberOfUsers'], 3, content) self.assertEqual( len(content['data']['project']['stats']['leadsActivity']), 1, content) self.assertEqual( len(content['data']['project']['stats']['entriesActivity']), 1, content) self.assertEqual(len(content['data']['project']['regions']), 2, content) self.assertListIds(content['data']['project']['regions'], [region1, region2], content) # login with request user self.force_login(request_user) content = self.query_check(query, variables={'id': public_project.id}) self.assertNotEqual(content['data']['project'], None, content) self.assertEqual(content['data']['project']['membershipPending'], True) # ---- (private-project) self.force_login(user) private_project.add_member(user) content = self.query_check(query, variables={'id': private_project.id}) self.assertNotEqual(content['data']['project'], None, content) self.assertEqual(len(content['data']['project']['regions']), 1, content) self.assertListIds(content['data']['project']['regions'], [region3], content)
def test_snapshot(self): query = ''' query MyQuery { projectExploreStats { totalProjects totalUsers leadsAddedWeekly dailyAverageLeadsTaggedPerProject generatedExportsMonthly topActiveProjects { projectId projectTitle analysisFrameworkId analysisFrameworkTitle } calculatedAt } } ''' def _cache_clear(): cache.delete( CacheKey.PROJECT_EXPLORE_STATS_LOADER_KEY) # Delete cache user = UserFactory.create() # -- With login self.force_login(user) _cache_clear() previous_content = content = self.query_check(query) self.assertMatchSnapshot(content, 'no-data') UserFactory.create_batch(3, is_active=False) # Some Inactive users analysis_framework = AnalysisFrameworkFactory.create() projects = ProjectFactory.create_batch(3) projects_with_af = ProjectFactory.create_batch( 3, analysis_framework=analysis_framework) # This shouldn't show in top projects but leads/entries count should private_project = ProjectFactory.create( title='Private Project', is_private=True, analysis_framework=analysis_framework) now = timezone.now() # Generate project cache _generate_project_stats_cache() content = self.query_check(query) self.assertEqual(content, previous_content) # Test for cache _cache_clear() previous_content = content = self.query_check( query) # Pull latest data self.assertMatchSnapshot(content, 'only-project') self.update_obj(LeadFactory.create(project=projects[0]), created_at=now + relativedelta(weeks=-1)) self.update_obj(LeadFactory.create(project=projects[0]), created_at=now + relativedelta(weeks=-1)) self.update_obj(LeadFactory.create(project=projects[1]), created_at=now + relativedelta(weeks=-2)) self.update_obj(LeadFactory.create(project=projects[1]), created_at=now + relativedelta(weeks=-1)) self.update_obj(LeadFactory.create(project=projects[1]), created_at=now + relativedelta(weeks=-1)) self.update_obj(LeadFactory.create(project=projects[2]), created_at=now + relativedelta(weeks=-2)) lead0_1 = self.update_obj( LeadFactory.create(project=projects_with_af[0]), created_at=now + relativedelta(weeks=-1)) lead1_1 = self.update_obj( LeadFactory.create(project=projects_with_af[1]), created_at=now + relativedelta(weeks=-2)) lead1_2 = self.update_obj( LeadFactory.create(project=projects_with_af[1]), created_at=now + relativedelta(weeks=-1)) plead1_1 = self.update_obj(LeadFactory.create(project=private_project), created_at=now + relativedelta(weeks=-2)) plead1_2 = self.update_obj(LeadFactory.create(project=private_project), created_at=now + relativedelta(weeks=-1)) self.update_obj(LeadFactory.create(project=projects_with_af[1]), created_at=now + relativedelta(weeks=-1)) self.update_obj(LeadFactory.create(project=projects_with_af[2]), created_at=now + relativedelta(weeks=-3)) self.update_obj(EntryFactory.create(lead=lead0_1), created_at=now + relativedelta(weeks=-1)) self.update_obj(EntryFactory.create(lead=lead1_1), created_at=now + relativedelta(weeks=-1)) self.update_obj(EntryFactory.create(lead=lead1_2), created_at=now + relativedelta(weeks=-1)) self.update_obj(EntryFactory.create(lead=plead1_1), created_at=now + relativedelta(weeks=-1)) self.update_obj(EntryFactory.create(lead=plead1_2), created_at=now + relativedelta(weeks=-1)) # Generate project cache _generate_project_stats_cache() self.update_obj(ExportFactory.create(project=projects_with_af[0], exported_by=user), exported_at=now + relativedelta(months=-1)) self.update_obj(ExportFactory.create(project=projects_with_af[0], exported_by=user), exported_at=now + relativedelta(months=-1)) self.update_obj(ExportFactory.create(project=projects_with_af[0], exported_by=user), exported_at=now + relativedelta(months=-2)) self.update_obj(ExportFactory.create(project=projects_with_af[1], exported_by=user), exported_at=now + relativedelta(months=-2)) self.update_obj(ExportFactory.create(project=projects_with_af[2], exported_by=user), exported_at=now + relativedelta(months=-3)) self.update_obj(ExportFactory.create(project=private_project, exported_by=user), exported_at=now + relativedelta(months=-1)) content = self.query_check(query) self.assertEqual(content, previous_content) # Test for cache _cache_clear() previous_content = content = self.query_check( query) # Pull latest data self.assertMatchSnapshot(content, 'with-data')
def test_user_filters(self): query = ''' query UserQuery($membersExcludeFramework: ID, $membersExcludeProject: ID, $search: String) { users( membersExcludeFramework: $membersExcludeFramework, membersExcludeProject: $membersExcludeProject, search: $search ) { results { organization lastName language isActive id firstName displayPictureUrl displayName } page pageSize } } ''' project1, project2 = ProjectFactory.create_batch(2) af1, af2 = AnalysisFrameworkFactory.create_batch(2) user = UserFactory.create(first_name='Normal Guy') user1, user2, user3 = UserFactory.create_batch(3) project1.add_member(user1) project1.add_member(user2) project2.add_member(user2) project2.add_member(user) af1.add_member(user1) af1.add_member(user2) af1.add_member(user) af2.add_member(user2) def _query_check(filters, **kwargs): return self.query_check(query, variables=filters, **kwargs) # Without authentication ----- content = _query_check({}, assert_for_error=True) # With authentication ----- self.force_login(user) # Without any filters for name, filters, count, users in ( ('no-filter', dict(), 4, [user, user1, user2, user3]), ('exclude-project-1', dict(membersExcludeProject=project1.pk), 2, [user, user3]), ('exclude-project-2', dict(membersExcludeProject=project2.pk), 2, [user1, user3]), ('exclude-af-1', dict(membersExcludeFramework=af1.pk), 1, [user3]), ('exclude-af-2', dict(membersExcludeFramework=af2.pk), 3, [user, user1, user3]), ('search', dict(search='Guy'), 1, [user]), ): content = _query_check(filters)['data']['users']['results'] self.assertEqual(len(content), count, (name, content)) self.assertListIds(content, users, (name, content))
def _user_membership_bulk(self, user_role): query = ''' mutation MyMutation( $id: ID!, $projectMembership: [BulkProjectMembershipInputType!], $projectMembershipDelete: [ID!]! ) { project(id: $id) { id title projectUserMembershipBulk(items: $projectMembership, deleteIds: $projectMembershipDelete) { errors result { id clientId joinedAt addedBy { id displayName } role { id title } member { id displayName } badges } deletedResult { id clientId joinedAt member { id displayName } role { id title level } addedBy { id displayName } badges } } } } ''' creater_user = UserFactory.create() user = UserFactory.create() low_permission_user = UserFactory.create() non_member_user = UserFactory.create() ( member_user0, member_user1, member_user2, member_user3, member_user4, member_user5, member_user6, member_user7, ) = UserFactory.create_batch(8) project = ProjectFactory.create(created_by=creater_user) user_group = UserGroupFactory.create(title='Group-1') membership1 = project.add_member(member_user1, badges=[ProjectMembership.BadgeType.QA]) membership2 = project.add_member(member_user2) membership_using_user_group = project.add_member(member_user7, linked_group=user_group) project.add_member(member_user5) creater_user_membership = project.add_member(creater_user, role=self.project_role_owner) another_clairvoyant_user = project.add_member(member_user0, role=self.project_role_owner) user_membership = project.add_member(user, role=user_role) project.add_member(low_permission_user) minput = dict( projectMembershipDelete=[ str(membership1.pk), # This will be only on try 1 # This shouldn't be on any response (requester + creater) str(user_membership.pk), str(creater_user_membership.pk), str(another_clairvoyant_user.pk), ], projectMembership=[ # Try updating membership (Valid on try 1, invalid on try 2) dict( member=member_user2.pk, clientId="member-user-2", role=self.project_role_owner.pk, id=membership2.pk, badges=[self.genum(ProjectMembership.BadgeType.QA)], ), # Try adding already existing member dict( member=member_user5.pk, clientId="member-user-5", role=self.project_role_member.pk, ), # Try adding new member (Valid on try 1, invalid on try 2) dict( member=member_user3.pk, clientId="member-user-3", role=self.project_role_member.pk, ), # Try adding new member (without giving role) -> this should use default role # Valid on try 1, invalid on try 2 dict( member=member_user4.pk, clientId="member-user-4", ), dict( id=membership_using_user_group.pk, member=member_user7.pk, clientId="member-user-2-with-user-group", role=self.project_role_member.pk, badges=[self.genum(ProjectMembership.BadgeType.QA)], ) ], ) def _query_check(**kwargs): return self.query_check( query, mnested=['project'], variables={'id': project.id, **minput}, **kwargs, ) # ---------- Without login _query_check(assert_for_error=True) # ---------- With login (with non-member) self.force_login(non_member_user) _query_check(assert_for_error=True) # ---------- With login (with low-permission member) self.force_login(low_permission_user) _query_check(assert_for_error=True) # ---------- With login (with higher permission) self.force_login(user) # ----------------- Some Invalid input response = _query_check()['data']['project']['projectUserMembershipBulk'] self.assertMatchSnapshot(response, 'try 1') # ----------------- Another try minput['projectMembership'].pop(1) minput['projectMembership'].extend([ # Invalid (changing member) dict( member=member_user6.pk, clientId="member-user-2", role=self.project_role_owner.pk, id=membership2.pk, ), dict( member=member_user2.pk, clientId="member-user-2", role=self.project_role_admin.pk, id=membership2.pk, ), ]) response = _query_check()['data']['project']['projectUserMembershipBulk'] self.assertMatchSnapshot(response, 'try 2')