Commit d2d61347 authored by James Ramsay's avatar James Ramsay

Add label helps to epic API

Adding and removing labels is a common operation, and label helpers have
been added to the issues and merge request API to make this more
convenient. For consistency, and convenience, these are added to the
Epic API.
parent 573a263c
......@@ -349,7 +349,9 @@ PUT /groups/:id/epics/:epic_iid
| `title` | string | no | The title of an epic |
| `description` | string | no | The description of an epic. Limited to 1,048,576 characters. |
| `confidential` | boolean | no | Whether the epic should be confidential |
| `labels` | string | no | The comma separated list of labels |
| `labels` | string | no | Comma-separated label names for an issue. Set to an empty string to unassign all labels. |
| `add_labels` | string | no | Comma-separated label names to add to an issue. |
| `remove_labels` | string | no | Comma-separated label names to remove from an issue. |
| `updated_at` | string | no | When the epic was updated. Date time string, ISO 8601 formatted, for example `2016-03-11T03:45:40Z` . Requires administrator or project/group owner privileges ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/255309) in GitLab 13.5) |
| `start_date_is_fixed` | boolean | no | Whether start date should be sourced from `start_date_fixed` or from milestones (since 11.3) |
| `start_date_fixed` | string | no | The fixed start date of an epic (since 11.3) |
......
---
title: Add add/remove label helpers to Epic API
merge_request: 40465
author:
type: added
......@@ -108,8 +108,10 @@ module API
optional :end_date, as: :due_date_fixed, type: String, desc: 'The due date of an epic'
optional :due_date_is_fixed, type: Boolean, desc: 'Indicates due date should be sourced from due_date_fixed field not the issue milestones'
optional :labels, type: Array[String], coerce_with: Validations::Types::CommaSeparatedToArray.coerce, desc: 'Comma-separated list of label names'
optional :add_labels, type: Array[String], coerce_with: Validations::Types::CommaSeparatedToArray.coerce, desc: 'Comma-separated list of label names'
optional :remove_labels, type: Array[String], coerce_with: Validations::Types::CommaSeparatedToArray.coerce, desc: 'Comma-separated list of label names'
optional :state_event, type: String, values: %w[reopen close], desc: 'State event for an epic'
at_least_one_of :title, :description, :start_date_fixed, :start_date_is_fixed, :due_date_fixed, :due_date_is_fixed, :labels, :state_event, :confidential
at_least_one_of :title, :description, :start_date_fixed, :start_date_is_fixed, :due_date_fixed, :due_date_is_fixed, :labels, :add_labels, :remove_labels, :state_event, :confidential
end
put ':id/(-/)epics/:epic_iid' do
Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab/issues/194104')
......
......@@ -7,6 +7,7 @@ RSpec.describe API::Epics do
let(:group) { create(:group) }
let(:project) { create(:project, :public, group: group) }
let(:label) { create(:group_label, group: group) }
let(:label2) { create(:group_label, group: group, title: 'label-2') }
let!(:epic) { create(:labeled_epic, group: group, labels: [label]) }
let(:params) { nil }
......@@ -61,6 +62,13 @@ RSpec.describe API::Epics do
end
end
shared_context 'with labels' do
before do
create(:label_link, label: label, target: epic)
create(:label_link, label: label2, target: epic)
end
end
describe 'GET /groups/:id/epics' do
let(:url) { "/groups/#{group.path}/epics" }
let(:params) { { include_descendant_groups: true } }
......@@ -762,22 +770,47 @@ RSpec.describe API::Epics do
expect(json_response['labels']).to be_empty
end
it 'updates the epic with labels param as array' do
stub_const("Gitlab::QueryLimiting::Transaction::THRESHOLD", 110)
context 'with labels' do
include_context 'with labels'
params[:labels] = ['label1', 'label2', 'foo, bar', '&,?']
it 'updates the epic with labels param as array' do
stub_const("Gitlab::QueryLimiting::Transaction::THRESHOLD", 110)
put api(url, user), params: params
params[:labels] = ['label1', 'label2', 'foo, bar', '&,?']
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['title']).to include 'new title'
expect(json_response['description']).to include 'new description'
expect(json_response['labels']).to include 'label1'
expect(json_response['labels']).to include 'label2'
expect(json_response['labels']).to include 'foo'
expect(json_response['labels']).to include 'bar'
expect(json_response['labels']).to include '&'
expect(json_response['labels']).to include '?'
put api(url, user), params: params
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['title']).to include 'new title'
expect(json_response['description']).to include 'new description'
expect(json_response['labels']).to include 'label1'
expect(json_response['labels']).to include 'label2'
expect(json_response['labels']).to include 'foo'
expect(json_response['labels']).to include 'bar'
expect(json_response['labels']).to include '&'
expect(json_response['labels']).to include '?'
end
it 'when adding labels, keeps existing labels and adds new' do
put api(url, user), params: { add_labels: '1, 2' }
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['labels']).to contain_exactly(label.title, label2.title, '1', '2')
end
it 'when removing labels, only removes those specified' do
put api(url, user), params: { remove_labels: label.title }
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['labels']).to eq([label2.title])
end
it 'when removing all labels, keeps no labels' do
put api(url, 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
context 'when state_event is close' do
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment