refactoring PostService

* move presenters back to controllers, this is view-logic
* use PostService in CommentService
* remove iframe route, this is not used anymore
* id/guid limit at 16 chars, hex(8) is 16 chars long
This commit is contained in:
Benjamin Neff 2016-03-06 15:26:05 +01:00
parent d872c64369
commit d94eae0d45
13 changed files with 208 additions and 299 deletions

View file

@ -3,8 +3,6 @@
# the COPYRIGHT file. # the COPYRIGHT file.
class PostsController < ApplicationController class PostsController < ApplicationController
include PostsHelper
before_action :authenticate_user!, only: :destroy before_action :authenticate_user!, only: :destroy
before_action :set_format_if_malformed_from_status_net, only: :show before_action :set_format_if_malformed_from_status_net, only: :show
@ -26,38 +24,36 @@ class PostsController < ApplicationController
end end
def show def show
post_service = PostService.new(id: params[:id], user: current_user) post = post_service.find(params[:id])
post_service.mark_user_notifications post_service.mark_user_notifications(post.id)
@post = post_service.post
respond_to do |format| respond_to do |format|
format.html { gon.post = post_service.present_json } format.html {
format.xml { render xml: @post.to_diaspora_xml } gon.post = PostPresenter.new(post, current_user)
format.json { render json: post_service.present_json } render locals: {post: post}
}
format.mobile { render locals: {post: post} }
format.xml { render xml: post.to_diaspora_xml }
format.json { render json: PostPresenter.new(post, current_user) }
end end
end end
def iframe
render text: post_iframe_url(params[:id]), layout: false
end
def oembed def oembed
post_id = OEmbedPresenter.id_from_url(params.delete(:url)) post_id = OEmbedPresenter.id_from_url(params.delete(:url))
post_service = PostService.new(id: post_id, user: current_user, post = post_service.find(post_id)
oembed: params.slice(:format, :maxheight, :minheight)) oembed = params.slice(:format, :maxheight, :minheight)
render json: post_service.present_oembed render json: OEmbedPresenter.new(post, oembed)
rescue
render nothing: true, status: 404
end end
def interactions def interactions
post_service = PostService.new(id: params[:id], user: current_user) post = post_service.find(params[:id])
respond_with post_service.present_interactions_json respond_with PostInteractionPresenter.new(post, 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
@post = post_service.post
respond_to do |format| respond_to do |format|
format.js { render "destroy", layout: false, format: :js }
format.json { render nothing: true, status: 204 } format.json { render nothing: true, status: 204 }
format.any { redirect_to stream_path } format.any { redirect_to stream_path }
end end
@ -65,6 +61,10 @@ class PostsController < ApplicationController
private private
def post_service
@post_service ||= PostService.new(current_user)
end
def set_format_if_malformed_from_status_net def set_format_if_malformed_from_status_net
request.format = :html if request.format == "application/html+xml" request.format = :html if request.format == "application/html+xml"
end end

View file

@ -155,21 +155,4 @@ class Post < ActiveRecord::Base
def nsfw def nsfw
self.author.profile.nsfw? self.author.profile.nsfw?
end end
def self.find_public(id)
where(post_key(id) => id).includes(:author, comments: :author).first.tap do |post|
raise ActiveRecord::RecordNotFound.new("could not find a post with id #{id}") unless post
raise Diaspora::NonPublic unless post.public?
end
end
def self.find_non_public_by_guid_or_id_with_user(id, user)
user.find_visible_shareable_by_id(Post, id, key: post_key(id)).tap do |post|
raise ActiveRecord::RecordNotFound.new("could not find a post with id #{id}") unless post
end
end
def self.post_key(id)
id.to_s.length <= 8 ? :id : :guid
end
end end

View file

@ -4,7 +4,7 @@ class CommentService
end end
def create(post_id, text) def create(post_id, text)
post = find_post!(post_id) post = post_service.find(post_id)
user.comment!(post, text) user.comment!(post, text)
end end
@ -19,24 +19,14 @@ class CommentService
end end
def find_for_post(post_id) def find_for_post(post_id)
find_post!(post_id).comments.for_a_stream post_service.find(post_id).comments.for_a_stream
end end
private private
attr_reader :user attr_reader :user
def find_post!(post_id) def post_service
find_post(post_id).tap do |post| @post_service ||= PostService.new(user)
raise ActiveRecord::RecordNotFound unless post
end
end
def find_post(post_id)
if user
user.find_visible_shareable_by_id(Post, post_id)
else
Post.find_by_id_and_public(post_id, true)
end
end end
end end

View file

@ -1,64 +1,59 @@
class PostService class PostService
attr_reader :post def initialize(user=nil)
@user = user
def initialize(params)
@id = params[:id]
@user = params[:user]
@oembed = params[:oembed] || {}
assign_post
end end
def assign_post def find(id_or_guid)
if user if user
@post = Post.find_non_public_by_guid_or_id_with_user(id, user) find_non_public_by_guid_or_id_with_user(id_or_guid)
else else
@post = Post.find_public(id) find_public(id_or_guid)
end end
end end
def present_json def mark_user_notifications(post_id)
PostPresenter.new(post, user) return unless user
mark_comment_reshare_like_notifications_read(post_id)
mark_mention_notifications_read(post_id)
end end
def present_interactions_json def destroy(post_id)
PostInteractionPresenter.new(post, user) post = find(post_id)
end raise Diaspora::NotMine unless post.author == user.person
user.retract(post)
def present_oembed
OEmbedPresenter.new(post, oembed)
end
def mark_user_notifications
mark_corresponding_notifications_read if user
end
def retract_post
raise Diaspora::NotMine unless user_owns_post?
user.retract(@post)
end end
private private
attr_reader :user, :id, :oembed attr_reader :user
def user_owns_post? def find_public(id_or_guid)
post.author == user.person Post.where(post_key(id_or_guid) => id_or_guid).first.tap do |post|
raise ActiveRecord::RecordNotFound, "could not find a post with id #{id_or_guid}" unless post
raise Diaspora::NonPublic unless post.public?
end
end end
def mark_corresponding_notifications_read def find_non_public_by_guid_or_id_with_user(id_or_guid)
mark_comment_reshare_like_notifications_read user.find_visible_shareable_by_id(Post, id_or_guid, key: post_key(id_or_guid)).tap do |post|
mark_mention_notifications_read raise ActiveRecord::RecordNotFound, "could not find a post with id #{id_or_guid} for user #{user.id}" unless post
end
end end
def mark_comment_reshare_like_notifications_read # We can assume a guid is at least 16 characters long as we have guids set to hex(8) since we started using them.
notification = Notification.where(recipient_id: user.id, target_type: "Post", target_id: post.id, unread: true) def post_key(id_or_guid)
notification.each do |notification| id_or_guid.to_s.length < 16 ? :id : :guid
end
def mark_comment_reshare_like_notifications_read(post_id)
notifications = Notification.where(recipient_id: user.id, target_type: "Post", target_id: post_id, unread: true)
notifications.each do |notification|
notification.set_read_state(true) notification.set_read_state(true)
end end
end end
def mark_mention_notifications_read def mark_mention_notifications_read(post_id)
mention = post.mentions.where(person_id: user.person_id).first mention = find(post_id).mentions.where(person_id: user.person_id).first
Notification.where(recipient_id: user.id, target_type: "Mention", target_id: mention.id, unread: true) Notification.where(recipient_id: user.id, target_type: "Mention", target_id: mention.id, unread: true)
.first.try(:set_read_state, true) if mention .first.try(:set_read_state, true) if mention
end end

View file

@ -1,2 +0,0 @@
var target = $("#<%= @post.guid %>")
target.hide('blind', { direction: 'vertical' }, 300, function(){ target.remove() });

View file

@ -3,7 +3,7 @@
-# the COPYRIGHT file. -# the COPYRIGHT file.
- content_for :page_title do - content_for :page_title do
= post_page_title @post = post_page_title post
- content_for :content do - content_for :content do
#container.container-fluid #container.container-fluid

View file

@ -3,6 +3,6 @@
-# the COPYRIGHT file. -# the COPYRIGHT file.
.stream .stream
= render :partial => 'shared/stream_element', = render partial: "shared/stream_element",
:locals => {:post => @post, :commenting_disabled => commenting_disabled?(@post), :expanded_info => true} locals: {post: post, commenting_disabled: commenting_disabled?(post), expanded_info: true}

View file

@ -26,7 +26,7 @@
!= reactions_link(post, "active") != reactions_link(post, "active")
.comment-container .comment-container
%ul.comments %ul.comments
= render partial: "comments/comment", collection: @post.comments.for_a_stream, locals: {post: @post} = render partial: "comments/comment", collection: post.comments.for_a_stream, locals: {post: post}
- else - else
!= reactions_link(post) != reactions_link(post)

View file

@ -40,10 +40,7 @@ Diaspora::Application.routes.draw do
resources :comments, only: %i(new create destroy index) resources :comments, only: %i(new create destroy index)
end end
get 'p/:id' => 'posts#show', :as => 'short_post' get 'p/:id' => 'posts#show', :as => 'short_post'
get 'posts/:id/iframe' => 'posts#iframe', :as => 'iframe'
# roll up likes into a nested resource above # roll up likes into a nested resource above
resources :comments, :only => [:create, :destroy] do resources :comments, :only => [:create, :destroy] do

View file

@ -5,104 +5,86 @@
require "spec_helper" require "spec_helper"
describe PostsController, type: :controller do describe PostsController, type: :controller do
let!(:post_service_double) { double("post_service") } let(:post) { alice.post(:status_message, text: "ohai", to: alice.aspects.first) }
before do
aspect = alice.aspects.first
@message = alice.build_post :status_message, text: "ohai", to: aspect.id
@message.save!
alice.add_to_streams(@message, [aspect])
alice.dispatch_post @message, to: aspect.id
allow(PostService).to receive(:new).and_return(post_service_double)
end
describe "#show" do describe "#show" do
before do
expect(post_service_double).to receive(:mark_user_notifications)
allow(post_service_double).to receive(:present_json)
end
context "user signed in" do context "user signed in" do
context "given a post that the user is allowed to see" do context "given a post that the user is allowed to see" do
before do before do
sign_in :user, alice sign_in :user, alice
expect(post_service_double).to receive(:post).and_return(@message)
end end
it "succeeds" do it "succeeds" do
get :show, id: @message.id expect_any_instance_of(PostService).to receive(:mark_user_notifications).with(post.id)
get :show, id: post.id
expect(response).to be_success expect(response).to be_success
end end
it 'succeeds after removing a mention when closing the mentioned user\'s account' do it "succeeds after removing a mention when closing the mentioned user's account" do
user = FactoryGirl.create(:user, username: "user") user = FactoryGirl.create(:user, username: "user")
alice.share_with(user.person, alice.aspects.first) alice.share_with(user.person, alice.aspects.first)
msg = alice.build_post :status_message,
text: "Mention @{User ; #{user.diaspora_handle}}", public: true, to: "all" msg = alice.post(:status_message, text: "Mention @{User ; #{user.diaspora_handle}}", public: true)
msg.save!
expect(msg.mentioned_people.count).to eq(1) expect(msg.mentioned_people.count).to eq(1)
user.destroy user.destroy
get :show, id: msg.id get :show, id: msg.id
expect(response).to be_success expect(response).to be_success
end end
it "renders the application layout on mobile" do it "renders the application layout on mobile" do
get :show, id: @message.id, format: :mobile get :show, id: post.id, format: :mobile
expect(response).to render_template("layouts/application") expect(response).to render_template("layouts/application")
end end
it "succeeds on mobile with a reshare" do it "succeeds on mobile with a reshare" do
get :show, id: FactoryGirl.create(:reshare, author: alice.person).id, format: :mobile reshare_id = FactoryGirl.create(:reshare, author: alice.person).id
expect_any_instance_of(PostService).to receive(:mark_user_notifications).with(reshare_id)
get :show, id: reshare_id, format: :mobile
expect(response).to be_success expect(response).to be_success
end end
end end
context "given a post that the user is not allowed to see" do context "given a post that the user is not allowed to see" do
before do before do
sign_in :user, alice sign_in :user, eve
expect(post_service_double).to receive(:post).and_raise(Diaspora::NonPublic)
end end
it "returns a 404" do it "returns a 404" do
get :show, id: @message.id expect {
expect(response.code).to eq("404") get :show, id: post.id
}.to raise_error ActiveRecord::RecordNotFound
end end
end end
end end
context "user not signed in" do context "user not signed in" do
context "given a public post" do context "given a public post" do
before :each do let(:public) { alice.post(:status_message, text: "hello", public: true) }
@status = alice.post(:status_message, text: "hello", public: true, to: "all")
expect(post_service_double).to receive(:post).and_return(@status)
end
it "shows a public post" do it "shows a public post" do
get :show, id: @status.id get :show, id: public.id
expect(response.body).to match "hello" expect(response.body).to match "hello"
end end
it "succeeds for statusnet" do it "succeeds for statusnet" do
@request.env["HTTP_ACCEPT"] = "application/html+xml,text/html" @request.env["HTTP_ACCEPT"] = "application/html+xml,text/html"
get :show, id: @status.id get :show, id: public.id
expect(response.body).to match "hello" expect(response.body).to match "hello"
end end
it "responds with diaspora xml if format is xml" do it "responds with diaspora xml if format is xml" do
get :show, id: @status.guid, format: :xml get :show, id: public.guid, format: :xml
expect(response.body).to eq(@status.to_diaspora_xml) expect(response.body).to eq(public.to_diaspora_xml)
end end
end end
context "given a limited post" do context "given a limited post" do
before do
expect(post_service_double).to receive(:post).and_raise(Diaspora::NonPublic)
end
it "forces the user to sign" do it "forces the user to sign" do
get :show, id: @message.id get :show, id: post.id
expect(response).to be_redirect expect(response).to be_redirect
expect(response).to redirect_to new_user_session_path expect(response).to redirect_to new_user_session_path
end end
@ -110,40 +92,55 @@ describe PostsController, type: :controller do
end end
end end
describe "iframe" do describe "oembed" do
it "contains an iframe" do it "works when you can see it" do
get :iframe, id: @message.id sign_in alice
get :oembed, url: "/posts/#{post.id}"
expect(response.body).to match /iframe/ expect(response.body).to match /iframe/
end end
end
describe "oembed" do it "returns a 404 response when the post is not found" do
it "receives a present oembed" do get :oembed, url: "/posts/#{post.id}"
expect(post_service_double).to receive(:present_oembed) expect(response.status).to eq(404)
get :oembed, url: "/posts/#{@message.id}"
end end
end end
describe "#destroy" do describe "#destroy" do
before do context "own post" do
sign_in alice before do
sign_in alice
end
it "works when it is your post" do
expect_any_instance_of(PostService).to receive(:destroy).with(post.id.to_s)
delete :destroy, format: :json, id: post.id
expect(response.status).to eq(204)
end
it "redirects to stream on mobile" do
delete :destroy, format: :mobile, id: post.id
expect(response).to be_redirect
expect(response).to redirect_to stream_path
end
end end
it "will receive a retract post" do context "post of another user" do
expect(post_service_double).to receive(:retract_post)
expect(post_service_double).to receive(:post).and_return(@message)
message = alice.post(:status_message, text: "hey", to: alice.aspects.first.id)
delete :destroy, format: :js, id: message.id
end
context "when Diaspora::NotMine is raised by retract post" do
it "will respond with a 403" do it "will respond with a 403" do
expect(post_service_double).to receive(:retract_post).and_raise(Diaspora::NotMine) sign_in :user, bob
message = alice.post(:status_message, text: "hey", to: alice.aspects.first.id)
delete :destroy, format: :js, id: message.id delete :destroy, format: :json, id: post.id
expect(response.body).to eq("You are not allowed to do that") expect(response.body).to eq("You are not allowed to do that")
expect(response.status).to eq(403) expect(response.status).to eq(403)
end end
it "will respond with a 404 if the post is not visible" do
sign_in :user, eve
expect {
delete :destroy, format: :json, id: post.id
}.to raise_error ActiveRecord::RecordNotFound
end
end end
end end
end end

View file

@ -415,56 +415,4 @@ describe Post, :type => :model do
expect(post.interacted_at).not_to be_blank expect(post.interacted_at).not_to be_blank
end end
end end
describe "#find_public" do
it "succeeds with an id" do
post = FactoryGirl.create :status_message, public: true
expect(Post.find_public post.id).to eq(post)
end
it "succeeds with an guid" do
post = FactoryGirl.create :status_message, public: true
expect(Post.find_public post.guid).to eq(post)
end
it "raises ActiveRecord::RecordNotFound for a non-existing id without a user" do
allow(Post).to receive_messages where: double(includes: double(first: nil))
expect {
Post.find_public 123
}.to raise_error ActiveRecord::RecordNotFound
end
it "raises Diaspora::NonPublic for a private post without a user" do
post = FactoryGirl.create :status_message
expect {
Post.find_public post.id
}.to raise_error Diaspora::NonPublic
end
end
describe "#find_non_public_by_guid_or_id_with_user" do
it "succeeds with an id" do
post = FactoryGirl.create :status_message_in_aspect
expect(Post.find_non_public_by_guid_or_id_with_user(post.id, post.author.owner)).to eq(post)
end
it "succeeds with an guid" do
post = FactoryGirl.create :status_message_in_aspect
expect(Post.find_non_public_by_guid_or_id_with_user(post.guid, post.author.owner)).to eq(post)
end
it "looks up on the passed user object if it's non-nil" do
post = FactoryGirl.create :status_message
user = double
expect(user).to receive(:find_visible_shareable_by_id).with(Post, post.id, key: :id).and_return(post)
Post.find_non_public_by_guid_or_id_with_user(post.id, user)
end
it "raises ActiveRecord::RecordNotFound with a non-existing id and a user" do
user = double(find_visible_shareable_by_id: nil)
expect {
Post.find_non_public_by_guid_or_id_with_user(123, user)
}.to raise_error ActiveRecord::RecordNotFound
end
end
end end

View file

@ -88,7 +88,7 @@ describe CommentService do
it "does not return comments for private post" do it "does not return comments for private post" do
expect { expect {
CommentService.new.find_for_post(post.id) CommentService.new.find_for_post(post.id)
}.to raise_error ActiveRecord::RecordNotFound }.to raise_error Diaspora::NonPublic
end end
end end

View file

@ -1,127 +1,128 @@
require "spec_helper" require "spec_helper"
describe PostService do describe PostService do
before do let(:post) { alice.post(:status_message, text: "ohai", to: alice.aspects.first) }
aspect = alice.aspects.first let(:public) { alice.post(:status_message, text: "hey", public: true) }
@message = alice.build_post :status_message, text: "ohai", to: aspect.id
@message.save!
alice.add_to_streams(@message, [aspect]) describe "#find" do
alice.dispatch_post @message, to: aspect.id context "with user" do
end it "returns the post, if it is the users post" do
expect(PostService.new(alice).find(post.id)).to eq(post)
end
it "works with guid" do
expect(PostService.new(alice).find(post.guid)).to eq(post)
end
it "returns the post, if the user can see the it" do
expect(PostService.new(bob).find(post.id)).to eq(post)
end
it "returns the post, if it is public" do
expect(PostService.new(eve).find(public.id)).to eq(public)
end
describe "#assign_post" do
context "when the post is private" do
it "RecordNotFound if the post cannot be found" do it "RecordNotFound if the post cannot be found" do
expect { PostService.new(id: 1_234_567, user: alice) }.to raise_error(ActiveRecord::RecordNotFound) expect {
PostService.new(alice).find("unknown")
}.to raise_error ActiveRecord::RecordNotFound, "could not find a post with id unknown for user #{alice.id}"
end end
it "NonPublic if there is no user" do
expect { PostService.new(id: @message.id) }.to raise_error(Diaspora::NonPublic) it "RecordNotFound if user cannot see the post" do
end expect {
it "RecordNotFound if user cannot see post" do PostService.new(eve).find(post.id)
expect { PostService.new(id: @message.id, user: eve) }.to raise_error(ActiveRecord::RecordNotFound) }.to raise_error ActiveRecord::RecordNotFound, "could not find a post with id #{post.id} for user #{eve.id}"
end end
end end
context "when the post is public" do context "without user" do
it "returns the post, if it is public" do
expect(PostService.new.find(public.id)).to eq(public)
end
it "works with guid" do
expect(PostService.new.find(public.guid)).to eq(public)
end
it "NonPublic if the post is private" do
expect {
PostService.new.find(post.id)
}.to raise_error Diaspora::NonPublic
end
it "RecordNotFound if the post cannot be found" do it "RecordNotFound if the post cannot be found" do
expect { PostService.new(id: 1_234_567) }.to raise_error(ActiveRecord::RecordNotFound) expect {
PostService.new.find("unknown")
}.to raise_error ActiveRecord::RecordNotFound, "could not find a post with id unknown"
end end
end end
# We want to be using guids from now on for this post route, but do not want to break
# pre-exisiting permalinks. We can assume a guid is 8 characters long as we have
# guids set to hex(8) since we started using them.
context "id/guid switch" do context "id/guid switch" do
before do let(:public) { alice.post(:status_message, text: "ohai", public: true) }
@status = alice.post(:status_message, text: "hello", public: true, to: "all")
it "assumes ids less than 16 chars are ids and not guids" do
post = Post.where(id: public.id)
expect(Post).to receive(:where).with(hash_including(id: "123456789012345")).and_return(post).at_least(:once)
PostService.new(alice).find("123456789012345")
end end
it "assumes guids less than 8 chars are ids and not guids" do it "assumes ids more than (or equal to) 16 chars are actually guids" do
post = Post.where(id: @status.id.to_s) post = Post.where(guid: public.guid)
expect(Post).to receive(:where).with(hash_including(id: @status.id)).and_return(post).at_least(:once) expect(Post).to receive(:where).with(hash_including(guid: "1234567890123456")).and_return(post).at_least(:once)
PostService.new(id: @status.id, user: alice) PostService.new(alice).find("1234567890123456")
end
it "assumes guids more than (or equal to) 8 chars are actually guids" do
post = Post.where(guid: @status.guid)
expect(Post).to receive(:where).with(hash_including(guid: @status.guid)).and_return(post).at_least(:once)
PostService.new(id: @status.guid, user: alice)
end end
end end
end end
describe "#mark_user_notifications" do describe "#mark_user_notifications" do
it "marks a corresponding notifications as read" do it "marks a corresponding notifications as read" do
FactoryGirl.create(:notification, recipient: alice, target: @message, unread: true) FactoryGirl.create(:notification, recipient: alice, target: post, unread: true)
FactoryGirl.create(:notification, recipient: alice, target: @message, unread: true) FactoryGirl.create(:notification, recipient: alice, target: post, unread: true)
post_service = PostService.new(id: @message.id, user: alice)
expect { post_service.mark_user_notifications }.to change(Notification.where(unread: true), :count).by(-2) expect {
PostService.new(alice).mark_user_notifications(post.id)
}.to change(Notification.where(unread: true), :count).by(-2)
end end
it "marks a corresponding mention notification as read" do it "marks a corresponding mention notification as read" do
status_text = "this is a text mentioning @{Mention User ; #{alice.diaspora_handle}} ... have fun testing!" status_text = "this is a text mentioning @{Mention User ; #{alice.diaspora_handle}} ... have fun testing!"
status_msg = mention_post = bob.post(:status_message, text: status_text, public: true)
bob.post(:status_message, text: status_text, public: true, to: "all")
mention = status_msg.mentions.where(person_id: alice.person.id).first expect {
FactoryGirl.create(:notification, recipient: alice, target_type: "Mention", target_id: mention.id, unread: true) PostService.new(alice).mark_user_notifications(mention_post.id)
post_service = PostService.new(id: status_msg.id, user: alice) }.to change(Notification.where(unread: true), :count).by(-1)
expect { post_service.mark_user_notifications }.to change(Notification.where(unread: true), :count).by(-1) end
it "does nothing without a user" do
expect_any_instance_of(PostService).not_to receive(:mark_comment_reshare_like_notifications_read).with(post.id)
expect_any_instance_of(PostService).not_to receive(:mark_mention_notifications_read).with(post.id)
PostService.new.mark_user_notifications(post.id)
end end
end end
describe "#present_json" do describe "#destroy" do
it "works for a private post" do
post_service = PostService.new(id: @message.id, user: alice)
expect(post_service.present_json.to_json).to match(/\"text\"\:\"ohai\"/)
end
it "works for a public post " do
status = alice.post(:status_message, text: "hello", public: true, to: "all")
post_service = PostService.new(id: status.id)
expect(post_service.present_json.to_json).to match(/\"text\"\:\"hello\"/)
end
end
describe "#present_oembed" do
it "works for a private post" do
post_service = PostService.new(id: @message.id, user: alice)
expect(post_service.present_oembed.to_json).to match(/iframe/)
end
it "works for a public post" do
status = alice.post(:status_message, text: "hello", public: true, to: "all")
post_service = PostService.new(id: status.id)
expect(post_service.present_oembed.to_json).to match(/iframe/)
end
end
describe "#retract_post" do
it "let a user delete his message" do it "let a user delete his message" do
message = alice.post(:status_message, text: "hey", to: alice.aspects.first.id) PostService.new(alice).destroy(post.id)
post_service = PostService.new(id: message.id, user: alice) expect(StatusMessage.find_by_id(post.id)).to be_nil
post_service.retract_post
expect(StatusMessage.find_by_id(message.id)).to be_nil
end end
it "sends a retraction on delete" do it "sends a retraction on delete" do
message = alice.post(:status_message, text: "hey", to: alice.aspects.first.id) expect(alice).to receive(:retract).with(post)
post_service = PostService.new(id: message.id, user: alice) PostService.new(alice).destroy(post.id)
expect(alice).to receive(:retract).with(message)
post_service.retract_post
end end
it "will not let you destroy posts visible to you but that you do not own" do it "will not let you destroy posts visible to you but that you do not own" do
message = bob.post(:status_message, text: "hey", to: bob.aspects.first.id) expect {
post_service = PostService.new(id: message.id, user: alice) PostService.new(bob).destroy(post.id)
expect { post_service.retract_post }.to raise_error(Diaspora::NotMine) }.to raise_error Diaspora::NotMine
expect(StatusMessage.exists?(message.id)).to be true expect(StatusMessage.find_by_id(post.id)).not_to be_nil
end end
it "will not let you destroy posts that are not visible to you" do it "will not let you destroy posts that are not visible to you" do
message = eve.post(:status_message, text: "hey", to: eve.aspects.first.id) expect {
expect { PostService.new(id: message.id, user: alice) }.to raise_error(ActiveRecord::RecordNotFound) PostService.new(eve).destroy(post.id)
expect(StatusMessage.exists?(message.id)).to be true }.to raise_error(ActiveRecord::RecordNotFound)
expect(StatusMessage.find_by_id(post.id)).not_to be_nil
end end
end end
end end