Index: appengine/monorail/tracker/test/issueadmin_test.py |
diff --git a/appengine/monorail/tracker/test/issueadmin_test.py b/appengine/monorail/tracker/test/issueadmin_test.py |
new file mode 100644 |
index 0000000000000000000000000000000000000000..2a923e0ac1051484281d28bb5fb3028a9861a618 |
--- /dev/null |
+++ b/appengine/monorail/tracker/test/issueadmin_test.py |
@@ -0,0 +1,400 @@ |
+# 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 |
+ |
+"""Tests for the issue admin pages.""" |
+ |
+import mox |
+import unittest |
+ |
+from framework import permissions |
+from framework import urls |
+from services import service_manager |
+from testing import fake |
+from testing import testing_helpers |
+from tracker import issueadmin |
+from tracker import tracker_bizobj |
+from tracker import tracker_constants |
+ |
+ |
+class TestBase(unittest.TestCase): |
+ |
+ def setUpServlet(self, servlet_factory): |
+ # pylint: disable=attribute-defined-outside-init |
+ self.services = service_manager.Services( |
+ project=fake.ProjectService(), |
+ config=fake.ConfigService(), |
+ user=fake.UserService(), |
+ issue=fake.IssueService(), |
+ features=fake.FeaturesService()) |
+ self.servlet = servlet_factory('req', 'res', services=self.services) |
+ self.project = self.services.project.TestAddProject('proj', project_id=789) |
+ self.config = tracker_bizobj.MakeDefaultProjectIssueConfig(789) |
+ self.services.config.StoreConfig(None, self.config) |
+ self.cnxn = fake.MonorailConnection() |
+ self.mr = testing_helpers.MakeMonorailRequest( |
+ path='/p/proj/admin', project=self.project) |
+ self.mox = mox.Mox() |
+ |
+ def tearDown(self): |
+ self.mox.UnsetStubs() |
+ self.mox.ResetAll() |
+ |
+ def _mockGetUser(self): |
+ self.mox.StubOutWithMock(self.services.user, 'GetUser') |
+ user = self.services.user.TestAddUser('user@invalid', 100) |
+ self.services.user.GetUser( |
+ mox.IgnoreArg(), mox.IgnoreArg()).MultipleTimes().AndReturn(user) |
+ |
+ |
+class IssueAdminBaseTest(TestBase): |
+ |
+ def setUp(self): |
+ super(IssueAdminBaseTest, self).setUpServlet(issueadmin.IssueAdminBase) |
+ |
+ def testGatherPageData(self): |
+ self._mockGetUser() |
+ self.mox.ReplayAll() |
+ page_data = self.servlet.GatherPageData(self.mr) |
+ self.mox.VerifyAll() |
+ |
+ self.assertItemsEqual(['admin_tab_mode', 'config'], page_data.keys()) |
+ config_view = page_data['config'] |
+ self.assertEqual(789, config_view.project_id) |
+ |
+ |
+class AdminStatusesTest(TestBase): |
+ |
+ def setUp(self): |
+ super(AdminStatusesTest, self).setUpServlet(issueadmin.AdminStatuses) |
+ |
+ def testProcessSubtabForm_MissingInput(self): |
+ post_data = fake.PostData() |
+ next_url = self.servlet.ProcessSubtabForm(post_data, self.mr) |
+ self.assertEqual(urls.ADMIN_STATUSES, next_url) |
+ self.assertEqual([], self.config.well_known_statuses) |
+ self.assertEqual([], self.config.statuses_offer_merge) |
+ |
+ def testProcessSubtabForm_EmptyInput(self): |
+ post_data = fake.PostData( |
+ predefinedopen=[''], predefinedclosed=[''], statuses_offer_merge=['']) |
+ next_url = self.servlet.ProcessSubtabForm(post_data, self.mr) |
+ self.assertEqual(urls.ADMIN_STATUSES, next_url) |
+ self.assertEqual([], self.config.well_known_statuses) |
+ self.assertEqual([], self.config.statuses_offer_merge) |
+ |
+ def testProcessSubtabForm_Normal(self): |
+ post_data = fake.PostData( |
+ predefinedopen=['New = newly reported'], |
+ predefinedclosed=['Fixed\nDuplicate'], |
+ statuses_offer_merge=['Duplicate']) |
+ next_url = self.servlet.ProcessSubtabForm(post_data, self.mr) |
+ self.assertEqual(urls.ADMIN_STATUSES, next_url) |
+ self.assertEqual(3, len(self.config.well_known_statuses)) |
+ self.assertEqual('New', self.config.well_known_statuses[0].status) |
+ self.assertTrue(self.config.well_known_statuses[0].means_open) |
+ self.assertEqual('Fixed', self.config.well_known_statuses[1].status) |
+ self.assertFalse(self.config.well_known_statuses[1].means_open) |
+ self.assertEqual('Duplicate', self.config.well_known_statuses[2].status) |
+ self.assertFalse(self.config.well_known_statuses[2].means_open) |
+ self.assertEqual(['Duplicate'], self.config.statuses_offer_merge) |
+ |
+ |
+class AdminLabelsTest(TestBase): |
+ |
+ def setUp(self): |
+ super(AdminLabelsTest, self).setUpServlet(issueadmin.AdminLabels) |
+ |
+ def testGatherPageData(self): |
+ self._mockGetUser() |
+ self.mox.ReplayAll() |
+ page_data = self.servlet.GatherPageData(self.mr) |
+ self.mox.VerifyAll() |
+ |
+ self.assertItemsEqual( |
+ ['admin_tab_mode', 'config', 'field_defs'], page_data.keys()) |
+ config_view = page_data['config'] |
+ self.assertEqual(789, config_view.project_id) |
+ self.assertEqual([], page_data['field_defs']) |
+ |
+ def testProcessSubtabForm_MissingInput(self): |
+ post_data = fake.PostData() |
+ next_url = self.servlet.ProcessSubtabForm(post_data, self.mr) |
+ self.assertEqual(urls.ADMIN_LABELS, next_url) |
+ self.assertEqual([], self.config.well_known_labels) |
+ self.assertEqual([], self.config.exclusive_label_prefixes) |
+ |
+ def testProcessSubtabForm_EmptyInput(self): |
+ post_data = fake.PostData( |
+ predefinedlabels=[''], excl_prefixes=['']) |
+ next_url = self.servlet.ProcessSubtabForm(post_data, self.mr) |
+ self.assertEqual(urls.ADMIN_LABELS, next_url) |
+ self.assertEqual([], self.config.well_known_labels) |
+ self.assertEqual([], self.config.exclusive_label_prefixes) |
+ |
+ def testProcessSubtabForm_Normal(self): |
+ post_data = fake.PostData( |
+ predefinedlabels=['Pri-0 = Burning issue\nPri-4 = It can wait'], |
+ excl_prefixes=['pri']) |
+ next_url = self.servlet.ProcessSubtabForm(post_data, self.mr) |
+ self.assertEqual(urls.ADMIN_LABELS, next_url) |
+ self.assertEqual(2, len(self.config.well_known_labels)) |
+ self.assertEqual('Pri-0', self.config.well_known_labels[0].label) |
+ self.assertEqual('Pri-4', self.config.well_known_labels[1].label) |
+ self.assertEqual(['pri'], self.config.exclusive_label_prefixes) |
+ |
+ |
+class AdminTemplatesTest(TestBase): |
+ |
+ def setUp(self): |
+ super(AdminTemplatesTest, self).setUpServlet(issueadmin.AdminTemplates) |
+ self.test_template = tracker_bizobj.MakeIssueTemplate( |
+ 'Test Template', 'sum', 'New', 111L, 'content', [], [], [], []) |
+ self.test_template.template_id = 12345 |
+ |
+ def testGatherPageData(self): |
+ self._mockGetUser() |
+ self.mox.ReplayAll() |
+ page_data = self.servlet.GatherPageData(self.mr) |
+ self.mox.VerifyAll() |
+ |
+ self.assertItemsEqual( |
+ ['admin_tab_mode', 'config', 'fields'], page_data.keys()) |
+ config_view = page_data['config'] |
+ self.assertEqual(789, config_view.project_id) |
+ self.assertEqual([], page_data['fields']) |
+ |
+ def testProcessSubtabForm_NoEditProjectPerm(self): |
+ """If user lacks perms, ignore the attempt to set default templates.""" |
+ self.config.templates.append(self.test_template) |
+ post_data = fake.PostData( |
+ default_template_for_developers=['Test Template'], |
+ default_template_for_users=['Test Template']) |
+ self.servlet._ParseAllTemplates = lambda x, y: self.config.templates |
+ self.mr.perms = permissions.EMPTY_PERMISSIONSET |
+ next_url = self.servlet.ProcessSubtabForm(post_data, self.mr) |
+ self.assertEqual(urls.ADMIN_TEMPLATES, next_url) |
+ self.assertEqual(0, self.config.default_template_for_developers) |
+ self.assertEqual(0, self.config.default_template_for_users) |
+ |
+ def testProcessSubtabForm_Normal(self): |
+ """If user lacks perms, ignore the attempt to set default templates.""" |
+ self.config.templates.append(self.test_template) |
+ post_data = fake.PostData( |
+ default_template_for_developers=['Test Template'], |
+ default_template_for_users=['Test Template']) |
+ self.servlet._ParseAllTemplates = lambda x, y: self.config.templates |
+ next_url = self.servlet.ProcessSubtabForm(post_data, self.mr) |
+ self.assertEqual(urls.ADMIN_TEMPLATES, next_url) |
+ self.assertEqual(12345, self.config.default_template_for_developers) |
+ self.assertEqual(12345, self.config.default_template_for_users) |
+ |
+ def testParseTemplate(self): |
+ pass # TODO(jrobbins): write this |
+ |
+ def testParseDefaultTempalteSelections_NotSpecified(self): |
+ self.config.templates.append(self.test_template) |
+ post_data = fake.PostData() |
+ for_devs, for_users = self.servlet._ParseDefaultTemplateSelections( |
+ post_data, self.config.tempaltes) |
+ self.assertEqual(None, for_devs) |
+ self.assertEqual(None, for_users) |
+ |
+ def testParseDefaultTempalteSelections_NotSpecified(self): |
+ self.config.templates.append(self.test_template) |
+ post_data = fake.PostData( |
+ default_template_for_developers=['Bad value'], |
+ default_template_for_users=['Bad value']) |
+ for_devs, for_users = self.servlet._ParseDefaultTemplateSelections( |
+ post_data, self.config.templates) |
+ self.assertEqual(None, for_devs) |
+ self.assertEqual(None, for_users) |
+ |
+ def testParseDefaultTempalteSelections_Normal(self): |
+ self.config.templates.append(self.test_template) |
+ post_data = fake.PostData( |
+ default_template_for_developers=['Test Template'], |
+ default_template_for_users=['Test Template']) |
+ for_devs, for_users = self.servlet._ParseDefaultTemplateSelections( |
+ post_data, self.config.templates) |
+ self.assertEqual(12345, for_devs) |
+ self.assertEqual(12345, for_users) |
+ |
+ |
+ |
+class AdminComponentsTest(TestBase): |
+ |
+ def setUp(self): |
+ super(AdminComponentsTest, self).setUpServlet(issueadmin.AdminComponents) |
+ self.cd_clean = tracker_bizobj.MakeComponentDef( |
+ 1, self.project.project_id, 'BackEnd', 'doc', False, [], [111L], 100000, |
+ 122L, 10000000, 133L) |
+ self.cd_with_subcomp = tracker_bizobj.MakeComponentDef( |
+ 2, self.project.project_id, 'FrontEnd', 'doc', False, [], [111L], |
+ 100000, 122L, 10000000, 133L) |
+ self.subcd = tracker_bizobj.MakeComponentDef( |
+ 3, self.project.project_id, 'FrontEnd>Worker', 'doc', False, [], [111L], |
+ 100000, 122L, 10000000, 133L) |
+ self.cd_with_template = tracker_bizobj.MakeComponentDef( |
+ 4, self.project.project_id, 'Middle', 'doc', False, [], [111L], |
+ 100000, 122L, 10000000, 133L) |
+ |
+ def testGatherPageData(self): |
+ self._mockGetUser() |
+ self.mox.ReplayAll() |
+ page_data = self.servlet.GatherPageData(self.mr) |
+ self.mox.VerifyAll() |
+ |
+ self.assertItemsEqual( |
+ ['admin_tab_mode', 'config', 'component_defs', |
+ 'failed_perm', 'failed_subcomp', 'failed_templ'], page_data.keys()) |
+ config_view = page_data['config'] |
+ self.assertEqual(789, config_view.project_id) |
+ self.assertEqual([], page_data['component_defs']) |
+ |
+ def testProcessFormData_NoErrors(self): |
+ self.config.component_defs = [ |
+ self.cd_clean, self.cd_with_subcomp, self.subcd, self.cd_with_template] |
+ post_data = { |
+ 'delete_components' : '%s,%s,%s' % ( |
+ self.cd_clean.path, self.cd_with_subcomp.path, self.subcd.path)} |
+ url = self.servlet.ProcessFormData(self.mr, post_data) |
+ self.assertTrue( |
+ url.startswith('http://127.0.0.1/p/proj/adminComponents?deleted=' |
+ 'FrontEnd%3EWorker%2CFrontEnd%2CBackEnd&failed_perm=&' |
+ 'failed_subcomp=&failed_templ=&ts=')) |
+ |
+ def testProcessFormData_SubCompError(self): |
+ self.config.component_defs = [ |
+ self.cd_clean, self.cd_with_subcomp, self.subcd, self.cd_with_template] |
+ post_data = { |
+ 'delete_components' : '%s,%s' % ( |
+ self.cd_clean.path, self.cd_with_subcomp.path)} |
+ url = self.servlet.ProcessFormData(self.mr, post_data) |
+ self.assertTrue( |
+ url.startswith('http://127.0.0.1/p/proj/adminComponents?deleted=' |
+ 'BackEnd&failed_perm=&failed_subcomp=FrontEnd&' |
+ 'failed_templ=&ts=')) |
+ |
+ def testProcessFormData_TemplateError(self): |
+ self.config.component_defs = [ |
+ self.cd_clean, self.cd_with_subcomp, self.subcd, self.cd_with_template] |
+ self.services.config.component_ids_to_templates[4] = 'Test Template' |
+ post_data = { |
+ 'delete_components' : '%s,%s,%s,%s' % ( |
+ self.cd_clean.path, self.cd_with_subcomp.path, self.subcd.path, |
+ self.cd_with_template.path)} |
+ url = self.servlet.ProcessFormData(self.mr, post_data) |
+ self.assertTrue( |
+ url.startswith('http://127.0.0.1/p/proj/adminComponents?deleted=' |
+ 'FrontEnd%3EWorker%2CFrontEnd%2CBackEnd&failed_perm=&' |
+ 'failed_subcomp=&failed_templ=Middle&ts=')) |
+ |
+ |
+class AdminViewsTest(TestBase): |
+ |
+ def setUp(self): |
+ super(AdminViewsTest, self).setUpServlet(issueadmin.AdminViews) |
+ |
+ def testGatherPageData(self): |
+ self._mockGetUser() |
+ self.mox.ReplayAll() |
+ page_data = self.servlet.GatherPageData(self.mr) |
+ self.mox.VerifyAll() |
+ |
+ self.assertItemsEqual( |
+ ['admin_tab_mode', 'config', 'issue_notify', |
+ 'new_query_indexes', 'max_queries'], |
+ page_data.keys()) |
+ config_view = page_data['config'] |
+ self.assertEqual(789, config_view.project_id) |
+ |
+ def testProcessSubtabForm(self): |
+ post_data = fake.PostData( |
+ default_col_spec=['id pri mstone owner status summary'], |
+ default_sort_spec=['mstone pri'], |
+ default_x_attr=['owner'], default_y_attr=['mstone']) |
+ next_url = self.servlet.ProcessSubtabForm(post_data, self.mr) |
+ self.assertEqual(urls.ADMIN_VIEWS, next_url) |
+ self.assertEqual( |
+ 'id pri mstone owner status summary', self.config.default_col_spec) |
+ self.assertEqual('mstone pri', self.config.default_sort_spec) |
+ self.assertEqual('owner', self.config.default_x_attr) |
+ self.assertEqual('mstone', self.config.default_y_attr) |
+ |
+ |
+class AdminViewsFunctionsTest(unittest.TestCase): |
+ |
+ def testParseListPreferences(self): |
+ # If no input, col_spec will be default column spec. |
+ # For other fiels empty strings should be returned. |
+ col_spec, sort_spec, x_attr, y_attr = issueadmin._ParseListPreferences( |
+ {}) |
+ self.assertEqual(tracker_constants.DEFAULT_COL_SPEC, col_spec) |
+ self.assertEqual('', sort_spec) |
+ self.assertEqual('', x_attr) |
+ self.assertEqual('', y_attr) |
+ |
+ # Test how hyphens in input are treated. |
+ spec = 'label1-sub1 label2 label3-sub3' |
+ col_spec, sort_spec, x_attr, y_attr = issueadmin._ParseListPreferences( |
+ fake.PostData(default_col_spec=[spec], |
+ default_sort_spec=[spec], |
+ default_x_attr=[spec], |
+ default_y_attr=[spec]), |
+ ) |
+ |
+ # Hyphens (and anything following) should be stripped from each term. |
+ self.assertEqual('label1-sub1 label2 label3-sub3', col_spec) |
+ |
+ # The sort spec should be as given (except with whitespace condensed). |
+ self.assertEqual(' '.join(spec.split()), sort_spec) |
+ |
+ # Only the first term (up to the first hyphen) should be used for x- or |
+ # y-attr. |
+ self.assertEqual('label1-sub1', x_attr) |
+ self.assertEqual('label1-sub1', y_attr) |
+ |
+ # Test that multibyte strings are not mangled. |
+ spec = ('\xe7\xaa\xbf\xe8\x8b\xa5-\xe7\xb9\xb9 ' |
+ '\xe5\x9c\xb0\xe3\x81\xa6-\xe5\xbd\x93-\xe3\x81\xbe\xe3\x81\x99') |
+ spec = spec.decode('utf-8') |
+ col_spec, sort_spec, x_attr, y_attr = issueadmin._ParseListPreferences( |
+ fake.PostData(default_col_spec=[spec], |
+ default_sort_spec=[spec], |
+ default_x_attr=[spec], |
+ default_y_attr=[spec]), |
+ ) |
+ self.assertEqual(spec, col_spec) |
+ self.assertEqual(' '.join(spec.split()), sort_spec) |
+ self.assertEqual('\xe7\xaa\xbf\xe8\x8b\xa5-\xe7\xb9\xb9'.decode('utf-8'), |
+ x_attr) |
+ self.assertEqual('\xe7\xaa\xbf\xe8\x8b\xa5-\xe7\xb9\xb9'.decode('utf-8'), |
+ y_attr) |
+ |
+ |
+class AdminRulesTest(TestBase): |
+ |
+ def setUp(self): |
+ super(AdminRulesTest, self).setUpServlet(issueadmin.AdminRules) |
+ |
+ def testGatherPageData(self): |
+ self._mockGetUser() |
+ self.mox.ReplayAll() |
+ page_data = self.servlet.GatherPageData(self.mr) |
+ self.mox.VerifyAll() |
+ |
+ self.assertItemsEqual( |
+ ['admin_tab_mode', 'config', 'rules', 'new_rule_indexes', 'max_rules'], |
+ page_data.keys()) |
+ config_view = page_data['config'] |
+ self.assertEqual(789, config_view.project_id) |
+ self.assertEqual([], page_data['rules']) |
+ |
+ def testProcessSubtabForm(self): |
+ pass # TODO(jrobbins): write this test |
+ |
+ |
+if __name__ == '__main__': |
+ unittest.main() |