Likes API endpoint complete

This commit is contained in:
Hank Grabowski 2018-10-15 10:36:34 -04:00
parent 2c94994f32
commit d6915ff5d0
7 changed files with 182 additions and 9 deletions

View file

@ -5,6 +5,8 @@ module Api
class BaseController < ApplicationController
include Api::OpenidConnect::ProtectedResourceEndpoint
protect_from_forgery unless: -> { request.format.json? }
protected
rescue_from Exception do |e|

View file

@ -3,31 +3,55 @@
module Api
module V1
class LikesController < Api::V1::BaseController
before_action only: %i[show] do
require_access_token %w[read]
end
before_action only: %i[create destroy] do
require_access_token %w[write]
end
rescue_from ActiveRecord::RecordNotFound do
render json: I18n.t("likes.not_found"), status: :not_found
render json: I18n.t("api.endpoint_errors.posts.post_not_found"), status: :not_found
end
rescue_from ActiveRecord::RecordInvalid do
render json: I18n.t("likes.create.fail"), status: :not_found
render json: I18n.t("api.endpoint_errors.likes.user_not_allowed_to_like"), status: :not_found
end
def show
likes = like_service.find_for_post(params[:post_id])
render json: likes.map {|x| like_json(x) }
end
def create
like_service.create(params[:post_id])
head :no_content, status: 204
rescue ActiveRecord::RecordInvalid => e
return render json: I18n.t("api.endpoint_errors.likes.like_exists"), status: :unprocessable_entity if
e.message == "Validation failed: Target has already been taken"
raise
else
head :no_content
end
def destroy
like_service.unlike_post(params[:post_id])
head :no_content, status: 204
success = like_service.unlike_post(params[:post_id])
if success
head :no_content
else
render json: I18n.t("api.endpoint_errors.likes.no_like"), status: :not_found
end
end
def like_service
@like_service ||= LikeService.new(current_user)
end
private
def like_json(like)
LikesPresenter.new(like).as_api_json
end
end
end
end

View file

@ -0,0 +1,10 @@
# frozen_string_literal: true
class LikesPresenter < BasePresenter
def as_api_json
{
guid: @presentable.guid,
author: PersonPresenter.new(@presentable.author).as_api_json
}
end
end

View file

@ -950,6 +950,13 @@ en:
contact_developer: "You should contact the developer of the application and include the following detailed error message:"
login_required: "You must first login before you can authorize this application"
could_not_authorize: "The application could not be authorized"
endpoint_errors:
likes:
user_not_allowed_to_like: "User is not allowed to like"
like_exists: "Like already exists"
no_like: "Like doesnt exist"
posts:
post_not_found: "Post with provided guid could not be found"
error:
not_found: "No record found for given id."
@ -1360,3 +1367,5 @@ en:
disabled: "Not available"
open: "Open"
closed: "Closed"

View file

@ -226,7 +226,7 @@ Rails.application.routes.draw do
resources :comments, only: %i[create index destroy] do
post "report" => "comments#report"
end
resource :likes, only: %i[create destroy]
resource :likes, only: %i[show create destroy]
end
resources :conversations, only: %i[show index create destroy] do
resources :messages, only: %i[index create]

View file

