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