# 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)
