From 9e521ca7007d32bd4e6491b3507de7d9ff8e4cef Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Wed, 13 Feb 2019 15:40:35 +0100 Subject: API: Bulk update for issues and merge requests This MR adds support for bulk update actions for issues and merge requests. A single API call can be used to update a list of issues or merge requests --- changelogs/unreleased/api-issuable-bulk-update.yml | 5 +++ lib/api/api.rb | 1 + lib/api/issuable_bulk_update.rb | 48 ++++++++++++++++++++++ 3 files changed, 54 insertions(+) create mode 100644 changelogs/unreleased/api-issuable-bulk-update.yml create mode 100644 lib/api/issuable_bulk_update.rb diff --git a/changelogs/unreleased/api-issuable-bulk-update.yml b/changelogs/unreleased/api-issuable-bulk-update.yml new file mode 100644 index 00000000000..302484f5569 --- /dev/null +++ b/changelogs/unreleased/api-issuable-bulk-update.yml @@ -0,0 +1,5 @@ +--- +title: 'API: Bulk update for issues and MRs' +merge_request: +author: +type: added diff --git a/lib/api/api.rb b/lib/api/api.rb index 4dd1b459554..3bcf5150b43 100644 --- a/lib/api/api.rb +++ b/lib/api/api.rb @@ -115,6 +115,7 @@ module API mount ::API::GroupVariables mount ::API::ImportGithub mount ::API::Internal + mount ::API::IssuableBulkUpdate mount ::API::Issues mount ::API::JobArtifacts mount ::API::Jobs diff --git a/lib/api/issuable_bulk_update.rb b/lib/api/issuable_bulk_update.rb new file mode 100644 index 00000000000..fe12242a676 --- /dev/null +++ b/lib/api/issuable_bulk_update.rb @@ -0,0 +1,48 @@ +# frozen_string_literal: true + +module API + class IssuableBulkUpdate < Grape::API + params do + requires :id, type: String, desc: 'The ID of a project' + end + resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do + %w(issue merge_request).each do |issuable| + desc "Updates a list of #{issuable.pluralize}" do + detail 'This feature was introduced in 11.9' + end + params do + optional :state_event, type: String, values: %w(reopen close), desc: 'Reopens or closes a resource' + optional :milestone_id, type: Integer, desc: 'The milestone ID number' + optional :add_label_ids, type: Array[Integer], desc: 'IDs of labels to be added' + optional :remove_label_ids, type: Array[Integer], desc: 'IDs of labels to be removed' + optional :subscription_event, type: String, values: %w(subscribe unsubscribe), + desc: 'Subscribes or unsubscribes from a resource' + + if issuable == 'issue' + optional :assignee_ids, type: Array[Integer], desc: 'List of assignees IDs' + at_least_one_of :state_event, :milestone_id, :add_label_ids, :remove_label_ids, + :subscription_event, :assignee_ids + else + optional :assignee_id, type: Integer, desc: 'ID of the assignee' + at_least_one_of :state_event, :milestone_id, :add_label_ids, :remove_label_ids, + :subscription_event, :assignee_id + end + end + put ":id/#{issuable}/bulk_update" do + update_params = declared_params(include_missing: false) + + result = Issuable::BulkUpdateService.new(user_project, current_user, update_params) + .execute(issuable) + quantity = result[:count] + + if result[:success] + status 200 + { notice: "#{quantity} #{issuable.pluralize(quantity)} updated" } + else + render_api_error!('Bulk update failed', 400) + end + end + end + end + end +end -- cgit v1.2.3 From 6b2673bc7ac0c51152b0e355ab99360f551438d3 Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Thu, 14 Feb 2019 12:30:18 +0100 Subject: Add new to test bulk_update endpoint for issues and MRs Add documentation for issues and MRs. Add shared tests for both bulk updating issues and MRs. --- changelogs/unreleased/api-issuable-bulk-update.yml | 4 +- doc/api/issues.md | 31 +++++ doc/api/merge_requests.md | 31 +++++ lib/api/issuable_bulk_update.rb | 9 +- spec/requests/api/issuable_bulk_update_spec.rb | 152 +++++++++++++++++++++ 5 files changed, 222 insertions(+), 5 deletions(-) create mode 100644 spec/requests/api/issuable_bulk_update_spec.rb diff --git a/changelogs/unreleased/api-issuable-bulk-update.yml b/changelogs/unreleased/api-issuable-bulk-update.yml index 302484f5569..3d4e96f9d1b 100644 --- a/changelogs/unreleased/api-issuable-bulk-update.yml +++ b/changelogs/unreleased/api-issuable-bulk-update.yml @@ -1,5 +1,5 @@ --- title: 'API: Bulk update for issues and MRs' -merge_request: -author: +merge_request: 25201 +author: Robert Schilling type: added diff --git a/doc/api/issues.md b/doc/api/issues.md index ed3165d95df..ccd28d21e98 100644 --- a/doc/api/issues.md +++ b/doc/api/issues.md @@ -635,6 +635,37 @@ Example response: **Note**: The `closed_by` attribute was [introduced in GitLab 10.6][ce-17042]. This value will only be present for issues which were closed after GitLab 10.6 and when the user account that closed the issue still exists. +## Bulk update issues + +> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/21368) in GitLab 11.8. + +Update multiple issues using a single API call. Returns the number of successfully updated issues. + +``` +PUT /projects/:id/issues/bulk_update +``` + +| Attribute | Type | Required | Description **** | +|----------------|---------|----------|------------------------------------------------------------------------------------------------------------| +| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. | +| `issuable_ids` | Array[integer] | yes | The IDs of issues to be updated. | +| `assignee_ids` | Array[integer] | no | The ID of the user(s) to assign the issue to. Set to `0` or provide an empty value to unassign all assignees. | +| `milestone_id` | integer | no | The global ID of a milestone to assign the issue to. Set to `0` or provide an empty value to unassign a milestone.| +| `add_label_ids` | Array[integer] | no | Comma-separated label IDs to be added. | +| `remove_label_ids` | Array[integer] | no | Comma-separated label IDs to be added. | +| `state_event` | string | no | The state event of an issue. Set `close` to close the issue and `reopen` to reopen it. | +| `subscription_event` | string | no | The subscription_event event of an issue. Set `subscribe` to subscribe to the issue and `unsubscribe` to unsubscribe from it. | + +```bash +curl --request PUT --header "PRIVATE-TOKEN: " https://gitlab.example.com/api/v4/projects/4/issues/bulk_update?issuable_ids[]=1&issuable_ids[]=2&state_event=close +``` + +Example response: + +```json +{ "message": "2 issues updated" } +``` + ## Delete an issue Only for admins and project owners. Soft deletes the issue in question. diff --git a/doc/api/merge_requests.md b/doc/api/merge_requests.md index d58cd45538d..05bc3d098c5 100644 --- a/doc/api/merge_requests.md +++ b/doc/api/merge_requests.md @@ -956,6 +956,37 @@ Must include at least one non-required attribute from above. } ``` +## Bulk update merge requests + +> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/21368) in GitLab 11.8. + +Update multiple merge requests using a single API call. Returns the number of successfully updated merge requests. + +``` +PUT /projects/:id/merge_requests/bulk_update +``` + +| Attribute | Type | Required | Description **** | +|----------------|---------|----------|------------------------------------------------------------------------------------------------------------| +| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. | +| `issuable_ids` | Array[integer] | yes | The IDs of merge requests to be updated. | +| `assignee_ids` | Array[integer] | no | The ID of the user(s) to assign the issue to. Set to `0` or provide an empty value to unassign all assignees. | +| `milestone_id` | integer | no | The global ID of a milestone to assign the issue to. Set to `0` or provide an empty value to unassign a milestone.| +| `add_label_ids` | Array[integer] | no | Comma-separated label IDs to be added. | +| `remove_label_ids` | Array[integer] | no | Comma-separated label IDs to be added. | +| `state_event` | string | no | The state event of an issue. Set `close` to close the issue and `reopen` to reopen it. | +| `subscription_event` | string | no | The subscription_event event of an issue. Set `subscribe` to subscribe to the issue and `unsubscribe` to unsubscribe from it. | + +```bash +curl --request PUT --header "PRIVATE-TOKEN: " https://gitlab.example.com/api/v4/projects/4/merge_requests/bulk_update?issuable_ids[]=1&issuable_ids[]=2&state_event=close +``` + +Example response: + +```json +{ "message": "2 merge_requests updated" } +``` + ## Delete a merge request Only for admins and project owners. Soft deletes the merge request in question. diff --git a/lib/api/issuable_bulk_update.rb b/lib/api/issuable_bulk_update.rb index fe12242a676..bcda8b32976 100644 --- a/lib/api/issuable_bulk_update.rb +++ b/lib/api/issuable_bulk_update.rb @@ -11,6 +11,7 @@ module API detail 'This feature was introduced in 11.9' end params do + requires :issuable_ids, type: Array[Integer], desc: "Array or #{issuable.pluralize} IDs to be updates" optional :state_event, type: String, values: %w(reopen close), desc: 'Reopens or closes a resource' optional :milestone_id, type: Integer, desc: 'The milestone ID number' optional :add_label_ids, type: Array[Integer], desc: 'IDs of labels to be added' @@ -28,16 +29,18 @@ module API :subscription_event, :assignee_id end end - put ":id/#{issuable}/bulk_update" do + put ":id/#{issuable.pluralize}/bulk_update" do + authorize! :"admin_#{issuable}", user_project + update_params = declared_params(include_missing: false) result = Issuable::BulkUpdateService.new(user_project, current_user, update_params) .execute(issuable) - quantity = result[:count] if result[:success] status 200 - { notice: "#{quantity} #{issuable.pluralize(quantity)} updated" } + quantity = result[:count] + { message: "#{quantity} #{issuable.pluralize(quantity)} updated" } else render_api_error!('Bulk update failed', 400) end diff --git a/spec/requests/api/issuable_bulk_update_spec.rb b/spec/requests/api/issuable_bulk_update_spec.rb new file mode 100644 index 00000000000..810fa8dc529 --- /dev/null +++ b/spec/requests/api/issuable_bulk_update_spec.rb @@ -0,0 +1,152 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe API::IssuableBulkUpdate do + set(:user) { create(:user) } + set(:project) do + create(:project, :public, creator_id: user.id, namespace: user.namespace) + end + + %w(issue merge_request).each do |issuable| + describe "PUT /projects/:id/#{issuable.pluralize}/bulk_update" do + let(:merge_request_1) { create(:merge_request, source_project: project) } + let(:merge_request_2) { create(:merge_request, :simple, source_project: project) } + let!(:issuables) { issuable == 'issue' ? create_list(:issue, 2, project: project) : [merge_request_1, merge_request_2] } + + def bulk_update(issuable, issuables, params, update_user = user) + put api("/projects/#{project.id}/#{issuable.pluralize}/bulk_update", update_user), + params: { issuable_ids: Array(issuables).map(&:id) }.merge(params) + end + + context 'with not enough permissions' do + it 'returns 403 for guest users' do + guest = create(:user) + project.add_guest(guest) + + bulk_update(issuable, issuables, { state_event: 'close' }, guest) + + expect(response).to have_gitlab_http_status(403) + end + end + + context 'when modifying the state' do + it "closes #{issuable}" do + bulk_update(issuable, issuables, { state_event: 'close' }) + + expect(response).to have_gitlab_http_status(200) + expect(json_response['message']).to eq("#{issuables.count} #{issuable.pluralize(issuables.count)} updated") + expect(project.public_send(issuable.pluralize).opened).to be_empty + expect(project.public_send(issuable.pluralize).closed).not_to be_empty + end + + it "opens #{issuable}" do + closed_issuables = create_list("closed_#{issuable}".to_sym, 2) + + bulk_update(issuable, closed_issuables, { state_event: 'reopen' }) + + expect(response).to have_gitlab_http_status(200) + expect(project.public_send(issuable.pluralize).closed).to be_empty + end + end + + context 'when modifying the milestone' do + let(:milestone) { create(:milestone, project: project) } + + it "adds a milestone #{issuable}" do + bulk_update(issuable, issuables, { milestone_id: milestone.id }) + + expect(response).to have_gitlab_http_status(200) + issuables.each do |issuable| + expect(issuable.reload.milestone).to eq(milestone) + end + end + + it 'removes a milestone' do + issuables.first.milestone = milestone + milestone_issuable = issuables.first + + bulk_update(issuable, [milestone_issuable], { milestone_id: 0 }) + + expect(response).to have_gitlab_http_status(200) + expect(milestone_issuable.reload.milestone).to eq(nil) + end + end + + context 'when modifying the subscription state' do + it "subscribes to #{issuable}" do + bulk_update(issuable, issuables, { subscription_event: 'subscribe' }) + + expect(response).to have_gitlab_http_status(200) + expect(issuables).to all(be_subscribed(user, project)) + end + + it 'unsubscribes from issues' do + issuables.each do |issuable| + issuable.subscriptions.create(user: user, project: project, subscribed: true) + end + + bulk_update(issuable, issuables, { subscription_event: 'unsubscribe' }) + + expect(response).to have_gitlab_http_status(200) + issuables.each do |issuable| + expect(issuable).not_to be_subscribed(user, project) + end + end + end + + context 'when modifying the assignee' do + it 'adds assignee to issues' do + params = issuable == 'issue' ? { assignee_ids: [user.id] } : { assignee_id: user.id } + + bulk_update(issuable, issuables, params) + + expect(response).to have_gitlab_http_status(200) + issuables.each do |issuable| + expect(issuable.reload.assignees).to eq([user]) + end + end + + it 'removes assignee' do + assigned_issuable = issuables.first + + if issuable == 'issue' + params = { assignee_ids: 0 } + assigned_issuable.assignees << user + else + params = { assignee_id: 0 } + assigned_issuable.update_attribute(:assignee, user) + end + + bulk_update(issuable, [assigned_issuable], params) + expect(assigned_issuable.reload.assignees).to eq([]) + end + end + + context 'when modifying labels' do + let(:bug) { create(:label, project: project) } + let(:regression) { create(:label, project: project) } + let(:feature) { create(:label, project: project) } + + it 'adds new labels' do + bulk_update(issuable, issuables, { add_label_ids: [bug.id, regression.id, feature.id] }) + + issuables.each do |issusable| + expect(issusable.reload.label_ids).to contain_exactly(bug.id, regression.id, feature.id) + end + end + + it 'removes labels' do + labled_issuable = issuables.first + labled_issuable.labels << bug + labled_issuable.labels << regression + labled_issuable.labels << feature + + bulk_update(issuable, [labled_issuable], { remove_label_ids: [bug.id, regression.id] }) + + expect(labled_issuable.reload.label_ids).to contain_exactly(feature.id) + end + end + end + end +end -- cgit v1.2.3 From 64ed7069c709949c0839aebe62d58191f75fa050 Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Mon, 18 Feb 2019 13:30:09 +0100 Subject: Incorporate review feedback Use shared examples for issues and merge requests rather than a loop creating common specs. --- doc/api/issues.md | 2 +- doc/api/merge_requests.md | 2 +- lib/api/issuable_bulk_update.rb | 4 +- spec/requests/api/issuable_bulk_update_spec.rb | 206 +++++++++++++------------ 4 files changed, 108 insertions(+), 106 deletions(-) diff --git a/doc/api/issues.md b/doc/api/issues.md index ccd28d21e98..81553746834 100644 --- a/doc/api/issues.md +++ b/doc/api/issues.md @@ -637,7 +637,7 @@ Example response: ## Bulk update issues -> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/21368) in GitLab 11.8. +> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/21368) in GitLab 11.9. Update multiple issues using a single API call. Returns the number of successfully updated issues. diff --git a/doc/api/merge_requests.md b/doc/api/merge_requests.md index 05bc3d098c5..78cb4db74e1 100644 --- a/doc/api/merge_requests.md +++ b/doc/api/merge_requests.md @@ -958,7 +958,7 @@ Must include at least one non-required attribute from above. ## Bulk update merge requests -> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/21368) in GitLab 11.8. +> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/21368) in GitLab 11.9. Update multiple merge requests using a single API call. Returns the number of successfully updated merge requests. diff --git a/lib/api/issuable_bulk_update.rb b/lib/api/issuable_bulk_update.rb index bcda8b32976..5ac6c252d96 100644 --- a/lib/api/issuable_bulk_update.rb +++ b/lib/api/issuable_bulk_update.rb @@ -11,7 +11,7 @@ module API detail 'This feature was introduced in 11.9' end params do - requires :issuable_ids, type: Array[Integer], desc: "Array or #{issuable.pluralize} IDs to be updates" + requires :issuable_ids, type: Array[Integer], desc: "Array of #{issuable.pluralize} IDs to be updated" optional :state_event, type: String, values: %w(reopen close), desc: 'Reopens or closes a resource' optional :milestone_id, type: Integer, desc: 'The milestone ID number' optional :add_label_ids, type: Array[Integer], desc: 'IDs of labels to be added' @@ -20,7 +20,7 @@ module API desc: 'Subscribes or unsubscribes from a resource' if issuable == 'issue' - optional :assignee_ids, type: Array[Integer], desc: 'List of assignees IDs' + optional :assignee_ids, type: Array[Integer], desc: 'List of assignee IDs' at_least_one_of :state_event, :milestone_id, :add_label_ids, :remove_label_ids, :subscription_event, :assignee_ids else diff --git a/spec/requests/api/issuable_bulk_update_spec.rb b/spec/requests/api/issuable_bulk_update_spec.rb index 810fa8dc529..6463f3f5d35 100644 --- a/spec/requests/api/issuable_bulk_update_spec.rb +++ b/spec/requests/api/issuable_bulk_update_spec.rb @@ -3,150 +3,152 @@ require 'spec_helper' describe API::IssuableBulkUpdate do - set(:user) { create(:user) } - set(:project) do - create(:project, :public, creator_id: user.id, namespace: user.namespace) - end - - %w(issue merge_request).each do |issuable| - describe "PUT /projects/:id/#{issuable.pluralize}/bulk_update" do - let(:merge_request_1) { create(:merge_request, source_project: project) } - let(:merge_request_2) { create(:merge_request, :simple, source_project: project) } - let!(:issuables) { issuable == 'issue' ? create_list(:issue, 2, project: project) : [merge_request_1, merge_request_2] } + set(:project) { create(:project) } + set(:user) { project.creator } - def bulk_update(issuable, issuables, params, update_user = user) - put api("/projects/#{project.id}/#{issuable.pluralize}/bulk_update", update_user), - params: { issuable_ids: Array(issuables).map(&:id) }.merge(params) - end + shared_examples "PUT /projects/:id/:issuable/bulk_update" do |issuable| + def bulk_update(issuable, issuables, params, update_user = user) + put api("/projects/#{project.id}/#{issuable.pluralize}/bulk_update", update_user), + params: { issuable_ids: Array(issuables).map(&:id) }.merge(params) + end - context 'with not enough permissions' do - it 'returns 403 for guest users' do - guest = create(:user) - project.add_guest(guest) + context 'with not enough permissions' do + it 'returns 403 for guest users' do + guest = create(:user) + project.add_guest(guest) - bulk_update(issuable, issuables, { state_event: 'close' }, guest) + bulk_update(issuable, issuables, { state_event: 'close' }, guest) - expect(response).to have_gitlab_http_status(403) - end + expect(response).to have_gitlab_http_status(403) end + end - context 'when modifying the state' do - it "closes #{issuable}" do - bulk_update(issuable, issuables, { state_event: 'close' }) + context 'when modifying the state' do + it "closes #{issuable}" do + bulk_update(issuable, issuables, { state_event: 'close' }) - expect(response).to have_gitlab_http_status(200) - expect(json_response['message']).to eq("#{issuables.count} #{issuable.pluralize(issuables.count)} updated") - expect(project.public_send(issuable.pluralize).opened).to be_empty - expect(project.public_send(issuable.pluralize).closed).not_to be_empty - end + expect(response).to have_gitlab_http_status(200) + expect(json_response['message']).to eq("#{issuables.count} #{issuable.pluralize(issuables.count)} updated") + expect(project.public_send(issuable.pluralize).opened).to be_empty + expect(project.public_send(issuable.pluralize).closed).not_to be_empty + end - it "opens #{issuable}" do - closed_issuables = create_list("closed_#{issuable}".to_sym, 2) + it "opens #{issuable}" do + closed_issuables = create_list("closed_#{issuable}".to_sym, 2) - bulk_update(issuable, closed_issuables, { state_event: 'reopen' }) + bulk_update(issuable, closed_issuables, { state_event: 'reopen' }) - expect(response).to have_gitlab_http_status(200) - expect(project.public_send(issuable.pluralize).closed).to be_empty - end + expect(response).to have_gitlab_http_status(200) + expect(project.public_send(issuable.pluralize).closed).to be_empty end + end - context 'when modifying the milestone' do - let(:milestone) { create(:milestone, project: project) } + context 'when modifying the milestone' do + let(:milestone) { create(:milestone, project: project) } - it "adds a milestone #{issuable}" do - bulk_update(issuable, issuables, { milestone_id: milestone.id }) + it "adds a milestone #{issuable}" do + bulk_update(issuable, issuables, { milestone_id: milestone.id }) - expect(response).to have_gitlab_http_status(200) - issuables.each do |issuable| - expect(issuable.reload.milestone).to eq(milestone) - end + expect(response).to have_gitlab_http_status(200) + issuables.each do |issuable| + expect(issuable.reload.milestone).to eq(milestone) end + end - it 'removes a milestone' do - issuables.first.milestone = milestone - milestone_issuable = issuables.first + it 'removes a milestone' do + issuables.first.milestone = milestone + milestone_issuable = issuables.first - bulk_update(issuable, [milestone_issuable], { milestone_id: 0 }) + bulk_update(issuable, [milestone_issuable], { milestone_id: 0 }) - expect(response).to have_gitlab_http_status(200) - expect(milestone_issuable.reload.milestone).to eq(nil) - end + expect(response).to have_gitlab_http_status(200) + expect(milestone_issuable.reload.milestone).to eq(nil) end + end - context 'when modifying the subscription state' do - it "subscribes to #{issuable}" do - bulk_update(issuable, issuables, { subscription_event: 'subscribe' }) + context 'when modifying the subscription state' do + it "subscribes to #{issuable}" do + bulk_update(issuable, issuables, { subscription_event: 'subscribe' }) - expect(response).to have_gitlab_http_status(200) - expect(issuables).to all(be_subscribed(user, project)) - end + expect(response).to have_gitlab_http_status(200) + expect(issuables).to all(be_subscribed(user, project)) + end - it 'unsubscribes from issues' do - issuables.each do |issuable| - issuable.subscriptions.create(user: user, project: project, subscribed: true) - end + it 'unsubscribes from issues' do + issuables.each do |issuable| + issuable.subscriptions.create(user: user, project: project, subscribed: true) + end - bulk_update(issuable, issuables, { subscription_event: 'unsubscribe' }) + bulk_update(issuable, issuables, { subscription_event: 'unsubscribe' }) - expect(response).to have_gitlab_http_status(200) - issuables.each do |issuable| - expect(issuable).not_to be_subscribed(user, project) - end + expect(response).to have_gitlab_http_status(200) + issuables.each do |issuable| + expect(issuable).not_to be_subscribed(user, project) end end + end - context 'when modifying the assignee' do - it 'adds assignee to issues' do - params = issuable == 'issue' ? { assignee_ids: [user.id] } : { assignee_id: user.id } + context 'when modifying the assignee' do + it 'adds assignee to issues' do + params = issuable == 'issue' ? { assignee_ids: [user.id] } : { assignee_id: user.id } - bulk_update(issuable, issuables, params) + bulk_update(issuable, issuables, params) - expect(response).to have_gitlab_http_status(200) - issuables.each do |issuable| - expect(issuable.reload.assignees).to eq([user]) - end + expect(response).to have_gitlab_http_status(200) + issuables.each do |issuable| + expect(issuable.reload.assignees).to eq([user]) end + end - it 'removes assignee' do - assigned_issuable = issuables.first - - if issuable == 'issue' - params = { assignee_ids: 0 } - assigned_issuable.assignees << user - else - params = { assignee_id: 0 } - assigned_issuable.update_attribute(:assignee, user) - end + it 'removes assignee' do + assigned_issuable = issuables.first - bulk_update(issuable, [assigned_issuable], params) - expect(assigned_issuable.reload.assignees).to eq([]) + if issuable == 'issue' + params = { assignee_ids: 0 } + assigned_issuable.assignees << user + else + params = { assignee_id: 0 } + assigned_issuable.update_attribute(:assignee, user) end + + bulk_update(issuable, [assigned_issuable], params) + expect(assigned_issuable.reload.assignees).to eq([]) end + end - context 'when modifying labels' do - let(:bug) { create(:label, project: project) } - let(:regression) { create(:label, project: project) } - let(:feature) { create(:label, project: project) } + context 'when modifying labels' do + let(:bug) { create(:label, project: project) } + let(:regression) { create(:label, project: project) } + let(:feature) { create(:label, project: project) } - it 'adds new labels' do - bulk_update(issuable, issuables, { add_label_ids: [bug.id, regression.id, feature.id] }) + it 'adds new labels' do + bulk_update(issuable, issuables, { add_label_ids: [bug.id, regression.id, feature.id] }) - issuables.each do |issusable| - expect(issusable.reload.label_ids).to contain_exactly(bug.id, regression.id, feature.id) - end + issuables.each do |issusable| + expect(issusable.reload.label_ids).to contain_exactly(bug.id, regression.id, feature.id) end + end - it 'removes labels' do - labled_issuable = issuables.first - labled_issuable.labels << bug - labled_issuable.labels << regression - labled_issuable.labels << feature + it 'removes labels' do + labled_issuable = issuables.first + labled_issuable.labels << bug + labled_issuable.labels << regression + labled_issuable.labels << feature - bulk_update(issuable, [labled_issuable], { remove_label_ids: [bug.id, regression.id] }) + bulk_update(issuable, [labled_issuable], { remove_label_ids: [bug.id, regression.id] }) - expect(labled_issuable.reload.label_ids).to contain_exactly(feature.id) - end + expect(labled_issuable.reload.label_ids).to contain_exactly(feature.id) end end end + + it_behaves_like 'PUT /projects/:id/:issuable/bulk_update', 'issue' do + let(:issuables) { create_list(:issue, 2, project: project) } + end + + it_behaves_like 'PUT /projects/:id/:issuable/bulk_update', 'merge_request' do + let(:merge_request_1) { create(:merge_request, source_project: project) } + let(:merge_request_2) { create(:merge_request, :simple, source_project: project) } + let(:issuables) { [merge_request_1, merge_request_2] } + end end -- cgit v1.2.3