def test_collection_get(self): """Test simple collection get""" with factories.single_commit(): review1 = factories.ReviewFactory( status=all_models.Review.STATES.UNREVIEWED) review2 = factories.ReviewFactory( status=all_models.Review.STATES.REVIEWED) resp = self.api.get_collection(all_models.Review, [review1.id, review2.id]) self.assert200(resp) self.assertIn("reviews_collection", resp.json) self.assertIn("reviews", resp.json["reviews_collection"]) self.assertEquals(2, len(resp.json["reviews_collection"]["reviews"]))
def test_gca_with_varying_titles(self, title): """if GCA with any title is changed review -> unreviewed""" with factories.single_commit(): ca_factory = factories.CustomAttributeDefinitionFactory gca = ca_factory(definition_type="program", title=title, attribute_type="Rich Text") program = factories.ProgramFactory() program.custom_attribute_values = [{ "attribute_value": "starting_value", "custom_attribute_id": gca.id }] 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_value": "new_value", }], }) review = all_models.Review.query.get(review_id) self.assertEqual(review.status, all_models.Review.STATES.UNREVIEWED)
def test_gca(self): """if GCA of reviewable is changed review -> unreviewed""" with factories.single_commit(): ca_factory = factories.CustomAttributeDefinitionFactory gca = ca_factory(definition_type="control", title="rich_test_gca", attribute_type="Rich Text") control = factories.ControlFactory() review = factories.ReviewFactory( status=all_models.Review.STATES.REVIEWED, reviewable=control) 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_value": "new_value", }], }) review = all_models.Review.query.get(review_id) self.assertEqual(review.status, all_models.Review.STATES.UNREVIEWED)
def test_proposal_apply_notification(self, notification_type, expected_notifications): """Reviewable object changed via proposal -> notification created""" with factories.single_commit(): program = factories.ProgramFactory() review = factories.ReviewFactory( status=all_models.Review.STATES.REVIEWED, reviewable=program, notification_type=notification_type) review_id = review.id proposal_content = { "fields": { "title": "new title" }, } proposal = factories.ProposalFactory(instance=program, content=proposal_content, agenda="agenda content") self.api.modify_object(proposal, {"status": proposal.STATES.APPLIED}) review = all_models.Review.query.get(review_id) self.assertEqual(review.status, all_models.Review.STATES.UNREVIEWED) review_notif_types = all_models.Review.NotificationObjectTypes notyf_unreviewed_type = all_models.Notification.query.join( all_models.NotificationType).filter( all_models.NotificationType.name == review_notif_types.STATUS_UNREVIEWED).all() self.assertEqual(expected_notifications, len(notyf_unreviewed_type))
def test_map_person_gca(self): """if Map:Person GCA value added review -> unreviewed""" with factories.single_commit(): ca_factory = factories.CustomAttributeDefinitionFactory gca = ca_factory(definition_type="control", title="map_test_gca", attribute_type="Map:Person") user_id = all_models.Person.query.filter_by( email="*****@*****.**").one().id control = factories.ControlFactory() review = factories.ReviewFactory( status=all_models.Review.STATES.REVIEWED, reviewable=control) 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": user_id, "attribute_value": "Person", }], }) review = all_models.Review.query.get(review_id) self.assertEqual(review.status, all_models.Review.STATES.UNREVIEWED)
def test_reviewable_attributes(self, notification_type, expected_notifications): """Review change state to Unreviewed Notification with notification type STATUS_UNREVIEWED created """ with factories.single_commit(): program = factories.ProgramFactory() review = factories.ReviewFactory( status=all_models.Review.STATES.REVIEWED, reviewable=program, notification_type=notification_type) review_id = review.id reviewable = review.reviewable self.api.modify_object(reviewable, {"title": "new title"}) review = all_models.Review.query.get(review_id) self.assertEqual(review.status, all_models.Review.STATES.UNREVIEWED) review_notif_types = all_models.Review.NotificationObjectTypes notyf_unreviewed_type = all_models.Notification.query.join( all_models.NotificationType).filter( all_models.NotificationType.name == review_notif_types.STATUS_UNREVIEWED).all() self.assertEqual(expected_notifications, len(notyf_unreviewed_type))
def test_map_snapshotable_notification(self, notification_type, expected_notifications): """Map snapshotable should change review status and add notification""" with factories.single_commit(): program = factories.ProgramFactory() review = factories.ReviewFactory( status=all_models.Review.STATES.REVIEWED, reviewable=program, notification_type=notification_type) review_id = review.id self.generator.generate_relationship( source=program, destination=factories.ProductFactory(), context=None, ) review = all_models.Review.query.get(review_id) self.assertEqual(review.status, all_models.Review.STATES.UNREVIEWED) review_notif_types = all_models.Review.NotificationObjectTypes notyf_unreviewed_type = all_models.Notification.query.join( all_models.NotificationType).filter( all_models.NotificationType.name == review_notif_types.STATUS_UNREVIEWED).all() self.assertEqual(expected_notifications, len(notyf_unreviewed_type))
def test_acl_roles(self): """Update of reviewable ACL shouldn't change review status""" with factories.single_commit(): control = factories.ControlFactory() review = factories.ReviewFactory( status=all_models.Review.STATES.REVIEWED, reviewable=control) review_id = review.id ac_role_id = all_models.AccessControlRole.query.filter_by( name="Primary Contacts", object_type="Control").one().id user_id = all_models.Person.query.filter_by( email="*****@*****.**").one().id self.api.modify_object( control, { "access_control_list": [{ "ac_role_id": ac_role_id, "person": { "id": user_id }, }], }) review = all_models.Review.query.get(review_id) self.assertEqual(review.status, all_models.Review.STATES.REVIEWED)
def test_review_status_update(self): """Test updating folder preserves review status""" threat = factories.ThreatFactory() factories.ReviewFactory( reviewable=threat, status=all_models.Review.STATES.REVIEWED, ) self.api.put(threat, {"folder": factories.random_str()}) program = all_models.Threat.query.get(threat.id) self.assertEqual(program.review.status, all_models.Review.STATES.REVIEWED)
def test_review_status_update(self): """Test updating folder preserves review status""" control = factories.ControlFactory() factories.ReviewFactory( reviewable=control, status=all_models.Review.STATES.REVIEWED, ) self.api.put(control, {"folder": factories.random_str()}) control = all_models.Control.query.get(control.id) self.assertEqual(control.review.status, all_models.Review.STATES.REVIEWED)
def test_review_get(self): """Test that review data is present in control get response""" with factories.single_commit(): control = factories.ControlFactory() review = factories.ReviewFactory(reviewable=control) review_id = review.id resp = self.api.get(all_models.Control, control.id) self.assert200(resp) resp_control = resp.json["control"] self.assertIn("review", resp_control) self.assertEquals(review_id, resp_control["review"]["id"])
def test_mapping_non_snapshotable(self): """Map non-snapshotable shouldn't change review status""" with factories.single_commit(): control = factories.ControlFactory() review = factories.ReviewFactory( status=all_models.Review.STATES.REVIEWED, reviewable=control) review_id = review.id factories.RelationshipFactory(source=control, destination=factories.IssueFactory()) review = all_models.Review.query.get(review_id) self.assertEqual(review.status, all_models.Review.STATES.REVIEWED)
def test_delete_review(self): """Test delete review via API""" with factories.single_commit(): control = factories.ControlFactory() control_id = control.id review = factories.ReviewFactory(reviewable=control) review_id = review.id resp = self.api.delete(review) self.assert200(resp) review = all_models.Review.query.get(review_id) control = all_models.Control.query.get(control_id) self.assertIsNone(review) self.assertEquals(0, len(control.related_objects(_types=["Review"])))
def test_delete_review(self): """Test delete review via API""" with factories.single_commit(): risk = factories.RiskFactory() risk_id = risk.id review = factories.ReviewFactory(reviewable=risk) review_id = review.id resp = self.api.delete(review) self.assert200(resp) review = all_models.Review.query.get(review_id) risk = all_models.Risk.query.get(risk_id) self.assertIsNone(review) self.assertEquals(0, len(risk.related_objects(_types=["Review"])))
def test_delete_review(self): """Test delete review via API""" with factories.single_commit(): program = factories.ProgramFactory() program_id = program.id review = factories.ReviewFactory(reviewable=program) review_id = review.id resp = self.api.delete(review) self.assert200(resp) review = all_models.Review.query.get(review_id) program = all_models.Program.query.get(program_id) self.assertIsNone(review) self.assertEquals(0, len(program.related_objects(_types=["Review"])))
def test_comments(self): """Add comment to reviewable shouldn't update review state""" with factories.single_commit(): control = factories.ControlFactory() review = factories.ReviewFactory( status=all_models.Review.STATES.REVIEWED, reviewable=control) review_id = review.id self.generator.generate_comment(control, "Verifiers", "some comment", send_notification="false") review = all_models.Review.query.get(review_id) self.assertEqual(review.status, all_models.Review.STATES.REVIEWED)
def setUp(self): """Set up for Reviewable test cases.""" super(TestExportReviewable, self).setUp() with factories.single_commit(): person1 = factories.PersonFactory() self.person1_email = person1.email person2 = factories.PersonFactory() self.person2_email = person2.email program = factories.ProgramFactory(title="Test program") review = factories.ReviewFactory(reviewable=program) review.add_person_with_role_name(person1, 'Reviewers') review.add_person_with_role_name(person2, 'Reviewers') self.client.get("/login")
def test_reviewable_attributes(self, attr_to_modify, new_value): """If attribute '{0}' modified move review to Unreviewed state""" with factories.single_commit(): control = factories.ControlFactory() review = factories.ReviewFactory( status=all_models.Review.STATES.REVIEWED, reviewable=control) review_id = review.id reviewable = review.reviewable self.api.modify_object(reviewable, { attr_to_modify: new_value() if callable(new_value) else new_value }) review = all_models.Review.query.get(review_id) self.assertEqual(review.status, all_models.Review.STATES.UNREVIEWED)
def test_map_snapshotable(self, snapshotable): """Map '{}' should change review status""" with factories.single_commit(): control = factories.ControlFactory() review = factories.ReviewFactory( status=all_models.Review.STATES.REVIEWED, reviewable=control) review_id = review.id self.generator.generate_relationship( source=control, destination=factories.get_model_factory(snapshotable)(), context=None, ) review = all_models.Review.query.get(review_id) self.assertEqual(review.status, all_models.Review.STATES.UNREVIEWED)
def test_proposal_apply_review_status(self, notification_type, num_notifications_expected): """Change via proposal with ignorable attrs review status not change""" with factories.single_commit(): risk = factories.RiskFactory() review = factories.ReviewFactory( status=all_models.Review.STATES.REVIEWED, reviewable=risk, notification_type=notification_type ) review_id = review.id user = factories.PersonFactory() acl = factories.AccessControlListFactory( ac_role=factories.AccessControlRoleFactory(object_type="Risk"), object=risk ) proposal_content = { "access_control_list": { acl.ac_role_id: { "added": [{"id": user.id, "email": user.email}], "deleted": [] } } } proposal = factories.ProposalFactory( instance=risk, content=proposal_content, agenda="agenda content" ) self.api.modify_object(proposal, {"status": proposal.STATES.APPLIED}) review = all_models.Review.query.get(review_id) self.assertEqual(review.status, all_models.Review.STATES.REVIEWED) review_notif_types = all_models.Review.NotificationObjectTypes notif_unreviewed_type = all_models.Notification.query.join( all_models.NotificationType ).filter( all_models.NotificationType.name == review_notif_types.STATUS_UNREVIEWED ).all() self.assertEqual(num_notifications_expected, len(notif_unreviewed_type))
def test_change_control_folder(self): """Updating folder via import should not change review status.""" control = factories.ControlFactory(title="Control") factories.ReviewFactory( reviewable=control, status=all_models.Review.STATES.REVIEWED, ) import_data = OrderedDict([("object_type", "Control"), ("Code*", control.slug), ("Folder", factories.random_str())]) response = self.import_data(import_data) self._check_csv_response(response, {}) control = all_models.Control.query.get(control.id) self.assertEqual( all_models.Review.STATES.REVIEWED, control.review_status, )
def test_simple_get(self): """Test simple get""" with factories.single_commit(): control = factories.ControlFactory() review = factories.ReviewFactory( email_message="test email message", notification_type="email", reviewable=control, status=all_models.Review.STATES.UNREVIEWED) resp = self.api.get(all_models.Review, review.id) self.assert200(resp) self.assertIn("review", resp.json) resp_review = resp.json["review"] self.assertEqual(all_models.Review.STATES.UNREVIEWED, resp_review["status"]) self.assertEqual(all_models.Review.NotificationTypes.EMAIL_TYPE, resp_review["notification_type"]) self.assertEqual("test email message", resp_review["email_message"])
def test_last_reviewed(self): """last_reviewed_by, last_reviewed_by should be set if reviewed""" review = factories.ReviewFactory( status=all_models.Review.STATES.UNREVIEWED) review_id = review.id resp = self.api.put( review, { "status": all_models.Review.STATES.REVIEWED, }, ) self.assert200(resp) self.assertIsNotNone(resp.json["review"]["last_reviewed_by"]) self.assertIsNotNone(resp.json["review"]["last_reviewed_at"]) review = all_models.Review.query.get(review_id) self.assertIsNotNone(review.last_reviewed_by) self.assertIsNotNone(review.last_reviewed_at)
def test_restore_review_status(self): """Test empty restore from Version History shouldn't restore review_status""" factories.ReviewFactory(status=all_models.Review.STATES.REVIEWED, reviewable=self.program) response = self.api.put( self.program, data={}, ) self.assert200(response) self.program = self.refresh_object( all_models.Program, id_=self.program.id, ) self.assertEqual(self.program.review_status, all_models.Review.STATES.REVIEWED)
def test_reference_url(self): """If reference url is updated state should not updated""" with factories.single_commit(): control = factories.ControlFactory() doc = factories.DocumentReferenceUrlFactory( title="Simple title", link="some_url.com", description="mega description", parent_obj={ "id": control.id, "type": "Control" }) review = factories.ReviewFactory( status=all_models.Review.STATES.REVIEWED, reviewable=control) review_id = review.id self.api.modify_object(doc, {"link": "new_link.com"}) review = all_models.Review.query.get(review_id) self.assertEqual(review.status, all_models.Review.STATES.REVIEWED)
def test_proposal_apply(self): """Reviewable object changed via proposal -> review.state-> UNREVIEWED""" with factories.single_commit(): control = factories.ControlFactory() review = factories.ReviewFactory( status=all_models.Review.STATES.REVIEWED, reviewable=control) review_id = review.id proposal_content = { "fields": { "title": "new title" }, } proposal = factories.ProposalFactory(instance=control, content=proposal_content, agenda="agenda content") self.api.modify_object(proposal, {"status": proposal.STATES.APPLIED}) review = all_models.Review.query.get(review_id) self.assertEqual(review.status, all_models.Review.STATES.UNREVIEWED)
def test_reviewable_revisions(self): """Check that proper revisions are created""" with factories.single_commit(): control = factories.ControlFactory() control_id = control.id review = factories.ReviewFactory( reviewable=control, status=all_models.Review.STATES.UNREVIEWED) reviewable = review.reviewable control_revisions = all_models.Revision.query.filter_by( resource_id=control_id, resource_type=control.type).order_by( all_models.Revision.created_at, ).all() self.assertEquals(1, len(control_revisions)) self.assertEquals(all_models.Review.STATES.UNREVIEWED, control_revisions[0].content["review_status"]) resp = self.api.put( review, { "status": all_models.Review.STATES.REVIEWED, }, ) self.assert200(resp) control_revisions = all_models.Revision.query.filter_by( resource_id=control_id, resource_type=control.type).order_by( all_models.Revision.created_at, ).all() self.assertEquals(2, len(control_revisions)) self.assertEquals(all_models.Review.STATES.REVIEWED, control_revisions[1].content["review_status"]) resp = self.api.put(reviewable, {"description": "some new description"}) self.assert200(resp) control_revisions = all_models.Revision.query.filter_by( resource_id=control_id, resource_type=control.type).order_by( all_models.Revision.created_at, ).all() self.assertEquals(3, len(control_revisions)) self.assertEquals(all_models.Review.STATES.UNREVIEWED, control_revisions[2].content["review_status"])
def test_unmap_snapshotable(self): """Unmap snapshotable should change review status""" with factories.single_commit(): control = factories.ControlFactory() review = factories.ReviewFactory(reviewable=control) review_id = review.id _, rel = self.obj_gen.generate_relationship( source=control, 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_update_map_person_gca(self): """if existing Map:Person GCA value changed review -> unreviewed""" with factories.single_commit(): ca_factory = factories.CustomAttributeDefinitionFactory gca = ca_factory(definition_type="program", title="map_test_gca", attribute_type="Map:Person") first_user_id = all_models.Person.query.filter_by( email="*****@*****.**").one().id second_user_id = factories.PersonFactory().id program = factories.ProgramFactory() program.custom_attribute_values = [{ "attribute_object_id": first_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": second_user_id, "attribute_value": "Person", }], }) review = all_models.Review.query.get(review_id) self.assertEqual(review.status, all_models.Review.STATES.UNREVIEWED)
class TestFullFilledModelExport(TestCase): """Test for export a full filled model""" # pylint: disable=undefined-variable FIELDS_FILLED_RULES = { 'archived': lambda **kwargs: set_attribute( kwargs['obj'], 'archived', False ), 'assertions': lambda **kwargs: set_attribute( kwargs['obj'], 'assertions', 'assertions' ), 'assessment_template': lambda **kwargs: set_attribute( kwargs['obj'], 'assessment_template', 'assessment_template' ), 'assessment_type': lambda **kwargs: set_attribute( kwargs['obj'], 'assessment_type', 'Control' ), 'audit': lambda **kwargs: TestFullFilledModelExport._map_object( source=kwargs['obj'], destination=kwargs['obj'].audit ), 'categories': lambda **kwargs: set_attribute( kwargs['obj'], 'categories', '["categories"]' ), 'comments': lambda **kwargs: TestFullFilledModelExport._map_object( source=kwargs['obj'], destination=factories.CommentFactory( description='description', assignee_type='Admin' ) ), 'company': lambda **kwargs: set_attribute( kwargs['obj'], 'company', 'company' ), 'component_id': lambda **kwargs: factories.IssueTrackerIssueFactory( enabled=True, issue_tracked_obj=kwargs['obj'], issue_id=123, issue_type="PROCESS", component_id=12345, hotlist_id=12345, issue_priority="P2", issue_severity="S2", issue_url="somelink", ), 'contact': lambda **kwargs: set_attribute( kwargs['obj'], 'contact', kwargs['user'] ), 'created_at': lambda **kwargs: set_attribute( kwargs['obj'], 'created_at', datetime.date(2019, 9, 24) ), 'created_by': lambda **kwargs: set_attribute( kwargs['obj'], 'created_by_id', kwargs['user'].id ), 'cycle': lambda **kwargs: set_attribute( kwargs['obj'], 'cycle', 'cycle' ), 'cycle_task_group': lambda **kwargs: set_attribute( kwargs['obj'], 'cycle_task_group', 'cycle_task_group' ), 'cycle_workflow': lambda **kwargs: set_attribute( kwargs['obj'], 'cycle_workflow', 'cycle_workflow' ), 'default_assignees': lambda **kwargs: set_attribute( kwargs['obj'], 'default_assignees', kwargs['user'] ), 'default_verifier': lambda **kwargs: set_attribute( kwargs['obj'], 'default_verifier', kwargs['user'] ), 'directive': lambda **kwargs: set_attribute( kwargs['obj'], 'directive', 'directive' ), 'delete': lambda **kwargs: set_attribute( kwargs['obj'], 'delete', 'delete' ), 'description': lambda **kwargs: set_attribute( kwargs['obj'], 'description', 'description' ), 'design': lambda **kwargs: set_attribute( kwargs['obj'], 'design', 'Effective' ), 'documents_file': lambda **kwargs: TestFullFilledModelExport._map_object( source=factories.DocumentFileFactory(link='link'), destination=kwargs['obj'], ), 'documents_reference_url': lambda **kwargs: TestFullFilledModelExport._map_object( source=factories.DocumentReferenceUrlFactory(link='link'), destination=kwargs['obj'], ), 'due_date': lambda **kwargs: set_attribute( kwargs['obj'], 'due_date', datetime.date(2019, 9, 24) ), 'email': lambda **kwargs: set_attribute( kwargs['obj'], 'email', '*****@*****.**' ), 'enabled': lambda **kwargs: set_attribute( kwargs['obj'], 'enabled', True ), 'end_date': lambda **kwargs: set_attribute( kwargs['obj'], 'end_date', datetime.date(2019, 9, 24) ), 'evidences_file': lambda **kwargs: TestFullFilledModelExport._map_object( source=factories.EvidenceFileFactory(), destination=kwargs['obj'], ), 'evidences_url': lambda **kwargs: TestFullFilledModelExport._map_object( source=factories.EvidenceUrlFactory(), destination=kwargs['obj'], ), 'finished_date': lambda **kwargs: set_attribute( kwargs['obj'], 'finished_date', datetime.date(2019, 9, 24) ), 'folder': lambda **kwargs: set_attribute( kwargs['obj'], 'folder', 'folder' ), 'fraud_related': lambda **kwargs: set_attribute( kwargs['obj'], 'fraud_related', True ), 'hotlist_id': lambda **kwargs: set_attribute( kwargs['obj'], 'hotlist_id', 'hotlist_id' ), 'is_verification_needed': lambda **kwargs: set_attribute( kwargs['obj'], 'is_verification_needed', True ), 'issue_priority': lambda **kwargs: set_attribute( kwargs['obj'], 'issue_priority', 'issue_priority' ), 'issue_severity': lambda **kwargs: set_attribute( kwargs['obj'], 'issue_severity', 'issue_severity' ), 'issue_title': lambda **kwargs: set_attribute( kwargs['obj'], 'issue_title', 'issue_title' ), 'issue_tracker': lambda **kwargs: set_attribute( kwargs['obj'], 'issue_tracker', 'issue_tracker' ), 'issue_type': lambda **kwargs: set_attribute( kwargs['obj'], 'issue_type', 'issue_type' ), 'key_control': lambda **kwargs: set_attribute( kwargs['obj'], 'key_control', True ), 'kind': lambda **kwargs: set_attribute( kwargs['obj'], 'kind', all_models.Option.query.filter( all_models.Option == 'product_type' ).first() ), 'labels': lambda **kwargs: factories.ObjectLabelFactory( labeled_object=kwargs['obj'], label=factories.LabelFactory( object_type=kwargs['obj'].__tablename__ ), ), 'last_assessment_date': lambda **kwargs: TestFullFilledModelExport._create_attributes( kwargs['obj'], 1 ), 'last_comment': lambda **kwargs: TestFullFilledModelExport._create_attributes( kwargs['obj'], 3 ), 'last_deprecated_date': lambda **kwargs: set_attribute( kwargs['obj'], 'last_deprecated_date', datetime.date(2019, 9, 24) ), 'last_submitted_at': lambda **kwargs: set_attribute( kwargs['obj'], 'last_submitted_at', datetime.date(2019, 9, 24) ), 'last_submitted_by': lambda **kwargs: set_attribute( kwargs['obj'], 'last_submitted_by_id', kwargs['user'].id ), 'last_verified_at': lambda **kwargs: set_attribute( kwargs['obj'], 'last_verified_at', datetime.date(2019, 9, 24) ), 'last_verified_by': lambda **kwargs: set_attribute( kwargs['obj'], 'last_verified_by_id', kwargs['user'].id ), 'means': lambda **kwargs: set_attribute(kwargs['obj'], 'means', 'means'), 'modified_by': lambda **kwargs: set_attribute( kwargs['obj'], 'modified_by', kwargs['user'] ), 'name': lambda **kwargs: set_attribute(kwargs['obj'], 'name', 'name'), 'network_zone': lambda **kwargs: set_attribute( kwargs['obj'], 'network_zone', all_models.Option.query.filter( all_models.Option == 'network_zone' ).first() ), 'notes': lambda **kwargs: set_attribute(kwargs['obj'], 'notes', 'notes'), 'notify_custom_message': lambda **kwargs: set_attribute( kwargs['obj'], 'notify_custom_message', 'notify_custom_message' ), 'notify_on_change': lambda **kwargs: set_attribute( kwargs['obj'], 'notify_on_change', True ), 'operationally': lambda **kwargs: set_attribute( kwargs['obj'], 'operationally', 'Effective' ), 'people_sync_enabled': lambda **kwargs: set_attribute( kwargs['obj'], 'people_sync_enabled', True ), 'procedure_description': lambda **kwargs: set_attribute( kwargs['obj'], 'procedure_description', 'procedure description' ), 'program': lambda **kwargs: set_attribute( kwargs['obj'], 'program', 'program' ), 'readonly': lambda **kwargs: set_attribute( kwargs['obj'], 'readonly', True ), 'recipients': lambda **kwargs: set_attribute( kwargs['obj'], 'recipients', 'recipients' ), 'repeat_every': lambda **kwargs: set_attribute( kwargs['obj'], 'repeat_every', 1 ), 'report_end_date': lambda **kwargs: set_attribute( kwargs['obj'], 'report_end_date', datetime.date(2019, 9, 24)), 'report_start_date': lambda **kwargs: set_attribute( kwargs['obj'], 'report_start_date', datetime.date(2019, 8, 20) ), 'review_status': lambda **kwargs: set_attribute( kwargs['obj'], 'review_status', 'review status' ), 'review_status_display_name': lambda **kwargs: set_attribute( kwargs['obj'], 'review_status_display_name', 'review status display name' ), 'reviewers': lambda **kwargs: TestFullFilledModelExport._create_acl( 'Reviewers', factories.ReviewFactory(reviewable=kwargs['obj']), kwargs['user'], ), 'risk_type': lambda **kwargs: set_attribute( kwargs['obj'], 'risk_type', 'risk_type' ), 'secondary_contact': lambda **kwargs: set_attribute( kwargs['obj'], 'secondary_contact', kwargs['user'] ), 'send_by_default': lambda **kwargs: set_attribute( kwargs['obj'], 'send_by_default', True ), 'slug': lambda **kwargs: set_attribute(kwargs['obj'], 'slug', 'slug'), 'sox_302_enabled': lambda **kwargs: set_attribute( kwargs['obj'], 'sox_302_enabled', True ), 'start_date': lambda **kwargs: set_attribute( kwargs['obj'], 'start_date', datetime.date(2019, 8, 20) ), 'status': lambda **kwargs: set_attribute( kwargs['obj'], 'status', 'In Progress' ), 'task_group': lambda **kwargs: set_attribute( kwargs['obj'], 'task_group', 'task_group' ), 'task_type': lambda **kwargs: set_attribute( kwargs['obj'], 'task_type', 'text' ), 'template_custom_attributes': lambda **kwargs: set_attribute( kwargs['obj'], 'template_custom_attributes', 'adsasd' ), 'template_object_type': lambda **kwargs: set_attribute( kwargs['obj'], 'template_object_type', 'Objective' ), 'test_plan': lambda **kwargs: set_attribute( kwargs['obj'], 'test_plan', 'test_plan' ), 'test_plan_procedure': lambda **kwargs: set_attribute( kwargs['obj'], 'test_plan_procedure', True ), 'threat_event': lambda **kwargs: set_attribute( kwargs['obj'], 'threat_event', 'threat event' ), 'threat_source': lambda **kwargs: set_attribute( kwargs['obj'], 'threat_source', 'threat source' ), 'title': lambda **kwargs: set_attribute(kwargs['obj'], 'title', 'title'), 'unit': lambda **kwargs: set_attribute( kwargs['obj'], 'unit', all_models.Workflow.DAY_UNIT ), 'updated_at': lambda **kwargs: set_attribute( kwargs['obj'], 'updated_at', datetime.date(2019, 8, 20) ), 'user_role': lambda **kwargs: set_attribute( kwargs['obj'], 'user_role', 'user_role' ), 'verified_date': lambda **kwargs: set_attribute( kwargs['obj'], 'verified_date', datetime.date(2019, 9, 24) ), 'verify_frequency': lambda **kwargs: set_attribute( kwargs['obj'], 'verify_frequency', 'verify frequency' ), 'vulnerability': lambda **kwargs: set_attribute( kwargs['obj'], 'vulnerability', 'vulnerability' ), 'workflow': lambda **kwargs: set_attribute( kwargs['obj'], 'workflow', 'workflow' ), } @staticmethod def _create_attributes(obj, attribute_template_id): """Create attribute for object""" attr = all_models.Attributes( object_id=obj.id, object_type=obj.__class__.__name__, value_datetime=datetime.datetime(2019, 9, 26), value_string="last comment", attribute_template_id=attribute_template_id, updated_at=datetime.datetime.now(), created_at=datetime.datetime.now(), ) db.session.add(attr) db.session.commit() @staticmethod def _map_object(source, destination): """Create relationship with between two objects""" from ggrc.models import exceptions try: factories.RelationshipFactory(source=source, destination=destination) except exceptions.ValidationError: return def _map_snapshot(self, obj, destination): """Create relationship between object and his snapshot""" revision = self._get_latest_object_revisions([obj])[0] parent = destination if not isinstance(parent, all_models.Audit): parent = destination.audit snapshot = factories.SnapshotFactory( child_id=revision.resource_id, child_type=revision.resource_type, revision=revision, parent=parent, parent_id=parent.id, ) factories.RelationshipFactory(source=snapshot, destination=destination) @staticmethod def _create_acl(role, obj, user): """Propagate acl for obj""" ac_role = all_models.AccessControlRole.query.filter( all_models.AccessControlRole.name == role, all_models.AccessControlRole.object_type == obj.__class__.__name__, ).one() factories.AccessControlPersonFactory( ac_list=obj.acr_acl_map[ac_role], person=user, ) @staticmethod def _set_field(alias, obj, user): """Set field for model""" kwargs = {'obj': obj, 'user': user} set_attr = TestFullFilledModelExport.FIELDS_FILLED_RULES[alias] set_attr(**kwargs) @staticmethod def _get_aliases(model): """Get aliases for provided model""" return [c for c in import_helper.get_object_column_definitions(model)] def assert_full_filled_model(self, data): """Assert that all columns are filled for export Args: data: list of rows from csv table Raises: AssertionError: if not all require columns are filled for model """ errors = [] # these columns only for import ignore = ['Delete', 'Comments', 'Policy / Regulation / Standard / Contract', 'Template', 'Custom Attributes'] rows = csv.reader(StringIO(data)) rows = [r for r in rows][:3] for top, column_name, field_value in zip(*rows): if column_name.startswith('unmap:') or column_name in ignore: continue elif top == 'Object type': title = column_name continue if field_value == '': errors.append(column_name) self.assertEqual(errors, [], 'These columns for {0} are not exported: {1}'.format( title, ', '.join(errors))) def build_object(self, model): """Fill all fields in model""" errors = [] obj = factories.get_model_factory(model.__name__)() aliases = sorted(self._get_aliases(model)) for alias in aliases: if alias.startswith('__mapping__'): title = alias.split(':')[1] mapped_model = ''.join([part.title() for part in title.split()]) destination_obj = factories.get_model_factory(mapped_model)() self._map_object(source=obj, destination=destination_obj) elif alias.startswith('__snapshot_mapping__'): title = alias.split(':')[1] mapped_model = ''.join([part.title() for part in title.split()]) destination_obj = factories.get_model_factory(mapped_model)() self._map_snapshot(destination_obj, obj) elif alias.startswith('__acl__'): role = alias.split(':')[1] self._create_acl(role, obj, self.user) elif not alias.startswith('__'): try: self._set_field(alias, obj, self.user) except KeyError: errors.append(alias) else: continue db.session.commit() self.assertEqual(errors, [], 'These columns are not filled for model: {}. ' 'Need to add rule for these into ' 'FIELDS_FILLED_RULES'.format( ', '.join(errors))) return obj def setUp(self): super(TestFullFilledModelExport, self).setUp() self.api = api_helper.Api() self.client.get('/login') self.user = all_models.Person.query.filter( all_models.Person.email == "*****@*****.**" ).one() @ddt.data( *get_exportables() ) def test_full_filled_model_export(self, model): """Test export of {0.__name__} with all filled columns We defined dict with fillable fields from all models. So since we get some new column in model we need define it in `attrs_dict` Raises: AssertionError: 1. Raised when column isn't present in `attrs_dict`. So we need to add rules for this column to dict. 2. Raised when some columns are missed for export. So we need fix rules for columns in `attrs_dict`. """ model_name = model.__name__ obj = self.build_object(model) data = [{ "object_name": model_name, "filters": { "expression": { 'left': 'id', 'op': {'name': '='}, 'right': obj.id, } }, "fields": "all", }] response = self.export_csv(data) response_data = response.data self.assert_full_filled_model(response_data) self.assert200(response)