# 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

"""Unittests for monorail.feature.activities."""
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import

import unittest

try:
  from mox3 import mox
except ImportError:
  import mox

from features import activities
from framework import framework_views
from framework import profiler
from proto import tracker_pb2
from proto import user_pb2
from services import service_manager
from testing import fake
from testing import testing_helpers


class ActivitiesTest(unittest.TestCase):

  def setUp(self):
    self.services = service_manager.Services(
        config=fake.ConfigService(),
        issue=fake.IssueService(),
        user=fake.UserService(),
        usergroup=fake.UserGroupService(),
        project=fake.ProjectService(),
    )

    self.project_name = 'proj'
    self.project_id = 987
    self.project = self.services.project.TestAddProject(
        self.project_name, project_id=self.project_id,
        process_inbound_email=True)

    self.issue_id = 11
    self.issue_local_id = 100
    self.issue = tracker_pb2.Issue()
    self.issue.issue_id = self.issue_id
    self.issue.project_id = self.project_id
    self.issue.local_id = self.issue_local_id
    self.services.issue.TestAddIssue(self.issue)

    self.comment_id = 123
    self.comment_timestamp = 120
    self.user = self.services.user.TestAddUser('testuser@example.com', 2)
    self.user_id = self.user.user_id
    self.mr_after = 1234

    self.mox = mox.Mox()

  def tearDown(self):
    self.mox.UnsetStubs()
    self.mox.ResetAll()

  def testActivities_NoUpdates(self):
    mr = testing_helpers.MakeMonorailRequest()
    updates_data = activities.GatherUpdatesData(
        self.services, mr, project_ids=[256],
        user_ids=None, ending=None, updates_page_url=None, autolink=None,
        highlight=None)

    self.assertIsNone(updates_data['pagination'])
    self.assertIsNone(updates_data['no_stars'])
    self.assertIsNone(updates_data['updates_data'])
    self.assertEqual('yes', updates_data['no_activities'])
    self.assertIsNone(updates_data['ending_type'])

  def createAndAssertUpdates(self, project_ids=None, user_ids=None,
                             ascending=True):
    comment_1 = tracker_pb2.IssueComment(
        id=self.comment_id, issue_id=self.issue_id,
        project_id=self.project_id, user_id=self.user_id,
        content='this is the 1st comment',
        timestamp=self.comment_timestamp)
    self.mox.StubOutWithMock(self.services.issue, 'GetIssueActivity')

    after = 0
    if ascending:
      after = self.mr_after
    self.services.issue.GetIssueActivity(
        mox.IgnoreArg(), num=50, before=0, after=after, project_ids=project_ids,
        user_ids=user_ids, ascending=ascending).AndReturn([comment_1])

    self.mox.ReplayAll()

    mr = testing_helpers.MakeMonorailRequest()
    if ascending:
      mr.after = self.mr_after

    updates_page_url='testing/testing'
    updates_data = activities.GatherUpdatesData(
        self.services, mr, project_ids=project_ids,
        user_ids=user_ids, ending=None, autolink=None,
        highlight='highlightme', updates_page_url=updates_page_url)
    self.mox.VerifyAll()

    if mr.after:
      pagination = updates_data['pagination']
      self.assertIsNone(pagination.last)
      self.assertEqual(
          '%s?before=%d' %
          (updates_page_url.split('/')[-1], self.comment_timestamp),
          pagination.next_url)
      self.assertEqual(
          '%s?after=%d' %
          (updates_page_url.split('/')[-1], self.comment_timestamp),
          pagination.prev_url)

    activity_view = updates_data['updates_data'].older[0]
    self.assertEqual(
        '<a class="ot-issue-link"\n \n '
        'href="/p//issues/detail?id=%s#c_ts%s"\n >'
        'issue %s</a>\n\n()\n\n\n\n\n \n commented on' % (
            self.issue_local_id, self.comment_timestamp, self.issue_local_id),
        activity_view.escaped_title)
    self.assertEqual(
        '<span class="ot-issue-comment">\n this is the 1st comment\n</span>',
        activity_view.escaped_body)
    self.assertEqual('highlightme', activity_view.highlight)
    self.assertEqual(self.project_name, activity_view.project_name)

  def testActivities_AscendingProjectUpdates(self):
    self.createAndAssertUpdates(project_ids=[self.project_id], ascending=True)

  def testActivities_DescendingProjectUpdates(self):
    self.createAndAssertUpdates(project_ids=[self.project_id], ascending=False)

  def testActivities_AscendingUserUpdates(self):
    self.createAndAssertUpdates(user_ids=[self.user_id], ascending=True)

  def testActivities_DescendingUserUpdates(self):
    self.createAndAssertUpdates(user_ids=[self.user_id], ascending=False)

  def testActivities_SpecifyProjectAndUser(self):
    self.createAndAssertUpdates(
        project_ids=[self.project_id], user_ids=[self.user_id], ascending=False)
