blob: 442bf8bc88b55b82f6fefa77e0e0096451c48262 [file] [log] [blame]
# Copyright 2018 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Unit test for Template creation servlet."""
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import
try:
from mox3 import mox
except ImportError:
import mox
import unittest
import settings
from mock import Mock
import ezt
from framework import permissions
from services import service_manager
from services import template_svc
from testing import fake
from testing import testing_helpers
from tracker import templatecreate
from tracker import tracker_bizobj
from tracker import tracker_views
from mrproto import tracker_pb2
class TemplateCreateTest(unittest.TestCase):
"""Tests for the TemplateCreate servlet."""
def setUp(self):
self.cnxn = 'fake cnxn'
self.services = service_manager.Services(
project=fake.ProjectService(),
config=fake.ConfigService(),
template=Mock(spec=template_svc.TemplateService),
user=fake.UserService())
self.servlet = templatecreate.TemplateCreate(services=self.services)
self.project = self.services.project.TestAddProject('proj')
self.fd_1 = tracker_bizobj.MakeFieldDef(
1, self.project.project_id, 'StringFieldName',
tracker_pb2.FieldTypes.STR_TYPE, None, '', False,
False, False, None, None, '', False, '', '',
tracker_pb2.NotifyTriggers.NEVER, 'no_action',
'some approval thing', False, approval_id=2)
self.fd_2 = tracker_bizobj.MakeFieldDef(
2, self.project.project_id, 'UXApproval',
tracker_pb2.FieldTypes.APPROVAL_TYPE, None, '', False, False, False,
None, None, '', False, '', '', tracker_pb2.NotifyTriggers.NEVER,
'no_action', 'Approval for UX review', False)
self.fd_3 = tracker_bizobj.MakeFieldDef(
3, self.project.project_id, 'TestApproval',
tracker_pb2.FieldTypes.APPROVAL_TYPE, None, '', False, False, False,
None, None, '', False, '', '', tracker_pb2.NotifyTriggers.NEVER,
'no_action', 'Approval for Test review', False)
self.fd_4 = tracker_bizobj.MakeFieldDef(
4, self.project.project_id, 'Target',
tracker_pb2.FieldTypes.INT_TYPE, None, '', False, False, False, None,
None, '', False, '', '', tracker_pb2.NotifyTriggers.NEVER, 'no_action',
'milestone target', False, is_phase_field=True)
self.fd_5 = tracker_bizobj.MakeFieldDef(
5,
self.project.project_id,
'RestrictedField',
tracker_pb2.FieldTypes.INT_TYPE,
None,
'',
False,
False,
False,
None,
None,
'',
False,
'',
'',
tracker_pb2.NotifyTriggers.NEVER,
'no_action',
'RestrictedField',
False,
is_restricted_field=True)
self.fd_6 = tracker_bizobj.MakeFieldDef(
6,
self.project.project_id,
'RestrictedEnumField',
tracker_pb2.FieldTypes.ENUM_TYPE,
None,
'',
False,
False,
False,
None,
None,
'',
False,
'',
'',
tracker_pb2.NotifyTriggers.NEVER,
'no_action',
'RestrictedEnumField',
False,
is_restricted_field=True)
ad_2 = tracker_pb2.ApprovalDef(approval_id=2)
ad_3 = tracker_pb2.ApprovalDef(approval_id=3)
self.config = self.services.config.GetProjectConfig(
'fake cnxn', self.project.project_id)
self.config.approval_defs.extend([ad_2, ad_3])
self.config.field_defs.extend(
[self.fd_1, self.fd_2, self.fd_3, self.fd_4, self.fd_5, self.fd_6])
first_tmpl = tracker_bizobj.MakeIssueTemplate(
'sometemplate', 'summary', None, None, 'content', [], [], [],
[])
self.services.config.StoreConfig(None, self.config)
templates = testing_helpers.DefaultTemplates()
templates.append(first_tmpl)
self.services.template.GetProjectTemplates = Mock(
return_value=templates)
self.mr = testing_helpers.MakeMonorailRequest(
project=self.project, perms=permissions.OWNER_ACTIVE_PERMISSIONSET)
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):
precomp_view_info = tracker_views._PrecomputeInfoForValueViews(
[], [], [], self.config, [])
fv = tracker_views._MakeFieldValueView(
self.fd_1, self.config, precomp_view_info, {})
page_data = self.servlet.GatherPageData(self.mr)
self.assertEqual(self.servlet.PROCESS_TAB_TEMPLATES,
page_data['admin_tab_mode'])
self.assertTrue(page_data['allow_edit'])
self.assertEqual(page_data['uneditable_fields'], ezt.boolean(False))
self.assertTrue(page_data['new_template_form'])
self.assertFalse(page_data['initial_members_only'])
self.assertEqual(page_data['template_name'], '')
self.assertEqual(page_data['initial_summary'], '')
self.assertFalse(page_data['initial_must_edit_summary'])
self.assertEqual(page_data['initial_content'], '')
self.assertEqual(page_data['initial_status'], '')
self.assertEqual(page_data['initial_owner'], '')
self.assertFalse(page_data['initial_owner_defaults_to_member'])
self.assertEqual(page_data['initial_components'], '')
self.assertFalse(page_data['initial_component_required'])
self.assertEqual(page_data['fields'][2].field_name, fv.field_name)
self.assertEqual(page_data['initial_admins'], '')
self.assertEqual(page_data['approval_subfields_present'], ezt.boolean(True))
self.assertEqual(page_data['phase_fields_present'], ezt.boolean(False))
def testProcessFormData_Reject(self):
self.services.user.TestAddUser('user@example.com', 222)
self.mr.auth.effective_ids = {222}
post_data = fake.PostData(
name=['sometemplate'],
members_only=['on'],
summary=['TLDR'],
summary_must_be_edited=['on'],
content=['HEY WHY'],
status=['Accepted'],
owner=['someone@world.com'],
label=['label-One', 'label-Two'],
custom_1=['NO'],
custom_2=['MOOD'],
components=['hey, hey2,he3'],
component_required=['on'],
owner_defaults_to_member=['no'],
add_approvals = ['on'],
phase_0=['Canary'],
phase_1=['Stable-Exp'],
phase_2=['Stable'],
phase_3=[''],
phase_4=[''],
phase_5=[''],
approval_2=['phase_1'],
approval_3=['phase_2']
)
self.mox.StubOutWithMock(self.servlet, 'PleaseCorrect')
self.servlet.PleaseCorrect(
self.mr,
initial_members_only=ezt.boolean(True),
template_name='sometemplate',
initial_content='TLDR',
initial_must_edit_summary=ezt.boolean(True),
initial_description='HEY WHY',
initial_status='Accepted',
initial_owner='someone@world.com',
initial_owner_defaults_to_member=ezt.boolean(False),
initial_components='hey, hey2, he3',
initial_component_required=ezt.boolean(True),
initial_admins='',
labels=['label-One', 'label-Two'],
fields=mox.IgnoreArg(),
initial_add_approvals=ezt.boolean(True),
initial_phases=[tracker_pb2.Phase(name=name) for
name in ['Canary', 'Stable-Exp', 'Stable', '', '', '']],
approvals=mox.IgnoreArg(),
prechecked_approvals=['2_phase_1', '3_phase_2'],
required_approval_ids=[]
)
self.mox.ReplayAll()
url = self.servlet.ProcessFormData(self.mr, post_data)
self.mox.VerifyAll()
self.assertEqual('Owner not found.', self.mr.errors.owner)
self.assertEqual('Unknown component he3', self.mr.errors.components)
self.assertEqual(
'Template with name sometemplate already exists', self.mr.errors.name)
self.assertEqual('Defined gates must have assigned approvals.',
self.mr.errors.phase_approvals)
self.assertIsNone(url)
def testProcessFormData_RejectRestrictedFields(self):
self.services.template.GetTemplateByName = Mock(return_value=None)
self.mr.perms = permissions.PermissionSet([])
post_data_add_fv = fake.PostData(
name=['secondtemplate'],
members_only=['on'],
summary=['TLDR'],
summary_must_be_edited=['on'],
content=['HEY WHY'],
status=['Accepted'],
label=['label-One', 'label-Two'],
custom_1=['Hey'],
custom_5=['7'],
component_required=['on'],
owner_defaults_to_member=['no'],
add_approvals=['no'],
phase_0=[''],
phase_1=[''],
phase_2=[''],
phase_3=[''],
phase_4=[''],
phase_5=['OOPs'],
approval_2=['phase_0'],
approval_3=['phase_2'])
post_data_label_edits_enum = fake.PostData(
name=['secondtemplate'],
members_only=['on'],
summary=['TLDR'],
summary_must_be_edited=['on'],
content=['HEY WHY'],
status=['Accepted'],
label=['label-One', 'label-Two', 'RestrictedEnumField-7'],
component_required=['on'],
owner_defaults_to_member=['no'],
add_approvals=['no'],
phase_0=[''],
phase_1=[''],
phase_2=[''],
phase_3=[''],
phase_4=[''],
phase_5=['OOPs'],
approval_2=['phase_0'],
approval_3=['phase_2'])
self.assertRaises(
AssertionError, self.servlet.ProcessFormData, self.mr, post_data_add_fv)
self.assertRaises(
AssertionError, self.servlet.ProcessFormData, self.mr,
post_data_label_edits_enum)
def testProcessFormData_Accept(self):
self.services.user.TestAddUser('user@example.com', 222)
self.mr.auth.effective_ids = {222}
self.services.template.GetTemplateByName = Mock(return_value=None)
post_data = fake.PostData(
name=['secondtemplate'],
members_only=['on'],
summary=['TLDR'],
summary_must_be_edited=['on'],
content=['HEY WHY'],
status=['Accepted'],
label=['label-One', 'label-Two', 'RestrictedEnumField-7'],
custom_1=['NO'],
custom_5=['37'],
component_required=['on'],
owner_defaults_to_member=['no'],
add_approvals=['no'],
phase_0=[''],
phase_1=[''],
phase_2=[''],
phase_3=[''],
phase_4=[''],
phase_5=['OOPs'],
approval_2=['phase_0'],
approval_3=['phase_2'])
url = self.servlet.ProcessFormData(self.mr, post_data)
self.assertTrue('/adminTemplates?saved=1&ts' in url)
self.assertEqual(0,
self.services.template.UpdateIssueTemplateDef.call_count)
# errors in phases should not matter if add_approvals is not 'on'
self.assertIsNone(self.mr.errors.phase_approvals)
def testProcessFormData_AcceptPhases(self):
self.services.user.TestAddUser('user@example.com', 222)
self.mr.auth.effective_ids = {222}
self.services.template.GetTemplateByName = Mock(return_value=None)
post_data = fake.PostData(
name=['secondtemplate'],
members_only=['on'],
summary=['TLDR'],
summary_must_be_edited=['on'],
content=['HEY WHY'],
status=['Accepted'],
label=['label-One', 'label-Two'],
custom_1=['NO'],
component_required=['on'],
owner_defaults_to_member=['no'],
add_approvals = ['on'],
phase_0=['Canary'],
phase_1=['Stable'],
phase_2=[''],
phase_3=[''],
phase_4=[''],
phase_5=[''],
approval_2=['phase_0'],
approval_3=['phase_1'],
approval_3_required=['on']
)
url = self.servlet.ProcessFormData(self.mr, post_data)
self.assertTrue('/adminTemplates?saved=1&ts' in url)
fv = tracker_pb2.FieldValue(field_id=1, str_value='NO', derived=False)
phases = [
tracker_pb2.Phase(name='Canary', rank=0, phase_id=0),
tracker_pb2.Phase(name='Stable', rank=1, phase_id=1)
]
approval_values = [
tracker_pb2.ApprovalValue(approval_id=2, phase_id=0),
tracker_pb2.ApprovalValue(
approval_id=3, status=tracker_pb2.ApprovalStatus(
tracker_pb2.ApprovalStatus.NEEDS_REVIEW), phase_id=1)
]
self.services.template.CreateIssueTemplateDef.assert_called_once_with(
self.mr.cnxn,
self.mr.project_id,
'secondtemplate',
'HEY WHY',
'TLDR',
True,
'Accepted',
True,
False,
True,
0, ['label-One', 'label-Two'], [], [], [fv],
phases=phases,
approval_values=approval_values)