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

Unified Diff: appengine/monorail/tracker/test/issuedetail_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/issuedetail_test.py
diff --git a/appengine/monorail/tracker/test/issuedetail_test.py b/appengine/monorail/tracker/test/issuedetail_test.py
new file mode 100644
index 0000000000000000000000000000000000000000..b001c7da465b873cd4998844fc6e186a239d61ab
--- /dev/null
+++ b/appengine/monorail/tracker/test/issuedetail_test.py
@@ -0,0 +1,565 @@
+# 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.issuedetail."""
+
+import logging
+import mox
+import time
+import unittest
+
+import settings
+from features import notify
+from framework import permissions
+from framework import template_helpers
+from proto import project_pb2
+from proto import tracker_pb2
+from proto import user_pb2
+from services import service_manager
+from services import issue_svc
+from testing import fake
+from testing import testing_helpers
+from tracker import issuedetail
+from tracker import tracker_constants
+from tracker import tracker_helpers
+
+
+class IssueDetailTest(unittest.TestCase):
+
+ def setUp(self):
+ self.cnxn = 'fake cnxn'
+ self.services = service_manager.Services(
+ config=fake.ConfigService(),
+ issue=fake.IssueService(),
+ user=fake.UserService(),
+ project=fake.ProjectService(),
+ issue_star=fake.IssueStarService(),
+ spam=fake.SpamService())
+ self.project = self.services.project.TestAddProject('proj', project_id=987)
+ self.config = tracker_pb2.ProjectIssueConfig()
+ self.config.statuses_offer_merge.append('Duplicate')
+ self.services.config.StoreConfig(self.cnxn, self.config)
+
+ def testChooseNextPage(self):
+ mr = testing_helpers.MakeMonorailRequest(
+ path='/p/proj/issues/detail?id=123&q=term')
+ mr.col_spec = ''
+ config = tracker_pb2.ProjectIssueConfig()
+ issue = fake.MakeTestIssue(987, 123, 'summary', 'New', 111L)
+
+ url = issuedetail._ChooseNextPage(
+ mr, issue.local_id, config, None, None,
+ user_pb2.IssueUpdateNav.UP_TO_LIST, '124')
+ self.assertTrue(url.startswith(
+ 'http://127.0.0.1/p/proj/issues/list?cursor=proj%3A123&q=term'))
+ self.assertTrue(url.endswith('&updated=123'))
+
+ url = issuedetail._ChooseNextPage(
+ mr, issue.local_id, config, None, None,
+ user_pb2.IssueUpdateNav.STAY_SAME_ISSUE, '124')
+ self.assertEqual('http://127.0.0.1/p/proj/issues/detail?id=123&q=term',
+ url)
+
+ url = issuedetail._ChooseNextPage(
+ mr, issue.local_id, config, None, None,
+ user_pb2.IssueUpdateNav.NEXT_IN_LIST, '124')
+ self.assertEqual('http://127.0.0.1/p/proj/issues/detail?id=124&q=term',
+ url)
+
+ # If this is the last in the list, the next_id from the form will be ''.
+ url = issuedetail._ChooseNextPage(
+ mr, issue.local_id, config, None, None,
+ user_pb2.IssueUpdateNav.NEXT_IN_LIST, '')
+ self.assertTrue(url.startswith(
+ 'http://127.0.0.1/p/proj/issues/list?cursor=proj%3A123&q=term'))
+ self.assertTrue(url.endswith('&updated=123'))
+
+ def testChooseNextPage_ForMoveRequest(self):
+ mr = testing_helpers.MakeMonorailRequest(
+ path='/p/proj/issues/detail?id=123&q=term')
+ mr.col_spec = ''
+ config = tracker_pb2.ProjectIssueConfig()
+ issue = fake.MakeTestIssue(987, 123, 'summary', 'New', 111L)
+ moved_to_project_name = 'projB'
+ moved_to_project_local_id = 543
+ moved_to_project_name_and_local_id = (moved_to_project_name,
+ moved_to_project_local_id)
+
+ url = issuedetail._ChooseNextPage(
+ mr, issue.local_id, config, moved_to_project_name_and_local_id, None,
+ user_pb2.IssueUpdateNav.UP_TO_LIST, '124')
+ self.assertTrue(url.startswith(
+ 'http://127.0.0.1/p/proj/issues/list?cursor=proj%3A123&moved_to_id=' +
+ str(moved_to_project_local_id) + '&moved_to_project=' +
+ moved_to_project_name + '&q=term'))
+
+ url = issuedetail._ChooseNextPage(
+ mr, issue.local_id, config, moved_to_project_name_and_local_id, None,
+ user_pb2.IssueUpdateNav.STAY_SAME_ISSUE, '124')
+ self.assertEqual(
+ 'http://127.0.0.1/p/%s/issues/detail?id=123&q=term' % (
+ moved_to_project_name),
+ url)
+ mr.project_name = 'proj' # reset project name back.
+
+ url = issuedetail._ChooseNextPage(
+ mr, issue.local_id, config, moved_to_project_name_and_local_id, None,
+ user_pb2.IssueUpdateNav.NEXT_IN_LIST, '124')
+ self.assertEqual('http://127.0.0.1/p/proj/issues/detail?id=124&q=term',
+ url)
+
+ # If this is the last in the list, the next_id from the form will be ''.
+ url = issuedetail._ChooseNextPage(
+ mr, issue.local_id, config, moved_to_project_name_and_local_id, None,
+ user_pb2.IssueUpdateNav.NEXT_IN_LIST, '')
+ self.assertTrue(url.startswith(
+ 'http://127.0.0.1/p/proj/issues/list?cursor=proj%3A123&moved_to_id=' +
+ str(moved_to_project_local_id) + '&moved_to_project=' +
+ moved_to_project_name + '&q=term'))
+
+ def testChooseNextPage_ForCopyRequest(self):
+ mr = testing_helpers.MakeMonorailRequest(
+ path='/p/proj/issues/detail?id=123&q=term')
+ mr.col_spec = ''
+ config = tracker_pb2.ProjectIssueConfig()
+ issue = fake.MakeTestIssue(987, 123, 'summary', 'New', 111L)
+ copied_to_project_name = 'projB'
+ copied_to_project_local_id = 543
+ copied_to_project_name_and_local_id = (copied_to_project_name,
+ copied_to_project_local_id)
+
+ url = issuedetail._ChooseNextPage(
+ mr, issue.local_id, config, None, copied_to_project_name_and_local_id,
+ user_pb2.IssueUpdateNav.UP_TO_LIST, '124')
+ self.assertTrue(url.startswith(
+ 'http://127.0.0.1/p/proj/issues/list?copied_from_id=123'
+ '&copied_to_id=' + str(copied_to_project_local_id) +
+ '&copied_to_project=' + copied_to_project_name +
+ '&cursor=proj%3A123&q=term'))
+
+ url = issuedetail._ChooseNextPage(
+ mr, issue.local_id, config, None, copied_to_project_name_and_local_id,
+ user_pb2.IssueUpdateNav.STAY_SAME_ISSUE, '124')
+ self.assertEqual('http://127.0.0.1/p/proj/issues/detail?id=123&q=term', url)
+ mr.project_name = 'proj' # reset project name back.
+
+ url = issuedetail._ChooseNextPage(
+ mr, issue.local_id, config, None, copied_to_project_name_and_local_id,
+ user_pb2.IssueUpdateNav.NEXT_IN_LIST, '124')
+ self.assertEqual('http://127.0.0.1/p/proj/issues/detail?id=124&q=term',
+ url)
+
+ # If this is the last in the list, the next_id from the form will be ''.
+ url = issuedetail._ChooseNextPage(
+ mr, issue.local_id, config, None, copied_to_project_name_and_local_id,
+ user_pb2.IssueUpdateNav.NEXT_IN_LIST, '')
+ self.assertTrue(url.startswith(
+ 'http://127.0.0.1/p/proj/issues/list?copied_from_id=123'
+ '&copied_to_id=' + str(copied_to_project_local_id) +
+ '&copied_to_project=' + copied_to_project_name +
+ '&cursor=proj%3A123&q=term'))
+
+ def testGatherHelpData(self):
+ servlet = issuedetail.IssueDetail('req', 'res', services=self.services)
+ mr = testing_helpers.MakeMonorailRequest()
+
+ # User did not jump to an issue, no query at all.
+ help_data = servlet.GatherHelpData(mr, {})
+ self.assertEqual(None, help_data['cue'])
+
+ # User did not jump to an issue, query was not a local ID number.
+ mr.query = 'memory leak'
+ help_data = servlet.GatherHelpData(mr, {})
+ self.assertEqual(None, help_data['cue'])
+
+ # User jumped directly to an issue, maybe they meant to search instead.
+ mr.query = '123'
+ help_data = servlet.GatherHelpData(mr, {})
+ self.assertEqual('search_for_numbers', help_data['cue'])
+ self.assertEqual(123, help_data['jump_local_id'])
+
+
+class IssueDetailFunctionsTest(unittest.TestCase):
+
+ def setUp(self):
+ self.project_name = 'proj'
+ self.project_id = 987
+ self.cnxn = 'fake cnxn'
+ self.services = service_manager.Services(
+ config=fake.ConfigService(),
+ issue=fake.IssueService(),
+ issue_star=fake.IssueStarService(),
+ project=fake.ProjectService(),
+ user=fake.UserService())
+ self.project = self.services.project.TestAddProject(
+ 'proj', project_id=987, committer_ids=[111L])
+ self.servlet = issuedetail.IssueDetail(
+ 'req', 'res', services=self.services)
+ self.mox = mox.Mox()
+
+ def tearDown(self):
+ self.mox.UnsetStubs()
+ self.mox.ResetAll()
+
+ def VerifyShouldShowFlipper(
+ self, expected, query, sort_spec, can, create_issues=0):
+ """Instantiate a _Flipper and check if makes a pipeline or not."""
+ services = service_manager.Services(
+ config=fake.ConfigService(),
+ issue=fake.IssueService(),
+ project=fake.ProjectService(),
+ user=fake.UserService())
+ mr = testing_helpers.MakeMonorailRequest(project=self.project)
+ mr.query = query
+ mr.sort_spec = sort_spec
+ mr.can = can
+ mr.project_name = self.project.project_name
+ mr.project = self.project
+
+ for idx in range(create_issues):
+ _local_id = services.issue.CreateIssue(
+ self.cnxn, services, self.project.project_id,
+ 'summary_%d' % idx, 'status', 111L, [], [], [], [], 111L,
+ 'description_%d' % idx)
+
+ self.assertEqual(
+ expected,
+ issuedetail._ShouldShowFlipper(mr, services))
+
+ def testShouldShowFlipper_RegularSizedProject(self):
+ # If the user is looking for a specific issue, no flipper.
+ self.VerifyShouldShowFlipper(
+ False, '123', '', tracker_constants.OPEN_ISSUES_CAN)
+ self.VerifyShouldShowFlipper(False, '123', '', 5)
+ self.VerifyShouldShowFlipper(
+ False, '123', 'priority', tracker_constants.OPEN_ISSUES_CAN)
+
+ # If the user did a search or sort or all in a small can, show flipper.
+ self.VerifyShouldShowFlipper(
+ True, 'memory leak', '', tracker_constants.OPEN_ISSUES_CAN)
+ self.VerifyShouldShowFlipper(
+ True, 'id=1,2,3', '', tracker_constants.OPEN_ISSUES_CAN)
+ # Any can other than 1 or 2 is doing a query and so it should have a
+ # failry narrow result set size. 5 is issues starred by me.
+ self.VerifyShouldShowFlipper(True, '', '', 5)
+ self.VerifyShouldShowFlipper(
+ True, '', 'status', tracker_constants.OPEN_ISSUES_CAN)
+
+ # In a project without a huge number of issues, still show the flipper even
+ # if there was no specific query.
+ self.VerifyShouldShowFlipper(
+ True, '', '', tracker_constants.OPEN_ISSUES_CAN)
+
+ def testShouldShowFlipper_LargeSizedProject(self):
+ settings.threshold_to_suppress_prev_next = 1
+
+ # In a project that has tons of issues, save time by not showing the
+ # flipper unless there was a specific query, sort, or can.
+ self.VerifyShouldShowFlipper(
+ False, '', '', tracker_constants.ALL_ISSUES_CAN, create_issues=3)
+ self.VerifyShouldShowFlipper(
+ False, '', '', tracker_constants.OPEN_ISSUES_CAN, create_issues=3)
+
+ def testFieldEditPermitted_NoEdit(self):
+ page_perms = testing_helpers.Blank(
+ EditIssueSummary=False, EditIssueStatus=False, EditIssueOwner=False,
+ EditIssueCc=False) # no perms are needed.
+ self.assertTrue(issuedetail._FieldEditPermitted(
+ [], '', '', '', '', 0, [], page_perms))
+
+ def testFieldEditPermitted_AllNeededPerms(self):
+ page_perms = testing_helpers.Blank(
+ EditIssueSummary=True, EditIssueStatus=True, EditIssueOwner=True,
+ EditIssueCc=True)
+ self.assertTrue(issuedetail._FieldEditPermitted(
+ [], '', '', 'new sum', 'new status', 111L, [222L], page_perms))
+
+ def testFieldEditPermitted_MissingPerms(self):
+ page_perms = testing_helpers.Blank(
+ EditIssueSummary=False, EditIssueStatus=False, EditIssueOwner=False,
+ EditIssueCc=False) # no perms.
+ self.assertFalse(issuedetail._FieldEditPermitted(
+ [], '', '', 'new sum', '', 0, [], page_perms))
+ self.assertFalse(issuedetail._FieldEditPermitted(
+ [], '', '', '', 'new status', 0, [], page_perms))
+ self.assertFalse(issuedetail._FieldEditPermitted(
+ [], '', '', '', '', 111L, [], page_perms))
+ self.assertFalse(issuedetail._FieldEditPermitted(
+ [], '', '', '', '', 0, [222L], page_perms))
+
+ def testFieldEditPermitted_NeededPermsNotOffered(self):
+ """Even if user has all the field-level perms, they still can't do this."""
+ page_perms = testing_helpers.Blank(
+ EditIssueSummary=True, EditIssueStatus=True, EditIssueOwner=True,
+ EditIssueCc=True)
+ self.assertFalse(issuedetail._FieldEditPermitted(
+ ['NewLabel'], '', '', '', '', 0, [], page_perms))
+ self.assertFalse(issuedetail._FieldEditPermitted(
+ [], 'new blocked on', '', '', '', 0, [], page_perms))
+ self.assertFalse(issuedetail._FieldEditPermitted(
+ [], '', 'new blocking', '', '', 0, [], page_perms))
+
+ def testValidateOwner_ChangedToValidOwner(self):
+ post_data_owner = 'superman@krypton.com'
+ parsed_owner_id = 111
+ original_issue_owner_id = 111
+ mr = testing_helpers.MakeMonorailRequest(project=self.project)
+
+ self.mox.StubOutWithMock(tracker_helpers, 'IsValidIssueOwner')
+ tracker_helpers.IsValidIssueOwner(
+ mr.cnxn, mr.project, parsed_owner_id, self.services).AndReturn(
+ (True, ''))
+ self.mox.ReplayAll()
+
+ ret = self.servlet._ValidateOwner(
+ mr, post_data_owner, parsed_owner_id, original_issue_owner_id)
+ self.mox.VerifyAll()
+ self.assertIsNone(ret)
+
+ def testValidateOwner_UnchangedInvalidOwner(self):
+ post_data_owner = 'superman@krypton.com'
+ parsed_owner_id = 111
+ original_issue_owner_id = 111
+ mr = testing_helpers.MakeMonorailRequest(project=self.project)
+ self.services.user.TestAddUser(post_data_owner, original_issue_owner_id)
+
+ self.mox.StubOutWithMock(tracker_helpers, 'IsValidIssueOwner')
+ tracker_helpers.IsValidIssueOwner(
+ mr.cnxn, mr.project, parsed_owner_id, self.services).AndReturn(
+ (False, 'invalid owner'))
+ self.mox.ReplayAll()
+
+ ret = self.servlet._ValidateOwner(
+ mr, post_data_owner, parsed_owner_id, original_issue_owner_id)
+ self.mox.VerifyAll()
+ self.assertIsNone(ret)
+
+ def testValidateOwner_ChangedFromValidToInvalidOwner(self):
+ post_data_owner = 'lexluthor'
+ parsed_owner_id = 111
+ original_issue_owner_id = 111
+ original_issue_owner = 'superman@krypton.com'
+ mr = testing_helpers.MakeMonorailRequest(project=self.project)
+ self.services.user.TestAddUser(original_issue_owner,
+ original_issue_owner_id)
+
+ self.mox.StubOutWithMock(tracker_helpers, 'IsValidIssueOwner')
+ tracker_helpers.IsValidIssueOwner(
+ mr.cnxn, mr.project, parsed_owner_id, self.services).AndReturn(
+ (False, 'invalid owner'))
+ self.mox.ReplayAll()
+
+ ret = self.servlet._ValidateOwner(
+ mr, post_data_owner, parsed_owner_id, original_issue_owner_id)
+ self.mox.VerifyAll()
+ self.assertEquals('invalid owner', ret)
+
+ def testProcessFormData_NoPermission(self):
+ """Anonymous users and users without ADD_ISSUE_COMMENT cannot comment."""
+ local_id_1 = self.services.issue.CreateIssue(
+ self.cnxn, self.services, self.project.project_id,
+ 'summary_1', 'status', 111L, [], [], [], [], 111L, 'description_1')
+ _, mr = testing_helpers.GetRequestObjects(
+ project=self.project,
+ perms=permissions.CONTRIBUTOR_INACTIVE_PERMISSIONSET)
+ mr.auth.user_id = 0
+ mr.local_id = local_id_1
+ self.assertRaises(permissions.PermissionException,
+ self.servlet.ProcessFormData, mr, {})
+ mr.auth.user_id = 111L
+ self.assertRaises(permissions.PermissionException,
+ self.servlet.ProcessFormData, mr, {})
+
+ def testProcessFormData_NonMembersCantEdit(self):
+ """Non-members can comment, but never affect issue fields."""
+ orig_prepsend = notify.PrepareAndSendIssueChangeNotification
+ notify.PrepareAndSendIssueChangeNotification = lambda *args, **kwargs: None
+
+ local_id_1 = self.services.issue.CreateIssue(
+ self.cnxn, self.services, self.project.project_id,
+ 'summary_1', 'status', 111L, [], [], [], [], 111L, 'description_1')
+ local_id_2 = self.services.issue.CreateIssue(
+ self.cnxn, self.services, self.project.project_id,
+ 'summary_2', 'status', 111L, [], [], [], [], 111L, 'description_2')
+
+ _amendments, _cmnt_pb = self.services.issue.ApplyIssueComment(
+ self.cnxn, self.services, 111L,
+ self.project.project_id, local_id_2, 'summary', 'Duplicate', 111L,
+ [], [], [], [], [], [], [], [], local_id_1,
+ comment='closing as a dup of 1')
+
+ non_member_user_id = 999L
+ post_data = fake.PostData({
+ 'merge_into': [''], # non-member tries to remove merged_into
+ 'comment': ['thanks!'],
+ 'can': ['1'],
+ 'q': ['foo'],
+ 'colspec': ['bar'],
+ 'sort': 'baz',
+ 'groupby': 'qux',
+ 'start': ['0'],
+ 'num': ['100'],
+ 'pagegen': [str(int(time.time()) + 1)],
+ })
+
+ _, mr = testing_helpers.GetRequestObjects(
+ user_info={'user_id': non_member_user_id},
+ path='/p/proj/issues/detail.do?id=%d' % local_id_2,
+ project=self.project, method='POST',
+ perms=permissions.USER_PERMISSIONSET)
+ mr.project_name = self.project.project_name
+ mr.project = self.project
+
+ # The form should be processed and redirect back to viewing the issue.
+ redirect_url = self.servlet.ProcessFormData(mr, post_data)
+ self.assertTrue(redirect_url.startswith(
+ 'http://127.0.0.1/p/proj/issues/detail?id=%d' % local_id_2))
+
+ # BUT, issue should not have been edited because user lacked permission.
+ updated_issue_2 = self.services.issue.GetIssueByLocalID(
+ self.cnxn, self.project.project_id, local_id_2)
+ self.assertEqual(local_id_1, updated_issue_2.merged_into)
+
+ notify.PrepareAndSendIssueChangeNotification = orig_prepsend
+
+ def testProcessFormData_DuplicateAddsACommentToTarget(self):
+ """Marking issue 2 as dup of 1 adds a comment to 1."""
+ orig_prepsend = notify.PrepareAndSendIssueChangeNotification
+ notify.PrepareAndSendIssueChangeNotification = lambda *args, **kwargs: None
+ orig_get_starrers = tracker_helpers.GetNewIssueStarrers
+ tracker_helpers.GetNewIssueStarrers = lambda *args, **kwargs: []
+
+ local_id_1 = self.services.issue.CreateIssue(
+ self.cnxn, self.services, self.project.project_id,
+ 'summary_1', 'New', 111L, [], [], [], [], 111L, 'description_1')
+ issue_1 = self.services.issue.GetIssueByLocalID(
+ self.cnxn, self.project.project_id, local_id_1)
+ issue_1.project_name = 'proj'
+ local_id_2 = self.services.issue.CreateIssue(
+ self.cnxn, self.services, self.project.project_id,
+ 'summary_2', 'New', 111L, [], [], [], [], 111L, 'description_2')
+ issue_2 = self.services.issue.GetIssueByLocalID(
+ self.cnxn, self.project.project_id, local_id_2)
+ issue_2.project_name = 'proj'
+
+ post_data = fake.PostData({
+ 'status': ['Duplicate'],
+ 'merge_into': [str(local_id_1)],
+ 'comment': ['marking as dup'],
+ 'can': ['1'],
+ 'q': ['foo'],
+ 'colspec': ['bar'],
+ 'sort': 'baz',
+ 'groupby': 'qux',
+ 'start': ['0'],
+ 'num': ['100'],
+ 'pagegen': [str(int(time.time()) + 1)],
+ })
+
+ member_user_id = 111L
+ _, mr = testing_helpers.GetRequestObjects(
+ user_info={'user_id': member_user_id},
+ path='/p/proj/issues/detail.do?id=%d' % local_id_2,
+ project=self.project, method='POST',
+ perms=permissions.COMMITTER_ACTIVE_PERMISSIONSET)
+ mr.project_name = self.project.project_name
+ mr.project = self.project
+
+ # The form should be processed and redirect back to viewing the issue.
+ self.servlet.ProcessFormData(mr, post_data)
+
+ self.assertEqual('Duplicate', issue_2.status)
+ self.assertEqual(issue_1.issue_id, issue_2.merged_into)
+ comments_1 = self.services.issue.GetCommentsForIssue(
+ self.cnxn, issue_1.issue_id)
+ self.assertEqual(2, len(comments_1))
+ self.assertEqual(
+ 'Issue 2 has been merged into this issue.',
+ comments_1[1].content)
+
+ # Making another comment on issue 2 does not affect issue 1.
+ self.servlet.ProcessFormData(mr, post_data)
+ comments_1 = self.services.issue.GetCommentsForIssue(
+ self.cnxn, issue_1.issue_id)
+ self.assertEqual(2, len(comments_1))
+
+ notify.PrepareAndSendIssueChangeNotification = orig_prepsend
+ tracker_helpers.GetNewIssueStarrers = orig_get_starrers
+
+ # TODO(jrobbins): add more unit tests for other aspects of ProcessForm.
+
+
+class SetStarFormTest(unittest.TestCase):
+
+ def setUp(self):
+ self.cnxn = 'fake cnxn'
+ self.services = service_manager.Services(
+ config=fake.ConfigService(),
+ issue=fake.IssueService(),
+ user=fake.UserService(),
+ project=fake.ProjectService(),
+ issue_star=fake.IssueStarService())
+ self.project = self.services.project.TestAddProject('proj', project_id=987)
+ self.servlet = issuedetail.SetStarForm(
+ 'req', 'res', services=self.services)
+
+ def testAssertBasePermission(self):
+ """Only users with SET_STAR could set star."""
+ local_id_1 = self.services.issue.CreateIssue(
+ self.cnxn, self.services, self.project.project_id,
+ 'summary_1', 'status', 111L, [], [], [], [], 111L, 'description_1')
+ _, mr = testing_helpers.GetRequestObjects(
+ project=self.project,
+ perms=permissions.READ_ONLY_PERMISSIONSET)
+ mr.local_id = local_id_1
+ self.assertRaises(permissions.PermissionException,
+ self.servlet.AssertBasePermission, mr)
+ _, mr = testing_helpers.GetRequestObjects(
+ project=self.project,
+ perms=permissions.CONTRIBUTOR_ACTIVE_PERMISSIONSET)
+ mr.local_id = local_id_1
+ self.servlet.AssertBasePermission(mr)
+
+
+class IssueCommentDeletionTest(unittest.TestCase):
+
+ def setUp(self):
+ self.cnxn = 'fake cnxn'
+ self.services = service_manager.Services(
+ config=fake.ConfigService(),
+ issue=fake.IssueService(),
+ user=fake.UserService(),
+ project=fake.ProjectService(),
+ issue_star=fake.IssueStarService())
+ self.project = self.services.project.TestAddProject('proj', project_id=987)
+ self.servlet = issuedetail.IssueCommentDeletion(
+ 'req', 'res', services=self.services)
+
+ def testProcessFormData_Permission(self):
+ """Permit users who can delete."""
+ local_id_1 = self.services.issue.CreateIssue(
+ self.cnxn, self.services, self.project.project_id,
+ 'summary_1', 'status', 111L, [], [], [], [], 111L, 'description_1')
+ _, mr = testing_helpers.GetRequestObjects(
+ project=self.project,
+ perms=permissions.READ_ONLY_PERMISSIONSET)
+ mr.local_id = local_id_1
+ mr.auth.user_id = 222L
+ post_data = {
+ 'id': local_id_1,
+ 'sequence_num': 0,
+ 'mode': 0}
+ self.assertRaises(permissions.PermissionException,
+ self.servlet.ProcessFormData, mr, post_data)
+ _, mr = testing_helpers.GetRequestObjects(
+ project=self.project,
+ perms=permissions.OWNER_ACTIVE_PERMISSIONSET)
+ mr.local_id = local_id_1
+ mr.auth.user_id = 222L
+ self.servlet.ProcessFormData(mr, post_data)
+
+
+if __name__ == '__main__':
+ unittest.main()
« no previous file with comments | « appengine/monorail/tracker/test/issuebulkedit_test.py ('k') | appengine/monorail/tracker/test/issueentry_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698