diff --git a/app/models/profile.rb b/app/models/profile.rb index 02c7ce617b6e99d5065fc8dd1dfb36961c13d3b4..8735d55f4245a6092c0ff8df3ce8c526bf64e47b 100644 --- a/app/models/profile.rb +++ b/app/models/profile.rb @@ -129,12 +129,7 @@ class Profile < ActiveRecord::Base end def tag_string - if @tag_string - @tag_string - else - tags = self.tags.pluck(:name) - tags.inject(""){|string, tag| string << "##{tag} " } - end + @tag_string ||= tags.pluck(:name).map {|tag| "##{tag}" }.join(" ") end # Constructs a full name by joining #first_name and #last_name diff --git a/lib/diaspora/federation/receive.rb b/lib/diaspora/federation/receive.rb index 97aa916de618e8e01cbe67fb807b58772bfc8040..692026a5cdfd14b0e06ddf8e7a3608e622963334 100644 --- a/lib/diaspora/federation/receive.rb +++ b/lib/diaspora/federation/receive.rb @@ -4,10 +4,7 @@ module Diaspora extend Diaspora::Logging def self.account_deletion(entity) - AccountDeletion.new( - person: author_of(entity), - diaspora_handle: entity.author - ).tap(&:save!) + AccountDeletion.create!(person: author_of(entity), diaspora_handle: entity.author) end def self.comment(entity) @@ -38,16 +35,14 @@ module Diaspora def self.conversation(entity) author = author_of(entity) ignore_existing_guid(Conversation, entity.guid, author) do - Conversation.new( + Conversation.create!( author: author, guid: entity.guid, subject: entity.subject, created_at: entity.created_at, - participant_handles: entity.participants - ).tap do |conversation| - conversation.messages = entity.messages.map {|message| build_message(message) } - conversation.save! - end + participant_handles: entity.participants, + messages: entity.messages.map {|message| build_message(message) } + ) end end @@ -70,15 +65,12 @@ module Diaspora end def self.participation(entity) - parent = entity.parent_type.constantize.find_by(guid: entity.parent_guid) - - return unless parent.author.local? + author = author_of(entity) + ignore_existing_guid(Participation, entity.guid, author) do + parent = entity.parent_type.constantize.find_by(guid: entity.parent_guid) - Participation.new( - author: author_of(entity), - guid: entity.guid, - target: entity.parent_type.constantize.find_by(guid: entity.parent_guid) - ).tap(&:save!) + Participation.create!(author: author, guid: entity.guid, target: parent) if parent.author.local? + end end def self.photo(entity) @@ -107,14 +99,11 @@ module Diaspora author = author_of(entity) ignore_existing_guid(PollParticipation, entity.guid, author) do PollParticipation.new( - author: author, - guid: entity.guid, - poll: Poll.find_by(guid: entity.parent_guid) - ).tap do |poll_participation| - poll_participation.poll_answer_guid = entity.poll_answer_guid - - save_relayable(poll_participation, entity) - end + author: author, + guid: entity.guid, + poll: Poll.find_by(guid: entity.parent_guid), + poll_answer_guid: entity.poll_answer_guid + ).tap {|poll_participation| save_relayable(poll_participation, entity) } end end @@ -138,14 +127,17 @@ module Diaspora end def self.reshare(entity) - Reshare.new( - author: author_of(entity), - guid: entity.guid, - created_at: entity.created_at, - provider_display_name: entity.provider_display_name, - public: entity.public, - root_guid: entity.root_guid - ).tap(&:save!) + author = author_of(entity) + ignore_existing_guid(Reshare, entity.guid, author) do + Reshare.create!( + author: author, + guid: entity.guid, + created_at: entity.created_at, + provider_display_name: entity.provider_display_name, + public: entity.public, + root_guid: entity.root_guid + ) + end end def self.retraction(entity, recipient_id) @@ -208,7 +200,7 @@ module Diaspora private_class_method :build_poll def self.save_photo(entity) - Photo.new( + Photo.create!( author: author_of(entity), guid: entity.guid, text: entity.text, @@ -219,7 +211,7 @@ module Diaspora status_message_guid: entity.status_message_guid, height: entity.height, width: entity.width - ).tap(&:save!) + ) end private_class_method :save_photo diff --git a/spec/integration/receiving_spec.rb b/spec/integration/receiving_spec.rb index 9e3079eed303a09336f9d933810182d263df70c5..451a29e77163ae6124394d6a1641e8d7df3dcbd2 100644 --- a/spec/integration/receiving_spec.rb +++ b/spec/integration/receiving_spec.rb @@ -5,12 +5,6 @@ require 'spec_helper' describe 'a user receives a post', :type => :request do - - def receive_with_zord(user, person, xml) - zord = Postzord::Receiver::Private.new(user, :person => person) - zord.parse_and_receive(xml) - end - before do @alices_aspect = alice.aspects.where(:name => "generic").first @bobs_aspect = bob.aspects.where(:name => "generic").first @@ -56,152 +50,4 @@ describe 'a user receives a post', :type => :request do expect(ShareVisibility.find_by(user_id: alice.id, shareable_id: @status_message.id)).not_to be_nil end end - - describe 'comments' do - - context 'remote' do - before do - skip # TODO - inlined_jobs do |queue| - connect_users(alice, @alices_aspect, eve, @eves_aspect) - @post = alice.post(:status_message, :text => "hello", :to => @alices_aspect.id) - - xml = Diaspora::Federation.xml(Diaspora::Federation::Entities.status_message(@post)).to_xml - - receive_with_zord(bob, alice.person, xml) - receive_with_zord(eve, alice.person, xml) - - comment = eve.comment!(@post, 'tada') - queue.drain_all - # After Eve creates her comment, it gets sent to Alice, who signs it with her private key - # before relaying it out to the contacts on the top-level post - comment.parent_author_signature = comment.sign_with_key(alice.encryption_key) - @xml = Diaspora::Federation.xml(Diaspora::Federation::Entities.comment(comment)).to_xml - comment.delete - - comment_with_whitespace = alice.comment!(@post, ' I cannot lift my thumb from the spacebar ') - queue.drain_all - comment_entity = Diaspora::Federation::Entities.comment(comment_with_whitespace) - @xml_with_whitespace = Diaspora::Federation.xml(comment_entity).to_xml - @guid_with_whitespace = comment_with_whitespace.guid - comment_with_whitespace.delete - end - end - - it 'should receive a relayed comment with leading whitespace' do - expect(eve.reload.visible_shareables(Post).size).to eq(1) - post_in_db = StatusMessage.find(@post.id) - expect(post_in_db.comments).to eq([]) - receive_with_zord(eve, alice.person, @xml_with_whitespace) - - expect(post_in_db.comments(true).first.guid).to eq(@guid_with_whitespace) - end - - it 'should correctly marshal a stranger for the downstream user' do - remote_person = eve.person.dup - eve.person.delete - eve.delete - Person.where(:id => remote_person.id).delete_all - Profile.where(:person_id => remote_person.id).delete_all - remote_person.attributes.delete(:id) # leaving a nil id causes it to try to save with id set to NULL in postgres - - remote_person.save(:validate => false) - remote_person.profile = FactoryGirl.create(:profile, :person => remote_person) - expect(Person).to receive(:find_or_fetch_by_identifier).twice.with(eve.person.diaspora_handle) - .and_return(remote_person) - - expect(bob.reload.visible_shareables(Post).size).to eq(1) - post_in_db = StatusMessage.find(@post.id) - expect(post_in_db.comments).to eq([]) - - receive_with_zord(bob, alice.person, @xml) - - expect(post_in_db.comments(true).first.author).to eq(remote_person) - end - end - - context 'local' do - before do - skip # TODO - @post = alice.post :status_message, :text => "hello", :to => @alices_aspect.id - - xml = Diaspora::Federation.xml(Diaspora::Federation::Entities.status_message(@post)).to_xml - - alice.share_with(eve.person, alice.aspects.first) - - receive_with_zord(bob, alice.person, xml) - receive_with_zord(eve, alice.person, xml) - end - - it 'does not raise a `Mysql2::Error: Duplicate entry...` exception on save' do - inlined_jobs do - @comment = bob.comment!(@post, 'tada') - @xml = Diaspora::Federation.xml(Diaspora::Federation::Entities.comment(@comment)).to_xml - - expect { - receive_with_zord(alice, bob.person, @xml) - }.to_not raise_exception - end - end - end - end - - - describe 'receiving mulitple versions of the same post from a remote pod' do - before do - @local_luke, @local_leia, @remote_raphael = set_up_friends - - @post = FactoryGirl.build( - :status_message, - text: "hey", - guid: UUID.generate(:compact), - author: @remote_raphael, - created_at: 5.days.ago, - updated_at: 5.days.ago - ) - end - - it "allows two people saving the same post" do - skip # TODO - xml = Diaspora::Federation.xml(Diaspora::Federation::Entities.status_message(@post)).to_xml - receive_with_zord(@local_luke, @remote_raphael, xml) - receive_with_zord(@local_leia, @remote_raphael, xml) - expect(Post.find_by_guid(@post.guid).updated_at).to be < Time.now.utc + 1 - expect(Post.find_by_guid(@post.guid).created_at.day).to eq(@post.created_at.day) - end - - it 'does not update the post if a new one is sent with a new created_at' do - skip # TODO - old_time = @post.created_at - xml = Diaspora::Federation.xml(Diaspora::Federation::Entities.status_message(@post)).to_xml - receive_with_zord(@local_luke, @remote_raphael, xml) - - @post = FactoryGirl.build( - :status_message, - text: "hey", - guid: @post.guid, - author: @remote_raphael, - created_at: 2.days.ago - ) - xml = Diaspora::Federation.xml(Diaspora::Federation::Entities.status_message(@post)).to_xml - receive_with_zord(@local_luke, @remote_raphael, xml) - - expect(Post.find_by_guid(@post.guid).created_at.day).to eq(old_time.day) - end - end - - - describe 'salmon' do - let(:post){alice.post :status_message, :text => "hello", :to => @alices_aspect.id} - let(:salmon){alice.salmon( post )} - - it 'processes a salmon for a post' do - salmon_xml = salmon.xml_for(bob.person) - - zord = Postzord::Receiver::Private.new(bob, :salmon_xml => salmon_xml) - zord.perform! - - expect(bob.visible_shareables(Post).include?(post)).to be true - end - end end diff --git a/spec/lib/diaspora/federated/request_spec.rb b/spec/lib/diaspora/federated/request_spec.rb index ed588d0bf3360f04ae129125887a2d20f2e33456..c92666baab4e60c8f7afce0ad1c1a83ff95583fa 100644 --- a/spec/lib/diaspora/federated/request_spec.rb +++ b/spec/lib/diaspora/federated/request_spec.rb @@ -65,38 +65,6 @@ describe Request do end end - describe '#receive' do - it 'creates a contact' do - skip # TODO - request = described_class.diaspora_initialize(:from => alice.person, :to => eve.person, :into => @aspect) - expect{ - request.receive(eve, alice.person) - }.to change{ - eve.contacts(true).size - }.by(1) - end - - it 'sets mutual if a contact already exists' do - skip # TODO - alice.share_with(eve.person, alice.aspects.first) - - expect { - described_class.diaspora_initialize(:from => eve.person, :to => alice.person, - :into => eve.aspects.first).receive(alice, eve.person) - }.to change { - alice.contacts.find_by_person_id(eve.person.id).mutual? - }.from(false).to(true) - - end - - it 'sets sharing' do - skip # TODO - described_class.diaspora_initialize(:from => eve.person, :to => alice.person, - :into => eve.aspects.first).receive(alice, eve.person) - expect(alice.contact_for(eve.person)).to be_sharing - end - end - context 'xml' do before do @request = described_class.diaspora_initialize(:from => alice.person, :to => eve.person, :into => @aspect) diff --git a/spec/lib/diaspora/federation/receive_spec.rb b/spec/lib/diaspora/federation/receive_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..c4a8a7e9ce7683444398631d55eddd01427bf5ca --- /dev/null +++ b/spec/lib/diaspora/federation/receive_spec.rb @@ -0,0 +1,549 @@ +require "spec_helper" + +describe Diaspora::Federation::Receive do + let(:sender) { FactoryGirl.create(:person) } + let(:post) { alice.post(:status_message, text: "hello", public: true) } + + describe ".account_deletion" do + let(:account_deletion_entity) { FactoryGirl.build(:account_deletion_entity, author: sender.diaspora_handle) } + + it "saves the account deletion" do + Diaspora::Federation::Receive.account_deletion(account_deletion_entity) + + account_deletion = AccountDeletion.find_by!(diaspora_handle: sender.diaspora_handle) + + expect(account_deletion.person).to eq(sender) + end + end + + describe ".comment" do + let(:comment_entity) { FactoryGirl.build(:comment_entity, author: sender.diaspora_handle, parent_guid: post.guid) } + + it "saves the comment" do + received = Diaspora::Federation::Receive.comment(comment_entity) + + comment = Comment.find_by!(guid: comment_entity.guid) + + expect(received).to eq(comment) + expect(comment.author).to eq(sender) + expect(comment.text).to eq(comment_entity.text) + expect(comment.created_at.iso8601).to eq(comment_entity.created_at.iso8601) + end + + it "attaches the comment to the post" do + Diaspora::Federation::Receive.comment(comment_entity) + + comment = Comment.find_by!(guid: comment_entity.guid) + + expect(post.comments).to include(comment) + expect(comment.post).to eq(post) + end + + it_behaves_like "it ignores existing object received twice", Comment, :comment do + let(:entity) { comment_entity } + end + end + + describe ".contact" do + let(:contact_entity) { + FactoryGirl.build(:contact_entity, author: sender.diaspora_handle, recipient: alice.diaspora_handle) + } + + it "creates the contact if it doesn't exist" do + received = Diaspora::Federation::Receive.contact(contact_entity) + + contact = alice.contacts.find_by!(person_id: sender.id) + + expect(received).to eq(contact) + expect(contact.sharing).to be_truthy + end + + it "updates the contact if it exists" do + alice.contacts.find_or_initialize_by(person_id: sender.id, receiving: true, sharing: false).save! + + received = Diaspora::Federation::Receive.contact(contact_entity) + + contact = alice.contacts.find_by!(person_id: sender.id) + + expect(received).to eq(contact) + expect(contact.sharing).to be_truthy + end + + it "does nothing, if already sharing" do + alice.contacts.find_or_initialize_by(person_id: sender.id, receiving: true, sharing: true).save! + + expect_any_instance_of(Contact).not_to receive(:save!) + + expect(Diaspora::Federation::Receive.contact(contact_entity)).to be_nil + end + end + + describe ".conversation" do + let(:conv_guid) { FactoryGirl.generate(:guid) } + let(:message_entity) { + FactoryGirl.build( + :message_entity, + author: alice.diaspora_handle, + parent_guid: conv_guid, + conversation_guid: conv_guid + ) + } + let(:conversation_entity) { + FactoryGirl.build( + :conversation_entity, + guid: conv_guid, + author: alice.diaspora_handle, + messages: [message_entity], + participants: "#{alice.diaspora_handle};#{bob.diaspora_handle}" + ) + } + + it "saves the conversation" do + received = Diaspora::Federation::Receive.conversation(conversation_entity) + + conv = Conversation.find_by!(guid: conversation_entity.guid) + + expect(received).to eq(conv) + expect(conv.author).to eq(alice.person) + expect(conv.subject).to eq(conversation_entity.subject) + end + + it "saves the message" do + Diaspora::Federation::Receive.conversation(conversation_entity) + + conv = Conversation.find_by!(guid: conversation_entity.guid) + + expect(conv.messages.count).to eq(1) + expect(conv.messages.first.author).to eq(alice.person) + expect(conv.messages.first.text).to eq(message_entity.text) + expect(conv.messages.first.created_at.iso8601).to eq(message_entity.created_at.iso8601) + end + + it "creates appropriate visibilities" do + Diaspora::Federation::Receive.conversation(conversation_entity) + + conv = Conversation.find_by!(guid: conversation_entity.guid) + + expect(conv.participants.count).to eq(2) + expect(conv.participants).to include(alice.person, bob.person) + end + + it_behaves_like "it ignores existing object received twice", Conversation, :conversation do + let(:entity) { conversation_entity } + end + end + + describe ".like" do + let(:like_entity) { FactoryGirl.build(:like_entity, author: sender.diaspora_handle, parent_guid: post.guid) } + + it "saves the like" do + received = Diaspora::Federation::Receive.like(like_entity) + + like = Like.find_by!(guid: like_entity.guid) + + expect(received).to eq(like) + expect(like.author).to eq(sender) + expect(like.positive).to be_truthy + end + + it "attaches the like to the post" do + Diaspora::Federation::Receive.like(like_entity) + + like = Like.find_by!(guid: like_entity.guid) + + expect(post.likes).to include(like) + expect(like.target).to eq(post) + end + + it_behaves_like "it ignores existing object received twice", Like, :like do + let(:entity) { like_entity } + end + end + + describe ".message" do + let(:conversation) { + FactoryGirl.build(:conversation, author: alice.person).tap do |conv| + conv.participants << sender + conv.save! + end + } + let(:message_entity) { + FactoryGirl.build( + :message_entity, + author: sender.diaspora_handle, + parent_guid: conversation.guid, + conversation_guid: conversation.guid + ) + } + + it "saves the message" do + received = Diaspora::Federation::Receive.message(message_entity) + + msg = Message.find_by!(guid: message_entity.guid) + + expect(received).to eq(msg) + expect(msg.author).to eq(sender) + expect(msg.text).to eq(message_entity.text) + expect(msg.created_at.iso8601).to eq(message_entity.created_at.iso8601) + end + + it "attaches the message to the conversation" do + msg = Diaspora::Federation::Receive.message(message_entity) + + conv = Conversation.find_by!(guid: conversation.guid) + + expect(conv.messages).to include(msg) + expect(msg.conversation).to eq(conv) + end + + it_behaves_like "it ignores existing object received twice", Message, :message do + let(:entity) { message_entity } + end + end + + describe ".participation" do + let(:participation_entity) { + FactoryGirl.build(:participation_entity, author: sender.diaspora_handle, parent_guid: post.guid) + } + + it "saves the participation" do + received = Diaspora::Federation::Receive.participation(participation_entity) + + participation = Participation.find_by!(guid: participation_entity.guid) + + expect(received).to eq(participation) + expect(participation.author).to eq(sender) + end + + it "attaches the participation to the post" do + Diaspora::Federation::Receive.participation(participation_entity) + + participation = Participation.find_by!(guid: participation_entity.guid) + + expect(post.participations).to include(participation) + expect(participation.target).to eq(post) + end + + it "does not save the participation if the target is not local" do + remote_post = FactoryGirl.create(:status_message, author: sender, public: true) + remote_participation = FactoryGirl.build( + :participation_entity, + author: sender.diaspora_handle, + parent_guid: remote_post.guid + ) + + expect(Diaspora::Federation::Receive.participation(remote_participation)).to be_nil + + expect(Participation.exists?(guid: remote_participation.guid)).to be_falsey + end + + it_behaves_like "it ignores existing object received twice", Participation, :participation do + let(:entity) { participation_entity } + end + end + + describe ".photo" do + let(:photo_entity) { FactoryGirl.build(:photo_entity, author: sender.diaspora_handle) } + + it "saves the photo if it does not already exist" do + received = Diaspora::Federation::Receive.photo(photo_entity) + + photo = Photo.find_by!(guid: photo_entity.guid) + + expect(received).to eq(photo) + expect(photo.author).to eq(sender) + expect(photo.remote_photo_name).to eq(photo_entity.remote_photo_name) + expect(photo.created_at.iso8601).to eq(photo_entity.created_at.iso8601) + end + + it "updates the photo if it is already persisted" do + Diaspora::Federation::Receive.photo(photo_entity) + + photo = Photo.find_by!(guid: photo_entity.guid) + photo.remote_photo_name = "foobar.jpg" + photo.save + + received = Diaspora::Federation::Receive.photo(photo_entity) + photo.reload + + expect(received).to eq(photo) + expect(photo.author).to eq(sender) + expect(photo.remote_photo_name).to eq(photo_entity.remote_photo_name) + end + + it "does not update the photo if the author mismatches" do + Diaspora::Federation::Receive.photo(photo_entity) + + photo = Photo.find_by!(guid: photo_entity.guid) + photo.remote_photo_name = "foobar.jpg" + photo.author = bob.person + photo.save + + expect { + Diaspora::Federation::Receive.photo(photo_entity) + }.to raise_error Diaspora::Federation::InvalidAuthor + + photo.reload + + expect(photo.author).to eq(bob.person) + expect(photo.remote_photo_name).to eq("foobar.jpg") + end + end + + describe ".poll_participation" do + let(:post_with_poll) { FactoryGirl.create(:status_message_with_poll) } + let(:poll_participation_entity) { + FactoryGirl.build( + :poll_participation_entity, + author: sender.diaspora_handle, + parent_guid: post_with_poll.poll.guid, + poll_answer_guid: post_with_poll.poll.poll_answers.first.guid + ) + } + + it "saves the poll participation" do + received = Diaspora::Federation::Receive.poll_participation(poll_participation_entity) + + poll_participation = PollParticipation.find_by!(guid: poll_participation_entity.guid) + + expect(received).to eq(poll_participation) + expect(poll_participation.author).to eq(sender) + expect(poll_participation.poll_answer).to eq(post_with_poll.poll.poll_answers.first) + end + + it "attaches the poll participation to the poll" do + Diaspora::Federation::Receive.poll_participation(poll_participation_entity) + + poll_participation = PollParticipation.find_by!(guid: poll_participation_entity.guid) + + expect(post_with_poll.poll.poll_participations).to include(poll_participation) + expect(poll_participation.poll).to eq(post_with_poll.poll) + end + + it_behaves_like "it ignores existing object received twice", PollParticipation, :poll_participation do + let(:entity) { poll_participation_entity } + end + end + + describe ".profile" do + let(:profile_entity) { FactoryGirl.build(:profile_entity, author: sender.diaspora_handle) } + + it "updates the profile of the person" do + received = Diaspora::Federation::Receive.profile(profile_entity) + + profile = Profile.find(sender.profile.id) + + expect(received).to eq(profile) + expect(profile.first_name).to eq(profile_entity.first_name) + expect(profile.last_name).to eq(profile_entity.last_name) + expect(profile.gender).to eq(profile_entity.gender) + expect(profile.bio).to eq(profile_entity.bio) + expect(profile.location).to eq(profile_entity.location) + expect(profile.searchable).to eq(profile_entity.searchable) + expect(profile.nsfw).to eq(profile_entity.nsfw) + expect(profile.tag_string).to eq(profile_entity.tag_string) + end + end + + describe ".reshare" do + let(:reshare_entity) { FactoryGirl.build(:reshare_entity, author: sender.diaspora_handle, root_guid: post.guid) } + + it "saves the reshare" do + received = Diaspora::Federation::Receive.reshare(reshare_entity) + + reshare = Reshare.find_by!(guid: reshare_entity.guid) + + expect(received).to eq(reshare) + expect(reshare.author).to eq(sender) + end + + it "attaches the reshare to the post" do + Diaspora::Federation::Receive.reshare(reshare_entity) + + reshare = Reshare.find_by!(guid: reshare_entity.guid) + + expect(post.reshares).to include(reshare) + expect(reshare.root).to eq(post) + expect(reshare.created_at.iso8601).to eq(reshare_entity.created_at.iso8601) + end + + it_behaves_like "it ignores existing object received twice", Reshare, :reshare do + let(:entity) { reshare_entity } + end + end + + describe ".retraction" do + it "destroys the post" do + remote_post = FactoryGirl.create(:status_message, author: sender, public: true) + + retraction = FactoryGirl.build( + :retraction_entity, + author: sender.diaspora_handle, + target_guid: remote_post.guid, + target_type: "Post" + ) + + expect_any_instance_of(StatusMessage).to receive(:destroy!).and_call_original + + Diaspora::Federation::Receive.retraction(retraction, nil) + + expect(StatusMessage.exists?(guid: remote_post.guid)).to be_falsey + end + + it "raises when the post does not exist" do + retraction = FactoryGirl.build( + :retraction_entity, + author: sender.diaspora_handle, + target_guid: FactoryGirl.generate(:guid), + target_type: "Post" + ) + + expect { + Diaspora::Federation::Receive.retraction(retraction, nil) + }.to raise_error ActiveRecord::RecordNotFound + end + + it "disconnects on Person-Retraction" do + alice.contacts.find_or_initialize_by(person_id: sender.id, receiving: true, sharing: true).save! + + retraction = FactoryGirl.build( + :retraction_entity, + author: sender.diaspora_handle, + target_guid: sender.guid, + target_type: "Person" + ) + + Diaspora::Federation::Receive.retraction(retraction, alice.id) + + contact = alice.contacts.find_by!(person_id: sender.id) + + expect(contact).not_to be_nil + expect(contact.sharing).to be_falsey + end + end + + describe ".status_message" do + context "basic status message" do + let(:status_message_entity) { FactoryGirl.build(:status_message_entity, author: sender.diaspora_handle) } + + it "saves the status message" do + received = Diaspora::Federation::Receive.status_message(status_message_entity) + + status_message = StatusMessage.find_by!(guid: status_message_entity.guid) + + expect(received).to eq(status_message) + expect(status_message.author).to eq(sender) + expect(status_message.raw_message).to eq(status_message_entity.raw_message) + expect(status_message.public).to eq(status_message_entity.public) + expect(status_message.created_at.iso8601).to eq(status_message_entity.created_at.iso8601) + expect(status_message.provider_display_name).to eq(status_message_entity.provider_display_name) + + expect(status_message.location).to be_nil + expect(status_message.poll).to be_nil + expect(status_message.photos).to be_empty + end + + it "returns the status message if it already exists" do + first = Diaspora::Federation::Receive.status_message(status_message_entity) + second = Diaspora::Federation::Receive.status_message(status_message_entity) + + expect(second).not_to be_nil + expect(first).to eq(second) + end + + it "does not change anything if the status message already exists" do + Diaspora::Federation::Receive.status_message(status_message_entity) + + expect_any_instance_of(StatusMessage).not_to receive(:create_or_update) + + Diaspora::Federation::Receive.status_message(status_message_entity) + end + end + + context "with poll" do + let(:poll_entity) { FactoryGirl.build(:poll_entity) } + let(:status_message_entity) { + FactoryGirl.build(:status_message_entity, author: sender.diaspora_handle, poll: poll_entity) + } + + it "saves the status message" do + received = Diaspora::Federation::Receive.status_message(status_message_entity) + + status_message = StatusMessage.find_by!(guid: status_message_entity.guid) + + expect(received).to eq(status_message) + expect(status_message.author).to eq(sender) + + expect(status_message.poll.question).to eq(poll_entity.question) + expect(status_message.poll.guid).to eq(poll_entity.guid) + expect(status_message.poll.poll_answers.count).to eq(poll_entity.poll_answers.count) + expect(status_message.poll.poll_answers.map(&:answer)).to eq(poll_entity.poll_answers.map(&:answer)) + end + end + + context "with location" do + let(:location_entity) { FactoryGirl.build(:location_entity) } + let(:status_message_entity) { + FactoryGirl.build(:status_message_entity, author: sender.diaspora_handle, location: location_entity) + } + + it "saves the status message" do + received = Diaspora::Federation::Receive.status_message(status_message_entity) + + status_message = StatusMessage.find_by!(guid: status_message_entity.guid) + + expect(received).to eq(status_message) + expect(status_message.author).to eq(sender) + + expect(status_message.location.address).to eq(location_entity.address) + expect(status_message.location.lat).to eq(location_entity.lat) + expect(status_message.location.lng).to eq(location_entity.lng) + end + end + + context "with photos" do + let(:status_message_guid) { FactoryGirl.generate(:guid) } + let(:photo1) { + FactoryGirl.build(:photo_entity, author: sender.diaspora_handle, status_message_guid: status_message_guid) + } + let(:photo2) { + FactoryGirl.build(:photo_entity, author: sender.diaspora_handle, status_message_guid: status_message_guid) + } + let(:status_message_entity) { + FactoryGirl.build( + :status_message_entity, + author: sender.diaspora_handle, + guid: status_message_guid, + photos: [photo1, photo2] + ) + } + + it "saves the status message and photos" do + received = Diaspora::Federation::Receive.status_message(status_message_entity) + + status_message = StatusMessage.find_by!(guid: status_message_entity.guid) + + expect(received).to eq(status_message) + expect(status_message.author).to eq(sender) + + expect(status_message.photos.map(&:guid)).to include(photo1.guid, photo2.guid) + end + + it "does not overwrite the photos if they already exist" do + received_photo = Diaspora::Federation::Receive.photo(photo1) + received_photo.text = "foobar" + received_photo.save! + + received = Diaspora::Federation::Receive.status_message(status_message_entity) + + status_message = StatusMessage.find_by!(guid: status_message_entity.guid) + + expect(received).to eq(status_message) + expect(status_message.author).to eq(sender) + + expect(status_message.photos.map(&:guid)).to include(photo1.guid, photo2.guid) + expect(status_message.photos.map(&:text)).to include(received_photo.text, photo2.text) + end + end + end +end diff --git a/spec/models/conversation_spec.rb b/spec/models/conversation_spec.rb index 5c4641037fe1cf152de4caac08ef6b62a693f6b0..d181bba163164f4abe1b6acd8772ff095e327aff 100644 --- a/spec/models/conversation_spec.rb +++ b/spec/models/conversation_spec.rb @@ -99,32 +99,6 @@ describe Conversation, :type => :model do expect(conversation.subscribers(user1)).to eq(user1.contacts.map(&:person)) end end - - describe "#receive" do - before do - Message.destroy_all - Conversation.destroy_all - end - - it "creates a message" do - skip # TODO - expect { - Diaspora::Parser.from_xml(xml).receive(user1, user2.person) - }.to change(Message, :count).by(1) - end - it "creates a conversation" do - skip # TODO - expect { - Diaspora::Parser.from_xml(xml).receive(user1, user2.person) - }.to change(Conversation, :count).by(1) - end - it "creates appropriate visibilities" do - skip # TODO - expect { - Diaspora::Parser.from_xml(xml).receive(user1, user2.person) - }.to change(ConversationVisibility, :count).by(participant_ids.size) - end - end end describe "#invalid parameters" do diff --git a/spec/models/photo_spec.rb b/spec/models/photo_spec.rb index b96eccc51a6aab71a559d0189d8194f89c6d92ab..bc6d2a041ca0757361725601d9d22b97ec14439d 100644 --- a/spec/models/photo_spec.rb +++ b/spec/models/photo_spec.rb @@ -274,23 +274,6 @@ describe Photo, :type => :model do end end - describe "#receive_public" do - it "updates the photo if it is already persisted" do - skip # TODO - allow(@photo).to receive(:persisted_shareable).and_return(@photo2) - expect(@photo2).to receive(:update_attributes) - @photo.receive_public - end - - it "does not update the photo if the author mismatches" do - skip # TODO - @photo.author = bob.person - allow(@photo).to receive(:persisted_shareable).and_return(@photo2) - expect(@photo).not_to receive(:update_existing_sharable) - @photo.receive_public - end - end - describe "#visible" do context "with a current user" do it "calls photos_from" do diff --git a/spec/shared_behaviors/receiving.rb b/spec/shared_behaviors/receiving.rb new file mode 100644 index 0000000000000000000000000000000000000000..2637ff49eac39a5515e6381d6cdba7503a7136af --- /dev/null +++ b/spec/shared_behaviors/receiving.rb @@ -0,0 +1,16 @@ +require "spec_helper" + +shared_examples_for "it ignores existing object received twice" do |klass, method| + it "return nil if the #{klass} already exists" do + expect(Diaspora::Federation::Receive.public_send(method, entity)).not_to be_nil + expect(Diaspora::Federation::Receive.public_send(method, entity)).to be_nil + end + + it "does not change anything if the #{klass} already exists" do + Diaspora::Federation::Receive.public_send(method, entity) + + expect_any_instance_of(klass).not_to receive(:create_or_update) + + Diaspora::Federation::Receive.public_send(method, entity) + end +end diff --git a/spec/shared_behaviors/relayable.rb b/spec/shared_behaviors/relayable.rb index d8e856354dcb17a4f65a327c9719071fb2b7891e..048c2e4aa5407593b78278686885afbd95e4d645 100644 --- a/spec/shared_behaviors/relayable.rb +++ b/spec/shared_behaviors/relayable.rb @@ -79,13 +79,6 @@ shared_examples_for "it is relayable" do context 'propagation' do describe '#receive' do - it 'does not overwrite a object that is already in the db' do - skip # TODO - expect { - @dup_object_by_parent_author.receive(@local_leia, @local_luke.person) - }.to_not change { @dup_object_by_parent_author.class.count } - end - it 'dispatches when the person receiving is the parent author' do skip # TODO p = Postzord::Dispatcher.build(@local_luke, @object_by_recipient)