blob: 0a8f06c46ef65fc7d2cf8d73b3204760ca077be3 [file] [log] [blame]
# Copyright 2017 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.
import datetime
import mock
import unittest
from dashboard.api import api_auth
from dashboard.api import bugs
from dashboard.common import testing_common
from dashboard.common import utils
from dashboard.models import try_job
class MockIssueTrackerService(object):
"""A fake version of IssueTrackerService that returns expected data."""
def __init__(self, http=None):
pass
@classmethod
def GetIssue(cls, _):
return {
'cc': [
{
'kind': 'monorail#issuePerson',
'htmlLink': 'https://bugs.chromium.org/u/1253971105',
'name': 'user@chromium.org',
}, {
'kind': 'monorail#issuePerson',
'name': 'hello@world.org',
}
],
'labels': [
'Type-Bug',
'Pri-3',
'M-61',
],
'owner': {
'kind': 'monorail#issuePerson',
'htmlLink': 'https://bugs.chromium.org/u/49586776',
'name': 'owner@chromium.org',
},
'id': 737355,
'author': {
'kind': 'monorail#issuePerson',
'htmlLink': 'https://bugs.chromium.org/u/49586776',
'name': 'author@chromium.org',
},
'state': 'closed',
'status': 'Fixed',
'summary': 'The bug title',
'components': [
'Blink>ServiceWorker',
'Foo>Bar',
],
'published': '2017-06-28T01:26:53',
'updated': '2018-03-01T16:16:22',
}
@classmethod
def GetIssueComments(cls, _):
return [{
'content': 'Comment one',
'published': '2017-06-28T04:42:55',
'author': 'comment-one-author@company.com',
}, {
'content': 'Comment two',
'published': '2017-06-28T10:16:14',
'author': 'author-two@chromium.org'
}]
class BugsTest(testing_common.TestCase):
def setUp(self):
super(BugsTest, self).setUp()
self.SetUpApp([(r'/api/bugs/(.*)', bugs.BugsHandler)])
# Add a fake issue tracker service that we can get call values from.
self.original_service = bugs.issue_tracker_service.IssueTrackerService
bugs.issue_tracker_service = mock.MagicMock()
self.service = MockIssueTrackerService
bugs.issue_tracker_service.IssueTrackerService = self.service
self.SetCurrentClientIdOAuth(api_auth.OAUTH_CLIENT_ID_WHITELIST[0])
def tearDown(self):
super(BugsTest, self).tearDown()
bugs.issue_tracker_service.IssueTrackerService = self.original_service
@mock.patch.object(utils, 'ServiceAccountHttp', mock.MagicMock())
def testPost_WithValidBug_ShowsData(self):
self.SetCurrentUserOAuth(testing_common.INTERNAL_USER)
try_job.TryJob(
bug_id=123456, status='started', bot='win_perf',
results_data={}, config='config = {"command": "cmd"}',
last_ran_timestamp=datetime.datetime(2017, 01, 01)).put()
try_job.TryJob(
bug_id=123456, status='failed', bot='android_bisect',
results_data={'metric': 'foo'},
config='config = {"command": "cmd"}').put()
try_job.TryJob(
bug_id=99999, status='failed', bot='win_perf',
results_data={'metric': 'foo'},
config='config = {"command": "cmd"}').put()
response = self.Post('/api/bugs/123456?include_comments=true')
bug = self.GetJsonValue(response, 'bug')
self.assertEqual('The bug title', bug.get('summary'))
self.assertEqual(2, len(bug.get('cc')))
self.assertEqual('hello@world.org', bug.get('cc')[1])
self.assertEqual('Fixed', bug.get('status'))
self.assertEqual('closed', bug.get('state'))
self.assertEqual('author@chromium.org', bug.get('author'))
self.assertEqual('owner@chromium.org', bug.get('owner'))
self.assertEqual('2017-06-28T01:26:53', bug.get('published'))
self.assertEqual('2018-03-01T16:16:22', bug.get('updated'))
self.assertEqual(2, len(bug.get('comments')))
self.assertEqual('Comment two', bug.get('comments')[1].get('content'))
self.assertEqual(
'author-two@chromium.org', bug.get('comments')[1].get('author'))
self.assertEqual(2, len(bug.get('legacy_bisects')))
self.assertEqual('started', bug.get('legacy_bisects')[0].get('status'))
self.assertEqual('cmd', bug.get('legacy_bisects')[0].get('command'))
self.assertEqual('2017-01-01T00:00:00', bug.get('legacy_bisects')[0].get(
'started_timestamp'))
self.assertEqual('', bug.get('legacy_bisects')[1].get(
'started_timestamp'))
@mock.patch.object(utils, 'ServiceAccountHttp', mock.MagicMock())
def testPost_WithValidBugButNoComments(self):
self.SetCurrentUserOAuth(testing_common.INTERNAL_USER)
try_job.TryJob(
bug_id=123456, status='started', bot='win_perf',
results_data={}, config='config = {"command": "cmd"}',
last_ran_timestamp=datetime.datetime(2017, 01, 01)).put()
try_job.TryJob(
bug_id=123456, status='failed', bot='android_bisect',
results_data={'metric': 'foo'},
config='config = {"command": "cmd"}').put()
try_job.TryJob(
bug_id=99999, status='failed', bot='win_perf',
results_data={'metric': 'foo'},
config='config = {"command": "cmd"}').put()
response = self.Post('/api/bugs/123456')
bug = self.GetJsonValue(response, 'bug')
self.assertNotIn('comments', bug)
@mock.patch.object(utils, 'ServiceAccountHttp', mock.MagicMock())
def testPost_WithInvalidBugIdParameter_ShowsError(self):
self.SetCurrentUserOAuth(testing_common.INTERNAL_USER)
response = self.Post('/api/bugs/foo', status=400)
self.assertIn('Invalid bug ID \\"foo\\".', response.body)
@mock.patch.object(utils, 'ServiceAccountHttp', mock.MagicMock())
def testPost_NoAccess_ShowsError(self):
self.SetCurrentUserOAuth(testing_common.EXTERNAL_USER)
response = self.Post('/api/bugs/foo', status=403)
self.assertIn('Access denied', response.body)
def testPost_NoOauthUser(self):
self.SetCurrentUserOAuth(None)
self.Post('/api/bugs/12345', status=401)
def testPost_BadOauthClientId(self):
self.SetCurrentUserOAuth(testing_common.INTERNAL_USER)
self.SetCurrentClientIdOAuth('invalid')
self.Post('/api/bugs/12345', status=403)
if __name__ == '__main__':
unittest.main()