# Copyright 2016 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Unit tests for projectadmin module."""
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import

import unittest

from framework import permissions
from project import projectadmin
from mrproto import project_pb2
from services import service_manager
from testing import fake
from testing import testing_helpers


class ProjectAdminTest(unittest.TestCase):
  """Unit tests for the ProjectAdmin servlet class."""

  def setUp(self):
    services = service_manager.Services(
        project=fake.ProjectService(),
        user=fake.UserService())
    self.servlet = projectadmin.ProjectAdmin(services=services)
    self.project = services.project.TestAddProject(
        'proj', summary='a summary', description='a description')
    self.request, self.mr = testing_helpers.GetRequestObjects(
        project=self.project)

  def testAssertBasePermission(self):
    # Contributors cannot edit the project
    mr = testing_helpers.MakeMonorailRequest(
        project=self.project,
        perms=permissions.CONTRIBUTOR_ACTIVE_PERMISSIONSET)
    self.assertRaises(permissions.PermissionException,
                      self.servlet.AssertBasePermission, mr)

    # Signed-out users cannot edit the project
    mr.perms = permissions.READ_ONLY_PERMISSIONSET
    self.assertRaises(permissions.PermissionException,
                      self.servlet.AssertBasePermission, mr)

    # Non-member users cannot edit the project
    mr.perms = permissions.USER_PERMISSIONSET
    self.assertRaises(permissions.PermissionException,
                      self.servlet.AssertBasePermission, mr)

    # Owners can edit the project
    mr.perms = permissions.OWNER_ACTIVE_PERMISSIONSET
    self.servlet.AssertBasePermission(mr)

  def testGatherPageData(self):
    # Project has all default values.
    page_data = self.servlet.GatherPageData(self.mr)
    self.assertEqual('a summary', page_data['initial_summary'])
    self.assertEqual('a description', page_data['initial_description'])
    self.assertEqual(
        int(project_pb2.ProjectAccess.ANYONE), page_data['initial_access'].key)

    self.assertFalse(page_data['process_inbound_email'])
    self.assertFalse(page_data['only_owners_remove_restrictions'])
    self.assertFalse(page_data['only_owners_see_contributors'])
    self.assertFalse(page_data['issue_notify_always_detailed'])

    # Now try some alternate Project field values.
    self.project.only_owners_remove_restrictions = True
    self.project.only_owners_see_contributors = True
    self.project.issue_notify_always_detailed = True
    page_data = self.servlet.GatherPageData(self.mr)
    self.assertTrue(page_data['only_owners_remove_restrictions'])
    self.assertTrue(page_data['only_owners_see_contributors'])
    self.assertTrue(page_data['issue_notify_always_detailed'])

    # TODO(jrobbins): many more tests needed.
