blob: c7bd1ca0a867d881916cf6d254256ed360c66037 [file] [log] [blame]
# Copyright 2016 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Unittests for monorail.tracker.issuebulkedit."""
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import
import mock
import os
import unittest
import flask
from google.appengine.api import memcache
from google.appengine.ext import testbed
from framework import exceptions
from framework import permissions
from mrproto import project_pb2
from mrproto 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
from tracker import tracker_constants
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(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_memcache_stub()
self.testbed.init_datastore_v3_stub()
self.mocked_methods = {}
def tearDown(self):
"""Restore mocked objects of other modules."""
self.testbed.deactivate()
for obj, items in self.mocked_methods.items():
for member, previous_value in items.items():
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."""
created_issue_1 = fake.MakeTestIssue(
789, 1, 'issue summary', 'New', 0, reporter_id=111)
self.services.issue.TestAddIssue(created_issue_1)
local_id_1 = created_issue_1.local_id
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_CustomFieldEdition(self):
"""Test GPD works in a normal no-corner-cases case."""
created_issue_1 = fake.MakeTestIssue(
789, 1, 'issue summary', 'New', 0, reporter_id=111)
self.services.issue.TestAddIssue(created_issue_1)
local_id_1 = created_issue_1.local_id
mr = testing_helpers.MakeMonorailRequest(
project=self.project, perms=permissions.PermissionSet([]))
mr.local_id_list = [local_id_1]
mr.auth.effective_ids = {222}
fd_not_restricted = tracker_bizobj.MakeFieldDef(
123,
789,
'CPU',
tracker_pb2.FieldTypes.INT_TYPE,
None,
'',
False,
False,
False,
None,
None,
'',
False,
'',
'',
tracker_pb2.NotifyTriggers.NEVER,
'no_action',
'doc',
False,
is_restricted_field=False)
self.config.field_defs.append(fd_not_restricted)
fd_restricted = tracker_bizobj.MakeFieldDef(
124,
789,
'CPU',
tracker_pb2.FieldTypes.INT_TYPE,
None,
'',
False,
False,
False,
None,
None,
'',
False,
'',
'',
tracker_pb2.NotifyTriggers.NEVER,
'no_action',
'doc',
False,
is_restricted_field=True)
self.config.field_defs.append(fd_restricted)
page_data = self.servlet.GatherPageData(mr)
self.assertTrue(page_data['fields'][0].is_editable)
self.assertFalse(page_data['fields'][1].is_editable)
def testGatherPageData_NoIssues(self):
"""Test GPD when no issues are specified in the mr."""
mr = testing_helpers.MakeMonorailRequest(
project=self.project)
self.assertRaises(exceptions.InputException,
self.servlet.GatherPageData, mr)
def testGatherPageData_FilteredIssues(self):
"""Test GPD when all specified issues get filtered out."""
created_issue_1 = fake.MakeTestIssue(
789,
1,
'issue summary',
'New',
0,
reporter_id=111,
labels=['restrict-view-Googler'])
self.services.issue.TestAddIssue(created_issue_1)
local_id_1 = created_issue_1.local_id
mr = testing_helpers.MakeMonorailRequest(
project=self.project)
mr.local_id_list = [local_id_1]
self.assertRaises(Exception, self.servlet.GatherPageData, mr)
def testGatherPageData_TypeLabels(self):
"""Test that GPD displays a custom field for appropriate issues."""
created_issue_1 = fake.MakeTestIssue(
789,
1,
'issue summary',
'New',
0,
reporter_id=111,
labels=['type-customlabels'])
self.services.issue.TestAddIssue(created_issue_1)
local_id_1 = created_issue_1.local_id
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, False, None, None, '', False, '', '',
tracker_pb2.NotifyTriggers.NEVER, 'no_action', 'doc', False)
self.config.field_defs.append(fd)
page_data = self.servlet.GatherPageData(mr)
self.assertEqual(1, len(page_data['fields']))
@mock.patch('framework.cloud_tasks_helpers.create_task')
def testProcessFormData(self, _create_task_mock):
"""Test that PFD works in a normal no-corner-cases case."""
created_issue_1 = fake.MakeTestIssue(
789, 1, 'issue summary', 'New', 111, reporter_id=111)
self.services.issue.TestAddIssue(created_issue_1)
local_id_1 = created_issue_1.local_id
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&q=&saved=1' in url)
def testProcessFormData_FreezeLabels(self):
"""Test that PFD works in a normal no-corner-cases case."""
created_issue_1 = fake.MakeTestIssue(
789, 1, 'issue summary', 'New', 111, reporter_id=111)
self.services.issue.TestAddIssue(created_issue_1)
local_id_1 = created_issue_1.local_id
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],
label=['freeze_new_label'])
self._MockMethods()
self.servlet.response = flask.Response()
self.servlet.ProcessFormData(mr, post_data)
self.assertEqual(
(
"The creation of new labels is blocked for the Chromium project"
" in Monorail. To continue with editing your issue, please"
" remove: freeze_new_label label(s)."), mr.errors.labels)
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 = flask.Response()
self.servlet.ProcessFormData(mr, post_data)
# 400 == bad request
self.assertEqual(400, self.servlet.response.status_code)
def testProcessFormData_NoUser(self):
"""Test PFD 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 = flask.Response()
self.servlet.ProcessFormData(mr, post_data)
# 400 == bad request
self.assertEqual(400, self.servlet.response.status_code)
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 = flask.Response()
self.servlet.ProcessFormData(mr, post_data)
# 400 == bad request
self.assertEqual(400, self.servlet.response.status_code)
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 = flask.Response()
self.servlet.ProcessFormData(mr, post_data)
# 400 == bad request
self.assertEqual(400, self.servlet.response.status_code)
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 = flask.Response()
self.servlet.ProcessFormData(mr, post_data)
# 400 == bad request
self.assertEqual(400, self.servlet.response.status_code)
created_issue_1 = fake.MakeTestIssue(
789, 1, 'issue summary', 'New', 111, reporter_id=111)
self.services.issue.TestAddIssue(created_issue_1)
local_id_1 = created_issue_1.local_id
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 GetFirstAmendment(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]
first_amendment = last_comment.amendments[0]
return first_amendment.field, first_amendment.newvalue
def testProcessFormData_BadUserField(self):
"""Test PFD when a nonexistent user is added as a field value."""
created_issue_1 = fake.MakeTestIssue(
789, 1, 'issue summary', 'New', 111, reporter_id=111)
self.services.issue.TestAddIssue(created_issue_1)
local_id_1 = created_issue_1.local_id
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, 'PM', tracker_pb2.FieldTypes.USER_TYPE, None,
'', False, False, False, None, None, '', False, '', '',
tracker_pb2.NotifyTriggers.NEVER, 'no_action', 'doc', False)
self.config.field_defs.append(fd)
post_data = fake.PostData(
custom_12345=['ghost@gmail.com'], owner=['owner@example.com'], can=[1],
q=[''], colspec=[''], sort=[''], groupby=[''], start=[0], num=[100])
self._MockMethods()
self.servlet.ProcessFormData(mr, post_data)
self.assertEqual('User not found.', mr.errors.custom_fields[0].message)
@mock.patch('framework.cloud_tasks_helpers.create_task')
def testProcessFormData_CustomFields(self, _create_task_mock):
"""Test PFD processes edits to custom fields."""
created_issue_1 = fake.MakeTestIssue(
789, 1, 'issue summary', 'New', 111, reporter_id=111)
self.services.issue.TestAddIssue(created_issue_1)
local_id_1 = created_issue_1.local_id
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, False, None, None, '', False, '', '',
tracker_pb2.NotifyTriggers.NEVER, 'no_action', 'doc', False)
self.config.field_defs.append(fd)
post_data = fake.PostData(
custom_12345=['10'],
owner=['owner@example.com'],
can=[1],
q=[''],
colspec=[''],
sort=[''],
groupby=[''],
start=[0],
num=[100])
self._MockMethods()
self.servlet.ProcessFormData(mr, post_data)
self.assertEqual(
(tracker_pb2.FieldID.CUSTOM, '10'),
self.GetFirstAmendment(789, local_id_1))
@mock.patch('framework.cloud_tasks_helpers.create_task')
def testProcessFormData_RestrictedCustomFieldsAccept(self, _create_task_mock):
"""We accept edits to restricted fields by editors (or admins)."""
created_issue_1 = fake.MakeTestIssue(
789, 1, 'issue summary', 'New', 111, reporter_id=111)
self.services.issue.TestAddIssue(created_issue_1)
local_id_1 = created_issue_1.local_id
mr = testing_helpers.MakeMonorailRequest(
project=self.project,
perms=permissions.PermissionSet(
[
permissions.EDIT_ISSUE, permissions.ADD_ISSUE_COMMENT,
permissions.VIEW
]),
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,
False,
None,
None,
'',
False,
'',
'',
tracker_pb2.NotifyTriggers.NEVER,
'no_action',
'doc',
False,
is_restricted_field=True)
fd.editor_ids = [111]
self.config.field_defs.append(fd)
post_data = fake.PostData(
custom_12345=['10'],
owner=['owner@example.com'],
can=[1],
q=[''],
colspec=[''],
sort=[''],
groupby=[''],
start=[0],
num=[100])
self._MockMethods()
self.servlet.ProcessFormData(mr, post_data)
self.assertEqual(
(tracker_pb2.FieldID.CUSTOM, '10'),
self.GetFirstAmendment(789, local_id_1))
def testProcessFormData_RestrictedCustomFieldsReject(self):
"""We reject edits to restricted fields by non-editors (and non-admins)."""
created_issue_1 = fake.MakeTestIssue(
789, 1, 'issue summary', 'New', 111, reporter_id=111)
self.services.issue.TestAddIssue(created_issue_1)
local_id_1 = created_issue_1.local_id
mr = testing_helpers.MakeMonorailRequest(
project=self.project,
perms=permissions.PermissionSet(
[
permissions.EDIT_ISSUE, permissions.ADD_ISSUE_COMMENT,
permissions.VIEW
]),
user_info={'user_id': 111})
mr.local_id_list = [local_id_1]
fd_int = tracker_bizobj.MakeFieldDef(
11111,
789,
'fd_int',
tracker_pb2.FieldTypes.INT_TYPE,
None,
'',
False,
False,
False,
None,
None,
'',
False,
'',
'',
tracker_pb2.NotifyTriggers.NEVER,
'no_action',
'doc',
False,
is_restricted_field=True)
fd_enum = tracker_bizobj.MakeFieldDef(
44444,
789,
'fdEnum',
tracker_pb2.FieldTypes.ENUM_TYPE,
None,
'',
False,
False,
False,
None,
None,
'',
False,
'',
'',
tracker_pb2.NotifyTriggers.NEVER,
'no_action',
'doc',
False,
is_restricted_field=True)
fd_int.admin_ids = [222]
fd_enum.editor_ids = [333]
self.config.field_defs = [fd_int, fd_enum]
post_data_add_fv = fake.PostData(
custom_11111=['10'],
owner=['owner@example.com'],
can=[1],
q=[''],
colspec=[''],
sort=[''],
groupby=[''],
start=[0],
num=[100])
post_data_rm_fv = fake.PostData(
op_custom_11111=['remove'],
custom_11111=['10'],
owner=['owner@example.com'],
can=[1],
q=[''],
colspec=[''],
sort=[''],
groupby=[''],
start=[0],
num=[100])
post_data_clear_fd = fake.PostData(
op_custom_11111=['clear'],
owner=['owner@example.com'],
can=[1],
q=[''],
colspec=[''],
sort=[''],
groupby=[''],
start=[0],
num=[100])
post_data_label_edits_enum = fake.PostData(
label=['fdEnum-a'],
owner=['owner@example.com'],
can=[1],
q=[''],
colspec=[''],
sort=[''],
groupby=[''],
start=[0],
num=[100])
post_data_label_rm_enum = fake.PostData(
label=['-fdEnum-b'],
owner=['owner@example.com'],
can=[1],
q=[''],
colspec=[''],
sort=[''],
groupby=[''],
start=[0],
num=[100])
self._MockMethods()
self.assertRaises(
AssertionError, self.servlet.ProcessFormData, mr, post_data_add_fv)
self.assertRaises(
AssertionError, self.servlet.ProcessFormData, mr, post_data_rm_fv)
self.assertRaises(
AssertionError, self.servlet.ProcessFormData, mr, post_data_clear_fd)
self.assertRaises(
AssertionError, self.servlet.ProcessFormData, mr,
post_data_label_edits_enum)
self.assertRaises(
AssertionError, self.servlet.ProcessFormData, mr,
post_data_label_rm_enum)
def testProcessFormData_DuplicateStatus_MergeSameIssue(self):
"""Test PFD processes null/cleared status values."""
created_issue_1 = fake.MakeTestIssue(
789, 1, 'issue summary', 'New', 111, reporter_id=111)
self.services.issue.TestAddIssue(created_issue_1)
local_id_1 = created_issue_1.local_id
created_issue_2 = fake.MakeTestIssue(
789, 1, 'issue summary', 'New', 112, reporter_id=112)
self.services.issue.TestAddIssue(created_issue_2)
merge_into_local_id_2 = created_issue_2.local_id
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.assertEqual('Cannot merge issue into itself', mr.errors.merge_into_id)
def testProcessFormData_DuplicateStatus_MergeMissingIssue(self):
"""Test PFD processes null/cleared status values."""
created_issue_1 = fake.MakeTestIssue(
789, 1, 'issue summary', 'New', 111, reporter_id=111)
self.services.issue.TestAddIssue(created_issue_1)
local_id_1 = created_issue_1.local_id
created_issue_2 = fake.MakeTestIssue(
789, 1, 'issue summary2', 'New', 112, reporter_id=112)
self.services.issue.TestAddIssue(created_issue_2)
local_id_2 = created_issue_2.local_id
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.assertEqual('Please enter an issue ID', mr.errors.merge_into_id)
@mock.patch('framework.cloud_tasks_helpers.create_task')
def testProcessFormData_DuplicateStatus_Success(self, _create_task_mock):
"""Test PFD processes null/cleared status values."""
created_issue_1 = fake.MakeTestIssue(
789, 1, 'issue summary', 'New', 111, reporter_id=111)
self.services.issue.TestAddIssue(created_issue_1)
local_id_1 = created_issue_1.local_id
created_issue_2 = fake.MakeTestIssue(
789, 2, 'issue summary2', 'New', 111, reporter_id=111)
self.services.issue.TestAddIssue(created_issue_2)
local_id_2 = created_issue_2.local_id
created_issue_3 = fake.MakeTestIssue(
789, 3, 'issue summary3', 'New', 112, reporter_id=112)
self.services.issue.TestAddIssue(created_issue_3)
merge_into_local_id_3 = created_issue_3.local_id
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 = [113, 120]
self.services.issue_star.SetStar(
mr.cnxn, self.services, None, merge_into_issue.issue_id, 120, 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 = [113, 114]
self.services.issue_star.SetStar(
mr.cnxn, self.services, None, issue_1.issue_id, 113, 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 = [113, 115, 118]
self.services.issue_star.SetStar(
mr.cnxn, self.services, None, issue_2.issue_id, 114, True)
self.services.issue_star.SetStar(
mr.cnxn, self.services, None, issue_2.issue_id, 115, True)
self.servlet.ProcessFormData(mr, post_data)
# Verify both source issues were updated.
self.assertEqual(
(tracker_pb2.FieldID.STATUS, 'Duplicate'),
self.GetFirstAmendment(self.project.project_id, local_id_1))
self.assertEqual(
(tracker_pb2.FieldID.STATUS, 'Duplicate'),
self.GetFirstAmendment(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.assertEqual(
'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.assertEqual(
[113, 120, 111, 114, 115, 118], merge_into_issue.cc_ids)
# Verify new starrers were added to the merge_into issue.
self.assertEqual(4,
self.services.issue_star.CountItemStars(
self.cnxn, merge_into_issue.issue_id))
self.assertEqual([120, 113, 114, 115],
self.services.issue_star.LookupItemStarrers(
self.cnxn, merge_into_issue.issue_id))
@mock.patch('framework.cloud_tasks_helpers.create_task')
def testProcessFormData_ClearStatus(self, _create_task_mock):
"""Test PFD processes null/cleared status values."""
created_issue_1 = fake.MakeTestIssue(
789, 1, 'issue summary', 'New', 111, reporter_id=111)
self.services.issue.TestAddIssue(created_issue_1)
local_id_1 = created_issue_1.local_id
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.assertEqual(
(tracker_pb2.FieldID.STATUS, ''), self.GetFirstAmendment(
789, local_id_1))
def testProcessFormData_InvalidOwner(self):
"""Test PFD rejects invalid owner emails."""
created_issue_1 = fake.MakeTestIssue(
789, 1, 'issue summary', 'New', 0, reporter_id=111)
self.services.issue.TestAddIssue(created_issue_1)
local_id_1 = created_issue_1.local_id
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())
@mock.patch('framework.cloud_tasks_helpers.create_task')
def testProcessFormData_MoveTo(self, _create_task_mock):
"""Test PFD processes move_to values."""
created_issue_1 = fake.MakeTestIssue(
789, 1, 'issue summary', 'New', 111, reporter_id=111)
self.services.issue.TestAddIssue(created_issue_1)
local_id_1 = created_issue_1.local_id
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)
def testProcessFormData_InvalidBlockIssues(self):
"""Test PFD processes invalid blocked_on and blocking values."""
created_issue_1 = fake.MakeTestIssue(
789, 1, 'issue summary', 'New', 111, reporter_id=111)
self.services.issue.TestAddIssue(created_issue_1)
local_id_1 = created_issue_1.local_id
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(
op_blockedonenter=['append'], blocked_on=['12345'],
op_blockingenter=['append'], blocking=['54321'],
can=[1], q=[''],
colspec=[''], sort=[''], groupby=[''], start=[0], num=[100])
self.servlet.ProcessFormData(mr, post_data)
self.assertEqual('Invalid issue ID 12345', mr.errors.blocked_on)
self.assertEqual('Invalid issue ID 54321', mr.errors.blocking)
def testProcessFormData_BlockIssuesOnItself(self):
"""Test PFD processes same issue blocked_on and blocking values."""
created_issue_1 = fake.MakeTestIssue(
789, 1, 'issue summary', 'New', 111, reporter_id=111)
self.services.issue.TestAddIssue(created_issue_1)
local_id_1 = created_issue_1.local_id
created_issue_2 = fake.MakeTestIssue(
789, 1, 'issue summary', 'New', 111, reporter_id=111)
self.services.issue.TestAddIssue(created_issue_2)
local_id_2 = created_issue_2.local_id
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, local_id_2]
self._MockMethods()
post_data = fake.PostData(
op_blockedonenter=['append'], blocked_on=[str(local_id_1)],
op_blockingenter=['append'], blocking=[str(local_id_2)],
can=[1], q=[''],
colspec=[''], sort=[''], groupby=[''], start=[0], num=[100])
self.servlet.ProcessFormData(mr, post_data)
self.assertEqual('Cannot block an issue on itself.', mr.errors.blocked_on)
self.assertEqual('Cannot block an issue on itself.', mr.errors.blocking)
def testProcessFormData_BlockIssuesOnArchivedProject(self):
"""Test PFD processes blocked_on and blocking issues without permissions."""
created_issue_1 = fake.MakeTestIssue(
789, 1, 'issue summary', 'New', 111, reporter_id=111)
self.services.issue.TestAddIssue(created_issue_1)
local_id_1 = created_issue_1.local_id
# Add issue to archived project.
archived_proj = self.services.project.TestAddProject(
name='archived-proj', project_id=789987, owner_ids=[111])
archived_proj.state = project_pb2.ProjectState.ARCHIVED
archived_iid = 2
created_issue_2 = fake.MakeTestIssue(
789987, archived_iid, 'issue summary', 'New', 111, reporter_id=111)
self.services.issue.TestAddIssue(created_issue_2)
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]
global_id = 'archived-proj:2'
self._MockMethods()
post_data = fake.PostData(
op_blockedonenter=['append'],
blocked_on=[global_id],
op_blockingenter=['append'],
blocking=[global_id],
can=[1],
q=[''],
colspec=[''],
sort=[''],
groupby=[''],
start=[0],
num=[100])
self.servlet.ProcessFormData(mr, post_data)
self.assertEqual(
'Target issue %s cannot be modified' % archived_iid,
mr.errors.blocked_on)
self.assertEqual(
'Target issue %s cannot be modified' % archived_iid, mr.errors.blocking)
@mock.patch('framework.cloud_tasks_helpers.create_task')
def testProcessFormData_NormalBlockIssues(self, _create_task_mock):
"""Test PFD processes blocked_on and blocking values."""
created_issue_1 = fake.MakeTestIssue(
789, 1, 'issue summary', 'New', 111, reporter_id=111)
self.services.issue.TestAddIssue(created_issue_1)
local_id_1 = created_issue_1.local_id
created_issueid = fake.MakeTestIssue(
789, 2, 'blocking', 'New', 111, reporter_id=111)
self.services.issue.TestAddIssue(created_issueid)
blocking_id = created_issueid.local_id
created_issueid = fake.MakeTestIssue(
789, 3, 'blocked on', 'New', 111, reporter_id=111)
self.services.issue.TestAddIssue(created_issueid)
blocked_on_id = created_issueid.local_id
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(
op_blockedonenter=['append'], blocked_on=[str(blocked_on_id)],
op_blockingenter=['append'], blocking=[str(blocking_id)],
can=[1], q=[''],
colspec=[''], sort=[''], groupby=[''], start=[0], num=[100])
self.servlet.ProcessFormData(mr, post_data)
self.assertIsNone(mr.errors.blocked_on)
self.assertIsNone(mr.errors.blocking)
def testProcessFormData_TooLongComment(self):
"""Test PFD rejects comments that are too long."""
created_issue_1 = fake.MakeTestIssue(
789, 1, 'issue summary', 'New', 111, reporter_id=111)
self.services.issue.TestAddIssue(created_issue_1)
local_id_1 = created_issue_1.local_id
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],
comment=[' ' + 'c' * tracker_constants.MAX_COMMENT_CHARS + ' '])
self._MockMethods()
self.servlet.ProcessFormData(mr, post_data)
self.assertTrue(mr.errors.AnyErrors())
self.assertEqual('Comment is too long.', mr.errors.comment)