diff options
Diffstat (limited to 'spec/requests/api/issues')
-rw-r--r-- | spec/requests/api/issues/issues_spec.rb | 6 | ||||
-rw-r--r-- | spec/requests/api/issues/put_projects_issues_spec.rb | 223 |
2 files changed, 116 insertions, 113 deletions
diff --git a/spec/requests/api/issues/issues_spec.rb b/spec/requests/api/issues/issues_spec.rb index 06878f57d43..315396c89c3 100644 --- a/spec/requests/api/issues/issues_spec.rb +++ b/spec/requests/api/issues/issues_spec.rb @@ -834,6 +834,12 @@ describe API::Issues do end end + describe 'PUT /projects/:id/issues/:issue_id' do + it_behaves_like 'issuable update endpoint' do + let(:entity) { issue } + end + end + describe 'DELETE /projects/:id/issues/:issue_iid' do it 'rejects a non member from deleting an issue' do delete api("/projects/#{project.id}/issues/#{issue.iid}", non_member) diff --git a/spec/requests/api/issues/put_projects_issues_spec.rb b/spec/requests/api/issues/put_projects_issues_spec.rb index 2ab8b9d7877..62a4d3b48b2 100644 --- a/spec/requests/api/issues/put_projects_issues_spec.rb +++ b/spec/requests/api/issues/put_projects_issues_spec.rb @@ -5,10 +5,6 @@ require 'spec_helper' describe API::Issues do let_it_be(:user) { create(:user) } let_it_be(:owner) { create(:owner) } - let_it_be(:project, reload: true) do - create(:project, :public, creator_id: owner.id, namespace: owner.namespace) - end - let(:user2) { create(:user) } let(:non_member) { create(:user) } let_it_be(:guest) { create(:user) } @@ -17,6 +13,11 @@ describe API::Issues do let(:admin) { create(:user, :admin) } let(:issue_title) { 'foo' } let(:issue_description) { 'closed' } + + let_it_be(:project, reload: true) do + create(:project, :public, creator_id: owner.id, namespace: owner.namespace) + end + let!(:closed_issue) do create :closed_issue, author: user, @@ -28,6 +29,7 @@ describe API::Issues do updated_at: 3.hours.ago, closed_at: 1.hour.ago end + let!(:confidential_issue) do create :issue, :confidential, @@ -37,6 +39,7 @@ describe API::Issues do created_at: generate(:past_time), updated_at: 2.hours.ago end + let!(:issue) do create :issue, author: user, @@ -48,18 +51,24 @@ describe API::Issues do title: issue_title, description: issue_description end + let_it_be(:label) do create(:label, title: 'label', color: '#FFAABB', project: project) end + let!(:label_link) { create(:label_link, label: label, target: issue) } let(:milestone) { create(:milestone, title: '1.0.0', project: project) } + let_it_be(:empty_milestone) do create(:milestone, title: '2.0.0', project: project) end - let!(:note) { create(:note_on_issue, author: user, project: project, noteable: issue) } + let!(:note) { create(:note_on_issue, author: user, project: project, noteable: issue) } let(:no_milestone_title) { 'None' } let(:any_milestone_title) { 'Any' } + let(:updated_title) { 'updated title' } + let(:issue_path) { "/projects/#{project.id}/issues/#{issue.iid}" } + let(:api_for_user) { api(issue_path, user) } before_all do project.add_reporter(user) @@ -72,108 +81,97 @@ describe API::Issues do describe 'PUT /projects/:id/issues/:issue_iid to update only title' do it 'updates a project issue' do - put api("/projects/#{project.id}/issues/#{issue.iid}", user), - params: { title: 'updated title' } - expect(response).to have_gitlab_http_status(:ok) + put api_for_user, params: { title: updated_title } - expect(json_response['title']).to eq('updated title') + expect(response).to have_gitlab_http_status(:ok) + expect(json_response['title']).to eq(updated_title) end it 'returns 404 error if issue iid not found' do - put api("/projects/#{project.id}/issues/44444", user), - params: { title: 'updated title' } + put api("/projects/#{project.id}/issues/44444", user), params: { title: updated_title } + expect(response).to have_gitlab_http_status(:not_found) end it 'returns 404 error if issue id is used instead of the iid' do - put api("/projects/#{project.id}/issues/#{issue.id}", user), - params: { title: 'updated title' } + put api("/projects/#{project.id}/issues/#{issue.id}", user), params: { title: updated_title } + expect(response).to have_gitlab_http_status(:not_found) end it 'allows special label names' do - put api("/projects/#{project.id}/issues/#{issue.iid}", user), + put api_for_user, params: { - title: 'updated title', + title: updated_title, labels: 'label, label?, label&foo, ?, &' } expect(response).to have_gitlab_http_status(:ok) - expect(json_response['labels']).to include 'label' - expect(json_response['labels']).to include 'label?' - expect(json_response['labels']).to include 'label&foo' - expect(json_response['labels']).to include '?' - expect(json_response['labels']).to include '&' end it 'allows special label names with labels param as array' do - put api("/projects/#{project.id}/issues/#{issue.iid}", user), + put api_for_user, params: { - title: 'updated title', + title: updated_title, labels: ['label', 'label?', 'label&foo, ?, &'] } expect(response).to have_gitlab_http_status(:ok) - expect(json_response['labels']).to include 'label' - expect(json_response['labels']).to include 'label?' - expect(json_response['labels']).to include 'label&foo' - expect(json_response['labels']).to include '?' - expect(json_response['labels']).to include '&' + expect(json_response['labels']).to contain_exactly('label', 'label?', 'label&foo', '?', '&') end context 'confidential issues' do + let(:confidential_issue_path) { "/projects/#{project.id}/issues/#{confidential_issue.iid}" } + it 'returns 403 for non project members' do - put api("/projects/#{project.id}/issues/#{confidential_issue.iid}", non_member), - params: { title: 'updated title' } + put api(confidential_issue_path, non_member), params: { title: updated_title } + expect(response).to have_gitlab_http_status(:forbidden) end it 'returns 403 for project members with guest role' do - put api("/projects/#{project.id}/issues/#{confidential_issue.iid}", guest), - params: { title: 'updated title' } + put api(confidential_issue_path, guest), params: { title: updated_title } + expect(response).to have_gitlab_http_status(:forbidden) end it 'updates a confidential issue for project members' do - put api("/projects/#{project.id}/issues/#{confidential_issue.iid}", user), - params: { title: 'updated title' } + put api(confidential_issue_path, user), params: { title: updated_title } + expect(response).to have_gitlab_http_status(:ok) - expect(json_response['title']).to eq('updated title') + expect(json_response['title']).to eq(updated_title) end it 'updates a confidential issue for author' do - put api("/projects/#{project.id}/issues/#{confidential_issue.iid}", author), - params: { title: 'updated title' } + put api(confidential_issue_path, author), params: { title: updated_title } + expect(response).to have_gitlab_http_status(:ok) - expect(json_response['title']).to eq('updated title') + expect(json_response['title']).to eq(updated_title) end it 'updates a confidential issue for admin' do - put api("/projects/#{project.id}/issues/#{confidential_issue.iid}", admin), - params: { title: 'updated title' } + put api(confidential_issue_path, admin), params: { title: updated_title } + expect(response).to have_gitlab_http_status(:ok) - expect(json_response['title']).to eq('updated title') + expect(json_response['title']).to eq(updated_title) end it 'sets an issue to confidential' do - put api("/projects/#{project.id}/issues/#{issue.iid}", user), - params: { confidential: true } + put api_for_user, params: { confidential: true } expect(response).to have_gitlab_http_status(:ok) expect(json_response['confidential']).to be_truthy end it 'makes a confidential issue public' do - put api("/projects/#{project.id}/issues/#{confidential_issue.iid}", user), - params: { confidential: false } + put api(confidential_issue_path, user), params: { confidential: false } expect(response).to have_gitlab_http_status(:ok) expect(json_response['confidential']).to be_falsy end it 'does not update a confidential issue with wrong confidential flag' do - put api("/projects/#{project.id}/issues/#{confidential_issue.iid}", user), - params: { confidential: 'foo' } + put api(confidential_issue_path, user), params: { confidential: 'foo' } expect(response).to have_gitlab_http_status(:bad_request) expect(json_response['error']).to eq('confidential is invalid') @@ -185,12 +183,12 @@ describe API::Issues do include_context 'includes Spam constants' def update_issue - put api("/projects/#{project.id}/issues/#{issue.iid}", user), params: params + put api_for_user, params: params end let(:params) do { - title: 'updated title', + title: updated_title, description: 'content here', labels: 'label, label2' } @@ -224,7 +222,7 @@ describe API::Issues do it 'creates a new spam log entry' do expect { update_issue } - .to log_spam(title: 'updated title', description: 'content here', user_id: user.id, noteable_type: 'Issue') + .to log_spam(title: updated_title, description: 'content here', user_id: user.id, noteable_type: 'Issue') end end @@ -241,7 +239,7 @@ describe API::Issues do it 'creates a new spam log entry' do expect { update_issue } - .to log_spam(title: 'updated title', description: 'content here', user_id: user.id, noteable_type: 'Issue') + .to log_spam(title: updated_title, description: 'content here', user_id: user.id, noteable_type: 'Issue') end end end @@ -249,49 +247,39 @@ describe API::Issues do describe 'PUT /projects/:id/issues/:issue_iid to update assignee' do context 'support for deprecated assignee_id' do it 'removes assignee' do - put api("/projects/#{project.id}/issues/#{issue.iid}", user), - params: { assignee_id: 0 } + put api_for_user, params: { assignee_id: 0 } expect(response).to have_gitlab_http_status(:ok) - expect(json_response['assignee']).to be_nil end it 'updates an issue with new assignee' do - put api("/projects/#{project.id}/issues/#{issue.iid}", user), - params: { assignee_id: user2.id } + put api_for_user, params: { assignee_id: user2.id } expect(response).to have_gitlab_http_status(:ok) - expect(json_response['assignee']['name']).to eq(user2.name) end end it 'removes assignee' do - put api("/projects/#{project.id}/issues/#{issue.iid}", user), - params: { assignee_ids: [0] } + put api_for_user, params: { assignee_ids: [0] } expect(response).to have_gitlab_http_status(:ok) - expect(json_response['assignees']).to be_empty end it 'updates an issue with new assignee' do - put api("/projects/#{project.id}/issues/#{issue.iid}", user), - params: { assignee_ids: [user2.id] } + put api_for_user, params: { assignee_ids: [user2.id] } expect(response).to have_gitlab_http_status(:ok) - expect(json_response['assignees'].first['name']).to eq(user2.name) end context 'single assignee restrictions' do it 'updates an issue with several assignees but only one has been applied' do - put api("/projects/#{project.id}/issues/#{issue.iid}", user), - params: { assignee_ids: [user2.id, guest.id] } + put api_for_user, params: { assignee_ids: [user2.id, guest.id] } expect(response).to have_gitlab_http_status(:ok) - expect(json_response['assignees'].size).to eq(1) end end @@ -301,16 +289,42 @@ describe API::Issues do let!(:label) { create(:label, title: 'dummy', project: project) } let!(:label_link) { create(:label_link, label: label, target: issue) } + it 'adds relevant labels' do + put api_for_user, params: { add_labels: '1, 2' } + + expect(response).to have_gitlab_http_status(:ok) + expect(json_response['labels']).to contain_exactly(label.title, '1', '2') + end + + context 'removes' do + let!(:label2) { create(:label, title: 'a-label', project: project) } + let!(:label_link2) { create(:label_link, label: label2, target: issue) } + + it 'removes relevant labels' do + put api_for_user, params: { remove_labels: label2.title } + + expect(response).to have_gitlab_http_status(:ok) + expect(json_response['labels']).to eq([label.title]) + end + + it 'removes all labels' do + put api_for_user, params: { remove_labels: "#{label.title}, #{label2.title}" } + + expect(response).to have_gitlab_http_status(:ok) + expect(json_response['labels']).to be_empty + end + end + it 'does not update labels if not present' do - put api("/projects/#{project.id}/issues/#{issue.iid}", user), - params: { title: 'updated title' } + put api_for_user, params: { title: updated_title } + expect(response).to have_gitlab_http_status(:ok) expect(json_response['labels']).to eq([label.title]) end it 'removes all labels and touches the record' do Timecop.travel(1.minute.from_now) do - put api("/projects/#{project.id}/issues/#{issue.iid}", user), params: { labels: '' } + put api_for_user, params: { labels: '' } end expect(response).to have_gitlab_http_status(:ok) @@ -320,7 +334,7 @@ describe API::Issues do it 'removes all labels and touches the record with labels param as array' do Timecop.travel(1.minute.from_now) do - put api("/projects/#{project.id}/issues/#{issue.iid}", user), params: { labels: [''] } + put api_for_user, params: { labels: [''] } end expect(response).to have_gitlab_http_status(:ok) @@ -330,20 +344,19 @@ describe API::Issues do it 'updates labels and touches the record' do Timecop.travel(1.minute.from_now) do - put api("/projects/#{project.id}/issues/#{issue.iid}", user), - params: { labels: 'foo,bar' } + put api_for_user, params: { labels: 'foo,bar' } end + expect(response).to have_gitlab_http_status(:ok) - expect(json_response['labels']).to include 'foo' - expect(json_response['labels']).to include 'bar' + expect(json_response['labels']).to contain_exactly('foo', 'bar') expect(json_response['updated_at']).to be > Time.now end it 'updates labels and touches the record with labels param as array' do Timecop.travel(1.minute.from_now) do - put api("/projects/#{project.id}/issues/#{issue.iid}", user), - params: { labels: %w(foo bar) } + put api_for_user, params: { labels: %w(foo bar) } end + expect(response).to have_gitlab_http_status(:ok) expect(json_response['labels']).to include 'foo' expect(json_response['labels']).to include 'bar' @@ -351,36 +364,22 @@ describe API::Issues do end it 'allows special label names' do - put api("/projects/#{project.id}/issues/#{issue.iid}", user), - params: { labels: 'label:foo, label-bar,label_bar,label/bar,label?bar,label&bar,?,&' } + put api_for_user, params: { labels: 'label:foo, label-bar,label_bar,label/bar,label?bar,label&bar,?,&' } + expect(response).to have_gitlab_http_status(:ok) - expect(json_response['labels']).to include 'label:foo' - expect(json_response['labels']).to include 'label-bar' - expect(json_response['labels']).to include 'label_bar' - expect(json_response['labels']).to include 'label/bar' - expect(json_response['labels']).to include 'label?bar' - expect(json_response['labels']).to include 'label&bar' - expect(json_response['labels']).to include '?' - expect(json_response['labels']).to include '&' + expect(json_response['labels']).to contain_exactly('label:foo', 'label-bar', 'label_bar', 'label/bar', 'label?bar', 'label&bar', '?', '&') end it 'allows special label names with labels param as array' do - put api("/projects/#{project.id}/issues/#{issue.iid}", user), - params: { labels: ['label:foo', 'label-bar', 'label_bar', 'label/bar,label?bar,label&bar,?,&'] } + put api_for_user, params: { labels: ['label:foo', 'label-bar', 'label_bar', 'label/bar,label?bar,label&bar,?,&'] } + expect(response).to have_gitlab_http_status(:ok) - expect(json_response['labels']).to include 'label:foo' - expect(json_response['labels']).to include 'label-bar' - expect(json_response['labels']).to include 'label_bar' - expect(json_response['labels']).to include 'label/bar' - expect(json_response['labels']).to include 'label?bar' - expect(json_response['labels']).to include 'label&bar' - expect(json_response['labels']).to include '?' - expect(json_response['labels']).to include '&' + expect(json_response['labels']).to contain_exactly('label:foo', 'label-bar', 'label_bar', 'label/bar', 'label?bar', 'label&bar', '?', '&') end it 'returns 400 if title is too long' do - put api("/projects/#{project.id}/issues/#{issue.iid}", user), - params: { title: 'g' * 256 } + put api_for_user, params: { title: 'g' * 256 } + expect(response).to have_gitlab_http_status(:bad_request) expect(json_response['message']['title']).to eq([ 'is too long (maximum is 255 characters)' @@ -390,16 +389,15 @@ describe API::Issues do describe 'PUT /projects/:id/issues/:issue_iid to update state and label' do it 'updates a project issue' do - put api("/projects/#{project.id}/issues/#{issue.iid}", user), - params: { labels: 'label2', state_event: 'close' } - expect(response).to have_gitlab_http_status(:ok) + put api_for_user, params: { labels: 'label2', state_event: 'close' } - expect(json_response['labels']).to include 'label2' + expect(response).to have_gitlab_http_status(:ok) + expect(json_response['labels']).to contain_exactly('label2') expect(json_response['state']).to eq 'closed' end it 'reopens a project isssue' do - put api("/projects/#{project.id}/issues/#{closed_issue.iid}", user), params: { state_event: 'reopen' } + put api(issue_path, user), params: { state_event: 'reopen' } expect(response).to have_gitlab_http_status(:ok) expect(json_response['state']).to eq 'opened' @@ -411,42 +409,41 @@ describe API::Issues do it 'accepts the update date to be set' do update_time = 2.weeks.ago - put api("/projects/#{project.id}/issues/#{issue.iid}", user), - params: { title: 'some new title', updated_at: update_time } + put api_for_user, params: { title: 'some new title', updated_at: update_time } expect(response).to have_gitlab_http_status(:ok) - expect(json_response['title']).to include 'some new title' + expect(json_response['title']).to eq('some new title') expect(Time.parse(json_response['updated_at'])).not_to be_like_time(update_time) end end context 'when admin or owner makes the request' do + let(:api_for_owner) { api(issue_path, owner) } + it 'not allow to set null for updated_at' do - put api("/projects/#{project.id}/issues/#{issue.iid}", owner), params: { updated_at: nil } + put api_for_owner, params: { updated_at: nil } expect(response).to have_gitlab_http_status(:bad_request) end it 'not allow to set blank for updated_at' do - put api("/projects/#{project.id}/issues/#{issue.iid}", owner), params: { updated_at: '' } + put api_for_owner, params: { updated_at: '' } expect(response).to have_gitlab_http_status(:bad_request) end it 'not allow to set invalid format for updated_at' do - put api("/projects/#{project.id}/issues/#{issue.iid}", owner), params: { updated_at: 'invalid-format' } + put api_for_owner, params: { updated_at: 'invalid-format' } expect(response).to have_gitlab_http_status(:bad_request) end it 'accepts the update date to be set' do update_time = 2.weeks.ago - put api("/projects/#{project.id}/issues/#{issue.iid}", owner), - params: { title: 'some new title', updated_at: update_time } + put api_for_owner, params: { title: 'some new title', updated_at: update_time } expect(response).to have_gitlab_http_status(:ok) - expect(json_response['title']).to include 'some new title' - + expect(json_response['title']).to eq('some new title') expect(Time.parse(json_response['updated_at'])).to be_like_time(update_time) end end @@ -456,7 +453,7 @@ describe API::Issues do it 'creates a new project issue' do due_date = 2.weeks.from_now.strftime('%Y-%m-%d') - put api("/projects/#{project.id}/issues/#{issue.iid}", user), params: { due_date: due_date } + put api_for_user, params: { due_date: due_date } expect(response).to have_gitlab_http_status(:ok) expect(json_response['due_date']).to eq(due_date) |