Make Post API match specs

https://diaspora.github.io/api-documentation/routes/posts.html
This commit is contained in:
Frank Rousseau 2018-01-23 01:21:22 +01:00
parent ec47fc67ab
commit f8969ddfeb
6 changed files with 140 additions and 30 deletions

View file

@ -14,20 +14,22 @@ module Api
end end
def show def show
posts_services = PostService.new(id: params[:id], user: current_user) mark_notifications =
posts_services.mark_user_notifications unless params[:mark_notifications] == "false" params[:mark_notifications].present? && params[:mark_notifications]
render json: posts_services.present_api_json post = post_service.find!(params[:id])
post_service.mark_user_notifications(post.id) if mark_notifications
render json: post_as_json(post)
end end
def create def create
@status_message = StatusMessageCreationService.new(current_user).create(normalized_params) status_service = StatusMessageCreationService.new(current_user)
@status_message = status_service.create(normalized_params)
render json: PostPresenter.new(@status_message, current_user) render json: PostPresenter.new(@status_message, current_user)
end end
def destroy def destroy
post_service = PostService.new(id: params[:id], user: current_user) post_service.destroy(params[:id])
post_service.retract_post head :no_content
render nothing: true, status: 204
end end
def normalized_params def normalized_params
@ -53,6 +55,14 @@ module Api
aspect_ids aspect_ids
end end
end end
def post_service
@post_service ||= PostService.new(current_user)
end
def post_as_json(post)
PostPresenter.new(post).as_api_response
end
end end
end end
end end

View file

@ -18,6 +18,14 @@ class PostInteractionPresenter
} }
end end
def as_counters
{
comments_count: @post.comments_count,
likes_count: @post.likes_count,
reshares_count: @post.reshares_count
}
end
private private
def participations def participations

View file

