def test_validate_ca_with_wrong_id(self): """Test adding custom "Map:Person" attribute with not existing Person.""" with factories.single_commit(): program = factories.ProgramFactory() attribute_definition = factories.CustomAttributeDefinitionFactory( definition_type="program", definition_id=program.id, attribute_type="Map:Person") program.custom_attribute_values = [{ "attribute_value": "Person:0", "custom_attribute_id": attribute_definition.id, }] with self.assertRaises(ValueError) as exception: program.validate_custom_attributes() self.assertEqual(exception.exception.message, 'Person with 0 id not exists')
def test_change_cad_title(self): """Test program revision after changing CAD's title.""" # pylint: disable=protected-access new_title = "new title" with factories.single_commit(): program = factories.ProgramFactory(title="1") cad = factories.CustomAttributeDefinitionFactory( definition_type="program") factories.CustomAttributeValueFactory( custom_attribute=cad, attributable=program, attribute_value="text") self.api.put(cad, {"title": new_title}) revision = all_models.Revision.query.filter( all_models.Revision.resource_type == "Program").order_by( all_models.Revision.id.desc()).first() self.assertEqual( revision._content['custom_attribute_definitions'][0]['title'], new_title)
def test_program_mapping(self): """Check creation of new Audit if Program has Control with mapped roles""" program = factories.ProgramFactory() self.api.post(all_models.Audit, [{ "audit": { "title": "New Audit", "program": { "id": program.id, "type": program.type }, "status": "Planned", "context": None } }]) audit = all_models.Audit.query.first() program = all_models.Program.query.first() relationships = all_models.Relationship.find_related(audit, program) self.assertIsNotNone(audit) self.assertIsNotNone(program) self.assertIsNotNone(relationships)
def test_create(self, agenda, comment): """Test case create proposal with agenda {agenda}.""" program = factories.ProgramFactory() program_id = program.id self.assertEqual(0, len(program.comments)) resp = self.api.post( all_models.Proposal, {"proposal": { "instance": { "id": program.id, "type": program.type, }, # "content": {"123": 123}, "full_instance_content": program.log_json(), "agenda": agenda, "context": None, }}) self.assertEqual(201, resp.status_code) program = all_models.Program.query.get(program_id) self.assertEqual(1, len(program.comments)) self.assertEqual(comment, program.comments[0].description)
def test_validate_text_ca_value(self): """Test validator for Text CA value.""" generator = ObjectGenerator() prog = factories.ProgramFactory() cad1 = factories.CustomAttributeDefinitionFactory( definition_type="program", definition_id=prog.id, attribute_type="Text", title="CA 1", ) val1 = factories.CustomAttributeValueFactory( attributable=prog, attribute_value=" http://www.some.url", custom_attribute=cad1, ) prog.custom_attribute_values = [val1] generator.api.modify_object(prog, {}) prog = prog.__class__.query.get(prog.id) self.assertEqual(prog.custom_attribute_values[0].attribute_value, "http://www.some.url")
def test_program_relatives(self): """Test program children and parents +--C<--+ | | v | A<-----B<-----E<----F | | D<-----+ """ with factories.single_commit(): program_a = factories.ProgramFactory() program_b = factories.ProgramFactory() program_c = factories.ProgramFactory() program_d = factories.ProgramFactory() program_e = factories.ProgramFactory() program_f = factories.ProgramFactory() factories.RelationshipFactory(source=program_b, destination=program_a) factories.RelationshipFactory(source=program_c, destination=program_b) factories.RelationshipFactory(source=program_e, destination=program_d) factories.RelationshipFactory(source=program_e, destination=program_b) factories.RelationshipFactory(source=program_e, destination=program_c) factories.RelationshipFactory(source=program_f, destination=program_e) parents_b = all_models.Program.get_all_relatives_ids( program_b.id, "parents") children_b = all_models.Program.get_all_relatives_ids( program_b.id, "children") parents_e = all_models.Program.get_all_relatives_ids( program_e.id, "parents") children_e = all_models.Program.get_all_relatives_ids( program_e.id, "children") self.assertEqual(parents_b, {program_c.id, program_e.id, program_f.id}) self.assertEqual(children_b, { program_a.id, }) self.assertEqual(parents_e, { program_f.id, }) self.assertEqual( children_e, {program_c.id, program_b.id, program_d.id, program_a.id})
def test_ca_setattr(self): """Test setting custom attribute values with setattr.""" with factories.single_commit(): prog = factories.ProgramFactory() cad1 = factories.CustomAttributeDefinitionFactory( definition_type="program", title="CA 1", ) setattr(prog, "custom_attribute_values", [{ "attribute_value": "55", "custom_attribute_id": cad1.id, }]) db.session.commit() prog = prog.__class__.query.get(prog.id) self.assertEqual( {"55"}, set(v.attribute_value for v in prog.custom_attribute_values), ) self.assertEqual(len(prog.custom_attribute_values), 1)
def test_filter_by_dt_field(self, field, aliases): """Control Snapshots are filtered by datetime fields""" program = factories.ProgramFactory() control = factories.ControlFactory() datetime_value = getattr(control, field) factories.RelationshipFactory(source=program, destination=control) self._create_audit(program=program, title="some title") for date_string in self.generate_date_strings(datetime_value): for alias in aliases: query_dict = self._make_snapshot_query_dict( "Control", expression=[alias, "=", date_string] ) filtered_controls = self._get_first_result_set(query_dict, "Snapshot") self.assertEqual( filtered_controls["count"], 1, "empty results for alias {} and value {}".format( alias, date_string ) )
def test_unmap_snapshotable(self): """Unmap snapshotable should change review status""" program = factories.ProgramFactory() resp, review = generate_review_object(program) review_id = review.id _, rel = self.generator.generate_relationship( source=program, destination=factories.ProductFactory(), context=None, ) review = all_models.Review.query.get(review_id) resp = self.api.modify_object( review, {"status": all_models.Review.STATES.REVIEWED}) self.assert200(resp) resp = self.api.delete(rel) self.assert200(resp) review = all_models.Review.query.get(review_id) self.assertEqual(review.status, all_models.Review.STATES.UNREVIEWED)
def test_validate_empty_mapping_ca(self): """Test adding empty id non-mandatory custom "Map:Person" attribute.""" with factories.single_commit(): program = factories.ProgramFactory() attribute_definition = factories.CustomAttributeDefinitionFactory( definition_type="program", definition_id=program.id, attribute_type="Map:Person", title='Person') program.custom_attribute_values = [{ "attribute_value": "Person", "custom_attribute_id": attribute_definition.id, }] program.validate_custom_attributes() program = program.__class__.query.get(program.id) self.assertEqual(len(program.custom_attribute_values), 1)
def test_create_review(self): """Create review via API, check that single relationship is created""" program = factories.ProgramFactory() program_id = program.id resp = self.api.post( all_models.Review, { "review": { "reviewable": { "type": program.type, "id": program.id, }, "context": None, "notification_type": "email", "status": all_models.Review.STATES.UNREVIEWED, "access_control_list": build_reviewer_acl() }, }, ) self.assertEqual(201, resp.status_code) review_id = resp.json["review"]["id"] review = all_models.Review.query.get(review_id) self.assertEqual(all_models.Review.STATES.UNREVIEWED, review.status) self.assertEqual(program.type, review.reviewable_type) self.assertEqual(program_id, review.reviewable_id) control_review_rel_count = all_models.Relationship.query.filter( all_models.Relationship.source_id == review.id, all_models.Relationship.source_type == review.type, all_models.Relationship.destination_id == program_id, all_models.Relationship.destination_type == program.type, ).union( all_models.Relationship.query.filter( all_models.Relationship.destination_id == review.id, all_models.Relationship.destination_type == review.type, all_models.Relationship.source_id == program_id, all_models.Relationship.source_type == program.type, ) ).count() self.assertEqual(1, control_review_rel_count)
def setup_objects(self): """Sets up all the objects needed by the tests""" objects = self.objects # Program objects['program'] = program = factories.ProgramFactory(title="A Program") # Controls objects['controls'] = controls = [ factories.ControlFactory(title="My First Control"), factories.ControlFactory(title="My Second Control") ] # Controls <-> Program mapping for control in controls: factories.RelationshipFactory(source=program, destination=control) # Audit objects['audit'] = audit = factories.AuditFactory( program=objects['program'], access_control_list=[{ "ac_role_id": self.audit_roles['Auditors'].id, "person": {"id": self.people['created_auditor'].id}, }, { "ac_role_id": self.audit_roles['Audit Captains'].id, "person": {"id": self.people['created_captain'].id}, }] ) factories.RelationshipFactory(source=program, destination=audit) # Assessment template objects['assessment_template'] = template = \ factories.AssessmentTemplateFactory() factories.RelationshipFactory(source=audit, destination=template) # Snapshot objects['snapshots'] = self._create_snapshots(audit, controls) for snapshot in objects['snapshots']: factories.RelationshipFactory(source=audit, destination=snapshot)
def test_import_issue_with_snapshot(self): """Test checks impossibility to map snapshot to issue via import""" with factories.single_commit(): program = factories.ProgramFactory() control = factories.ControlFactory() factories.RelationshipFactory(source=program, destination=control) response = self.import_data( OrderedDict([ ("object_type", "Audit"), ("Code*", ""), ("Title", "New Audit"), ("State", "Planned"), ("Audit Captains", "*****@*****.**"), ("Program", program.slug), ("map:control versions", control.slug), ])) self._check_csv_response(response, {}) test_due_date = "15/06/2018" audit = models.Audit.query.first() response = self.import_data( OrderedDict([ ("object_type", "Issue"), ("Code*", ""), ("Title*", "Test issue due_date"), ("Admin*", "*****@*****.**"), ("Due Date", test_due_date), ("map:Audit", audit.slug), ("map:control versions", control.slug), ])) expected_errors = { "Issue": { "row_warnings": { errors.ISSUE_SNAPSHOT_MAP_WARNING.format( line=3, column_name=control.__class__.__name__), } } } self._check_csv_response(response, expected_errors)
def test_notification_add_new_review( self, notification_type, expected_notifications ): """After creation of new review notification should be created""" program = factories.ProgramFactory() resp, _ = self.generator.generate_object( all_models.Review, { "reviewable": { "type": program.type, "id": program.id, }, "context": None, "notification_type": notification_type, "status": all_models.Review.STATES.UNREVIEWED, "access_control_list": build_reviewer_acl(), }, ) self.assertEqual(201, resp.status_code) self.assertEqual( expected_notifications, len(all_models.Notification.query.all()) )
def test_audit_imports(self): """ this tests if the audit gets imported with a mapped program """ # with factories.single_commit(): program1 = factories.ProgramFactory(title="prog-1") audit_data = [ collections.OrderedDict([ ("object_type", "Audit"), ("Code*", ""), ("Program", program1.slug), ("Title", "Aud-1"), ("State", "Planned"), ("Audit Captains", "*****@*****.**"), ("Auditors", "*****@*****.**"), ]), ] response = self.import_data(*audit_data) self._check_csv_response(response, {}) self.assertEqual(1, Audit.query.count()) audit = Audit.query.filter(Audit.title == "Aud-1").first() self.assertEqual(audit.program_id, program1.id)
def test_creation_mapped_control(self): """Check creation of new Audit if Program has Control with mapped roles""" control = factories.ControlFactory() # Map original of control to several assessments to get propagated roles self.generate_control_mappings(control) # Existing control should be updated to create new revision with ACL self.api.put(control, {"title": "Test Control"}) program = factories.ProgramFactory() factories.RelationshipFactory(source=program, destination=control) response = self.api.post(all_models.Audit, [{ "audit": { "title": "New Audit", "program": { "id": program.id }, "status": "Planned", "context": None } }]) self.assert200(response)
def test_create_on_post_only(self): """Test if proposal relationship is created on post only.""" program = factories.ProgramFactory() response = self.create_proposal_for(program) post_rels = self.proposal_relationships(program).all() proposal = all_models.Proposal.query.get(response.json["proposal"]["id"]) # Invalidate ACR cache manually as after first post # it will in detached state flask.g.global_ac_roles = None response = self.api.put( proposal, { "proposal": { "status": all_models.Proposal.STATES.APPLIED, "apply_reason": "test" } } ) self.assert200(response) put_rels = self.proposal_relationships(program).all() self.assertEqual(post_rels, put_rels)
def test_self_reviewer_notification_on_create_review(self, _): """Auto assigned Reviewer should NOT receive email notification""" current_user = all_models.Person.query.filter_by( email="*****@*****.**").one() reviewer_role_id = all_models.AccessControlRole.query.filter_by( name="Reviewers", object_type="Review", ).one().id program = factories.ProgramFactory() email_message = "email email_message" self.generator.generate_object( all_models.Review, { "reviewable": { "type": program.type, "id": program.id, }, "context": None, "notification_type": all_models.Review.NotificationTypes.EMAIL_TYPE, "status": all_models.Review.STATES.REVIEWED, "email_message": email_message, "access_control_list": [{ "ac_role_id": reviewer_role_id, "person": { "id": current_user.id }, }], }, ) with mock.patch.object(fast_digest.DIGEST_TMPL, "render") as bodybuilder_mock: fast_digest.send_notification() # assert no email sent bodybuilder_mock.assert_not_called()
def _test_contact_field(self, contact_name_field, search_field): """Util function for test for filtering by contact fields""" person_name = "name" person_email = "*****@*****.**" program = factories.ProgramFactory() program_id = program.id control_kwargs = { contact_name_field: factories.PersonFactory(name=person_name, email=person_email), } control = factories.ControlFactory(**control_kwargs) factories.RelationshipFactory(source=program, destination=control) program = models.Program.query.filter_by(id=program_id).one() self._create_audit(program=program, title="some title") self.assert_rows_number_in_search(search_field, person_name, 1) self.assert_rows_number_in_search(search_field, person_email, 1) self.assert_rows_number_in_search(search_field, "negative_" + person_name, 0) self.assert_rows_number_in_search(search_field, "negative_" + person_email, 0)
def test_update_audit_with_control(self): """Test import of existing Audit with mapped Control Snapshot.""" with factories.single_commit(): program = factories.ProgramFactory() audit = factories.AuditFactory(program=program) audit_id = audit.id control = factories.ControlFactory() factories.RelationshipFactory(source=program, destination=control) snapshot = self._create_snapshots(audit, [control])[0] factories.RelationshipFactory(source=audit, destination=snapshot) response = self.import_data(OrderedDict([ ("object_type", "Audit"), ("Code*", audit.slug), ("Title", "New Title"), ("Audit Captains", "*****@*****.**"), ("Program", program.slug), ("map:control versions", control.slug), ])) self._check_csv_response(response, {}) audit = all_models.Audit.query.get(audit_id) self.assertEqual(audit.title, "New Title")
def test_simple_relevant_query(self): """Test simple relevant query""" contract_slugs = [] program_slugs = [] with factories.single_commit(): for i in range(1, 5): contract = factories.ContractFactory(title="contract-{}".format(i)) contract_slugs.append(contract.slug) program = factories.ProgramFactory(title="program-{}".format(i)) program_slugs.append(program.slug) factories.RelationshipFactory(source=contract, destination=program) data = [ get_related_objects("Contract", "Program", contract_slugs[:2]) ] response = self.export_csv(data) expected = set([1, 2]) for i in range(1, 5): if i in expected: self.assertIn(",program-{},".format(i), response.data) else: self.assertNotIn(",program-{},".format(i), response.data)
def test_adding_bad_ca_dict(self): """Test setting invalid custom attribute values.""" with factories.single_commit(): prog = factories.ProgramFactory() cad1 = factories.CustomAttributeDefinitionFactory( definition_type="section", title="CA 1", ) with self.assertRaises(ValueError): prog.custom_attribute_values = [{ "attribute_value": "55", "custom_attribute_id": -1 }] prog.validate_custom_attributes() with self.assertRaises(ValueError): prog.custom_attribute_values = [{ "attribute_value": "55", "custom_attribute_id": cad1.id, }] prog.validate_custom_attributes()
def test_acl_roles_clear(self): """Test clearing ACL roles for Program with '--' value""" with factories.single_commit(): program = factories.ProgramFactory() for role in ["Program Editors", "Program Editors", "Program Readers"]: person = factories.PersonFactory() acl = program.acr_name_acl_map[role] factories.AccessControlPersonFactory( ac_list=acl, person=person, ) for role in {"Program Editors", "Program Readers"}: response = self.import_data(OrderedDict([ ("object_type", program.type), ("code", program.slug), (role, "--"), ])) self._check_csv_response(response, {}) program = models.all_models.Program.query.first() for _, acl in program.access_control_list: self.assertNotEqual(acl.ac_role.name, role)
def test_validate_invalid_type_ca(self): """Test adding invalid attribute type to custom "Map:Person" attribute.""" with factories.single_commit(): attribute_definition = factories.CustomAttributeDefinitionFactory( definition_type="program", attribute_type="Map:Person", mandatory=True) program = factories.ProgramFactory() program.custom_attribute_values = [{ "attribute_value": "Assessment:1", "custom_attribute_id": attribute_definition.id, }] with self.assertRaises(ValueError) as exception: program.validate_custom_attributes() self.assertEqual( exception.exception.message, 'Invalid attribute type: Assessment expected Person')
def test_validate_ca_with_empty_id(self): """Test adding empty id to mandatory custom "Map:Person" attribute.""" with factories.single_commit(): attribute_definition = factories.CustomAttributeDefinitionFactory( definition_type="program", attribute_type="Map:Person", title='Person', mandatory=True) program = factories.ProgramFactory() program.custom_attribute_values = [{ "attribute_value": "Person", "custom_attribute_id": attribute_definition.id, }] with self.assertRaises(ValueError) as exception: program.validate_custom_attributes() self.assertEqual(exception.exception.message, 'Missing mandatory attribute: Person')
def test_delete_map_person_gca(self): """if existing Map:Person GCA value deleted review -> unreviewed""" with factories.single_commit(): ca_factory = factories.CustomAttributeDefinitionFactory gca = ca_factory(definition_type="program", title="map_test_gca", attribute_type="Map:Person") user_id = all_models.Person.query.filter_by( email="*****@*****.**").one().id program = factories.ProgramFactory() program.custom_attribute_values = [{ "attribute_object_id": user_id, "custom_attribute_id": gca.id, "attribute_value": "Person" }] review = factories.ReviewFactory( status=all_models.Review.STATES.REVIEWED, reviewable=program) review_id = review.id reviewable = review.reviewable review = all_models.Review.query.get(review_id) self.assertEqual(review.status, all_models.Review.STATES.REVIEWED) self.api.modify_object( reviewable, { "custom_attribute_values": [{ "custom_attribute_id": gca.id, "attribute_object_id": None, "attribute_object": None, "attribute_value": "Person", }], }) review = all_models.Review.query.get(review_id) self.assertEqual(review.status, all_models.Review.STATES.UNREVIEWED)
def test_adding_mapping_ca_dict(self): """Test adding mapping custom attribute values with a dict.""" with factories.single_commit(): cad1 = factories.CustomAttributeDefinitionFactory( definition_type="program", attribute_type="Map:Person", title="CA 1", ) cad2 = factories.CustomAttributeDefinitionFactory( definition_type="program", attribute_type="Map:Person", title="CA 2", ) person = factories.PersonFactory() prog = factories.ProgramFactory() prog.custom_attribute_values = [{ "attribute_value": "Person:%s" % person.id, "custom_attribute_id": cad1.id, }, { "attribute_value": "Person", "attribute_object_id": str(person.id), "custom_attribute_id": cad2.id, }] prog.validate_custom_attributes() prog = prog.__class__.query.get(prog.id) self.assertEqual( {str(person.id)}, set(v.attribute_object_id for v in prog.custom_attribute_values), ) self.assertEqual( {"Person"}, set(v.attribute_value for v in prog.custom_attribute_values), ) self.assertEqual(len(prog.custom_attribute_values), 2)
def test_email_proposal_program(self, role_name): """Test sending email to Program manager/Editor/Primary Contacts""" from ggrc.models import all_models role_1 = all_models.AccessControlRole.query.filter( all_models.AccessControlRole.name == role_name, all_models.AccessControlRole.object_type == 'Program', ).one() with factories.single_commit(): program = factories.ProgramFactory() person_1 = factories.PersonFactory() # has 1 role factories.AccessControlPersonFactory( ac_list=program.acr_acl_map[role_1], person=person_1) proposal_1 = factories.ProposalFactory( instance=program, content={ "fields": { "title": "a" }, "access_control_list": {}, "custom_attribute_values": {}, "mapping_fields": {}, "mapping_list_fields": {}, }, agenda="agenda 1") self.assertIsNone(proposal_1.proposed_notified_datetime) with mock.patch( "ggrc.notifications.common.send_email") as send_email_mock: with mock.patch.object(fast_digest.DIGEST_TMPL, "render") as bodybuilder_mock: fast_digest.send_notification() self.assertIsNotNone(proposal_1.proposed_notified_datetime) self.assertEqual(1, len(bodybuilder_mock.call_args_list)) self.assertEqual(1, len(send_email_mock.call_args_list)) # email to each required person self.assertEqual( [person_1.email], [a[1]["user_email"] for a in send_email_mock.call_args_list])
def test_single_acl_to_multiple(self, count): """Test propagation of single ACL entry to multiple children.""" with factories.single_commit(): program = factories.ProgramFactory() for i in range(count): audit = factories.AuditFactory(program=program) factories.RelationshipFactory( source=program if i % 2 == 0 else audit, destination=program if i % 2 == 1 else audit, ) acl_id = program.acr_name_acl_map["Program Editors"].id child_ids = propagation._handle_acl_step([acl_id], self.user_id) self.assertEqual( all_models.AccessControlList.query.filter( all_models.AccessControlList.parent_id.isnot(None)).count(), count * 2) self.assertEqual( db.session.execute(child_ids.alias("counts").count()).scalar(), count, )
def test_updating_ca_dict(self): """Test updating custom attribute values with a dict.""" with factories.single_commit(): prog = factories.ProgramFactory() cad1 = factories.CustomAttributeDefinitionFactory( definition_type="program", title="CA 1", ) prog.custom_attribute_values = [{ "attribute_value": "55", "custom_attribute_id": cad1.id, }] db.session.commit() prog = prog.__class__.query.get(prog.id) prog.custom_attribute_values = [{ "attribute_value": "57", "custom_attribute_id": cad1.id, }] self.assertEqual(len(prog.custom_attribute_values), 1) self.assertEqual(prog.custom_attribute_values[0].attribute_value, "57")