diff --git a/apps/assessment_registry/factories.py b/apps/assessment_registry/factories.py index d0d00c6107..f2dbc0d991 100644 --- a/apps/assessment_registry/factories.py +++ b/apps/assessment_registry/factories.py @@ -10,6 +10,7 @@ Question, Answer, AssessmentRegistry, + AssessmentRegistryOrganization, MethodologyAttribute, AdditionalDocument, ScoreRating, @@ -215,3 +216,10 @@ def bg_countries(self, create, extracted, **_): self.bg_countries.add( # pyright: ignore [reportGeneralTypeIssues] country ) + + +class AssessmentRegistryOrganizationFactory(DjangoModelFactory): + organization_type = fuzzy.FuzzyChoice(_choices(AssessmentRegistryOrganization.Type)) + + class Meta: + model = AssessmentRegistryOrganization diff --git a/apps/assessment_registry/tests/snapshots/snap_test_mutation.py b/apps/assessment_registry/tests/snapshots/snap_test_mutation.py index 9a35b862f0..8aac709a69 100644 --- a/apps/assessment_registry/tests/snapshots/snap_test_mutation.py +++ b/apps/assessment_registry/tests/snapshots/snap_test_mutation.py @@ -7,101 +7,72 @@ snapshots = Snapshot() -snapshots['TestAnalysisMutationSnapShotTestCase::test_assessment_registry_update error'] = { +snapshots['TestAssessmentRegistryMutationSnapShotTestCase::test_assessment_registry_update error'] = { 'data': { 'project': { 'updateAssessmentRegistry': { - 'errors': None, - 'ok': True, - 'result': { - 'additionalDocumentComplete': True, - 'additionalDocuments': [ - ], - 'affectedGroups': [ - 'ALL_AFFECTED' - ], - 'bgCountries': [ - { - 'id': '1' - } - ], - 'bgCrisisStartDate': '2019-07-03', - 'bgCrisisType': 'LANDSLIDE', - 'bgPreparedness': 'WITHOUT_PREPAREDNESS', - 'cna': [ - ], - 'cnaComplete': True, - 'confidentiality': 'CONFIDENTIAL', - 'confidentialityDisplay': 'Confidential', - 'coordinatedJoint': 'HARMONIZED', - 'coordinatedJointDisplay': 'Coordinated - Harmonized', - 'costEstimatesUsd': 0, - 'createdAt': '2021-01-01T00:00:00.123456+00:00', - 'dataCollectionEndDate': '2020-09-06', - 'dataCollectionStartDate': '2021-06-21', - 'dataCollectionTechniques': '''Current hear claim well two truth out major. Upon these story film. Drive note bad rule. -She campaign little near enter their institution. Up sense ready require human.''', - 'detailsType': 'MONITORING', - 'detailsTypeDisplay': 'Monitoring', - 'externalSupport': 'NO_EXTERNAL_SUPPORT_RECEIVED', - 'externalSupportDisplay': 'No external support received', - 'family': 'HUMANITARIAN_NEEDS_OVERVIEW', - 'familyDisplay': 'Humanitarian Needs Overview (HNO)', - 'focusComplete': True, - 'focuses': [ - 'CONTEXT', - 'HUMANITERIAN_ACCESS', - 'DISPLACEMENT' - ], - 'frequency': 'REGULAR', - 'frequencyDisplay': 'Regular', - 'id': '1', - 'language': [ - 'ENGLISH', - 'FRENCH' - ], - 'lead': { - 'id': '2' + 'errors': [ + { + 'arrayErrors': [ + { + 'clientId': 'nonMemberErrors', + 'messages': 'Dublicate organization selected', + 'objectErrors': None + } + ], + 'clientId': None, + 'field': 'stakeholders', + 'messages': None, + 'objectErrors': None }, - 'limitations': '''Choice father why often my security arm. Live try most arm meet surface attention attack. Identify walk now often always. -Price north first end prove fire. How public feel first sell.''', - 'metadataComplete': True, - 'methodologyAttributes': [ - ], - 'methodologyComplete': True, - 'modifiedAt': '2021-01-01T00:00:00.123456+00:00', - 'noOfPages': 0, - 'objectives': '''Then fire pretty how trip learn enter. Seat much section investment on. -Young catch management sense technology. Physical society instead as. Other life edge network wall quite.''', - 'protectionInfoMgmts': [ - 'PROTECTION_MONITORING' - ], - 'protectionRisks': [ - ], - 'publicationDate': '2020-02-16', - 'sampling': '''Best issue interest level. Pull worker better. -Song body court movie cell contain. Economic type kitchen technology nearly anything yourself. Why unit support.''', - 'sectors': [ - 'HEALTH', - 'SHELTER', - 'WASH' - ], - 'status': 'ONGOING', - 'summaryComplete': True, - 'summaryDimensionMeta': [ - ], - 'summaryPillarMeta': None, - 'summarySubDimensionIssue': [ - ], - 'summarySubPillarIssue': [ - ] - } + { + 'arrayErrors': [ + { + 'clientId': 'nonMemberErrors', + 'messages': 'Score ratings should have unique score types', + 'objectErrors': None + } + ], + 'clientId': None, + 'field': 'scoreRatings', + 'messages': None, + 'objectErrors': None + }, + { + 'arrayErrors': [ + { + 'clientId': 'nonMemberErrors', + 'messages': 'Score analytical density should have unique sectors', + 'objectErrors': None + } + ], + 'clientId': None, + 'field': 'scoreAnalyticalDensity', + 'messages': None, + 'objectErrors': None + }, + { + 'arrayErrors': [ + { + 'clientId': 'nonMemberErrors', + 'messages': 'Dublicate question selected', + 'objectErrors': None + } + ], + 'clientId': None, + 'field': 'cna', + 'messages': None, + 'objectErrors': None + } + ], + 'ok': False, + 'result': None } } } } -snapshots['TestAnalysisMutationSnapShotTestCase::test_assessment_registry_update success'] = { +snapshots['TestAssessmentRegistryMutationSnapShotTestCase::test_assessment_registry_update success'] = { 'data': { 'project': { 'updateAssessmentRegistry': { @@ -123,6 +94,18 @@ 'bgCrisisType': 'LANDSLIDE', 'bgPreparedness': 'WITHOUT_PREPAREDNESS', 'cna': [ + { + 'answer': True, + 'id': '1', + 'question': { + 'id': '1', + 'question': 'test question', + 'sector': 'RELEVANCE', + 'sectorDisplay': 'Relevance', + 'subSector': 'RELEVANCE', + 'subSectorDisplay': 'Relevance' + } + } ], 'cnaComplete': True, 'confidentiality': 'CONFIDENTIAL', diff --git a/apps/assessment_registry/tests/test_mutation.py b/apps/assessment_registry/tests/test_mutation.py index c0069a7ddd..50ccde4969 100644 --- a/apps/assessment_registry/tests/test_mutation.py +++ b/apps/assessment_registry/tests/test_mutation.py @@ -4,15 +4,18 @@ from geo.factories import GeoAreaFactory, AdminLevelFactory, RegionFactory from gallery.factories import FileFactory from project.factories import ProjectFactory +from project.models import ProjectOrganization from user.factories import UserFactory from lead.factories import LeadFactory from assessment_registry.factories import ( AssessmentRegistryFactory, + AssessmentRegistryOrganizationFactory, QuestionFactory, SummaryIssueFactory, ) from assessment_registry.models import ( AssessmentRegistry, + AssessmentRegistryOrganization, MethodologyAttribute, AdditionalDocument, ScoreRating, @@ -124,35 +127,6 @@ class TestAssessmentRegistryMutation(GraphQLTestCase): } } ''' - UPDATE_ASSESSMENT_REGISTRY_QUERY = ''' - mutation MyMutation ($projectId: ID!, $input: AssessmentRegistryCreateInputType!, $assessmentRegistryId: ID!) { - project(id: $projectId) { - updateAssessmentRegistry(data: $input, id: $assessmentRegistryId) { - ok - errors - result { - id - bgPreparedness - bgCountries { - id - } - bgCrisisType - confidentiality - coordinatedJoint - detailsType - externalSupport - family - frequency - language - status - lead { - id - } - } - } - } - } -''' def setUp(self): super().setUp() @@ -161,7 +135,7 @@ def setUp(self): self.readonly_member_user = UserFactory.create() self.member_user = UserFactory.create() self.project1 = ProjectFactory.create() - self.lead1, self.lead2, self.lead3 = LeadFactory.create_batch(3, project=self.project1) + self.lead1, self.lead2 = LeadFactory.create_batch(2, project=self.project1) self.organization1 = OrganizationFactory.create() self.organization2 = OrganizationFactory.create() self.region = RegionFactory.create() @@ -177,24 +151,6 @@ def setUp(self): self.project1.add_member(self.readonly_member_user, role=self.project_role_reader) self.project1.add_member(self.member_user, role=self.project_role_member) self.summary_issue1, self.summary_issue2, self.summary_issue3 = SummaryIssueFactory.create_batch(3) - self.assessment_registry = AssessmentRegistryFactory.create( - project=self.project1, - lead=self.lead3, - bg_crisis_type=AssessmentRegistry.CrisisType.EARTH_QUAKE, - bg_preparedness=AssessmentRegistry.PreparednessType.WITH_PREPAREDNESS, - confidentiality=AssessmentRegistry.ConfidentialityType.UNPROTECTED, - coordinated_joint=AssessmentRegistry.CoordinationType.COORDINATED, - status=AssessmentRegistry.StatusType.PLANNED, - details_type=AssessmentRegistry.Type.INITIAL, - external_support=AssessmentRegistry.ExternalSupportType.EXTERNAL_SUPPORT_RECIEVED, - family=AssessmentRegistry.FamilyType.DISPLACEMENT_TRAKING_MATRIX, - frequency=AssessmentRegistry.FrequencyType.ONE_OFF, - language=[ - AssessmentRegistry.Language.ENGLISH, - AssessmentRegistry.Language.SPANISH, - ], - bg_countries=[self.region.id], - ) def test_create_assessment_registry(self): def _query_check(minput, **kwargs): @@ -349,78 +305,8 @@ def _query_check(minput, **kwargs): self.assertEqual(data['metadataComplete'], True) self.assertIsNotNone(data['protectionRisks']) - def test_update_assessment_registry(self): - def _query_check(mutation, minput, variables, assert_for_error=False, **kwargs): - return self.query_check( - mutation, - minput=minput, - variables=variables, - assert_for_error=assert_for_error, - **kwargs - ) - - update_minput = dict( - bgCrisisType=self.genum(AssessmentRegistry.CrisisType.LANDSLIDE), - bgPreparedness=self.genum(AssessmentRegistry.PreparednessType.WITHOUT_PREPAREDNESS), - confidentiality=self.genum(AssessmentRegistry.ConfidentialityType.CONFIDENTIAL), - coordinatedJoint=self.genum(AssessmentRegistry.CoordinationType.HARMONIZED), - status=self.genum(AssessmentRegistry.StatusType.ONGOING), - detailsType=self.genum(AssessmentRegistry.Type.MONITORING), - externalSupport=self.genum(AssessmentRegistry.ExternalSupportType.NO_EXTERNAL_SUPPORT_RECEIVED), - family=self.genum(AssessmentRegistry.FamilyType.HUMANITARIAN_NEEDS_OVERVIEW), - frequency=self.genum(AssessmentRegistry.FrequencyType.REGULAR), - lead=self.lead2.id, - language=[ - self.genum(AssessmentRegistry.Language.ENGLISH), - self.genum(AssessmentRegistry.Language.FRENCH) - ], - bgCountries=[self.region.id], - ) - # -- Without login - _query_check( - self.UPDATE_ASSESSMENT_REGISTRY_QUERY, - update_minput, - variables={'projectId': self.project1.id, 'assessmentRegistryId': self.assessment_registry.id}, - assert_for_error=True, - okay=False - ) - - user_roles = [self.non_member_user, self.readonly_member_user] - for user in user_roles: - self.force_login(user) - _query_check( - self.UPDATE_ASSESSMENT_REGISTRY_QUERY, - update_minput, - variables={'projectId': self.project1.id, 'assessmentRegistryId': self.assessment_registry.id}, - assert_for_error=True, - okay=False - ) - - # --- member user - self.force_login(self.member_user) - content = _query_check( - self.UPDATE_ASSESSMENT_REGISTRY_QUERY, - update_minput, - variables={'projectId': self.project1.id, 'assessmentRegistryId': self.assessment_registry.id}, - okay=False - ) - data = content['data']['project']['updateAssessmentRegistry']['result'] - self.assertEqual(data['id'], str(self.assessment_registry.id)) - self.assertEqual(data['bgCrisisType'], update_minput['bgCrisisType']) - self.assertEqual(data['bgPreparedness'], update_minput['bgPreparedness']) - self.assertEqual(data['confidentiality'], update_minput['confidentiality']) - self.assertEqual(data['coordinatedJoint'], update_minput['coordinatedJoint']) - self.assertEqual(data['status'], update_minput['status']) - self.assertEqual(data['detailsType'], update_minput['detailsType']) - self.assertEqual(data['externalSupport'], update_minput['externalSupport']) - self.assertEqual(data['family'], update_minput['family']) - self.assertEqual(data['frequency'], update_minput['frequency']) - self.assertEqual(data['lead']['id'], str(update_minput['lead'])) - self.assertEqual(data['language'], update_minput['language']) - self.assertEqual(data['bgCountries'][0]['id'], str(update_minput['bgCountries'][0])) - -class TestAnalysisMutationSnapShotTestCase(GraphQLSnapShotTestCase): +class TestAssessmentRegistryMutationSnapShotTestCase(GraphQLSnapShotTestCase): UPDATE_ASSESSMENT_REGISTRY_QUERY = ''' mutation MyMutation( $projectId: ID!, @@ -548,7 +434,7 @@ def setUp(self): self.admin_level1 = AdminLevelFactory.create(region=self.region) # geo_areas self.geo_area1, self.geo_area2 = GeoAreaFactory.create_batch(2, admin_level=self.admin_level1) - self.question1 = QuestionFactory.create( + self.question = QuestionFactory.create( sector=Question.QuestionSector.RELEVANCE.value, sub_sector=Question.QuestionSubSector.RELEVANCE.value, question="test question" @@ -594,7 +480,12 @@ def setUp(self): protection_info_mgmts=[AssessmentRegistry.ProtectionInfoType.PROTECTION_MONITORING], affected_groups=[AssessmentRegistry.AffectedGroupType.ALL_AFFECTED], ) - self.m_input = dict( + self.stakeholders = AssessmentRegistryOrganizationFactory.create( + organization_type=AssessmentRegistryOrganization.Type.LEAD_ORGANIZATION, + organization=self.organization1, + assessment_registry=self.assessment_registry + ) + self.minput = dict( bgCrisisType=self.genum(AssessmentRegistry.CrisisType.LANDSLIDE), bgPreparedness=self.genum(AssessmentRegistry.PreparednessType.WITHOUT_PREPAREDNESS), confidentiality=self.genum(AssessmentRegistry.ConfidentialityType.CONFIDENTIAL), @@ -610,37 +501,135 @@ def setUp(self): self.genum(AssessmentRegistry.Language.FRENCH) ], bgCountries=[self.region.id], + scoreRatings=[ + dict( + scoreType=self.genum(ScoreRating.ScoreCriteria.ASSUMPTIONS), + rating=self.genum(ScoreRating.RatingType.VERY_POOR), + reason="test" + ), + dict( + scoreType=self.genum(ScoreRating.ScoreCriteria.RELEVANCE), + rating=self.genum(ScoreRating.RatingType.VERY_POOR), + reason="test" + ) + ], + scoreAnalyticalDensity=[ + dict( + sector=self.genum(AssessmentRegistry.SectorType.FOOD_SECURITY), + analysisLevelCovered=[ + self.genum(ScoreAnalyticalDensity.AnalysisLevelCovered.ISSUE_UNMET_NEEDS_ARE_DETAILED), + self.genum(ScoreAnalyticalDensity.AnalysisLevelCovered.ISSUE_UNMET_NEEDS_ARE_PRIORITIZED_RANKED), + ], + figureProvided=[ + self.genum(ScoreAnalyticalDensity.FigureProvidedByAssessment.TOTAL_POP_IN_THE_ASSESSED_AREAS), + ], + score=1, + ), + dict( + sector=self.genum(AssessmentRegistry.SectorType.SHELTER), + analysisLevelCovered=[], + score=2 + ) + ], + stakeholders=[ + dict( + organization=self.stakeholders.id, + organizationType=self.genum(ProjectOrganization.Type.LEAD_ORGANIZATION), + ), + dict( + organization=self.stakeholders.id, + organizationType=self.genum(ProjectOrganization.Type.INTERNATIONAL_PARTNER), + ), + ], + cna=[ + dict( + answer=True, + question=self.question.id, + ) + ], ) def test_assessment_registry_update(self): """ This test makes sure only valid users can update AssessmentRegistry """ - def _query_check(**kwargs): + def _query_check(minput, **kwargs): return self.query_check( self.UPDATE_ASSESSMENT_REGISTRY_QUERY, - minput=self.m_input, + minput=minput, variables={'projectId': self.project1.id, 'assessmentRegistryId': self.assessment_registry.id}, **kwargs ) # -- Without login - _query_check(assert_for_error=True) + _query_check(self.minput, assert_for_error=True) # -- With login (non-member) self.force_login(self.non_member_user) - _query_check(assert_for_error=True) + _query_check(self.minput, assert_for_error=True) # --- member user (read-only) self.force_login(self.readonly_member_user) - _query_check(assert_for_error=True) + _query_check(self.minput, assert_for_error=True) # --- member user - # Invalid input self.force_login(self.member_user) - response = _query_check(okay=False) - self.assertMatchSnapshot(response, 'error') # Valid input - response = _query_check() + response = _query_check(self.minput) self.assertMatchSnapshot(response, 'success') + + self.minput['scoreRatings'] = [ + dict( + scoreType=self.genum(ScoreRating.ScoreCriteria.ASSUMPTIONS), + rating=self.genum(ScoreRating.RatingType.VERY_POOR), + reason="test" + ), + dict( + scoreType=self.genum(ScoreRating.ScoreCriteria.ASSUMPTIONS), + rating=self.genum(ScoreRating.RatingType.VERY_POOR), + reason="test" + ) + ] + self.minput['scoreAnalyticalDensity'] = [ + dict( + sector=self.genum(AssessmentRegistry.SectorType.FOOD_SECURITY), + analysisLevelCovered=[ + self.genum(ScoreAnalyticalDensity.AnalysisLevelCovered.ISSUE_UNMET_NEEDS_ARE_DETAILED), + self.genum(ScoreAnalyticalDensity.AnalysisLevelCovered.ISSUE_UNMET_NEEDS_ARE_PRIORITIZED_RANKED), + ], + figureProvided=[ + self.genum(ScoreAnalyticalDensity.FigureProvidedByAssessment.TOTAL_POP_IN_THE_ASSESSED_AREAS), + ], + score=1, + ), + dict( + sector=self.genum(AssessmentRegistry.SectorType.FOOD_SECURITY), + analysisLevelCovered=[], + score=1, + ) + ] + self.minput['stakeholders'] = [ + dict( + organization=self.stakeholders.id, + organizationType=self.genum(ProjectOrganization.Type.LEAD_ORGANIZATION), + ), + dict( + organization=self.stakeholders.id, + organizationType=self.genum(ProjectOrganization.Type.LEAD_ORGANIZATION), + ), + ] + self.minput['cna'] = [ + dict( + answer=True, + question=self.question.id, + ), + dict( + answer=True, + question=self.question.id, + ), + ] + + # Invalid inputs + response = _query_check(self.minput, okay=False) + self.assertMatchSnapshot(response, "error")