Commit 11702c48 authored by Felipe Artur's avatar Felipe Artur Committed by Jan Provaznik

Allow to create epics with GraphQL

Add mutation to create epics on GraphQL
parent 40078751
...@@ -66,6 +66,14 @@ The API can be explored interactively using the [GraphiQL IDE](../index.md#graph ...@@ -66,6 +66,14 @@ The API can be explored interactively using the [GraphiQL IDE](../index.md#graph
| `errors` | String! => Array | Reasons why the mutation failed. | | `errors` | String! => Array | Reasons why the mutation failed. |
| `note` | Note | The note after mutation | | `note` | Note | The note after mutation |
### CreateEpicPayload
| Name | Type | Description |
| --- | ---- | ---------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Reasons why the mutation failed. |
| `epic` | Epic | The created epic |
### CreateImageDiffNotePayload ### CreateImageDiffNotePayload
| Name | Type | Description | | Name | Type | Description |
......
...@@ -10,6 +10,7 @@ module EE ...@@ -10,6 +10,7 @@ module EE
mount_mutation ::Mutations::DesignManagement::Delete, calls_gitaly: true mount_mutation ::Mutations::DesignManagement::Delete, calls_gitaly: true
mount_mutation ::Mutations::EpicTree::Reorder mount_mutation ::Mutations::EpicTree::Reorder
mount_mutation ::Mutations::Epics::Update mount_mutation ::Mutations::Epics::Update
mount_mutation ::Mutations::Epics::Create
end end
end end
end end
......
# frozen_string_literal: true
module Mutations
module SharedEpicArguments
extend ActiveSupport::Concern
prepended do
argument :group_path, GraphQL::ID_TYPE,
required: true,
description: "The group the epic to mutate is in"
argument :title,
GraphQL::STRING_TYPE,
required: false,
description: 'The title of the epic'
argument :description,
GraphQL::STRING_TYPE,
required: false,
description: 'The description of the epic'
argument :start_date_fixed,
GraphQL::STRING_TYPE,
required: false,
description: 'The start date of the epic'
argument :due_date_fixed,
GraphQL::STRING_TYPE,
required: false,
description: 'The end date of the epic'
argument :start_date_is_fixed,
GraphQL::BOOLEAN_TYPE,
required: false,
description: 'Indicates start date should be sourced from start_date_fixed field not the issue milestones'
argument :due_date_is_fixed,
GraphQL::BOOLEAN_TYPE,
required: false,
description: 'Indicates end date should be sourced from due_date_fixed field not the issue milestones'
end
def validate_arguments!(args)
if args.empty?
raise Gitlab::Graphql::Errors::ArgumentError,
'The list of epic attributes is empty'
end
end
end
end
# frozen_string_literal: true
module Mutations
module Epics
class Create < BaseMutation
include Mutations::ResolvesGroup
prepend Mutations::SharedEpicArguments
graphql_name 'CreateEpic'
authorize :create_epic
field :epic,
Types::EpicType,
null: true,
description: 'The created epic'
def resolve(args)
group_path = args.delete(:group_path)
validate_arguments!(args)
group = authorized_find!(group_path: group_path)
epic = ::Epics::CreateService.new(group, current_user, args).execute
response_object = epic if epic.valid?
{
epic: response_object,
errors: errors_on_object(epic)
}
end
private
def find_object(group_path:)
resolve_group(full_path: group_path)
end
end
end
end
...@@ -4,47 +4,14 @@ module Mutations ...@@ -4,47 +4,14 @@ module Mutations
module Epics module Epics
class Update < BaseMutation class Update < BaseMutation
include Mutations::ResolvesGroup include Mutations::ResolvesGroup
prepend Mutations::SharedEpicArguments
graphql_name 'UpdateEpic' graphql_name 'UpdateEpic'
argument :group_path, GraphQL::ID_TYPE,
required: true,
description: "The group the epic to mutate is in"
argument :iid, GraphQL::STRING_TYPE, argument :iid, GraphQL::STRING_TYPE,
required: true, required: true,
description: "The iid of the epic to mutate" description: "The iid of the epic to mutate"
argument :title,
GraphQL::STRING_TYPE,
required: false,
description: 'The title of the epic'
argument :description,
GraphQL::STRING_TYPE,
required: false,
description: 'The description of the epic'
argument :start_date_fixed,
GraphQL::STRING_TYPE,
required: false,
description: 'The start date of the epic'
argument :due_date_fixed,
GraphQL::STRING_TYPE,
required: false,
description: 'The end date of the epic'
argument :start_date_is_fixed,
GraphQL::BOOLEAN_TYPE,
required: false,
description: 'Indicates start date should be sourced from start_date_fixed field not the issue milestones'
argument :due_date_is_fixed,
GraphQL::BOOLEAN_TYPE,
required: false,
description: 'Indicates end date should be sourced from due_date_fixed field not the issue milestones'
argument :state_event, argument :state_event,
Types::EpicStateEventEnum, Types::EpicStateEventEnum,
required: false, required: false,
...@@ -61,10 +28,7 @@ module Mutations ...@@ -61,10 +28,7 @@ module Mutations
group_path = args.delete(:group_path) group_path = args.delete(:group_path)
epic_iid = args.delete(:iid) epic_iid = args.delete(:iid)
if args.empty? validate_arguments!(args)
raise Gitlab::Graphql::Errors::ArgumentError,
"The list of attributes to update is empty"
end
epic = authorized_find!(group_path: group_path, iid: epic_iid) epic = authorized_find!(group_path: group_path, iid: epic_iid)
epic = ::Epics::UpdateService.new(epic.group, current_user, args).execute(epic) epic = ::Epics::UpdateService.new(epic.group, current_user, args).execute(epic)
......
---
title: Allow to create epics with GraphQL
merge_request: 19030
author:
type: added
# frozen_string_literal: true
require 'spec_helper'
describe 'Creating an Epic' do
include GraphqlHelpers
let_it_be(:current_user) { create(:user) }
let_it_be(:group) { create(:group) }
let(:attributes) do
{
title: 'title',
description: 'some description',
start_date_fixed: '2019-09-17',
due_date_fixed: '2019-09-18',
start_date_is_fixed: true,
due_date_is_fixed: true
}
end
let(:mutation) do
params = { group_path: group.full_path }.merge(attributes)
graphql_mutation(:create_epic, params)
end
def mutation_response
graphql_mutation_response(:create_epic)
end
context 'when the user does not have permission' do
before do
stub_licensed_features(epics: true)
end
it_behaves_like 'a mutation that returns top-level errors',
errors: ['The resource that you are attempting to access does not exist '\
'or you don\'t have permission to perform this action']
it 'does not create epic' do
expect { post_graphql_mutation(mutation, current_user: current_user) }.not_to change(Epic, :count)
end
end
context 'when the user has permission' do
before do
group.add_reporter(current_user)
end
context 'when epics are disabled' do
before do
stub_licensed_features(epics: false)
end
it_behaves_like 'a mutation that returns top-level errors',
errors: ['The resource that you are attempting to access does not '\
'exist or you don\'t have permission to perform this action']
end
context 'when epics are enabled' do
before do
stub_licensed_features(epics: true)
end
it 'creates the epic' do
post_graphql_mutation(mutation, current_user: current_user)
epic_hash = mutation_response['epic']
expect(epic_hash['title']).to eq('title')
expect(epic_hash['description']).to eq('some description')
expect(epic_hash['startDateFixed']).to eq('2019-09-17')
expect(epic_hash['startDateIsFixed']).to eq(true)
expect(epic_hash['dueDateFixed']).to eq('2019-09-18')
expect(epic_hash['dueDateIsFixed']).to eq(true)
end
context 'when there are ActiveRecord validation errors' do
let(:attributes) { { title: '' } }
it_behaves_like 'a mutation that returns errors in the response',
errors: ["Title can't be blank"]
it 'does not create the epic' do
expect { post_graphql_mutation(mutation, current_user: current_user) }.not_to change(Epic, :count)
end
end
context 'when the list of attributes is empty' do
let(:attributes) { {} }
it_behaves_like 'a mutation that returns top-level errors',
errors: ['The list of epic attributes is empty']
it 'does not create the epic' do
expect { post_graphql_mutation(mutation, current_user: current_user) }.not_to change(Epic, :count)
end
end
end
end
end
...@@ -117,7 +117,7 @@ describe 'Updating an Epic' do ...@@ -117,7 +117,7 @@ describe 'Updating an Epic' do
let(:attributes) { {} } let(:attributes) { {} }
it_behaves_like 'a mutation that returns top-level errors', it_behaves_like 'a mutation that returns top-level errors',
errors: ['The list of attributes to update is empty'] errors: ['The list of epic attributes is empty']
end end
end end
end end
......
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