Commit a0d19381 authored by Bob Van Landuyt's avatar Bob Van Landuyt

Merge branch '352938-add-graphql-to-destroy-saved-reply' into 'master'

Add GraphQL API to Destroy Saved Reply

See merge request gitlab-org/gitlab!82643
parents 1c6719ba cd873535
...@@ -5,7 +5,7 @@ module Mutations ...@@ -5,7 +5,7 @@ module Mutations
class Base < BaseMutation class Base < BaseMutation
field :saved_reply, Types::SavedReplyType, field :saved_reply, Types::SavedReplyType,
null: true, null: true,
description: 'Updated saved reply.' description: 'Saved reply after mutation.'
private private
......
# frozen_string_literal: true
module Mutations
module SavedReplies
class Destroy < Base
graphql_name 'SavedReplyDestroy'
authorize :destroy_saved_replies
argument :id, Types::GlobalIDType[::Users::SavedReply],
required: true,
description: copy_field_description(Types::SavedReplyType, :id)
def resolve(id:)
raise Gitlab::Graphql::Errors::ResourceNotAvailable, 'Feature disabled' unless feature_enabled?
saved_reply = authorized_find!(id)
result = ::Users::SavedReplies::DestroyService.new(saved_reply: saved_reply).execute
present_result(result)
end
end
end
end
...@@ -23,7 +23,7 @@ module Mutations ...@@ -23,7 +23,7 @@ module Mutations
raise Gitlab::Graphql::Errors::ResourceNotAvailable, 'Feature disabled' unless feature_enabled? raise Gitlab::Graphql::Errors::ResourceNotAvailable, 'Feature disabled' unless feature_enabled?
saved_reply = authorized_find!(id) saved_reply = authorized_find!(id)
result = ::Users::SavedReplies::UpdateService.new(current_user: current_user, saved_reply: saved_reply, name: name, content: content).execute result = ::Users::SavedReplies::UpdateService.new(saved_reply: saved_reply, name: name, content: content).execute
present_result(result) present_result(result)
end end
end end
......
...@@ -131,6 +131,7 @@ module Types ...@@ -131,6 +131,7 @@ module Types
mount_mutation Mutations::WorkItems::Update mount_mutation Mutations::WorkItems::Update
mount_mutation Mutations::SavedReplies::Create mount_mutation Mutations::SavedReplies::Create
mount_mutation Mutations::SavedReplies::Update mount_mutation Mutations::SavedReplies::Update
mount_mutation Mutations::SavedReplies::Destroy
end end
end end
......
...@@ -25,6 +25,7 @@ class UserPolicy < BasePolicy ...@@ -25,6 +25,7 @@ class UserPolicy < BasePolicy
enable :update_user_status enable :update_user_status
enable :create_saved_replies enable :create_saved_replies
enable :update_saved_replies enable :update_saved_replies
enable :destroy_saved_replies
enable :read_user_personal_access_tokens enable :read_user_personal_access_tokens
enable :read_group_count enable :read_group_count
enable :read_user_groups enable :read_user_groups
......
# frozen_string_literal: true
module Users
module SavedReplies
class DestroyService
def initialize(saved_reply:)
@saved_reply = saved_reply
end
def execute
if saved_reply.destroy
ServiceResponse.success(payload: { saved_reply: saved_reply })
else
ServiceResponse.error(message: saved_reply.errors.full_messages)
end
end
private
attr_reader :saved_reply
end
end
end
...@@ -3,8 +3,7 @@ ...@@ -3,8 +3,7 @@
module Users module Users
module SavedReplies module SavedReplies
class UpdateService class UpdateService
def initialize(current_user:, saved_reply:, name:, content:) def initialize(saved_reply:, name:, content:)
@current_user = current_user
@saved_reply = saved_reply @saved_reply = saved_reply
@name = name @name = name
@content = content @content = content
...@@ -20,7 +19,7 @@ module Users ...@@ -20,7 +19,7 @@ module Users
private private
attr_reader :current_user, :saved_reply, :name, :content attr_reader :saved_reply, :name, :content
end end
end end
end end
...@@ -4261,7 +4261,26 @@ Input type: `SavedReplyCreateInput` ...@@ -4261,7 +4261,26 @@ Input type: `SavedReplyCreateInput`
| ---- | ---- | ----------- | | ---- | ---- | ----------- |
| <a id="mutationsavedreplycreateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. | | <a id="mutationsavedreplycreateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationsavedreplycreateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. | | <a id="mutationsavedreplycreateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
| <a id="mutationsavedreplycreatesavedreply"></a>`savedReply` | [`SavedReply`](#savedreply) | Updated saved reply. | | <a id="mutationsavedreplycreatesavedreply"></a>`savedReply` | [`SavedReply`](#savedreply) | Saved reply after mutation. |
### `Mutation.savedReplyDestroy`
Input type: `SavedReplyDestroyInput`
#### Arguments
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationsavedreplydestroyclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationsavedreplydestroyid"></a>`id` | [`UsersSavedReplyID!`](#userssavedreplyid) | Global ID of the saved reply. |
#### Fields
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationsavedreplydestroyclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationsavedreplydestroyerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
| <a id="mutationsavedreplydestroysavedreply"></a>`savedReply` | [`SavedReply`](#savedreply) | Saved reply after mutation. |
### `Mutation.savedReplyUpdate` ### `Mutation.savedReplyUpdate`
...@@ -4282,7 +4301,7 @@ Input type: `SavedReplyUpdateInput` ...@@ -4282,7 +4301,7 @@ Input type: `SavedReplyUpdateInput`
| ---- | ---- | ----------- | | ---- | ---- | ----------- |
| <a id="mutationsavedreplyupdateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. | | <a id="mutationsavedreplyupdateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationsavedreplyupdateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. | | <a id="mutationsavedreplyupdateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
| <a id="mutationsavedreplyupdatesavedreply"></a>`savedReply` | [`SavedReply`](#savedreply) | Updated saved reply. | | <a id="mutationsavedreplyupdatesavedreply"></a>`savedReply` | [`SavedReply`](#savedreply) | Saved reply after mutation. |
### `Mutation.scanExecutionPolicyCommit` ### `Mutation.scanExecutionPolicyCommit`
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Mutations::SavedReplies::Destroy do
let_it_be(:current_user) { create(:user) }
let_it_be(:saved_reply) { create(:saved_reply, user: current_user) }
let(:mutation) { described_class.new(object: nil, context: { current_user: current_user }, field: nil) }
describe '#resolve' do
subject(:resolve) do
mutation.resolve(id: saved_reply.to_global_id)
end
context 'when feature is disabled' do
before do
stub_feature_flags(saved_replies: false)
end
it 'raises Gitlab::Graphql::Errors::ResourceNotAvailable' do
expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable, 'Feature disabled')
end
end
context 'when feature is enabled for current user' do
before do
stub_feature_flags(saved_replies: current_user)
end
context 'when service fails to delete a new saved reply' do
before do
saved_reply.destroy!
end
it 'raises Gitlab::Graphql::Errors::ResourceNotAvailable' do
expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
end
end
context 'when service successfully deletes the saved reply' do
it { expect(subject[:errors]).to be_empty }
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Users::SavedReplies::DestroyService do
describe '#execute' do
let!(:saved_reply) { create(:saved_reply) }
subject { described_class.new(saved_reply: saved_reply).execute }
context 'when destroy fails' do
before do
allow(saved_reply).to receive(:destroy).and_return(false)
end
it 'does not remove Saved Reply from database' do
expect { subject }.not_to change(::Users::SavedReply, :count)
end
it { is_expected.not_to be_success }
end
context 'when destroy succeeds' do
it { is_expected.to be_success }
it 'removes Saved Reply from database' do
expect { subject }.to change(::Users::SavedReply, :count).by(-1)
end
it 'returns saved reply' do
expect(subject[:saved_reply]).to eq(saved_reply)
end
end
end
end
...@@ -9,7 +9,7 @@ RSpec.describe Users::SavedReplies::UpdateService do ...@@ -9,7 +9,7 @@ RSpec.describe Users::SavedReplies::UpdateService do
let_it_be(:other_saved_reply) { create(:saved_reply, user: current_user) } let_it_be(:other_saved_reply) { create(:saved_reply, user: current_user) }
let_it_be(:saved_reply_from_other_user) { create(:saved_reply) } let_it_be(:saved_reply_from_other_user) { create(:saved_reply) }
subject { described_class.new(current_user: current_user, saved_reply: saved_reply, name: name, content: content).execute } subject { described_class.new(saved_reply: saved_reply, name: name, content: content).execute }
context 'when update fails' do context 'when update fails' do
let(:name) { other_saved_reply.name } let(:name) { other_saved_reply.name }
......
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