Merge pull request #13 from frankrousseau/api-reshare-update
API Reshare Endpoint Feature Complete With Full Tests
This commit is contained in:
commit
6924781bb0
5 changed files with 265 additions and 5 deletions
42
app/controllers/api/v1/reshares_controller.rb
Normal file
42
app/controllers/api/v1/reshares_controller.rb
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Api
|
||||||
|
module V1
|
||||||
|
class ResharesController < Api::V1::BaseController
|
||||||
|
before_action only: %i[show] do
|
||||||
|
require_access_token %w[read]
|
||||||
|
end
|
||||||
|
|
||||||
|
before_action only: %i[create] do
|
||||||
|
require_access_token %w[read write]
|
||||||
|
end
|
||||||
|
|
||||||
|
rescue_from ActiveRecord::RecordNotFound do
|
||||||
|
render json: I18n.t("api.endpoint_errors.posts.post_not_found"), status: :not_found
|
||||||
|
end
|
||||||
|
|
||||||
|
rescue_from Diaspora::NonPublic do
|
||||||
|
render json: I18n.t("api.endpoint_errors.posts.post_not_found"), status: :not_found
|
||||||
|
end
|
||||||
|
|
||||||
|
def show
|
||||||
|
reshares = reshare_service.find_for_post(params[:post_id]).map do |r|
|
||||||
|
{guid: r.guid, author: PersonPresenter.new(r.author).as_api_json}
|
||||||
|
end
|
||||||
|
render json: reshares
|
||||||
|
end
|
||||||
|
|
||||||
|
def create
|
||||||
|
reshare = reshare_service.create(params[:post_id])
|
||||||
|
rescue ActiveRecord::RecordNotFound, ActiveRecord::RecordInvalid, RuntimeError
|
||||||
|
render plain: I18n.t("reshares.create.error"), status: :unprocessable_entity
|
||||||
|
else
|
||||||
|
render json: PostPresenter.new(reshare, current_user).as_api_response
|
||||||
|
end
|
||||||
|
|
||||||
|
def reshare_service
|
||||||
|
@reshare_service ||= ReshareService.new(current_user)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -24,6 +24,7 @@ module User::SocialActions
|
||||||
end
|
end
|
||||||
|
|
||||||
def reshare!(target, opts={})
|
def reshare!(target, opts={})
|
||||||
|
raise I18n.t("reshares.create.error") if target.author.guid == guid
|
||||||
build_post(:reshare, :root_guid => target.guid).tap do |reshare|
|
build_post(:reshare, :root_guid => target.guid).tap do |reshare|
|
||||||
reshare.save!
|
reshare.save!
|
||||||
update_or_create_participation!(target)
|
update_or_create_participation!(target)
|
||||||
|
|
|
||||||
|
|
@ -226,6 +226,7 @@ Rails.application.routes.draw do
|
||||||
resources :comments, only: %i[create index destroy] do
|
resources :comments, only: %i[create index destroy] do
|
||||||
post "report" => "comments#report"
|
post "report" => "comments#report"
|
||||||
end
|
end
|
||||||
|
resource :reshares, only: %i[show create]
|
||||||
resource :likes, only: %i[show create destroy]
|
resource :likes, only: %i[show create destroy]
|
||||||
end
|
end
|
||||||
resources :conversations, only: %i[show index create destroy] do
|
resources :conversations, only: %i[show index create destroy] do
|
||||||
|
|
|
||||||
216
spec/integration/api/reshares_controller_spec.rb
Normal file
216
spec/integration/api/reshares_controller_spec.rb
Normal file
|
|
@ -0,0 +1,216 @@
|
||||||
|
# frozen_sTring_literal: true
|
||||||
|
|
||||||
|
require "spec_helper"
|
||||||
|
|
||||||
|
describe Api::V1::ResharesController do
|
||||||
|
let(:auth) { FactoryGirl.create(:auth_with_read_and_write) }
|
||||||
|
let!(:access_token) { auth.create_access_token.to_s }
|
||||||
|
let(:auth_read_only) { FactoryGirl.create(:auth_with_read) }
|
||||||
|
let!(:access_token_read_only) { auth_read_only.create_access_token.to_s }
|
||||||
|
|
||||||
|
before do
|
||||||
|
@user_post = auth.user.post(
|
||||||
|
:status_message,
|
||||||
|
text: "This is a status message",
|
||||||
|
public: true,
|
||||||
|
to: "all"
|
||||||
|
)
|
||||||
|
|
||||||
|
@eve_post = eve.post(
|
||||||
|
:status_message,
|
||||||
|
text: "This is Bob's status message",
|
||||||
|
public: true,
|
||||||
|
to: "all"
|
||||||
|
)
|
||||||
|
|
||||||
|
@alice_reshare = ReshareService.new(alice).create(@user_post.id)
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#show" do
|
||||||
|
context "with valid post id" do
|
||||||
|
it "succeeds" do
|
||||||
|
get(
|
||||||
|
api_v1_post_reshares_path(@user_post.guid),
|
||||||
|
params: {access_token: access_token}
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(response.status).to eq(200)
|
||||||
|
reshares = JSON.parse(response.body)
|
||||||
|
expect(reshares.length).to eq(1)
|
||||||
|
reshare = reshares[0]
|
||||||
|
expect(reshare["guid"]).not_to be_nil
|
||||||
|
confirm_person_format(reshare["author"], alice)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "succeeds but empty with private post it can see" do
|
||||||
|
private_post = auth.user.post(
|
||||||
|
:status_message,
|
||||||
|
text: "to aspect only",
|
||||||
|
public: false,
|
||||||
|
to: auth.user.aspects.first.id
|
||||||
|
)
|
||||||
|
|
||||||
|
get(
|
||||||
|
api_v1_post_reshares_path(private_post.id),
|
||||||
|
params: {
|
||||||
|
access_token: access_token
|
||||||
|
}
|
||||||
|
)
|
||||||
|
expect(response.status).to eq(200)
|
||||||
|
reshares = JSON.parse(response.body)
|
||||||
|
expect(reshares.length).to eq(0)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "with invalid post id" do
|
||||||
|
it "fails with bad id" do
|
||||||
|
get(
|
||||||
|
api_v1_post_reshares_path("999_999_999"),
|
||||||
|
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
|
||||||
|
|
||||||
|
it "fails with private post it shouldn't see" do
|
||||||
|
private_post = alice.post(:status_message, text: "to aspect only", public: false, to: alice.aspects.first.id)
|
||||||
|
get(
|
||||||
|
api_v1_post_reshares_path(private_post.id),
|
||||||
|
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
|
||||||
|
|
||||||
|
context "improper credentials" do
|
||||||
|
it "fails when not logged in" do
|
||||||
|
get(
|
||||||
|
api_v1_post_reshares_path(@user_post.id),
|
||||||
|
params: {
|
||||||
|
access_token: "999_999_999"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
expect(response.status).to eq(401)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#create" do
|
||||||
|
context "with valid post id" do
|
||||||
|
it "succeeds" do
|
||||||
|
post(
|
||||||
|
api_v1_post_reshares_path(post_id: @eve_post.guid),
|
||||||
|
params: {access_token: access_token}
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(response.status).to eq(200)
|
||||||
|
post = JSON.parse(response.body)
|
||||||
|
expect(post["guid"]).not_to be_nil
|
||||||
|
expect(post["body"]).to eq(@eve_post.text)
|
||||||
|
expect(post["post_type"]).to eq("Reshare")
|
||||||
|
expect(post["author"]["guid"]).to eq(auth.user.guid)
|
||||||
|
expect(post["root"]["guid"]).to eq(@eve_post.guid)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "fails to reshare twice" do
|
||||||
|
reshare_service.create(@eve_post.id)
|
||||||
|
post(
|
||||||
|
api_v1_post_reshares_path(post_id: @eve_post.guid),
|
||||||
|
params: {access_token: access_token}
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(response.status).to eq(422)
|
||||||
|
expect(response.body).to eq(I18n.t("reshares.create.error"))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "with invalid post id" do
|
||||||
|
it "fails with bad id" do
|
||||||
|
post(
|
||||||
|
api_v1_post_reshares_path(post_id: "999_999_999"),
|
||||||
|
params: {access_token: access_token}
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(response.status).to eq(422)
|
||||||
|
expect(response.body).to eq(I18n.t("reshares.create.error"))
|
||||||
|
end
|
||||||
|
|
||||||
|
it "fails with own post" do
|
||||||
|
post(
|
||||||
|
api_v1_post_reshares_path(post_id: @user_post.guid),
|
||||||
|
params: {access_token: access_token}
|
||||||
|
)
|
||||||
|
|
||||||
|
puts(response.body)
|
||||||
|
expect(response.status).to eq(422)
|
||||||
|
expect(response.body).to eq(I18n.t("reshares.create.error"))
|
||||||
|
end
|
||||||
|
|
||||||
|
it "fails with private post it shouldn't see" do
|
||||||
|
private_post = alice.post(:status_message, text: "to aspect only", public: false, to: alice.aspects.first.id)
|
||||||
|
post(
|
||||||
|
api_v1_post_reshares_path(private_post.id),
|
||||||
|
params: {
|
||||||
|
access_token: access_token
|
||||||
|
}
|
||||||
|
)
|
||||||
|
expect(response.status).to eq(422)
|
||||||
|
expect(response.body).to eq(I18n.t("reshares.create.error"))
|
||||||
|
end
|
||||||
|
|
||||||
|
it "fails with private post it can see" do
|
||||||
|
private_post = alice.post(:status_message, text: "to aspect only", public: false, to: alice.aspects)
|
||||||
|
get(
|
||||||
|
api_v1_post_reshares_path(private_post.id),
|
||||||
|
params: {
|
||||||
|
access_token: access_token
|
||||||
|
}
|
||||||
|
)
|
||||||
|
puts(response.body)
|
||||||
|
expect(response.status).to eq(404)
|
||||||
|
expect(response.body).to eq(I18n.t("api.endpoint_errors.posts.post_not_found"))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "improper credentials" do
|
||||||
|
it "fails when not logged in" do
|
||||||
|
post(
|
||||||
|
api_v1_post_reshares_path(@eve_post.id),
|
||||||
|
params: {
|
||||||
|
access_token: "999_999_999"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
expect(response.status).to eq(401)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "fails when logged in read only" do
|
||||||
|
post(
|
||||||
|
api_v1_post_reshares_path(@eve_post.id),
|
||||||
|
params: {
|
||||||
|
access_token: auth_read_only
|
||||||
|
}
|
||||||
|
)
|
||||||
|
expect(response.status).to eq(401)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def reshare_service(user=auth.user)
|
||||||
|
@reshare_service ||= ReshareService.new(user)
|
||||||
|
end
|
||||||
|
|
||||||
|
# rubocop:disable Metrics/AbcSize
|
||||||
|
def confirm_person_format(post_person, user)
|
||||||
|
expect(post_person["guid"]).to eq(user.guid)
|
||||||
|
expect(post_person["diaspora_id"]).to eq(user.diaspora_handle)
|
||||||
|
expect(post_person["name"]).to eq(user.name)
|
||||||
|
expect(post_person["avatar"]).to eq(user.profile.image_url)
|
||||||
|
end
|
||||||
|
# rubocop:enable Metrics/AbcSize
|
||||||
|
end
|
||||||
|
|
@ -7,7 +7,7 @@ describe ReshareService do
|
||||||
it "doesn't create a reshare of my own post" do
|
it "doesn't create a reshare of my own post" do
|
||||||
expect {
|
expect {
|
||||||
ReshareService.new(alice).create(post.id)
|
ReshareService.new(alice).create(post.id)
|
||||||
}.not_to raise_error
|
}.to raise_error RuntimeError
|
||||||
end
|
end
|
||||||
|
|
||||||
it "creates a reshare of a post of a contact" do
|
it "creates a reshare of a post of a contact" do
|
||||||
|
|
@ -76,9 +76,9 @@ describe ReshareService do
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns the user's reshare first" do
|
it "returns the user's reshare first" do
|
||||||
[alice, bob, eve].map {|user| ReshareService.new(user).create(post.id) }
|
[bob, eve].map {|user| ReshareService.new(user).create(post.id) }
|
||||||
|
|
||||||
[alice, bob, eve].each do |user|
|
[bob, eve].each do |user|
|
||||||
expect(
|
expect(
|
||||||
ReshareService.new(user).find_for_post(post.id).first.author.id
|
ReshareService.new(user).find_for_post(post.id).first.author.id
|
||||||
).to be user.person.id
|
).to be user.person.id
|
||||||
|
|
@ -88,7 +88,7 @@ describe ReshareService do
|
||||||
|
|
||||||
context "without user" do
|
context "without user" do
|
||||||
it "returns reshares for a public post" do
|
it "returns reshares for a public post" do
|
||||||
reshare = ReshareService.new(alice).create(post.id)
|
reshare = ReshareService.new(bob).create(post.id)
|
||||||
expect(ReshareService.new.find_for_post(post.id)).to include(reshare)
|
expect(ReshareService.new.find_for_post(post.id)).to include(reshare)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -101,7 +101,7 @@ describe ReshareService do
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns all reshares of a post" do
|
it "returns all reshares of a post" do
|
||||||
reshares = [alice, bob, eve].map {|user| ReshareService.new(user).create(post.id) }
|
reshares = [bob, eve].map {|user| ReshareService.new(user).create(post.id) }
|
||||||
|
|
||||||
expect(ReshareService.new.find_for_post(post.id)).to match_array(reshares)
|
expect(ReshareService.new.find_for_post(post.id)).to match_array(reshares)
|
||||||
end
|
end
|
||||||
Loading…
Reference in a new issue