Allow replying to an individual note in the API

If you can do this in the UI, you should be able to do it in the API. If
a discussion is not a single note discussion, or it is replyable, you
can reply to it.
This commit is contained in:
Sean McGivern 2019-05-06 11:59:02 +01:00
parent 0a7c9660e6
commit 00af4c6d6a
5 changed files with 34 additions and 11 deletions

View file

@ -0,0 +1,5 @@
---
title: Allow replying to individual notes from API
merge_request:
author:
type: fixed

View file

@ -153,7 +153,8 @@ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab
### Add note to existing issue discussion ### Add note to existing issue discussion
Adds a new note to the discussion. Adds a new note to the discussion. This can also
[create a discussion from a single comment](../user/discussions/#start-a-discussion-by-replying-to-a-standard-comment).
``` ```
POST /projects/:id/issues/:issue_iid/discussions/:discussion_id/notes POST /projects/:id/issues/:issue_iid/discussions/:discussion_id/notes
@ -652,7 +653,8 @@ curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.
### Add note to existing merge request discussion ### Add note to existing merge request discussion
Adds a new note to the discussion. Adds a new note to the discussion. This can also
[create a discussion from a single comment](../user/discussions/#start-a-discussion-by-replying-to-a-standard-comment).
``` ```
POST /projects/:id/merge_requests/:merge_request_iid/discussions/:discussion_id/notes POST /projects/:id/merge_requests/:merge_request_iid/discussions/:discussion_id/notes

View file

@ -134,9 +134,13 @@ module API
post ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id/notes" do post ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id/notes" do
noteable = find_noteable(parent_type, noteables_str, params[:noteable_id]) noteable = find_noteable(parent_type, noteables_str, params[:noteable_id])
notes = readable_discussion_notes(noteable, params[:discussion_id]) notes = readable_discussion_notes(noteable, params[:discussion_id])
first_note = notes.first
break not_found!("Discussion") if notes.empty? break not_found!("Discussion") if notes.empty?
break bad_request!("Discussion is an individual note.") unless notes.first.part_of_discussion?
unless first_note.part_of_discussion? || first_note.to_discussion.can_convert_to_discussion?
break bad_request!("Discussion can not be replied to.")
end
opts = { opts = {
note: params[:body], note: params[:body],

View file

@ -13,7 +13,7 @@ describe API::Discussions do
let!(:issue) { create(:issue, project: project, author: user) } let!(:issue) { create(:issue, project: project, author: user) }
let!(:issue_note) { create(:discussion_note_on_issue, noteable: issue, project: project, author: user) } let!(:issue_note) { create(:discussion_note_on_issue, noteable: issue, project: project, author: user) }
it_behaves_like 'discussions API', 'projects', 'issues', 'iid' do it_behaves_like 'discussions API', 'projects', 'issues', 'iid', can_reply_to_invididual_notes: true do
let(:parent) { project } let(:parent) { project }
let(:noteable) { issue } let(:noteable) { issue }
let(:note) { issue_note } let(:note) { issue_note }
@ -37,7 +37,7 @@ describe API::Discussions do
let!(:diff_note) { create(:diff_note_on_merge_request, noteable: noteable, project: project, author: user) } let!(:diff_note) { create(:diff_note_on_merge_request, noteable: noteable, project: project, author: user) }
let(:parent) { project } let(:parent) { project }
it_behaves_like 'discussions API', 'projects', 'merge_requests', 'iid' it_behaves_like 'discussions API', 'projects', 'merge_requests', 'iid', can_reply_to_invididual_notes: true
it_behaves_like 'diff discussions API', 'projects', 'merge_requests', 'iid' it_behaves_like 'diff discussions API', 'projects', 'merge_requests', 'iid'
it_behaves_like 'resolvable discussions API', 'projects', 'merge_requests', 'iid' it_behaves_like 'resolvable discussions API', 'projects', 'merge_requests', 'iid'
end end

View file

@ -1,4 +1,4 @@
shared_examples 'discussions API' do |parent_type, noteable_type, id_name| shared_examples 'discussions API' do |parent_type, noteable_type, id_name, can_reply_to_invididual_notes: false|
describe "GET /#{parent_type}/:id/#{noteable_type}/:noteable_id/discussions" do describe "GET /#{parent_type}/:id/#{noteable_type}/:noteable_id/discussions" do
it "returns an array of discussions" do it "returns an array of discussions" do
get api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/discussions", user) get api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/discussions", user)
@ -136,13 +136,25 @@ shared_examples 'discussions API' do |parent_type, noteable_type, id_name|
expect(response).to have_gitlab_http_status(400) expect(response).to have_gitlab_http_status(400)
end end
it "returns a 400 bad request error if discussion is individual note" do context 'when the discussion is an individual note' do
note.update_attribute(:type, nil) before do
note.update!(type: nil)
post api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/"\ post api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/"\
"discussions/#{note.discussion_id}/notes", user), params: { body: 'hi!' } "discussions/#{note.discussion_id}/notes", user), params: { body: 'hi!' }
end
expect(response).to have_gitlab_http_status(400) if can_reply_to_invididual_notes
it 'creates a new discussion' do
expect(response).to have_gitlab_http_status(201)
expect(json_response['body']).to eq('hi!')
expect(json_response['type']).to eq('DiscussionNote')
end
else
it 'returns 400 bad request' do
expect(response).to have_gitlab_http_status(400)
end
end
end end
end end