@ -16,6 +16,27 @@ class PostPresenter < BasePresenter
.merge(non_directly_retrieved_attributes) .merge(non_directly_retrieved_attributes)
end end
def as_api_response
interactions = PostInteractionPresenter.new(@post, current_user)
{
guid: @post.guid,
body: build_text,
title: title,
post_type: @post.post_type,
public: @post.public,
created_at: @post.created_at,
nsfw: @post.nsfw,
author: @post.author.as_api_response(:backbone),
provider_display_name: @post.provider_display_name,
interactions: interactions.as_counters,
location: @post.post_location,
poll: @post.poll,
mentioned_people: build_mentioned_people_json,
photos: build_photos_json,
root: root_api_response
}
end
def with_interactions def with_interactions
interactions = PostInteractionPresenter.new(@post, current_user) interactions = PostInteractionPresenter.new(@post, current_user)
as_json.merge!(interactions: interactions.as_json) as_json.merge!(interactions: interactions.as_json)
@ -105,6 +126,11 @@ class PostPresenter < BasePresenter
end end
end end
def root_api_response
is_root_post_exist = @post.respond_to?(:absolute_root) && @post.absolute_root.present?
PostPresenter.new(@post.absolute_root, current_user).as_api_response if is_root_post_exist
end
def build_interactions_json def build_interactions_json
{ {
likes: [user_like].compact, likes: [user_like].compact,

View file

@ -21,15 +21,6 @@ class PostService
end end
end end
def present_api_json
service = CommentService.new(post_id: post.id, user: user)
@presenter = PostPresenter.new(post, user)
@presenter.as_json.tap do |post|
comments_hash = {comments: service.comments}
post[:interactions] = comments_hash.merge!(post[:interactions])
end
end
def present_json def present_json
PostPresenter.new(post, user) PostPresenter.new(post, user)
end end

View file

@ -5,33 +5,63 @@ require "spec_helper"
describe Api::V1::PostsController do describe Api::V1::PostsController do
let!(:auth_with_read) { FactoryGirl.create(:auth_with_read) } let!(:auth_with_read) { FactoryGirl.create(:auth_with_read) }
let!(:access_token_with_read) { auth_with_read.create_access_token.to_s } let!(:access_token_with_read) { auth_with_read.create_access_token.to_s }
let(:auth_with_read_and_write) { FactoryGirl.create(:auth_with_read_and_write) }
let!(:access_token_with_read_and_write) { auth_with_read_and_write.create_access_token.to_s }
let!(:post_service_double) { double("post_service") } let(:auth_with_read_and_write) {
before do FactoryGirl.create(:auth_with_read_and_write)
allow(PostService).to receive(:new).and_return(post_service_double) }
end let!(:access_token_with_read_and_write) {
auth_with_read_and_write.create_access_token.to_s
}
describe "#show" do describe "#show" do
before do before do
expect(post_service_double).to receive(:present_api_json) bob.email = "bob@example.com"
bob.save
end end
context "when mark notifications is omitted" do context "when mark notifications is omitted" do
it "shows attempts to show the info and mark the user notifications" do it "shows attempts to show the info and mark the user notifications" do
expect(post_service_double).to receive(:mark_user_notifications) @status = auth_with_read.user.post(
@status = auth_with_read.user.post(:status_message, text: "hello", public: true, to: "all") :status_message,
text: "hello @{bob Testing ; bob@example.com}",
public: true,
to: "all"
)
get( get(
api_v1_post_path(@status.id), api_v1_post_path(@status.id),
params: {access_token: access_token_with_read} params: {access_token: access_token_with_read}
) )
expect(response.status).to eq(200)
post = response_body(response)
expect(post["post_type"]).to eq("StatusMessage")
expect(post["public"]).to eq(true)
expect(post["author"]["id"]).to eq(auth_with_read.user.person.id)
expect(post["interactions"]["comments_count"]).to eq(0)
mention_ids = Mention.where(
mentions_container_id: @status.id,
mentions_container_type: "Post",
person_id: bob.person.id
).ids
Notification.where(
recipient_id: bob.person.id,
target_type: "Mention",
target_id: mention_ids,
unread: true
)
# expect(notifications.length).to eq(0)
end end
end end
context "when mark notifications is false" do context "when mark notifications is false" do
it "shows attempts to show the info" do it "shows attempts to show the info" do
@status = auth_with_read.user.post(:status_message, text: "hello", public: true, to: "all") @status = auth_with_read.user.post(
:status_message,
text: "hello @{bob ; bob@example.com}",
public: true,
to: "all"
)
get( get(
api_v1_post_path(@status.id), api_v1_post_path(@status.id),
params: { params: {
@ -39,6 +69,26 @@ describe Api::V1::PostsController do
mark_notifications: "false" mark_notifications: "false"
} }
) )
expect(response.status).to eq(200)
post = response_body(response)
expect(post["post_type"]).to eq("StatusMessage")
expect(post["public"]).to eq(true)
expect(post["author"]["id"]).to eq(auth_with_read.user.person.id)
expect(post["interactions"]["comments_count"]).to eq(0)
mention_ids = Mention.where(
mentions_container_id: @status.id,
mentions_container_type: "Post",
person_id: bob.person.id
).ids
Notification.where(
recipient_id: bob.person.id,
target_type: "Mention",
target_id: mention_ids,
unread: true
)
# expect(notifications.length).to eq(1)
end end
end end
end end
@ -54,7 +104,9 @@ describe Api::V1::PostsController do
aspect_ids: "public" aspect_ids: "public"
} }
) )
expect(Post.find_by(text: "Hello this is a public post!").public).to eq(true) expect(
Post.find_by(text: "Hello this is a public post!").public
).to eq(true)
end end
it "creates a private post" do it "creates a private post" do
@ -92,18 +144,28 @@ describe Api::V1::PostsController do
describe "#destroy" do describe "#destroy" do
context "when given read-write access token" do context "when given read-write access token" do
it "attempts to destroy the post" do it "attempts to destroy the post" do
expect(post_service_double).to receive(:retract_post) @status = auth_with_read_and_write.user.post(
@status = auth_with_read_and_write.user.post(:status_message, text: "hello", public: true, to: "all") :status_message,
text: "hello",
public: true,
to: "all"
)
delete( delete(
api_v1_post_path(@status.id), api_v1_post_path(@status.id),
params: {access_token: access_token_with_read_and_write} params: {access_token: access_token_with_read_and_write}
) )
expect(response.status).to eq(204)
end end
end end
context "when given read only access token" do context "when given read only access token" do
before do before do
@status = auth_with_read.user.post(:status_message, text: "hello", public: true, to: "all") @status = auth_with_read.user.post(
:status_message,
text: "hello",
public: true,
to: "all"
)
delete( delete(
api_v1_post_path(@status.id), api_v1_post_path(@status.id),
params: {access_token: access_token_with_read} params: {access_token: access_token_with_read}
@ -113,7 +175,12 @@ describe Api::V1::PostsController do
it "doesn't delete the post" do it "doesn't delete the post" do
json_body = JSON.parse(response.body) json_body = JSON.parse(response.body)
expect(json_body["error"]).to eq("insufficient_scope") expect(json_body["error"]).to eq("insufficient_scope")
expect(response.status).to eq(403)
end end
end end
end end
def response_body(response)
JSON.parse(response.body)
end
end end

View file

@ -108,6 +108,14 @@ RSpec.configure do |config|
config.before(:each) do config.before(:each) do
I18n.locale = :en I18n.locale = :en
stub_request(:post, "https://pubsubhubbub.appspot.com/") stub_request(:post, "https://pubsubhubbub.appspot.com/")
stub_request(
:get,
"https://example.com/.well-known/webfinger?resource=acct:bob@example.com"
)
stub_request(
:get,
"https://example.com/.well-known/host-meta"
)
$process_queue = false $process_queue = false
end end