Skip to content
Snippets Groups Projects
Commit d0ccbb2e authored by Jan Provaznik's avatar Jan Provaznik Committed by Charlie Ablett
Browse files

Reuse scope board mutation logic for epic boards

Label arguments and related logic (arguments validation) is needed
for epic boards too, so these arguments are moved to
ScopedBoardMutation and issue-specific arguments are renamed left in
ScopedIssueBoardArguments.
parent 8df02215
No related branches found
No related tags found
No related merge requests found
Showing
with 115 additions and 64 deletions
Loading
Loading
@@ -22,7 +22,7 @@ def resolve(args)
response = ::Boards::CreateService.new(board_parent, current_user, args).execute
 
{
board: response.payload,
board: response.success? ? response.payload : nil,
errors: response.errors
}
end
Loading
Loading
---
title: Fixed error handling GraphQL API when issue board creation fails
merge_request: 55982
author:
type: fixed
Loading
Loading
@@ -5,10 +5,10 @@ module Mutations
module Boards
module Create
extend ActiveSupport::Concern
prepend ::Mutations::Boards::ScopedBoardMutation
 
prepended do
include Mutations::Boards::ScopedBoardArguments
prepend ::Mutations::Boards::ScopedIssueBoardArguments
prepend ::Mutations::Boards::ScopedBoardMutation
end
end
end
Loading
Loading
# frozen_string_literal: true
module EE
module Mutations
module Boards
module ScopedBoardArguments
extend ActiveSupport::Concern
included do
argument :assignee_id,
::Types::GlobalIDType[::User],
required: false,
description: 'The ID of user to be assigned to the board.'
# Cannot pre-load ::Types::MilestoneType because we are also assigning values like:
# ::Timebox::None(0), ::Timebox::Upcoming(-2) or ::Timebox::Started(-3), that cannot be resolved to a DB record.
argument :milestone_id,
::Types::GlobalIDType[::Milestone],
required: false,
description: 'The ID of milestone to be assigned to the board.'
# Cannot pre-load ::Types::IterationType because we are also assigning values like:
# ::Iteration::Predefined::None(0) or ::Iteration::Predefined::Current(-4), that cannot be resolved to a DB record.
argument :iteration_id,
::Types::GlobalIDType[::Iteration],
required: false,
description: 'The ID of iteration to be assigned to the board.'
argument :weight,
GraphQL::INT_TYPE,
required: false,
description: 'The weight value to be assigned to the board.'
argument :labels, [GraphQL::STRING_TYPE],
required: false,
description: copy_field_description(::Types::IssueType, :labels)
argument :label_ids, [::Types::GlobalIDType[::Label]],
required: false,
description: 'The IDs of labels to be added to the board.'
end
end
end
end
end
Loading
Loading
@@ -5,10 +5,10 @@ module Mutations
module Boards
module Update
extend ActiveSupport::Concern
prepend ::Mutations::Boards::ScopedBoardMutation
 
prepended do
include Mutations::Boards::ScopedBoardArguments
prepend ::Mutations::Boards::ScopedIssueBoardArguments
prepend ::Mutations::Boards::ScopedBoardMutation
end
end
end
Loading
Loading
Loading
Loading
@@ -6,6 +6,7 @@ module EpicBoards
class Create < ::Mutations::BaseMutation
include Mutations::ResolvesGroup
include Mutations::Boards::CommonMutationArguments
prepend Mutations::Boards::ScopedBoardMutation
 
graphql_name 'EpicBoardCreate'
 
Loading
Loading
@@ -27,7 +28,7 @@ def resolve(args)
service_response = ::Boards::EpicBoards::CreateService.new(group, current_user, args).execute
 
{
epic_board: service_response.payload,
epic_board: service_response.success? ? service_response.payload : nil,
errors: service_response.errors
}
end
Loading
Loading
Loading
Loading
@@ -16,14 +16,6 @@ class Update < ::Mutations::BaseMutation
required: true,
description: 'The epic board global ID.'
 
argument :labels, [GraphQL::STRING_TYPE],
required: false,
description: 'Labels to be added to the board.'
argument :label_ids, [::Types::GlobalIDType[::Label]],
required: false,
description: 'The IDs of labels to be added to the board.'
field :epic_board,
Types::Boards::EpicBoardType,
null: true,
Loading
Loading
Loading
Loading
@@ -5,6 +5,16 @@ module Boards
module ScopedBoardMutation
extend ActiveSupport::Concern
 
prepended do
argument :labels, [GraphQL::STRING_TYPE],
required: false,
description: copy_field_description(::Types::IssueType, :labels)
argument :label_ids, [::Types::GlobalIDType[::Label]],
required: false,
description: 'IDs of labels to be added to the board.'
end
def resolve(**args)
parsed_params = parse_arguments(args)
 
Loading
Loading
# frozen_string_literal: true
module Mutations
module Boards
module ScopedIssueBoardArguments
extend ActiveSupport::Concern
prepended do
argument :assignee_id,
::Types::GlobalIDType[::User],
required: false,
description: 'ID of user to be assigned to the board.'
# Cannot pre-load ::Types::MilestoneType because we are also assigning values like:
# ::Timebox::None(0), ::Timebox::Upcoming(-2) or ::Timebox::Started(-3), that cannot be resolved to a DB record.
argument :milestone_id,
::Types::GlobalIDType[::Milestone],
required: false,
description: 'ID of milestone to be assigned to the board.'
# Cannot pre-load ::Types::IterationType because we are also assigning values like:
# ::Iteration::Predefined::None(0) or ::Iteration::Predefined::Current(-4), that cannot be resolved to a DB record.
argument :iteration_id,
::Types::GlobalIDType[::Iteration],
required: false,
description: 'ID of iteration to be assigned to the board.'
argument :weight,
GraphQL::INT_TYPE,
required: false,
description: 'Weight value to be assigned to the board.'
end
end
end
end
Loading
Loading
@@ -23,7 +23,7 @@
context 'field tests' do
subject { described_class }
 
it { is_expected.to have_graphql_arguments(:groupPath, :name, :hideBacklogList, :hideClosedList) }
it { is_expected.to have_graphql_arguments(:groupPath, :name, :hideBacklogList, :hideClosedList, :labels, :labelIds) }
it { is_expected.to have_graphql_fields(:epic_board).at_least }
end
 
Loading
Loading
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Mutations::Boards::EpicBoards::Create do
include GraphqlHelpers
let_it_be(:current_user) { create(:user) }
let_it_be(:group) { create(:group) }
let(:name) { 'board name' }
let(:mutation) { graphql_mutation(:epic_board_create, params) }
let(:label) { create(:group_label, group: group) }
let(:params) { { groupPath: group.full_path, name: 'foo', hide_backlog_list: true, labels: [label.name] } }
subject { post_graphql_mutation(mutation, current_user: current_user) }
def mutation_response
graphql_mutation_response(:epic_board_create)
end
before do
stub_licensed_features(epics: true, scoped_issue_board: true)
end
context 'when the user does not have permission' do
it_behaves_like 'a mutation that returns a top-level access error'
end
context 'when the user has permission' do
before do
group.add_developer(current_user)
end
it 'returns the created board' do
post_graphql_mutation(mutation, current_user: current_user)
expect(mutation_response).to have_key('epicBoard')
expect(mutation_response['epicBoard']['name']).to eq(params[:name])
expect(mutation_response['epicBoard']['hideBacklogList']).to eq(params[:hide_backlog_list])
expect(mutation_response['epicBoard']['labels']['count']).to eq(1)
end
context 'when create fails' do
let(:params) { { groupPath: group.full_path, name: 'x' * 256 } }
it 'returns an error' do
post_graphql_mutation(mutation, current_user: current_user)
expect(mutation_response).to have_key('epicBoard')
expect(mutation_response['epicBoard']).to be_nil
expect(mutation_response['errors'].first).to eq('There was an error when creating a board.')
end
end
end
end
Loading
Loading
@@ -66,9 +66,7 @@ def mutation_response
 
context 'when the Boards::CreateService returns an error response' do
before do
allow_next_instance_of(Boards::CreateService) do |service|
allow(service).to receive(:execute).and_return(ServiceResponse.error(message: 'There was an error.'))
end
params[:name] = ''
end
 
it 'does not create a board' do
Loading
Loading
@@ -80,7 +78,7 @@ def mutation_response
 
expect(mutation_response).to have_key('board')
expect(mutation_response['board']).to be_nil
expect(mutation_response['errors'].first).to eq('There was an error.')
expect(mutation_response['errors'].first).to eq('There was an error when creating a board.')
end
end
end
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment