1# frozen_string_literal: true
2
3require 'spec_helper'
4
5RSpec.describe 'Toggling an AwardEmoji' do
6  include GraphqlHelpers
7
8  let_it_be(:current_user) { create(:user) }
9  let_it_be(:project, reload: true) { create(:project) }
10  let_it_be(:awardable) { create(:note, project: project) }
11
12  let(:emoji_name) { 'thumbsup' }
13  let(:mutation) do
14    variables = {
15      awardable_id: GitlabSchema.id_from_object(awardable).to_s,
16      name: emoji_name
17    }
18
19    graphql_mutation(:award_emoji_toggle, variables)
20  end
21
22  def mutation_response
23    graphql_mutation_response(:award_emoji_toggle)
24  end
25
26  shared_examples 'a mutation that does not create or destroy an AwardEmoji' do
27    specify do
28      expect do
29        post_graphql_mutation(mutation, current_user: current_user)
30      end.not_to change { AwardEmoji.count }
31    end
32  end
33
34  def create_award_emoji(user)
35    create(:award_emoji, name: emoji_name, awardable: awardable, user: user )
36  end
37
38  context 'when the user has permission' do
39    before do
40      project.add_developer(current_user)
41    end
42
43    context 'when the given awardable is not an Awardable' do
44      let(:awardable) { create(:label, project: project) }
45
46      it_behaves_like 'a mutation that does not create or destroy an AwardEmoji'
47
48      it_behaves_like 'a mutation that returns top-level errors' do
49        let(:match_errors) { include(/was provided invalid value for awardableId/) }
50      end
51    end
52
53    context 'when the given awardable is an Awardable but still cannot be awarded an emoji' do
54      let(:awardable) { create(:system_note, project: project) }
55
56      it_behaves_like 'a mutation that does not create or destroy an AwardEmoji'
57
58      it_behaves_like 'a mutation that returns top-level errors',
59        errors: ['You cannot award emoji to this resource.']
60    end
61
62    context 'when the given awardable is an Awardable' do
63      context 'when no emoji has been awarded by the current_user yet' do
64        # Create an award emoji for another user. This therefore tests that
65        # toggling is correctly scoped to the user's emoji only.
66        let!(:award_emoji) { create_award_emoji(create(:user)) }
67
68        it 'creates an emoji' do
69          expect do
70            post_graphql_mutation(mutation, current_user: current_user)
71          end.to change { AwardEmoji.count }.by(1)
72        end
73
74        it 'returns the emoji' do
75          post_graphql_mutation(mutation, current_user: current_user)
76
77          expect(mutation_response['awardEmoji']['name']).to eq(emoji_name)
78        end
79
80        it 'returns toggledOn as true' do
81          post_graphql_mutation(mutation, current_user: current_user)
82
83          expect(mutation_response['toggledOn']).to eq(true)
84        end
85
86        describe 'marking Todos as done' do
87          let(:user) { current_user}
88
89          subject { post_graphql_mutation(mutation, current_user: user) }
90
91          include_examples 'creating award emojis marks Todos as done'
92        end
93
94        context 'when there were active record validation errors' do
95          before do
96            expect_next_instance_of(AwardEmoji) do |award|
97              expect(award).to receive(:valid?).at_least(:once).and_return(false)
98              expect(award).to receive_message_chain(:errors, :full_messages).and_return(['Error 1', 'Error 2'])
99            end
100          end
101
102          it_behaves_like 'a mutation that does not create or destroy an AwardEmoji'
103
104          it_behaves_like 'a mutation that returns errors in the response', errors: ['Error 1', 'Error 2']
105
106          it 'returns an empty awardEmoji' do
107            post_graphql_mutation(mutation, current_user: current_user)
108
109            expect(mutation_response).to have_key('awardEmoji')
110            expect(mutation_response['awardEmoji']).to be_nil
111          end
112        end
113      end
114
115      context 'when an emoji has been awarded by the current_user' do
116        let!(:award_emoji) { create_award_emoji(current_user) }
117
118        it 'removes the emoji' do
119          expect do
120            post_graphql_mutation(mutation, current_user: current_user)
121          end.to change { AwardEmoji.count }.by(-1)
122        end
123
124        it 'returns no errors' do
125          post_graphql_mutation(mutation, current_user: current_user)
126
127          expect(graphql_errors).to be_nil
128        end
129
130        it 'returns an empty awardEmoji' do
131          post_graphql_mutation(mutation, current_user: current_user)
132
133          expect(mutation_response).to have_key('awardEmoji')
134          expect(mutation_response['awardEmoji']).to be_nil
135        end
136
137        it 'returns toggledOn as false' do
138          post_graphql_mutation(mutation, current_user: current_user)
139
140          expect(mutation_response['toggledOn']).to eq(false)
141        end
142      end
143    end
144  end
145
146  context 'when the user does not have permission' do
147    it_behaves_like 'a mutation that does not create or destroy an AwardEmoji'
148    it_behaves_like 'a mutation that returns a top-level access error'
149  end
150end
151