From 7475f9d175482254b9b3097226b95a14c5325cff Mon Sep 17 00:00:00 2001
From: "Z.J. van de Weg" <zegerjan@gitlab.com>
Date: Thu, 30 Jun 2016 10:56:56 +0200
Subject: [PATCH] API support for Award Emoji on Snippets

---
 CHANGELOG                             |  2 +-
 lib/api/award_emoji.rb                | 30 ++++++++++-----
 spec/requests/api/award_emoji_spec.rb | 55 ++++++++++++++++++++++++---
 3 files changed, 71 insertions(+), 16 deletions(-)

diff --git a/CHANGELOG b/CHANGELOG
index 786e9113af2..2344d9e36e4 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -281,6 +281,7 @@ v 8.11.0
   - Clean up unused routes (Josef Strzibny)
   - Fix issue on empty project to allow developers to only push to protected branches if given permission
   - API: Add enpoints for pipelines
+  - Emoji can be awarded on Snippets !4456
   - Add green outline to New Branch button. !5447 (winniehell)
   - Optimize generating of cache keys for issues and notes
   - Fix repository push email formatting in Outlook
@@ -508,7 +509,6 @@ v 8.10.0
   - Updated project header design
   - Issuable collapsed assignee tooltip is now the users name
   - Fix compare view not changing code view rendering style
-  - Emoji can be awarded on Snippets !4456
   - Exclude email check from the standard health check
   - Updated layout for Projects, Groups, Users on Admin area. !4424
   - Fix changing issue state columns in milestone view
diff --git a/lib/api/award_emoji.rb b/lib/api/award_emoji.rb
index 2898e8222fa..ecce75cd413 100644
--- a/lib/api/award_emoji.rb
+++ b/lib/api/award_emoji.rb
@@ -87,9 +87,7 @@ module API
 
     helpers do
       def can_read_awardable?
-        ability = "read_#{awardable.class.to_s.underscore}".to_sym
-
-        can?(current_user, ability, awardable)
+        can?(current_user, ability_name(awardable), awardable)
       end
 
       def can_award_awardable?
@@ -100,18 +98,30 @@ module API
         @awardable ||=
           begin
             if params.include?(:note_id)
-              noteable.notes.find(params[:note_id])
+              note_id = params[:note_id]
+              params.delete(:note_id)
+
+              awardable.notes.find(note_id)
+            elsif params.include?(:issue_id)
+              user_project.issues.find(params[:issue_id])
+            elsif params.include?(:merge_request_id)
+              user_project.merge_requests.find(params[:merge_request_id])
             else
-              noteable
+              user_project.snippets.find(params[:snippet_id])
             end
           end
       end
 
-      def noteable
-        if params.include?(:issue_id)
-          user_project.issues.find(params[:issue_id])
-        else
-          user_project.merge_requests.find(params[:merge_request_id])
+      def ability_name(awardable)
+        case awardable
+        when Note
+          ability_name(awardable.noteable)
+        when Snippet
+          :read_project_snippet
+        when MergeRequest
+          :read_merge_request
+        when Issue
+          :read_issue
         end
       end
     end
diff --git a/spec/requests/api/award_emoji_spec.rb b/spec/requests/api/award_emoji_spec.rb
index f55702794f6..f94ed37ddbc 100644
--- a/spec/requests/api/award_emoji_spec.rb
+++ b/spec/requests/api/award_emoji_spec.rb
@@ -4,7 +4,7 @@ describe API::API, api: true  do
   include ApiHelpers
   let(:user)            { create(:user) }
   let!(:project)        { create(:project) }
-  let(:issue)           { create(:issue, project: project) }
+  let(:issue)           { create(:issue, project: project, author: user) }
   let!(:award_emoji)    { create(:award_emoji, awardable: issue, user: user) }
   let!(:merge_request)  { create(:merge_request, source_project: project, target_project: project) }
   let!(:downvote)       { create(:award_emoji, :downvote, awardable: merge_request, user: user) }
@@ -14,9 +14,6 @@ describe API::API, api: true  do
 
   describe "GET /projects/:id/awardable/:awardable_id/award_emoji" do
     context 'on an issue' do
-      let(:issue)           { create(:issue, project: project, author: user) }
-      let!(:award_emoji)    { create(:award_emoji, awardable: issue, user: user) }
-
       it "returns an array of award_emoji" do
         get api("/projects/#{project.id}/issues/#{issue.id}/award_emoji", user)
 
@@ -43,7 +40,16 @@ describe API::API, api: true  do
     end
 
     context 'on a snippet' do
-      it 'returns the awarded '
+      let(:snippet) { create(:project_snippet, :public, project: project) }
+      let!(:award)  { create(:award_emoji, awardable: snippet) }
+
+      it 'returns the awarded emoji' do
+        get api("/projects/#{project.id}/snippets/#{snippet.id}/award_emoji", user)
+
+        expect(response).to have_http_status(200)
+        expect(json_response).to be_an Array
+        expect(json_response.first['name']).to eq(award.name)
+      end
     end
 
     context 'when the user has no access' do
@@ -98,6 +104,20 @@ describe API::API, api: true  do
       end
     end
 
+    context 'on a snippet' do
+      let(:snippet) { create(:project_snippet, :public, project: project) }
+      let!(:award)  { create(:award_emoji, awardable: snippet) }
+
+      it 'returns the awarded emoji' do
+        get api("/projects/#{project.id}/snippets/#{snippet.id}/award_emoji/#{award.id}", user)
+
+        expect(response).to have_http_status(200)
+        expect(json_response['name']).to eq(award.name)
+        expect(json_response['awardable_id']).to eq(snippet.id)
+        expect(json_response['awardable_type']).to eq("Snippet")
+      end
+    end
+
     context 'when the user has no access' do
       it 'returns a status code 404' do
         user1 = create(:user)
@@ -167,6 +187,18 @@ describe API::API, api: true  do
         end
       end
     end
+
+    context 'on a snippet' do
+      it 'creates a new award emoji' do
+        snippet = create(:project_snippet, :public, project: project)
+
+        post api("/projects/#{project.id}/snippets/#{snippet.id}/award_emoji", user), name: 'blowfish'
+
+        expect(response).to have_http_status(201)
+        expect(json_response['name']).to eq('blowfish')
+        expect(json_response['user']['username']).to eq(user.username)
+      end
+    end
   end
 
   describe "POST /projects/:id/awardable/:awardable_id/notes/:note_id/award_emoji" do
@@ -236,6 +268,19 @@ describe API::API, api: true  do
         expect(response).to have_http_status(404)
       end
     end
+
+    context 'when the awardable is a Snippet' do
+      let(:snippet) { create(:project_snippet, :public, project: project) }
+      let!(:award)  { create(:award_emoji, awardable: snippet, user: user) }
+
+      it 'deletes the award' do
+        expect do
+          delete api("/projects/#{project.id}/snippets/#{snippet.id}/award_emoji/#{award.id}", user)
+        end.to change { snippet.award_emoji.count }.from(1).to(0)
+
+        expect(response).to have_http_status(200)
+      end
+    end
   end
 
   describe 'DELETE /projects/:id/awardable/:awardable_id/award_emoji/:award_emoji_id' do
-- 
2.30.9