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

"""Tests for the Monorail home page."""
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import

import mock
import unittest

import ezt

import settings
from framework import permissions
from mrproto import project_pb2
from mrproto import site_pb2
from services import service_manager
from sitewide import hostinghome
from sitewide import projectsearch
from testing import fake
from testing import testing_helpers


class MockProjectSearchPipeline(object):

  def __init__(self, _mr, services):
    self.visible_results = services.mock_visible_results
    self.pagination = None

  def SearchForIDs(self, domain=None):
    pass

  def GetProjectsAndPaginate(self, cnxn, list_page_url):
    pass


class HostingHomeTest(unittest.TestCase):

  def setUp(self):
    self.services = service_manager.Services(
        project=fake.ProjectService(),
        project_star=fake.ProjectStarService())
    self.services.mock_visible_results = []
    self.project_a = self.services.project.TestAddProject('a', project_id=1)
    self.project_b = self.services.project.TestAddProject('b', project_id=2)

    self.servlet = hostinghome.HostingHome(services=self.services)
    self.mr = testing_helpers.MakeMonorailRequest(user_info={'user_id': 111})

    self.orig_pipeline_class = projectsearch.ProjectSearchPipeline
    projectsearch.ProjectSearchPipeline = MockProjectSearchPipeline

  def tearDown(self):
    projectsearch.ProjectSearchPipeline = self.orig_pipeline_class

  def testSearch_ZeroResults(self):
    self.services.mock_visible_results = []
    page_data = self.servlet.GatherPageData(self.mr)
    self.assertEqual([], page_data['projects'])

  def testSearch_NonzeroResults(self):
    self.services.mock_visible_results = [self.project_a, self.project_b]
    page_data = self.servlet.GatherPageData(self.mr)
    self.assertEqual(['a', 'b'],
                     [pv.project_name for pv in page_data['projects']])

  def testStarCounts(self):
    """Test the display of star counts on each displayed project."""
    self.services.mock_visible_results = [self.project_a, self.project_b]
    # We go straight to the services layer because this is a test set up
    # rather than an actual user request.
    self.services.project_star.SetStar('fake cnxn', 1, 111, True)
    self.services.project_star.SetStar('fake cnxn', 1, 222, True)
    page_data = self.servlet.GatherPageData(self.mr)
    project_view_a, project_view_b = page_data['projects']
    self.assertEqual(2, project_view_a.num_stars)
    self.assertEqual(0, project_view_b.num_stars)

  def testStarredProjects(self):
    self.services.mock_visible_results = [self.project_a, self.project_b]
    self.services.project_star.SetStar('fake cnxn', 1, 111, True)
    page_data = self.servlet.GatherPageData(self.mr)
    project_view_a, project_view_b = page_data['projects']
    self.assertTrue(project_view_a.starred)
    self.assertFalse(project_view_b.starred)

  def testGatherPageData(self):
    mr = testing_helpers.MakeMonorailRequest()
    page_data = self.servlet.GatherPageData(mr)
    self.assertEqual(settings.learn_more_link, page_data['learn_more_link'])

  def testGatherPageData_CanCreateProject(self):
    mr = testing_helpers.MakeMonorailRequest()
    mr.perms = permissions.PermissionSet([permissions.CREATE_PROJECT])
    page_data = self.servlet.GatherPageData(mr)
    self.assertEqual(
      ezt.boolean(settings.project_creation_restriction ==
                  site_pb2.UserTypeRestriction.ANYONE),
      page_data['can_create_project'])

    mr.perms = permissions.PermissionSet([])
    page_data = self.servlet.GatherPageData(mr)
    self.assertEqual(ezt.boolean(False), page_data['can_create_project'])

  @mock.patch('settings.domain_to_default_project', {})
  def testMaybeRedirectToDomainDefaultProject_NoMatch(self):
    """No redirect if the user is not accessing via a configured domain."""
    mr = testing_helpers.MakeMonorailRequest()
    mr.request.host = 'example.com'
    msg = self.servlet._MaybeRedirectToDomainDefaultProject(mr)
    print('msg: ' + msg)
    self.assertTrue(msg.startswith('No configured'))

  @mock.patch('settings.domain_to_default_project', {'example.com': 'huh'})
  def testMaybeRedirectToDomainDefaultProject_NoSuchProject(self):
    """No redirect if the configured project does not exist."""
    mr = testing_helpers.MakeMonorailRequest()
    mr.request.host = 'example.com'
    print('host is %r' % mr.request.host)
    msg = self.servlet._MaybeRedirectToDomainDefaultProject(mr)
    print('msg: ' + msg)
    self.assertTrue(msg.endswith('not found'))

  @mock.patch('settings.domain_to_default_project', {'example.com': 'a'})
  def testMaybeRedirectToDomainDefaultProject_CantView(self):
    """No redirect if the user can't view the configured project."""
    self.project_a.access = project_pb2.ProjectAccess.MEMBERS_ONLY
    mr = testing_helpers.MakeMonorailRequest()
    mr.request.host = 'example.com'
    msg = self.servlet._MaybeRedirectToDomainDefaultProject(mr)
    print('msg: ' + msg)
    self.assertTrue(msg.startswith('User cannot'))

  @mock.patch('settings.domain_to_default_project', {'example.com': 'a'})
  def testMaybeRedirectToDomainDefaultProject_Redirect(self):
    """We redirect if there's a configured project that the user can view."""
    mr = testing_helpers.MakeMonorailRequest()
    mr.request.host = 'example.com'
    self.servlet.redirect = mock.Mock()
    msg = self.servlet._MaybeRedirectToDomainDefaultProject(mr)
    print('msg: ' + msg)
    self.assertTrue(msg.startswith('Redirected'))
    self.servlet.redirect.assert_called_once()
