blob: 5fc97296f49b4f8c229dd5d5bfd34c576072c09d [file] [log] [blame]
Adrià Vilanova Martínezf19ea432024-01-23 20:20:52 +01001# Copyright 2020 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"""Tests for the hotlists servicer."""
5from __future__ import print_function
6from __future__ import division
7from __future__ import absolute_import
8
9import unittest
10
11from google.protobuf import timestamp_pb2
12from mock import patch
13
14from api import resource_name_converters as rnc
15from api.v3 import converters
16from api.v3 import frontend_servicer
17from api.v3.api_proto import frontend_pb2
18from api.v3.api_proto import project_objects_pb2
19from framework import exceptions
20from framework import monorailcontext
Adrià Vilanova Martínezf19ea432024-01-23 20:20:52 +010021from mrproto import tracker_pb2
Copybara854996b2021-09-07 19:36:02 +000022from services import service_manager
23from testing import fake
24from tracker import tracker_constants
25
26
27class FrontendServicerTest(unittest.TestCase):
28
29 def setUp(self):
30 self.cnxn = fake.MonorailConnection()
31 self.services = service_manager.Services(
32 features=fake.FeaturesService(),
33 issue=fake.IssueService(),
34 project=fake.ProjectService(),
35 config=fake.ConfigService(),
36 user=fake.UserService(),
37 template=fake.TemplateService(),
38 usergroup=fake.UserGroupService())
39 self.frontend_svcr = frontend_servicer.FrontendServicer(
40 self.services, make_rate_limiter=False)
41
42 self.user_1 = self.services.user.TestAddUser('user_111@example.com', 111)
43 self.user_1_resource_name = 'users/111'
44 self.project_1_resource_name = 'projects/proj'
45 self.project_1 = self.services.project.TestAddProject(
46 'proj', project_id=789)
47 self.template_0 = self.services.template.TestAddIssueTemplateDef(
48 11110, self.project_1.project_id, 'template0')
49 self.PAST_TIME = 12345
50 self.component_def_1_path = 'foo'
51 self.component_def_1_id = self.services.config.CreateComponentDef(
52 self.cnxn, self.project_1.project_id, self.component_def_1_path,
53 'cd1_docstring', False, [self.user_1.user_id], [], self.PAST_TIME,
54 self.user_1.user_id, [])
55 self.field_def_1_name = 'test_field_1'
56 self.field_def_1 = self._CreateFieldDef(
57 self.project_1.project_id,
58 self.field_def_1_name,
59 'STR_TYPE',
60 admin_ids=[self.user_1.user_id],
61 is_required=True,
62 is_multivalued=True,
63 is_phase_field=True,
64 regex='abc')
65 self.approval_def_1_name = 'approval_field_1'
66 self.approval_def_1_id = self._CreateFieldDef(
67 self.project_1.project_id,
68 self.approval_def_1_name,
69 'APPROVAL_TYPE',
70 docstring='ad_1_docstring',
71 admin_ids=[self.user_1.user_id])
72 self.approval_def_1 = tracker_pb2.ApprovalDef(
73 approval_id=self.approval_def_1_id,
74 approver_ids=[self.user_1.user_id],
75 survey='approval_def_1 survey')
76 self.services.config.UpdateConfig(
77 self.cnxn,
78 self.project_1,
79 # UpdateConfig accepts tuples rather than protorpc *Defs
80 approval_defs=[
81 (ad.approval_id, ad.approver_ids, ad.survey)
82 for ad in [self.approval_def_1]
83 ])
84
85 def _CreateFieldDef(
86 self,
87 project_id,
88 field_name,
89 field_type_str,
90 docstring=None,
91 min_value=None,
92 max_value=None,
93 regex=None,
94 needs_member=None,
95 needs_perm=None,
96 grants_perm=None,
97 notify_on=None,
98 date_action_str=None,
99 admin_ids=None,
100 editor_ids=None,
101 is_required=False,
102 is_niche=False,
103 is_multivalued=False,
104 is_phase_field=False,
105 approval_id=None,
106 is_restricted_field=False):
107 """Calls CreateFieldDef with reasonable defaults, returns the ID."""
108 if admin_ids is None:
109 admin_ids = []
110 if editor_ids is None:
111 editor_ids = []
112 return self.services.config.CreateFieldDef(
113 self.cnxn,
114 project_id,
115 field_name,
116 field_type_str,
117 None,
118 None,
119 is_required,
120 is_niche,
121 is_multivalued,
122 min_value,
123 max_value,
124 regex,
125 needs_member,
126 needs_perm,
127 grants_perm,
128 notify_on,
129 date_action_str,
130 docstring,
131 admin_ids,
132 editor_ids,
133 is_phase_field=is_phase_field,
134 approval_id=approval_id,
135 is_restricted_field=is_restricted_field)
136
137 def CallWrapped(self, wrapped_handler, mc, *args, **kwargs):
138 self.frontend_svcr.converter = converters.Converter(mc, self.services)
139 return wrapped_handler.wrapped(self.frontend_svcr, mc, *args, **kwargs)
140
141 @patch('project.project_helpers.GetThumbnailUrl')
142 def testGatherProjectEnvironment(self, mock_GetThumbnailUrl):
143 """We can fetch all project related parameters for web frontend."""
144 mock_GetThumbnailUrl.return_value = 'xyz'
145
146 request = frontend_pb2.GatherProjectEnvironmentRequest(
147 parent=self.project_1_resource_name)
148 mc = monorailcontext.MonorailContext(
149 self.services, cnxn=self.cnxn, requester=self.user_1.email)
150 response = self.CallWrapped(
151 self.frontend_svcr.GatherProjectEnvironment, mc, request)
152 project_config = self.services.config.GetProjectConfig(
153 self.cnxn, self.project_1.project_id)
154
155 self.assertEqual(
156 response.project,
157 self.frontend_svcr.converter.ConvertProject(self.project_1))
158 self.assertEqual(
159 response.project_config,
160 self.frontend_svcr.converter.ConvertProjectConfig(project_config))
161
162 self.assertEqual(
163 len(response.statuses),
164 len(tracker_constants.DEFAULT_WELL_KNOWN_STATUSES))
165 self.assertEqual(
166 response.statuses[0],
167 project_objects_pb2.StatusDef(
168 name='projects/{project_name}/statusDefs/{status}'.format(
169 project_name=self.project_1.project_name,
170 status=tracker_constants.DEFAULT_WELL_KNOWN_STATUSES[0][0]),
171 value=tracker_constants.DEFAULT_WELL_KNOWN_STATUSES[0][0],
172 type=project_objects_pb2.StatusDef.StatusDefType.Value('OPEN'),
173 rank=0,
174 docstring=tracker_constants.DEFAULT_WELL_KNOWN_STATUSES[0][1],
175 state=project_objects_pb2.StatusDef.StatusDefState.Value('ACTIVE'),
176 ))
177
178 self.assertEqual(
179 len(response.well_known_labels),
180 len(tracker_constants.DEFAULT_WELL_KNOWN_LABELS))
181 self.assertEqual(
182 response.well_known_labels[0],
183 project_objects_pb2.LabelDef(
184 name='projects/{project_name}/labelDefs/{label}'.format(
185 project_name=self.project_1.project_name,
186 label=tracker_constants.DEFAULT_WELL_KNOWN_LABELS[0][0]),
187 value=tracker_constants.DEFAULT_WELL_KNOWN_LABELS[0][0],
188 docstring=tracker_constants.DEFAULT_WELL_KNOWN_LABELS[0][1],
189 state=project_objects_pb2.LabelDef.LabelDefState.Value('ACTIVE'),
190 ))
191
192 expected = self.frontend_svcr.converter.ConvertComponentDefs(
193 project_config.component_defs, self.project_1.project_id)
194 # Have to use list comprehension to break response sub field into list
195 self.assertEqual([api_cd for api_cd in response.components], expected)
196
197 expected = self.frontend_svcr.converter.ConvertFieldDefs(
198 project_config.field_defs, self.project_1.project_id)
199 self.assertEqual([api_fd for api_fd in response.fields], expected)
200
201 expected = self.frontend_svcr.converter.ConvertApprovalDefs(
202 project_config.approval_defs, self.project_1.project_id)
203 self.assertEqual([api_ad for api_ad in response.approval_fields], expected)
204
205 def testGatherProjectMembershipsForUser(self):
206 """We can list a user's project memberships."""
207 self.services.project.TestAddProject(
208 'owner_proj', project_id=777, owner_ids=[111])
209 self.services.project.TestAddProject(
210 'committer_proj', project_id=888, committer_ids=[111])
Adrià Vilanova Martínezf19ea432024-01-23 20:20:52 +0100211 self.services.project.TestAddProject(
212 'contributor_proj', project_id=999, contrib_ids=[111])
Copybara854996b2021-09-07 19:36:02 +0000213
214 request = frontend_pb2.GatherProjectMembershipsForUserRequest(
215 user=self.user_1_resource_name)
216 mc = monorailcontext.MonorailContext(
217 self.services, cnxn=self.cnxn, requester=self.user_1.email)
218 response = self.CallWrapped(
219 self.frontend_svcr.GatherProjectMembershipsForUser, mc, request)
220
221 owner_membership = project_objects_pb2.ProjectMember(
222 name='projects/{}/members/{}'.format('owner_proj', '111'),
223 role=project_objects_pb2.ProjectMember.ProjectRole.Value('OWNER'))
224 committer_membership = project_objects_pb2.ProjectMember(
225 name='projects/{}/members/{}'.format('committer_proj', '111'),
226 role=project_objects_pb2.ProjectMember.ProjectRole.Value('COMMITTER'))
227 contributor_membership = project_objects_pb2.ProjectMember(
228 name='projects/{}/members/{}'.format('contributor_proj', '111'),
229 role=project_objects_pb2.ProjectMember.ProjectRole.Value('CONTRIBUTOR'))
230 self.assertEqual(
231 response,
232 frontend_pb2.GatherProjectMembershipsForUserResponse(
233 project_memberships=[
234 owner_membership, committer_membership, contributor_membership
235 ]))