def test_creating_new_ticket_for_linked_issue(self, update_mock): """Test create new ticket for already linked assessment""" with factories.single_commit(): audit = factories.AuditFactory() factories.IssueTrackerIssueFactory(enabled=True, issue_tracked_obj=audit) iti = factories.IssueTrackerIssueFactory( enabled=True, issue_id=TICKET_ID, issue_tracked_obj=factories.AssessmentFactory(audit=audit)) new_data = {"issue_id": ''} issue_request_payload = self.put_request_payload_builder(new_data) with mock.patch.object(assessment_integration, '_is_issue_tracker_enabled', return_value=True): with mock.patch("ggrc.integrations.issues.Client.create_issue", return_value={"issueId": TICKET_ID + 1}) as create_mock: response = self.api.put(iti.issue_tracked_obj, issue_request_payload) self.assert200(response) # Detach comment should be sent to previous ticket update_mock.assert_called_once() self.assertEqual(TICKET_ID, update_mock.call_args[0][0]) create_mock.assert_called_once() # check if data was changed in our DB issue_id = response.json.get("assessment").get("id") issue_tracker_issue = models.IssuetrackerIssue.get_issue( "Assessment", issue_id, ) self.assertNotEqual(int(issue_tracker_issue.issue_id), TICKET_ID)
def test_fill_missing_values_from_audit(self): """Check prepare_json_method get missed values from audit.""" with factories.single_commit(): audit = factories.AuditFactory() factories.IssueTrackerIssueFactory( enabled=True, issue_tracked_obj=audit, component_id=213, hotlist_id=333, issue_type=constants.DEFAULT_ISSUETRACKER_VALUES['issue_type'], issue_priority="S0", issue_severity="P0", ) assmt = factories.AssessmentFactory( audit=audit, ) factories.IssueTrackerIssueFactory( enabled=True, issue_tracked_obj=assmt ) audit_issue_tracker_info = audit.issuetracker_issue.to_dict() assmt_issue_tracker_info = assmt.issuetracker_issue.to_dict() integration_utils.set_values_for_missed_fields(assmt, assmt_issue_tracker_info) fields_to_check = ["component_id", "hotlist_id", "issue_type", "issue_priority", "issue_severity"] for field in fields_to_check: self.assertEqual(assmt_issue_tracker_info[field], audit_issue_tracker_info[field])
def test_already_linked_ticket(self, enabled_mock): """Test Assessment w/o IT couldn't be linked to already linked ticket""" with factories.single_commit(): audit = factories.AuditFactory() factories.IssueTrackerIssueFactory( enabled=True, issue_tracked_obj=audit ) factories.IssueTrackerIssueFactory( enabled=True, issue_id=TICKET_ID, issue_tracked_obj=factories.AssessmentFactory(audit=audit) ) new_assmt = factories.AssessmentFactory() issue_data = {"issue_id": TICKET_ID} issue_request_payload = self.put_request_payload_builder(issue_data) response = self.api.put(new_assmt, issue_request_payload) self.assert200(response) self.assertTrue(response.json["assessment"]["issue_tracker"]["_warnings"]) issue_id = response.json.get("assessment").get("id") issue_tracker_issue = models.IssuetrackerIssue.get_issue( "Assessment", issue_id, ) self.assertFalse(issue_tracker_issue) enabled_mock.assert_called()
def test_related_assessments(self): """Assessment with empty issuetracker_issue should be synced""" with factories.single_commit(): audit = factories.AuditFactory() factories.IssueTrackerIssueFactory( issue_tracked_obj=audit, issue_id=None, component_id=12345, hotlist_id=54321, issue_priority="P2", issue_severity="S2", ) assess1 = factories.AssessmentFactory(audit=audit) assess1_id = assess1.id assess2 = factories.AssessmentFactory(audit=audit) assess2_id = assess2.id factories.IssueTrackerIssueFactory( issue_tracked_obj=assess2, issue_id=None, component_id=9999, hotlist_id=7777, issue_priority="P1", issue_severity="S1", ) self.assertIsNone(assess1.issuetracker_issue) with mock.patch("ggrc.notifications.common.send_email"): response = self.generate_children_issues_for( audit.type, audit.id, assess1.type ) self.assert200(response) self.assertEqual(response.json.get("errors"), []) assess1 = all_models.Assessment.query.get(assess1_id) self.assertIsNotNone( assess1.issuetracker_issue, "issuetracker_issue was not created for assessment {}".format( assess1.id ) ) self.assertEqual("12345", assess1.issuetracker_issue.component_id) self.assertEqual("54321", assess1.issuetracker_issue.hotlist_id) self.assertEqual("P2", assess1.issuetracker_issue.issue_priority) self.assertEqual("S2", assess1.issuetracker_issue.issue_severity) assess2 = all_models.Assessment.query.get(assess2_id) self.assertEqual("9999", assess2.issuetracker_issue.component_id) self.assertEqual("7777", assess2.issuetracker_issue.hotlist_id) self.assertEqual("P1", assess2.issuetracker_issue.issue_priority) self.assertEqual("S1", assess2.issuetracker_issue.issue_severity)
def _create_asmt(people_sync_enabled): """Helper function creating assessment and audit.""" with factories.single_commit(): asmt = factories.AssessmentFactory() factories.IssueTrackerIssueFactory( enabled=True, issue_tracked_obj=asmt.audit, people_sync_enabled=people_sync_enabled, **TestAsmtSyncJob._issuetracker_data()) factories.IssueTrackerIssueFactory( enabled=True, issue_tracked_obj=asmt, **TestAsmtSyncJob._issuetracker_data()) return asmt
def test_sync_due_date(self): """Test adding due_date in Issue""" due_date = "2018-09-13" date_format = "%Y-%m-%d" iti1 = factories.IssueTrackerIssueFactory( enabled=True, issue_id="1", issue_tracked_obj=factories.IssueFactory(status="Draft") ) iti2 = factories.IssueTrackerIssueFactory( enabled=True, issue_id="2", issue_tracked_obj=factories.IssueFactory(status="Draft") ) batches = [ { "1": { "status": "new", "type": "BUG", "priority": "P2", "severity": "S2", "custom_fields": [{ constants.CUSTOM_FIELDS_DUE_DATE: due_date }], }, "2": { "status": "new", "type": "BUG", "priority": "P2", "severity": "S2", "custom_fields": [], } } ] # Perform action. with mock.patch.object(sync_utils, "iter_issue_batches", return_value=batches): issue_sync_job.sync_issue_attributes() # Assert results. issue1 = all_models.Issue.query.get(iti1.issue_tracked_obj.id) self.assertEquals(issue1.due_date.strftime(date_format), due_date) issue2 = all_models.Issue.query.get(iti2.issue_tracked_obj.id) self.assertIsNone(issue2.due_date)
def test_update_untracked_fields(self, issue_attrs, mock_update_issue): """Test updating issue with fields which shouldn't be sync.""" iti = factories.IssueTrackerIssueFactory( enabled=True, issue_tracked_obj=factories.IssueFactory()) with mock.patch.object(settings, "ISSUE_TRACKER_ENABLED", True): self.api.put(iti.issue_tracked_obj, issue_attrs) mock_update_issue.assert_not_called()
def test_adding_comment_to_issue(self, update_issue_mock, url_builder_mock): """Test adding comment to issue.""" iti = factories.IssueTrackerIssueFactory( enabled=True, issue_tracked_obj=factories.IssueFactory()) comment = factories.CommentFactory(description="test comment") expected_result = { "comment": u"A new comment is added by 'Example User' to the 'Issue': " u"'test comment'.\nUse the following to link to get more " u"information from the GGRC 'Issue'. Link - " u"http://issue_url.com" } with mock.patch.object(settings, "ISSUE_TRACKER_ENABLED", True): self.api.post( all_models.Relationship, { "relationship": { "source": { "id": iti.issue_tracked_obj.id, "type": "Issue" }, "destination": { "id": comment.id, "type": "comment" }, "context": None }, }) url_builder_mock.assert_called_once() update_issue_mock.assert_called_with(iti.issue_id, expected_result)
def test_get_issue_json(self, model): """Test get_issue_json method issue's update""" with factories.single_commit(): factory = factories.get_model_factory(model) obj = factory() factories.IssueTrackerIssueFactory( enabled=True, issue_tracked_obj=obj, title='title', component_id=111, hotlist_id=222, issue_type="PROCESS", issue_priority="P2", issue_severity="S2", ) expected_result = { 'component_id': 111, 'severity': u'S2', 'title': u'title', 'hotlist_ids': [222], 'priority': u'P2', 'type': u'PROCESS' } updater = issuetracker_bulk_sync.IssueTrackerBulkUpdater() # pylint: disable=protected-access result = updater._get_issue_json(obj) self.assertEqual(expected_result, result)
def test_task_already_run_status(self): """Test if new task started when another is in progress.""" audit_id, _ = self.setup_assessments(1) response = self.generate_children_issues_for("Audit", audit_id, "Assessment") self.assert200(response) db.session.query(all_models.BackgroundTask).update( {"status": "Running"}) db.session.commit() with factories.single_commit(): asmnt = factories.AssessmentFactory(audit_id=audit_id) audit = all_models.Audit.query.get(audit_id) factories.RelationshipFactory(source=audit, destination=asmnt) factories.IssueTrackerIssueFactory( issue_tracked_obj=asmnt, issue_id=None, title=None, ) response = self.generate_children_issues_for("Audit", audit_id, "Assessment") self.assert400(response) self.assertEqual( response.json["message"], "Task 'generate_children_issues' already run for Audit {}.".format( audit_id)) url = "background_task_status/{}/{}".format("audit", audit_id) response = self.api.client.get(url) self.assert200(response) self.assertEqual(response.json.get("status"), "Running") self.assertEqual(response.json.get("operation"), "generate_children_issues") self.assertEqual(response.json.get("errors"), [])
def test_basic_import(self, mock_create_issue, mock_update_issue): """Test basic import functionality.""" with mock.patch.object(assessment_integration, '_is_issue_tracker_enabled', return_value=True): # update existing object iti = factories.IssueTrackerIssueFactory(enabled=True) asmt = iti.issue_tracked_obj audit = asmt.audit response = self.import_data( OrderedDict([ ('object_type', 'Assessment'), ('Code*', asmt.slug), ('Audit', audit.slug), ])) self._check_csv_response(response, {}) # import new object response = self.import_data( OrderedDict([ ('object_type', 'Assessment'), ('Code*', 'Test Code'), ('Audit', audit.slug), ('Creators', '*****@*****.**'), ('Assignees*', '*****@*****.**'), ('Title', 'Some Title'), ])) self._check_csv_response(response, {})
def test_people_sync_audit_update(self, current_obj_value, imported_value, expected_obj_value, expected_warnings): """Test Audit people sync={0} set during updated via import.""" with factories.single_commit(): audit = factories.AuditFactory() factories.IssueTrackerIssueFactory( issue_tracked_obj=audit, people_sync_enabled=current_obj_value, ) response = self.import_data( OrderedDict([ ("object_type", "Audit"), ("Code*", audit.slug), ("Sync people with Ticket Tracker", imported_value), ])) expected_resp = self._prepare_expected_import_resp( "Audit", row_warnings=expected_warnings) self._check_csv_response(response, expected_resp) audit = all_models.Audit.query.one() self.assertEqual( audit.issue_tracker["people_sync_enabled"], expected_obj_value, )
def test_issue_export(self, model_name): """Test export for issuetracked attributes. Attribute list: component_id, hotlist_id, issue_type, issue_priority, issue_severity""" factory = factories.get_model_factory(model_name) with factories.single_commit(): factories.IssueTrackerIssueFactory( issue_tracked_obj=factory(), component_id=12345, hotlist_id=54321, issue_type="PROCESS", issue_severity="S4", issue_priority="P4", enabled=True ) data = [{"object_name": model_name, "fields": "all", "filters": {"expression": {}}}] response = self.export_csv(data) self.assertEqual(response.status_code, 200) self.assertIn("Component ID", response.data) self.assertIn("12345", response.data) self.assertIn("Hotlist ID", response.data) self.assertIn("54321", response.data) self.assertIn("Issue Type", response.data) self.assertIn("PROCESS", response.data) self.assertIn("Priority", response.data) self.assertIn("P4", response.data) self.assertIn("Severity", response.data) self.assertIn("S4", response.data) self.assertIn("true", response.data)
def test_adding_comment_to_issue(self, update_issue_mock, url_builder_mock): """Test adding comment to issue.""" role = all_models.Role.query.filter( all_models.Role.name == "Administrator" ).one() with factories.single_commit(): client_user = factories.PersonFactory(name="Test User") rbac_factories.UserRoleFactory(role=role, person=client_user) self.api.set_user(client_user) self.client.get("/login") iti = factories.IssueTrackerIssueFactory( enabled=True, issue_tracked_obj=factories.IssueFactory() ) comment = factories.CommentFactory(description="test comment") expected_result = { "comment": params_builder.BaseIssueTrackerParamsBuilder.COMMENT_TMPL.format( author=client_user.name, comment=comment.description, model="Issue", link="http://issue_url.com", ) } with mock.patch.object(settings, "ISSUE_TRACKER_ENABLED", True): self.api.post(all_models.Relationship, { "relationship": { "source": {"id": iti.issue_tracked_obj.id, "type": "Issue"}, "destination": {"id": comment.id, "type": "comment"}, "context": None }, }) url_builder_mock.assert_called_once() update_issue_mock.assert_called_with(iti.issue_id, expected_result)
def test_new_linked_assessment(self, assmt_attrs, ticket_attrs, upd_mock): """Test link new Assessment to IssueTracker ticket sets correct fields""" with factories.single_commit(): audit = factories.AuditFactory() factories.IssueTrackerIssueFactory( enabled=True, issue_tracked_obj=audit ) assmt_request_payload = self.request_payload_builder(assmt_attrs, audit) response_payload = self.response_payload_builder(ticket_attrs) with mock.patch.object( assessment_integration.AssessmentTrackerHandler, '_is_tracker_enabled', return_value=True ): with mock.patch("ggrc.integrations.issues.Client.get_issue", return_value=response_payload) as get_mock: response = self.api.post(all_models.Assessment, assmt_request_payload) get_mock.assert_called_once() upd_mock.assert_called_once() self.assertEqual(response.status_code, 201) assmt_id = response.json.get("assessment").get("id") it_issue = models.IssuetrackerIssue.get_issue("Assessment", assmt_id) self.check_issuetracker_issue_fields(it_issue, assmt_request_payload)
def test_update_issuetracker_assignee(self, mocked_update_issue): """Test assignee sync in case it has been updated.""" email1 = "*****@*****.**" email2 = "*****@*****.**" assignee_role_id = AccessControlRole.query.filter_by( object_type="Assessment", name="Assignees" ).first().id assignees = [factories.PersonFactory(email=email2), factories.PersonFactory(email=email1)] iti_issue_id = [] iti = factories.IssueTrackerIssueFactory(enabled=True) iti_issue_id.append(iti.issue_id) asmt = iti.issue_tracked_obj with mock.patch.object(issue_tracker, '_is_issue_tracker_enabled', return_value=True): acl = [acl_helper.get_acl_json(assignee_role_id, assignee.id) for assignee in assignees] self.api.put(asmt, { "access_control_list": acl }) kwargs = {'status': 'ASSIGNED', 'component_id': None, 'severity': None, 'title': iti.title, 'hotlist_ids': [], 'priority': None, 'assignee': email1, 'verifier': email1, 'ccs': [email2]} mocked_update_issue.assert_called_once_with(iti_issue_id[0], kwargs)
def test_update_issuetracker_due_date(self, mocked_update_issue): """Test title sync in case it has been updated.""" with mock.patch.object(assessment_integration, '_is_issue_tracker_enabled', return_value=True): iti_issue_id = [] iti = factories.IssueTrackerIssueFactory(enabled=True) iti_issue_id.append(iti.issue_id) asmt = iti.issue_tracked_obj new_due_date = '2018-09-25' custom_fields = [{ 'name': 'Due Date', 'value': new_due_date, 'type': 'DATE', 'display_string': 'Due Date', }] self.api.put(asmt, {'start_date': new_due_date, 'title': 'title'}) kwargs = { 'status': 'ASSIGNED', 'component_id': None, 'severity': None, 'title': 'title', 'hotlist_ids': [], 'priority': None, 'custom_fields': custom_fields } mocked_update_issue.assert_called_once_with( iti_issue_id[0], kwargs) issue = db.session.query(models.IssuetrackerIssue).get(iti.id) self.assertEqual(issue.due_date.strftime("%Y-%m-%d"), new_due_date)
def test_assmt_default_values_from_default(self, missed_field, alias, value): """Test correct default value was set to {0} if audit doesn't have one""" expected_warning = expected_warning_for_default( line=3, column_name=missed_field, alias=alias) expected_messages = { "Assessment": { "row_warnings": {expected_warning}, } } with factories.single_commit(): audit = factories.AuditFactory() factories.IssueTrackerIssueFactory(issue_tracked_obj=audit) response = self.import_data( OrderedDict([ ("object_type", "Assessment"), ("Code*", "OBJ-1"), ("Audit*", audit.slug), ("Assignees*", "*****@*****.**"), ("Creators", "*****@*****.**"), ("Title", "Object Title"), (alias, value), ])) self._check_csv_response(response, expected_messages) obj = all_models.Assessment.query.one() self.assertEqual(str(obj.issue_tracker[missed_field]), str(default_values[missed_field]))
def test_sync_issue_statuses(self, issuetracker_status, issue_status): """Test updating issue statuses in GGRC.""" # Arrange test data. issue_tracker_issue_id = "1" iti = factories.IssueTrackerIssueFactory( enabled=True, issue_id=issue_tracker_issue_id, issue_tracked_obj=factories.IssueFactory(status="Draft")) batches = [{ issue_tracker_issue_id: { "status": issuetracker_status, "type": "BUG", "priority": "P2", "severity": "S2", } }] # Perform action. with mock.patch.object(sync_utils, "iter_issue_batches", return_value=batches): issue_sync_job.sync_issue_attributes() # Assert results. issue = all_models.Issue.query.get(iti.issue_tracked_obj.id) self.assertEquals(issue.status, issue_status)
def test_issue_tracker_error(self, update_issue_mock): """Test issue tracker errors. Issue in Issue tracker doesn't change state in case receiving an error. """ iti = factories.IssueTrackerIssueFactory( enabled=True, issue_tracked_obj=factories.IssueFactory() ) update_issue_mock.side_effect = integrations_errors.HttpError("data") issue_attrs = { "issue_tracker": { "enabled": True, "hotlist_id": "123", "issue_id": iti.issue_id, } } with mock.patch.object(settings, "ISSUE_TRACKER_ENABLED", True),\ mock.patch.object(all_models.IssuetrackerIssue, "create_or_update_from_dict") as update_info_mock: self.api.put(iti.issue_tracked_obj, issue_attrs) # Check that "enabled" flag hasn't been changed. self.assertTrue("enabled" not in update_info_mock.call_args[0][1])
def test_existing_issue_link(self, update_mock): """Test Issue link to another ticket """ iti = factories.IssueTrackerIssueFactory( enabled=True, issue_id=TICKET_ID, issue_tracked_obj=factories.IssueFactory()) new_ticket_id = TICKET_ID + 1 new_data = {"issue_id": new_ticket_id} issue_request_payload = self.put_request_payload_builder(new_data) response_payload = self.response_payload_builder(new_data) with mock.patch("ggrc.integrations.issues.Client.get_issue", return_value=response_payload) as get_mock: with mock.patch.object(integration_utils, "exclude_auditor_emails", return_value={ u"*****@*****.**", }): response = self.api.put(iti.issue_tracked_obj, issue_request_payload) get_mock.assert_called_once() self.assert200(response) # check if data was changed in our DB issue_id = response.json.get("issue").get("id") issue_tracker_issue = models.IssuetrackerIssue.get_issue( "Issue", issue_id) self.assertEqual(int(issue_tracker_issue.issue_id), new_ticket_id) # check detach comment was sent detach_comment_template = params_builder.IssueParamsBuilder.DETACH_TMPL comment = detach_comment_template.format(new_ticket_id=new_ticket_id) expected_args = (TICKET_ID, {"status": "OBSOLETE", "comment": comment}) self.assertEqual(expected_args, update_mock.call_args[0])
def test_ticket_generation_assmt_disallowed_on_create(self, status): """Test ticket generation disallowed for Assmt in {} status on update""" with factories.single_commit(): audit = factories.AuditFactory() factories.IssueTrackerIssueFactory( issue_tracked_obj=audit, enabled=True, ) expected_warning = (errors.WRONG_ASSESSMENT_TICKET_STATUS.format( line=3, column_name="Ticket Tracker Integration", )) expected_messages = { "Assessment": { "row_warnings": {expected_warning}, } } response = self.import_data( OrderedDict([ ("object_type", "Assessment"), ("Code*", "OBJ-1"), ("Audit*", audit.slug), ("Assignees*", "*****@*****.**"), ("Creators", "*****@*****.**"), ("Verifiers", "*****@*****.**"), ("Title", "Object Title"), ("State", status), ("Ticket Tracker Integration", "On"), ])) self._check_csv_response(response, expected_messages) obj = all_models.Assessment.query.one() self.assertFalse(obj.issue_tracker["enabled"])