Project import generated by Copybara.
GitOrigin-RevId: d9e9e3fb4e31372ec1fb43b178994ca78fa8fe70
diff --git a/project/test/__init__.py b/project/test/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/project/test/__init__.py
diff --git a/project/test/peopledetail_test.py b/project/test/peopledetail_test.py
new file mode 100644
index 0000000..547df80
--- /dev/null
+++ b/project/test/peopledetail_test.py
@@ -0,0 +1,262 @@
+# 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
+
+"""Unittest for the people detail page."""
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+
+import logging
+
+import unittest
+
+import webapp2
+
+from framework import authdata
+from framework import exceptions
+from framework import permissions
+from project import peopledetail
+from proto import project_pb2
+from services import service_manager
+from testing import fake
+from testing import testing_helpers
+
+
+class PeopleDetailTest(unittest.TestCase):
+
+ def setUp(self):
+ services = service_manager.Services(
+ project=fake.ProjectService(),
+ usergroup=fake.UserGroupService(),
+ user=fake.UserService())
+ services.user.TestAddUser('jrobbins', 111)
+ services.user.TestAddUser('jrobbins@jrobbins.org', 333)
+ services.user.TestAddUser('jrobbins@chromium.org', 555)
+ services.user.TestAddUser('imso31337@gmail.com', 999)
+ self.project = services.project.TestAddProject('proj')
+ self.project.owner_ids.extend([111, 222])
+ self.project.committer_ids.extend([333, 444])
+ self.project.contributor_ids.extend([555])
+ self.servlet = peopledetail.PeopleDetail('req', 'res', services=services)
+
+ def VerifyAccess(self, exception_expected):
+ mr = testing_helpers.MakeMonorailRequest(
+ path='/p/proj/people/detail?u=111',
+ project=self.project,
+ perms=permissions.OWNER_ACTIVE_PERMISSIONSET)
+ self.servlet.AssertBasePermission(mr)
+ # Owner never raises PermissionException.
+
+ mr = testing_helpers.MakeMonorailRequest(
+ path='/p/proj/people/detail?u=333',
+ project=self.project,
+ perms=permissions.COMMITTER_ACTIVE_PERMISSIONSET)
+ self.servlet.AssertBasePermission(mr)
+ # Committer never raises PermissionException.
+
+ mr = testing_helpers.MakeMonorailRequest(
+ path='/p/proj/people/detail?u=555',
+ project=self.project,
+ perms=permissions.CONTRIBUTOR_ACTIVE_PERMISSIONSET)
+ if exception_expected:
+ self.assertRaises(permissions.PermissionException,
+ self.servlet.AssertBasePermission, mr)
+ else:
+ self.servlet.AssertBasePermission(mr)
+ # No PermissionException raised
+
+ # Sign-out users
+ mr = testing_helpers.MakeMonorailRequest(
+ path='/p/proj/people/detail?u=555',
+ project=self.project,
+ perms=permissions.READ_ONLY_PERMISSIONSET)
+ if exception_expected:
+ self.assertRaises(permissions.PermissionException,
+ self.servlet.AssertBasePermission, mr)
+ else:
+ self.servlet.AssertBasePermission(mr)
+
+ # Non-membr users
+ mr = testing_helpers.MakeMonorailRequest(
+ path='/p/proj/people/detail?u=555',
+ project=self.project,
+ perms=permissions.USER_PERMISSIONSET)
+ if exception_expected:
+ self.assertRaises(permissions.PermissionException,
+ self.servlet.AssertBasePermission, mr)
+ else:
+ self.servlet.AssertBasePermission(mr)
+
+ def testAssertBasePermission_Normal(self):
+ self.VerifyAccess(False)
+
+ def testAssertBasePermission_HubSpoke(self):
+ self.project.only_owners_see_contributors = True
+ self.VerifyAccess(True)
+
+ def testAssertBasePermission_HubSpokeViewingSelf(self):
+ self.project.only_owners_see_contributors = True
+ mr = testing_helpers.MakeMonorailRequest(
+ path='/p/proj/people/detail?u=333',
+ project=self.project,
+ perms=permissions.COMMITTER_ACTIVE_PERMISSIONSET)
+ mr.auth.user_id = 333
+ self.servlet.AssertBasePermission(mr)
+ # No PermissionException raised
+
+ def testGatherPageData(self):
+ mr = testing_helpers.MakeMonorailRequest(
+ path='/p/proj/people/detail?u=111',
+ project=self.project,
+ perms=permissions.OWNER_ACTIVE_PERMISSIONSET)
+ mr.auth = authdata.AuthData()
+ page_data = self.servlet.GatherPageData(mr)
+ self.assertFalse(page_data['warn_abandonment'])
+ self.assertEqual(2, page_data['total_num_owners'])
+ # TODO(jrobbins): fill in tests for all other aspects.
+
+ def testValidateMemberID(self):
+ # We can validate owners
+ self.assertEqual(
+ 111, self.servlet.ValidateMemberID('fake cnxn', 111, self.project))
+
+ # We can parse members
+ self.assertEqual(
+ 333, self.servlet.ValidateMemberID('fake cnxn', 333, self.project))
+
+ # 404 for user that does not exist
+ with self.assertRaises(webapp2.HTTPException) as cm:
+ self.servlet.ValidateMemberID('fake cnxn', 8933, self.project)
+ self.assertEqual(404, cm.exception.code)
+
+ # 404 for valid user that is not in this project
+ with self.assertRaises(webapp2.HTTPException) as cm:
+ self.servlet.ValidateMemberID('fake cnxn', 999, self.project)
+ self.assertEqual(404, cm.exception.code)
+
+ def testParsePersonData_BadPost(self):
+ mr = testing_helpers.MakeMonorailRequest(
+ path='/p/proj/people/detail',
+ project=self.project)
+ post_data = fake.PostData()
+ with self.assertRaises(exceptions.InputException):
+ _result = self.servlet.ParsePersonData(mr, post_data)
+
+ def testParsePersonData_NoDetails(self):
+ mr = testing_helpers.MakeMonorailRequest(
+ path='/p/proj/people/detail?u=111',
+ project=self.project)
+ post_data = fake.PostData(role=['owner'])
+ u, r, ac, n, _, _ = self.servlet.ParsePersonData(mr, post_data)
+ self.assertEqual(111, u)
+ self.assertEqual('owner', r)
+ self.assertEqual([], ac)
+ self.assertEqual('', n)
+
+ mr = testing_helpers.MakeMonorailRequest(
+ path='/p/proj/people/detail?u=333',
+ project=self.project)
+ post_data = fake.PostData(role=['owner'])
+ u, r, ac, n, _, _ = self.servlet.ParsePersonData(mr, post_data)
+ self.assertEqual(333, u)
+
+ def testParsePersonData(self):
+ mr = testing_helpers.MakeMonorailRequest(
+ path='/p/proj/people/detail?u=111',
+ project=self.project)
+ post_data = fake.PostData(
+ role=['owner'], extra_perms=['ViewQuota', 'EditIssue'])
+ u, r, ac, n, _, _ = self.servlet.ParsePersonData(mr, post_data)
+ self.assertEqual(111, u)
+ self.assertEqual('owner', r)
+ self.assertEqual(['ViewQuota', 'EditIssue'], ac)
+ self.assertEqual('', n)
+
+ post_data = fake.PostData({
+ 'role': ['owner'],
+ 'extra_perms': [' ', ' \t'],
+ 'notes': [''],
+ 'ac_include': [123],
+ 'ac_expand': [123],
+ })
+ (u, r, ac, n, ac_exclusion, no_expand
+ ) = self.servlet.ParsePersonData(mr, post_data)
+ self.assertEqual(111, u)
+ self.assertEqual('owner', r)
+ self.assertEqual([], ac)
+ self.assertEqual('', n)
+ self.assertFalse(ac_exclusion)
+ self.assertFalse(no_expand)
+
+ post_data = fake.PostData({
+ 'username': ['jrobbins'],
+ 'role': ['owner'],
+ 'extra_perms': ['_ViewQuota', ' __EditIssue'],
+ 'notes': [' Our local Python expert '],
+ })
+ (u, r, ac, n, ac_exclusion, no_expand
+ )= self.servlet.ParsePersonData(mr, post_data)
+ self.assertEqual(111, u)
+ self.assertEqual('owner', r)
+ self.assertEqual(['ViewQuota', 'EditIssue'], ac)
+ self.assertEqual('Our local Python expert', n)
+ self.assertTrue(ac_exclusion)
+ self.assertTrue(no_expand)
+
+ def testCanEditMemberNotes(self):
+ """Only owners can edit member notes."""
+ mr = testing_helpers.MakeMonorailRequest(
+ path='/p/proj/people/detail?u=111',
+ project=self.project,
+ perms=permissions.CONTRIBUTOR_ACTIVE_PERMISSIONSET)
+ result = self.servlet.CanEditMemberNotes(mr, 222)
+ self.assertFalse(result)
+
+ mr.auth.user_id = 222
+ result = self.servlet.CanEditMemberNotes(mr, 222)
+ self.assertTrue(result)
+
+ mr = testing_helpers.MakeMonorailRequest(
+ path='/p/proj/people/detail?u=111',
+ project=self.project,
+ perms=permissions.OWNER_ACTIVE_PERMISSIONSET)
+ result = self.servlet.CanEditMemberNotes(mr, 222)
+ self.assertTrue(result)
+
+ def testCanEditPerms(self):
+ """Only owners can edit member perms."""
+ mr = testing_helpers.MakeMonorailRequest(
+ path='/p/proj/people/detail?u=111',
+ project=self.project,
+ perms=permissions.CONTRIBUTOR_ACTIVE_PERMISSIONSET)
+ result = self.servlet.CanEditPerms(mr)
+ self.assertFalse(result)
+
+ mr = testing_helpers.MakeMonorailRequest(
+ path='/p/proj/people/detail?u=111',
+ project=self.project,
+ perms=permissions.OWNER_ACTIVE_PERMISSIONSET)
+ result = self.servlet.CanEditPerms(mr)
+ self.assertTrue(result)
+
+ def testCanRemoveRole(self):
+ """Owners can remove members. Users could also remove themselves."""
+ mr = testing_helpers.MakeMonorailRequest(
+ path='/p/proj/people/detail?u=111',
+ project=self.project,
+ perms=permissions.CONTRIBUTOR_ACTIVE_PERMISSIONSET)
+ result = self.servlet.CanRemoveRole(mr, 222)
+ self.assertFalse(result)
+
+ mr.auth.user_id = 111
+ result = self.servlet.CanRemoveRole(mr, 111)
+ self.assertTrue(result)
+
+ mr = testing_helpers.MakeMonorailRequest(
+ path='/p/proj/people/detail?u=111',
+ project=self.project,
+ perms=permissions.OWNER_ACTIVE_PERMISSIONSET)
+ result = self.servlet.CanRemoveRole(mr, 222)
+ self.assertTrue(result)
diff --git a/project/test/peoplelist_test.py b/project/test/peoplelist_test.py
new file mode 100644
index 0000000..6620df9
--- /dev/null
+++ b/project/test/peoplelist_test.py
@@ -0,0 +1,158 @@
+# 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
+
+"""Unittest for People List servlet."""
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+
+import unittest
+
+from framework import authdata
+from framework import permissions
+from project import peoplelist
+from proto import user_pb2
+from services import service_manager
+from testing import fake
+from testing import testing_helpers
+
+
+class PeopleListTest(unittest.TestCase):
+ """Tests for the PeopleList servlet."""
+
+ def setUp(self):
+ services = service_manager.Services(
+ project=fake.ProjectService(),
+ user=fake.UserService(),
+ usergroup=fake.UserGroupService())
+ services.user.TestAddUser('jrobbins@gmail.com', 111)
+ services.user.TestAddUser('jrobbins@jrobbins.org', 222)
+ services.user.TestAddUser('jrobbins@chromium.org', 333)
+ services.user.TestAddUser('imso31337@gmail.com', 999)
+ self.project = services.project.TestAddProject('proj')
+ self.project.owner_ids.extend([111])
+ self.project.committer_ids.extend([222])
+ self.project.contributor_ids.extend([333])
+ self.servlet = peoplelist.PeopleList('req', 'res', services=services)
+
+ def VerifyAccess(self, exception_expected):
+ mr = testing_helpers.MakeMonorailRequest(
+ path='/p/proj/people/list',
+ project=self.project,
+ perms=permissions.OWNER_ACTIVE_PERMISSIONSET)
+ self.servlet.AssertBasePermission(mr)
+ # Owner never raises PermissionException.
+
+ mr = testing_helpers.MakeMonorailRequest(
+ path='/p/proj/people/list',
+ project=self.project,
+ perms=permissions.COMMITTER_ACTIVE_PERMISSIONSET)
+ self.servlet.AssertBasePermission(mr)
+ # Committer never raises PermissionException.
+
+ mr = testing_helpers.MakeMonorailRequest(
+ path='/p/proj/people/list',
+ project=self.project,
+ perms=permissions.CONTRIBUTOR_ACTIVE_PERMISSIONSET)
+ if exception_expected:
+ self.assertRaises(permissions.PermissionException,
+ self.servlet.AssertBasePermission, mr)
+ else:
+ self.servlet.AssertBasePermission(mr)
+ # No PermissionException raised
+
+ # Sign-out users
+ mr = testing_helpers.MakeMonorailRequest(
+ path='/p/proj/people/detail?u=555',
+ project=self.project,
+ perms=permissions.READ_ONLY_PERMISSIONSET)
+ if exception_expected:
+ self.assertRaises(permissions.PermissionException,
+ self.servlet.AssertBasePermission, mr)
+ else:
+ self.servlet.AssertBasePermission(mr)
+
+ # Non-membr users
+ mr = testing_helpers.MakeMonorailRequest(
+ path='/p/proj/people/detail?u=555',
+ project=self.project,
+ perms=permissions.USER_PERMISSIONSET)
+ if exception_expected:
+ self.assertRaises(permissions.PermissionException,
+ self.servlet.AssertBasePermission, mr)
+ else:
+ self.servlet.AssertBasePermission(mr)
+
+ def testAssertBasePermission_Normal(self):
+ self.VerifyAccess(False)
+
+ def testAssertBasePermission_HideMembers(self):
+ self.project.only_owners_see_contributors = True
+ self.VerifyAccess(True)
+
+ def testGatherPageData(self):
+ mr = testing_helpers.MakeMonorailRequest(
+ path='/p/proj/people/list',
+ project=self.project,
+ perms=permissions.OWNER_ACTIVE_PERMISSIONSET)
+ mr.auth = authdata.AuthData()
+ page_data = self.servlet.GatherPageData(mr)
+
+ self.assertEqual(1, page_data['total_num_owners'])
+ # TODO(jrobbins): fill in tests for all other aspects.
+
+ def testProcessFormData_Permission(self):
+ """Only owners could add/remove members."""
+ mr = testing_helpers.MakeMonorailRequest(
+ path='/p/proj/people/list',
+ project=self.project,
+ perms=permissions.CONTRIBUTOR_ACTIVE_PERMISSIONSET)
+ self.assertRaises(permissions.PermissionException,
+ self.servlet.ProcessFormData, mr, {})
+
+ mr = testing_helpers.MakeMonorailRequest(
+ path='/p/proj/people/list',
+ project=self.project,
+ perms=permissions.OWNER_ACTIVE_PERMISSIONSET)
+ self.servlet.ProcessFormData(mr, {})
+
+ def testGatherHelpData_Anon(self):
+ mr = testing_helpers.MakeMonorailRequest(
+ path='/p/proj/people/list',
+ project=self.project)
+ help_data = self.servlet.GatherHelpData(mr, {})
+ self.assertEqual(
+ {'account_cue': None, 'cue': None},
+ help_data)
+
+ def testGatherHelpData_Nonmember(self):
+ mr = testing_helpers.MakeMonorailRequest(
+ path='/p/proj/people/list',
+ project=self.project)
+ mr.auth.user_id = 999
+ mr.auth.effective_ids = {999}
+ help_data = self.servlet.GatherHelpData(mr, {})
+ self.assertEqual(
+ {'account_cue': None, 'cue': 'how_to_join_project'},
+ help_data)
+
+ self.servlet.services.user.SetUserPrefs(
+ 'cnxn', 999,
+ [user_pb2.UserPrefValue(name='how_to_join_project', value='true')])
+ help_data = self.servlet.GatherHelpData(mr, {})
+ self.assertEqual(
+ {'account_cue': None, 'cue': None},
+ help_data)
+
+ def testGatherHelpData_Member(self):
+ mr = testing_helpers.MakeMonorailRequest(
+ path='/p/proj/people/list',
+ project=self.project)
+ mr.auth.user_id = 111
+ mr.auth.effective_ids = {111}
+ help_data = self.servlet.GatherHelpData(mr, {})
+ self.assertEqual(
+ {'account_cue': None, 'cue': None},
+ help_data)
diff --git a/project/test/project_helpers_test.py b/project/test/project_helpers_test.py
new file mode 100644
index 0000000..4732895
--- /dev/null
+++ b/project/test/project_helpers_test.py
@@ -0,0 +1,179 @@
+# 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 helpers module."""
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+
+import unittest
+
+from mock import patch
+
+from framework import framework_views
+from framework import permissions
+from project import project_constants
+from project import project_helpers
+from proto import project_pb2
+from services import service_manager
+from testing import fake
+
+
+class HelpersUnitTest(unittest.TestCase):
+
+ def setUp(self):
+ self.cnxn = 'fake sql connection'
+ self.services = service_manager.Services(
+ project=fake.ProjectService(),
+ user=fake.UserService())
+ self.services.user.TestAddUser('a@example.com', 111)
+ self.services.user.TestAddUser('b@example.com', 222)
+ self.services.user.TestAddUser('c@example.com', 333)
+ self.users_by_id = framework_views.MakeAllUserViews(
+ 'cnxn', self.services.user, [111, 222, 333])
+ self.effective_ids_by_user = {user: set() for user in {111, 222, 333}}
+
+ def testBuildProjectMembers(self):
+ project = project_pb2.MakeProject(
+ 'proj', owner_ids=[111], committer_ids=[222],
+ contributor_ids=[333])
+ page_data = project_helpers.BuildProjectMembers(
+ self.cnxn, project, self.services.user)
+ self.assertEqual(111, page_data['owners'][0].user_id)
+ self.assertEqual(222, page_data['committers'][0].user_id)
+ self.assertEqual(333, page_data['contributors'][0].user_id)
+ self.assertEqual(3, len(page_data['all_members']))
+
+ def testParseUsernames(self):
+ # Form field was not present in post data.
+ id_set = project_helpers.ParseUsernames(
+ self.cnxn, self.services.user, None)
+ self.assertEqual(set(), id_set)
+
+ # Form field was present, but empty.
+ id_set = project_helpers.ParseUsernames(
+ self.cnxn, self.services.user, '')
+ self.assertEqual(set(), id_set)
+
+ # Parsing valid user names.
+ id_set = project_helpers.ParseUsernames(
+ self.cnxn, self.services.user, 'a@example.com, c@example.com')
+ self.assertEqual({111, 333}, id_set)
+
+ def testParseProjectAccess_NotOffered(self):
+ project = project_pb2.MakeProject('proj')
+ access = project_helpers.ParseProjectAccess(project, None)
+ self.assertEqual(None, access)
+
+ def testParseProjectAccess_AllowedChoice(self):
+ project = project_pb2.MakeProject('proj')
+ access = project_helpers.ParseProjectAccess(project, '1')
+ self.assertEqual(project_pb2.ProjectAccess.ANYONE, access)
+
+ access = project_helpers.ParseProjectAccess(project, '3')
+ self.assertEqual(project_pb2.ProjectAccess.MEMBERS_ONLY, access)
+
+ def testParseProjectAccess_BogusChoice(self):
+ project = project_pb2.MakeProject('proj')
+ access = project_helpers.ParseProjectAccess(project, '9')
+ self.assertEqual(None, access)
+
+ def testUsersWithPermsInProject_StandardPermission(self):
+ project = project_pb2.MakeProject('proj', committer_ids=[111])
+ perms_needed = {permissions.VIEW, permissions.EDIT_ISSUE}
+ actual = project_helpers.UsersWithPermsInProject(
+ project, perms_needed, self.users_by_id, self.effective_ids_by_user)
+ self.assertEqual(
+ {permissions.VIEW: {111, 222, 333},
+ permissions.EDIT_ISSUE: {111}},
+ actual)
+
+ def testUsersWithPermsInProject_IndirectPermission(self):
+ perms_needed = {permissions.EDIT_ISSUE}
+ # User 111 has the EDIT_ISSUE permission.
+ project = project_pb2.MakeProject('proj', committer_ids=[111])
+ # User 222 has the EDIT_ISSUE permission, because 111 is included in its
+ # effective IDs.
+ self.effective_ids_by_user[222] = {111}
+ # User 333 doesn't have the EDIT_ISSUE permission, since only direct
+ # effective IDs are taken into account.
+ self.effective_ids_by_user[333] = {222}
+ actual = project_helpers.UsersWithPermsInProject(
+ project, perms_needed, self.users_by_id, self.effective_ids_by_user)
+ self.assertEqual(
+ {permissions.EDIT_ISSUE: {111, 222}},
+ actual)
+
+ def testUsersWithPermsInProject_CustomPermission(self):
+ project = project_pb2.MakeProject('proj')
+ project.extra_perms = [
+ project_pb2.Project.ExtraPerms(
+ member_id=111,
+ perms=['FooPerm', 'BarPerm']),
+ project_pb2.Project.ExtraPerms(
+ member_id=222,
+ perms=['BarPerm'])]
+ perms_needed = {'FooPerm', 'BarPerm'}
+ actual = project_helpers.UsersWithPermsInProject(
+ project, perms_needed, self.users_by_id, self.effective_ids_by_user)
+ self.assertEqual(
+ {'FooPerm': {111},
+ 'BarPerm': {111, 222}},
+ actual)
+
+ @patch('google.appengine.api.app_identity.get_default_gcs_bucket_name')
+ @patch('framework.gcs_helpers.SignUrl')
+ def testGetThumbnailUrl(self, mock_SignUrl, mock_get_default_gcs_bucket_name):
+ bucket_name = 'testbucket'
+ expected_url = 'signed/url'
+
+ mock_get_default_gcs_bucket_name.return_value = bucket_name
+ mock_SignUrl.return_value = expected_url
+
+ self.assertEqual(expected_url, project_helpers.GetThumbnailUrl('xyz'))
+ mock_get_default_gcs_bucket_name.assert_called_once()
+ mock_SignUrl.assert_called_once_with(bucket_name, 'xyz' + '-thumbnail')
+
+ def testIsValidProjectName_BadChars(self):
+ self.assertFalse(project_helpers.IsValidProjectName('spa ce'))
+ self.assertFalse(project_helpers.IsValidProjectName('under_score'))
+ self.assertFalse(project_helpers.IsValidProjectName('name.dot'))
+ self.assertFalse(project_helpers.IsValidProjectName('pie#sign$'))
+ self.assertFalse(project_helpers.IsValidProjectName('(who?)'))
+
+ def testIsValidProjectName_BadHyphen(self):
+ self.assertFalse(project_helpers.IsValidProjectName('name-'))
+ self.assertFalse(project_helpers.IsValidProjectName('-name'))
+ self.assertTrue(project_helpers.IsValidProjectName('project-name'))
+
+ def testIsValidProjectName_MinimumLength(self):
+ self.assertFalse(project_helpers.IsValidProjectName('x'))
+ self.assertTrue(project_helpers.IsValidProjectName('xy'))
+
+ def testIsValidProjectName_MaximumLength(self):
+ self.assertFalse(
+ project_helpers.IsValidProjectName(
+ 'x' * (project_constants.MAX_PROJECT_NAME_LENGTH + 1)))
+ self.assertTrue(
+ project_helpers.IsValidProjectName(
+ 'x' * (project_constants.MAX_PROJECT_NAME_LENGTH)))
+
+ def testIsValidProjectName_InvalidName(self):
+ self.assertFalse(project_helpers.IsValidProjectName(''))
+ self.assertFalse(project_helpers.IsValidProjectName('000'))
+
+ def testIsValidProjectName_ValidName(self):
+ self.assertTrue(project_helpers.IsValidProjectName('098asd'))
+ self.assertTrue(project_helpers.IsValidProjectName('one-two-three'))
+
+ def testAllProjectMembers(self):
+ p = project_pb2.Project()
+ self.assertEqual(project_helpers.AllProjectMembers(p), [])
+
+ p.owner_ids.extend([1, 2, 3])
+ p.committer_ids.extend([4, 5, 6])
+ p.contributor_ids.extend([7, 8, 9])
+ self.assertEqual(
+ project_helpers.AllProjectMembers(p), [1, 2, 3, 4, 5, 6, 7, 8, 9])
diff --git a/project/test/project_views_test.py b/project/test/project_views_test.py
new file mode 100644
index 0000000..940116e
--- /dev/null
+++ b/project/test/project_views_test.py
@@ -0,0 +1,112 @@
+# 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 project_views module."""
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+
+import unittest
+
+from framework import framework_views
+from project import project_views
+from proto import project_pb2
+from services import service_manager
+from testing import fake
+
+
+class ProjectAccessViewTest(unittest.TestCase):
+
+ def testAccessViews(self):
+ anyone_view = project_views.ProjectAccessView(
+ project_pb2.ProjectAccess.ANYONE)
+ self.assertEqual(anyone_view.key, int(project_pb2.ProjectAccess.ANYONE))
+
+ members_only_view = project_views.ProjectAccessView(
+ project_pb2.ProjectAccess.MEMBERS_ONLY)
+ self.assertEqual(members_only_view.key,
+ int(project_pb2.ProjectAccess.MEMBERS_ONLY))
+
+
+class ProjectViewTest(unittest.TestCase):
+
+ def setUp(self):
+ self.services = service_manager.Services(
+ project=fake.ProjectService(),
+ user=fake.UserService())
+ self.services.project.TestAddProject('test')
+
+ def testNormalProject(self):
+ project = self.services.project.GetProjectByName('fake cnxn', 'test')
+ project_view = project_views.ProjectView(project)
+ self.assertEqual('test', project_view.project_name)
+ self.assertEqual('/p/test', project_view.relative_home_url)
+ self.assertEqual('LIVE', project_view.state_name)
+
+ def testCachedContentTimestamp(self):
+ project = self.services.project.GetProjectByName('fake cnxn', 'test')
+
+ # Project was never updated since we added cached_content_timestamp.
+ project.cached_content_timestamp = 0
+ view = project_views.ProjectView(project, now=1 * 60 * 60 + 234)
+ self.assertEqual(1 * 60 * 60, view.cached_content_timestamp)
+
+ # Project was updated within the last hour, use that timestamp.
+ project.cached_content_timestamp = 1 * 60 * 60 + 123
+ view = project_views.ProjectView(project, now=1 * 60 * 60 + 234)
+ self.assertEqual(1 * 60 * 60 + 123, view.cached_content_timestamp)
+
+ # Project was not updated within the last hour, but user groups
+ # could have been updated on groups.google.com without any
+ # notification to us, so the client will ask for an updated feed
+ # at least once an hour.
+ project.cached_content_timestamp = 1 * 60 * 60 + 123
+ view = project_views.ProjectView(project, now=2 * 60 * 60 + 234)
+ self.assertEqual(2 * 60 * 60, view.cached_content_timestamp)
+
+
+class MemberViewTest(unittest.TestCase):
+
+ def setUp(self):
+ self.alice_view = framework_views.StuffUserView(111, 'alice', True)
+ self.bob_view = framework_views.StuffUserView(222, 'bob', True)
+ self.carol_view = framework_views.StuffUserView(333, 'carol', True)
+
+ self.project = project_pb2.Project()
+ self.project.project_name = 'proj'
+ self.project.owner_ids.append(111)
+ self.project.committer_ids.append(222)
+ self.project.contributor_ids.append(333)
+
+ def testViewingSelf(self):
+ member_view = project_views.MemberView(
+ 0, 111, self.alice_view, self.project, None)
+ self.assertFalse(member_view.viewing_self)
+ member_view = project_views.MemberView(
+ 222, 111, self.alice_view, self.project, None)
+ self.assertFalse(member_view.viewing_self)
+
+ member_view = project_views.MemberView(
+ 111, 111, self.alice_view, self.project, None)
+ self.assertTrue(member_view.viewing_self)
+
+ def testRoles(self):
+ member_view = project_views.MemberView(
+ 0, 111, self.alice_view, self.project, None)
+ self.assertEqual('Owner', member_view.role)
+ self.assertEqual('/p/proj/people/detail?u=111',
+ member_view.detail_url)
+
+ member_view = project_views.MemberView(
+ 0, 222, self.bob_view, self.project, None)
+ self.assertEqual('Committer', member_view.role)
+ self.assertEqual('/p/proj/people/detail?u=222',
+ member_view.detail_url)
+
+ member_view = project_views.MemberView(
+ 0, 333, self.carol_view, self.project, None)
+ self.assertEqual('Contributor', member_view.role)
+ self.assertEqual('/p/proj/people/detail?u=333',
+ member_view.detail_url)
diff --git a/project/test/projectadmin_test.py b/project/test/projectadmin_test.py
new file mode 100644
index 0000000..0257cd0
--- /dev/null
+++ b/project/test/projectadmin_test.py
@@ -0,0 +1,78 @@
+# 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 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 proto 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('req', 'res', 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.
diff --git a/project/test/projectadminadvanced_test.py b/project/test/projectadminadvanced_test.py
new file mode 100644
index 0000000..a654d98
--- /dev/null
+++ b/project/test/projectadminadvanced_test.py
@@ -0,0 +1,128 @@
+# 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 projectadminadvanced module."""
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+
+import time
+import unittest
+from mock import patch
+
+from framework import permissions
+from project import projectadminadvanced
+from proto import project_pb2
+from services import service_manager
+from testing import fake
+from testing import testing_helpers
+
+NOW = 1277762224
+
+
+class ProjectAdminAdvancedTest(unittest.TestCase):
+ """Unit tests for the ProjectAdminAdvanced servlet class."""
+
+ def setUp(self):
+ services = service_manager.Services(
+ project=fake.ProjectService())
+ self.servlet = projectadminadvanced.ProjectAdminAdvanced(
+ 'req', 'res', services=services)
+ self.project = services.project.TestAddProject('proj', owner_ids=[111])
+ self.mr = testing_helpers.MakeMonorailRequest(
+ project=self.project,
+ perms=permissions.OWNER_ACTIVE_PERMISSIONSET,
+ user_info={'user_id': 111})
+
+ def testAssertBasePermission(self):
+ # Signed-out users cannot edit the project
+ self.mr.perms = permissions.READ_ONLY_PERMISSIONSET
+ self.assertRaises(permissions.PermissionException,
+ self.servlet.AssertBasePermission, self.mr)
+
+ # Non-member users cannot edit the project
+ self.mr.perms = permissions.USER_PERMISSIONSET
+ self.assertRaises(permissions.PermissionException,
+ self.servlet.AssertBasePermission, self.mr)
+
+ # Contributors cannot edit the project
+ self.mr.perms = permissions.CONTRIBUTOR_ACTIVE_PERMISSIONSET
+ self.assertRaises(
+ permissions.PermissionException,
+ self.servlet.AssertBasePermission, self.mr)
+
+ self.mr.perms = permissions.OWNER_ACTIVE_PERMISSIONSET
+ self.servlet.AssertBasePermission(self.mr)
+
+ def testGatherPageData(self):
+ page_data = self.servlet.GatherPageData(self.mr)
+ self.assertEqual(self.servlet.ADMIN_TAB_ADVANCED,
+ page_data['admin_tab_mode'])
+
+ def testGatherPublishingOptions_Live(self):
+ pub_data = self.servlet._GatherPublishingOptions(self.mr)
+ self.assertTrue(pub_data['offer_archive'])
+ self.assertTrue(pub_data['offer_move'])
+ self.assertFalse(pub_data['offer_publish'])
+ self.assertFalse(pub_data['offer_delete'])
+ self.assertEqual('http://', pub_data['moved_to'])
+
+ def testGatherPublishingOptions_Moved(self):
+ self.project.moved_to = 'other location'
+ pub_data = self.servlet._GatherPublishingOptions(self.mr)
+ self.assertTrue(pub_data['offer_archive'])
+ self.assertTrue(pub_data['offer_move'])
+ self.assertFalse(pub_data['offer_publish'])
+ self.assertFalse(pub_data['offer_delete'])
+ self.assertEqual('other location', pub_data['moved_to'])
+
+ def testGatherPublishingOptions_Archived(self):
+ self.project.state = project_pb2.ProjectState.ARCHIVED
+ pub_data = self.servlet._GatherPublishingOptions(self.mr)
+ self.assertFalse(pub_data['offer_archive'])
+ self.assertFalse(pub_data['offer_move'])
+ self.assertTrue(pub_data['offer_publish'])
+ self.assertTrue(pub_data['offer_delete'])
+
+ def testGatherPublishingOptions_Doomed(self):
+ self.project.state = project_pb2.ProjectState.ARCHIVED
+ self.project.state_reason = 'you are a spammer'
+ pub_data = self.servlet._GatherPublishingOptions(self.mr)
+ self.assertFalse(pub_data['offer_archive'])
+ self.assertFalse(pub_data['offer_move'])
+ self.assertFalse(pub_data['offer_publish'])
+ self.assertTrue(pub_data['offer_delete'])
+
+ def testGatherQuotaData(self):
+ self.mr.perms = permissions.OWNER_ACTIVE_PERMISSIONSET
+ quota_data = self.servlet._GatherQuotaData(self.mr)
+ self.assertFalse(quota_data['offer_quota_editing'])
+
+ self.mr.perms = permissions.ADMIN_PERMISSIONSET
+ quota_data = self.servlet._GatherQuotaData(self.mr)
+ self.assertTrue(quota_data['offer_quota_editing'])
+
+ def testBuildComponentQuota(self):
+ ezt_item = self.servlet._BuildComponentQuota(
+ 5000, 10000, 'attachments')
+ self.assertEqual(50, ezt_item.used_percent)
+ self.assertEqual('attachments', ezt_item.field_name)
+
+ @patch('time.time')
+ def testProcessFormData_NotDeleted(self, mock_time):
+ mock_time.return_value = NOW
+ self.mr.project_name = 'proj'
+ post_data = fake.PostData()
+ next_url = self.servlet.ProcessFormData(self.mr, post_data)
+ self.assertEqual(
+ 'http://127.0.0.1/p/proj/adminAdvanced?saved=1&ts=%s' % NOW,
+ next_url)
+
+ def testProcessFormData_AfterDeletion(self):
+ self.mr.project_name = 'proj'
+ self.project.state = project_pb2.ProjectState.ARCHIVED
+ post_data = fake.PostData(deletebtn='1')
+ next_url = self.servlet.ProcessFormData(self.mr, post_data)
+ self.assertEqual('http://127.0.0.1/hosting_old/', next_url)
diff --git a/project/test/projectexport_test.py b/project/test/projectexport_test.py
new file mode 100644
index 0000000..6dbe990
--- /dev/null
+++ b/project/test/projectexport_test.py
@@ -0,0 +1,148 @@
+# 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 the projectexport servlet."""
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+
+import unittest
+
+from mock import Mock, patch
+
+from framework import permissions
+from project import projectexport
+from proto import tracker_pb2
+from services import service_manager
+from services.template_svc import TemplateService
+from testing import fake
+from testing import testing_helpers
+
+
+class ProjectExportTest(unittest.TestCase):
+
+ def setUp(self):
+ self.services = service_manager.Services()
+ self.servlet = projectexport.ProjectExport(
+ 'req', 'res', services=self.services)
+
+ def testAssertBasePermission(self):
+ mr = testing_helpers.MakeMonorailRequest(
+ perms=permissions.OWNER_ACTIVE_PERMISSIONSET)
+ self.assertRaises(permissions.PermissionException,
+ self.servlet.AssertBasePermission, mr)
+ mr.auth.user_pb.is_site_admin = True
+ self.servlet.AssertBasePermission(mr)
+
+
+class ProjectExportJSONTest(unittest.TestCase):
+
+ def setUp(self):
+ self.services = service_manager.Services(
+ config=fake.ConfigService(),
+ project=fake.ProjectService(),
+ user=fake.UserService(),
+ template=Mock(spec=TemplateService))
+ self.services.user.TestAddUser('user1@example.com', 111)
+ self.servlet = projectexport.ProjectExportJSON(
+ 'req', 'res', services=self.services)
+ self.project = fake.Project(project_id=789)
+ self.mr = testing_helpers.MakeMonorailRequest(
+ perms=permissions.OWNER_ACTIVE_PERMISSIONSET)
+ self.mr.auth.user_pb.is_site_admin = True
+ self.mr.project = self.project
+
+ @patch('time.time')
+ def testHandleRequest_Normal(self, mockTime):
+ mockTime.return_value = 123456789
+ self.services.project.GetProject = Mock(return_value=self.project)
+ test_config = fake.MakeTestConfig(project_id=789, labels=[], statuses=[])
+ self.services.config.GetProjectConfig = Mock(return_value=test_config)
+ test_templates = testing_helpers.DefaultTemplates()
+ self.services.template.GetProjectTemplates = Mock(
+ return_value=test_templates)
+ self.services.config.UsersInvolvedInConfig = Mock(return_value=[111])
+
+ json_data = self.servlet.HandleRequest(self.mr)
+
+ expected = {
+ 'project': {
+ 'committers': [],
+ 'owners': [],
+ 'recent_activity': 0,
+ 'name': 'proj',
+ 'contributors': [],
+ 'perms': [],
+ 'attachment_quota': None,
+ 'process_inbound_email': False,
+ 'revision_url_format': None,
+ 'summary': '',
+ 'access': 'ANYONE',
+ 'state': 'LIVE',
+ 'read_only_reason': None,
+ 'only_owners_remove_restrictions': False,
+ 'only_owners_see_contributors': False,
+ 'attachment_bytes': 0,
+ 'issue_notify_address': None,
+ 'description': ''
+ },
+ 'config': {
+ 'templates': [{
+ 'status': 'Accepted',
+ 'members_only': True,
+ 'labels': [],
+ 'summary_must_be_edited': True,
+ 'owner': None,
+ 'owner_defaults_to_member': True,
+ 'component_required': False,
+ 'name': 'Defect report from developer',
+ 'summary': 'Enter one-line summary',
+ 'content': 'What steps will reproduce the problem?\n1. \n2. \n3. \n'
+ '\n'
+ 'What is the expected output?\n\n\nWhat do you see instead?\n'
+ '\n\n'
+ 'Please use labels and text to provide additional information.\n',
+ 'admins': []
+ }, {
+ 'status': 'New',
+ 'members_only': False,
+ 'labels': [],
+ 'summary_must_be_edited': True,
+ 'owner': None,
+ 'owner_defaults_to_member': True,
+ 'component_required': False,
+ 'name': 'Defect report from user',
+ 'summary': 'Enter one-line summary', 'content': 'What steps will '
+ 'reproduce the problem?\n1. \n2. \n3. \n\nWhat is the expected '
+ 'output?\n\n\nWhat do you see instead?\n\n\nWhat version of the '
+ 'product are you using? On what operating system?\n\n\nPlease '
+ 'provide any additional information below.\n',
+ 'admins': []
+ }],
+ 'labels': [],
+ 'statuses_offer_merge': ['Duplicate'],
+ 'exclusive_label_prefixes': ['Type', 'Priority', 'Milestone'],
+ 'only_known_values': False,
+ 'statuses': [],
+ 'list_spec': '',
+ 'developer_template': 0,
+ 'user_template': 0,
+ 'grid_y': '',
+ 'grid_x': '',
+ 'components': [],
+ 'list_cols': 'ID Type Status Priority Milestone Owner Summary'
+ },
+ 'emails': ['user1@example.com'],
+ 'metadata': {
+ 'version': 1,
+ 'when': 123456789,
+ 'who': None,
+ }
+ }
+ self.assertDictEqual(expected, json_data)
+ self.services.template.GetProjectTemplates.assert_called_once_with(
+ self.mr.cnxn, 789)
+ self.services.config.UsersInvolvedInConfig.assert_called_once_with(
+ test_config, test_templates)
diff --git a/project/test/projectsummary_test.py b/project/test/projectsummary_test.py
new file mode 100644
index 0000000..033664d
--- /dev/null
+++ b/project/test/projectsummary_test.py
@@ -0,0 +1,85 @@
+# 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 Project Summary servlet."""
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+
+import unittest
+
+from framework import permissions
+from project import projectsummary
+from proto import project_pb2
+from proto import user_pb2
+from services import service_manager
+from testing import fake
+from testing import testing_helpers
+
+
+class ProjectSummaryTest(unittest.TestCase):
+
+ def setUp(self):
+ services = service_manager.Services(
+ project=fake.ProjectService(),
+ user=fake.UserService(),
+ usergroup=fake.UserGroupService(),
+ project_star=fake.ProjectStarService())
+ self.project = services.project.TestAddProject(
+ 'proj', project_id=123, summary='sum',
+ description='desc')
+ self.servlet = projectsummary.ProjectSummary(
+ 'req', 'res', services=services)
+
+ def testGatherPageData(self):
+ mr = testing_helpers.MakeMonorailRequest(project=self.project)
+ page_data = self.servlet.GatherPageData(mr)
+ self.assertEqual(
+ '<p>desc</p>', page_data['formatted_project_description'])
+ self.assertEqual(
+ int(project_pb2.ProjectAccess.ANYONE), page_data['access_level'].key)
+ self.assertEqual(0, page_data['num_stars'])
+ self.assertEqual('s', page_data['plural'])
+
+ def testGatherHelpData(self):
+ mr = testing_helpers.MakeMonorailRequest(project=self.project)
+
+ # Non-members cannot edit project, so cue is not relevant.
+ mr.perms = permissions.READ_ONLY_PERMISSIONSET
+ help_data = self.servlet.GatherHelpData(mr, {})
+ self.assertEqual(None, help_data['cue'])
+
+ # Members (not owners) cannot edit project, so cue is not relevant.
+ mr.perms = permissions.READ_ONLY_PERMISSIONSET
+ help_data = self.servlet.GatherHelpData(mr, {})
+ self.assertEqual(None, help_data['cue'])
+
+ # This is a project member who has set up mailing lists and added
+ # members, but has not noted any duties.
+ mr = testing_helpers.MakeMonorailRequest(project=self.project)
+ self.project.issue_notify_address = 'example@domain.com'
+ self.project.committer_ids.extend([111, 222])
+ help_data = self.servlet.GatherHelpData(mr, {})
+ self.assertEqual('document_team_duties', help_data['cue'])
+
+ # Now help set up notes too.
+ project_commitments = project_pb2.ProjectCommitments()
+ project_commitments.project_id = self.project.project_id
+ project_commitments.commitments.append(
+ project_pb2.ProjectCommitments.MemberCommitment())
+ self.servlet.services.project.TestStoreProjectCommitments(
+ project_commitments)
+ help_data = self.servlet.GatherHelpData(mr, {})
+ self.assertEqual(None, help_data['cue'])
+
+ def testGatherHelpData_Dismissed(self):
+ mr = testing_helpers.MakeMonorailRequest(project=self.project)
+ mr.auth.user_id = 111
+ self.project.committer_ids.extend([111, 222])
+ self.servlet.services.user.SetUserPrefs(
+ 'cnxn', 111,
+ [user_pb2.UserPrefValue(name='document_team_duties', value='true')])
+ help_data = self.servlet.GatherHelpData(mr, {})
+ self.assertEqual(None, help_data['cue'])
diff --git a/project/test/projectupdates_test.py b/project/test/projectupdates_test.py
new file mode 100644
index 0000000..c2542e8
--- /dev/null
+++ b/project/test/projectupdates_test.py
@@ -0,0 +1,60 @@
+# 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.project.projectupdates."""
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+
+import unittest
+
+import mox
+
+from features import activities
+from project import projectupdates
+from services import service_manager
+from testing import fake
+from testing import testing_helpers
+
+
+class ProjectUpdatesTest(unittest.TestCase):
+
+ def setUp(self):
+ self.services = service_manager.Services(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.mr = testing_helpers.MakeMonorailRequest(
+ services=self.services, project=self.project)
+ self.mr.project_name = self.project_name
+ self.project_updates = projectupdates.ProjectUpdates(
+ None, None, self.services)
+ self.mox = mox.Mox()
+
+ def tearDown(self):
+ self.mox.UnsetStubs()
+ self.mox.ResetAll()
+
+ def testGatherPageData(self):
+ self.mox.StubOutWithMock(activities, 'GatherUpdatesData')
+ activities.GatherUpdatesData(
+ self.services, self.mr, project_ids=[self.project_id],
+ ending='by_user',
+ updates_page_url='/p/%s/updates/list' % self.project_name,
+ autolink=self.services.autolink).AndReturn({'test': 'testing'})
+ self.mox.ReplayAll()
+
+ page_data = self.project_updates.GatherPageData(self.mr)
+ self.mox.VerifyAll()
+ self.assertEqual(
+ {
+ 'subtab_mode': None,
+ 'user_updates_tab_mode': None,
+ 'test': 'testing'
+ }, page_data)
diff --git a/project/test/redirects_test.py b/project/test/redirects_test.py
new file mode 100644
index 0000000..2f51495
--- /dev/null
+++ b/project/test/redirects_test.py
@@ -0,0 +1,90 @@
+# 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
+
+"""Tests for project handlers that redirect."""
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+
+import httplib
+import unittest
+
+import webapp2
+
+from framework import urls
+from project import redirects
+from services import service_manager
+from testing import fake
+from testing import testing_helpers
+
+
+class WikiRedirectTest(unittest.TestCase):
+
+ def setUp(self):
+ self.services = service_manager.Services()
+ self.servlet = redirects.WikiRedirect(
+ webapp2.Request.blank('url'), webapp2.Response(),
+ services=self.services)
+ self.project = fake.Project()
+ self.servlet.mr = testing_helpers.MakeMonorailRequest(
+ project=self.project)
+
+ def testRedirect_NoSuchProject(self):
+ """Visiting a project that we don't host is 404."""
+ self.servlet.mr.project = None
+ self.servlet.get()
+ self.assertEqual(
+ httplib.NOT_FOUND, self.servlet.response.status_code)
+
+ def testRedirect_NoDocsSpecified(self):
+ """Visiting any old wiki URL goes to admin intro by default."""
+ self.servlet.get()
+ self.assertEqual(
+ httplib.MOVED_PERMANENTLY, self.servlet.response.status_code)
+ self.assertTrue(
+ self.servlet.response.location.endswith(urls.ADMIN_INTRO))
+
+ def testRedirect_DocsSpecified(self):
+ """Visiting any old wiki URL goes to project docs URL."""
+ self.project.docs_url = 'some_url'
+ self.servlet.get()
+ self.assertEqual(
+ httplib.MOVED_PERMANENTLY, self.servlet.response.status_code)
+ self.assertEqual('some_url', self.servlet.response.location)
+
+
+class SourceRedirectTest(unittest.TestCase):
+
+ def setUp(self):
+ self.services = service_manager.Services()
+ self.servlet = redirects.SourceRedirect(
+ webapp2.Request.blank('url'), webapp2.Response(),
+ services=self.services)
+ self.project = fake.Project()
+ self.servlet.mr = testing_helpers.MakeMonorailRequest(
+ project=self.project)
+
+ def testRedirect_NoSuchProject(self):
+ """Visiting a project that we don't host is 404."""
+ self.servlet.mr.project = None
+ self.servlet.get()
+ self.assertEqual(
+ httplib.NOT_FOUND, self.servlet.response.status_code)
+
+ def testRedirect_NoSrcSpecified(self):
+ """Visiting any old source code URL goes to admin intro by default."""
+ self.servlet.get()
+ self.assertEqual(
+ httplib.MOVED_PERMANENTLY, self.servlet.response.status_code)
+ self.assertTrue(
+ self.servlet.response.location.endswith(urls.ADMIN_INTRO))
+
+ def testRedirect_SrcSpecified(self):
+ """Visiting any old source code URL goes to project source URL."""
+ self.project.source_url = 'some_url'
+ self.servlet.get()
+ self.assertEqual(
+ httplib.MOVED_PERMANENTLY, self.servlet.response.status_code)
+ self.assertEqual('some_url', self.servlet.response.location)