Project import generated by Copybara.

GitOrigin-RevId: d9e9e3fb4e31372ec1fb43b178994ca78fa8fe70
diff --git a/tracker/test/fieldcreate_test.py b/tracker/test/fieldcreate_test.py
new file mode 100644
index 0000000..580d095
--- /dev/null
+++ b/tracker/test/fieldcreate_test.py
@@ -0,0 +1,301 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file or at
+# https://developers.google.com/open-source/licenses/bsd
+
+"""Unit tests for the fieldcreate servlet."""
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+
+import mox
+import mock
+import unittest
+import logging
+
+import ezt
+
+from framework import permissions
+from proto import tracker_pb2
+from services import service_manager
+from testing import fake
+from testing import testing_helpers
+from tracker import fieldcreate
+from tracker import tracker_bizobj
+
+
+class FieldCreateTest(unittest.TestCase):
+
+  def setUp(self):
+    self.cnxn = 'fake cnxn'
+    self.services = service_manager.Services(
+        user=fake.UserService(),
+        config=fake.ConfigService(),
+        project=fake.ProjectService())
+    self.servlet = fieldcreate.FieldCreate(
+        'req', 'res', services=self.services)
+    self.project = self.services.project.TestAddProject('proj')
+    self.mr = testing_helpers.MakeMonorailRequest(
+        project=self.project, perms=permissions.OWNER_ACTIVE_PERMISSIONSET)
+    self.services.user.TestAddUser('gatsby@example.com', 111)
+    self.services.user.TestAddUser('sport@example.com', 222)
+
+    self.mox = mox.Mox()
+
+  def tearDown(self):
+    self.mox.UnsetStubs()
+    self.mox.ResetAll()
+
+  def testAssertBasePermission(self):
+    # Anon users can never do it
+    self.mr.perms = permissions.READ_ONLY_PERMISSIONSET
+    self.assertRaises(
+        permissions.PermissionException,
+        self.servlet.AssertBasePermission, self.mr)
+
+    # Project owner can do it.
+    self.mr.perms = permissions.OWNER_ACTIVE_PERMISSIONSET
+    self.servlet.AssertBasePermission(self.mr)
+
+    # Project member cannot do it
+    self.mr.perms = permissions.COMMITTER_ACTIVE_PERMISSIONSET
+    self.assertRaises(
+        permissions.PermissionException,
+        self.servlet.AssertBasePermission, self.mr)
+    self.mr.perms = permissions.CONTRIBUTOR_ACTIVE_PERMISSIONSET
+    self.assertRaises(
+        permissions.PermissionException,
+        self.servlet.AssertBasePermission, self.mr)
+
+  def testGatherPageData(self):
+    approval_fd = tracker_bizobj.MakeFieldDef(
+        1, self.mr.project_id, 'LaunchApproval',
+        tracker_pb2.FieldTypes.APPROVAL_TYPE, None, '', False,
+        False, False, None, None, '', False, '', '',
+        tracker_pb2.NotifyTriggers.NEVER, 'no_action',
+        'some approval thing', False)
+    config = self.services.config.GetProjectConfig(
+        self.mr.cnxn, self.mr.project_id)
+    config.field_defs.append(approval_fd)
+    self.services.config.StoreConfig(self.cnxn, config)
+    page_data = self.servlet.GatherPageData(self.mr)
+    self.assertEqual(self.servlet.PROCESS_TAB_LABELS,
+                     page_data['admin_tab_mode'])
+    self.assertItemsEqual(
+        ['Defect', 'Enhancement', 'Task', 'Other'],
+        page_data['well_known_issue_types'])
+    self.assertEqual(['LaunchApproval'], page_data['approval_names'])
+    self.assertEqual('', page_data['initial_admins'])
+    self.assertEqual('', page_data['initial_editors'])
+    self.assertIsNone(page_data['initial_is_restricted_field'])
+
+  def testProcessFormData(self):
+    post_data = fake.PostData(
+        name=['somefield'],
+        field_type=['INT_TYPE'],
+        min_value=['1'],
+        max_value=['99'],
+        notify_on=['any_comment'],
+        importance=['required'],
+        is_multivalued=['Yes'],
+        docstring=['It is just some field'],
+        applicable_type=['Defect'],
+        date_action=['no_action'],
+        admin_names=['gatsby@example.com'],
+        editor_names=['sport@example.com'],
+        is_restricted_field=['Yes'])
+    url = self.servlet.ProcessFormData(self.mr, post_data)
+    self.assertTrue('/adminLabels?saved=1&' in url)
+    config = self.services.config.GetProjectConfig(
+        self.mr.cnxn, self.mr.project_id)
+
+    fd = tracker_bizobj.FindFieldDef('somefield', config)
+    self.assertEqual('somefield', fd.field_name)
+    self.assertEqual(tracker_pb2.FieldTypes.INT_TYPE, fd.field_type)
+    self.assertEqual(1, fd.min_value)
+    self.assertEqual(99, fd.max_value)
+    self.assertEqual(tracker_pb2.NotifyTriggers.ANY_COMMENT, fd.notify_on)
+    self.assertTrue(fd.is_required)
+    self.assertFalse(fd.is_niche)
+    self.assertTrue(fd.is_multivalued)
+    self.assertEqual('It is just some field', fd.docstring)
+    self.assertEqual('Defect', fd.applicable_type)
+    self.assertEqual('', fd.applicable_predicate)
+    self.assertEqual([111], fd.admin_ids)
+    self.assertEqual([222], fd.editor_ids)
+
+  def testProcessFormData_Reject_EditorsForNonRestrictedField(self):
+    # This method tests that an exception is raised
+    # when trying to add editors to a non restricted field.
+    post_data = fake.PostData(
+        name=['somefield'],
+        field_type=['INT_TYPE'],
+        min_value=['1'],
+        max_value=['99'],
+        notify_on=['any_comment'],
+        importance=['required'],
+        is_multivalued=['Yes'],
+        docstring=['It is just some field'],
+        applicable_type=['Defect'],
+        date_action=['no_action'],
+        admin_names=['gatsby@example.com'],
+        editor_names=['sport@example.com'])
+
+    self.assertRaises(
+        AssertionError, self.servlet.ProcessFormData, self.mr, post_data)
+
+  def testProcessFormData_Reject_EditorsForApprovalField(self):
+    #This method tests that an exception is raised
+    #when trying to add editors to an approval field.
+    post_data = fake.PostData(
+        name=['approval_field'],
+        field_type=['approval_type'],
+        notify_on=['any_comment'],
+        importance=['required'],
+        is_multivalued=['Yes'],
+        docstring=['It is just some field'],
+        applicable_type=['Defect'],
+        date_action=['no_action'],
+        approver_names=['gatsby@example.com'],
+        is_restricted_field=['Yes'],
+        admin_names=['gatsby@example.com'],
+        editor_names=[''])
+
+    self.assertRaises(
+        AssertionError, self.servlet.ProcessFormData, self.mr, post_data)
+
+  @mock.patch('framework.servlet.Servlet.PleaseCorrect')
+  def testProcessFormData_RejectAssertions(self, fake_servlet_pc):
+    #This method tests when errors are found using when the
+    #field_helpers.ParsedFieldDefAssertions is triggered.
+    post_data = fake.PostData(
+        name=['somefield'],
+        field_type=['INT_TYPE'],
+        min_value=['1'],
+        max_value=['99'],
+        notify_on=['any_comment'],
+        importance=['required'],
+        is_multivalued=['Yes'],
+        docstring=['It is just some field'],
+        applicable_type=['Defect'],
+        date_action=['wrong_date_action'],
+        admin_names=['gatsby@example.com'],
+        editor_names=[''])
+
+    self.servlet.ProcessFormData(self.mr, post_data)
+
+    fake_servlet_pc.assert_called_once_with(
+        self.mr,
+        initial_field_name='somefield',
+        initial_type='INT_TYPE',
+        initial_parent_approval_name='',
+        initial_field_docstring='It is just some field',
+        initial_applicable_type='Defect',
+        initial_applicable_predicate='',
+        initial_needs_member=None,
+        initial_needs_perm='',
+        initial_importance='required',
+        initial_is_multivalued='yes',
+        initial_grants_perm='',
+        initial_notify_on=1,
+        initial_date_action='wrong_date_action',
+        initial_choices='',
+        initial_approvers='',
+        initial_survey='',
+        initial_is_phase_field=False,
+        initial_admins='gatsby@example.com',
+        initial_editors='',
+        initial_is_restricted_field=False)
+    self.assertTrue(self.mr.errors.AnyErrors())
+
+
+  def testProcessFormData_RejectNoApprover(self):
+    post_data = fake.PostData(
+        name=['approvalField'],
+        field_type=['approval_type'],
+        approver_names=[''],
+        admin_names=[''],
+        editor_names=[''],
+        parent_approval_name=['UIApproval'],
+        is_phase_field=['on'])
+
+    self.mox.StubOutWithMock(self.servlet, 'PleaseCorrect')
+    self.servlet.PleaseCorrect(
+        self.mr,
+        initial_field_name=post_data.get('name'),
+        initial_type=post_data.get('field_type'),
+        initial_field_docstring=post_data.get('docstring', ''),
+        initial_applicable_type=post_data.get('applical_type', ''),
+        initial_applicable_predicate='',
+        initial_needs_member=ezt.boolean('needs_member' in post_data),
+        initial_needs_perm=post_data.get('needs_perm', '').strip(),
+        initial_importance=post_data.get('importance'),
+        initial_is_multivalued=ezt.boolean('is_multivalued' in post_data),
+        initial_grants_perm=post_data.get('grants_perm', '').strip(),
+        initial_notify_on=0,
+        initial_date_action=post_data.get('date_action'),
+        initial_choices=post_data.get('choices', ''),
+        initial_approvers=post_data.get('approver_names'),
+        initial_parent_approval_name=post_data.get('parent_approval_name', ''),
+        initial_survey=post_data.get('survey', ''),
+        initial_is_phase_field=False,
+        initial_admins=post_data.get('admin_names'),
+        initial_editors=post_data.get('editor_names'),
+        initial_is_restricted_field=False)
+    self.mox.ReplayAll()
+    url = self.servlet.ProcessFormData(self.mr, post_data)
+    self.mox.VerifyAll()
+    self.assertEqual(
+        'Please provide at least one default approver.',
+        self.mr.errors.approvers)
+    self.assertIsNone(url)
+
+
+class FieldCreateMethodsTest(unittest.TestCase):
+
+  def setUp(self):
+    self.config = tracker_bizobj.MakeDefaultProjectIssueConfig(789)
+
+  def testFieldNameErrorMessage_NoConflict(self):
+    self.assertIsNone(fieldcreate.FieldNameErrorMessage(
+        'somefield', self.config))
+
+  def testFieldNameErrorMessage_PrefixReserved(self):
+    self.assertEqual(
+        'That name is reserved.',
+        fieldcreate.FieldNameErrorMessage('owner', self.config))
+
+  def testFieldNameErrorMessage_SuffixReserved(self):
+    self.assertEqual(
+        'That suffix is reserved.',
+        fieldcreate.FieldNameErrorMessage('doh-approver', self.config))
+
+  def testFieldNameErrorMessage_AlreadyInUse(self):
+    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)
+    self.assertEqual(
+        'That name is already in use.',
+        fieldcreate.FieldNameErrorMessage('CPU', self.config))
+
+  def testFieldNameErrorMessage_PrefixOfExisting(self):
+    fd = tracker_bizobj.MakeFieldDef(
+        123, 789, 'sign-off', 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)
+    self.assertEqual(
+        'That name is a prefix of an existing field name.',
+        fieldcreate.FieldNameErrorMessage('sign', self.config))
+
+  def testFieldNameErrorMessage_IncludesExisting(self):
+    fd = tracker_bizobj.MakeFieldDef(
+        123, 789, 'opt', 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)
+    self.assertEqual(
+        'An existing field name is a prefix of that name.',
+        fieldcreate.FieldNameErrorMessage('opt-in', self.config))