def testProcessFormData_AcceptPhases(self): post_data = fake.PostData(name=['TestTemplate'], members_only=['on'], summary=['TLDR'], summary_must_be_edited=[''], content=['HEY WHY'], status=['Accepted'], owner=['*****@*****.**'], label=['label-One', 'label-Two'], custom_1=['NO'], custom_2=['MOOD'], components=['BackEnd'], component_required=['on'], owner_defaults_to_member=['on'], add_approvals=['on'], phase_0=['Canary'], phase_1=['Stable'], phase_2=[''], phase_3=[''], phase_4=[''], phase_5=[''], approval_3=['phase_0'], approval_4=['phase_1']) url = self.servlet.ProcessFormData(self.mr, post_data) self.assertTrue( '/templates/detail?saved=1&template=TestTemplate&' in url) self.services.template.UpdateIssueTemplateDef.assert_called_once_with( self.mr.cnxn, 47925, 12345, status='Accepted', component_required=True, phases=[ tracker_pb2.Phase(name='Canary', rank=0, phase_id=0), tracker_pb2.Phase(name='Stable', rank=1, phase_id=1) ], approval_values=[ tracker_pb2.ApprovalValue(approval_id=3, phase_id=0), tracker_pb2.ApprovalValue(approval_id=4, phase_id=1) ], name='TestTemplate', field_values=[ tracker_pb2.FieldValue(field_id=1, str_value='NO', derived=False), tracker_pb2.FieldValue(field_id=2, str_value='MOOD', derived=False) ], labels=['label-One', 'label-Two'], owner_defaults_to_member=True, admin_ids=[], content='HEY WHY', component_ids=[1], summary_must_be_edited=False, summary='TLDR', members_only=True, owner_id=333)
def testConvertApprovals(self): """Test we can convert ApprovalValues.""" cnxn = None config = tracker_bizobj.MakeDefaultProjectIssueConfig(789) config.field_defs = [ tracker_bizobj.MakeFieldDef( 1, 789, 'DesignReview', tracker_pb2.FieldTypes.APPROVAL_TYPE, None, None, False, False, False, None, None, None, False, None, None, None, None, 'doc', False), tracker_bizobj.MakeFieldDef( 2, 789, 'PrivacyReview', tracker_pb2.FieldTypes.APPROVAL_TYPE, None, None, False, False, False, 0, 99, None, False, None, None, None, None, 'doc', False), tracker_bizobj.MakeFieldDef( 5, 789, 'UXReview', tracker_pb2.FieldTypes.APPROVAL_TYPE, None, None, False, False, False, None, None, None, False, None, None, None, None, 'doc', False), tracker_bizobj.MakeFieldDef( 6, 789, 'Homepage', tracker_pb2.FieldTypes.URL_TYPE, None, None, False, False, False, None, None, None, False, None, None, None, None, 'doc', False), ] phases = [ tracker_pb2.Phase(phase_id=1), tracker_pb2.Phase(phase_id=2, name="JustAPhase", rank=3), ] ts = 1536260059 expected = [ api_pb2_v1.Approval( approvalName="DesignReview", approvers=[self.person_1], setter=self.person_1, status=api_pb2_v1.ApprovalStatus.needsReview, setOn=datetime.datetime.fromtimestamp(ts), ), api_pb2_v1.Approval( approvalName="UXReview", approvers=[self.person_1], status=api_pb2_v1.ApprovalStatus.notSet, phaseName="JustAPhase", ), ] avs = [ tracker_pb2.ApprovalValue( approval_id=1, approver_ids=[111], setter_id=111, status=tracker_pb2.ApprovalStatus.NEEDS_REVIEW, set_on=ts), tracker_pb2.ApprovalValue( approval_id=5, approver_ids=[111], phase_id=2) ] actual = api_pb2_v1_helpers.convert_approvals( cnxn, avs, self.services, config, phases) self.assertEqual(actual, expected)
def testProcessFormData_AcceptPhases(self): self.services.template.GetTemplateByName = Mock(return_value=None) post_data = fake.PostData(name=['secondtemplate'], members_only=['on'], summary=['TLDR'], summary_must_be_edited=['on'], content=['HEY WHY'], status=['Accepted'], label=['label-One', 'label-Two'], custom_1=['NO'], component_required=['on'], owner_defaults_to_member=['no'], add_approvals=['on'], phase_0=['Canary'], phase_1=['Stable'], phase_2=[''], phase_3=[''], phase_4=[''], phase_5=[''], approval_2=['phase_0'], approval_3=['phase_1'], approval_3_required=['on']) url = self.servlet.ProcessFormData(self.mr, post_data) self.assertTrue('/adminTemplates?saved=1&ts' in url) fv = tracker_pb2.FieldValue(field_id=1, str_value='NO', derived=False) phases = [ tracker_pb2.Phase(name='Canary', rank=0, phase_id=0), tracker_pb2.Phase(name='Stable', rank=1, phase_id=1) ] approval_values = [ tracker_pb2.ApprovalValue(approval_id=2, phase_id=0), tracker_pb2.ApprovalValue( approval_id=3, status=tracker_pb2.ApprovalStatus( tracker_pb2.ApprovalStatus.NEEDS_REVIEW), phase_id=1) ] self.services.template.CreateIssueTemplateDef.assert_called_once_with( self.mr.cnxn, 47925, 'secondtemplate', 'HEY WHY', 'TLDR', True, 'Accepted', True, False, True, 0, ['label-One', 'label-Two'], [], [], [fv], phases=phases, approval_values=approval_values)
def testIndexOrLexicalList_ApprovalStatus(self): art = fake.MakeTestIssue(789, 1, 'sum 2', 'New', 111) art.labels = ['samename-value1'] art.approval_values = [tracker_pb2.ApprovalValue(approval_id=4)] all_field_defs = [ tracker_bizobj.MakeFieldDef(3, 789, 'samename', tracker_pb2.FieldTypes.INT_TYPE, None, None, False, False, False, None, None, None, False, None, None, None, None, 'cow spots', False), tracker_bizobj.MakeFieldDef(4, 788, 'samename', tracker_pb2.FieldTypes.APPROVAL_TYPE, None, None, False, False, False, None, None, None, False, None, None, None, None, 'cow spots', False) ] accessor = sorting._IndexOrLexicalList([], all_field_defs, 'samename', {}) self.assertEqual([0, 'value1'], accessor(art)) neg_accessor = MakeDescending(accessor) self.assertEqual( [sorting.DescendingValue('value1'), sorting.DescendingValue(0)], neg_accessor(art))
def testIndexOrLexicalList_ApprovalApprover(self): art = art = fake.MakeTestIssue(789, 1, 'sum 2', 'New', 111) art.labels = ['samename-approver-value1'] art.approval_values = [ tracker_pb2.ApprovalValue(approval_id=4, approver_ids=[333]) ] all_field_defs = [ tracker_bizobj.MakeFieldDef(4, 788, 'samename', tracker_pb2.FieldTypes.APPROVAL_TYPE, None, None, False, False, False, None, None, None, False, None, None, None, None, 'cow spots', False) ] users_by_id = { 333: framework_views.StuffUserView(333, '*****@*****.**', True) } accessor = sorting._IndexOrLexicalList([], all_field_defs, 'samename-approver', users_by_id) self.assertEqual(['*****@*****.**', 'value1'], accessor(art)) neg_accessor = MakeDescending(accessor) self.assertEqual([ sorting.DescendingValue('value1'), sorting.DescendingValue('*****@*****.**') ], neg_accessor(art))
def testUpdateIssueTemplateDef(self): av_20 = tracker_pb2.ApprovalValue(approval_id=20, phase_id=11) av_21 = tracker_pb2.ApprovalValue(approval_id=21, phase_id=11) approval_values = [av_20, av_21] phases = [tracker_pb2.Phase(name='Canary', phase_id=11, rank=11)] self.template_service.UpdateIssueTemplateDef( self.cnxn, 789, 1, content='content', summary='summary', component_required=True, labels=[], admin_ids=[111], phases=phases, approval_values=approval_values) new_values = dict(content='content', summary='summary', component_required=True) self.template_service.template_tbl.Update\ .assert_called_once_with(self.cnxn, new_values, id=1, commit=False) self.template_service.template2label_tbl.Delete\ .assert_called_once_with(self.cnxn, template_id=1, commit=False) self.template_service.template2label_tbl.InsertRows\ .assert_called_once_with(self.cnxn, template_svc.TEMPLATE2LABEL_COLS, [], commit=False) self.template_service.template2admin_tbl.Delete\ .assert_called_once_with(self.cnxn, template_id=1, commit=False) self.template_service.template2admin_tbl.InsertRows\ .assert_called_once_with(self.cnxn, template_svc.TEMPLATE2ADMIN_COLS, [(1, 111)], commit=False) self.template_service.template2approvalvalue_tbl.Delete\ .assert_called_once_with(self.cnxn, template_id=1, commit=False) self.template_service.issuephasedef_tbl.InsertRow\ .assert_called_once_with(self.cnxn, name='Canary', rank=11, commit=False) self.template_service.template2approvalvalue_tbl.InsertRows\ .assert_called_once_with(self.cnxn, template_svc.TEMPLATE2APPROVALVALUE_COLS, [(20, 1, 1, 'not_set'), (21, 1, 1, 'not_set')], commit=False) self.cnxn.Commit.assert_called_once_with() self.template_service.template_set_2lc.InvalidateKeys\ .assert_called_once_with(self.cnxn, [789]) self.template_service.template_def_2lc.InvalidateKeys\ .assert_called_once_with(self.cnxn, [1])
def CreateApprovalCopies(self, avs): return [ tracker_pb2.ApprovalValue(approval_id=av.approval_id, status=av.status, setter_id=av.setter_id, set_on=av.set_on, phase_id=av.phase_id) for av in avs ]
def testGatherPageData_Approvals(self): user = self.services.user.TestAddUser('user@invalid', 100) mr = testing_helpers.MakeMonorailRequest( path='/p/proj/issues/entry', services=self.services) mr.auth.user_view = framework_views.MakeUserView( 'cnxn', self.services.user, 100) mr.template_name = 'rutabaga' self.mox.StubOutWithMock(self.services.user, 'GetUser') self.services.user.GetUser( mox.IgnoreArg(), mox.IgnoreArg()).MultipleTimes().AndReturn(user) self.mox.ReplayAll() config = self.services.config.GetProjectConfig(mr.cnxn, mr.project_id) config.field_defs = [ tracker_bizobj.MakeFieldDef( 24, mr.project_id, 'UXReview', tracker_pb2.FieldTypes.APPROVAL_TYPE, None, '', False, False, False, None, None, '', False, '', '', tracker_pb2.NotifyTriggers.NEVER, 'no_action', 'doc', False)] self.services.config.StoreConfig(mr.cnxn, config) template = tracker_pb2.TemplateDef() template.phases = [tracker_pb2.Phase( phase_id=1, rank=4, name='Stable')] template.approval_values = [tracker_pb2.ApprovalValue( approval_id=24, phase_id=1, status=tracker_pb2.ApprovalStatus.NEEDS_REVIEW)] self.services.template.GetTemplateByName.return_value = template page_data = self.servlet.GatherPageData(mr) self.mox.VerifyAll() self.assertEqual(page_data['approvals'][0].field_name, 'UXReview') self.assertEqual(page_data['initial_phases'][0], tracker_pb2.Phase(phase_id=1, name='Stable', rank=4)) self.assertEqual(page_data['prechecked_approvals'], ['24_phase_0']) self.assertEqual(page_data['required_approval_ids'], [24]) # phase fields row shown when config contains phase fields. config.field_defs.append(tracker_bizobj.MakeFieldDef( 26, mr.project_id, 'GateTarget', tracker_pb2.FieldTypes.INT_TYPE, None, '', False, False, False, None, None, '', False, '', '', tracker_pb2.NotifyTriggers.NEVER, 'no_action', 'doc', False, is_phase_field=True)) self.services.config.StoreConfig(mr.cnxn, config) page_data = self.servlet.GatherPageData(mr) self.assertEqual(page_data['issue_phase_names'], ['stable']) # approval subfields in config hidden when chosen template does not contain # its parent approval template = tracker_pb2.TemplateDef() self.services.template.GetTemplateByName.return_value = template page_data = self.servlet.GatherPageData(mr) self.assertEqual(page_data['approvals'], []) # phase fields row hidden when template has no phases self.assertEqual(page_data['issue_phase_names'], [])
def testAttachDefaultApprovers(self): config = tracker_bizobj.MakeDefaultProjectIssueConfig(789) config.approval_defs = [ tracker_pb2.ApprovalDef( approval_id=23, approver_ids=[222], survey='Question?'), tracker_pb2.ApprovalDef( approval_id=24, approver_ids=[111], survey='Question?')] approval_values = [tracker_pb2.ApprovalValue( approval_id=24, phase_id=1, status=tracker_pb2.ApprovalStatus.NEEDS_REVIEW)] issueentry._AttachDefaultApprovers(config, approval_values) self.assertEqual(approval_values[0].approver_ids, [111])
def testConvertApprovals_errors(self): """we dont crash on bad requests.""" cnxn = None config = tracker_bizobj.MakeDefaultProjectIssueConfig(789) config.field_defs = [ tracker_bizobj.MakeFieldDef(1, 789, 'DesignReview', tracker_pb2.FieldTypes.APPROVAL_TYPE, None, None, False, False, False, None, None, None, False, None, None, None, None, 'doc', False), tracker_bizobj.MakeFieldDef(5, 789, 'UXReview', tracker_pb2.FieldTypes.APPROVAL_TYPE, None, None, False, False, False, None, None, None, False, None, None, None, None, 'doc', False), tracker_bizobj.MakeFieldDef(3, 789, 'DesignDoc', tracker_pb2.FieldTypes.URL_TYPE, None, None, False, False, False, 0, 99, None, False, None, None, None, None, 'doc', False), ] phases = [] avs = [ tracker_pb2.ApprovalValue(approval_id=1, approver_ids=[111]), # phase does not exist tracker_pb2.ApprovalValue(approval_id=2, phase_id=2), tracker_pb2.ApprovalValue( approval_id=3), # field 3 is not an approval tracker_pb2.ApprovalValue(approval_id=4), # field 4 does not exist ] expected = [ api_pb2_v1.Approval(approvalName="DesignReview", approvers=[self.person_1], status=api_pb2_v1.ApprovalStatus.notSet) ] actual = api_pb2_v1_helpers.convert_approvals(cnxn, avs, self.services, config, phases) self.assertEqual(actual, expected)
def testGatherApprovalsPageData(self): self.fd_3.is_deleted = True self.config.field_defs = [self.fd_3, self.fd_4, self.fd_5] approval_values = [ tracker_pb2.ApprovalValue(approval_id=3, phase_id=8), tracker_pb2.ApprovalValue( approval_id=4, phase_id=9, status=tracker_pb2.ApprovalStatus.NEEDS_REVIEW), tracker_pb2.ApprovalValue(approval_id=5) ] tmpl_phases = [ tracker_pb2.Phase(phase_id=8, rank=1, name='deletednoshow'), tracker_pb2.Phase(phase_id=9, rank=2, name='notdeleted') ] (prechecked_approvals, required_approval_ids, phases) = template_helpers.GatherApprovalsPageData( approval_values, tmpl_phases, self.config) self.assertItemsEqual(prechecked_approvals, ['4_phase_0', '5']) self.assertEqual(required_approval_ids, [4]) self.assertEqual(phases[0], tmpl_phases[1]) self.assertIsNone(phases[1].name) self.assertEqual(len(phases), 6)
def setUp(self): self.config = tracker_bizobj.MakeDefaultProjectIssueConfig(789) self.config.field_defs = [ tracker_bizobj.MakeFieldDef( 1, 789, 'Goats', tracker_pb2.FieldTypes.INT_TYPE, None, None, False, False, False, None, None, None, False, None, None, None, None, 'Num of Goats in the season', False, is_phase_field=True), tracker_bizobj.MakeFieldDef( 2, 789, 'DogNames', tracker_pb2.FieldTypes.STR_TYPE, None, None, False, False, False, None, None, None, False, None, None, None, None, 'good dog names', False), tracker_bizobj.MakeFieldDef( 3, 789, 'Approval', tracker_pb2.FieldTypes.APPROVAL_TYPE, None, None, False, False, False, None, None, None, False, None, None, None, None, 'Tracks review from cows', False) ] self.config.approval_defs = [tracker_pb2.ApprovalDef(approval_id=3)] self.issue = MakeTestIssue( local_id=1, issue_id=100001, summary='One') self.issue.field_values = [ tracker_bizobj.MakeFieldValue( 1, 34, None, None, None, None, False, phase_id=23), tracker_bizobj.MakeFieldValue( 1, 35, None, None, None, None, False, phase_id=24), tracker_bizobj.MakeFieldValue( 2, None, 'Waffles', None, None, None, False), ] self.issue.phases = [ tracker_pb2.Phase(phase_id=23, name='winter'), tracker_pb2.Phase(phase_id=24, name='summer')] self.issue.approval_values = [ tracker_pb2.ApprovalValue( approval_id=3, approver_ids=[111, 222, 333])] self.users_by_id = { 111: framework_views.StuffUserView(111, '*****@*****.**', False), 222: framework_views.StuffUserView(222, '*****@*****.**', True), } self.summary_table_cell_kws = { 'col': None, 'users_by_id': {}, 'non_col_labels': [('lab', False)], 'label_values': {}, 'related_issues': {}, 'config': 'fake_config', }
def testNotifyApprovalChangeTask_GetApprovalEmailRecipients(self): task = notify.NotifyApprovalChangeTask(request=None, response=None, services=self.services) issue = fake.MakeTestIssue(789, 1, 'summary', 'New', 111) approval_value = tracker_pb2.ApprovalValue( approver_ids=[222, 333], status=tracker_pb2.ApprovalStatus.APPROVED) comment = tracker_pb2.IssueComment(project_id=789, user_id=1, issue_id=78901) # Comment with not amendments notifies everyone. rids = task._GetApprovalEmailRecipients(approval_value, comment, issue, [777, 888]) self.assertItemsEqual(rids, [111, 222, 333, 777, 888]) # New APPROVED status notifies owners and any_comment users. amendment = tracker_bizobj.MakeApprovalStatusAmendment( tracker_pb2.ApprovalStatus.APPROVED) comment.amendments = [amendment] rids = task._GetApprovalEmailRecipients(approval_value, comment, issue, [777, 888]) self.assertItemsEqual(rids, [111, 777, 888]) # New REVIEW_REQUESTED status notifies approvers. approval_value.status = tracker_pb2.ApprovalStatus.REVIEW_REQUESTED amendment = tracker_bizobj.MakeApprovalStatusAmendment( tracker_pb2.ApprovalStatus.REVIEW_REQUESTED) comment.amendments = [amendment] rids = task._GetApprovalEmailRecipients(approval_value, comment, issue, [777, 888]) self.assertItemsEqual(rids, [222, 333]) # Approvers change notifies everyone. amendment = tracker_bizobj.MakeApprovalApproversAmendment([222], [555]) comment.amendments = [amendment] approval_value.approver_ids = [222] rids = task._GetApprovalEmailRecipients(approval_value, comment, issue, [777], omit_ids=[444, 333]) self.assertItemsEqual(rids, [111, 222, 555, 777])
def _GetPhasesAndApprovalsFromParsed(mr, phase_names, approvals_to_phase_idx, required_approval_ids): """Get Phase PBs from a parsed phase_names and approvals_by_phase_idx.""" phases = [] approvals = [] valid_phase_names = [] for name in phase_names: if name: if not tracker_constants.PHASE_NAME_RE.match(name): mr.errors.phase_approvals = 'Invalid gate name(s).' return phases, approvals valid_phase_names.append(name) if len(valid_phase_names) != len( set(name.lower() for name in valid_phase_names)): mr.errors.phase_approvals = 'Duplicate gate names.' return phases, approvals valid_phase_idxs = [idx for idx, name in enumerate(phase_names) if name] if set(valid_phase_idxs) != set( [idx for idx in approvals_to_phase_idx.values() if idx is not None]): mr.errors.phase_approvals = 'Defined gates must have assigned approvals.' return phases, approvals # Distributing the ranks over a wider range is not necessary since # any edits to template phases will cause a complete rewrite. # phase_id is temporarily the idx for keeping track of which approvals # belong to which phases. for idx, phase_name in enumerate(phase_names): if phase_name: phase = tracker_pb2.Phase(name=phase_name, rank=idx, phase_id=idx) phases.append(phase) for approval_id, phase_idx in approvals_to_phase_idx.items(): av = tracker_pb2.ApprovalValue(approval_id=approval_id, phase_id=phase_idx) if approval_id in required_approval_ids: av.status = tracker_pb2.ApprovalStatus.NEEDS_REVIEW approvals.append(av) return phases, approvals
def testCreateIssueTemplateDef(self): fv = tracker_bizobj.MakeFieldValue(1, None, 'somestring', None, None, None, False) av_23 = tracker_pb2.ApprovalValue( approval_id=23, phase_id=11, status=tracker_pb2.ApprovalStatus.NEEDS_REVIEW) av_24 = tracker_pb2.ApprovalValue(approval_id=24, phase_id=11) approval_values = [av_23, av_24] phases = [tracker_pb2.Phase(name='Canary', rank=11, phase_id=11)] actual_template_id = self.template_service.CreateIssueTemplateDef( self.cnxn, 789, 'template', 'content', 'summary', True, 'Available', True, True, True, owner_id=111, labels=['label'], component_ids=[3], admin_ids=[222], field_values=[fv], phases=phases, approval_values=approval_values) self.assertEqual(1, actual_template_id) self.template_service.template_tbl.InsertRow\ .assert_called_once_with(self.cnxn, project_id=789, name='template', content='content', summary='summary', summary_must_be_edited=True, owner_id=111, status='Available', members_only=True, owner_defaults_to_member=True, component_required=True, commit=False) self.template_service.template2label_tbl.InsertRows\ .assert_called_once_with(self.cnxn, template_svc.TEMPLATE2LABEL_COLS, [(1, 'label')], commit=False) self.template_service.template2component_tbl.InsertRows\ .assert_called_once_with(self.cnxn, template_svc.TEMPLATE2COMPONENT_COLS, [(1, 3)], commit=False) self.template_service.template2admin_tbl.InsertRows\ .assert_called_once_with(self.cnxn, template_svc.TEMPLATE2ADMIN_COLS, [(1, 222)], commit=False) self.template_service.template2fieldvalue_tbl.InsertRows\ .assert_called_once_with(self.cnxn, template_svc.TEMPLATE2FIELDVALUE_COLS, [(1, 1, None, 'somestring', None, None, None)], commit=False) self.template_service.issuephasedef_tbl.InsertRow\ .assert_called_once_with(self.cnxn, name='Canary', rank=11, commit=False) self.template_service.template2approvalvalue_tbl.InsertRows\ .assert_called_once_with(self.cnxn, template_svc.TEMPLATE2APPROVALVALUE_COLS, [(23, 1, 81, 'needs_review'), (24, 1, 81, 'not_set')], commit=False) self.cnxn.Commit.assert_called_once_with() self.template_service.template_set_2lc.InvalidateKeys\ .assert_called_once_with(self.cnxn, [789])
def testConvertIssue(self): """Convert an internal Issue PB to an IssueWrapper API PB.""" self.services.project.TestAddProject( 'test-project', owner_ids=[2], project_id=12345) self.services.user.TestAddUser('*****@*****.**', 111) mar = mock.Mock() mar.cnxn = None mar.project_name = 'test-project' mar.project_id = 12345 mar.auth.effective_ids = {111} mar.perms = permissions.READ_ONLY_PERMISSIONSET mar.profiler = profiler.Profiler() mar.config = tracker_bizobj.MakeDefaultProjectIssueConfig(12345) mar.config.field_defs = [ tracker_bizobj.MakeFieldDef( 1, 12345, 'EstDays', tracker_pb2.FieldTypes.INT_TYPE, None, None, False, False, False, None, None, None, False, None, None, None, None, 'doc', False, approval_id=2), tracker_bizobj.MakeFieldDef( 2, 12345, 'DesignReview', tracker_pb2.FieldTypes.APPROVAL_TYPE, None, None, False, False, False, None, None, None, False, None, None, None, None, 'doc', False), tracker_bizobj.MakeFieldDef( 3, 12345, 'StringField', tracker_pb2.FieldTypes.STR_TYPE, None, None, False, False, False, None, None, None, False, None, None, None, None, 'doc', False), tracker_bizobj.MakeFieldDef( 4, 12345, 'DressReview', tracker_pb2.FieldTypes.APPROVAL_TYPE, None, None, False, False, False, None, None, None, False, None, None, None, None, 'doc', False), ] self.services.config.StoreConfig(mar.cnxn, mar.config) now = 1472067725 now_dt = datetime.datetime.fromtimestamp(now) fvs = [ tracker_bizobj.MakeFieldValue( 1, 4, None, None, None, None, False, phase_id=4), tracker_bizobj.MakeFieldValue( 3, None, 'string', None, None, None, False, phase_id=4), # missing phase tracker_bizobj.MakeFieldValue( 3, None, u'\xe2\x9d\xa4\xef\xb8\x8f', None, None, None, False, phase_id=2), ] phases = [ tracker_pb2.Phase(phase_id=3, name="JustAPhase", rank=4), tracker_pb2.Phase(phase_id=4, name="NotAPhase", rank=9) ] approval_values = [ tracker_pb2.ApprovalValue( approval_id=2, phase_id=3, approver_ids=[111]), tracker_pb2.ApprovalValue(approval_id=4, approver_ids=[111]) ] issue = fake.MakeTestIssue( 12345, 1, 'one', 'New', 111, field_values=fvs, approval_values=approval_values, phases=phases) issue.opened_timestamp = now issue.owner_modified_timestamp = now issue.status_modified_timestamp = now issue.component_modified_timestamp = now # TODO(jrobbins): set up a lot more fields. for cls in [api_pb2_v1.IssueWrapper, api_pb2_v1.IssuesGetInsertResponse]: result = api_pb2_v1_helpers.convert_issue(cls, issue, mar, self.services) self.assertEquals(1, result.id) self.assertEquals('one', result.title) self.assertEquals('one', result.summary) self.assertEquals(now_dt, result.published) self.assertEquals(now_dt, result.owner_modified) self.assertEquals(now_dt, result.status_modified) self.assertEquals(now_dt, result.component_modified) self.assertEquals( result.fieldValues, [api_pb2_v1.FieldValue( fieldName='EstDays', fieldValue='4', approvalName='DesignReview', derived=False), api_pb2_v1.FieldValue(fieldName='StringField', fieldValue='string', phaseName="NotAPhase", derived=False), api_pb2_v1.FieldValue(fieldName='StringField', fieldValue=u'\xe2\x9d\xa4\xef\xb8\x8f', derived=False), ] ) self.assertEqual( result.approvalValues, [api_pb2_v1.Approval( approvalName="DesignReview", approvers=[self.person_1], status=api_pb2_v1.ApprovalStatus.notSet, phaseName="JustAPhase", ), api_pb2_v1.Approval( approvalName="DressReview", approvers=[self.person_1], status=api_pb2_v1.ApprovalStatus.notSet, )] ) self.assertEqual( result.phases, [api_pb2_v1.Phase(phaseName="JustAPhase", rank=4), api_pb2_v1.Phase(phaseName="NotAPhase", rank=9) ])
def testMakeIssueJSON(self): config = self.services.config.GetProjectConfig(self.cnxn, 789) config.field_defs.extend([ tracker_pb2.FieldDef( field_id=1, field_name='UXReview', field_type=tracker_pb2.FieldTypes.APPROVAL_TYPE), tracker_pb2.FieldDef(field_id=2, field_name='approvalsubfield', field_type=tracker_pb2.FieldTypes.STR_TYPE, approval_id=1), tracker_pb2.FieldDef(field_id=3, field_name='phasefield', field_type=tracker_pb2.FieldTypes.INT_TYPE, is_phase_field=True), tracker_pb2.FieldDef(field_id=4, field_name='normalfield', field_type=tracker_pb2.FieldTypes.STR_TYPE) ]) self.services.config.StoreConfig(self.cnxn, config) phases = [ tracker_pb2.Phase(phase_id=1, name='Phase1', rank=1), tracker_pb2.Phase(phase_id=2, name='Phase2', rank=2) ] avs = [ tracker_pb2.ApprovalValue( approval_id=1, status=tracker_pb2.ApprovalStatus.APPROVED, setter_id=111, set_on=7, approver_ids=[333, 444], phase_id=1) ] fvs = [ tracker_pb2.FieldValue(field_id=2, str_value='two'), tracker_pb2.FieldValue(field_id=3, int_value=3, phase_id=2), tracker_pb2.FieldValue(field_id=4, str_value='four') ] labels = ['test', 'Type-FLT-Launch'] issue = fake.MakeTestIssue(self.project.project_id, 1, 'summary', 'Open', 111, labels=labels, issue_id=78901, reporter_id=222, opened_timestamp=1, closed_timestamp=2, modified_timestamp=3, project_name='project', field_values=fvs, phases=phases, approval_values=avs) email_dict = { 111: '*****@*****.**', 222: '*****@*****.**', 333: '*****@*****.**', 444: '*****@*****.**' } comment_list = [ tracker_pb2.IssueComment(content='simple'), tracker_pb2.IssueComment(content='issue desc', is_description=True) ] starrer_id_list = [222, 333] issue_JSON = self.jsonfeed._MakeIssueJSON(self.mr, issue, email_dict, comment_list, starrer_id_list) expected_JSON = { 'local_id': 1, 'reporter': '*****@*****.**', 'summary': 'summary', 'owner': '*****@*****.**', 'status': 'Open', 'cc': [], 'labels': labels, 'phases': [{ 'id': 1, 'name': 'Phase1', 'rank': 1 }, { 'id': 2, 'name': 'Phase2', 'rank': 2 }], 'fields': [{ 'field': 'approvalsubfield', 'phase': None, 'approval': 'UXReview', 'str_value': 'two' }, { 'field': 'phasefield', 'phase': 'Phase2', 'int_value': 3 }, { 'field': 'normalfield', 'phase': None, 'str_value': 'four' }], 'approvals': [{ 'approval': 'UXReview', 'status': 'APPROVED', 'setter': '*****@*****.**', 'set_on': 7, 'approvers': ['*****@*****.**', '*****@*****.**'], 'phase': 'Phase1' }], 'starrers': ['*****@*****.**', '*****@*****.**'], 'comments': [ { 'content': 'simple', 'timestamp': None, 'amendments': [], 'commenter': None, 'attachments': [], 'description_num': None }, { 'content': 'issue desc', 'timestamp': None, 'amendments': [], 'commenter': None, 'attachments': [], 'description_num': '1' }, ], 'opened': 1, 'modified': 3, 'closed': 2, } self.assertEqual(expected_JSON, issue_JSON)
def FetchItems(self, cnxn, keys): """On RAM and memcache miss, hit the database. Args: cnxn: A MonorailConnection. keys: A list of template IDs (ints). Returns: A dict of {template_id: TemplateDef}. """ template_dict = {} # Fetch template rows and relations. template_rows = self.template_service.template_tbl.Select( cnxn, cols=TEMPLATE_COLS, id=keys, order_by=[('name', [])]) template2label_rows = self.template_service.\ template2label_tbl.Select( cnxn, cols=TEMPLATE2LABEL_COLS, template_id=keys) template2component_rows = self.template_service.\ template2component_tbl.Select( cnxn, cols=TEMPLATE2COMPONENT_COLS, template_id=keys) template2admin_rows = self.template_service.template2admin_tbl.Select( cnxn, cols=TEMPLATE2ADMIN_COLS, template_id=keys) template2fieldvalue_rows = self.template_service.\ template2fieldvalue_tbl.Select( cnxn, cols=TEMPLATE2FIELDVALUE_COLS, template_id=keys) template2approvalvalue_rows = self.template_service.\ template2approvalvalue_tbl.Select( cnxn, cols=TEMPLATE2APPROVALVALUE_COLS, template_id=keys) phase_ids = [av_row[2] for av_row in template2approvalvalue_rows] phase_rows = self.template_service.issuephasedef_tbl.Select( cnxn, cols=ISSUEPHASEDEF_COLS, id=list(set(phase_ids))) # Build TemplateDef with all related data. for template_row in template_rows: template = UnpackTemplate(template_row) template_dict[template.template_id] = template for template2label_row in template2label_rows: template_id, label = template2label_row template = template_dict.get(template_id) if template: template.labels.append(label) for template2component_row in template2component_rows: template_id, component_id = template2component_row template = template_dict.get(template_id) if template: template.component_ids.append(component_id) for template2admin_row in template2admin_rows: template_id, admin_id = template2admin_row template = template_dict.get(template_id) if template: template.admin_ids.append(admin_id) for fv_row in template2fieldvalue_rows: (template_id, field_id, int_value, str_value, user_id, date_value, url_value) = fv_row fv = tracker_bizobj.MakeFieldValue( field_id, int_value, str_value, user_id, date_value, url_value, False) template = template_dict.get(template_id) if template: template.field_values.append(fv) phases_by_id = {} for phase_row in phase_rows: (phase_id, name, rank) = phase_row phase = tracker_pb2.Phase( phase_id=phase_id, name=name, rank=rank) phases_by_id[phase_id] = phase # Note: there is no templateapproval2approver_tbl. for av_row in template2approvalvalue_rows: (approval_id, template_id, phase_id, status) = av_row approval_value = tracker_pb2.ApprovalValue( approval_id=approval_id, phase_id=phase_id, status=tracker_pb2.ApprovalStatus(status.upper())) template = template_dict.get(template_id) if template: template.approval_values.append(approval_value) phase = phases_by_id.get(phase_id) if phase and phase not in template.phases: template_dict.get(template_id).phases.append(phase) return template_dict
def testNotifyApprovalChangeTask_Normal(self): config = self.services.config.GetProjectConfig('cnxn', 12345) config.field_defs = [ # issue's User field with any_comment is notified. tracker_bizobj.MakeFieldDef( 121, 12345, 'TL', tracker_pb2.FieldTypes.USER_TYPE, '', '', False, False, False, None, None, None, False, '', None, tracker_pb2.NotifyTriggers.ANY_COMMENT, 'no_action', 'TL, notified on everything', False), # issue's User field with never is not notified. tracker_bizobj.MakeFieldDef( 122, 12345, 'silentTL', tracker_pb2.FieldTypes.USER_TYPE, '', '', False, False, False, None, None, None, False, '', None, tracker_pb2.NotifyTriggers.NEVER, 'no_action', 'TL, notified on nothing', False), # approval's User field with any_comment is notified. tracker_bizobj.MakeFieldDef(123, 12345, 'otherapprovalTL', tracker_pb2.FieldTypes.USER_TYPE, '', '', False, False, False, None, None, None, False, '', None, tracker_pb2.NotifyTriggers.ANY_COMMENT, 'no_action', 'TL on the approvers team', False, approval_id=3), # another approval's User field with any_comment is not notified. tracker_bizobj.MakeFieldDef(124, 12345, 'otherapprovalTL', tracker_pb2.FieldTypes.USER_TYPE, '', '', False, False, False, None, None, None, False, '', None, tracker_pb2.NotifyTriggers.ANY_COMMENT, 'no_action', 'TL on another approvers team', False, approval_id=4), tracker_bizobj.MakeFieldDef(3, 12345, 'Goat-Approval', tracker_pb2.FieldTypes.APPROVAL_TYPE, '', '', False, False, False, None, None, None, False, '', None, tracker_pb2.NotifyTriggers.NEVER, 'no_action', 'Get Approval from Goats', False) ] self.services.config.StoreConfig('cnxn', config) # Custom user_type field TLs self.services.user.TestAddUser('*****@*****.**', 111) self.services.user.TestAddUser('*****@*****.**', 222) self.services.user.TestAddUser('*****@*****.**', 333) self.services.user.TestAddUser('*****@*****.**', 444) # Approvers self.services.user.TestAddUser('*****@*****.**', 777) self.services.user.TestAddUser('*****@*****.**', 888) self.services.user.TestAddUser('*****@*****.**', 999) self.services.user.TestAddUser('*****@*****.**', 666) self.services.user.TestAddUser('*****@*****.**', 661) self.services.user.TestAddUser('*****@*****.**', 662) self.services.user.TestAddUser('*****@*****.**', 663) self.services.usergroup.TestAddGroupSettings( 666, '*****@*****.**') self.services.usergroup.TestAddMembers(666, [661, 662, 663]) canary_phase = tracker_pb2.Phase(name='Canary', phase_id=1, rank=1) approval_values = [ tracker_pb2.ApprovalValue(approval_id=3, approver_ids=[888, 999, 666, 661]) ] approval_issue = MakeTestIssue(project_id=12345, local_id=2, owner_id=2, reporter_id=1, is_spam=True) approval_issue.phases = [canary_phase] approval_issue.approval_values = approval_values approval_issue.field_values = [ tracker_bizobj.MakeFieldValue(121, None, None, 111, None, None, False), tracker_bizobj.MakeFieldValue(122, None, None, 222, None, None, False), tracker_bizobj.MakeFieldValue(123, None, None, 333, None, None, False), tracker_bizobj.MakeFieldValue(124, None, None, 444, None, None, False), ] self.services.issue.TestAddIssue(approval_issue) amend = tracker_bizobj.MakeApprovalApproversAmendment([888], [777]) comment = tracker_pb2.IssueComment(project_id=12345, user_id=999, issue_id=approval_issue.issue_id, amendments=[amend], timestamp=1234567890, content='just a comment.') attach = tracker_pb2.Attachment(attachment_id=4567, filename='sploot.jpg', mimetype='image/png', gcs_object_id='/pid/attachments/abcd', filesize=(1024 * 1023)) comment.attachments.append(attach) self.services.issue.TestAddComment(comment, approval_issue.local_id) self.services.issue.TestAddAttachment(attach, comment.id, approval_issue.issue_id) task = notify.NotifyApprovalChangeTask(request=None, response=None, services=self.services) params = { 'send_email': 1, 'issue_id': approval_issue.issue_id, 'approval_id': 3, 'comment_id': comment.id, } mr = testing_helpers.MakeMonorailRequest(user_info={'user_id': 1}, params=params, method='POST', services=self.services) result = task.HandleRequest(mr) self.assertTrue('just a comment' in result['tasks'][0]['body']) self.assertTrue('Approvers: -approver' in result['tasks'][0]['body']) self.assertTrue('sploot.jpg' in result['tasks'][0]['body']) self.assertTrue( '/issues/attachment?aid=4567' in result['tasks'][0]['body']) self.assertItemsEqual([ '*****@*****.**', '*****@*****.**', '*****@*****.**', '*****@*****.**', '*****@*****.**', '*****@*****.**', '*****@*****.**', '*****@*****.**' ], result['notified']) # Test no approvers/groups notified # Status change to NEED_INFO does not email approvers. amend2 = tracker_bizobj.MakeApprovalStatusAmendment( tracker_pb2.ApprovalStatus.NEED_INFO) comment2 = tracker_pb2.IssueComment(project_id=12345, user_id=999, issue_id=approval_issue.issue_id, amendments=[amend2], timestamp=1234567891, content='') self.services.issue.TestAddComment(comment2, approval_issue.local_id) task = notify.NotifyApprovalChangeTask(request=None, response=None, services=self.services) params = { 'send_email': 1, 'issue_id': approval_issue.issue_id, 'approval_id': 3, 'comment_id': comment2.id, } mr = testing_helpers.MakeMonorailRequest(user_info={'user_id': 1}, params=params, method='POST', services=self.services) result = task.HandleRequest(mr) self.assertTrue('Status: need_info' in result['tasks'][0]['body']) self.assertItemsEqual( ['*****@*****.**', '*****@*****.**', '*****@*****.**'], result['notified'])
def testFetchItems_Normal(self): template_9_row = (9, 1, 'template-9', 'content', 'summary', False, 111, 'status', False, False, False) template_8_row = (8, 1, 'template-8', 'content', 'summary', False, 111, 'status', False, False, False) template_7_row = (7, 2, 'template-7', 'content', 'summary', False, 111, 'status', False, False, False) self.template_def_2lc.template_service.template_tbl.Select\ .return_value = [template_7_row, template_8_row, template_9_row] self.template_def_2lc.template_service.template2label_tbl.Select\ .return_value = [(9, 'label-1'), (7, 'label-2')] self.template_def_2lc.template_service.template2component_tbl.Select\ .return_value = [(9, 13), (7, 14)] self.template_def_2lc.template_service.template2admin_tbl.Select\ .return_value = [(9, 111), (7, 222)] fv1_row = (15, None, 'fv-1', None, None, None, False) fv2_row = (16, None, 'fv-2', None, None, None, False) fv1 = tracker_bizobj.MakeFieldValue(*fv1_row) fv2 = tracker_bizobj.MakeFieldValue(*fv2_row) self.template_def_2lc.template_service.template2fieldvalue_tbl.Select\ .return_value = [((9,) + fv1_row[:-1]), ((7,) + fv2_row[:-1])] av1_row = (17, 9, 19, 'na') av2_row = (18, 7, 20, 'not_set') av1 = tracker_pb2.ApprovalValue( approval_id=17, phase_id=19, status=tracker_pb2.ApprovalStatus('NA')) av2 = tracker_pb2.ApprovalValue( approval_id=18, phase_id=20, status=tracker_pb2.ApprovalStatus('NOT_SET')) phase1_row = (19, 'phase-1', 1) phase2_row = (20, 'phase-2', 2) phase1 = tracker_pb2.Phase(phase_id=19, name='phase-1', rank=1) phase2 = tracker_pb2.Phase(phase_id=20, name='phase-2', rank=2) self.template_def_2lc.template_service.template2approvalvalue_tbl.Select\ .return_value = [av1_row, av2_row] self.template_def_2lc.template_service.issuephasedef_tbl.Select\ .return_value = [phase1_row, phase2_row] actual = self.template_def_2lc.FetchItems(cnxn=None, keys=[7, 8, 9]) self.assertEqual(3, len(list(actual.keys()))) self.assertTrue(isinstance(actual[7], tracker_pb2.TemplateDef)) self.assertTrue(isinstance(actual[8], tracker_pb2.TemplateDef)) self.assertTrue(isinstance(actual[9], tracker_pb2.TemplateDef)) self.assertEqual(7, actual[7].template_id) self.assertEqual(8, actual[8].template_id) self.assertEqual(9, actual[9].template_id) self.assertEqual(['label-2'], actual[7].labels) self.assertEqual([], actual[8].labels) self.assertEqual(['label-1'], actual[9].labels) self.assertEqual([14], actual[7].component_ids) self.assertEqual([], actual[8].component_ids) self.assertEqual([13], actual[9].component_ids) self.assertEqual([222], actual[7].admin_ids) self.assertEqual([], actual[8].admin_ids) self.assertEqual([111], actual[9].admin_ids) self.assertEqual([fv2], actual[7].field_values) self.assertEqual([], actual[8].field_values) self.assertEqual([fv1], actual[9].field_values) self.assertEqual([phase2], actual[7].phases) self.assertEqual([], actual[8].phases) self.assertEqual([phase1], actual[9].phases) self.assertEqual([av2], actual[7].approval_values) self.assertEqual([], actual[8].approval_values) self.assertEqual([av1], actual[9].approval_values)
def setUp(self): self.cnxn = 'fake cnxn' mock_template_service = Mock(spec=template_svc.TemplateService) self.services = service_manager.Services( project=fake.ProjectService(), config=fake.ConfigService(), template=mock_template_service, usergroup=fake.UserGroupService(), user=fake.UserService()) self.servlet = templatedetail.TemplateDetail('req', 'res', services=self.services) self.services.user.TestAddUser('*****@*****.**', 111) self.services.user.TestAddUser('*****@*****.**', 222) self.services.user.TestAddUser('*****@*****.**', 111) self.services.user.TestAddUser('*****@*****.**', 333) self.project = self.services.project.TestAddProject('proj') self.services.project.TestAddProjectMembers([333], self.project, 'CONTRIBUTOR_ROLE') self.template = self.test_template = tracker_bizobj.MakeIssueTemplate( 'TestTemplate', 'sum', 'New', 111, 'content', ['label1', 'label2'], [], [222], [], summary_must_be_edited=True, owner_defaults_to_member=True, component_required=False, members_only=False) self.template.template_id = 12345 self.services.template.GetTemplateByName = Mock( return_value=self.template) self.mr = testing_helpers.MakeMonorailRequest(project=self.project) self.mr.template_name = 'TestTemplate' self.mox = mox.Mox() self.fd_1 = tracker_bizobj.MakeFieldDef( 1, 789, 'UXReview', tracker_pb2.FieldTypes.STR_TYPE, None, '', False, False, False, None, None, '', False, '', '', tracker_pb2.NotifyTriggers.NEVER, 'no_action', 'Approval for UX review', False, approval_id=2) self.fd_2 = tracker_bizobj.MakeFieldDef( 2, 789, 'UXReview', tracker_pb2.FieldTypes.STR_TYPE, None, '', False, False, False, None, None, '', False, '', '', tracker_pb2.NotifyTriggers.NEVER, 'no_action', 'Approval for UX review', False) self.fd_3 = tracker_bizobj.MakeFieldDef( 3, 789, 'TestApproval', tracker_pb2.FieldTypes.APPROVAL_TYPE, None, '', False, False, False, None, None, '', False, '', '', tracker_pb2.NotifyTriggers.NEVER, 'no_action', 'Approval for Test', False) self.fd_4 = tracker_bizobj.MakeFieldDef( 4, 789, 'SecurityApproval', tracker_pb2.FieldTypes.APPROVAL_TYPE, None, '', False, False, False, None, None, '', False, '', '', tracker_pb2.NotifyTriggers.NEVER, 'no_action', 'Approval for Security', False) self.fd_5 = tracker_bizobj.MakeFieldDef( 5, 789, 'GateTarget', tracker_pb2.FieldTypes.INT_TYPE, None, '', False, False, False, None, None, '', False, '', '', tracker_pb2.NotifyTriggers.NEVER, 'no_action', 'milestone target', False, is_phase_field=True) self.fd_6 = tracker_bizobj.MakeFieldDef( 6, 789, 'Choices', tracker_pb2.FieldTypes.ENUM_TYPE, None, '', False, False, False, None, None, '', False, '', '', tracker_pb2.NotifyTriggers.NEVER, 'no_action', 'milestone target', False, is_phase_field=True) self.ad_3 = tracker_pb2.ApprovalDef(approval_id=3) self.ad_4 = tracker_pb2.ApprovalDef(approval_id=4) self.cd_1 = tracker_bizobj.MakeComponentDef(1, 789, 'BackEnd', 'doc', False, [111], [], 100000, 222) self.template.component_ids.append(1) self.canary_phase = tracker_pb2.Phase(name='Canary', phase_id=1, rank=1) self.av_3 = tracker_pb2.ApprovalValue(approval_id=3, phase_id=1) self.stable_phase = tracker_pb2.Phase(name='Stable', phase_id=2, rank=3) self.av_4 = tracker_pb2.ApprovalValue(approval_id=4, phase_id=2) self.template.phases.extend([self.stable_phase, self.canary_phase]) self.template.approval_values.extend([self.av_3, self.av_4]) self.config = self.services.config.GetProjectConfig( 'fake cnxn', self.project.project_id) self.templates = testing_helpers.DefaultTemplates() self.template.labels.extend([ 'GateTarget-Should-Not', 'GateTarget-Be-Masked', 'Choices-Wrapped', 'Choices-Burritod' ]) self.templates.append(self.template) self.services.template.GetProjectTemplates = Mock( return_value=self.templates) self.services.template.FindTemplateByName = Mock( return_value=self.template) self.config.component_defs.append(self.cd_1) self.config.field_defs.extend( [self.fd_1, self.fd_2, self.fd_3, self.fd_4, self.fd_5, self.fd_6]) self.config.approval_defs.extend([self.ad_3, self.ad_4]) self.services.config.StoreConfig(None, self.config)