blob: fe3d22f9b4415e511112e8d2713314d7461d8e74 [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"""Unittests for monorail.tracker.issuedetailezt."""
7from __future__ import print_function
8from __future__ import division
9from __future__ import absolute_import
10
11import logging
12import mock
Adrià Vilanova Martínez9f9ade52022-10-10 23:20:11 +020013try:
14 from mox3 import mox
15except ImportError:
16 import mox
Copybara854996b2021-09-07 19:36:02 +000017import time
18import unittest
19
20import settings
21from businesslogic import work_env
22from proto import features_pb2
23from features import hotlist_views
24from features import send_notifications
25from framework import authdata
26from framework import exceptions
27from framework import framework_views
28from framework import framework_helpers
29from framework import urls
30from framework import permissions
31from framework import profiler
32from framework import sorting
33from framework import template_helpers
34from proto import project_pb2
35from proto import tracker_pb2
36from proto import user_pb2
37from services import service_manager
38from services import issue_svc
39from services import tracker_fulltext
40from testing import fake
41from testing import testing_helpers
42from tracker import issuedetailezt
43from tracker import tracker_constants
44from tracker import tracker_helpers
45
46
47class GetAdjacentIssueTest(unittest.TestCase):
48
49 def setUp(self):
50 self.cnxn = 'fake cnxn'
51 self.services = service_manager.Services(
52 config=fake.ConfigService(),
53 issue=fake.IssueService(),
54 user=fake.UserService(),
55 project=fake.ProjectService(),
56 issue_star=fake.IssueStarService(),
57 spam=fake.SpamService())
58 self.services.project.TestAddProject('proj', project_id=789)
59 self.mr = testing_helpers.MakeMonorailRequest()
60 self.mr.auth.user_id = 111
61 self.mr.auth.effective_ids = {111}
62 self.mr.me_user_id = 111
63 self.work_env = work_env.WorkEnv(
64 self.mr, self.services, 'Testing phase')
65
66 def testGetAdjacentIssue_PrevIssue(self):
67 cur_issue = fake.MakeTestIssue(789, 2, 'sum', 'New', 111, issue_id=78902)
68 next_issue = fake.MakeTestIssue(789, 3, 'sum', 'New', 111, issue_id=78903)
69 prev_issue = fake.MakeTestIssue(789, 1, 'sum', 'New', 111, issue_id=78901)
70 self.services.issue.TestAddIssue(cur_issue)
71 self.services.issue.TestAddIssue(next_issue)
72 self.services.issue.TestAddIssue(prev_issue)
73
74 with self.work_env as we:
75 we.FindIssuePositionInSearch = mock.Mock(
76 return_value=[78901, 1, 78903, 3])
77
78 actual_issue = issuedetailezt.GetAdjacentIssue(
79 self.mr, we, cur_issue)
80 self.assertEqual(prev_issue, actual_issue)
81 we.FindIssuePositionInSearch.assert_called_once_with(cur_issue)
82
83 def testGetAdjacentIssue_NextIssue(self):
84 cur_issue = fake.MakeTestIssue(789, 2, 'sum', 'New', 111, issue_id=78902)
85 next_issue = fake.MakeTestIssue(789, 3, 'sum', 'New', 111, issue_id=78903)
86 prev_issue = fake.MakeTestIssue(789, 1, 'sum', 'New', 111, issue_id=78901)
87 self.services.issue.TestAddIssue(cur_issue)
88 self.services.issue.TestAddIssue(next_issue)
89 self.services.issue.TestAddIssue(prev_issue)
90
91 with self.work_env as we:
92 we.FindIssuePositionInSearch = mock.Mock(
93 return_value=[78901, 1, 78903, 3])
94
95 actual_issue = issuedetailezt.GetAdjacentIssue(
96 self.mr, we, cur_issue, next_issue=True)
97 self.assertEqual(next_issue, actual_issue)
98 we.FindIssuePositionInSearch.assert_called_once_with(cur_issue)
99
100 def testGetAdjacentIssue_NotFound(self):
101 cur_issue = fake.MakeTestIssue(789, 2, 'sum', 'New', 111, issue_id=78902)
102 prev_issue = fake.MakeTestIssue(789, 1, 'sum', 'New', 111, issue_id=78901)
103 self.services.issue.TestAddIssue(cur_issue)
104 self.services.issue.TestAddIssue(prev_issue)
105
106 with self.work_env as we:
107 we.FindIssuePositionInSearch = mock.Mock(
108 return_value=[78901, 1, 78903, 3])
109
110 with self.assertRaises(exceptions.NoSuchIssueException):
111 issuedetailezt.GetAdjacentIssue(
112 self.mr, we, cur_issue, next_issue=True)
113 we.FindIssuePositionInSearch.assert_called_once_with(cur_issue)
114
115 def testGetAdjacentIssue_Hotlist(self):
116 cur_issue = fake.MakeTestIssue(789, 2, 'sum', 'New', 111, issue_id=78902)
117 next_issue = fake.MakeTestIssue(789, 3, 'sum', 'New', 111, issue_id=78903)
118 prev_issue = fake.MakeTestIssue(789, 1, 'sum', 'New', 111, issue_id=78901)
119 self.services.issue.TestAddIssue(cur_issue)
120 self.services.issue.TestAddIssue(next_issue)
121 self.services.issue.TestAddIssue(prev_issue)
122 hotlist = fake.Hotlist('name', 678, owner_ids=[111])
123
124 with self.work_env as we:
125 we.GetIssuePositionInHotlist = mock.Mock(
126 return_value=[78901, 1, 78903, 3])
127
128 actual_issue = issuedetailezt.GetAdjacentIssue(
129 self.mr, we, cur_issue, hotlist=hotlist, next_issue=True)
130 self.assertEqual(next_issue, actual_issue)
131 we.GetIssuePositionInHotlist.assert_called_once_with(
132 cur_issue, hotlist, self.mr.can, self.mr.sort_spec,
133 self.mr.group_by_spec)
134
135
136class FlipperRedirectTest(unittest.TestCase):
137
138 def setUp(self):
139 self.services = service_manager.Services(
140 config=fake.ConfigService(),
141 features=fake.FeaturesService(),
142 issue=fake.IssueService(),
143 user=fake.UserService(),
144 project=fake.ProjectService())
145 self.project = self.services.project.TestAddProject(
146 'proj', project_id=987, committer_ids=[111])
147 self.next_servlet = issuedetailezt.FlipperNext(
148 'req', 'res', services=self.services)
149 self.prev_servlet = issuedetailezt.FlipperPrev(
150 'req', 'res', services=self.services)
151 self.list_servlet = issuedetailezt.FlipperList(
152 'req', 'res', services=self.services)
153 mr = testing_helpers.MakeMonorailRequest(project=self.project)
154 mr.local_id = 123
155 mr.me_user_id = 111
156
157 self.next_servlet.mr = mr
158 self.prev_servlet.mr = mr
159 self.list_servlet.mr = mr
160
161 self.fake_issue_1 = fake.MakeTestIssue(987, 123, 'summary', 'New', 111,
162 project_name='rutabaga')
163 self.services.issue.TestAddIssue(self.fake_issue_1)
164 self.fake_issue_2 = fake.MakeTestIssue(987, 456, 'summary', 'New', 111,
165 project_name='rutabaga')
166 self.services.issue.TestAddIssue(self.fake_issue_2)
167 self.fake_issue_3 = fake.MakeTestIssue(987, 789, 'summary', 'New', 111,
168 project_name='potato')
169 self.services.issue.TestAddIssue(self.fake_issue_3)
170
171 self.next_servlet.redirect = mock.Mock()
172 self.prev_servlet.redirect = mock.Mock()
173 self.list_servlet.redirect = mock.Mock()
174
175 @mock.patch('tracker.issuedetailezt.GetAdjacentIssue')
176 def testFlipperNext(self, patchGetAdjacentIssue):
177 patchGetAdjacentIssue.return_value = self.fake_issue_2
178 self.next_servlet.mr.GetIntParam = mock.Mock(return_value=None)
179
180 self.next_servlet.get(project_name='proj', viewed_username=None)
181 self.next_servlet.mr.GetIntParam.assert_called_once_with('hotlist_id')
182 patchGetAdjacentIssue.assert_called_once()
183 self.next_servlet.redirect.assert_called_once_with(
184 '/p/rutabaga/issues/detail?id=456')
185
186 @mock.patch('tracker.issuedetailezt.GetAdjacentIssue')
187 def testFlipperNext_Hotlist(self, patchGetAdjacentIssue):
188 patchGetAdjacentIssue.return_value = self.fake_issue_3
189 self.next_servlet.mr.GetIntParam = mock.Mock(return_value=123)
190 # TODO(jeffcarp): Mock hotlist_id param on path here.
191
192 self.next_servlet.get(project_name='proj', viewed_username=None)
193 self.next_servlet.mr.GetIntParam.assert_called_with('hotlist_id')
194 self.next_servlet.redirect.assert_called_once_with(
195 '/p/potato/issues/detail?id=789')
196
197 @mock.patch('tracker.issuedetailezt.GetAdjacentIssue')
198 def testFlipperPrev(self, patchGetAdjacentIssue):
199 patchGetAdjacentIssue.return_value = self.fake_issue_2
200 self.next_servlet.mr.GetIntParam = mock.Mock(return_value=None)
201
202 self.prev_servlet.get(project_name='proj', viewed_username=None)
203 self.prev_servlet.mr.GetIntParam.assert_called_with('hotlist_id')
204 patchGetAdjacentIssue.assert_called_once()
205 self.prev_servlet.redirect.assert_called_once_with(
206 '/p/rutabaga/issues/detail?id=456')
207
208 @mock.patch('tracker.issuedetailezt.GetAdjacentIssue')
209 def testFlipperPrev_Hotlist(self, patchGetAdjacentIssue):
210 patchGetAdjacentIssue.return_value = self.fake_issue_3
211 self.prev_servlet.mr.GetIntParam = mock.Mock(return_value=123)
212 # TODO(jeffcarp): Mock hotlist_id param on path here.
213
214 self.prev_servlet.get(project_name='proj', viewed_username=None)
215 self.prev_servlet.mr.GetIntParam.assert_called_with('hotlist_id')
216 self.prev_servlet.redirect.assert_called_once_with(
217 '/p/potato/issues/detail?id=789')
218
219 @mock.patch('tracker.issuedetailezt._ComputeBackToListURL')
220 def testFlipperList(self, patch_ComputeBackToListURL):
221 patch_ComputeBackToListURL.return_value = '/p/test/issues/list'
222 self.list_servlet.mr.GetIntParam = mock.Mock(return_value=None)
223
224 self.list_servlet.get()
225
226 self.list_servlet.mr.GetIntParam.assert_called_with('hotlist_id')
227 patch_ComputeBackToListURL.assert_called_once()
228 self.list_servlet.redirect.assert_called_once_with(
229 '/p/test/issues/list')
230
231 @mock.patch('tracker.issuedetailezt._ComputeBackToListURL')
232 def testFlipperList_Hotlist(self, patch_ComputeBackToListURL):
233 patch_ComputeBackToListURL.return_value = '/p/test/issues/list'
234 self.list_servlet.mr.GetIntParam = mock.Mock(return_value=123)
235
236 self.list_servlet.get()
237
238 self.list_servlet.mr.GetIntParam.assert_called_with('hotlist_id')
239 self.list_servlet.redirect.assert_called_once_with(
240 '/p/test/issues/list')
241
242
243class ShouldShowFlipperTest(unittest.TestCase):
244
245 def setUp(self):
246 self.cnxn = 'fake cnxn'
247
248 def VerifyShouldShowFlipper(
249 self, expected, query, sort_spec, can, create_issues=0):
250 """Instantiate a _Flipper and check if makes a pipeline or not."""
251 services = service_manager.Services(
252 config=fake.ConfigService(),
253 issue=fake.IssueService(),
254 project=fake.ProjectService(),
255 user=fake.UserService())
256 project = services.project.TestAddProject(
257 'proj', project_id=987, committer_ids=[111])
258 mr = testing_helpers.MakeMonorailRequest(project=project)
259 mr.query = query
260 mr.sort_spec = sort_spec
261 mr.can = can
262 mr.project_name = project.project_name
263 mr.project = project
264
265 for idx in range(create_issues):
266 _created_issue = fake.MakeTestIssue(
267 project.project_id,
268 idx,
269 'summary_%d' % idx,
270 'status',
271 111,
272 reporter_id=111)
273 services.issue.TestAddIssue(_created_issue)
274
275 self.assertEqual(expected, issuedetailezt._ShouldShowFlipper(mr, services))
276
277 def testShouldShowFlipper_RegularSizedProject(self):
278 # If the user is looking for a specific issue, no flipper.
279 self.VerifyShouldShowFlipper(
280 False, '123', '', tracker_constants.OPEN_ISSUES_CAN)
281 self.VerifyShouldShowFlipper(False, '123', '', 5)
282 self.VerifyShouldShowFlipper(
283 False, '123', 'priority', tracker_constants.OPEN_ISSUES_CAN)
284
285 # If the user did a search or sort or all in a small can, show flipper.
286 self.VerifyShouldShowFlipper(
287 True, 'memory leak', '', tracker_constants.OPEN_ISSUES_CAN)
288 self.VerifyShouldShowFlipper(
289 True, 'id=1,2,3', '', tracker_constants.OPEN_ISSUES_CAN)
290 # Any can other than 1 or 2 is doing a query and so it should have a
291 # failry narrow result set size. 5 is issues starred by me.
292 self.VerifyShouldShowFlipper(True, '', '', 5)
293 self.VerifyShouldShowFlipper(
294 True, '', 'status', tracker_constants.OPEN_ISSUES_CAN)
295
296 # In a project without a huge number of issues, still show the flipper even
297 # if there was no specific query.
298 self.VerifyShouldShowFlipper(
299 True, '', '', tracker_constants.OPEN_ISSUES_CAN)
300
301 def testShouldShowFlipper_LargeSizedProject(self):
302 settings.threshold_to_suppress_prev_next = 1
303
304 # In a project that has tons of issues, save time by not showing the
305 # flipper unless there was a specific query, sort, or can.
306 self.VerifyShouldShowFlipper(
307 False, '', '', tracker_constants.ALL_ISSUES_CAN, create_issues=3)
308 self.VerifyShouldShowFlipper(
309 False, '', '', tracker_constants.OPEN_ISSUES_CAN, create_issues=3)