blob: 124aa7f8ca14f03b3e49fad4662d093f5a689c9a [file] [log] [blame]
# Copyright 2016 The Chromium Authors. All rights reserved.
# Use of this source code is govered 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 issue tracker views."""
import unittest
import mox
from google.appengine.api import app_identity
from third_party import ezt
from framework import gcs_helpers
from framework import urls
from proto import project_pb2
from proto import tracker_pb2
from testing import testing_helpers
from tracker import tracker_views
def _Issue(project_name, local_id, summary, status):
issue = tracker_pb2.Issue()
issue.project_name = project_name
issue.local_id = local_id
issue.issue_id = 100000 + local_id
issue.summary = summary
issue.status = status
return issue
def _MakeConfig():
config = tracker_pb2.ProjectIssueConfig()
config.well_known_statuses.append(tracker_pb2.StatusDef(
status='New', means_open=True))
config.well_known_statuses.append(tracker_pb2.StatusDef(
status='Old', means_open=False))
return config
class IssueViewTest(unittest.TestCase):
def setUp(self):
self.issue1 = _Issue('proj', 1, 'not too long summary', 'New')
self.issue2 = _Issue('proj', 2, 'sum 2', '')
self.issue3 = _Issue('proj', 3, 'sum 3', '')
self.issue4 = _Issue('proj', 4, 'sum 4', '')
self.issue1.reporter_id = 1002
self.issue1.owner_id = 2002
self.issue1.labels.extend(['A', 'B'])
self.issue1.derived_labels.extend(['C', 'D'])
self.issue2.reporter_id = 2002
self.issue2.labels.extend(['foo', 'bar'])
self.issue2.blocked_on_iids.extend(
[self.issue1.issue_id, self.issue3.issue_id])
self.issue2.blocking_iids.extend(
[self.issue1.issue_id, self.issue4.issue_id])
dref = tracker_pb2.DanglingIssueRef()
dref.project = 'codesite'
dref.issue_id = 5001
self.issue2.dangling_blocking_refs.append(dref)
self.issue3.reporter_id = 3002
self.issue3.labels.extend(['Hot'])
self.issue4.reporter_id = 3002
self.issue4.labels.extend(['Foo', 'Bar'])
self.restricted = _Issue('proj', 7, 'summary 7', '')
self.restricted.labels.extend([
'Restrict-View-Commit', 'Restrict-View-MyCustomPerm'])
self.restricted.derived_labels.extend([
'Restrict-AddIssueComment-Commit', 'Restrict-EditIssue-Commit',
'Restrict-Action-NeededPerm'])
self.users_by_id = {
0: 'user 0',
1002: 'user 1002',
2002: 'user 2002',
3002: 'user 3002',
4002: 'user 4002',
}
def CheckSimpleIssueView(self, config):
view1 = tracker_views.IssueView(
self.issue1, self.users_by_id, config)
self.assertEqual('not too long summary', view1.summary)
self.assertEqual('New', view1.status.name)
self.assertEqual('user 2002', view1.owner)
self.assertEqual('A', view1.labels[0].name)
self.assertEqual('B', view1.labels[1].name)
self.assertEqual('C', view1.derived_labels[0].name)
self.assertEqual('D', view1.derived_labels[1].name)
self.assertEqual([], view1.blocked_on)
self.assertEqual([], view1.blocking)
detail_url = '/p/%s%s?id=%d' % (
self.issue1.project_name, urls.ISSUE_DETAIL,
self.issue1.local_id)
self.assertEqual(detail_url, view1.detail_relative_url)
return view1
def testSimpleIssueView(self):
config = tracker_pb2.ProjectIssueConfig()
view1 = self.CheckSimpleIssueView(config)
self.assertEqual('', view1.status.docstring)
config.well_known_statuses.append(tracker_pb2.StatusDef(
status='New', status_docstring='Issue has not had review yet'))
view1 = self.CheckSimpleIssueView(config)
self.assertEqual('Issue has not had review yet',
view1.status.docstring)
self.assertIsNone(view1.restrictions.has_restrictions)
self.assertEqual('', view1.restrictions.view)
self.assertEqual('', view1.restrictions.add_comment)
self.assertEqual('', view1.restrictions.edit)
def testIsOpen(self):
config = _MakeConfig()
view1 = tracker_views.IssueView(
self.issue1, self.users_by_id, config)
self.assertEqual(ezt.boolean(True), view1.is_open)
self.issue1.status = 'Old'
view1 = tracker_views.IssueView(
self.issue1, self.users_by_id, config)
self.assertEqual(ezt.boolean(False), view1.is_open)
def testIssueViewWithBlocking(self):
# Treat issues 3 and 4 as visible to the current user.
view2 = tracker_views.IssueView(
self.issue2, self.users_by_id, _MakeConfig(),
open_related={self.issue1.issue_id: self.issue1,
self.issue3.issue_id: self.issue3},
closed_related={self.issue4.issue_id: self.issue4})
self.assertEqual(['not too long summary', 'sum 3'],
[ref.summary for ref in view2.blocked_on])
self.assertEqual(['not too long summary', 'sum 4',
'Issue 5001 in codesite.'],
[ref.summary for ref in view2.blocking])
# Now, treat issues 3 and 4 as not visible to the current user.
view2 = tracker_views.IssueView(
self.issue2, self.users_by_id, _MakeConfig(),
open_related={self.issue1.issue_id: self.issue1}, closed_related={})
self.assertEqual(['not too long summary'],
[ref.summary for ref in view2.blocked_on])
self.assertEqual(['not too long summary', 'Issue 5001 in codesite.'],
[ref.summary for ref in view2.blocking])
# Treat nothing as visible to the current user. Can still see dangling ref.
view2 = tracker_views.IssueView(
self.issue2, self.users_by_id, _MakeConfig(),
open_related={}, closed_related={})
self.assertEqual([], view2.blocked_on)
self.assertEqual(['Issue 5001 in codesite.'],
[ref.summary for ref in view2.blocking])
def testIssueViewWithRestrictions(self):
view = tracker_views.IssueView(
self.restricted, self.users_by_id, _MakeConfig())
self.assertTrue(view.restrictions.has_restrictions)
self.assertEqual('Commit and MyCustomPerm', view.restrictions.view)
self.assertEqual('Commit', view.restrictions.add_comment)
self.assertEqual('Commit', view.restrictions.edit)
self.assertEqual(['Restrict-Action-NeededPerm'], view.restrictions.other)
self.assertEqual('Restrict-View-Commit', view.labels[0].name)
self.assertTrue(view.labels[0].is_restrict)
class RestrictionsViewTest(unittest.TestCase):
pass # TODO(jrobbins): write tests
class IssueRefViewTest(unittest.TestCase):
issue1 = testing_helpers.Blank(
local_id=1,
project_name='foo',
summary='blue screen')
issue2 = testing_helpers.Blank(
local_id=2,
project_name='foo',
summary='hissing noise')
issue3 = testing_helpers.Blank(
local_id=3,
project_name='foo',
summary='sinking feeling')
issue4 = testing_helpers.Blank(
local_id=4,
project_name='bar',
summary='aliens among us')
def testNormalCase(self):
open_list = {1: self.issue1,
2: self.issue2}
closed_list = {3: self.issue3}
ref_iid = 1
irv = tracker_views.IssueRefView('foo', ref_iid, open_list, closed_list)
self.assertEquals(irv.visible, ezt.boolean(True))
self.assertEquals(irv.is_open, ezt.boolean(True))
self.assertEquals(irv.url, 'detail?id=1')
self.assertEquals(irv.display_name, 'issue 1')
self.assertEquals(irv.summary, 'blue screen')
ref_iid = 3
irv = tracker_views.IssueRefView('foo', ref_iid, open_list, closed_list)
self.assertEquals(irv.visible, ezt.boolean(True))
self.assertEquals(irv.is_open, ezt.boolean(False))
self.assertEquals(irv.url, 'detail?id=3')
self.assertEquals(irv.display_name, 'issue 3')
self.assertEquals(irv.summary, 'sinking feeling')
def testMissingIssueShouldNotBeVisible(self):
open_list = {1: self.issue1,
2: self.issue2}
closed_list = {3: self.issue3}
ref_iid = 99
irv = tracker_views.IssueRefView('foo', ref_iid, open_list, closed_list)
self.assertEquals(irv.visible, ezt.boolean(False))
def testCrossProjectReference(self):
open_list = {1: self.issue1,
2: self.issue2}
closed_list = {3: self.issue3,
4: self.issue4}
ref_iid = 4
irv = tracker_views.IssueRefView('foo', ref_iid, open_list, closed_list)
self.assertEquals(irv.visible, ezt.boolean(True))
self.assertEquals(irv.is_open, ezt.boolean(False))
self.assertEquals(
irv.url, '/p/bar%s?id=4' % urls.ISSUE_DETAIL)
self.assertEquals(irv.display_name, 'issue bar:4')
self.assertEquals(irv.summary, 'aliens among us')
class DanglingIssueRefViewTest(unittest.TestCase):
pass # TODO(jrobbins): write tests
class AttachmentViewTest(unittest.TestCase):
def MakeViewAndVerifyFields(
self, size, name, mimetype, expected_size_str, expect_viewable):
attach_pb = tracker_pb2.Attachment()
attach_pb.filesize = size
attach_pb.attachment_id = 12345
attach_pb.filename = name
attach_pb.mimetype = mimetype
view = tracker_views.AttachmentView(attach_pb, 'proj')
self.assertEqual('/images/paperclip.png', view.iconurl)
self.assertEqual(expected_size_str, view.filesizestr)
dl = 'attachment?aid=12345'
self.assertEqual(dl, view.downloadurl)
if expect_viewable:
self.assertEqual(dl + '&inline=1', view.url)
self.assertEqual(dl + '&inline=1&thumb=1', view.thumbnail_url)
else:
self.assertEqual(None, view.url)
self.assertEqual(None, view.thumbnail_url)
def testNonImage(self):
self.MakeViewAndVerifyFields(
123, 'file.ext', 'funky/bits', '123 bytes', False)
def testViewableImage(self):
self.MakeViewAndVerifyFields(
123, 'logo.gif', 'image/gif', '123 bytes', True)
self.MakeViewAndVerifyFields(
123, 'screenshot.jpg', 'image/jpeg', '123 bytes', True)
def testHugeImage(self):
self.MakeViewAndVerifyFields(
18 * 1024 * 1024, 'panorama.png', 'image/jpeg', '18.0 MB', False)
def testViewableText(self):
name = 'hello.c'
attach_pb = tracker_pb2.Attachment()
attach_pb.filesize = 1234
attach_pb.attachment_id = 12345
attach_pb.filename = name
attach_pb.mimetype = 'text/plain'
view = tracker_views.AttachmentView(attach_pb, 'proj')
view_url = '/p/proj/issues/attachmentText?aid=12345'
self.assertEqual(view_url, view.url)
class LogoViewTest(unittest.TestCase):
def setUp(self):
self.mox = mox.Mox()
def tearDown(self):
self.mox.UnsetStubs()
self.mox.ResetAll()
def testProjectWithLogo(self):
bucket_name = 'testbucket'
logo_gcs_id = '123'
logo_file_name = 'logo.png'
project_pb = project_pb2.MakeProject(
'testProject', logo_gcs_id=logo_gcs_id, logo_file_name=logo_file_name)
object_path = '/' + bucket_name + logo_gcs_id
self.mox.StubOutWithMock(app_identity, 'get_default_gcs_bucket_name')
app_identity.get_default_gcs_bucket_name().AndReturn(bucket_name)
self.mox.StubOutWithMock(gcs_helpers, 'SignUrl')
gcs_helpers.SignUrl(object_path + '-thumbnail').AndReturn('signed/url')
gcs_helpers.SignUrl(object_path).AndReturn('signed/url')
self.mox.ReplayAll()
view = tracker_views.LogoView(project_pb)
self.mox.VerifyAll()
self.assertEquals('logo.png', view.filename)
self.assertEquals('image/png', view.mimetype)
self.assertEquals('signed/url', view.thumbnail_url)
self.assertEquals('signed/url&response-content-displacement=attachment%3B'
'+filename%3Dlogo.png', view.viewurl)
def testProjectWithNoLogo(self):
project_pb = project_pb2.MakeProject('testProject')
view = tracker_views.LogoView(project_pb)
self.assertEquals('', view.thumbnail_url)
self.assertEquals('', view.viewurl)
class IsViewableImageTest(unittest.TestCase):
def testIsViewableImage(self):
self.assertTrue(tracker_views.IsViewableImage('image/gif', 123))
self.assertTrue(tracker_views.IsViewableImage(
'image/gif; charset=binary', 123))
self.assertTrue(tracker_views.IsViewableImage('image/png', 123))
self.assertTrue(tracker_views.IsViewableImage(
'image/png; charset=binary', 123))
self.assertTrue(tracker_views.IsViewableImage('image/x-png', 123))
self.assertTrue(tracker_views.IsViewableImage('image/jpeg', 123))
self.assertTrue(tracker_views.IsViewableImage(
'image/jpeg; charset=binary', 123))
self.assertTrue(tracker_views.IsViewableImage(
'image/jpeg', 3 * 1024 * 1024))
self.assertFalse(tracker_views.IsViewableImage('junk/bits', 123))
self.assertFalse(tracker_views.IsViewableImage(
'junk/bits; charset=binary', 123))
self.assertFalse(tracker_views.IsViewableImage(
'image/jpeg', 13 * 1024 * 1024))
class IsViewableTextTest(unittest.TestCase):
pass # TODO(jrobbins): write tests
class AmendmentViewTest(unittest.TestCase):
pass # TODO(jrobbins): write tests
class ComponentDefViewTest(unittest.TestCase):
pass # TODO(jrobbins): write tests
class ComponentValueTest(unittest.TestCase):
pass # TODO(jrobbins): write tests
class FieldValueViewTest(unittest.TestCase):
pass # TODO(jrobbins): write tests
class FieldValueViewTest_Applicability(unittest.TestCase):
pass # TODO(jrobbins): write tests
class MakeFieldValueViewTest(unittest.TestCase):
pass # TODO(jrobbins): write tests
class FindFieldValuesTest(unittest.TestCase):
pass # TODO(jrobbins): write tests
class MakeBounceFieldValueViewsTest(unittest.TestCase):
pass # TODO(jrobbins): write tests
class ConvertLabelsToFieldValuesTest(unittest.TestCase):
def testConvertLabelsToFieldValues_NoLabels(self):
result = tracker_views._ConvertLabelsToFieldValues(
[], 'opsys', {})
self.assertEqual([], result)
def testConvertLabelsToFieldValues_NoMatch(self):
result = tracker_views._ConvertLabelsToFieldValues(
['Pri-3', 'M-44', 'Security', 'Via-Wizard'], 'opsys', {})
self.assertEqual([], result)
def testConvertLabelsToFieldValues_HasMatch(self):
result = tracker_views._ConvertLabelsToFieldValues(
['Pri-3', 'M-44', 'Security', 'OpSys-OSX'], 'opsys', {})
self.assertEqual(1, len(result))
self.assertEqual('OSX', result[0].val)
self.assertEqual('OSX', result[0].val_short)
self.assertEqual('', result[0].docstring)
result = tracker_views._ConvertLabelsToFieldValues(
['Pri-3', 'M-44', 'Security', 'OpSys-OSX', 'OpSys-All'],
'opsys', {'OpSys-All': 'Happens everywhere'})
self.assertEqual(2, len(result))
self.assertEqual('OSX', result[0].val)
self.assertEqual('OSX', result[0].val_short)
self.assertEqual('', result[0].docstring)
self.assertEqual('All', result[1].val)
self.assertEqual('All', result[1].val_short)
self.assertEqual('Happens everywhere', result[1].docstring)
class FieldDefViewTest(unittest.TestCase):
pass # TODO(jrobbins): write tests
class IssueTemplateViewTest(unittest.TestCase):
pass # TODO(jrobbins): write tests
class MakeFieldUserViewsTest(unittest.TestCase):
pass # TODO(jrobbins): write tests
class ConfigViewTest(unittest.TestCase):
pass # TODO(jrobbins): write tests
if __name__ == '__main__':
unittest.main()