blob: 460f5c343149bccf050014511205d4e1363cb800 [file] [log] [blame]
Copybara854996b2021-09-07 19:36:02 +00001# Copyright 2016 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style
3# license that can be found in the LICENSE file or at
4# https://developers.google.com/open-source/licenses/bsd
5
6"""Tests for the API v1 helpers."""
7from __future__ import print_function
8from __future__ import division
9from __future__ import absolute_import
10
11import datetime
12import mock
13import unittest
14
15from framework import framework_constants
16from framework import permissions
17from framework import profiler
18from services import api_pb2_v1_helpers
19from services import service_manager
20from proto import api_pb2_v1
21from proto import project_pb2
22from proto import tracker_pb2
23from proto import usergroup_pb2
24from testing import fake
25from tracker import tracker_bizobj
26
27
28def MakeTemplate(prefix):
29 return tracker_pb2.TemplateDef(
30 name='%s-template' % prefix,
31 content='%s-content' % prefix,
32 summary='%s-summary' % prefix,
33 summary_must_be_edited=True,
34 status='New',
35 labels=['%s-label1' % prefix, '%s-label2' % prefix],
36 members_only=True,
37 owner_defaults_to_member=True,
38 component_required=True,
39 )
40
41
42def MakeLabel(prefix):
43 return tracker_pb2.LabelDef(
44 label='%s-label' % prefix,
45 label_docstring='%s-description' % prefix
46 )
47
48
49def MakeStatus(prefix):
50 return tracker_pb2.StatusDef(
51 status='%s-New' % prefix,
52 means_open=True,
53 status_docstring='%s-status' % prefix
54 )
55
56
57def MakeProjectIssueConfig(prefix):
58 return tracker_pb2.ProjectIssueConfig(
59 restrict_to_known=True,
60 default_col_spec='ID Type Priority Summary',
61 default_sort_spec='ID Priority',
62 well_known_statuses=[
63 MakeStatus('%s-status1' % prefix),
64 MakeStatus('%s-status2' % prefix),
65 ],
66 well_known_labels=[
67 MakeLabel('%s-label1' % prefix),
68 MakeLabel('%s-label2' % prefix),
69 ],
70 default_template_for_developers=1,
71 default_template_for_users=2
72 )
73
74
75def MakeProject(prefix):
76 return project_pb2.MakeProject(
77 project_name='%s-project' % prefix,
78 summary='%s-summary' % prefix,
79 description='%s-description' % prefix,
80 )
81
82
83class ApiV1HelpersTest(unittest.TestCase):
84
85 def setUp(self):
86 self.services = service_manager.Services(
87 user=fake.UserService(),
88 issue=fake.IssueService(),
89 project=fake.ProjectService(),
90 config=fake.ConfigService(),
91 issue_star=fake.IssueStarService())
92 self.services.user.TestAddUser('user@example.com', 111)
93 self.person_1 = api_pb2_v1_helpers.convert_person(111, None, self.services)
94
95 def testConvertTemplate(self):
96 """Test convert_template."""
97 template = MakeTemplate('test')
98 prompt = api_pb2_v1_helpers.convert_template(template)
99 self.assertEqual(template.name, prompt.name)
100 self.assertEqual(template.summary, prompt.title)
101 self.assertEqual(template.content, prompt.description)
102 self.assertEqual(template.summary_must_be_edited, prompt.titleMustBeEdited)
103 self.assertEqual(template.status, prompt.status)
104 self.assertEqual(template.labels, prompt.labels)
105 self.assertEqual(template.members_only, prompt.membersOnly)
106 self.assertEqual(template.owner_defaults_to_member, prompt.defaultToMember)
107 self.assertEqual(template.component_required, prompt.componentRequired)
108
109 def testConvertLabel(self):
110 """Test convert_label."""
111 labeldef = MakeLabel('test')
112 label = api_pb2_v1_helpers.convert_label(labeldef)
113 self.assertEqual(labeldef.label, label.label)
114 self.assertEqual(labeldef.label_docstring, label.description)
115
116 def testConvertStatus(self):
117 """Test convert_status."""
118 statusdef = MakeStatus('test')
119 status = api_pb2_v1_helpers.convert_status(statusdef)
120 self.assertEqual(statusdef.status, status.status)
121 self.assertEqual(statusdef.means_open, status.meansOpen)
122 self.assertEqual(statusdef.status_docstring, status.description)
123
124 def testConvertProjectIssueConfig(self):
125 """Test convert_project_config."""
126 prefix = 'test'
127 config = MakeProjectIssueConfig(prefix)
128 templates = [
129 MakeTemplate('%s-template1' % prefix),
130 MakeTemplate('%s-template2' % prefix),
131 ]
132 config_api = api_pb2_v1_helpers.convert_project_config(config, templates)
133 self.assertEqual(config.restrict_to_known, config_api.restrictToKnown)
134 self.assertEqual(config.default_col_spec.split(), config_api.defaultColumns)
135 self.assertEqual(
136 config.default_sort_spec.split(), config_api.defaultSorting)
137 self.assertEqual(2, len(config_api.statuses))
138 self.assertEqual(2, len(config_api.labels))
139 self.assertEqual(2, len(config_api.prompts))
140 self.assertEqual(
141 config.default_template_for_developers,
142 config_api.defaultPromptForMembers)
143 self.assertEqual(
144 config.default_template_for_users,
145 config_api.defaultPromptForNonMembers)
146
147 def testConvertProject(self):
148 """Test convert_project."""
149 project = MakeProject('testprj')
150 prefix = 'testconfig'
151 config = MakeProjectIssueConfig(prefix)
152 role = api_pb2_v1.Role.owner
153 templates = [
154 MakeTemplate('%s-template1' % prefix),
155 MakeTemplate('%s-template2' % prefix),
156 ]
157 project_api = api_pb2_v1_helpers.convert_project(project, config, role,
158 templates)
159 self.assertEqual(project.project_name, project_api.name)
160 self.assertEqual(project.project_name, project_api.externalId)
161 self.assertEqual('/p/%s/' % project.project_name, project_api.htmlLink)
162 self.assertEqual(project.summary, project_api.summary)
163 self.assertEqual(project.description, project_api.description)
164 self.assertEqual(role, project_api.role)
165 self.assertIsInstance(
166 project_api.issuesConfig, api_pb2_v1.ProjectIssueConfig)
167
168 def testConvertPerson(self):
169 """Test convert_person."""
170 result = api_pb2_v1_helpers.convert_person(111, None, self.services)
171 self.assertIsInstance(result, api_pb2_v1.AtomPerson)
172 self.assertEqual('user@example.com', result.name)
173
174 none_user = api_pb2_v1_helpers.convert_person(None, '', self.services)
175 self.assertIsNone(none_user)
176
177 deleted_user = api_pb2_v1_helpers.convert_person(
178 framework_constants.DELETED_USER_ID, '', self.services)
179 self.assertEqual(
180 deleted_user,
181 api_pb2_v1.AtomPerson(
182 kind='monorail#issuePerson',
183 name=framework_constants.DELETED_USER_NAME))
184
185 def testConvertIssueIDs(self):
186 """Test convert_issue_ids."""
187 issue1 = fake.MakeTestIssue(789, 1, 'one', 'New', 111)
188 self.services.issue.TestAddIssue(issue1)
189 issue_ids = [100001]
190 mar = mock.Mock()
191 mar.cnxn = None
192 mar.project_name = 'test-project'
193 result = api_pb2_v1_helpers.convert_issue_ids(issue_ids, mar, self.services)
194 self.assertEqual(1, len(result))
195 self.assertEqual(1, result[0].issueId)
196
197 def testConvertIssueRef(self):
198 """Test convert_issueref_pbs."""
199 issue1 = fake.MakeTestIssue(12345, 1, 'one', 'New', 111)
200 self.services.issue.TestAddIssue(issue1)
201 self.services.project.TestAddProject(
202 'test-project', owner_ids=[2],
203 project_id=12345)
204 mar = mock.Mock()
205 mar.cnxn = None
206 mar.project_name = 'test-project'
207 mar.project_id = 12345
208 ir = api_pb2_v1.IssueRef(
209 issueId=1,
210 projectId='test-project'
211 )
212 result = api_pb2_v1_helpers.convert_issueref_pbs([ir], mar, self.services)
213 self.assertEqual(1, len(result))
214 self.assertEqual(100001, result[0])
215
216 def testConvertIssue(self):
217 """Convert an internal Issue PB to an IssueWrapper API PB."""
218 self.services.project.TestAddProject(
219 'test-project', owner_ids=[2], project_id=12345)
220 self.services.user.TestAddUser('user@example.com', 111)
221
222 mar = mock.Mock()
223 mar.cnxn = None
224 mar.project_name = 'test-project'
225 mar.project_id = 12345
226 mar.auth.effective_ids = {111}
227 mar.perms = permissions.READ_ONLY_PERMISSIONSET
228 mar.profiler = profiler.Profiler()
229 mar.config = tracker_bizobj.MakeDefaultProjectIssueConfig(12345)
230 mar.config.field_defs = [
231 tracker_bizobj.MakeFieldDef(
232 1, 12345, 'EstDays', tracker_pb2.FieldTypes.INT_TYPE, None, None,
233 False, False, False, None, None, None, False, None, None, None,
234 None, 'doc', False, approval_id=2),
235 tracker_bizobj.MakeFieldDef(
236 2, 12345, 'DesignReview', tracker_pb2.FieldTypes.APPROVAL_TYPE,
237 None, None, False, False, False, None, None, None, False, None,
238 None, None, None, 'doc', False),
239 tracker_bizobj.MakeFieldDef(
240 3, 12345, 'StringField', tracker_pb2.FieldTypes.STR_TYPE, None,
241 None, False, False, False, None, None, None, False, None, None,
242 None, None, 'doc', False),
243 tracker_bizobj.MakeFieldDef(
244 4, 12345, 'DressReview', tracker_pb2.FieldTypes.APPROVAL_TYPE,
245 None, None, False, False, False, None, None, None, False, None,
246 None, None, None, 'doc', False),
247 ]
248 self.services.config.StoreConfig(mar.cnxn, mar.config)
249
250 now = 1472067725
251 now_dt = datetime.datetime.fromtimestamp(now)
252
253 fvs = [
254 tracker_bizobj.MakeFieldValue(
255 1, 4, None, None, None, None, False, phase_id=4),
256 tracker_bizobj.MakeFieldValue(
257 3, None, 'string', None, None, None, False, phase_id=4),
258 # missing phase
259 tracker_bizobj.MakeFieldValue(
260 3, None, u'\xe2\x9d\xa4\xef\xb8\x8f', None, None, None, False,
261 phase_id=2),
262 ]
263 phases = [
264 tracker_pb2.Phase(phase_id=3, name="JustAPhase", rank=4),
265 tracker_pb2.Phase(phase_id=4, name="NotAPhase", rank=9)
266 ]
267 approval_values = [
268 tracker_pb2.ApprovalValue(
269 approval_id=2, phase_id=3, approver_ids=[111]),
270 tracker_pb2.ApprovalValue(approval_id=4, approver_ids=[111])
271 ]
272 issue = fake.MakeTestIssue(
273 12345, 1, 'one', 'New', 111, field_values=fvs,
274 approval_values=approval_values, phases=phases)
275 issue.opened_timestamp = now
276 issue.owner_modified_timestamp = now
277 issue.status_modified_timestamp = now
278 issue.component_modified_timestamp = now
279 # TODO(jrobbins): set up a lot more fields.
280
281 for cls in [api_pb2_v1.IssueWrapper, api_pb2_v1.IssuesGetInsertResponse]:
282 result = api_pb2_v1_helpers.convert_issue(cls, issue, mar, self.services)
283 self.assertEqual(1, result.id)
284 self.assertEqual('one', result.title)
285 self.assertEqual('one', result.summary)
286 self.assertEqual(now_dt, result.published)
287 self.assertEqual(now_dt, result.owner_modified)
288 self.assertEqual(now_dt, result.status_modified)
289 self.assertEqual(now_dt, result.component_modified)
290 self.assertEqual(
291 result.fieldValues, [
292 api_pb2_v1.FieldValue(
293 fieldName='EstDays',
294 fieldValue='4',
295 approvalName='DesignReview',
296 derived=False),
297 api_pb2_v1.FieldValue(
298 fieldName='StringField',
299 fieldValue='string',
300 phaseName="NotAPhase",
301 derived=False),
302 api_pb2_v1.FieldValue(
303 fieldName='StringField',
304 fieldValue=u'\xe2\x9d\xa4\xef\xb8\x8f',
305 derived=False),
306 ])
307 self.assertEqual(
308 result.approvalValues,
309 [api_pb2_v1.Approval(
310 approvalName="DesignReview",
311 approvers=[self.person_1],
312 status=api_pb2_v1.ApprovalStatus.notSet,
313 phaseName="JustAPhase",
314 ),
315 api_pb2_v1.Approval(
316 approvalName="DressReview",
317 approvers=[self.person_1],
318 status=api_pb2_v1.ApprovalStatus.notSet,
319 )]
320 )
321 self.assertEqual(
322 result.phases,
323 [api_pb2_v1.Phase(phaseName="JustAPhase", rank=4),
324 api_pb2_v1.Phase(phaseName="NotAPhase", rank=9)
325 ])
326
327 # TODO(jrobbins): check a lot more fields.
328
329 def testConvertAttachment(self):
330 """Test convert_attachment."""
331
332 attachment = tracker_pb2.Attachment(
333 attachment_id=1,
334 filename='stats.txt',
335 filesize=12345,
336 mimetype='text/plain',
337 deleted=False)
338
339 result = api_pb2_v1_helpers.convert_attachment(attachment)
340 self.assertEqual(attachment.attachment_id, result.attachmentId)
341 self.assertEqual(attachment.filename, result.fileName)
342 self.assertEqual(attachment.filesize, result.fileSize)
343 self.assertEqual(attachment.mimetype, result.mimetype)
344 self.assertEqual(attachment.deleted, result.isDeleted)
345
346 def testConvertAmendments(self):
347 """Test convert_amendments."""
348 self.services.user.TestAddUser('user2@example.com', 222)
349 mar = mock.Mock()
350 mar.cnxn = None
351 issue = mock.Mock()
352 issue.project_name = 'test-project'
353
354 amendment_summary = tracker_pb2.Amendment(
355 field=tracker_pb2.FieldID.SUMMARY,
356 newvalue='new summary')
357 amendment_status = tracker_pb2.Amendment(
358 field=tracker_pb2.FieldID.STATUS,
359 newvalue='new status')
360 amendment_owner = tracker_pb2.Amendment(
361 field=tracker_pb2.FieldID.OWNER,
362 added_user_ids=[111])
363 amendment_labels = tracker_pb2.Amendment(
364 field=tracker_pb2.FieldID.LABELS,
365 newvalue='label1 -label2')
366 amendment_cc_add = tracker_pb2.Amendment(
367 field=tracker_pb2.FieldID.CC,
368 added_user_ids=[111])
369 amendment_cc_remove = tracker_pb2.Amendment(
370 field=tracker_pb2.FieldID.CC,
371 removed_user_ids=[222])
372 amendment_blockedon = tracker_pb2.Amendment(
373 field=tracker_pb2.FieldID.BLOCKEDON,
374 newvalue='1')
375 amendment_blocking = tracker_pb2.Amendment(
376 field=tracker_pb2.FieldID.BLOCKING,
377 newvalue='other:2 -3')
378 amendment_mergedinto = tracker_pb2.Amendment(
379 field=tracker_pb2.FieldID.MERGEDINTO,
380 newvalue='4')
381 amendments = [
382 amendment_summary, amendment_status, amendment_owner,
383 amendment_labels, amendment_cc_add, amendment_cc_remove,
384 amendment_blockedon, amendment_blocking, amendment_mergedinto]
385
386 result = api_pb2_v1_helpers.convert_amendments(
387 issue, amendments, mar, self.services)
388 self.assertEqual(amendment_summary.newvalue, result.summary)
389 self.assertEqual(amendment_status.newvalue, result.status)
390 self.assertEqual('user@example.com', result.owner)
391 self.assertEqual(['label1', '-label2'], result.labels)
392 self.assertEqual(['user@example.com', '-user2@example.com'], result.cc)
393 self.assertEqual(['test-project:1'], result.blockedOn)
394 self.assertEqual(['other:2', '-test-project:3'], result.blocking)
395 self.assertEqual(amendment_mergedinto.newvalue, result.mergedInto)
396
397 def testConvertApprovalAmendments(self):
398 """Test convert_approval_comment."""
399 self.services.user.TestAddUser('user1@example.com', 111)
400 self.services.user.TestAddUser('user2@example.com', 222)
401 self.services.user.TestAddUser('user3@example.com', 333)
402 mar = mock.Mock()
403 mar.cnxn = None
404 amendment_status = tracker_bizobj.MakeApprovalStatusAmendment(
405 tracker_pb2.ApprovalStatus.APPROVED)
406 amendment_approvers = tracker_bizobj.MakeApprovalApproversAmendment(
407 [111, 222], [333])
408 amendments = [amendment_status, amendment_approvers]
409 result = api_pb2_v1_helpers.convert_approval_amendments(
410 amendments, mar, self.services)
411 self.assertEqual(amendment_status.newvalue, result.status)
412 self.assertEqual(
413 ['user1@example.com', 'user2@example.com', '-user3@example.com'],
414 result.approvers)
415
416 def testConvertComment(self):
417 """Test convert_comment."""
418 mar = mock.Mock()
419 mar.cnxn = None
420 mar.perms = permissions.PermissionSet([])
421 issue = fake.MakeTestIssue(project_id=12345, local_id=1, summary='sum',
422 status='New', owner_id=1001)
423
424 comment = tracker_pb2.IssueComment(
425 user_id=111,
426 content='test content',
427 sequence=1,
428 deleted_by=111,
429 timestamp=1437700000,
430 )
431 result = api_pb2_v1_helpers.convert_comment(
432 issue, comment, mar, self.services, None)
433 self.assertEqual('user@example.com', result.author.name)
434 self.assertEqual(comment.content, result.content)
435 self.assertEqual('user@example.com', result.deletedBy.name)
436 self.assertEqual(1, result.id)
437 # Ensure that the published timestamp falls in a timestamp range to account
438 # for the test being run in different timezones.
439 # Using "Fri, 23 Jul 2015 00:00:00" and "Fri, 25 Jul 2015 00:00:00".
440 self.assertTrue(
441 datetime.datetime(2015, 7, 23, 0, 0, 0) <= result.published <=
442 datetime.datetime(2015, 7, 25, 0, 0, 0))
443 self.assertEqual(result.kind, 'monorail#issueComment')
444
445 def testConvertApprovalComment(self):
446 """Test convert_approval_comment."""
447 mar = mock.Mock()
448 mar.cnxn = None
449 mar.perms = permissions.PermissionSet([])
450 issue = fake.MakeTestIssue(project_id=12345, local_id=1, summary='sum',
451 status='New', owner_id=1001)
452 comment = tracker_pb2.IssueComment(
453 user_id=111,
454 content='test content',
455 sequence=1,
456 deleted_by=111,
457 timestamp=1437700000,
458 )
459 result = api_pb2_v1_helpers.convert_approval_comment(
460 issue, comment, mar, self.services, None)
461 self.assertEqual('user@example.com', result.author.name)
462 self.assertEqual(comment.content, result.content)
463 self.assertEqual('user@example.com', result.deletedBy.name)
464 self.assertEqual(1, result.id)
465 # Ensure that the published timestamp falls in a timestamp range to account
466 # for the test being run in different timezones.
467 # Using "Fri, 23 Jul 2015 00:00:00" and "Fri, 25 Jul 2015 00:00:00".
468 self.assertTrue(
469 datetime.datetime(2015, 7, 23, 0, 0, 0) <= result.published <=
470 datetime.datetime(2015, 7, 25, 0, 0, 0))
471 self.assertEqual(result.kind, 'monorail#approvalComment')
472
473
474 def testGetUserEmail(self):
475 email = api_pb2_v1_helpers._get_user_email(self.services.user, '', 111)
476 self.assertEqual('user@example.com', email)
477
478 no_user_found = api_pb2_v1_helpers._get_user_email(
479 self.services.user, '', 222)
480 self.assertEqual(framework_constants.USER_NOT_FOUND_NAME, no_user_found)
481
482 deleted = api_pb2_v1_helpers._get_user_email(
483 self.services.user, '', framework_constants.DELETED_USER_ID)
484 self.assertEqual(framework_constants.DELETED_USER_NAME, deleted)
485
486 none_user_id = api_pb2_v1_helpers._get_user_email(
487 self.services.user, '', None)
488 self.assertEqual(framework_constants.NO_USER_NAME, none_user_id)
489
490 def testSplitRemoveAdd(self):
491 """Test split_remove_add."""
492
493 items = ['1', '-2', '-3', '4']
494 list_to_add, list_to_remove = api_pb2_v1_helpers.split_remove_add(items)
495
496 self.assertEqual(['1', '4'], list_to_add)
497 self.assertEqual(['2', '3'], list_to_remove)
498
499 def testIssueGlobalIDs(self):
500 """Test issue_global_ids."""
501 issue1 = fake.MakeTestIssue(12345, 1, 'one', 'New', 111)
502 self.services.issue.TestAddIssue(issue1)
503 self.services.project.TestAddProject(
504 'test-project', owner_ids=[2],
505 project_id=12345)
506 mar = mock.Mock()
507 mar.cnxn = None
508 mar.project_name = 'test-project'
509 mar.project_id = 12345
510 pairs = ['test-project:1']
511 result = api_pb2_v1_helpers.issue_global_ids(
512 pairs, 12345, mar, self.services)
513 self.assertEqual(100001, result[0])
514
515 def testConvertGroupSettings(self):
516 """Test convert_group_settings."""
517
518 setting = usergroup_pb2.MakeSettings('owners', 'mdb', 0)
519 result = api_pb2_v1_helpers.convert_group_settings('test-group', setting)
520 self.assertEqual('test-group', result.groupName)
521 self.assertEqual(setting.who_can_view_members, result.who_can_view_members)
522 self.assertEqual(setting.ext_group_type, result.ext_group_type)
523 self.assertEqual(setting.last_sync_time, result.last_sync_time)
524
525 def testConvertComponentDef(self):
526 pass # TODO(jrobbins): Fill in this test.
527
528 def testConvertComponentIDs(self):
529 pass # TODO(jrobbins): Fill in this test.
530
531 def testConvertFieldValues_Empty(self):
532 """The client's request might not have any field edits."""
533 mar = mock.Mock()
534 mar.config = tracker_bizobj.MakeDefaultProjectIssueConfig(789)
535
536 field_values = []
537 actual = api_pb2_v1_helpers.convert_field_values(
538 field_values, mar, self.services)
539 (fv_list_add, fv_list_remove, fv_list_clear,
540 label_list_add, label_list_remove) = actual
541 self.assertEqual([], fv_list_add)
542 self.assertEqual([], fv_list_remove)
543 self.assertEqual([], fv_list_clear)
544 self.assertEqual([], label_list_add)
545 self.assertEqual([], label_list_remove)
546
547 def testConvertFieldValues_Normal(self):
548 """The client wants to edit a custom field."""
549 mar = mock.Mock()
550 mar.config = tracker_bizobj.MakeDefaultProjectIssueConfig(789)
551 mar.config.field_defs = [
552 tracker_bizobj.MakeFieldDef(
553 1, 789, 'Priority', tracker_pb2.FieldTypes.ENUM_TYPE, None, None,
554 False, False, False, None, None, None, False, None, None, None,
555 None, 'doc', False),
556 tracker_bizobj.MakeFieldDef(
557 2, 789, 'EstDays', tracker_pb2.FieldTypes.INT_TYPE, None, None,
558 False, False, False, 0, 99, None, False, None, None, None,
559 None, 'doc', False),
560 tracker_bizobj.MakeFieldDef(
561 3, 789, 'Nickname', tracker_pb2.FieldTypes.STR_TYPE, None, None,
562 False, False, False, None, None, None, False, None, None, None,
563 None, 'doc', False),
564 tracker_bizobj.MakeFieldDef(
565 4, 789, 'Verifier', tracker_pb2.FieldTypes.USER_TYPE, None, None,
566 False, False, False, None, None, None, False, None, None, None,
567 None, 'doc', False),
568 tracker_bizobj.MakeFieldDef(
569 5, 789, 'Deadline', tracker_pb2.FieldTypes.DATE_TYPE, None, None,
570 False, False, False, None, None, None, False, None, None, None,
571 None, 'doc', False),
572 tracker_bizobj.MakeFieldDef(
573 6, 789, 'Homepage', tracker_pb2.FieldTypes.URL_TYPE, None, None,
574 False, False, False, None, None, None, False, None, None, None,
575 None, 'doc', False),
576 ]
577 field_values = [
578 api_pb2_v1.FieldValue(fieldName='Priority', fieldValue='High'),
579 api_pb2_v1.FieldValue(fieldName='EstDays', fieldValue='4'),
580 api_pb2_v1.FieldValue(fieldName='Nickname', fieldValue='Scout'),
581 api_pb2_v1.FieldValue(
582 fieldName='Verifier', fieldValue='user@example.com'),
583 api_pb2_v1.FieldValue(fieldName='Deadline', fieldValue='2017-12-06'),
584 api_pb2_v1.FieldValue(
585 fieldName='Homepage', fieldValue='http://example.com'),
586 ]
587 actual = api_pb2_v1_helpers.convert_field_values(
588 field_values, mar, self.services)
589 (fv_list_add, fv_list_remove, fv_list_clear,
590 label_list_add, label_list_remove) = actual
591 self.assertEqual(
592 [
593 tracker_bizobj.MakeFieldValue(2, 4, None, None, None, None, False),
594 tracker_bizobj.MakeFieldValue(
595 3, None, 'Scout', None, None, None, False),
596 tracker_bizobj.MakeFieldValue(
597 4, None, None, 111, None, None, False),
598 tracker_bizobj.MakeFieldValue(
599 5, None, None, None, 1512518400, None, False),
600 tracker_bizobj.MakeFieldValue(
601 6, None, None, None, None, 'http://example.com', False),
602 ], fv_list_add)
603 self.assertEqual([], fv_list_remove)
604 self.assertEqual([], fv_list_clear)
605 self.assertEqual(['Priority-High'], label_list_add)
606 self.assertEqual([], label_list_remove)
607
608 def testConvertFieldValues_ClearAndRemove(self):
609 """The client wants to clear and remove some custom fields."""
610 mar = mock.Mock()
611 mar.config = tracker_bizobj.MakeDefaultProjectIssueConfig(789)
612 mar.config.field_defs = [
613 tracker_bizobj.MakeFieldDef(
614 1, 789, 'Priority', tracker_pb2.FieldTypes.ENUM_TYPE, None, None,
615 False, False, False, None, None, None, False, None, None, None,
616 None, 'doc', False),
617 tracker_bizobj.MakeFieldDef(
618 11, 789, 'OS', tracker_pb2.FieldTypes.ENUM_TYPE, None, None,
619 False, False, False, None, None, None, False, None, None, None,
620 None, 'doc', False),
621 tracker_bizobj.MakeFieldDef(
622 2, 789, 'EstDays', tracker_pb2.FieldTypes.INT_TYPE, None, None,
623 False, False, False, 0, 99, None, False, None, None, None,
624 None, 'doc', False),
625 tracker_bizobj.MakeFieldDef(
626 3, 789, 'Nickname', tracker_pb2.FieldTypes.STR_TYPE, None, None,
627 False, False, False, None, None, None, False, None, None, None,
628 None, 'doc', False),
629 ]
630 field_values = [
631 api_pb2_v1.FieldValue(
632 fieldName='Priority', fieldValue='High',
633 operator=api_pb2_v1.FieldValueOperator.remove),
634 api_pb2_v1.FieldValue(
635 fieldName='OS', operator=api_pb2_v1.FieldValueOperator.clear),
636 api_pb2_v1.FieldValue(
637 fieldName='EstDays', operator=api_pb2_v1.FieldValueOperator.clear),
638 api_pb2_v1.FieldValue(
639 fieldName='Nickname', fieldValue='Scout',
640 operator=api_pb2_v1.FieldValueOperator.remove),
641 ]
642 actual = api_pb2_v1_helpers.convert_field_values(
643 field_values, mar, self.services)
644 (fv_list_add, fv_list_remove, fv_list_clear,
645 label_list_add, label_list_remove) = actual
646 self.assertEqual([], fv_list_add)
647 self.assertEqual(
648 [
649 tracker_bizobj.MakeFieldValue(
650 3, None, 'Scout', None, None, None, False)
651 ], fv_list_remove)
652 self.assertEqual([11, 2], fv_list_clear)
653 self.assertEqual([], label_list_add)
654 self.assertEqual(['Priority-High'], label_list_remove)
655
656 def testConvertFieldValues_Errors(self):
657 """We don't crash on bad requests."""
658 mar = mock.Mock()
659 mar.config = tracker_bizobj.MakeDefaultProjectIssueConfig(789)
660 mar.config.field_defs = [
661 tracker_bizobj.MakeFieldDef(
662 2, 789, 'EstDays', tracker_pb2.FieldTypes.INT_TYPE, None, None,
663 False, False, False, 0, 99, None, False, None, None, None,
664 None, 'doc', False),
665 ]
666 field_values = [
667 api_pb2_v1.FieldValue(
668 fieldName='Unknown', operator=api_pb2_v1.FieldValueOperator.clear),
669 ]
670 actual = api_pb2_v1_helpers.convert_field_values(
671 field_values, mar, self.services)
672 (fv_list_add, fv_list_remove, fv_list_clear,
673 label_list_add, label_list_remove) = actual
674 self.assertEqual([], fv_list_add)
675 self.assertEqual([], fv_list_remove)
676 self.assertEqual([], fv_list_clear)
677 self.assertEqual([], label_list_add)
678 self.assertEqual([], label_list_remove)
679
680 def testConvertApprovals(self):
681 """Test we can convert ApprovalValues."""
682 cnxn = None
683 config = tracker_bizobj.MakeDefaultProjectIssueConfig(789)
684 config.field_defs = [
685 tracker_bizobj.MakeFieldDef(
686 1, 789, 'DesignReview', tracker_pb2.FieldTypes.APPROVAL_TYPE, None,
687 None, False, False, False, None, None, None, False, None, None,
688 None, None, 'doc', False),
689 tracker_bizobj.MakeFieldDef(
690 2, 789, 'PrivacyReview', tracker_pb2.FieldTypes.APPROVAL_TYPE, None,
691 None, False, False, False, 0, 99, None, False, None, None, None,
692 None, 'doc', False),
693 tracker_bizobj.MakeFieldDef(
694 5, 789, 'UXReview', tracker_pb2.FieldTypes.APPROVAL_TYPE, None,
695 None, False, False, False, None, None, None, False, None, None,
696 None, None, 'doc', False),
697 tracker_bizobj.MakeFieldDef(
698 6, 789, 'Homepage', tracker_pb2.FieldTypes.URL_TYPE, None, None,
699 False, False, False, None, None, None, False, None, None, None,
700 None, 'doc', False),
701 ]
702 phases = [
703 tracker_pb2.Phase(phase_id=1),
704 tracker_pb2.Phase(phase_id=2, name="JustAPhase", rank=3),
705 ]
706 ts = 1536260059
707 expected = [
708 api_pb2_v1.Approval(
709 approvalName="DesignReview",
710 approvers=[self.person_1],
711 setter=self.person_1,
712 status=api_pb2_v1.ApprovalStatus.needsReview,
713 setOn=datetime.datetime.fromtimestamp(ts),
714 ),
715 api_pb2_v1.Approval(
716 approvalName="UXReview",
717 approvers=[self.person_1],
718 status=api_pb2_v1.ApprovalStatus.notSet,
719 phaseName="JustAPhase",
720 ),
721 ]
722 avs = [
723 tracker_pb2.ApprovalValue(
724 approval_id=1, approver_ids=[111], setter_id=111,
725 status=tracker_pb2.ApprovalStatus.NEEDS_REVIEW, set_on=ts),
726 tracker_pb2.ApprovalValue(
727 approval_id=5, approver_ids=[111], phase_id=2)
728 ]
729 actual = api_pb2_v1_helpers.convert_approvals(
730 cnxn, avs, self.services, config, phases)
731
732 self.assertEqual(actual, expected)
733
734 def testConvertApprovals_errors(self):
735 """we dont crash on bad requests."""
736 cnxn = None
737 config = tracker_bizobj.MakeDefaultProjectIssueConfig(789)
738 config.field_defs = [
739 tracker_bizobj.MakeFieldDef(
740 1, 789, 'DesignReview', tracker_pb2.FieldTypes.APPROVAL_TYPE, None,
741 None, False, False, False, None, None, None, False, None, None,
742 None, None, 'doc', False),
743 tracker_bizobj.MakeFieldDef(
744 5, 789, 'UXReview', tracker_pb2.FieldTypes.APPROVAL_TYPE, None,
745 None, False, False, False, None, None, None, False, None, None,
746 None, None, 'doc', False),
747 tracker_bizobj.MakeFieldDef(
748 3, 789, 'DesignDoc', tracker_pb2.FieldTypes.URL_TYPE, None, None,
749 False, False, False, 0, 99, None, False, None, None, None,
750 None, 'doc', False),
751 ]
752 phases = []
753 avs = [
754 tracker_pb2.ApprovalValue(approval_id=1, approver_ids=[111]),
755 # phase does not exist
756 tracker_pb2.ApprovalValue(approval_id=2, phase_id=2),
757 tracker_pb2.ApprovalValue(approval_id=3), # field 3 is not an approval
758 tracker_pb2.ApprovalValue(approval_id=4), # field 4 does not exist
759 ]
760 expected = [
761 api_pb2_v1.Approval(
762 approvalName="DesignReview",
763 approvers=[self.person_1],
764 status=api_pb2_v1.ApprovalStatus.notSet)
765 ]
766
767 actual = api_pb2_v1_helpers.convert_approvals(
768 cnxn, avs, self.services, config, phases)
769 self.assertEqual(actual, expected)
770
771 def testConvertPhases(self):
772 """We can convert Phases."""
773 phases = [
774 tracker_pb2.Phase(name="JustAPhase", rank=1),
775 tracker_pb2.Phase(name="Can'tPhaseMe", rank=4),
776 tracker_pb2.Phase(phase_id=11, rank=5),
777 tracker_pb2.Phase(rank=3),
778 tracker_pb2.Phase(name="Phase"),
779 ]
780 expected = [
781 api_pb2_v1.Phase(phaseName="JustAPhase", rank=1),
782 api_pb2_v1.Phase(phaseName="Can'tPhaseMe", rank=4),
783 api_pb2_v1.Phase(phaseName="Phase"),
784 ]
785 actual = api_pb2_v1_helpers.convert_phases(phases)
786 self.assertEqual(actual, expected)