Commit cbd3e638 authored by Michael Kozono's avatar Michael Kozono

Merge branch '34132-graphql-epic-subscribtions' into 'master'

Graphql mutation for (un)subscribing to an epic

See merge request gitlab-org/gitlab!19083
parents 40771e9c e264fc71
......@@ -59,6 +59,14 @@ module Subscribable
.update(subscribed: false)
end
def set_subscription(user, desired_state, project = nil)
if desired_state
subscribe(user, project)
else
unsubscribe(user, project)
end
end
private
def unsubscribe_from_other_levels(user, project)
......
---
title: Graphql mutation for (un)subscribing to an epic
merge_request: 19083
author:
type: added
......@@ -271,6 +271,14 @@ The API can be explored interactively using the [GraphiQL IDE](../index.md#graph
| `createNote` | Boolean! | Whether or not a user can perform `create_note` on this resource |
| `awardEmoji` | Boolean! | Whether or not a user can perform `award_emoji` on this resource |
### EpicSetSubscriptionPayload
| 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 epic after mutation |
### EpicTreeReorderPayload
| Name | Type | Description |
......
......@@ -11,6 +11,7 @@ module EE
mount_mutation ::Mutations::EpicTree::Reorder
mount_mutation ::Mutations::Epics::Update
mount_mutation ::Mutations::Epics::Create
mount_mutation ::Mutations::Epics::SetSubscription
end
end
end
......
# frozen_string_literal: true
module Mutations
module Epics
class Base < ::Mutations::BaseMutation
include Mutations::ResolvesGroup
private
def find_object(group_path:, iid:)
group = resolve_group(full_path: group_path)
resolver = Resolvers::EpicResolver
.single.new(object: group, context: context)
resolver.resolve(iid: iid)
end
end
end
end
# frozen_string_literal: true
module Mutations
module Epics
class SetSubscription < Base
graphql_name 'EpicSetSubscription'
authorize :read_epic
argument :group_path, GraphQL::ID_TYPE,
required: true,
description: 'The group the epic to (un)subscribe is in'
argument :iid, GraphQL::ID_TYPE,
required: true,
description: 'The iid of the epic to (un)subscribe'
argument :subscribed_state, GraphQL::BOOLEAN_TYPE,
required: true,
description: 'The desired state of the subscription'
field :epic,
Types::EpicType,
null: true,
description: 'The epic after mutation'
def resolve(args)
group_path = args.delete(:group_path)
epic_iid = args.delete(:iid)
desired_state = args.delete(:subscribed_state)
epic = authorized_find!(group_path: group_path, iid: epic_iid)
epic.set_subscription(current_user, desired_state)
{
epic: epic.reset,
errors: errors_on_object(epic)
}
end
end
end
end
......@@ -2,8 +2,7 @@
module Mutations
module Epics
class Update < BaseMutation
include Mutations::ResolvesGroup
class Update < Base
prepend Mutations::SharedEpicArguments
graphql_name 'UpdateEpic'
......@@ -38,16 +37,6 @@ module Mutations
errors: errors_on_object(epic)
}
end
private
def find_object(group_path:, iid:)
group = resolve_group(full_path: group_path)
resolver = Resolvers::EpicResolver
.single.new(object: group, context: context)
resolver.resolve(iid: iid)
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
describe 'Set an Epic Subscription' do
include GraphqlHelpers
let_it_be(:current_user) { create(:user) }
let_it_be(:group) { create(:group) }
let(:epic) { create(:epic, group: group) }
let(:subscribed_state) { true }
let(:mutation) do
params = { group_path: group.full_path, iid: epic.iid.to_s, subscribed_state: subscribed_state }
graphql_mutation(:epic_set_subscription, params)
end
def mutation_response
graphql_mutation_response(:epic_set_subscription)
end
context 'when epics feature is disabled' do
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 subscribe user to the epic' do
post_graphql_mutation(mutation, current_user: current_user)
expect(epic.subscribed?(current_user)).to be_falsey
end
end
context 'when epics feature is enabled' do
before do
stub_licensed_features(epics: true)
end
context 'when a user wants to subscribe to an epic' do
it 'subscribes the user to the epic' do
post_graphql_mutation(mutation, current_user: current_user)
expect(epic.subscribed?(current_user)).to be_truthy
end
end
context 'when a user wants to unsubscribe from an epic' do
let(:subscribed_state) { false }
it 'unsubscribes the user from the epic' do
epic.subscribe(current_user)
post_graphql_mutation(mutation, current_user: current_user)
expect(epic.subscribed?(current_user)).to be_falsey
end
end
end
end
......@@ -133,4 +133,60 @@ describe Subscribable, 'Subscribable' do
end
end
end
describe '#set_subscription' do
shared_examples 'setting subscriptions' do
context 'when desired_state is set to true' do
context 'when a user is subscribed to the resource' do
it 'keeps the user subscribed' do
resource.subscriptions.create(user: user_1, subscribed: true, project: resource_project)
resource.set_subscription(user_1, true, resource_project)
expect(resource.subscribed?(user_1, resource_project)).to be_truthy
end
end
context 'when a user is not subscribed to the resource' do
it 'subscribes the user to the resource' do
expect { resource.set_subscription(user_1, true, resource_project) }
.to change { resource.subscribed?(user_1, resource_project) }
.from(false).to(true)
end
end
end
context 'when desired_state is set to false' do
context 'when a user is subscribed to the resource' do
it 'unsubscribes the user from the resource' do
resource.subscriptions.create(user: user_1, subscribed: true, project: resource_project)
expect { resource.set_subscription(user_1, false, resource_project) }
.to change { resource.subscribed?(user_1, resource_project) }
.from(true).to(false)
end
end
context 'when a user is not subscribed to the resource' do
it 'keeps the user unsubscribed' do
resource.set_subscription(user_1, false, resource_project)
expect(resource.subscribed?(user_1, resource_project)).to be_falsey
end
end
end
end
context 'without project' do
let(:resource_project) { nil }
it_behaves_like 'setting subscriptions'
end
context 'with project' do
let(:resource_project) { project }
it_behaves_like 'setting subscriptions'
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