OLD | NEW |
(Empty) | |
| 1 # Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is govered 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 """Unittest for the tracker helpers module.""" |
| 7 |
| 8 import unittest |
| 9 |
| 10 import settings |
| 11 |
| 12 from framework import framework_constants |
| 13 from framework import framework_helpers |
| 14 from framework import permissions |
| 15 from framework import template_helpers |
| 16 from framework import urls |
| 17 from proto import project_pb2 |
| 18 from proto import tracker_pb2 |
| 19 from proto import user_pb2 |
| 20 from services import service_manager |
| 21 from testing import fake |
| 22 from testing import testing_helpers |
| 23 from tracker import tracker_bizobj |
| 24 from tracker import tracker_constants |
| 25 from tracker import tracker_helpers |
| 26 |
| 27 TEST_ID_MAP = { |
| 28 'a@example.com': 1, |
| 29 'b@example.com': 2, |
| 30 'c@example.com': 3, |
| 31 'd@example.com': 4, |
| 32 } |
| 33 |
| 34 |
| 35 def _Issue(project_name, local_id, summary, status): |
| 36 issue = tracker_pb2.Issue() |
| 37 issue.project_name = project_name |
| 38 issue.project_id = 789 |
| 39 issue.local_id = local_id |
| 40 issue.issue_id = 100000 + local_id |
| 41 issue.summary = summary |
| 42 issue.status = status |
| 43 return issue |
| 44 |
| 45 |
| 46 def _MakeConfig(): |
| 47 config = tracker_pb2.ProjectIssueConfig() |
| 48 config.well_known_statuses.append(tracker_pb2.StatusDef( |
| 49 means_open=True, status='New', deprecated=False)) |
| 50 config.well_known_statuses.append(tracker_pb2.StatusDef( |
| 51 status='Old', means_open=False, deprecated=False)) |
| 52 config.well_known_statuses.append(tracker_pb2.StatusDef( |
| 53 status='StatusThatWeDontUseAnymore', means_open=False, deprecated=True)) |
| 54 |
| 55 return config |
| 56 |
| 57 |
| 58 class HelpersTest(unittest.TestCase): |
| 59 |
| 60 def setUp(self): |
| 61 self.services = service_manager.Services( |
| 62 project=fake.ProjectService(), |
| 63 config=fake.ConfigService(), |
| 64 issue=fake.IssueService(), |
| 65 user=fake.UserService(), |
| 66 usergroup=fake.UserGroupService()) |
| 67 |
| 68 for email, user_id in TEST_ID_MAP.iteritems(): |
| 69 self.services.user.TestAddUser(email, user_id) |
| 70 |
| 71 self.services.project.TestAddProject('testproj', project_id=789) |
| 72 self.issue1 = fake.MakeTestIssue(789, 1, 'one', 'New', 111L) |
| 73 self.issue1.project_name = 'testproj' |
| 74 self.services.issue.TestAddIssue(self.issue1) |
| 75 self.issue2 = fake.MakeTestIssue(789, 2, 'two', 'New', 111L) |
| 76 self.issue2.project_name = 'testproj' |
| 77 self.services.issue.TestAddIssue(self.issue2) |
| 78 self.issue3 = fake.MakeTestIssue(789, 3, 'three', 'New', 111L) |
| 79 self.issue3.project_name = 'testproj' |
| 80 self.services.issue.TestAddIssue(self.issue3) |
| 81 self.cnxn = 'fake connextion' |
| 82 self.errors = template_helpers.EZTError() |
| 83 self.default_colspec_param = 'colspec=%s' % ( |
| 84 tracker_constants.DEFAULT_COL_SPEC.replace(' ', '%20')) |
| 85 self.services.usergroup.TestAddGroupSettings(999L, 'group@example.com') |
| 86 |
| 87 def testParseIssueRequest_Empty(self): |
| 88 post_data = fake.PostData() |
| 89 errors = template_helpers.EZTError() |
| 90 parsed = tracker_helpers.ParseIssueRequest( |
| 91 'fake cnxn', post_data, self.services, errors, 'proj') |
| 92 self.assertEqual('', parsed.summary) |
| 93 self.assertEqual('', parsed.comment) |
| 94 self.assertEqual('', parsed.status) |
| 95 self.assertEqual('', parsed.users.owner_username) |
| 96 self.assertEqual(0, parsed.users.owner_id) |
| 97 self.assertEqual([], parsed.users.cc_usernames) |
| 98 self.assertEqual([], parsed.users.cc_usernames_remove) |
| 99 self.assertEqual([], parsed.users.cc_ids) |
| 100 self.assertEqual([], parsed.users.cc_ids_remove) |
| 101 self.assertEqual('', parsed.template_name) |
| 102 self.assertEqual([], parsed.labels) |
| 103 self.assertEqual([], parsed.labels_remove) |
| 104 self.assertEqual({}, parsed.fields.vals) |
| 105 self.assertEqual({}, parsed.fields.vals_remove) |
| 106 self.assertEqual([], parsed.fields.fields_clear) |
| 107 self.assertEqual('', parsed.blocked_on.entered_str) |
| 108 self.assertEqual([], parsed.blocked_on.iids) |
| 109 |
| 110 def testParseIssueRequest_Normal(self): |
| 111 post_data = fake.PostData({ |
| 112 'summary': ['some summary'], |
| 113 'comment': ['some comment'], |
| 114 'status': ['SomeStatus'], |
| 115 'template_name': ['some template'], |
| 116 'label': ['lab1', '-lab2'], |
| 117 'custom_123': ['field1123a', 'field1123b'], |
| 118 }) |
| 119 errors = template_helpers.EZTError() |
| 120 parsed = tracker_helpers.ParseIssueRequest( |
| 121 'fake cnxn', post_data, self.services, errors, 'proj') |
| 122 self.assertEqual('some summary', parsed.summary) |
| 123 self.assertEqual('some comment', parsed.comment) |
| 124 self.assertEqual('SomeStatus', parsed.status) |
| 125 self.assertEqual('', parsed.users.owner_username) |
| 126 self.assertEqual(0, parsed.users.owner_id) |
| 127 self.assertEqual([], parsed.users.cc_usernames) |
| 128 self.assertEqual([], parsed.users.cc_usernames_remove) |
| 129 self.assertEqual([], parsed.users.cc_ids) |
| 130 self.assertEqual([], parsed.users.cc_ids_remove) |
| 131 self.assertEqual('some template', parsed.template_name) |
| 132 self.assertEqual(['lab1'], parsed.labels) |
| 133 self.assertEqual(['lab2'], parsed.labels_remove) |
| 134 self.assertEqual({123: ['field1123a', 'field1123b']}, parsed.fields.vals) |
| 135 self.assertEqual({}, parsed.fields.vals_remove) |
| 136 self.assertEqual([], parsed.fields.fields_clear) |
| 137 |
| 138 def testParseBlockers_BlockedOnNothing(self): |
| 139 """Was blocked on nothing, still nothing.""" |
| 140 post_data = {tracker_helpers.BLOCKED_ON: ''} |
| 141 parsed_blockers = tracker_helpers._ParseBlockers( |
| 142 self.cnxn, post_data, self.services, self.errors, 'testproj', |
| 143 tracker_helpers.BLOCKED_ON) |
| 144 |
| 145 self.assertEqual('', parsed_blockers.entered_str) |
| 146 self.assertEqual([], parsed_blockers.iids) |
| 147 self.assertIsNone(getattr(self.errors, tracker_helpers.BLOCKED_ON)) |
| 148 self.assertIsNone(getattr(self.errors, tracker_helpers.BLOCKING)) |
| 149 |
| 150 def testParseBlockers_BlockedOnAdded(self): |
| 151 """Was blocked on nothing; now 1, 2, 3.""" |
| 152 post_data = {tracker_helpers.BLOCKED_ON: '1, 2, 3'} |
| 153 parsed_blockers = tracker_helpers._ParseBlockers( |
| 154 self.cnxn, post_data, self.services, self.errors, 'testproj', |
| 155 tracker_helpers.BLOCKED_ON) |
| 156 |
| 157 self.assertEqual('1, 2, 3', parsed_blockers.entered_str) |
| 158 self.assertEqual([100001, 100002, 100003], parsed_blockers.iids) |
| 159 self.assertIsNone(getattr(self.errors, tracker_helpers.BLOCKED_ON)) |
| 160 self.assertIsNone(getattr(self.errors, tracker_helpers.BLOCKING)) |
| 161 |
| 162 def testParseBlockers_BlockedOnDuplicateRef(self): |
| 163 """Was blocked on nothing; now just 2, but repeated in input.""" |
| 164 post_data = {tracker_helpers.BLOCKED_ON: '2, 2, 2'} |
| 165 parsed_blockers = tracker_helpers._ParseBlockers( |
| 166 self.cnxn, post_data, self.services, self.errors, 'testproj', |
| 167 tracker_helpers.BLOCKED_ON) |
| 168 |
| 169 self.assertEqual('2, 2, 2', parsed_blockers.entered_str) |
| 170 self.assertEqual([100002], parsed_blockers.iids) |
| 171 self.assertIsNone(getattr(self.errors, tracker_helpers.BLOCKED_ON)) |
| 172 self.assertIsNone(getattr(self.errors, tracker_helpers.BLOCKING)) |
| 173 |
| 174 def testParseBlockers_Missing(self): |
| 175 """Parsing an input field that was not in the POST.""" |
| 176 post_data = {} |
| 177 parsed_blockers = tracker_helpers._ParseBlockers( |
| 178 self.cnxn, post_data, self.services, self.errors, 'testproj', |
| 179 tracker_helpers.BLOCKED_ON) |
| 180 |
| 181 self.assertEqual('', parsed_blockers.entered_str) |
| 182 self.assertEqual([], parsed_blockers.iids) |
| 183 self.assertIsNone(getattr(self.errors, tracker_helpers.BLOCKED_ON)) |
| 184 self.assertIsNone(getattr(self.errors, tracker_helpers.BLOCKING)) |
| 185 |
| 186 def testParseBlockers_SameIssueNoProject(self): |
| 187 """Adding same issue as blocker should modify the errors object.""" |
| 188 post_data = {'id': '2', tracker_helpers.BLOCKING: '2, 3'} |
| 189 |
| 190 parsed_blockers = tracker_helpers._ParseBlockers( |
| 191 self.cnxn, post_data, self.services, self.errors, 'testproj', |
| 192 tracker_helpers.BLOCKING) |
| 193 self.assertEqual('2, 3', parsed_blockers.entered_str) |
| 194 self.assertEqual([], parsed_blockers.iids) |
| 195 self.assertEqual( |
| 196 getattr(self.errors, tracker_helpers.BLOCKING), |
| 197 'Cannot be blocking the same issue') |
| 198 self.assertIsNone(getattr(self.errors, tracker_helpers.BLOCKED_ON)) |
| 199 |
| 200 def testParseBlockers_SameIssueSameProject(self): |
| 201 """Adding same issue as blocker should modify the errors object.""" |
| 202 post_data = {'id': '2', tracker_helpers.BLOCKING: 'testproj:2, 3'} |
| 203 |
| 204 parsed_blockers = tracker_helpers._ParseBlockers( |
| 205 self.cnxn, post_data, self.services, self.errors, 'testproj', |
| 206 tracker_helpers.BLOCKING) |
| 207 self.assertEqual('testproj:2, 3', parsed_blockers.entered_str) |
| 208 self.assertEqual([], parsed_blockers.iids) |
| 209 self.assertEqual( |
| 210 getattr(self.errors, tracker_helpers.BLOCKING), |
| 211 'Cannot be blocking the same issue') |
| 212 self.assertIsNone(getattr(self.errors, tracker_helpers.BLOCKED_ON)) |
| 213 |
| 214 def testParseBlockers_SameIssueDifferentProject(self): |
| 215 """Adding different blocker issue should not modify the errors object.""" |
| 216 post_data = {'id': '2', tracker_helpers.BLOCKING: 'testproj:2'} |
| 217 |
| 218 parsed_blockers = tracker_helpers._ParseBlockers( |
| 219 self.cnxn, post_data, self.services, self.errors, 'testprojB', |
| 220 tracker_helpers.BLOCKING) |
| 221 self.assertEqual('testproj:2', parsed_blockers.entered_str) |
| 222 self.assertEqual([100002], parsed_blockers.iids) |
| 223 self.assertIsNone(getattr(self.errors, tracker_helpers.BLOCKING)) |
| 224 self.assertIsNone(getattr(self.errors, tracker_helpers.BLOCKED_ON)) |
| 225 |
| 226 def testParseBlockers_Invalid(self): |
| 227 """Input fields with invalid values should modify the errors object.""" |
| 228 post_data = {tracker_helpers.BLOCKING: '2, foo', |
| 229 tracker_helpers.BLOCKED_ON: '3, bar'} |
| 230 |
| 231 parsed_blockers = tracker_helpers._ParseBlockers( |
| 232 self.cnxn, post_data, self.services, self.errors, 'testproj', |
| 233 tracker_helpers.BLOCKING) |
| 234 self.assertEqual('2, foo', parsed_blockers.entered_str) |
| 235 self.assertEqual([100002], parsed_blockers.iids) |
| 236 self.assertEqual( |
| 237 getattr(self.errors, tracker_helpers.BLOCKING), 'Invalid issue ID foo') |
| 238 self.assertIsNone(getattr(self.errors, tracker_helpers.BLOCKED_ON)) |
| 239 |
| 240 parsed_blockers = tracker_helpers._ParseBlockers( |
| 241 self.cnxn, post_data, self.services, self.errors, 'testproj', |
| 242 tracker_helpers.BLOCKED_ON) |
| 243 self.assertEqual('3, bar', parsed_blockers.entered_str) |
| 244 self.assertEqual([100003], parsed_blockers.iids) |
| 245 self.assertEqual( |
| 246 getattr(self.errors, tracker_helpers.BLOCKED_ON), |
| 247 'Invalid issue ID bar') |
| 248 |
| 249 def testParseBlockers_Dangling(self): |
| 250 """A ref to a sanctioned projected should be allowed.""" |
| 251 post_data = {'id': '2', tracker_helpers.BLOCKING: 'otherproj:2'} |
| 252 real_codesite_projects = settings.recognized_codesite_projects |
| 253 settings.recognized_codesite_projects = ['otherproj'] |
| 254 parsed_blockers = tracker_helpers._ParseBlockers( |
| 255 self.cnxn, post_data, self.services, self.errors, 'testproj', |
| 256 tracker_helpers.BLOCKING) |
| 257 self.assertEqual('otherproj:2', parsed_blockers.entered_str) |
| 258 self.assertEqual([('otherproj', 2)], parsed_blockers.dangling_refs) |
| 259 settings.recognized_codesite_projects = real_codesite_projects |
| 260 |
| 261 def testMeansOpenInProject(self): |
| 262 config = _MakeConfig() |
| 263 |
| 264 # ensure open means open |
| 265 self.assertTrue(tracker_helpers.MeansOpenInProject('New', config)) |
| 266 self.assertTrue(tracker_helpers.MeansOpenInProject('new', config)) |
| 267 |
| 268 # ensure an unrecognized status means open |
| 269 self.assertTrue(tracker_helpers.MeansOpenInProject( |
| 270 '_undefined_status_', config)) |
| 271 |
| 272 # ensure closed means closed |
| 273 self.assertFalse(tracker_helpers.MeansOpenInProject('Old', config)) |
| 274 self.assertFalse(tracker_helpers.MeansOpenInProject('old', config)) |
| 275 self.assertFalse(tracker_helpers.MeansOpenInProject( |
| 276 'StatusThatWeDontUseAnymore', config)) |
| 277 |
| 278 def testIsNoisy(self): |
| 279 self.assertTrue(tracker_helpers.IsNoisy(778, 320)) |
| 280 self.assertFalse(tracker_helpers.IsNoisy(20, 500)) |
| 281 self.assertFalse(tracker_helpers.IsNoisy(500, 20)) |
| 282 self.assertFalse(tracker_helpers.IsNoisy(1, 1)) |
| 283 |
| 284 def testClassifyPlusMinusItems(self): |
| 285 add, remove = tracker_helpers._ClassifyPlusMinusItems([]) |
| 286 self.assertEquals([], add) |
| 287 self.assertEquals([], remove) |
| 288 |
| 289 add, remove = tracker_helpers._ClassifyPlusMinusItems( |
| 290 ['', ' ', ' \t', '-']) |
| 291 self.assertItemsEqual([], add) |
| 292 self.assertItemsEqual([], remove) |
| 293 |
| 294 add, remove = tracker_helpers._ClassifyPlusMinusItems( |
| 295 ['a', 'b', 'c']) |
| 296 self.assertItemsEqual(['a', 'b', 'c'], add) |
| 297 self.assertItemsEqual([], remove) |
| 298 |
| 299 add, remove = tracker_helpers._ClassifyPlusMinusItems( |
| 300 ['a-a-a', 'b-b', 'c-']) |
| 301 self.assertItemsEqual(['a-a-a', 'b-b', 'c-'], add) |
| 302 self.assertItemsEqual([], remove) |
| 303 |
| 304 add, remove = tracker_helpers._ClassifyPlusMinusItems( |
| 305 ['-a']) |
| 306 self.assertItemsEqual([], add) |
| 307 self.assertItemsEqual(['a'], remove) |
| 308 |
| 309 add, remove = tracker_helpers._ClassifyPlusMinusItems( |
| 310 ['-a', 'b', 'c-c']) |
| 311 self.assertItemsEqual(['b', 'c-c'], add) |
| 312 self.assertItemsEqual(['a'], remove) |
| 313 |
| 314 add, remove = tracker_helpers._ClassifyPlusMinusItems( |
| 315 ['-a', '-b-b', '-c-']) |
| 316 self.assertItemsEqual([], add) |
| 317 self.assertItemsEqual(['a', 'b-b', 'c-'], remove) |
| 318 |
| 319 # We dedup, but we don't cancel out items that are both added and removed. |
| 320 add, remove = tracker_helpers._ClassifyPlusMinusItems( |
| 321 ['a', 'a', '-a']) |
| 322 self.assertItemsEqual(['a'], add) |
| 323 self.assertItemsEqual(['a'], remove) |
| 324 |
| 325 def testParseIssueRequestAttachments(self): |
| 326 file1 = testing_helpers.Blank( |
| 327 filename='hello.c', |
| 328 value='hello world') |
| 329 |
| 330 file2 = testing_helpers.Blank( |
| 331 filename='README', |
| 332 value='Welcome to our project') |
| 333 |
| 334 file3 = testing_helpers.Blank( |
| 335 filename='c:\\dir\\subdir\\FILENAME.EXT', |
| 336 value='Abort, Retry, or Fail?') |
| 337 |
| 338 # Browsers send this if FILE field was not filled in. |
| 339 file4 = testing_helpers.Blank( |
| 340 filename='', |
| 341 value='') |
| 342 |
| 343 attachments = tracker_helpers._ParseIssueRequestAttachments({}) |
| 344 self.assertEquals([], attachments) |
| 345 |
| 346 attachments = tracker_helpers._ParseIssueRequestAttachments(fake.PostData({ |
| 347 'file1': [file1], |
| 348 })) |
| 349 self.assertEquals( |
| 350 [('hello.c', 'hello world', 'text/plain')], |
| 351 attachments) |
| 352 |
| 353 attachments = tracker_helpers._ParseIssueRequestAttachments(fake.PostData({ |
| 354 'file1': [file1], |
| 355 'file2': [file2], |
| 356 })) |
| 357 self.assertEquals( |
| 358 [('hello.c', 'hello world', 'text/plain'), |
| 359 ('README', 'Welcome to our project', 'text/plain')], |
| 360 attachments) |
| 361 |
| 362 attachments = tracker_helpers._ParseIssueRequestAttachments(fake.PostData({ |
| 363 'file3': [file3], |
| 364 })) |
| 365 self.assertEquals( |
| 366 [('FILENAME.EXT', 'Abort, Retry, or Fail?', |
| 367 'application/octet-stream')], |
| 368 attachments) |
| 369 |
| 370 attachments = tracker_helpers._ParseIssueRequestAttachments(fake.PostData({ |
| 371 'file1': [file4], # Does not appear in result |
| 372 'file3': [file3], |
| 373 'file4': [file4], # Does not appear in result |
| 374 })) |
| 375 self.assertEquals( |
| 376 [('FILENAME.EXT', 'Abort, Retry, or Fail?', |
| 377 'application/octet-stream')], |
| 378 attachments) |
| 379 |
| 380 def testParseIssueRequestUsers(self): |
| 381 post_data = {} |
| 382 parsed_users = tracker_helpers._ParseIssueRequestUsers( |
| 383 'fake connection', post_data, self.services) |
| 384 self.assertEquals('', parsed_users.owner_username) |
| 385 self.assertEquals( |
| 386 framework_constants.NO_USER_SPECIFIED, parsed_users.owner_id) |
| 387 self.assertEquals([], parsed_users.cc_usernames) |
| 388 self.assertEquals([], parsed_users.cc_usernames_remove) |
| 389 self.assertEquals([], parsed_users.cc_ids) |
| 390 self.assertEquals([], parsed_users.cc_ids_remove) |
| 391 |
| 392 post_data = fake.PostData({ |
| 393 'owner': [''], |
| 394 }) |
| 395 parsed_users = tracker_helpers._ParseIssueRequestUsers( |
| 396 'fake connection', post_data, self.services) |
| 397 self.assertEquals('', parsed_users.owner_username) |
| 398 self.assertEquals( |
| 399 framework_constants.NO_USER_SPECIFIED, parsed_users.owner_id) |
| 400 self.assertEquals([], parsed_users.cc_usernames) |
| 401 self.assertEquals([], parsed_users.cc_usernames_remove) |
| 402 self.assertEquals([], parsed_users.cc_ids) |
| 403 self.assertEquals([], parsed_users.cc_ids_remove) |
| 404 |
| 405 post_data = fake.PostData({ |
| 406 'owner': [' \t'], |
| 407 }) |
| 408 parsed_users = tracker_helpers._ParseIssueRequestUsers( |
| 409 'fake connection', post_data, self.services) |
| 410 self.assertEquals('', parsed_users.owner_username) |
| 411 self.assertEquals( |
| 412 framework_constants.NO_USER_SPECIFIED, parsed_users.owner_id) |
| 413 self.assertEquals([], parsed_users.cc_usernames) |
| 414 self.assertEquals([], parsed_users.cc_usernames_remove) |
| 415 self.assertEquals([], parsed_users.cc_ids) |
| 416 self.assertEquals([], parsed_users.cc_ids_remove) |
| 417 |
| 418 post_data = fake.PostData({ |
| 419 'owner': ['b@example.com'], |
| 420 }) |
| 421 parsed_users = tracker_helpers._ParseIssueRequestUsers( |
| 422 'fake connection', post_data, self.services) |
| 423 self.assertEquals('b@example.com', parsed_users.owner_username) |
| 424 self.assertEquals(TEST_ID_MAP['b@example.com'], parsed_users.owner_id) |
| 425 self.assertEquals([], parsed_users.cc_usernames) |
| 426 self.assertEquals([], parsed_users.cc_usernames_remove) |
| 427 self.assertEquals([], parsed_users.cc_ids) |
| 428 self.assertEquals([], parsed_users.cc_ids_remove) |
| 429 |
| 430 post_data = fake.PostData({ |
| 431 'owner': ['b@example.com'], |
| 432 }) |
| 433 parsed_users = tracker_helpers._ParseIssueRequestUsers( |
| 434 'fake connection', post_data, self.services) |
| 435 self.assertEquals('b@example.com', parsed_users.owner_username) |
| 436 self.assertEquals(TEST_ID_MAP['b@example.com'], parsed_users.owner_id) |
| 437 self.assertEquals([], parsed_users.cc_usernames) |
| 438 self.assertEquals([], parsed_users.cc_usernames_remove) |
| 439 self.assertEquals([], parsed_users.cc_ids) |
| 440 self.assertEquals([], parsed_users.cc_ids_remove) |
| 441 |
| 442 post_data = fake.PostData({ |
| 443 'cc': ['b@example.com'], |
| 444 }) |
| 445 parsed_users = tracker_helpers._ParseIssueRequestUsers( |
| 446 'fake connection', post_data, self.services) |
| 447 self.assertEquals('', parsed_users.owner_username) |
| 448 self.assertEquals( |
| 449 framework_constants.NO_USER_SPECIFIED, parsed_users.owner_id) |
| 450 self.assertEquals(['b@example.com'], parsed_users.cc_usernames) |
| 451 self.assertEquals([], parsed_users.cc_usernames_remove) |
| 452 self.assertEquals([TEST_ID_MAP['b@example.com']], parsed_users.cc_ids) |
| 453 self.assertEquals([], parsed_users.cc_ids_remove) |
| 454 |
| 455 post_data = fake.PostData({ |
| 456 'cc': ['-b@example.com, c@example.com,,' |
| 457 'a@example.com,'], |
| 458 }) |
| 459 parsed_users = tracker_helpers._ParseIssueRequestUsers( |
| 460 'fake connection', post_data, self.services) |
| 461 self.assertEquals('', parsed_users.owner_username) |
| 462 self.assertEquals( |
| 463 framework_constants.NO_USER_SPECIFIED, parsed_users.owner_id) |
| 464 self.assertItemsEqual(['c@example.com', 'a@example.com'], |
| 465 parsed_users.cc_usernames) |
| 466 self.assertEquals(['b@example.com'], parsed_users.cc_usernames_remove) |
| 467 self.assertItemsEqual([TEST_ID_MAP['c@example.com'], |
| 468 TEST_ID_MAP['a@example.com']], |
| 469 parsed_users.cc_ids) |
| 470 self.assertEquals([TEST_ID_MAP['b@example.com']], |
| 471 parsed_users.cc_ids_remove) |
| 472 |
| 473 post_data = fake.PostData({ |
| 474 'owner': ['fuhqwhgads@example.com'], |
| 475 'cc': ['c@example.com, fuhqwhgads@example.com'], |
| 476 }) |
| 477 parsed_users = tracker_helpers._ParseIssueRequestUsers( |
| 478 'fake connection', post_data, self.services) |
| 479 self.assertEquals('fuhqwhgads@example.com', parsed_users.owner_username) |
| 480 gen_uid = framework_helpers.MurmurHash3_x86_32(parsed_users.owner_username) |
| 481 self.assertEquals(gen_uid, parsed_users.owner_id) # autocreated user |
| 482 self.assertItemsEqual( |
| 483 ['c@example.com', 'fuhqwhgads@example.com'], parsed_users.cc_usernames) |
| 484 self.assertEquals([], parsed_users.cc_usernames_remove) |
| 485 self.assertItemsEqual( |
| 486 [TEST_ID_MAP['c@example.com'], gen_uid], parsed_users.cc_ids) |
| 487 self.assertEquals([], parsed_users.cc_ids_remove) |
| 488 |
| 489 def testIsValidIssueOwner(self): |
| 490 project = project_pb2.Project() |
| 491 project.owner_ids.extend([1L, 2L]) |
| 492 project.committer_ids.extend([3L]) |
| 493 project.contributor_ids.extend([4L, 999L]) |
| 494 |
| 495 valid, _ = tracker_helpers.IsValidIssueOwner( |
| 496 'fake cnxn', project, framework_constants.NO_USER_SPECIFIED, |
| 497 self.services) |
| 498 self.assertTrue(valid) |
| 499 |
| 500 valid, _ = tracker_helpers.IsValidIssueOwner( |
| 501 'fake cnxn', project, 1L, |
| 502 self.services) |
| 503 self.assertTrue(valid) |
| 504 valid, _ = tracker_helpers.IsValidIssueOwner( |
| 505 'fake cnxn', project, 2L, |
| 506 self.services) |
| 507 self.assertTrue(valid) |
| 508 valid, _ = tracker_helpers.IsValidIssueOwner( |
| 509 'fake cnxn', project, 3L, |
| 510 self.services) |
| 511 self.assertTrue(valid) |
| 512 valid, _ = tracker_helpers.IsValidIssueOwner( |
| 513 'fake cnxn', project, 4L, |
| 514 self.services) |
| 515 self.assertTrue(valid) |
| 516 |
| 517 valid, _ = tracker_helpers.IsValidIssueOwner( |
| 518 'fake cnxn', project, 7L, |
| 519 self.services) |
| 520 self.assertFalse(valid) |
| 521 |
| 522 valid, _ = tracker_helpers.IsValidIssueOwner( |
| 523 'fake cnxn', project, 999L, |
| 524 self.services) |
| 525 self.assertFalse(valid) |
| 526 |
| 527 def testGetAllowedOpenAndClosedRelatedIssues(self): |
| 528 gaoacri = tracker_helpers.GetAllowedOpenAndClosedRelatedIssues |
| 529 opened = { |
| 530 100001: _Issue('proj', 1, 'summary 1', 'New'), |
| 531 100002: _Issue('proj', 2, 'summary 2', 'Accepted'), |
| 532 } |
| 533 closed = { |
| 534 100003: _Issue('proj', 3, 'summary 3', 'Accepted'), |
| 535 100004: _Issue('proj', 4, 'summary 4', 'Invalid'), |
| 536 } |
| 537 project = project_pb2.Project() |
| 538 project.project_id = 789 |
| 539 project.project_name = 'proj' |
| 540 project.state = project_pb2.ProjectState.LIVE |
| 541 mr = testing_helpers.MakeMonorailRequest(project=project) |
| 542 fake_issue_service = testing_helpers.Blank( |
| 543 GetOpenAndClosedIssues=lambda _cnxn, iids: ( |
| 544 [opened[iid] for iid in iids if iid in opened], |
| 545 [closed[iid] for iid in iids if iid in closed])) |
| 546 fake_config_service = testing_helpers.Blank( |
| 547 GetProjectConfigs=lambda _cnxn, pids: ( |
| 548 {pid: tracker_bizobj.MakeDefaultProjectIssueConfig(pid) |
| 549 for pid in pids})) |
| 550 fake_project_service = testing_helpers.Blank( |
| 551 GetProjects=lambda _, project_ids: {project.project_id: project}) |
| 552 services = service_manager.Services( |
| 553 issue=fake_issue_service, config=fake_config_service, |
| 554 project=fake_project_service) |
| 555 |
| 556 issue = tracker_pb2.Issue() |
| 557 issue.project_id = 789 |
| 558 # No merged into, no blocking, no blocked on. |
| 559 open_dict, closed_dict = gaoacri(services, mr, issue) |
| 560 self.assertEqual({}, open_dict) |
| 561 self.assertEqual({}, closed_dict) |
| 562 |
| 563 # An open "merged into" |
| 564 issue.merged_into = 100001 |
| 565 open_dict, closed_dict = gaoacri(services, mr, issue) |
| 566 self.assertEqual({100001: opened[100001]}, open_dict) |
| 567 self.assertEqual({}, closed_dict) |
| 568 |
| 569 # A closed "merged into" |
| 570 issue.merged_into = 100003 |
| 571 open_dict, closed_dict = gaoacri(services, mr, issue) |
| 572 self.assertEqual({}, open_dict) |
| 573 self.assertEqual({100003: closed[100003]}, closed_dict) |
| 574 |
| 575 # Some blocking and blocked on |
| 576 issue.blocking_iids.append(100001) |
| 577 issue.blocked_on_iids.append(100004) |
| 578 open_dict, closed_dict = gaoacri(services, mr, issue) |
| 579 self.assertEqual({100001: opened[100001]}, open_dict) |
| 580 self.assertEqual({100003: closed[100003], |
| 581 100004: closed[100004]}, closed_dict) |
| 582 |
| 583 def testMergeCCsAndAddComment(self): |
| 584 target_issue = fake.MakeTestIssue( |
| 585 789, 10, 'Target issue', 'New', 111L) |
| 586 source_issue = fake.MakeTestIssue( |
| 587 789, 100, 'Source issue', 'New', 222L) |
| 588 source_issue.cc_ids.append(111L) |
| 589 # Issue without owner |
| 590 source_issue_2 = fake.MakeTestIssue( |
| 591 789, 101, 'Source issue 2', 'New', 0L) |
| 592 |
| 593 project = self.services.project.TestAddProject( |
| 594 'testproj', owner_ids=[222L], project_id=789) |
| 595 self.services.issue.TestAddIssue(target_issue) |
| 596 self.services.issue.TestAddIssue(source_issue) |
| 597 self.services.issue.TestAddIssue(source_issue_2) |
| 598 |
| 599 # We copy this list so that it isn't updated by the test framework |
| 600 initial_issue_comments = ( |
| 601 self.services.issue.GetCommentsForIssue( |
| 602 'fake cnxn', target_issue.issue_id)[:]) |
| 603 mr = testing_helpers.MakeMonorailRequest(user_info={'user_id': 111L}) |
| 604 |
| 605 # Merging source into target should create a comment. |
| 606 self.assertIsNotNone( |
| 607 tracker_helpers.MergeCCsAndAddComment( |
| 608 self.services, mr, source_issue, project, target_issue)) |
| 609 updated_issue_comments = self.services.issue.GetCommentsForIssue( |
| 610 'fake cnxn', target_issue.issue_id) |
| 611 for comment in initial_issue_comments: |
| 612 self.assertIn(comment, updated_issue_comments) |
| 613 self.assertEqual( |
| 614 len(initial_issue_comments) + 1, len(updated_issue_comments)) |
| 615 |
| 616 # Merging source into target should add source's owner to target's CCs. |
| 617 updated_target_issue = self.services.issue.GetIssueByLocalID( |
| 618 'fake cnxn', 789, 10) |
| 619 self.assertIn(111L, updated_target_issue.cc_ids) |
| 620 self.assertIn(222L, updated_target_issue.cc_ids) |
| 621 |
| 622 # Merging source 2 into target should make a comment, but not update CCs. |
| 623 self.assertIsNotNone( |
| 624 tracker_helpers.MergeCCsAndAddComment( |
| 625 self.services, mr, source_issue_2, project, updated_target_issue)) |
| 626 updated_target_issue = self.services.issue.GetIssueByLocalID( |
| 627 'fake cnxn', 789, 10) |
| 628 self.assertNotIn(0L, updated_target_issue.cc_ids) |
| 629 |
| 630 def testMergeCCsAndAddCommentRestrictedSourceIssue(self): |
| 631 target_issue = fake.MakeTestIssue( |
| 632 789, 10, 'Target issue', 'New', 222L) |
| 633 target_issue_2 = fake.MakeTestIssue( |
| 634 789, 11, 'Target issue 2', 'New', 222L) |
| 635 source_issue = fake.MakeTestIssue( |
| 636 789, 100, 'Source issue', 'New', 111L) |
| 637 source_issue.cc_ids.append(111L) |
| 638 source_issue.labels.append('Restrict-View-Commit') |
| 639 target_issue_2.labels.append('Restrict-View-Commit') |
| 640 |
| 641 project = self.services.project.TestAddProject( |
| 642 'testproj', owner_ids=[222L], project_id=789) |
| 643 self.services.issue.TestAddIssue(source_issue) |
| 644 self.services.issue.TestAddIssue(target_issue) |
| 645 self.services.issue.TestAddIssue(target_issue_2) |
| 646 |
| 647 # We copy this list so that it isn't updated by the test framework |
| 648 initial_issue_comments = self.services.issue.GetCommentsForIssue( |
| 649 'fake cnxn', target_issue.issue_id)[:] |
| 650 mr = testing_helpers.MakeMonorailRequest(user_info={'user_id': 111L}) |
| 651 self.assertIsNotNone( |
| 652 tracker_helpers.MergeCCsAndAddComment( |
| 653 self.services, mr, source_issue, project, target_issue)) |
| 654 |
| 655 # When the source is restricted, we update the target comments... |
| 656 updated_issue_comments = self.services.issue.GetCommentsForIssue( |
| 657 'fake cnxn', target_issue.issue_id) |
| 658 for comment in initial_issue_comments: |
| 659 self.assertIn(comment, updated_issue_comments) |
| 660 self.assertEqual( |
| 661 len(initial_issue_comments) + 1, len(updated_issue_comments)) |
| 662 # ...but not the target CCs... |
| 663 updated_target_issue = self.services.issue.GetIssueByLocalID( |
| 664 'fake cnxn', 789, 10) |
| 665 self.assertNotIn(111L, updated_target_issue.cc_ids) |
| 666 # ...unless both issues have the same restrictions. |
| 667 self.assertIsNotNone( |
| 668 tracker_helpers.MergeCCsAndAddComment( |
| 669 self.services, mr, source_issue, project, target_issue_2)) |
| 670 updated_target_issue_2 = self.services.issue.GetIssueByLocalID( |
| 671 'fake cnxn', 789, 11) |
| 672 self.assertIn(111L, updated_target_issue_2.cc_ids) |
| 673 |
| 674 def testFormatIssueListURLNoCurrentState(self): |
| 675 config = tracker_pb2.ProjectIssueConfig() |
| 676 path = '/p/proj/issues/detail?id=123' |
| 677 mr = testing_helpers.MakeMonorailRequest( |
| 678 path=path, headers={'Host': 'code.google.com'}) |
| 679 mr.ComputeColSpec(config) |
| 680 |
| 681 absolute_base_url = 'http://code.google.com' |
| 682 |
| 683 url_1 = tracker_helpers.FormatIssueListURL(mr, config) |
| 684 self.assertEquals( |
| 685 '%s/p/proj/issues/list?%s' % ( |
| 686 absolute_base_url, self.default_colspec_param), |
| 687 url_1) |
| 688 |
| 689 url_2 = tracker_helpers.FormatIssueListURL( |
| 690 mr, config, foo=123) |
| 691 self.assertEquals( |
| 692 '%s/p/proj/issues/list?%s&foo=123' % ( |
| 693 absolute_base_url, self.default_colspec_param), |
| 694 url_2) |
| 695 |
| 696 url_3 = tracker_helpers.FormatIssueListURL( |
| 697 mr, config, foo=123, bar='abc') |
| 698 self.assertEquals( |
| 699 '%s/p/proj/issues/list?bar=abc&%s&foo=123' % ( |
| 700 absolute_base_url, self.default_colspec_param), |
| 701 url_3) |
| 702 |
| 703 url_4 = tracker_helpers.FormatIssueListURL( |
| 704 mr, config, baz='escaped+encoded&and100% "safe"') |
| 705 self.assertEquals( |
| 706 '%s/p/proj/issues/list?' |
| 707 'baz=escaped%%2Bencoded%%26and100%%25%%20%%22safe%%22&%s' % ( |
| 708 absolute_base_url, self.default_colspec_param), |
| 709 url_4) |
| 710 |
| 711 def testFormatIssueListURLKeepCurrentState(self): |
| 712 config = tracker_pb2.ProjectIssueConfig() |
| 713 path = '/p/proj/issues/detail?id=123&sort=aa&colspec=a b c&groupby=d' |
| 714 mr = testing_helpers.MakeMonorailRequest( |
| 715 path=path, headers={'Host': 'localhost:8080'}) |
| 716 mr.ComputeColSpec(config) |
| 717 |
| 718 absolute_base_url = 'http://localhost:8080' |
| 719 |
| 720 url_1 = tracker_helpers.FormatIssueListURL(mr, config) |
| 721 self.assertEquals( |
| 722 '%s/p/proj/issues/list?colspec=a%%20b%%20c' |
| 723 '&groupby=d&sort=aa' % absolute_base_url, |
| 724 url_1) |
| 725 |
| 726 url_2 = tracker_helpers.FormatIssueListURL( |
| 727 mr, config, foo=123) |
| 728 self.assertEquals( |
| 729 '%s/p/proj/issues/list?' |
| 730 'colspec=a%%20b%%20c&foo=123&groupby=d&sort=aa' % absolute_base_url, |
| 731 url_2) |
| 732 |
| 733 url_3 = tracker_helpers.FormatIssueListURL( |
| 734 mr, config, colspec='X Y Z') |
| 735 self.assertEquals( |
| 736 '%s/p/proj/issues/list?colspec=a%%20b%%20c' |
| 737 '&groupby=d&sort=aa' % absolute_base_url, |
| 738 url_3) |
| 739 |
| 740 def testFormatRelativeIssueURL(self): |
| 741 self.assertEquals( |
| 742 '/p/proj/issues/attachment', |
| 743 tracker_helpers.FormatRelativeIssueURL( |
| 744 'proj', urls.ISSUE_ATTACHMENT)) |
| 745 |
| 746 self.assertEquals( |
| 747 '/p/proj/issues/detail?id=123', |
| 748 tracker_helpers.FormatRelativeIssueURL( |
| 749 'proj', urls.ISSUE_DETAIL, id=123)) |
| 750 |
| 751 |
| 752 class MakeViewsForUsersInIssuesTest(unittest.TestCase): |
| 753 |
| 754 def setUp(self): |
| 755 self.issue1 = _Issue('proj', 1, 'summary 1', 'New') |
| 756 self.issue1.owner_id = 1001 |
| 757 self.issue1.reporter_id = 1002 |
| 758 |
| 759 self.issue2 = _Issue('proj', 2, 'summary 2', 'New') |
| 760 self.issue2.owner_id = 2001 |
| 761 self.issue2.reporter_id = 2002 |
| 762 self.issue2.cc_ids.extend([1, 1001, 1002, 1003]) |
| 763 |
| 764 self.issue3 = _Issue('proj', 3, 'summary 3', 'New') |
| 765 self.issue3.owner_id = 1001 |
| 766 self.issue3.reporter_id = 3002 |
| 767 |
| 768 self.user = fake.UserService() |
| 769 for user_id in [1, 1001, 1002, 1003, 2001, 2002, 3002]: |
| 770 self.user.TestAddUser( |
| 771 'test%d' % user_id, user_id, add_user=True) |
| 772 |
| 773 def testMakeViewsForUsersInIssues(self): |
| 774 issue_list = [self.issue1, self.issue2, self.issue3] |
| 775 users_by_id = tracker_helpers.MakeViewsForUsersInIssues( |
| 776 'fake cnxn', issue_list, self.user) |
| 777 self.assertItemsEqual([1, 1001, 1002, 1003, 2001, 2002, 3002], |
| 778 users_by_id.keys()) |
| 779 for user_id in [1001, 1002, 1003, 2001]: |
| 780 self.assertEqual(users_by_id[user_id].user_id, user_id) |
| 781 |
| 782 def testMakeViewsForUsersInIssuesOmittingSome(self): |
| 783 issue_list = [self.issue1, self.issue2, self.issue3] |
| 784 users_by_id = tracker_helpers.MakeViewsForUsersInIssues( |
| 785 'fake cnxn', issue_list, self.user, omit_ids=[1001, 1003]) |
| 786 self.assertItemsEqual([1, 1002, 2001, 2002, 3002], users_by_id.keys()) |
| 787 for user_id in [1002, 2001, 2002, 3002]: |
| 788 self.assertEqual(users_by_id[user_id].user_id, user_id) |
| 789 |
| 790 def testMakeViewsForUsersInIssuesEmpty(self): |
| 791 issue_list = [] |
| 792 users_by_id = tracker_helpers.MakeViewsForUsersInIssues( |
| 793 'fake cnxn', issue_list, self.user) |
| 794 self.assertItemsEqual([], users_by_id.keys()) |
| 795 |
| 796 |
| 797 class GetAllIssueProjectsTest(unittest.TestCase): |
| 798 issue_x_1 = tracker_pb2.Issue() |
| 799 issue_x_1.project_id = 789 |
| 800 issue_x_1.local_id = 1 |
| 801 issue_x_1.reporter_id = 1002 |
| 802 |
| 803 issue_x_2 = tracker_pb2.Issue() |
| 804 issue_x_2.project_id = 789 |
| 805 issue_x_2.local_id = 2 |
| 806 issue_x_2.reporter_id = 2002 |
| 807 |
| 808 issue_y_1 = tracker_pb2.Issue() |
| 809 issue_y_1.project_id = 678 |
| 810 issue_y_1.local_id = 1 |
| 811 issue_y_1.reporter_id = 2002 |
| 812 |
| 813 def setUp(self): |
| 814 self.project_service = fake.ProjectService() |
| 815 self.project_service.TestAddProject('proj-x', project_id=789) |
| 816 self.project_service.TestAddProject('proj-y', project_id=678) |
| 817 self.cnxn = 'fake connection' |
| 818 |
| 819 def testGetAllIssueProjects_Empty(self): |
| 820 self.assertEqual( |
| 821 {}, tracker_helpers.GetAllIssueProjects( |
| 822 self.cnxn, [], self.project_service)) |
| 823 |
| 824 def testGetAllIssueProjects_Normal(self): |
| 825 self.assertEqual( |
| 826 {789: self.project_service.GetProjectByName(self.cnxn, 'proj-x')}, |
| 827 tracker_helpers.GetAllIssueProjects( |
| 828 self.cnxn, [self.issue_x_1, self.issue_x_2], self.project_service)) |
| 829 self.assertEqual( |
| 830 {789: self.project_service.GetProjectByName(self.cnxn, 'proj-x'), |
| 831 678: self.project_service.GetProjectByName(self.cnxn, 'proj-y')}, |
| 832 tracker_helpers.GetAllIssueProjects( |
| 833 self.cnxn, [self.issue_x_1, self.issue_x_2, self.issue_y_1], |
| 834 self.project_service)) |
| 835 |
| 836 |
| 837 class FilterOutNonViewableIssuesTest(unittest.TestCase): |
| 838 owner_id = 111L |
| 839 committer_id = 222L |
| 840 nonmember_1_id = 1002L |
| 841 nonmember_2_id = 2002L |
| 842 nonmember_3_id = 3002L |
| 843 |
| 844 issue1 = tracker_pb2.Issue() |
| 845 issue1.project_name = 'proj' |
| 846 issue1.project_id = 789 |
| 847 issue1.local_id = 1 |
| 848 issue1.reporter_id = nonmember_1_id |
| 849 |
| 850 issue2 = tracker_pb2.Issue() |
| 851 issue2.project_name = 'proj' |
| 852 issue2.project_id = 789 |
| 853 issue2.local_id = 2 |
| 854 issue2.reporter_id = nonmember_2_id |
| 855 issue2.labels.extend(['foo', 'bar']) |
| 856 |
| 857 issue3 = tracker_pb2.Issue() |
| 858 issue3.project_name = 'proj' |
| 859 issue3.project_id = 789 |
| 860 issue3.local_id = 3 |
| 861 issue3.reporter_id = nonmember_3_id |
| 862 issue3.labels.extend(['restrict-view-commit']) |
| 863 |
| 864 issue4 = tracker_pb2.Issue() |
| 865 issue4.project_name = 'proj' |
| 866 issue4.project_id = 789 |
| 867 issue4.local_id = 4 |
| 868 issue4.reporter_id = nonmember_3_id |
| 869 issue4.labels.extend(['Foo', 'Restrict-View-Commit']) |
| 870 |
| 871 def setUp(self): |
| 872 self.user = user_pb2.User() |
| 873 self.project = self.MakeProject(project_pb2.ProjectState.LIVE) |
| 874 self.config = tracker_bizobj.MakeDefaultProjectIssueConfig( |
| 875 self.project.project_id) |
| 876 self.project_dict = {self.project.project_id: self.project} |
| 877 self.config_dict = {self.config.project_id: self.config} |
| 878 |
| 879 def MakeProject(self, state): |
| 880 p = project_pb2.Project( |
| 881 project_id=789, project_name='proj', state=state, |
| 882 owner_ids=[self.owner_id], committer_ids=[self.committer_id]) |
| 883 return p |
| 884 |
| 885 def testFilterOutNonViewableIssues_Member(self): |
| 886 # perms will be permissions.COMMITTER_ACTIVE_PERMISSIONSET |
| 887 filtered_issues = tracker_helpers.FilterOutNonViewableIssues( |
| 888 {self.committer_id}, self.user, self.project_dict, |
| 889 self.config_dict, |
| 890 [self.issue1, self.issue2, self.issue3, self.issue4]) |
| 891 self.assertListEqual([1, 2, 3, 4], |
| 892 [issue.local_id for issue in filtered_issues]) |
| 893 |
| 894 def testFilterOutNonViewableIssues_Owner(self): |
| 895 # perms will be permissions.OWNER_ACTIVE_PERMISSIONSET |
| 896 filtered_issues = tracker_helpers.FilterOutNonViewableIssues( |
| 897 {self.owner_id}, self.user, self.project_dict, self.config_dict, |
| 898 [self.issue1, self.issue2, self.issue3, self.issue4]) |
| 899 self.assertListEqual([1, 2, 3, 4], |
| 900 [issue.local_id for issue in filtered_issues]) |
| 901 |
| 902 def testFilterOutNonViewableIssues_Empty(self): |
| 903 # perms will be permissions.COMMITTER_ACTIVE_PERMISSIONSET |
| 904 filtered_issues = tracker_helpers.FilterOutNonViewableIssues( |
| 905 {self.committer_id}, self.user, self.project_dict, |
| 906 self.config_dict, []) |
| 907 self.assertListEqual([], filtered_issues) |
| 908 |
| 909 def testFilterOutNonViewableIssues_NonMember(self): |
| 910 # perms will be permissions.READ_ONLY_PERMISSIONSET |
| 911 filtered_issues = tracker_helpers.FilterOutNonViewableIssues( |
| 912 {self.nonmember_1_id}, self.user, self.project_dict, |
| 913 self.config_dict, [self.issue1, self.issue2, self.issue3, self.issue4]) |
| 914 self.assertListEqual([1, 2], |
| 915 [issue.local_id for issue in filtered_issues]) |
| 916 |
| 917 def testFilterOutNonViewableIssues_Reporter(self): |
| 918 # perms will be permissions.READ_ONLY_PERMISSIONSET |
| 919 filtered_issues = tracker_helpers.FilterOutNonViewableIssues( |
| 920 {self.nonmember_3_id}, self.user, self.project_dict, |
| 921 self.config_dict, [self.issue1, self.issue2, self.issue3, self.issue4]) |
| 922 self.assertListEqual([1, 2, 3, 4], |
| 923 [issue.local_id for issue in filtered_issues]) |
| 924 |
| 925 |
| 926 class IssueMergeTest(unittest.TestCase): |
| 927 |
| 928 def setUp(self): |
| 929 self.cnxn = 'fake cnxn' |
| 930 self.services = service_manager.Services( |
| 931 config=fake.ConfigService(), |
| 932 issue=fake.IssueService(), |
| 933 user=fake.UserService(), |
| 934 project=fake.ProjectService(), |
| 935 issue_star=fake.IssueStarService(), |
| 936 spam=fake.SpamService() |
| 937 ) |
| 938 self.project = self.services.project.TestAddProject('proj', project_id=987) |
| 939 self.config = tracker_bizobj.MakeDefaultProjectIssueConfig( |
| 940 self.project.project_id) |
| 941 self.project_dict = {self.project.project_id: self.project} |
| 942 self.config_dict = {self.config.project_id: self.config} |
| 943 |
| 944 def testParseMergeFields_NotSpecified(self): |
| 945 issue = fake.MakeTestIssue(987, 1, 'summary', 'New', 111L) |
| 946 errors = template_helpers.EZTError() |
| 947 post_data = {} |
| 948 |
| 949 text, merge_into_issue = tracker_helpers.ParseMergeFields( |
| 950 self.cnxn, None, 'proj', post_data, 'New', self.config, issue, errors) |
| 951 self.assertEqual('', text) |
| 952 self.assertEqual(None, merge_into_issue) |
| 953 |
| 954 text, merge_into_issue = tracker_helpers.ParseMergeFields( |
| 955 self.cnxn, None, 'proj', post_data, 'Duplicate', self.config, issue, |
| 956 errors) |
| 957 self.assertEqual('', text) |
| 958 self.assertTrue(errors.merge_into_id) |
| 959 self.assertEqual(None, merge_into_issue) |
| 960 |
| 961 def testParseMergeFields_WrongStatus(self): |
| 962 issue = fake.MakeTestIssue(987, 1, 'summary', 'New', 111L) |
| 963 errors = template_helpers.EZTError() |
| 964 post_data = {'merge_into': '12'} |
| 965 |
| 966 text, merge_into_issue = tracker_helpers.ParseMergeFields( |
| 967 self.cnxn, None, 'proj', post_data, 'New', self.config, issue, errors) |
| 968 self.assertEqual('', text) |
| 969 self.assertEqual(None, merge_into_issue) |
| 970 |
| 971 def testParseMergeFields_NoSuchIssue(self): |
| 972 issue = fake.MakeTestIssue(987, 1, 'summary', 'New', 111L) |
| 973 issue.merged_into = 12 |
| 974 errors = template_helpers.EZTError() |
| 975 post_data = {'merge_into': '12'} |
| 976 |
| 977 text, merge_into_issue = tracker_helpers.ParseMergeFields( |
| 978 self.cnxn, self.services, 'proj', post_data, 'Duplicate', |
| 979 self.config, issue, errors) |
| 980 self.assertEqual('12', text) |
| 981 self.assertEqual(None, merge_into_issue) |
| 982 |
| 983 def testParseMergeFields_DontSelfMerge(self): |
| 984 issue = fake.MakeTestIssue(987, 1, 'summary', 'New', 111L) |
| 985 errors = template_helpers.EZTError() |
| 986 post_data = {'merge_into': '1'} |
| 987 |
| 988 text, merge_into_issue = tracker_helpers.ParseMergeFields( |
| 989 self.cnxn, self.services, 'proj', post_data, 'Duplicate', self.config, |
| 990 issue, errors) |
| 991 self.assertEqual('1', text) |
| 992 self.assertEqual(None, merge_into_issue) |
| 993 self.assertEqual('Cannot merge issue into itself', errors.merge_into_id) |
| 994 |
| 995 def testParseMergeFields_NewIssueToMerge(self): |
| 996 merged_local_id = self.services.issue.CreateIssue( |
| 997 self.cnxn, self.services, |
| 998 self.project.project_id, 'unused_summary', 'unused_status', 111L, |
| 999 [], [], [], [], 111L, 'unused_marked_description') |
| 1000 mergee_local_id = self.services.issue.CreateIssue( |
| 1001 self.cnxn, self.services, |
| 1002 self.project.project_id, 'unused_summary', 'unused_status', 111L, |
| 1003 [], [], [], [], 111L, 'unused_marked_description') |
| 1004 merged_issue = self.services.issue.GetIssueByLocalID( |
| 1005 self.cnxn, self.project.project_id, merged_local_id) |
| 1006 mergee_issue = self.services.issue.GetIssueByLocalID( |
| 1007 self.cnxn, self.project.project_id, mergee_local_id) |
| 1008 |
| 1009 errors = template_helpers.EZTError() |
| 1010 post_data = {'merge_into': str(mergee_issue.local_id)} |
| 1011 |
| 1012 text, merge_into_issue = tracker_helpers.ParseMergeFields( |
| 1013 self.cnxn, self.services, 'proj', post_data, 'Duplicate', self.config, |
| 1014 merged_issue, errors) |
| 1015 self.assertEqual(str(mergee_issue.local_id), text) |
| 1016 self.assertEqual(mergee_issue, merge_into_issue) |
| 1017 |
| 1018 def testIsMergeAllowed(self): |
| 1019 mr = testing_helpers.MakeMonorailRequest() |
| 1020 issue = fake.MakeTestIssue(987, 1, 'summary', 'New', 111L) |
| 1021 issue.project_name = self.project.project_name |
| 1022 |
| 1023 for (perm_set, expected_merge_allowed) in ( |
| 1024 (permissions.READ_ONLY_PERMISSIONSET, False), |
| 1025 (permissions.COMMITTER_INACTIVE_PERMISSIONSET, False), |
| 1026 (permissions.COMMITTER_ACTIVE_PERMISSIONSET, True), |
| 1027 (permissions.OWNER_ACTIVE_PERMISSIONSET, True)): |
| 1028 mr.perms = perm_set |
| 1029 merge_allowed = tracker_helpers.IsMergeAllowed(issue, mr, self.services) |
| 1030 self.assertEquals(expected_merge_allowed, merge_allowed) |
| 1031 |
| 1032 def testMergeIssueStars(self): |
| 1033 mr = testing_helpers.MakeMonorailRequest() |
| 1034 mr.project_name = self.project.project_name |
| 1035 mr.project = self.project |
| 1036 |
| 1037 config = self.services.config.GetProjectConfig( |
| 1038 self.cnxn, self.project.project_id) |
| 1039 self.services.issue_star.SetStar( |
| 1040 self.cnxn, self.services, config, 1, 1, True) |
| 1041 self.services.issue_star.SetStar( |
| 1042 self.cnxn, self.services, config, 1, 2, True) |
| 1043 self.services.issue_star.SetStar( |
| 1044 self.cnxn, self.services, config, 1, 3, True) |
| 1045 self.services.issue_star.SetStar( |
| 1046 self.cnxn, self.services, config, 2, 3, True) |
| 1047 self.services.issue_star.SetStar( |
| 1048 self.cnxn, self.services, config, 2, 4, True) |
| 1049 self.services.issue_star.SetStar( |
| 1050 self.cnxn, self.services, config, 2, 5, True) |
| 1051 |
| 1052 new_starrers = tracker_helpers.GetNewIssueStarrers( |
| 1053 self.cnxn, self.services, 1, 2) |
| 1054 self.assertItemsEqual(new_starrers, [1, 2]) |
| 1055 tracker_helpers.AddIssueStarrers( |
| 1056 self.cnxn, self.services, mr, 2, self.project, new_starrers) |
| 1057 issue_2_starrers = self.services.issue_star.LookupItemStarrers( |
| 1058 self.cnxn, 2) |
| 1059 # XXX(jrobbins): these tests incorrectly mix local IDs with IIDs. |
| 1060 self.assertItemsEqual([1, 2, 3, 4, 5], issue_2_starrers) |
| 1061 |
| 1062 |
| 1063 if __name__ == '__main__': |
| 1064 unittest.main() |
OLD | NEW |