blob: 0dcff927f52122d16462b47f02deee8e436d0d03 [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 componentdetail servlet."""
6from __future__ import print_function
7from __future__ import division
8from __future__ import absolute_import
9
10import unittest
11
Adrià Vilanova Martínezf19ea432024-01-23 20:20:52 +010012from mock import Mock
Copybara854996b2021-09-07 19:36:02 +000013
Adrià Vilanova Martínez9f9ade52022-10-10 23:20:11 +020014try:
15 from mox3 import mox
16except ImportError:
17 import mox
Copybara854996b2021-09-07 19:36:02 +000018
19from features import filterrules_helpers
20from framework import permissions
Adrià Vilanova Martínezf19ea432024-01-23 20:20:52 +010021from mrproto import project_pb2
Copybara854996b2021-09-07 19:36:02 +000022from services import service_manager
23from services import template_svc
24from testing import fake
25from testing import testing_helpers
26from tracker import componentdetail
27from tracker import tracker_bizobj
28
Copybara854996b2021-09-07 19:36:02 +000029
30class ComponentDetailTest(unittest.TestCase):
31
32 def setUp(self):
33 self.services = service_manager.Services(
34 user=fake.UserService(),
35 issue=fake.IssueService(),
36 config=fake.ConfigService(),
37 template=Mock(spec=template_svc.TemplateService),
38 project=fake.ProjectService())
Adrià Vilanova Martínezf19ea432024-01-23 20:20:52 +010039 self.servlet = componentdetail.ComponentDetail(services=self.services)
Copybara854996b2021-09-07 19:36:02 +000040 self.project = self.services.project.TestAddProject('proj')
41 self.mr = testing_helpers.MakeMonorailRequest(
42 project=self.project, perms=permissions.OWNER_ACTIVE_PERMISSIONSET)
43 self.mr.auth.email = 'b@example.com'
44 self.config = self.services.config.GetProjectConfig(
45 'fake cnxn', self.project.project_id)
46 self.services.config.StoreConfig('fake cnxn', self.config)
47 self.cd = tracker_bizobj.MakeComponentDef(
48 1, self.project.project_id, 'BackEnd', 'doc', False, [], [111], 100000,
49 122, 10000000, 133)
50 self.config.component_defs = [self.cd]
51 self.services.user.TestAddUser('a@example.com', 111)
52 self.services.user.TestAddUser('b@example.com', 122)
53 self.services.user.TestAddUser('c@example.com', 133)
54 self.mr.component_path = 'BackEnd'
55
56 self.mox = mox.Mox()
57
58 def tearDown(self):
59 self.mox.UnsetStubs()
60 self.mox.ResetAll()
61
62 def testGetComponentDef_NotFound(self):
63 self.mr.component_path = 'NeverHeardOfIt'
Adrià Vilanova Martínezf19ea432024-01-23 20:20:52 +010064 self.assertRaises(Exception, self.servlet._GetComponentDef, self.mr)
Copybara854996b2021-09-07 19:36:02 +000065
66 def testGetComponentDef_Normal(self):
67 actual_config, actual_cd = self.servlet._GetComponentDef(self.mr)
68 self.assertEqual(self.config, actual_config)
69 self.assertEqual(self.cd, actual_cd)
70
71 def testAssertBasePermission_AnyoneCanView(self):
72 self.servlet.AssertBasePermission(self.mr)
73 self.mr.perms = permissions.COMMITTER_ACTIVE_PERMISSIONSET
74 self.servlet.AssertBasePermission(self.mr)
75 self.mr.perms = permissions.CONTRIBUTOR_ACTIVE_PERMISSIONSET
76 self.servlet.AssertBasePermission(self.mr)
77 self.mr.perms = permissions.READ_ONLY_PERMISSIONSET
78 self.servlet.AssertBasePermission(self.mr)
79
80 def testAssertBasePermission_MembersOnly(self):
81 self.project.access = project_pb2.ProjectAccess.MEMBERS_ONLY
82 # The project members can view the component definition.
83 self.servlet.AssertBasePermission(self.mr)
84 self.mr.perms = permissions.COMMITTER_ACTIVE_PERMISSIONSET
85 self.servlet.AssertBasePermission(self.mr)
86 self.mr.perms = permissions.CONTRIBUTOR_ACTIVE_PERMISSIONSET
87 self.servlet.AssertBasePermission(self.mr)
88 # Non-member is not allowed to view anything in the project.
89 self.mr.perms = permissions.EMPTY_PERMISSIONSET
90 self.assertRaises(
91 permissions.PermissionException,
92 self.servlet.AssertBasePermission, self.mr)
93
94 def testGatherPageData_ReadWrite(self):
95 page_data = self.servlet.GatherPageData(self.mr)
96 self.assertEqual(self.servlet.PROCESS_TAB_COMPONENTS,
97 page_data['admin_tab_mode'])
98 self.assertTrue(page_data['allow_edit'])
99 self.assertEqual([], page_data['initial_admins'])
100 component_def_view = page_data['component_def']
101 self.assertEqual('BackEnd', component_def_view.path)
102
103 def testGatherPageData_ReadOnly(self):
104 self.mr.perms = permissions.READ_ONLY_PERMISSIONSET
105 page_data = self.servlet.GatherPageData(self.mr)
106 self.assertEqual(self.servlet.PROCESS_TAB_COMPONENTS,
107 page_data['admin_tab_mode'])
108 self.assertFalse(page_data['allow_edit'])
109 self.assertFalse(page_data['allow_delete'])
110 self.assertEqual([], page_data['initial_admins'])
111 component_def_view = page_data['component_def']
112 self.assertEqual('BackEnd', component_def_view.path)
113
114 def testGatherPageData_ObscuredCreatorModifier(self):
115 page_data = self.servlet.GatherPageData(self.mr)
116
117 self.assertEqual('b...@example.com', page_data['creator'].display_name)
118 self.assertEqual('/u/122/', page_data['creator'].profile_url)
119 self.assertEqual('Jan 1970', page_data['created'])
120 self.assertEqual('c...@example.com', page_data['modifier'].display_name)
121 self.assertEqual('/u/133/', page_data['modifier'].profile_url)
122 self.assertEqual('Apr 1970', page_data['modified'])
123
124 def testGatherPageData_VisibleCreatorModifierForAdmin(self):
125 self.mr.auth.user_pb.is_site_admin = True
126 page_data = self.servlet.GatherPageData(self.mr)
127
128 self.assertEqual('b@example.com', page_data['creator'].display_name)
129 self.assertEqual('/u/b@example.com/', page_data['creator'].profile_url)
130 self.assertEqual('Jan 1970', page_data['created'])
131 self.assertEqual('c@example.com', page_data['modifier'].display_name)
132 self.assertEqual('/u/c@example.com/', page_data['modifier'].profile_url)
133 self.assertEqual('Apr 1970', page_data['modified'])
134
135 def testGatherPageData_VisibleCreatorForSelf(self):
136 self.mr.auth.user_id = 122
137 page_data = self.servlet.GatherPageData(self.mr)
138
139 self.assertEqual('b@example.com', page_data['creator'].display_name)
140 self.assertEqual('/u/b@example.com/', page_data['creator'].profile_url)
141 self.assertEqual('Jan 1970', page_data['created'])
142 # Modifier should still be obscured.
143 self.assertEqual('c...@example.com', page_data['modifier'].display_name)
144 self.assertEqual('/u/133/', page_data['modifier'].profile_url)
145 self.assertEqual('Apr 1970', page_data['modified'])
146
147 def testGatherPageData_VisibleCreatorModifierForUnobscuredEmail(self):
148 creator = self.services.user.GetUser(self.mr.cnxn, 122)
149 creator.obscure_email = False
150 modifier = self.services.user.GetUser(self.mr.cnxn, 133)
151 modifier.obscure_email = False
152 page_data = self.servlet.GatherPageData(self.mr)
153
154 self.assertEqual('b@example.com', page_data['creator'].display_name)
155 self.assertEqual('/u/b@example.com/', page_data['creator'].profile_url)
156 self.assertEqual('Jan 1970', page_data['created'])
157 self.assertEqual('c@example.com', page_data['modifier'].display_name)
158 self.assertEqual('/u/c@example.com/', page_data['modifier'].profile_url)
159 self.assertEqual('Apr 1970', page_data['modified'])
160
161 def testGatherPageData_WithSubComponents(self):
162 subcd = tracker_bizobj.MakeComponentDef(
163 2, self.project.project_id, 'BackEnd>Worker', 'doc', False, [], [111],
164 0, 122)
165 self.config.component_defs.append(subcd)
166 page_data = self.servlet.GatherPageData(self.mr)
167 self.assertFalse(page_data['allow_delete'])
168 self.assertEqual([subcd], page_data['subcomponents'])
169
170 def testGatherPageData_WithTemplates(self):
171 self.services.template.TemplatesWithComponent.return_value = ['template']
172 page_data = self.servlet.GatherPageData(self.mr)
173 self.assertFalse(page_data['allow_delete'])
174 self.assertEqual(['template'], page_data['templates'])
175
176 def testProcessFormData_Permission(self):
177 """Only owners can edit components."""
178 mr = testing_helpers.MakeMonorailRequest(
179 project=self.project,
180 perms=permissions.CONTRIBUTOR_ACTIVE_PERMISSIONSET)
181 mr.component_path = 'BackEnd'
182 post_data = fake.PostData(
183 name=['BackEnd'],
184 deletecomponent=['Submit'])
185 self.assertRaises(permissions.PermissionException,
186 self.servlet.ProcessFormData, mr, post_data)
187
188 self.servlet.ProcessFormData(self.mr, post_data)
189
190 def testProcessFormData_Delete(self):
191 post_data = fake.PostData(
192 name=['BackEnd'],
193 deletecomponent=['Submit'])
194 url = self.servlet.ProcessFormData(self.mr, post_data)
195 self.assertTrue('/adminComponents?deleted=1&' in url)
196 self.assertIsNone(
197 tracker_bizobj.FindComponentDef('BackEnd', self.config))
198
199 def testProcessFormData_Delete_WithSubComponent(self):
200 subcd = tracker_bizobj.MakeComponentDef(
201 2, self.project.project_id, 'BackEnd>Worker', 'doc', False, [], [111],
202 0, 122)
203 self.config.component_defs.append(subcd)
204
205 post_data = fake.PostData(
206 name=['BackEnd'],
207 deletecomponent=['Submit'])
208 with self.assertRaises(permissions.PermissionException) as cm:
209 self.servlet.ProcessFormData(self.mr, post_data)
210 self.assertEqual(
211 'User tried to delete component that had subcomponents',
Adrià Vilanova Martínezf19ea432024-01-23 20:20:52 +0100212 str(cm.exception))
Copybara854996b2021-09-07 19:36:02 +0000213
214 def testProcessFormData_Edit(self):
215 post_data = fake.PostData(
216 leaf_name=['BackEnd'],
217 docstring=['This is where the magic happens'],
218 deprecated=[True],
219 admins=['a@example.com'],
220 cc=['a@example.com'],
221 labels=['Hot, Cold'])
222
223 url = self.servlet.ProcessFormData(self.mr, post_data)
224
225 self.mox.VerifyAll()
226 self.assertTrue('/components/detail?component=BackEnd&saved=1&' in url)
227 config = self.services.config.GetProjectConfig(
228 self.mr.cnxn, self.mr.project_id)
229
230 cd = tracker_bizobj.FindComponentDef('BackEnd', config)
231 self.assertEqual('BackEnd', cd.path)
232 self.assertEqual(
233 'This is where the magic happens',
234 cd.docstring)
235 self.assertEqual(True, cd.deprecated)
236 self.assertEqual([111], cd.admin_ids)
237 self.assertEqual([111], cd.cc_ids)
238
239 def testProcessDeleteComponent(self):
240 self.servlet._ProcessDeleteComponent(self.mr, self.cd)
241 self.assertIsNone(
242 tracker_bizobj.FindComponentDef('BackEnd', self.config))
243
244 def testProcessEditComponent(self):
245 post_data = fake.PostData(
246 leaf_name=['BackEnd'],
247 docstring=['This is where the magic happens'],
248 deprecated=[True],
249 admins=['a@example.com'],
250 cc=['a@example.com'],
251 labels=['Hot, Cold'])
252
253 self.servlet._ProcessEditComponent(
254 self.mr, post_data, self.config, self.cd)
255
256 self.mox.VerifyAll()
257 config = self.services.config.GetProjectConfig(
258 self.mr.cnxn, self.mr.project_id)
259 cd = tracker_bizobj.FindComponentDef('BackEnd', config)
260 self.assertEqual('BackEnd', cd.path)
261 self.assertEqual(
262 'This is where the magic happens',
263 cd.docstring)
264 self.assertEqual(True, cd.deprecated)
265 self.assertEqual([111], cd.admin_ids)
266 self.assertEqual([111], cd.cc_ids)
267 # Assert that creator and created were not updated.
268 self.assertEqual(122, cd.creator_id)
269 self.assertEqual(100000, cd.created)
270 # Assert that modifier and modified were updated.
271 self.assertEqual(122, cd.modifier_id)
272 self.assertTrue(cd.modified > 10000000)
273
274 def testProcessEditComponent_RenameWithSubComponents(self):
275 subcd_1 = tracker_bizobj.MakeComponentDef(
276 2, self.project.project_id, 'BackEnd>Worker1', 'doc', False, [], [111],
277 0, 125, 3, 126)
278 subcd_2 = tracker_bizobj.MakeComponentDef(
279 3, self.project.project_id, 'BackEnd>Worker2', 'doc', False, [], [111],
280 0, 125, 4, 127)
281 self.config.component_defs.extend([subcd_1, subcd_2])
282
283 self.mox.StubOutWithMock(filterrules_helpers, 'RecomputeAllDerivedFields')
284 filterrules_helpers.RecomputeAllDerivedFields(
285 self.mr.cnxn, self.services, self.mr.project, self.config)
286 self.mox.ReplayAll()
287 post_data = fake.PostData(
288 leaf_name=['BackEnds'],
289 docstring=['This is where the magic happens'],
290 deprecated=[True],
291 admins=['a@example.com'],
292 cc=['a@example.com'],
293 labels=[''])
294
295 self.servlet._ProcessEditComponent(
296 self.mr, post_data, self.config, self.cd)
297
298 self.mox.VerifyAll()
299 config = self.services.config.GetProjectConfig(
300 self.mr.cnxn, self.mr.project_id)
301 cd = tracker_bizobj.FindComponentDef('BackEnds', config)
302 self.assertEqual('BackEnds', cd.path)
303 subcd_1 = tracker_bizobj.FindComponentDef('BackEnds>Worker1', config)
304 self.assertEqual('BackEnds>Worker1', subcd_1.path)
305 # Assert that creator and modifier have not changed for subcd_1.
306 self.assertEqual(125, subcd_1.creator_id)
307 self.assertEqual(0, subcd_1.created)
308 self.assertEqual(126, subcd_1.modifier_id)
309 self.assertEqual(3, subcd_1.modified)
310
311 subcd_2 = tracker_bizobj.FindComponentDef('BackEnds>Worker2', config)
312 self.assertEqual('BackEnds>Worker2', subcd_2.path)
313 # Assert that creator and modifier have not changed for subcd_2.
314 self.assertEqual(125, subcd_2.creator_id)
315 self.assertEqual(0, subcd_2.created)
316 self.assertEqual(127, subcd_2.modifier_id)
317 self.assertEqual(4, subcd_2.modified)