@ -15,6 +15,47 @@ describe Api::V1::LikesController do
)
end
describe "#show" do
context "with right post id" do
it "succeeds in getting empty likes" do
get(
api_v1_post_likes_path(post_id: @status.guid),
params: {access_token: access_token}
)
expect(response.status).to eq(200)
likes = response_body(response)
expect(likes.length).to eq(0)
end
it "succeeds in getting post with likes" do
like_service(bob).create(@status.guid)
like_service(auth.user).create(@status.guid)
like_service(alice).create(@status.guid)
get(
api_v1_post_likes_path(post_id: @status.guid),
params: {access_token: access_token}
)
expect(response.status).to eq(200)
likes = response_body(response)
expect(likes.length).to eq(3)
confirm_like_format(likes, alice)
confirm_like_format(likes, bob)
confirm_like_format(likes, auth.user)
end
end
context "with wrong post id" do
it "fails at getting likes" do
get(
api_v1_post_likes_path(post_id: "badguid"),
params: {access_token: access_token}
)
expect(response.status).to eq(404)
expect(response.body).to eq(I18n.t("api.endpoint_errors.posts.post_not_found"))
end
end
end
describe "#create" do
context "with right post id" do
it "succeeeds in liking post" do
@ -27,6 +68,25 @@ describe Api::V1::LikesController do
expect(likes.length).to eq(1)
expect(likes[0].author.id).to eq(auth.user.person.id)
end
it "fails in liking already liked post" do
post(
api_v1_post_likes_path(post_id: @status.guid),
params: {access_token: access_token}
)
expect(response.status).to eq(204)
post(
api_v1_post_likes_path(post_id: @status.guid),
params: {access_token: access_token}
)
expect(response.status).to eq(422)
expect(response.body).to eq(I18n.t("api.endpoint_errors.likes.like_exists"))
likes = like_service.find_for_post(@status.guid)
expect(likes.length).to eq(1)
expect(likes[0].author.id).to eq(auth.user.person.id)
end
end
context "with wrong post id" do
@ -36,11 +96,12 @@ describe Api::V1::LikesController do
params: {access_token: access_token}
)
expect(response.status).to eq(404)
expect(response.body).to eq(I18n.t("api.endpoint_errors.posts.post_not_found"))
end
end
end
describe "#create" do
describe "#delete" do
before do
post(
api_v1_post_likes_path(post_id: @status.guid),
@ -58,6 +119,24 @@ describe Api::V1::LikesController do
likes = like_service.find_for_post(@status.guid)
expect(likes.length).to eq(0)
end
it "fails at unliking post user didn't like" do
delete(
api_v1_post_likes_path(post_id: @status.guid),
params: {access_token: access_token}
)
expect(response.status).to eq(204)
delete(
api_v1_post_likes_path(post_id: @status.guid),
params: {access_token: access_token}
)
expect(response.status).to eq(404)
expect(response.body).to eq(I18n.t("api.endpoint_errors.likes.no_like"))
likes = like_service.find_for_post(@status.guid)
expect(likes.length).to eq(0)
end
end
context "with wrong post id" do
@ -67,11 +146,28 @@ describe Api::V1::LikesController do
params: {access_token: access_token}
)
expect(response.status).to eq(404)
expect(response.body).to eq(I18n.t("api.endpoint_errors.posts.post_not_found"))
end
end
end
def like_service
LikeService.new(auth.user)
private
# rubocop:disable Metrics/AbcSize
def confirm_like_format(likes, user)
like = likes.find {|like_element| like_element["author"]["guid"] == user.guid }
author = like["author"]
expect(author["diaspora_id"]).to eq(user.diaspora_handle)
expect(author["name"]).to eq(user.name)
expect(author["avatar"]).to eq(user.profile.image_url)
end
# rubocop:enable Metrics/AbcSize
def like_service(user=auth.user)
LikeService.new(user)
end
def response_body(response)
JSON.parse(response.body)
end
end

View file

@ -0,0 +1,32 @@
# frozen_string_literal: true
describe LikesPresenter do
before do
@status = alice.post(
:status_message,
text: "This is a status message from alice",
public: true,
to: "all"
)
bobs_like_service = LikeService.new(bob)
like = bobs_like_service.create(@status.guid)
@presenter = LikesPresenter.new(like, bob)
end
describe "#as_api_json" do
it "works" do
expect(@presenter.as_api_json).to be_present
end
it "confirm API V1 compliance" do
like = @presenter.as_api_json
expect(like.has_key?(:guid)).to be_truthy
author = like[:author]
expect(author).not_to be_nil
expect(author).to include(guid: bob.guid)
expect(author).to include(diaspora_id: bob.diaspora_handle)
expect(author).to include(name: bob.name)
expect(author).to include(avatar: bob.profile.image_url)
end
end
end