Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2346)

Unified Diff: appengine/monorail/tracker/test/issuebulkedit_test.py

Issue 1868553004: Open Source Monorail (Closed) Base URL: https://chromium.googlesource.com/infra/infra.git@master
Patch Set: Rebase Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: appengine/monorail/tracker/test/issuebulkedit_test.py
diff --git a/appengine/monorail/tracker/test/issuebulkedit_test.py b/appengine/monorail/tracker/test/issuebulkedit_test.py
new file mode 100644
index 0000000000000000000000000000000000000000..aa722deba9e23f2f627ed3038049edc5f05a8d60
--- /dev/null
+++ b/appengine/monorail/tracker/test/issuebulkedit_test.py
@@ -0,0 +1,462 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is govered by a BSD-style
+# license that can be found in the LICENSE file or at
+# https://developers.google.com/open-source/licenses/bsd
+
+"""Unittests for monorail.tracker.issuebulkedit."""
+
+import os
+import unittest
+import webapp2
+
+from google.appengine.api import memcache
+from google.appengine.api import taskqueue
+from google.appengine.ext import testbed
+
+from framework import monorailrequest
+from framework import permissions
+from proto import tracker_pb2
+from services import service_manager
+from services import tracker_fulltext
+from testing import fake
+from testing import testing_helpers
+from tracker import issuebulkedit
+from tracker import tracker_bizobj
+
+
+class Response(object):
+
+ def __init__(self):
+ self.status = None
+
+
+class IssueBulkEditTest(unittest.TestCase):
+
+ def setUp(self):
+ self.services = service_manager.Services(
+ features=fake.FeaturesService(),
+ project=fake.ProjectService(),
+ config=fake.ConfigService(),
+ issue=fake.IssueService(),
+ issue_star=fake.IssueStarService(),
+ user=fake.UserService(),
+ usergroup=fake.UserGroupService())
+ self.servlet = issuebulkedit.IssueBulkEdit(
+ 'req', 'res', services=self.services)
+ self.mr = testing_helpers.MakeMonorailRequest(
+ perms=permissions.OWNER_ACTIVE_PERMISSIONSET)
+ self.project = self.services.project.TestAddProject(
+ name='proj', project_id=789, owner_ids=[111])
+ self.cnxn = 'fake connection'
+ self.config = self.services.config.GetProjectConfig(
+ self.cnxn, self.project.project_id)
+ self.services.config.StoreConfig(self.cnxn, self.config)
+ self.owner = self.services.user.TestAddUser('owner@example.com', 111)
+
+ self.testbed = testbed.Testbed()
+ self.testbed.activate()
+ self.testbed.init_taskqueue_stub()
+ self.testbed.init_memcache_stub()
+ self.testbed.init_datastore_v3_stub()
+ self.taskqueue_stub = self.testbed.get_stub(testbed.TASKQUEUE_SERVICE_NAME)
+ self.taskqueue_stub._root_path = os.path.dirname(
+ os.path.dirname(os.path.dirname( __file__ )))
+
+ self.mocked_methods = {}
+
+ def tearDown(self):
+ """Restore mocked objects of other modules."""
+ for obj, items in self.mocked_methods.iteritems():
+ for member, previous_value in items.iteritems():
+ setattr(obj, member, previous_value)
+
+ def testAssertBasePermission(self):
+ """Permit users with EDIT_ISSUE and ADD_ISSUE_COMMENT permissions."""
+ mr = testing_helpers.MakeMonorailRequest(
+ perms=permissions.CONTRIBUTOR_ACTIVE_PERMISSIONSET)
+ self.assertRaises(permissions.PermissionException,
+ self.servlet.AssertBasePermission, mr)
+
+ self.servlet.AssertBasePermission(self.mr)
+
+ def testGatherPageData(self):
+ """Test GPD works in a normal no-corner-cases case."""
+ local_id_1 = self.services.issue.CreateIssue(
+ self.cnxn, self.services, 789, 'issue summary', 'New', None,
+ [], [], [], [], 111L, 'test issue')
+ mr = testing_helpers.MakeMonorailRequest(
+ project=self.project)
+ mr.local_id_list = [local_id_1]
+
+ page_data = self.servlet.GatherPageData(mr)
+ self.assertEqual(1, page_data['num_issues'])
+
+ def testGatherPageData_NoIssues(self):
+ """Test GPD when no issues are specified in the mr."""
+ mr = testing_helpers.MakeMonorailRequest(
+ project=self.project)
+ self.assertRaises(monorailrequest.InputException,
+ self.servlet.GatherPageData, mr)
+
+ def testGatherPageData_FilteredIssues(self):
+ """Test GPD when all specified issues get filtered out."""
+ local_id_1 = self.services.issue.CreateIssue(
+ self.cnxn, self.services, 789, 'issue summary', 'New', None, [],
+ ['restrict-view-Googler'], [], [],
+ 111L, 'test issue')
+ mr = testing_helpers.MakeMonorailRequest(
+ project=self.project)
+ mr.local_id_list = [local_id_1]
+
+ self.assertRaises(webapp2.HTTPException,
+ self.servlet.GatherPageData, mr)
+
+ def testGatherPageData_TypeLabels(self):
+ """Test that GPD displays a custom field for appropriate issues."""
+ local_id_1 = self.services.issue.CreateIssue(
+ self.cnxn, self.services, 789, 'issue summary', 'New', None, [],
+ ['type-customlabels'], [], [],
+ 111L, 'test issue')
+ mr = testing_helpers.MakeMonorailRequest(
+ project=self.project)
+ mr.local_id_list = [local_id_1]
+
+ fd = tracker_bizobj.MakeFieldDef(
+ 123, 789, 'CPU', tracker_pb2.FieldTypes.INT_TYPE, None,
+ '', False, False, None, None, '', False, '', '',
+ tracker_pb2.NotifyTriggers.NEVER, 'doc', False)
+ self.config.field_defs.append(fd)
+
+ page_data = self.servlet.GatherPageData(mr)
+ self.assertEqual(1, len(page_data['fields']))
+
+ def testProcessFormData(self):
+ """Test that PFD works in a normal no-corner-cases case."""
+ local_id_1 = self.services.issue.CreateIssue(
+ self.cnxn, self.services, 789, 'issue summary', 'New', 111L,
+ [], [], [], [], 111L, 'test issue')
+ mr = testing_helpers.MakeMonorailRequest(
+ project=self.project,
+ perms=permissions.OWNER_ACTIVE_PERMISSIONSET,
+ user_info={'user_id': 111})
+ mr.local_id_list = [local_id_1]
+
+ post_data = fake.PostData(
+ owner=['owner@example.com'], can=[1],
+ q=[''], colspec=[''], sort=[''], groupby=[''], start=[0], num=[100])
+ self._MockMethods()
+ url = self.servlet.ProcessFormData(mr, post_data)
+ self.assertTrue('list?can=1&saved=1' in url)
+
+ def testProcessFormData_NoIssues(self):
+ """Test PFD when no issues are specified."""
+ mr = testing_helpers.MakeMonorailRequest(
+ project=self.project,
+ perms=permissions.OWNER_ACTIVE_PERMISSIONSET,
+ user_info={'user_id': 111})
+ post_data = fake.PostData()
+ self.servlet.response = Response()
+ self.servlet.ProcessFormData(mr, post_data)
+ # 400 == bad request
+ self.assertEqual(400, self.servlet.response.status)
+
+ def testProcessFormData_NoUser(self):
+ """Test PDF when the user is not logged in."""
+ mr = testing_helpers.MakeMonorailRequest(
+ project=self.project)
+ mr.local_id_list = [99999]
+ post_data = fake.PostData()
+ self.servlet.response = Response()
+ self.servlet.ProcessFormData(mr, post_data)
+ # 400 == bad request
+ self.assertEqual(400, self.servlet.response.status)
+
+ def testProcessFormData_CantComment(self):
+ """Test PFD when the user can't comment on any of the issues."""
+ mr = testing_helpers.MakeMonorailRequest(
+ project=self.project,
+ perms=permissions.EMPTY_PERMISSIONSET,
+ user_info={'user_id': 111})
+ mr.local_id_list = [99999]
+ post_data = fake.PostData()
+ self.servlet.response = Response()
+ self.servlet.ProcessFormData(mr, post_data)
+ # 400 == bad request
+ self.assertEqual(400, self.servlet.response.status)
+
+ def testProcessFormData_CantEdit(self):
+ """Test PFD when the user can't edit any issue metadata."""
+ mr = testing_helpers.MakeMonorailRequest(
+ project=self.project,
+ perms=permissions.CONTRIBUTOR_ACTIVE_PERMISSIONSET,
+ user_info={'user_id': 111})
+ mr.local_id_list = [99999]
+ post_data = fake.PostData()
+ self.servlet.response = Response()
+ self.servlet.ProcessFormData(mr, post_data)
+ # 400 == bad request
+ self.assertEqual(400, self.servlet.response.status)
+
+ def testProcessFormData_CantMove(self):
+ """Test PFD when the user can't move issues."""
+ mr = testing_helpers.MakeMonorailRequest(
+ project=self.project,
+ perms=permissions.COMMITTER_ACTIVE_PERMISSIONSET,
+ user_info={'user_id': 111})
+ mr.local_id_list = [99999]
+ post_data = fake.PostData(move_to=['proj'])
+ self.servlet.response = Response()
+ self.servlet.ProcessFormData(mr, post_data)
+ # 400 == bad request
+ self.assertEqual(400, self.servlet.response.status)
+
+ local_id_1 = self.services.issue.CreateIssue(
+ self.cnxn, self.services, 789, 'issue summary', 'New', 111L,
+ [], [], [], [], 111L, 'test issue')
+ mr.perms = permissions.OWNER_ACTIVE_PERMISSIONSET
+ mr.local_id_list = [local_id_1]
+ mr.project_name = 'proj'
+ self._MockMethods()
+ self.servlet.ProcessFormData(mr, post_data)
+ self.assertEqual(
+ 'The issues are already in project proj', mr.errors.move_to)
+
+ post_data = fake.PostData(move_to=['notexist'])
+ self.servlet.ProcessFormData(mr, post_data)
+ self.assertEqual('No such project: notexist', mr.errors.move_to)
+
+ def _MockMethods(self):
+ # Mock methods of other modules to avoid unnecessary testing
+ self.mocked_methods[tracker_fulltext] = {
+ 'IndexIssues': tracker_fulltext.IndexIssues,
+ 'UnindexIssues': tracker_fulltext.UnindexIssues}
+ def DoNothing(*_args, **_kwargs):
+ pass
+ self.servlet.PleaseCorrect = DoNothing
+ tracker_fulltext.IndexIssues = DoNothing
+ tracker_fulltext.UnindexIssues = DoNothing
+
+ def VerifyIssueUpdated(self, project_id, local_id):
+ issue = self.services.issue.GetIssueByLocalID(
+ self.cnxn, project_id, local_id)
+ issue_id = issue.issue_id
+ comments = self.services.issue.GetCommentsForIssue(self.cnxn, issue_id)
+ last_comment = comments[-1]
+ if last_comment.amendments[0].newvalue == 'Updated':
+ return True
+ else:
+ return False
+
+ def testProcessFormData_CustomFields(self):
+ """Test PFD processes edits to custom fields."""
+ local_id_1 = self.services.issue.CreateIssue(
+ self.cnxn, self.services, 789, 'issue summary', 'New', 111L,
+ [], [], [], [], 111L, 'test issue')
+ mr = testing_helpers.MakeMonorailRequest(
+ project=self.project,
+ perms=permissions.OWNER_ACTIVE_PERMISSIONSET,
+ user_info={'user_id': 111})
+ mr.local_id_list = [local_id_1]
+
+ fd = tracker_bizobj.MakeFieldDef(
+ 12345, 789, 'CPU', tracker_pb2.FieldTypes.INT_TYPE, None,
+ '', False, False, None, None, '', False, '', '',
+ tracker_pb2.NotifyTriggers.NEVER, 'doc', False)
+ self.config.field_defs.append(fd)
+
+ post_data = fake.PostData(
+ custom_12345=['111'], owner=['owner@example.com'], can=[1],
+ q=[''], colspec=[''], sort=[''], groupby=[''], start=[0], num=[100])
+ self._MockMethods()
+ self.servlet.ProcessFormData(mr, post_data)
+ self.assertTrue(self.VerifyIssueUpdated(789, local_id_1))
+
+ def testProcessFormData_DuplicateStatus_MergeSameIssue(self):
+ """Test PFD processes null/cleared status values."""
+ local_id_1 = self.services.issue.CreateIssue(
+ self.cnxn, self.services, self.project.project_id, 'issue summary',
+ 'New', 111L, [], [], [], [], 111L, 'test issue')
+ merge_into_local_id_2 = self.services.issue.CreateIssue(
+ self.cnxn, self.services, self.project.project_id, 'issue summary2',
+ 'New', 112L, [], [], [], [], 112L, 'test issue2')
+
+ mr = testing_helpers.MakeMonorailRequest(
+ project=self.project,
+ perms=permissions.OWNER_ACTIVE_PERMISSIONSET,
+ user_info={'user_id': 111})
+ mr.local_id_list = [local_id_1, merge_into_local_id_2]
+ mr.project_name = 'proj'
+
+ # Add required project_name to merge_into_issue.
+ merge_into_issue = self.services.issue.GetIssueByLocalID(
+ mr.cnxn, self.project.project_id, merge_into_local_id_2)
+ merge_into_issue.project_name = 'proj'
+
+ post_data = fake.PostData(status=['Duplicate'],
+ merge_into=[str(merge_into_local_id_2)], owner=['owner@example.com'],
+ can=[1], q=[''], colspec=[''], sort=[''], groupby=[''], start=[0],
+ num=[100])
+ self._MockMethods()
+ self.servlet.ProcessFormData(mr, post_data)
+ self.assertEquals('Cannot merge issue into itself', mr.errors.merge_into_id)
+
+ def testProcessFormData_DuplicateStatus_MergeMissingIssue(self):
+ """Test PFD processes null/cleared status values."""
+ local_id_1 = self.services.issue.CreateIssue(
+ self.cnxn, self.services, self.project.project_id, 'issue summary',
+ 'New', 111L, [], [], [], [], 111L, 'test issue')
+ local_id_2 = self.services.issue.CreateIssue(
+ self.cnxn, self.services, self.project.project_id, 'issue summary2',
+ 'New', 112L, [], [], [], [], 112L, 'test issue2')
+ mr = testing_helpers.MakeMonorailRequest(
+ project=self.project,
+ perms=permissions.OWNER_ACTIVE_PERMISSIONSET,
+ user_info={'user_id': 111})
+ mr.local_id_list = [local_id_1, local_id_2]
+ mr.project_name = 'proj'
+
+ post_data = fake.PostData(status=['Duplicate'],
+ merge_into=['non existant id'], owner=['owner@example.com'],
+ can=[1], q=[''], colspec=[''], sort=[''], groupby=[''], start=[0],
+ num=[100])
+ self._MockMethods()
+ self.servlet.ProcessFormData(mr, post_data)
+ self.assertEquals('Please enter an issue ID',
+ mr.errors.merge_into_id)
+
+ def testProcessFormData_DuplicateStatus_Success(self):
+ """Test PFD processes null/cleared status values."""
+ local_id_1 = self.services.issue.CreateIssue(
+ self.cnxn, self.services, self.project.project_id, 'issue summary',
+ 'New', 111L, [], [], [], [], 111L, 'test issue')
+ local_id_2 = self.services.issue.CreateIssue(
+ self.cnxn, self.services, self.project.project_id, 'issue summary2',
+ 'New', 111L, [], [], [], [], 111L, 'test issue2')
+ merge_into_local_id_3 = self.services.issue.CreateIssue(
+ self.cnxn, self.services, self.project.project_id, 'issue summary3',
+ 'New', 112L, [], [], [], [], 112L, 'test issue3')
+ mr = testing_helpers.MakeMonorailRequest(
+ project=self.project,
+ perms=permissions.OWNER_ACTIVE_PERMISSIONSET,
+ user_info={'user_id': 111})
+ mr.local_id_list = [local_id_1, local_id_2]
+ mr.project_name = 'proj'
+
+ post_data = fake.PostData(status=['Duplicate'],
+ merge_into=[str(merge_into_local_id_3)], owner=['owner@example.com'],
+ can=[1], q=[''], colspec=[''], sort=[''], groupby=[''], start=[0],
+ num=[100])
+ self._MockMethods()
+
+ # Add project_name, CCs and starrers to the merge_into_issue.
+ merge_into_issue = self.services.issue.GetIssueByLocalID(
+ mr.cnxn, self.project.project_id, merge_into_local_id_3)
+ merge_into_issue.project_name = 'proj'
+ merge_into_issue.cc_ids = [113L, 120L]
+ self.services.issue_star.SetStar(
+ mr.cnxn, None, None, merge_into_issue.issue_id, 120L, True)
+
+ # Add project_name, CCs and starrers to the source issues.
+ # Issue 1
+ issue_1 = self.services.issue.GetIssueByLocalID(
+ mr.cnxn, self.project.project_id, local_id_1)
+ issue_1.project_name = 'proj'
+ issue_1.cc_ids = [113L, 114L]
+ self.services.issue_star.SetStar(
+ mr.cnxn, None, None, issue_1.issue_id, 113L, True)
+ # Issue 2
+ issue_2 = self.services.issue.GetIssueByLocalID(
+ mr.cnxn, self.project.project_id, local_id_2)
+ issue_2.project_name = 'proj'
+ issue_2.cc_ids = [113L, 115L, 118L]
+ self.services.issue_star.SetStar(
+ mr.cnxn, None, None, issue_2.issue_id, 114L, True)
+ self.services.issue_star.SetStar(
+ mr.cnxn, None, None, issue_2.issue_id, 115L, True)
+
+ self.servlet.ProcessFormData(mr, post_data)
+
+ # Verify both source issues were updated.
+ self.assertTrue(
+ self.VerifyIssueUpdated(self.project.project_id, local_id_1))
+ self.assertTrue(
+ self.VerifyIssueUpdated(self.project.project_id, local_id_2))
+
+ # Verify that the merge into issue was updated with a comment.
+ comments = self.services.issue.GetCommentsForIssue(
+ self.cnxn, merge_into_issue.issue_id)
+ self.assertEquals(
+ 'Issue 1 has been merged into this issue.\n'
+ 'Issue 2 has been merged into this issue.', comments[-1].content)
+
+ # Verify CC lists and owner were merged to the merge_into issue.
+ self.assertEquals(
+ [113L, 120L, 114L, 115L, 118L, 111L], merge_into_issue.cc_ids)
+ # Verify new starrers were added to the merge_into issue.
+ self.assertEquals(4,
+ self.services.issue_star.CountItemStars(
+ self.cnxn, merge_into_issue.issue_id))
+ self.assertEquals([120L, 113L, 114L, 115L],
+ self.services.issue_star.LookupItemStarrers(
+ self.cnxn, merge_into_issue.issue_id))
+
+ def testProcessFormData_ClearStatus(self):
+ """Test PFD processes null/cleared status values."""
+ local_id_1 = self.services.issue.CreateIssue(
+ self.cnxn, self.services, 789, 'issue summary', 'New', 111L,
+ [], [], [], [], 111L, 'test issue')
+ mr = testing_helpers.MakeMonorailRequest(
+ project=self.project,
+ perms=permissions.OWNER_ACTIVE_PERMISSIONSET,
+ user_info={'user_id': 111})
+ mr.local_id_list = [local_id_1]
+
+ post_data = fake.PostData(
+ op_statusenter=['clear'], owner=['owner@example.com'], can=[1],
+ q=[''], colspec=[''], sort=[''], groupby=[''], start=[0], num=[100])
+ self._MockMethods()
+ self.servlet.ProcessFormData(mr, post_data)
+ self.assertTrue(self.VerifyIssueUpdated(789, local_id_1))
+
+ def testProcessFormData_InvalidOwner(self):
+ """Test PFD rejects invalid owner emails."""
+ local_id_1 = self.services.issue.CreateIssue(
+ self.cnxn, self.services, 789, 'issue summary', 'New', None,
+ [], [], [], [], 111L, 'test issue')
+ mr = testing_helpers.MakeMonorailRequest(
+ project=self.project,
+ perms=permissions.OWNER_ACTIVE_PERMISSIONSET,
+ user_info={'user_id': 111})
+ mr.local_id_list = [local_id_1]
+ post_data = fake.PostData(
+ owner=['invalid'])
+ self.servlet.response = Response()
+ self._MockMethods()
+ self.servlet.ProcessFormData(mr, post_data)
+ self.assertTrue(mr.errors.AnyErrors())
+
+ def testProcessFormData_MoveTo(self):
+ """Test PFD processes move_to values."""
+ local_id_1 = self.services.issue.CreateIssue(
+ self.cnxn, self.services, 789, 'issue to move', 'New', 111L,
+ [], [], [], [], 111L, 'test issue')
+ move_to_project = self.services.project.TestAddProject(
+ name='proj2', project_id=790, owner_ids=[111])
+
+ mr = testing_helpers.MakeMonorailRequest(
+ project=self.project,
+ perms=permissions.OWNER_ACTIVE_PERMISSIONSET,
+ user_info={'user_id': 111})
+ mr.project_name = 'proj'
+ mr.local_id_list = [local_id_1]
+
+ self._MockMethods()
+ post_data = fake.PostData(
+ move_to=['proj2'], can=[1], q=[''],
+ colspec=[''], sort=[''], groupby=[''], start=[0], num=[100])
+ self.servlet.response = Response()
+ self.servlet.ProcessFormData(mr, post_data)
+
+ issue = self.services.issue.GetIssueByLocalID(
+ self.cnxn, move_to_project.project_id, local_id_1)
+ self.assertIsNotNone(issue)
« no previous file with comments | « appengine/monorail/tracker/test/issueattachmenttext_test.py ('k') | appengine/monorail/tracker/test/issuedetail_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698