blob: 5d465868584dffc5607015758b7a0a06ef7eb178 [file] [log] [blame]
Adrià Vilanova Martínezf19ea432024-01-23 20:20:52 +01001# Copyright 2016 The Chromium Authors
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
Copybara854996b2021-09-07 19:36:02 +00004
5"""Unit tests for the field_helpers module."""
6from __future__ import print_function
7from __future__ import division
8from __future__ import absolute_import
9
10import time
11import unittest
12import re
13
14from framework import exceptions
15from framework import permissions
16from framework import template_helpers
Adrià Vilanova Martínezf19ea432024-01-23 20:20:52 +010017from mrproto import project_pb2
18from mrproto import tracker_pb2
Copybara854996b2021-09-07 19:36:02 +000019from services import service_manager
20from services import config_svc
21from testing import fake
22from testing import testing_helpers
23from tracker import field_helpers
24from tracker import tracker_bizobj
25
26
27class FieldHelpersTest(unittest.TestCase):
28
29 def setUp(self):
30 self.config = tracker_bizobj.MakeDefaultProjectIssueConfig(789)
31 self.config.well_known_labels.append(tracker_pb2.LabelDef(
32 label='OldLabel', label_docstring='Do not use any longer',
33 deprecated=True))
34
35 self.services = service_manager.Services(
36 issue=fake.IssueService(),
37 usergroup=fake.UserGroupService(),
38 config=fake.ConfigService(),
39 user=fake.UserService())
40 self.project = fake.Project()
41 self.mr = testing_helpers.MakeMonorailRequest(
42 project=self.project, services=self.services)
43 self.mr.cnxn = fake.MonorailConnection()
44 self.errors = template_helpers.EZTError()
45
46 def testListApplicableFieldDefs(self):
47 issue_1 = fake.MakeTestIssue(
48 789,
49 1,
50 'sum',
51 'New',
52 111,
53 issue_id=78901,
54 labels=['type-defect', 'other-label'])
55 issue_2 = fake.MakeTestIssue(
56 789,
57 2,
58 'sum',
59 'New',
60 111,
61 issue_id=78902,
62 labels=['type-feedback', 'other-label1'])
63 issue_3 = fake.MakeTestIssue(
64 789,
65 3,
66 'sum',
67 'New',
68 111,
69 issue_id=78903,
70 labels=['type-defect'],
71 approval_values=[
72 tracker_pb2.ApprovalValue(approval_id=3),
73 tracker_pb2.ApprovalValue(approval_id=5)
74 ])
75 issue_4 = fake.MakeTestIssue(
76 789, 4, 'sum', 'New', 111, issue_id=78904) # test no labels at all
77 issue_5 = fake.MakeTestIssue(
78 789,
79 5,
80 'sum',
81 'New',
82 111,
83 issue_id=78905,
84 labels=['type'], # test labels ignored
85 approval_values=[tracker_pb2.ApprovalValue(approval_id=5)])
86 self.services.issue.TestAddIssue(issue_1)
87 self.services.issue.TestAddIssue(issue_2)
88 self.services.issue.TestAddIssue(issue_3)
89 self.services.issue.TestAddIssue(issue_4)
90 self.services.issue.TestAddIssue(issue_5)
91 fd_1 = tracker_pb2.FieldDef(
92 field_name='FirstField',
93 field_id=1,
94 field_type=tracker_pb2.FieldTypes.STR_TYPE,
95 applicable_type='feedback') # applicable
96 fd_2 = tracker_pb2.FieldDef(
97 field_name='SecField',
98 field_id=2,
99 field_type=tracker_pb2.FieldTypes.INT_TYPE,
100 applicable_type='no') # not applicable
101 fd_3 = tracker_pb2.FieldDef(
102 field_name='LegalApproval',
103 field_id=3,
104 field_type=tracker_pb2.FieldTypes.APPROVAL_TYPE,
105 applicable_type='') # applicable
106 fd_4 = tracker_pb2.FieldDef(
107 field_name='UserField',
108 field_id=4,
109 field_type=tracker_pb2.FieldTypes.USER_TYPE,
110 applicable_type='') # applicable
111 fd_5 = tracker_pb2.FieldDef(
112 field_name='DogApproval',
113 field_id=5,
114 field_type=tracker_pb2.FieldTypes.APPROVAL_TYPE,
115 applicable_type='') # applicable
116 fd_6 = tracker_pb2.FieldDef(
117 field_name='SixthField',
118 field_id=6,
119 field_type=tracker_pb2.FieldTypes.INT_TYPE,
120 applicable_type='Defect') # applicable
121 fd_7 = tracker_pb2.FieldDef(
122 field_name='CatApproval',
123 field_id=7,
124 field_type=tracker_pb2.FieldTypes.APPROVAL_TYPE,
125 applicable_type='') # not applicable
126 config = tracker_bizobj.MakeDefaultProjectIssueConfig(789)
127 config.field_defs = [fd_1, fd_2, fd_3, fd_4, fd_5, fd_6, fd_7]
128 issues = [issue_1, issue_2, issue_3, issue_4, issue_5]
129
130 actual_fds = field_helpers.ListApplicableFieldDefs(issues, config)
131 self.assertEqual(actual_fds, [fd_1, fd_3, fd_4, fd_5, fd_6])
132
133 def testParseFieldDefRequest_Empty(self):
134 post_data = fake.PostData()
135 parsed = field_helpers.ParseFieldDefRequest(post_data, self.config)
136 self.assertEqual('', parsed.field_name)
137 self.assertEqual(None, parsed.field_type_str)
138 self.assertEqual(None, parsed.min_value)
139 self.assertEqual(None, parsed.max_value)
140 self.assertEqual(None, parsed.regex)
141 self.assertFalse(parsed.needs_member)
142 self.assertEqual('', parsed.needs_perm)
143 self.assertEqual('', parsed.grants_perm)
144 self.assertEqual(0, parsed.notify_on)
145 self.assertFalse(parsed.is_required)
146 self.assertFalse(parsed.is_niche)
147 self.assertFalse(parsed.is_multivalued)
148 self.assertEqual('', parsed.field_docstring)
149 self.assertEqual('', parsed.choices_text)
150 self.assertEqual('', parsed.applicable_type)
151 self.assertEqual('', parsed.applicable_predicate)
152 unchanged_labels = [
153 (label_def.label, label_def.label_docstring, label_def.deprecated)
154 for label_def in self.config.well_known_labels]
155 self.assertEqual(unchanged_labels, parsed.revised_labels)
156 self.assertEqual('', parsed.approvers_str)
157 self.assertEqual('', parsed.survey)
158 self.assertEqual('', parsed.parent_approval_name)
159 self.assertFalse(parsed.is_phase_field)
160
161 def testParseFieldDefRequest_Normal(self):
162 post_data = fake.PostData(
163 name=['somefield'],
164 field_type=['INT_TYPE'],
165 min_value=['11'],
166 max_value=['99'],
167 regex=['.*'],
168 needs_member=['Yes'],
169 needs_perm=['Commit'],
170 grants_perm=['View'],
171 notify_on=['any_comment'],
172 importance=['required'],
173 is_multivalued=['Yes'],
174 docstring=['It is just some field'],
175 choices=['Hot = Lots of activity\nCold = Not much activity'],
176 applicable_type=['Defect'],
177 approver_names=['approver@chromium.org'],
178 survey=['Are there UX changes?'],
179 parent_approval_name=['UIReview'],
180 is_phase_field=['on'],
181 )
182 parsed = field_helpers.ParseFieldDefRequest(post_data, self.config)
183 self.assertEqual('somefield', parsed.field_name)
184 self.assertEqual('INT_TYPE', parsed.field_type_str)
185 self.assertEqual(11, parsed.min_value)
186 self.assertEqual(99, parsed.max_value)
187 self.assertEqual('.*', parsed.regex)
188 self.assertTrue(parsed.needs_member)
189 self.assertEqual('Commit', parsed.needs_perm)
190 self.assertEqual('View', parsed.grants_perm)
191 self.assertEqual(1, parsed.notify_on)
192 self.assertTrue(parsed.is_required)
193 self.assertFalse(parsed.is_niche)
194 self.assertTrue(parsed.is_multivalued)
195 self.assertEqual('It is just some field', parsed.field_docstring)
196 self.assertEqual('Hot = Lots of activity\nCold = Not much activity',
197 parsed.choices_text)
198 self.assertEqual('Defect', parsed.applicable_type)
199 self.assertEqual('', parsed.applicable_predicate)
200 unchanged_labels = [
201 (label_def.label, label_def.label_docstring, label_def.deprecated)
202 for label_def in self.config.well_known_labels]
203 new_labels = [
204 ('somefield-Hot', 'Lots of activity', False),
205 ('somefield-Cold', 'Not much activity', False)]
206 self.assertEqual(unchanged_labels + new_labels, parsed.revised_labels)
207 self.assertEqual('approver@chromium.org', parsed.approvers_str)
208 self.assertEqual('Are there UX changes?', parsed.survey)
209 self.assertEqual('UIReview', parsed.parent_approval_name)
210 self.assertTrue(parsed.is_phase_field)
211
212 def testParseFieldDefRequest_PreventPhaseApprovals(self):
213 post_data = fake.PostData(
214 field_type=['approval_type'],
215 is_phase_field=['on'],
216 )
217 parsed = field_helpers.ParseFieldDefRequest(post_data, self.config)
218 self.assertEqual('approval_type', parsed.field_type_str)
219 self.assertFalse(parsed.is_phase_field)
220
221 def testParseChoicesIntoWellKnownLabels_NewFieldDef(self):
222 choices_text = 'Hot = Lots of activity\nCold = Not much activity'
223 field_name = 'somefield'
224 revised_labels = field_helpers._ParseChoicesIntoWellKnownLabels(
225 choices_text, field_name, self.config, 'enum_type')
226 unchanged_labels = [
227 (label_def.label, label_def.label_docstring, label_def.deprecated)
228 for label_def in self.config.well_known_labels]
229 new_labels = [
230 ('somefield-Hot', 'Lots of activity', False),
231 ('somefield-Cold', 'Not much activity', False)]
232 self.assertEqual(unchanged_labels + new_labels, revised_labels)
233
234 def testParseChoicesIntoWellKnownLabels_ConvertExistingLabel(self):
235 choices_text = 'High = Must be fixed\nMedium = Might slip'
236 field_name = 'Priority'
237 revised_labels = field_helpers._ParseChoicesIntoWellKnownLabels(
238 choices_text, field_name, self.config, 'enum_type')
239 kept_labels = [
240 (label_def.label, label_def.label_docstring, label_def.deprecated)
241 for label_def in self.config.well_known_labels
242 if not label_def.label.startswith('Priority-')]
243 new_labels = [
244 ('Priority-High', 'Must be fixed', False),
245 ('Priority-Medium', 'Might slip', False)]
246 self.maxDiff = None
247 self.assertEqual(kept_labels + new_labels, revised_labels)
248
249 # TODO(jojwang): test this separately
250 # test None field_type_str, updating existing fielddef
251 self.config.field_defs.append(tracker_pb2.FieldDef(
252 field_id=13, field_name='Priority',
253 field_type=tracker_pb2.FieldTypes.ENUM_TYPE))
254 revised_labels = field_helpers._ParseChoicesIntoWellKnownLabels(
255 choices_text, field_name, self.config, None)
256 self.assertEqual(kept_labels + new_labels, revised_labels)
257
258 def testParseChoicesIntoWellKnownLabels_NotEnumField(self):
259 choices_text = ''
260 field_name = 'NotEnum'
261 self.config.well_known_labels = [
262 tracker_pb2.LabelDef(label='NotEnum-Should'),
263 tracker_pb2.LabelDef(label='NotEnum-Not-Be-Masked')]
264 revised_labels = field_helpers._ParseChoicesIntoWellKnownLabels(
265 choices_text, field_name, self.config, 'str_type')
266 new_labels = [
267 ('NotEnum-Should', None, False),
268 ('NotEnum-Not-Be-Masked', None, False)]
269 self.assertEqual(new_labels, revised_labels)
270
271 # TODO(jojwang): test this separately
272 # test None field_type_str, updating existing fielddef
273 self.config.field_defs.append(tracker_pb2.FieldDef(
274 field_id=13, field_name='NotEnum',
275 field_type=tracker_pb2.FieldTypes.STR_TYPE))
276 revised_labels = field_helpers._ParseChoicesIntoWellKnownLabels(
277 choices_text, field_name, self.config, None)
278 self.assertEqual(revised_labels, new_labels)
279
280 def testShiftEnumFieldsIntoLabels_Empty(self):
281 labels = []
282 labels_remove = []
283 field_val_strs = {}
284 field_val_strs_remove = {}
285 field_helpers.ShiftEnumFieldsIntoLabels(
286 labels, labels_remove, field_val_strs, field_val_strs_remove,
287 self.config)
288 self.assertEqual([], labels)
289 self.assertEqual([], labels_remove)
290 self.assertEqual({}, field_val_strs)
291 self.assertEqual({}, field_val_strs_remove)
292
293 def testShiftEnumFieldsIntoLabels_NoOp(self):
294 labels = ['Security', 'Performance', 'Pri-1', 'M-2']
295 labels_remove = ['ReleaseBlock']
296 field_val_strs = {123: ['CPU']}
297 field_val_strs_remove = {234: ['Small']}
298 field_helpers.ShiftEnumFieldsIntoLabels(
299 labels, labels_remove, field_val_strs, field_val_strs_remove,
300 self.config)
301 self.assertEqual(['Security', 'Performance', 'Pri-1', 'M-2'], labels)
302 self.assertEqual(['ReleaseBlock'], labels_remove)
303 self.assertEqual({123: ['CPU']}, field_val_strs)
304 self.assertEqual({234: ['Small']}, field_val_strs_remove)
305
306 def testShiftEnumFieldsIntoLabels_FoundSomeEnumFields(self):
307 self.config.field_defs.append(
308 tracker_bizobj.MakeFieldDef(
309 123, 789, 'Component', tracker_pb2.FieldTypes.ENUM_TYPE, None,
310 '', False, False, False, None, None, '', False, '', '',
311 tracker_pb2.NotifyTriggers.NEVER,
312 'no_action', 'What HW part is affected?',
313 False))
314 self.config.field_defs.append(
315 tracker_bizobj.MakeFieldDef(
316 234, 789, 'Size', tracker_pb2.FieldTypes.ENUM_TYPE, None,
317 '', False, False, False, None, None, '', False, '', '',
318 tracker_pb2.NotifyTriggers.NEVER,
319 'no_action', 'How big is this work item?',
320 False))
321 labels = ['Security', 'Performance', 'Pri-1', 'M-2']
322 labels_remove = ['ReleaseBlock']
323 field_val_strs = {123: ['CPU']}
324 field_val_strs_remove = {234: ['Small']}
325 field_helpers.ShiftEnumFieldsIntoLabels(
326 labels, labels_remove, field_val_strs, field_val_strs_remove,
327 self.config)
328 self.assertEqual(
329 ['Security', 'Performance', 'Pri-1', 'M-2', 'Component-CPU'],
330 labels)
331 self.assertEqual(['ReleaseBlock', 'Size-Small'], labels_remove)
332 self.assertEqual({}, field_val_strs)
333 self.assertEqual({}, field_val_strs_remove)
334
335 def testReviseApprovals_New(self):
336 self.config.field_defs.append(
337 tracker_bizobj.MakeFieldDef(
338 123, 789, 'UX Review', tracker_pb2.FieldTypes.APPROVAL_TYPE, None,
339 '', False, False, False, None, None, '', False, '', '',
340 tracker_pb2.NotifyTriggers.NEVER, 'no_action',
341 'Approval for UX review', False))
342 existing_approvaldef = tracker_pb2.ApprovalDef(
343 approval_id=123, approver_ids=[101, 102], survey='')
344 self.config.approval_defs = [existing_approvaldef]
345 revised_approvals = field_helpers.ReviseApprovals(
346 124, [103], '', self.config)
347 self.assertEqual(len(revised_approvals), 2)
348 self.assertEqual(revised_approvals,
349 [(123, [101, 102], ''), (124, [103], '')])
350
351 def testReviseApprovals_Existing(self):
352 existing_approvaldef = tracker_pb2.ApprovalDef(
353 approval_id=123, approver_ids=[101, 102], survey='')
354 self.config.approval_defs = [existing_approvaldef]
355 revised_approvals = field_helpers.ReviseApprovals(
356 123, [103], '', self.config)
357 self.assertEqual(revised_approvals, [(123, [103], '')])
358
359 def testParseOneFieldValue_IntType(self):
360 fd = tracker_bizobj.MakeFieldDef(
361 123, 789, 'Foo', tracker_pb2.FieldTypes.INT_TYPE, None,
362 '', False, False, False, None, None, '', False, '', '',
363 tracker_pb2.NotifyTriggers.NEVER, 'no_action', 'doc', False)
364 fv = field_helpers.ParseOneFieldValue(
365 self.mr.cnxn, self.services.user, fd, '8675309')
366 self.assertEqual(fv.field_id, 123)
367 self.assertEqual(fv.int_value, 8675309)
368
369 def testParseOneFieldValue_StrType(self):
370 fd = tracker_bizobj.MakeFieldDef(
371 123, 789, 'Foo', tracker_pb2.FieldTypes.STR_TYPE, None,
372 '', False, False, False, None, None, '', False, '', '',
373 tracker_pb2.NotifyTriggers.NEVER, 'no_action', 'doc', False)
374 fv = field_helpers.ParseOneFieldValue(
375 self.mr.cnxn, self.services.user, fd, '8675309')
376 self.assertEqual(fv.field_id, 123)
377 self.assertEqual(fv.str_value, '8675309')
378
379 def testParseOneFieldValue_UserType(self):
380 self.services.user.TestAddUser('user@example.com', 111)
381 fd = tracker_bizobj.MakeFieldDef(
382 123, 789, 'Foo', tracker_pb2.FieldTypes.USER_TYPE, None,
383 '', False, False, False, None, None, '', False, '', '',
384 tracker_pb2.NotifyTriggers.NEVER, 'no_action', 'doc', False)
385 fv = field_helpers.ParseOneFieldValue(
386 self.mr.cnxn, self.services.user, fd, 'user@example.com')
387 self.assertEqual(fv.field_id, 123)
388 self.assertEqual(fv.user_id, 111)
389
390 def testParseOneFieldValue_DateType(self):
391 fd = tracker_bizobj.MakeFieldDef(
392 123, 789, 'Deadline', tracker_pb2.FieldTypes.DATE_TYPE, None,
393 '', False, False, False, None, None, '', False, '', '',
394 tracker_pb2.NotifyTriggers.NEVER, 'no_action', 'doc', False)
395 fv = field_helpers.ParseOneFieldValue(
396 self.mr.cnxn, self.services.user, fd, '2009-02-13')
397 self.assertEqual(fv.field_id, 123)
398 self.assertEqual(fv.date_value, 1234483200)
399
400 def testParseOneFieldValue_UrlType(self):
401 fd = tracker_bizobj.MakeFieldDef(
402 123, 789, 'Design Doc', tracker_pb2.FieldTypes.URL_TYPE, None,
403 '', False, False, False, None, None, '', False, '', '',
404 tracker_pb2.NotifyTriggers.NEVER, 'no_action', 'doc', False)
405 fv = field_helpers.ParseOneFieldValue(
406 self.mr.cnxn, self.services.user, fd, 'www.google.com')
407 self.assertEqual(fv.field_id, 123)
408 self.assertEqual(fv.url_value, 'http://www.google.com')
409
410 def testParseOneFieldValue(self):
411 fd = tracker_bizobj.MakeFieldDef(
412 123, 789, 'Target', tracker_pb2.FieldTypes.INT_TYPE, None,
413 '', False, False, False, None, None, '', False, '', '',
414 tracker_pb2.NotifyTriggers.NEVER, 'no_action', 'milestone target',
415 False, is_phase_field=True)
416 phase_fvs = field_helpers.ParseOnePhaseFieldValue(
417 self.mr.cnxn, self.services.user, fd, '70', [30, 40])
418 self.assertEqual(len(phase_fvs), 2)
419 self.assertEqual(phase_fvs[0].phase_id, 30)
420 self.assertEqual(phase_fvs[1].phase_id, 40)
421
422 def testParseFieldValues_Empty(self):
423 field_val_strs = {}
424 phase_field_val_strs = {}
425 field_values = field_helpers.ParseFieldValues(
426 self.mr.cnxn, self.services.user, field_val_strs,
427 phase_field_val_strs, self.config)
428 self.assertEqual([], field_values)
429
430 def testParseFieldValues_EmptyPhases(self):
431 field_val_strs = {126: ['70']}
432 phase_field_val_strs = {}
433 fd_phase = tracker_bizobj.MakeFieldDef(
434 126, 789, 'Target', tracker_pb2.FieldTypes.INT_TYPE, None,
435 '', False, False, False, None, None, '', False, '', '',
436 tracker_pb2.NotifyTriggers.NEVER, 'no_action', 'milestone target',
437 False, is_phase_field=True)
438 self.config.field_defs.extend([fd_phase])
439 field_values = field_helpers.ParseFieldValues(
440 self.mr.cnxn, self.services.user, field_val_strs,
441 phase_field_val_strs, self.config)
442 self.assertEqual([], field_values)
443
444 def testParseFieldValues_Normal(self):
445 fd_int = tracker_bizobj.MakeFieldDef(
446 123, 789, 'CPU', tracker_pb2.FieldTypes.INT_TYPE, None,
447 '', False, False, False, None, None, '', False, '', '',
448 tracker_pb2.NotifyTriggers.NEVER, 'no_action', 'doc', False)
449 fd_date = tracker_bizobj.MakeFieldDef(
450 124, 789, 'Deadline', tracker_pb2.FieldTypes.DATE_TYPE, None,
451 '', False, False, False, None, None, '', False, '', '',
452 tracker_pb2.NotifyTriggers.NEVER, 'no_action', 'doc', False)
453 fd_url = tracker_bizobj.MakeFieldDef(
454 125, 789, 'Design Doc', tracker_pb2.FieldTypes.URL_TYPE, None,
455 '', False, False, False, None, None, '', False, '', '',
456 tracker_pb2.NotifyTriggers.NEVER, 'no_action', 'doc', False)
457 fd_phase = tracker_bizobj.MakeFieldDef(
458 126, 789, 'Target', tracker_pb2.FieldTypes.INT_TYPE, None,
459 '', False, False, False, None, None, '', False, '', '',
460 tracker_pb2.NotifyTriggers.NEVER, 'no_action', 'milestone target',
461 False, is_phase_field=True)
462 self.config.field_defs.extend([fd_int, fd_date, fd_url, fd_phase])
463 field_val_strs = {
464 123: ['80386', '68040'],
465 124: ['2009-02-13'],
466 125: ['www.google.com'],
467 }
468 phase_field_val_strs = {
469 126: {'beta': ['89'],
470 'stable': ['70'],
471 'missing': ['234'],
472 }}
473 field_values = field_helpers.ParseFieldValues(
474 self.mr.cnxn, self.services.user, field_val_strs,
475 phase_field_val_strs, self.config,
476 phase_ids_by_name={'stable': [30, 40], 'beta': [88]})
477 fv1 = tracker_bizobj.MakeFieldValue(
478 123, 80386, None, None, None, None, False)
479 fv2 = tracker_bizobj.MakeFieldValue(
480 123, 68040, None, None, None, None, False)
481 fv3 = tracker_bizobj.MakeFieldValue(
482 124, None, None, None, 1234483200, None, False)
483 fv4 = tracker_bizobj.MakeFieldValue(
484 125, None, None, None, None, 'http://www.google.com', False)
485 fv5 = tracker_bizobj.MakeFieldValue(
486 126, 89, None, None, None, None, False, phase_id=88)
487 fv6 = tracker_bizobj.MakeFieldValue(
488 126, 70, None, None, None, None, False, phase_id=30)
489 fv7 = tracker_bizobj.MakeFieldValue(
490 126, 70, None, None, None, None, False, phase_id=40)
491 self.assertEqual([fv1, fv2, fv3, fv4, fv5, fv6, fv7], field_values)
492
493 def test_IntType(self):
494 fd = tracker_bizobj.MakeFieldDef(
495 123, 789, 'CPU', tracker_pb2.FieldTypes.INT_TYPE, None,
496 '', False, False, False, None, None, '', False, '', '',
497 tracker_pb2.NotifyTriggers.NEVER, 'no_action', 'doc', False)
498 fv = tracker_bizobj.MakeFieldValue(123, 8086, None, None, None, None, False)
499 msg = field_helpers.ValidateCustomFieldValue(
500 self.mr.cnxn, self.mr.project, self.services, fd, fv)
501 self.assertIsNone(msg)
502
503 fd.min_value = 1
504 fd.max_value = 999
505 msg = field_helpers.ValidateCustomFieldValue(
506 self.mr.cnxn, self.mr.project, self.services, fd, fv)
507 self.assertEqual('Value must be <= 999.', msg)
508
509 fv.int_value = 0
510 msg = field_helpers.ValidateCustomFieldValue(
511 self.mr.cnxn, self.mr.project, self.services, fd, fv)
512 self.assertEqual('Value must be >= 1.', msg)
513
514 def test_StrType(self):
515 fd = tracker_bizobj.MakeFieldDef(
516 123, 789, 'CPU', tracker_pb2.FieldTypes.STR_TYPE, None,
517 '', False, False, False, None, None, '', False, '', '',
518 tracker_pb2.NotifyTriggers.NEVER, 'no_action', 'doc', False)
519 fv = tracker_bizobj.MakeFieldValue(
520 123, None, 'i386', None, None, None, False)
521 msg = field_helpers.ValidateCustomFieldValue(
522 self.mr.cnxn, self.mr.project, self.services, fd, fv)
523 self.assertIsNone(msg)
524
525 fd.regex = r'^\d*$'
526 msg = field_helpers.ValidateCustomFieldValue(
527 self.mr.cnxn, self.mr.project, self.services, fd, fv)
528 self.assertEqual(r'Value must match regular expression: ^\d*$.', msg)
529
530 fv.str_value = '386'
531 msg = field_helpers.ValidateCustomFieldValue(
532 self.mr.cnxn, self.mr.project, self.services, fd, fv)
533 self.assertIsNone(msg)
534
535 def test_UserType(self):
536 fd = tracker_bizobj.MakeFieldDef(
537 123, 789, 'Fake Field', tracker_pb2.FieldTypes.USER_TYPE, None,
538 '', False, False, False, None, None, '', False, '', '',
539 tracker_pb2.NotifyTriggers.NEVER, 'no_action', 'doc', False)
540
541 self.services.user.TestAddUser('owner@example.com', 111)
542 self.mr.project.owner_ids.extend([111])
543 owner = tracker_bizobj.MakeFieldValue(
544 fd.field_id, None, None, 111, None, None, False)
545
546 self.services.user.TestAddUser('committer@example.com', 222)
547 self.mr.project.committer_ids.extend([222])
548 self.mr.project.extra_perms = [
549 project_pb2.Project.ExtraPerms(
550 member_id=222,
551 perms=['FooPerm'])]
552 committer = tracker_bizobj.MakeFieldValue(
553 fd.field_id, None, None, 222, None, None, False)
554
555 self.services.user.TestAddUser('user@example.com', 333)
556 user = tracker_bizobj.MakeFieldValue(
557 fd.field_id, None, None, 333, None, None, False)
558
559 # Normal
560 for fv in (owner, committer, user):
561 msg = field_helpers.ValidateCustomFieldValue(
562 self.mr.cnxn, self.mr.project, self.services, fd, fv)
563 self.assertIsNone(msg)
564
565 # Needs to be member (user isn't a member).
566 fd.needs_member = True
567 for fv in (owner, committer):
568 msg = field_helpers.ValidateCustomFieldValue(
569 self.mr.cnxn, self.mr.project, self.services, fd, fv)
570 self.assertIsNone(msg)
571 msg = field_helpers.ValidateCustomFieldValue(
572 self.mr.cnxn, self.mr.project, self.services, fd, user)
573 self.assertEqual('User must be a member of the project.', msg)
574
575 # Needs DeleteAny permission (only owner has it).
576 fd.needs_perm = 'DeleteAny'
577 msg = field_helpers.ValidateCustomFieldValue(
578 self.mr.cnxn, self.mr.project, self.services, fd, owner)
579 self.assertIsNone(msg)
580 msg = field_helpers.ValidateCustomFieldValue(
581 self.mr.cnxn, self.mr.project, self.services, fd, committer)
582 self.assertEqual('User must have permission "DeleteAny".', msg)
583 msg = field_helpers.ValidateCustomFieldValue(
584 self.mr.cnxn, self.mr.project, self.services, fd, user)
585 self.assertEqual('User must be a member of the project.', msg)
586
587 # Needs custom permission (only committer has it).
588 fd.needs_perm = 'FooPerm'
589 msg = field_helpers.ValidateCustomFieldValue(
590 self.mr.cnxn, self.mr.project, self.services, fd, owner)
591 self.assertEqual('User must have permission "FooPerm".', msg)
592 msg = field_helpers.ValidateCustomFieldValue(
593 self.mr.cnxn, self.mr.project, self.services, fd, committer)
594 self.assertIsNone(msg)
595 msg = field_helpers.ValidateCustomFieldValue(
596 self.mr.cnxn, self.mr.project, self.services, fd, user)
597 self.assertEqual('User must be a member of the project.', msg)
598
599 def test_DateType(self):
600 pass # TODO(jrobbins): write this test. @@@
601
602 def test_UrlType(self):
603 fd = tracker_bizobj.MakeFieldDef(
604 123, 789, 'CPU', tracker_pb2.FieldTypes.URL_TYPE, None,
605 '', False, False, False, None, None, '', False, '', '',
606 tracker_pb2.NotifyTriggers.NEVER, 'no_action', 'doc', False)
607
608 fv = tracker_bizobj.MakeFieldValue(
609 123, None, None, None, None, 'www.google.com', False)
610 msg = field_helpers.ValidateCustomFieldValue(
611 self.mr.cnxn, self.mr.project, self.services, fd, fv)
612 self.assertIsNone(msg)
613
614 fv.url_value = 'go/puppies'
615 msg = field_helpers.ValidateCustomFieldValue(
616 self.mr.cnxn, self.mr.project, self.services, fd, fv)
617 self.assertIsNone(msg)
618
619 fv.url_value = 'go/213'
620 msg = field_helpers.ValidateCustomFieldValue(
621 self.mr.cnxn, self.mr.project, self.services, fd, fv)
622 self.assertIsNone(msg)
623
624 fv.url_value = 'puppies'
625 msg = field_helpers.ValidateCustomFieldValue(
626 self.mr.cnxn, self.mr.project, self.services, fd, fv)
627 self.assertEqual('Value must be a valid url.', msg)
628
629 def test_OtherType(self):
630 # There are currently no validation options for date-type custom fields.
631 fd = tracker_bizobj.MakeFieldDef(
632 123, 789, 'Deadline', tracker_pb2.FieldTypes.DATE_TYPE, None,
633 '', False, False, False, None, None, '', False, '', '',
634 tracker_pb2.NotifyTriggers.NEVER, 'no_action', 'doc', False)
635 fv = tracker_bizobj.MakeFieldValue(
636 123, None, None, None, 1234567890, None, False)
637 msg = field_helpers.ValidateCustomFieldValue(
638 self.mr.cnxn, self.mr.project, self.services, fd, fv)
639 self.assertIsNone(msg)
640
641 def testValidateCustomFields_NoCustomFieldValues(self):
642 err_msgs = field_helpers.ValidateCustomFields(
643 self.mr, self.services, [], self.config, self.mr.project,
644 ezt_errors=self.errors)
645 self.assertFalse(self.errors.AnyErrors())
646 self.assertEqual(err_msgs, [])
647
648 def testValidateCustomFields_NoErrors(self):
649 fd = tracker_bizobj.MakeFieldDef(
650 123, 789, 'CPU', tracker_pb2.FieldTypes.INT_TYPE, None,
651 '', False, False, False, None, None, '', False, '', '',
652 tracker_pb2.NotifyTriggers.NEVER, 'no_action', 'doc', False)
653 self.config.field_defs.append(fd)
654 fv1 = tracker_bizobj.MakeFieldValue(
655 123, 8086, None, None, None, None, False)
656 fv2 = tracker_bizobj.MakeFieldValue(123, 486, None, None, None, None, False)
657
658 err_msgs = field_helpers.ValidateCustomFields(
659 self.mr, self.services, [fv1, fv2], self.config, self.mr.project,
660 ezt_errors=self.errors)
661 self.assertFalse(self.errors.AnyErrors())
662 self.assertEqual(err_msgs, [])
663
664 def testValidateCustomFields_SomeValueErrors(self):
665 fd = tracker_bizobj.MakeFieldDef(
666 123, 789, 'CPU', tracker_pb2.FieldTypes.INT_TYPE, None,
667 '', False, False, False, None, None, '', False, '', '',
668 tracker_pb2.NotifyTriggers.NEVER, 'no_action', 'doc', False)
669 self.config.field_defs.append(fd)
670 fv1 = tracker_bizobj.MakeFieldValue(
671 123, 8086, None, None, None, None, False)
672 fv2 = tracker_bizobj.MakeFieldValue(123, 486, None, None, None, None, False)
673
674 fd.min_value = 1
675 fd.max_value = 999
676 err_msgs = field_helpers.ValidateCustomFields(
677 self.mr, self.services, [fv1, fv2], self.config, self.mr.project,
678 ezt_errors=self.errors)
679 self.assertTrue(self.errors.AnyErrors())
680 self.assertEqual(1, len(self.errors.custom_fields))
681 custom_field_error = self.errors.custom_fields[0]
682 self.assertEqual(123, custom_field_error.field_id)
683 self.assertEqual('Value must be <= 999.', custom_field_error.message)
684 self.assertEqual(len(err_msgs), 1)
685 self.assertTrue(re.search(r'Value must be <= 999.', err_msgs[0]))
686
687 def testValidateCustomFields_DeletedRequiredFields_Ignored(self):
688 issue = fake.MakeTestIssue(
689 789,
690 1,
691 'sum',
692 'New',
693 111,
694 issue_id=78901,
695 labels=['type-defect', 'other-label'])
696 fd = tracker_bizobj.MakeFieldDef(
697 123, 789, 'CPU', tracker_pb2.FieldTypes.INT_TYPE, None, '', False,
698 False, False, None, None, '', False, '', '',
699 tracker_pb2.NotifyTriggers.NEVER, 'no_action', 'doc', True)
700 self.config.field_defs.append(fd)
701
702 err_msgs = field_helpers.ValidateCustomFields(
703 self.mr,
704 self.services, [],
705 self.config,
706 self.mr.project,
707 ezt_errors=self.errors,
708 issue=issue)
709 self.assertFalse(self.errors.AnyErrors())
710 self.assertEqual(err_msgs, [])
711
712 def testValidateCustomFields_RequiredFields_Normal(self):
713 issue = fake.MakeTestIssue(
714 789,
715 1,
716 'sum',
717 'New',
718 111,
719 issue_id=78901,
720 labels=['type-defect', 'other-label'])
721
722 required = True
723 fd = tracker_bizobj.MakeFieldDef(
724 123, 789, 'CPU', tracker_pb2.FieldTypes.INT_TYPE, None, '', required,
725 False, False, None, None, '', False, '', '',
726 tracker_pb2.NotifyTriggers.NEVER, 'no_action', 'doc', False)
727 self.config.field_defs.append(fd)
728 fv1 = tracker_bizobj.MakeFieldValue(
729 123, 8086, None, None, None, None, False)
730 fv2 = tracker_bizobj.MakeFieldValue(123, 486, None, None, None, None, False)
731
732 err_msgs = field_helpers.ValidateCustomFields(
733 self.mr,
734 self.services, [fv1, fv2],
735 self.config,
736 self.mr.project,
737 issue=issue)
738 self.assertEqual(len(err_msgs), 0)
739
740 def testValidateCustomFields_RequiredFields_ErrorsWhenMissing(self):
741 issue = fake.MakeTestIssue(
742 789,
743 1,
744 'sum',
745 'New',
746 111,
747 issue_id=78901,
748 labels=['type-defect', 'other-label'])
749
750 required = True
751 fd = tracker_bizobj.MakeFieldDef(
752 123, 789, 'CPU', tracker_pb2.FieldTypes.INT_TYPE, None, '', required,
753 False, False, None, None, '', False, '', '',
754 tracker_pb2.NotifyTriggers.NEVER, 'no_action', 'doc', False)
755 self.config.field_defs.append(fd)
756
757 err_msgs = field_helpers.ValidateCustomFields(
758 self.mr, self.services, [], self.config, self.mr.project, issue=issue)
759 self.assertEqual(len(err_msgs), 1)
760 self.assertTrue(re.search(r'CPU field is required.', err_msgs[0]))
761
762 def testValidateCustomFields_RequiredFields_EnumFieldNormal(self):
763 # Enums are a special case because their values are stored in labels.
764 issue = fake.MakeTestIssue(
765 789,
766 1,
767 'sum',
768 'New',
769 111,
770 issue_id=78901,
771 labels=['type-defect', 'other-label', 'CPU-enum-value'])
772 required = True
773 fd = tracker_bizobj.MakeFieldDef(
774 123, 789, 'CPU', tracker_pb2.FieldTypes.ENUM_TYPE, None, '', required,
775 False, False, None, None, '', False, '', '',
776 tracker_pb2.NotifyTriggers.NEVER, 'no_action', 'doc', False)
777 self.config.field_defs.append(fd)
778
779 err_msgs = field_helpers.ValidateCustomFields(
780 self.mr, self.services, [], self.config, self.mr.project, issue=issue)
781 self.assertEqual(len(err_msgs), 0)
782
783 def testValidateCustomFields_RequiredFields_EnumFieldMultiWord(self):
784 # Enum fields with dashes in them require special label prefix parsing.
785 issue = fake.MakeTestIssue(
786 789,
787 1,
788 'sum',
789 'New',
790 111,
791 issue_id=78901,
792 labels=['type-defect', 'other-label', 'an-enum-value'])
793 required = True
794 fd = tracker_bizobj.MakeFieldDef(
795 123, 789, 'an-enum', tracker_pb2.FieldTypes.ENUM_TYPE, None, '',
796 required, False, False, None, None, '', False, '', '',
797 tracker_pb2.NotifyTriggers.NEVER, 'no_action', 'doc', False)
798 self.config.field_defs.append(fd)
799
800 err_msgs = field_helpers.ValidateCustomFields(
801 self.mr, self.services, [], self.config, self.mr.project, issue=issue)
802 self.assertEqual(len(err_msgs), 0)
803
804 def testValidateCustomFields_RequiredFields_EnumFieldError(self):
805 # Enums are a special case because their values are stored in labels.
806 issue = fake.MakeTestIssue(
807 789,
808 1,
809 'sum',
810 'New',
811 111,
812 issue_id=78901,
813 labels=['type-defect', 'other-label'])
814 required = True
815 fd = tracker_bizobj.MakeFieldDef(
816 123, 789, 'CPU', tracker_pb2.FieldTypes.ENUM_TYPE, None, '', required,
817 False, False, None, None, '', False, '', '',
818 tracker_pb2.NotifyTriggers.NEVER, 'no_action', 'doc', False)
819 self.config.field_defs.append(fd)
820
821 err_msgs = field_helpers.ValidateCustomFields(
822 self.mr, self.services, [], self.config, self.mr.project, issue=issue)
823 self.assertEqual(len(err_msgs), 1)
824 self.assertTrue(re.search(r'CPU field is required.', err_msgs[0]))
825
826 def testAssertCustomFieldsEditPerms_Empty(self):
827 self.assertIsNone(
828 field_helpers.AssertCustomFieldsEditPerms(
829 self.mr, self.config, [], [], [], [], []))
830
831 def testAssertCustomFieldsEditPerms_Normal(self):
832 self.services.user.TestAddUser('user@example.com', 222)
833 self.mr.auth.effective_ids = {222}
834 fd_int = tracker_bizobj.MakeFieldDef(
835 11111,
836 1,
837 'fdInt',
838 tracker_pb2.FieldTypes.INT_TYPE,
839 None,
840 '',
841 False,
842 False,
843 False,
844 None,
845 None,
846 '',
847 False,
848 '',
849 '',
850 tracker_pb2.NotifyTriggers.NEVER,
851 'no_action',
852 'doc',
853 False,
854 is_restricted_field=True)
855 fd_str = tracker_bizobj.MakeFieldDef(
856 22222,
857 1,
858 'fdStr',
859 tracker_pb2.FieldTypes.STR_TYPE,
860 None,
861 '',
862 False,
863 False,
864 False,
865 None,
866 None,
867 '',
868 False,
869 '',
870 '',
871 tracker_pb2.NotifyTriggers.NEVER,
872 'no_action',
873 'doc',
874 False,
875 is_restricted_field=True)
876 fd_date = tracker_bizobj.MakeFieldDef(
877 33333,
878 1,
879 'fdDate',
880 tracker_pb2.FieldTypes.DATE_TYPE,
881 None,
882 '',
883 False,
884 False,
885 False,
886 None,
887 None,
888 '',
889 False,
890 '',
891 '',
892 tracker_pb2.NotifyTriggers.NEVER,
893 'no_action',
894 'doc',
895 False,
896 is_restricted_field=True)
897 fd_enum1 = tracker_bizobj.MakeFieldDef(
898 44444,
899 1,
900 'fdEnum1',
901 tracker_pb2.FieldTypes.ENUM_TYPE,
902 None,
903 '',
904 False,
905 False,
906 False,
907 None,
908 None,
909 '',
910 False,
911 '',
912 '',
913 tracker_pb2.NotifyTriggers.NEVER,
914 'no_action',
915 'doc',
916 False,
917 is_restricted_field=True)
918 fd_enum2 = tracker_bizobj.MakeFieldDef(
919 55555,
920 1,
921 'fdEnum2',
922 tracker_pb2.FieldTypes.ENUM_TYPE,
923 None,
924 '',
925 False,
926 False,
927 False,
928 None,
929 None,
930 '',
931 False,
932 '',
933 '',
934 tracker_pb2.NotifyTriggers.NEVER,
935 'no_action',
936 'doc',
937 False,
938 is_restricted_field=True)
939 self.config.field_defs = [fd_int, fd_str, fd_date, fd_enum1, fd_enum2]
940 fv1 = tracker_bizobj.MakeFieldValue(
941 11111, 37, None, None, None, None, False)
942 fv2 = tracker_bizobj.MakeFieldValue(
943 22222, None, 'Chicken', None, None, None, False)
944 self.assertIsNone(
945 field_helpers.AssertCustomFieldsEditPerms(
946 self.mr, self.config, [fv1], [fv2], [33333], ['Dog', 'fdEnum1-a'],
947 ['Cat', 'fdEnum2-b']))
948
949 def testAssertCustomFieldsEditPerms_Reject(self):
950 self.mr.perms = permissions.PermissionSet([])
951 fd_int = tracker_bizobj.MakeFieldDef(
952 11111,
953 1,
954 'fdInt',
955 tracker_pb2.FieldTypes.INT_TYPE,
956 None,
957 '',
958 False,
959 False,
960 False,
961 None,
962 None,
963 '',
964 False,
965 '',
966 '',
967 tracker_pb2.NotifyTriggers.NEVER,
968 'no_action',
969 'doc',
970 False,
971 is_restricted_field=True)
972 fd_enum = tracker_bizobj.MakeFieldDef(
973 44444,
974 1,
975 'fdEnum',
976 tracker_pb2.FieldTypes.ENUM_TYPE,
977 None,
978 '',
979 False,
980 False,
981 False,
982 None,
983 None,
984 '',
985 False,
986 '',
987 '',
988 tracker_pb2.NotifyTriggers.NEVER,
989 'no_action',
990 'doc',
991 False,
992 is_restricted_field=True)
993 self.config.field_defs = [fd_int, fd_enum]
994 fv = tracker_bizobj.MakeFieldValue(11111, 37, None, None, None, None, False)
995
996 self.assertRaises(
997 AssertionError, field_helpers.AssertCustomFieldsEditPerms, self.mr,
998 self.config, [fv], [], [], [], [])
999
1000 self.assertRaises(
1001 AssertionError, field_helpers.AssertCustomFieldsEditPerms, self.mr,
1002 self.config, [], [fv], [], [], [])
1003
1004 self.assertRaises(
1005 AssertionError, field_helpers.AssertCustomFieldsEditPerms, self.mr,
1006 self.config, [], [], [11111], [], [])
1007
1008 self.assertRaises(
1009 AssertionError, field_helpers.AssertCustomFieldsEditPerms, self.mr,
1010 self.config, [], [], [], ['Dog', 'fdEnum-a'], [])
1011
1012 self.assertRaises(
1013 AssertionError, field_helpers.AssertCustomFieldsEditPerms, self.mr,
1014 self.config, [], [], [], [], ['Cat', 'fdEnum-b'])
1015
1016 def testApplyRestrictedDefaultValues(self):
1017 self.mr.perms = permissions.PermissionSet([])
1018 self.services.user.TestAddUser('user@example.com', 222)
1019 self.mr.auth.effective_ids = {222}
1020 fd_int = tracker_bizobj.MakeFieldDef(
1021 11111,
1022 1,
1023 'fdInt',
1024 tracker_pb2.FieldTypes.INT_TYPE,
1025 None,
1026 '',
1027 False,
1028 False,
1029 False,
1030 None,
1031 None,
1032 '',
1033 False,
1034 '',
1035 '',
1036 tracker_pb2.NotifyTriggers.NEVER,
1037 'no_action',
1038 'doc',
1039 False,
1040 is_restricted_field=False)
1041 fd_str = tracker_bizobj.MakeFieldDef(
1042 22222,
1043 1,
1044 'fdStr',
1045 tracker_pb2.FieldTypes.STR_TYPE,
1046 None,
1047 '',
1048 False,
1049 False,
1050 False,
1051 None,
1052 None,
1053 '',
1054 False,
1055 '',
1056 '',
1057 tracker_pb2.NotifyTriggers.NEVER,
1058 'no_action',
1059 'doc',
1060 False,
1061 is_restricted_field=True)
1062 fd_str_2 = tracker_bizobj.MakeFieldDef(
1063 33333,
1064 1,
1065 'fdStr_2',
1066 tracker_pb2.FieldTypes.STR_TYPE,
1067 None,
1068 '',
1069 False,
1070 False,
1071 False,
1072 None,
1073 None,
1074 '',
1075 False,
1076 '',
1077 '',
1078 tracker_pb2.NotifyTriggers.NEVER,
1079 'no_action',
1080 'doc',
1081 False,
1082 is_restricted_field=False)
1083 fd_enum = tracker_bizobj.MakeFieldDef(
1084 44444,
1085 1,
1086 'fdEnum',
1087 tracker_pb2.FieldTypes.ENUM_TYPE,
1088 None,
1089 '',
1090 False,
1091 False,
1092 False,
1093 None,
1094 None,
1095 '',
1096 False,
1097 '',
1098 '',
1099 tracker_pb2.NotifyTriggers.NEVER,
1100 'no_action',
1101 'doc',
1102 False,
1103 is_restricted_field=False)
1104 fd_restricted_enum = tracker_bizobj.MakeFieldDef(
1105 55555,
1106 1,
1107 'fdRestrictedEnum',
1108 tracker_pb2.FieldTypes.ENUM_TYPE,
1109 None,
1110 '',
1111 False,
1112 False,
1113 False,
1114 None,
1115 None,
1116 '',
1117 False,
1118 '',
1119 '',
1120 tracker_pb2.NotifyTriggers.NEVER,
1121 'no_action',
1122 'doc',
1123 False,
1124 is_restricted_field=True)
1125 self.config.field_defs = [
1126 fd_int, fd_str, fd_str_2, fd_enum, fd_restricted_enum
1127 ]
1128 fv = tracker_bizobj.MakeFieldValue(
1129 33333, None, 'Happy', None, None, None, False)
1130 temp_fv = tracker_bizobj.MakeFieldValue(
1131 11111, 37, None, None, None, None, False)
1132 temp_restricted_fv = tracker_bizobj.MakeFieldValue(
1133 22222, None, 'Chicken', None, None, None, False)
1134 field_vals = [fv]
1135 labels = ['Car', 'Bus']
1136 temp_field_vals = [temp_fv, temp_restricted_fv]
1137 temp_labels = ['Bike', 'fdEnum-a', 'fdRestrictedEnum-b']
1138 field_helpers.ApplyRestrictedDefaultValues(
1139 self.mr, self.config, field_vals, labels, temp_field_vals, temp_labels)
1140 self.assertEqual(labels, ['Car', 'Bus', 'fdRestrictedEnum-b'])
1141 self.assertEqual(field_vals, [fv, temp_restricted_fv])
1142
1143 def testFormatUrlFieldValue(self):
1144 self.assertEqual('http://www.google.com',
1145 field_helpers.FormatUrlFieldValue('www.google.com'))
1146 self.assertEqual('https://www.bing.com',
1147 field_helpers.FormatUrlFieldValue('https://www.bing.com'))
1148
1149 def testReviseFieldDefFromParsed_INT(self):
1150 parsed_field_def = field_helpers.ParsedFieldDef(
1151 'EstDays',
1152 'int_type',
1153 min_value=5,
1154 max_value=7,
1155 regex='',
1156 needs_member=True,
1157 needs_perm='Commit',
1158 grants_perm='View',
1159 notify_on=tracker_pb2.NotifyTriggers.ANY_COMMENT,
1160 is_required=True,
1161 is_niche=True,
1162 importance='required',
1163 is_multivalued=True,
1164 field_docstring='updated doc',
1165 choices_text='',
1166 applicable_type='Launch',
1167 applicable_predicate='',
1168 revised_labels=[],
1169 date_action_str='ping_participants',
1170 approvers_str='',
1171 survey='',
1172 parent_approval_name='',
1173 is_phase_field=False,
1174 is_restricted_field=False)
1175
1176 fd = tracker_bizobj.MakeFieldDef(
1177 123, 789, 'EstDays', tracker_pb2.FieldTypes.INT_TYPE, None,
1178 '', False, False, False, 4, None, '', False, '', '',
1179 tracker_pb2.NotifyTriggers.NEVER, 'no_action', 'doc', False,
1180 approval_id=3)
1181
1182 new_fd = field_helpers.ReviseFieldDefFromParsed(parsed_field_def, fd)
1183 # assert INT fields
1184 self.assertEqual(new_fd.min_value, 5)
1185 self.assertEqual(new_fd.max_value, 7)
1186
1187 # assert USER fields
1188 self.assertEqual(new_fd.notify_on, tracker_pb2.NotifyTriggers.ANY_COMMENT)
1189 self.assertTrue(new_fd.needs_member)
1190 self.assertEqual(new_fd.needs_perm, 'Commit')
1191 self.assertEqual(new_fd.grants_perm, 'View')
1192
1193 # assert DATE fields
1194 self.assertEqual(new_fd.date_action,
1195 tracker_pb2.DateAction.PING_PARTICIPANTS)
1196
1197 # assert general fields
1198 self.assertTrue(new_fd.is_required)
1199 self.assertTrue(new_fd.is_niche)
1200 self.assertEqual(new_fd.applicable_type, 'Launch')
1201 self.assertEqual(new_fd.docstring, 'updated doc')
1202 self.assertTrue(new_fd.is_multivalued)
1203 self.assertEqual(new_fd.approval_id, 3)
1204 self.assertFalse(new_fd.is_phase_field)
1205 self.assertFalse(new_fd.is_restricted_field)
1206
1207 def testParsedFieldDefAssertions_Accepted(self):
1208 parsed_fd = field_helpers.ParsedFieldDef(
1209 'EstDays',
1210 'int_type',
1211 min_value=5,
1212 max_value=7,
1213 regex='',
1214 needs_member=True,
1215 needs_perm='Commit',
1216 grants_perm='View',
1217 notify_on=tracker_pb2.NotifyTriggers.ANY_COMMENT,
1218 is_required=True,
1219 is_niche=False,
1220 importance='required',
1221 is_multivalued=True,
1222 field_docstring='updated doc',
1223 choices_text='',
1224 applicable_type='Launch',
1225 applicable_predicate='',
1226 revised_labels=[],
1227 date_action_str='ping_participants',
1228 approvers_str='',
1229 survey='',
1230 parent_approval_name='',
1231 is_phase_field=False,
1232 is_restricted_field=False)
1233
1234 field_helpers.ParsedFieldDefAssertions(self.mr, parsed_fd)
1235 self.assertFalse(self.mr.errors.AnyErrors())
1236
1237 def testParsedFieldDefAssertions_Rejected(self):
1238 parsed_fd = field_helpers.ParsedFieldDef(
1239 'restrictApprovalField',
1240 'approval_type',
1241 min_value=10,
1242 max_value=7,
1243 regex='/foo(?)/',
1244 needs_member=True,
1245 needs_perm='Commit',
1246 grants_perm='View',
1247 notify_on=tracker_pb2.NotifyTriggers.ANY_COMMENT,
1248 is_required=True,
1249 is_niche=True,
1250 importance='required',
1251 is_multivalued=True,
1252 field_docstring='updated doc',
1253 choices_text='',
1254 applicable_type='Launch',
1255 applicable_predicate='',
1256 revised_labels=[],
1257 date_action_str='custom_date_action_str',
1258 approvers_str='',
1259 survey='',
1260 parent_approval_name='',
1261 is_phase_field=False,
1262 is_restricted_field=True)
1263
1264 field_helpers.ParsedFieldDefAssertions(self.mr, parsed_fd)
1265 self.assertTrue(self.mr.errors.AnyErrors())
1266
1267 self.assertEqual(
1268 self.mr.errors.is_niche, 'A field cannot be both required and niche.')
1269 self.assertEqual(
1270 self.mr.errors.date_action,
1271 'The date action should be either: ' + ', '.join(
1272 config_svc.DATE_ACTION_ENUM) + '.')
1273 self.assertEqual(
1274 self.mr.errors.min_value, 'Minimum value must be less than maximum.')
1275 self.assertEqual(self.mr.errors.regex, 'Invalid regular expression.')
Adrià Vilanova Martínezf19ea432024-01-23 20:20:52 +01001276
1277 def testValidateLabels_NoLabels(self):
1278 err_msg = field_helpers.ValidateLabels(
1279 self.mr.cnxn,
1280 self.services,
1281 self.mr.project_id, [''],
1282 ezt_errors=self.errors)
1283 self.assertFalse(self.errors.AnyErrors())
1284 self.assertEqual(err_msg, None)
1285
1286 def testValidateLabels_ExistingLabel(self):
1287 err_msg = field_helpers.ValidateLabels(
1288 self.mr.cnxn,
1289 self.services,
1290 self.mr.project_id, ['old_label'],
1291 ezt_errors=self.errors)
1292 self.assertFalse(self.errors.AnyErrors())
1293 self.assertEqual(err_msg, None)
1294
1295 def testValidateLabels_AllowlistedLabel(self):
1296 err_msg = field_helpers.ValidateLabels(
1297 self.mr.cnxn,
1298 self.services,
1299 self.mr.project_id, ['old_label', 'CVE-test'],
1300 ezt_errors=self.errors)
1301 self.assertFalse(self.errors.AnyErrors())
1302 self.assertEqual(err_msg, None)
1303
1304 def testValidateLabels_Error(self):
1305 err_msg = field_helpers.ValidateLabels(
1306 self.mr.cnxn,
1307 self.services,
1308 self.mr.project_id, ['freeze_new_label'],
1309 ezt_errors=self.errors)
1310 self.assertTrue(self.errors.AnyErrors())
1311 self.assertEqual(
1312 err_msg, (
1313 'The creation of new labels is blocked for the Chromium project'
1314 ' in Monorail. To continue with editing your issue, please'
1315 ' remove: freeze_new_label label(s).'))