diff --git a/rhodecode/api/tests/test_get_pull_request_comments.py b/rhodecode/api/tests/test_get_pull_request_comments.py new file mode 100644 --- /dev/null +++ b/rhodecode/api/tests/test_get_pull_request_comments.py @@ -0,0 +1,82 @@ +# -*- coding: utf-8 -*- + +# Copyright (C) 2010-2017 RhodeCode GmbH +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License, version 3 +# (only), as published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +# This program is dual-licensed. If you wish to learn more about the +# RhodeCode Enterprise Edition, including its added features, Support services, +# and proprietary license terms, please see https://rhodecode.com/licenses/ + + +import pytest +import urlobject + +from rhodecode.api.tests.utils import ( + build_data, api_call, assert_error, assert_ok) +from rhodecode.lib import helpers as h +from rhodecode.lib.utils2 import safe_unicode + +pytestmark = pytest.mark.backends("git", "hg") + + +@pytest.mark.usefixtures("testuser_api", "app") +class TestGetPullRequestComments(object): + + def test_api_get_pull_request_comments(self, pr_util, http_host_only_stub): + from rhodecode.model.pull_request import PullRequestModel + + pull_request = pr_util.create_pull_request(mergeable=True) + id_, params = build_data( + self.apikey, 'get_pull_request_comments', + pullrequestid=pull_request.pull_request_id) + + response = api_call(self.app, params) + + assert response.status == '200 OK' + resp_date = response.json['result'][0]['comment_created_on'] + resp_comment_id = response.json['result'][0]['comment_id'] + + expected = [ + {'comment_author': {'active': True, + 'full_name_or_username': 'RhodeCode Admin', + 'username': 'test_admin'}, + 'comment_created_on': resp_date, + 'comment_f_path': None, + 'comment_id': resp_comment_id, + 'comment_lineno': None, + 'comment_status': {'status': 'under_review', + 'status_lbl': 'Under Review'}, + 'comment_text': 'Auto status change to |new_status|\n\n.. |new_status| replace:: *"Under Review"*', + 'comment_type': 'note', + 'pull_request_version': None} + ] + assert_ok(id_, expected, response.body) + + def test_api_get_pull_request_comments_repo_error(self, pr_util): + pull_request = pr_util.create_pull_request() + id_, params = build_data( + self.apikey, 'get_pull_request_comments', + repoid=666, pullrequestid=pull_request.pull_request_id) + response = api_call(self.app, params) + + expected = 'repository `666` does not exist' + assert_error(id_, expected, given=response.body) + + def test_api_get_pull_request_comments_pull_request_error(self): + id_, params = build_data( + self.apikey, 'get_pull_request_comments', pullrequestid=666) + response = api_call(self.app, params) + + expected = 'pull request `666` does not exist' + assert_error(id_, expected, given=response.body) diff --git a/rhodecode/api/views/pull_request_api.py b/rhodecode/api/views/pull_request_api.py --- a/rhodecode/api/views/pull_request_api.py +++ b/rhodecode/api/views/pull_request_api.py @@ -311,6 +311,109 @@ def merge_pull_request( @jsonrpc_method() +def get_pull_request_comments( + request, apiuser, pullrequestid, repoid=Optional(None)): + """ + Get all comments of pull request specified with the `pullrequestid` + + :param apiuser: This is filled automatically from the |authtoken|. + :type apiuser: AuthUser + :param repoid: Optional repository name or repository ID. + :type repoid: str or int + :param pullrequestid: The pull request ID. + :type pullrequestid: int + + Example output: + + .. code-block:: bash + + id : + result : [ + { + "comment_author": { + "active": true, + "full_name_or_username": "Tom Gore", + "username": "admin" + }, + "comment_created_on": "2017-01-02T18:43:45.533", + "comment_f_path": null, + "comment_id": 25, + "comment_lineno": null, + "comment_status": { + "status": "under_review", + "status_lbl": "Under Review" + }, + "comment_text": "Example text", + "comment_type": null, + "pull_request_version": null + } + ], + error : null + """ + + pull_request = get_pull_request_or_error(pullrequestid) + if Optional.extract(repoid): + repo = get_repo_or_error(repoid) + else: + repo = pull_request.target_repo + + if not PullRequestModel().check_user_read( + pull_request, apiuser, api=True): + raise JSONRPCError('repository `%s` or pull request `%s` ' + 'does not exist' % (repoid, pullrequestid)) + + (pull_request_latest, + pull_request_at_ver, + pull_request_display_obj, + at_version) = PullRequestModel().get_pr_version( + pull_request.pull_request_id, version=None) + + versions = pull_request_display_obj.versions() + ver_map = { + ver.pull_request_version_id: cnt + for cnt, ver in enumerate(versions, 1) + } + + # GENERAL COMMENTS with versions # + q = CommentsModel()._all_general_comments_of_pull_request(pull_request) + q = q.order_by(ChangesetComment.comment_id.asc()) + general_comments = q.all() + + # INLINE COMMENTS with versions # + q = CommentsModel()._all_inline_comments_of_pull_request(pull_request) + q = q.order_by(ChangesetComment.comment_id.asc()) + inline_comments = q.all() + + data = [] + for comment in inline_comments + general_comments: + full_data = comment.get_api_data() + pr_version_id = None + if comment.pull_request_version_id: + pr_version_id = 'v{}'.format( + ver_map[comment.pull_request_version_id]) + + # sanitize some entries + + full_data['pull_request_version'] = pr_version_id + full_data['comment_author'] = { + 'username': full_data['comment_author'].username, + 'full_name_or_username': full_data['comment_author'].full_name_or_username, + 'active': full_data['comment_author'].active, + } + + if full_data['comment_status']: + full_data['comment_status'] = { + 'status': full_data['comment_status'][0].status, + 'status_lbl': full_data['comment_status'][0].status_lbl, + } + else: + full_data['comment_status'] = {} + + data.append(full_data) + return data + + +@jsonrpc_method() def comment_pull_request( request, apiuser, repoid, pullrequestid, message=Optional(None), commit_id=Optional(None), status=Optional(None),