Project import generated by Copybara.

GitOrigin-RevId: d9e9e3fb4e31372ec1fb43b178994ca78fa8fe70
diff --git a/framework/test/framework_views_test.py b/framework/test/framework_views_test.py
new file mode 100644
index 0000000..57f9fd1
--- /dev/null
+++ b/framework/test/framework_views_test.py
@@ -0,0 +1,326 @@
+# 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
+
+"""Unit tests for framework_views classes."""
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+
+import time
+import unittest
+
+from framework import framework_constants
+from framework import framework_views
+from framework import monorailrequest
+from proto import project_pb2
+from proto import tracker_pb2
+from proto import user_pb2
+import settings
+from services import service_manager
+from testing import fake
+
+
+LONG_STR = 'VeryLongStringThatCertainlyWillNotFit'
+LONG_PART_STR = 'OnePartThatWillNotFit-OneShort'
+
+
+class LabelViewTest(unittest.TestCase):
+
+  def testLabelView(self):
+    view = framework_views.LabelView('', None)
+    self.assertEqual('', view.name)
+
+    view = framework_views.LabelView('Priority-High', None)
+    self.assertEqual('Priority-High', view.name)
+    self.assertIsNone(view.is_restrict)
+    self.assertEqual('', view.docstring)
+    self.assertEqual('Priority', view.prefix)
+    self.assertEqual('High', view.value)
+
+    view = framework_views.LabelView('%s-%s' % (LONG_STR, LONG_STR), None)
+    self.assertEqual('%s-%s' % (LONG_STR, LONG_STR), view.name)
+    self.assertEqual('', view.docstring)
+    self.assertEqual(LONG_STR, view.prefix)
+    self.assertEqual(LONG_STR, view.value)
+
+    view = framework_views.LabelView(LONG_PART_STR, None)
+    self.assertEqual(LONG_PART_STR, view.name)
+    self.assertEqual('', view.docstring)
+    self.assertEqual('OnePartThatWillNotFit', view.prefix)
+    self.assertEqual('OneShort', view.value)
+
+    config = tracker_pb2.ProjectIssueConfig()
+    config.well_known_labels.append(tracker_pb2.LabelDef(
+        label='Priority-High', label_docstring='Must ship in this milestone'))
+
+    view = framework_views.LabelView('Priority-High', config)
+    self.assertEqual('Must ship in this milestone', view.docstring)
+
+    view = framework_views.LabelView('Priority-Foo', config)
+    self.assertEqual('', view.docstring)
+
+    view = framework_views.LabelView('Restrict-View-Commit', None)
+    self.assertTrue(view.is_restrict)
+
+
+class StatusViewTest(unittest.TestCase):
+
+  def testStatusView(self):
+    view = framework_views.StatusView('', None)
+    self.assertEqual('', view.name)
+
+    view = framework_views.StatusView('Accepted', None)
+    self.assertEqual('Accepted', view.name)
+    self.assertEqual('', view.docstring)
+    self.assertEqual('yes', view.means_open)
+
+    view = framework_views.StatusView(LONG_STR, None)
+    self.assertEqual(LONG_STR, view.name)
+    self.assertEqual('', view.docstring)
+    self.assertEqual('yes', view.means_open)
+
+    config = tracker_pb2.ProjectIssueConfig()
+    config.well_known_statuses.append(tracker_pb2.StatusDef(
+        status='SlamDunk', status_docstring='Code fixed and taught a lesson',
+        means_open=False))
+
+    view = framework_views.StatusView('SlamDunk', config)
+    self.assertEqual('Code fixed and taught a lesson', view.docstring)
+    self.assertFalse(view.means_open)
+
+    view = framework_views.StatusView('SlammedBack', config)
+    self.assertEqual('', view.docstring)
+
+
+class UserViewTest(unittest.TestCase):
+
+  def setUp(self):
+    self.user = user_pb2.User(user_id=111)
+
+  def testGetAvailablity_Anon(self):
+    self.user.user_id = 0
+    user_view = framework_views.UserView(self.user)
+    self.assertEqual(None, user_view.avail_message)
+    self.assertEqual(None, user_view.avail_state)
+
+  def testGetAvailablity_Banned(self):
+    self.user.banned = 'spamming'
+    user_view = framework_views.UserView(self.user)
+    self.assertEqual('Banned', user_view.avail_message)
+    self.assertEqual('banned', user_view.avail_state)
+
+  def testGetAvailablity_Vacation(self):
+    self.user.vacation_message = 'gone fishing'
+    user_view = framework_views.UserView(self.user)
+    self.assertEqual('gone fishing', user_view.avail_message)
+    self.assertEqual('none', user_view.avail_state)
+
+    self.user.vacation_message = (
+      'Gone fishing as really long time with lots of friends and reading '
+      'a long novel by a famous author.  I wont have internet access but '
+      'If you urgently need anything you can call Alice or Bob for most '
+      'things otherwise call Charlie.  Wish me luck! ')
+    user_view = framework_views.UserView(self.user)
+    self.assertTrue(len(user_view.avail_message) >= 50)
+    self.assertTrue(len(user_view.avail_message_short) < 50)
+    self.assertEqual('none', user_view.avail_state)
+
+  def testGetAvailablity_Bouncing(self):
+    self.user.email_bounce_timestamp = 1234567890
+    user_view = framework_views.UserView(self.user)
+    self.assertEqual('Email to this user bounced', user_view.avail_message)
+    self.assertEqual(user_view.avail_message_short, user_view.avail_message)
+    self.assertEqual('none', user_view.avail_state)
+
+  def testGetAvailablity_Groups(self):
+    user_view = framework_views.UserView(self.user, is_group=True)
+    self.assertEqual(None, user_view.avail_message)
+    self.assertEqual(None, user_view.avail_state)
+
+    self.user.email = 'likely-user-group@example.com'
+    user_view = framework_views.UserView(self.user)
+    self.assertEqual(None, user_view.avail_message)
+    self.assertEqual(None, user_view.avail_state)
+
+  def testGetAvailablity_NeverVisitied(self):
+    self.user.last_visit_timestamp = 0
+    user_view = framework_views.UserView(self.user)
+    self.assertEqual('User never visited', user_view.avail_message)
+    self.assertEqual('never', user_view.avail_state)
+
+  def testGetAvailablity_NotRecent(self):
+    now = int(time.time())
+    self.user.last_visit_timestamp = now - 20 * framework_constants.SECS_PER_DAY
+    user_view = framework_views.UserView(self.user)
+    self.assertEqual('Last visit 20 days ago', user_view.avail_message)
+    self.assertEqual('unsure', user_view.avail_state)
+
+  def testGetAvailablity_ReallyLongTime(self):
+    now = int(time.time())
+    self.user.last_visit_timestamp = now - 99 * framework_constants.SECS_PER_DAY
+    user_view = framework_views.UserView(self.user)
+    self.assertEqual('Last visit > 30 days ago', user_view.avail_message)
+    self.assertEqual('none', user_view.avail_state)
+
+  def testDeletedUser(self):
+    deleted_user = user_pb2.User(user_id=1)
+    user_view = framework_views.UserView(deleted_user)
+    self.assertEqual(
+        user_view.display_name, framework_constants.DELETED_USER_NAME)
+    self.assertEqual(user_view.email, '')
+    self.assertEqual(user_view.obscure_email, '')
+    self.assertEqual(user_view.profile_url, '')
+
+class RevealEmailsToMembersTest(unittest.TestCase):
+
+  def setUp(self):
+    self.cnxn = fake.MonorailConnection()
+    self.services = service_manager.Services(
+        project=fake.ProjectService(),
+        user=fake.UserService(),
+        usergroup=fake.UserGroupService())
+    self.mr = monorailrequest.MonorailRequest(None)
+    self.mr.project = self.services.project.TestAddProject(
+        'proj',
+        project_id=789,
+        owner_ids=[111],
+        committer_ids=[222],
+        contrib_ids=[333, 888])
+    user = self.services.user.TestAddUser('test@example.com', 1000)
+    self.mr.auth.user_pb = user
+
+  def CheckRevealAllToMember(
+      self, logged_in_user_id, expected, viewed_user_id=333, group_id=None):
+    user_view = framework_views.StuffUserView(
+        viewed_user_id, 'user@example.com', True)
+
+    if group_id:
+      pass  # xxx re-implement groups
+
+    users_by_id = {333: user_view}
+    self.mr.auth.user_id = logged_in_user_id
+    self.mr.auth.effective_ids = {logged_in_user_id}
+    # Assert display name is obscured before the reveal.
+    self.assertEqual('u...@example.com', user_view.display_name)
+    # Assert profile url contains user ID before the reveal.
+    self.assertEqual('/u/%s/' % viewed_user_id, user_view.profile_url)
+    framework_views.RevealAllEmailsToMembers(
+        self.cnxn, self.services, self.mr.auth, users_by_id)
+    self.assertEqual(expected, not user_view.obscure_email)
+    if expected:
+      # Assert display name is now revealed.
+      self.assertEqual('user@example.com', user_view.display_name)
+      # Assert profile url contains the email.
+      self.assertEqual('/u/user@example.com/', user_view.profile_url)
+    else:
+      # Assert display name is still hidden.
+      self.assertEqual('u...@example.com', user_view.display_name)
+      # Assert profile url still contains user ID.
+      self.assertEqual('/u/%s/' % viewed_user_id, user_view.profile_url)
+
+  # TODO(https://crbug.com/monorail/8192): Remove this method and related test.
+  def DeprecatedCheckRevealAllToMember(
+      self, logged_in_user_id, expected, viewed_user_id=333, group_id=None):
+    user_view = framework_views.StuffUserView(
+        viewed_user_id, 'user@example.com', True)
+
+    if group_id:
+      pass  # xxx re-implement groups
+
+    users_by_id = {333: user_view}
+    self.mr.auth.user_id = logged_in_user_id
+    self.mr.auth.effective_ids = {logged_in_user_id}
+    # Assert display name is obscured before the reveal.
+    self.assertEqual('u...@example.com', user_view.display_name)
+    # Assert profile url contains user ID before the reveal.
+    self.assertEqual('/u/%s/' % viewed_user_id, user_view.profile_url)
+    framework_views.RevealAllEmailsToMembers(
+        self.cnxn, self.services, self.mr.auth, users_by_id, self.mr.project)
+    self.assertEqual(expected, not user_view.obscure_email)
+    if expected:
+      # Assert display name is now revealed.
+      self.assertEqual('user@example.com', user_view.display_name)
+      # Assert profile url contains the email.
+      self.assertEqual('/u/user@example.com/', user_view.profile_url)
+    else:
+      # Assert display name is still hidden.
+      self.assertEqual('u...@example.com', user_view.display_name)
+      # Assert profile url still contains user ID.
+      self.assertEqual('/u/%s/' % viewed_user_id, user_view.profile_url)
+
+  def testDontRevealEmailsToPriviledgedDomain(self):
+    """We no longer give this advantage based on email address domain."""
+    for priviledged_user_domain in settings.priviledged_user_domains:
+      self.mr.auth.user_pb.email = 'test@' + priviledged_user_domain
+      self.CheckRevealAllToMember(100001, False)
+
+  def testRevealEmailToSelf(self):
+    logged_in_user = self.services.user.TestAddUser('user@example.com', 333)
+    self.mr.auth.user_pb = logged_in_user
+    self.CheckRevealAllToMember(333, True)
+
+  def testRevealAllEmailsToMembers_Collaborators(self):
+    self.CheckRevealAllToMember(0, False)
+    self.CheckRevealAllToMember(111, True)
+    self.CheckRevealAllToMember(222, True)
+    self.CheckRevealAllToMember(333, True)
+    self.CheckRevealAllToMember(444, False)
+
+    # Viewed user has indirect role in the project via a group.
+    self.CheckRevealAllToMember(0, False, group_id=888)
+    self.CheckRevealAllToMember(111, True, group_id=888)
+    # xxx re-implement
+    # self.CheckRevealAllToMember(
+    #     111, True, viewed_user_id=444, group_id=888)
+
+    # Logged in user has indirect role in the project via a group.
+    self.CheckRevealAllToMember(888, True)
+
+  def testDeprecatedRevealAllEmailsToMembers_Collaborators(self):
+    self.DeprecatedCheckRevealAllToMember(0, False)
+    self.DeprecatedCheckRevealAllToMember(111, True)
+    self.DeprecatedCheckRevealAllToMember(222, True)
+    self.DeprecatedCheckRevealAllToMember(333, True)
+    self.DeprecatedCheckRevealAllToMember(444, False)
+
+    # Viewed user has indirect role in the project via a group.
+    self.DeprecatedCheckRevealAllToMember(0, False, group_id=888)
+    self.DeprecatedCheckRevealAllToMember(111, True, group_id=888)
+
+    # Logged in user has indirect role in the project via a group.
+    self.DeprecatedCheckRevealAllToMember(888, True)
+
+  def testRevealAllEmailsToMembers_Admins(self):
+    self.CheckRevealAllToMember(555, False)
+    self.mr.auth.user_pb.is_site_admin = True
+    self.CheckRevealAllToMember(555, True)
+
+
+class RevealAllEmailsTest(unittest.TestCase):
+
+  def testRevealAllEmail(self):
+    users_by_id = {
+        111: framework_views.StuffUserView(111, 'a@a.com', True),
+        222: framework_views.StuffUserView(222, 'b@b.com', True),
+        333: framework_views.StuffUserView(333, 'c@c.com', True),
+        999: framework_views.StuffUserView(999, 'z@z.com', True),
+        }
+    # Assert display names are obscured before the reveal.
+    self.assertEqual('a...@a.com', users_by_id[111].display_name)
+    self.assertEqual('b...@b.com', users_by_id[222].display_name)
+    self.assertEqual('c...@c.com', users_by_id[333].display_name)
+    self.assertEqual('z...@z.com', users_by_id[999].display_name)
+
+    framework_views.RevealAllEmails(users_by_id)
+
+    self.assertFalse(users_by_id[111].obscure_email)
+    self.assertFalse(users_by_id[222].obscure_email)
+    self.assertFalse(users_by_id[333].obscure_email)
+    self.assertFalse(users_by_id[999].obscure_email)
+    # Assert display names are now revealed.
+    self.assertEqual('a@a.com', users_by_id[111].display_name)
+    self.assertEqual('b@b.com', users_by_id[222].display_name)
+    self.assertEqual('c@c.com', users_by_id[333].display_name)
+    self.assertEqual('z@z.com', users_by_id[999].display_name)