blob: ecd096bed5801530cb1003adbabcda0a9368216b [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 fielddetail servlet."""
6from __future__ import print_function
7from __future__ import division
8from __future__ import absolute_import
9
Adrià Vilanova Martínez9f9ade52022-10-10 23:20:11 +020010try:
11 from mox3 import mox
12except ImportError:
13 import mox
Copybara854996b2021-09-07 19:36:02 +000014import unittest
15import logging
16
Copybara854996b2021-09-07 19:36:02 +000017from framework import permissions
Adrià Vilanova Martínezf19ea432024-01-23 20:20:52 +010018from mrproto import project_pb2
19from mrproto import tracker_pb2
Copybara854996b2021-09-07 19:36:02 +000020from services import service_manager
21from testing import fake
22from testing import testing_helpers
23from tracker import fielddetail
24from tracker import tracker_bizobj
Copybara854996b2021-09-07 19:36:02 +000025
26
27class FieldDetailTest(unittest.TestCase):
28
29 def setUp(self):
30 self.services = service_manager.Services(
31 user=fake.UserService(),
32 config=fake.ConfigService(),
33 project=fake.ProjectService())
Adrià Vilanova Martínezf19ea432024-01-23 20:20:52 +010034 self.servlet = fielddetail.FieldDetail(services=self.services)
Copybara854996b2021-09-07 19:36:02 +000035 self.project = self.services.project.TestAddProject('proj')
36 self.mr = testing_helpers.MakeMonorailRequest(
37 project=self.project, perms=permissions.OWNER_ACTIVE_PERMISSIONSET)
38 self.config = self.services.config.GetProjectConfig(
39 'fake cnxn', self.project.project_id)
40 self.services.config.StoreConfig('fake cnxn', self.config)
41 self.fd = tracker_bizobj.MakeFieldDef(
42 123, 789, 'CPU', tracker_pb2.FieldTypes.INT_TYPE, None,
43 '', False, False, False, None, None, '', False, '', '',
44 tracker_pb2.NotifyTriggers.NEVER, 'no_action', 'doc', False)
45 self.fd.admin_ids = [111]
46 self.fd.editor_ids = [222]
47 self.config.field_defs.append(self.fd)
48 self.services.user.TestAddUser('gatsby@example.com', 111)
49 self.services.user.TestAddUser('sport@example.com', 222)
50 self.mr.field_name = 'CPU'
51
52 # Approvals
53 self.approval_def = tracker_pb2.ApprovalDef(
54 approval_id=234, approver_ids=[111], survey='Question 1?')
55 self.sub_fd = tracker_pb2.FieldDef(
56 field_name='UIMocks', approval_id=234, applicable_type='')
57 self.sub_fd_deleted = tracker_pb2.FieldDef(
58 field_name='UIMocksDeleted', approval_id=234, applicable_type='',
59 is_deleted=True)
60 self.config.field_defs.extend([self.sub_fd, self.sub_fd_deleted])
61 self.config.approval_defs.append(self.approval_def)
62 self.approval_fd = tracker_bizobj.MakeFieldDef(
63 234, 789, 'UIReview', tracker_pb2.FieldTypes.APPROVAL_TYPE, None,
64 '', False, False, False, None, None, '', False, '', '',
65 tracker_pb2.NotifyTriggers.NEVER, 'no_action', 'doc', False)
66 self.config.field_defs.append(self.approval_fd)
67
68 self.mox = mox.Mox()
69
70 def tearDown(self):
71 self.mox.UnsetStubs()
72 self.mox.ResetAll()
73
74 def testGetFieldDef_NotFound(self):
75 self.mr.field_name = 'NeverHeardOfIt'
Adrià Vilanova Martínezf19ea432024-01-23 20:20:52 +010076 self.assertRaises(Exception, self.servlet._GetFieldDef, self.mr)
Copybara854996b2021-09-07 19:36:02 +000077
78 def testGetFieldDef_Normal(self):
79 actual_config, actual_fd = self.servlet._GetFieldDef(self.mr)
80 self.assertEqual(self.config, actual_config)
81 self.assertEqual(self.fd, actual_fd)
82
83 def testAssertBasePermission_AnyoneCanView(self):
84 self.servlet.AssertBasePermission(self.mr)
85 self.mr.perms = permissions.COMMITTER_ACTIVE_PERMISSIONSET
86 self.servlet.AssertBasePermission(self.mr)
87 self.mr.perms = permissions.CONTRIBUTOR_ACTIVE_PERMISSIONSET
88 self.servlet.AssertBasePermission(self.mr)
89 self.mr.perms = permissions.READ_ONLY_PERMISSIONSET
90 self.servlet.AssertBasePermission(self.mr)
91
92 def testAssertBasePermission_MembersOnly(self):
93 self.project.access = project_pb2.ProjectAccess.MEMBERS_ONLY
94 # The project members can view the field definition.
95 self.servlet.AssertBasePermission(self.mr)
96 self.mr.perms = permissions.COMMITTER_ACTIVE_PERMISSIONSET
97 self.servlet.AssertBasePermission(self.mr)
98 self.mr.perms = permissions.CONTRIBUTOR_ACTIVE_PERMISSIONSET
99 self.servlet.AssertBasePermission(self.mr)
100 # Non-member is not allowed to view anything in the project.
101 self.mr.perms = permissions.EMPTY_PERMISSIONSET
102 self.assertRaises(
103 permissions.PermissionException,
104 self.servlet.AssertBasePermission, self.mr)
105
106 def testGatherPageData_ReadWrite(self):
107 page_data = self.servlet.GatherPageData(self.mr)
108 self.assertEqual(self.servlet.PROCESS_TAB_LABELS,
109 page_data['admin_tab_mode'])
110 self.assertTrue(page_data['allow_edit'])
111 self.assertEqual('gatsby@example.com', page_data['initial_admins'])
112 self.assertEqual('sport@example.com', page_data['initial_editors'])
113 field_def_view = page_data['field_def']
114 self.assertEqual('CPU', field_def_view.field_name)
115 self.assertEqual(page_data['approval_subfields'], [])
116 self.assertEqual(page_data['initial_approvers'], '')
117
118 def testGatherPageData_ReadOnly(self):
119 self.mr.perms = permissions.READ_ONLY_PERMISSIONSET
120 page_data = self.servlet.GatherPageData(self.mr)
121 self.assertEqual(self.servlet.PROCESS_TAB_LABELS,
122 page_data['admin_tab_mode'])
123 self.assertFalse(page_data['allow_edit'])
124 self.assertEqual('gatsby@example.com', page_data['initial_admins'])
125 self.assertEqual('sport@example.com', page_data['initial_editors'])
126 field_def_view = page_data['field_def']
127 self.assertEqual('CPU', field_def_view.field_name)
128 self.assertEqual(page_data['approval_subfields'], [])
129 self.assertEqual(page_data['initial_approvers'], '')
130
131 def testGatherPageData_Approval(self):
132 self.mr.field_name = 'UIReview'
133 page_data = self.servlet.GatherPageData(self.mr)
134 self.assertEqual(page_data['approval_subfields'], [self.sub_fd])
135 self.assertEqual(page_data['initial_approvers'], 'gatsby@example.com')
136 field_def_view = page_data['field_def']
137 self.assertEqual(field_def_view.field_name, 'UIReview')
138 self.assertEqual(field_def_view.survey, 'Question 1?')
139
140 def testProcessFormData_Permission(self):
141 """Only owners can edit fields."""
142 mr = testing_helpers.MakeMonorailRequest(
143 project=self.project,
144 perms=permissions.CONTRIBUTOR_ACTIVE_PERMISSIONSET)
145 mr.field_name = 'CPU'
146 post_data = fake.PostData(
147 name=['CPU'],
148 deletefield=['Submit'])
149 self.assertRaises(permissions.PermissionException,
150 self.servlet.ProcessFormData, mr, post_data)
151
152 self.servlet.ProcessFormData(self.mr, post_data)
153
154 def testProcessFormData_Delete(self):
155 post_data = fake.PostData(
156 name=['CPU'],
157 deletefield=['Submit'])
158 url = self.servlet.ProcessFormData(self.mr, post_data)
159 self.assertTrue('/adminLabels?deleted=1&' in url)
160 fd = tracker_bizobj.FindFieldDef('CPU', self.config)
161 self.assertEqual('CPU', fd.field_name)
162 self.assertTrue(fd.is_deleted)
163
164 def testProcessFormData_Cancel(self):
165 post_data = fake.PostData(
166 name=['CPU'],
167 cancel=['Submit'],
168 max_value=['200'])
169 url = self.servlet.ProcessFormData(self.mr, post_data)
170 logging.info(url)
171 self.assertTrue('/adminLabels?ts=' in url)
172 config = self.services.config.GetProjectConfig(
173 self.mr.cnxn, self.mr.project_id)
174
175 fd = tracker_bizobj.FindFieldDef('CPU', config)
176 self.assertIsNone(fd.max_value)
177 self.assertIsNone(fd.min_value)
178
179 def testProcessFormData_Edit(self):
180 post_data = fake.PostData(
181 name=['CPU'],
182 field_type=['INT_TYPE'],
183 min_value=['2'],
184 max_value=['98'],
185 notify_on=['never'],
186 is_required=[],
187 is_multivalued=[],
188 docstring=['It is just some field'],
189 applicable_type=['Defect'],
190 admin_names=['gatsby@example.com'])
191 url = self.servlet.ProcessFormData(self.mr, post_data)
192 self.assertTrue('/fields/detail?field=CPU&saved=1&' in url)
193 config = self.services.config.GetProjectConfig(
194 self.mr.cnxn, self.mr.project_id)
195
196 fd = tracker_bizobj.FindFieldDef('CPU', config)
197 self.assertEqual('CPU', fd.field_name)
198 self.assertEqual(2, fd.min_value)
199 self.assertEqual(98, fd.max_value)
200 self.assertEqual([111], fd.admin_ids)
201 self.assertEqual([], fd.editor_ids)
202
203 def testProcessDeleteField(self):
204 self.servlet._ProcessDeleteField(self.mr, self.config, self.fd)
205 self.assertTrue(self.fd.is_deleted)
206
207 def testProcessDeleteField_subfields(self):
208 approval_fd = tracker_bizobj.MakeFieldDef(
209 3, 789, 'Legal', tracker_pb2.FieldTypes.APPROVAL_TYPE, None,
210 '', False, False, False, None, None, '', False, '', '',
211 tracker_pb2.NotifyTriggers.NEVER, 'no_action', 'doc', False)
212 self.fd.approval_id=3
213 self.config.field_defs.append(approval_fd)
214 self.servlet._ProcessDeleteField(self.mr, self.config, approval_fd)
215 self.assertTrue(self.fd.is_deleted)
216 self.assertTrue(approval_fd.is_deleted)
217
218 def testProcessEditField_Normal(self):
219 post_data = fake.PostData(
220 name=['CPU'],
221 field_type=['INT_TYPE'],
222 min_value=['2'],
223 admin_names=['gatsby@example.com'],
224 editor_names=['sport@example.com'],
225 is_restricted_field=['Yes'])
226 self.servlet._ProcessEditField(
227 self.mr, post_data, self.config, self.fd)
228 fd = tracker_bizobj.FindFieldDef('CPU', self.config)
229 self.assertEqual('CPU', fd.field_name)
230 self.assertEqual(2, fd.min_value)
231 self.assertEqual([111], fd.admin_ids)
232 self.assertEqual([222], fd.editor_ids)
233
234 def testProcessEditField_Reject(self):
235 post_data = fake.PostData(
236 name=['CPU'],
237 field_type=['INT_TYPE'],
238 min_value=['4'],
239 max_value=['1'],
240 admin_names=[''],
241 editor_names=[''])
242
243 self.mox.StubOutWithMock(self.servlet, 'PleaseCorrect')
244 self.servlet.PleaseCorrect(
245 self.mr,
246 field_def=mox.IgnoreArg(),
247 initial_applicable_type='',
248 initial_choices='',
249 initial_admins='',
250 initial_editors='',
251 initial_approvers='',
252 initial_is_restricted_field=False)
253 self.mox.ReplayAll()
254
255 url = self.servlet._ProcessEditField(
256 self.mr, post_data, self.config, self.fd)
257 self.assertEqual('Minimum value must be less than maximum.',
258 self.mr.errors.min_value)
259 self.assertIsNone(url)
260
261 fd = tracker_bizobj.FindFieldDef('CPU', self.config)
262 self.assertIsNone(fd.min_value)
263 self.assertIsNone(fd.max_value)
264
265 def testProcessEditField_Reject_EditorsForNonRestrictedField(self):
266 # This method tests that an exception is raised
267 # when trying to add editors to a non restricted field.
268 post_data = fake.PostData(
269 name=['CPU'],
270 field_type=['INT_TYPE'],
271 min_value=['2'],
272 admin_names=[''],
273 editor_names=['gatsby@example.com'])
274
275 self.assertRaises(
276 AssertionError, self.servlet._ProcessEditField, self.mr, post_data,
277 self.config, self.fd)
278
279 def testProcessEditField_RejectAssertions_1(self):
280 # This method tests that an exception is raised
281 # when trying to add editors to an approval field.
282 post_data = fake.PostData(
283 name=['CPU'],
284 approver_names=['gatsby@example.com'],
285 admin_names=[''],
286 editor_names=['sports@example.com'])
287
288 self.assertRaises(
289 AssertionError, self.servlet._ProcessEditField, self.mr, post_data,
290 self.config, self.approval_fd)
291
292 def testProcessEditField_RejectAssertions_2(self):
293 #This method tests that an exception is raised
294 #when trying to restrict an approval field.
295 post_data = fake.PostData(
296 name=['CPU'],
297 approver_names=['gatsby@example.com'],
298 is_restricted_field=['Yes'],
299 admin_names=[''],
300 editor_names=[''])
301
302 self.assertRaises(
303 AssertionError, self.servlet._ProcessEditField, self.mr, post_data,
304 self.config, self.approval_fd)
305
306 def testProcessEditField_RejectApproval(self):
307 self.mr.field_name = 'UIReview'
308 post_data = fake.PostData(
309 name=['UIReview'],
310 admin_names=[''],
311 editor_names=[''],
312 survey=['WIll there be UI changes?'],
313 approver_names=[''])
314
315 self.mox.StubOutWithMock(self.servlet, 'PleaseCorrect')
316 self.servlet.PleaseCorrect(
317 self.mr,
318 field_def=mox.IgnoreArg(),
319 initial_applicable_type='',
320 initial_choices='',
321 initial_admins='',
322 initial_editors='',
323 initial_approvers='',
324 initial_is_restricted_field=False)
325 self.mox.ReplayAll()
326
327 url = self.servlet._ProcessEditField(
328 self.mr, post_data, self.config, self.approval_fd)
329 self.assertEqual('Please provide at least one default approver.',
330 self.mr.errors.approvers)
331 self.assertIsNone(url)
332
333 def testProcessEditField_Approval(self):
334 self.mr.field_name = 'UIReview'
335 post_data = fake.PostData(
336 name=['UIReview'],
337 admin_names=[''],
338 editor_names=[''],
339 survey=['WIll there be UI changes?'],
340 approver_names=['sport@example.com, gatsby@example.com'])
341
342
343 url = self.servlet._ProcessEditField(
344 self.mr, post_data, self.config, self.approval_fd)
345 self.assertTrue('/fields/detail?field=UIReview&saved=1&' in url)
346
347 approval_def = tracker_bizobj.FindApprovalDef('UIReview', self.config)
348 self.assertEqual(len(approval_def.approver_ids), 2)
349 self.assertEqual(sorted(approval_def.approver_ids), sorted([111, 222]))