diaspora/spec/models/reshare_spec.rb
Jonne Haß 777e3123d6 Try fetching missing parent of relayables
* Extract post fetching logic from Reshare into
  its own module
* raise proper error message when fetching fails
* raise proper error message when parent is still missing

We can't skip fetch failures or missing parents and
still need to retry them in case we're sent the parent
later on
2014-09-07 10:47:47 +02:00

260 lines
8.9 KiB
Ruby

require 'spec_helper'
describe Reshare, :type => :model do
include Rails.application.routes.url_helpers
it 'has a valid Factory' do
expect(FactoryGirl.build(:reshare)).to be_valid
end
it 'requires root' do
reshare = FactoryGirl.build(:reshare, :root => nil)
expect(reshare).not_to be_valid
end
it 'require public root' do
reshare = FactoryGirl.build(:reshare, :root => FactoryGirl.create(:status_message, :public => false))
expect(reshare).not_to be_valid
expect(reshare.errors[:base]).to include('Only posts which are public may be reshared.')
end
it 'forces public' do
expect(FactoryGirl.create(:reshare, :public => false).public).to be true
end
describe "#receive" do
let(:receive_reshare) { @reshare.receive(@root.author.owner, @reshare.author) }
before do
@reshare = FactoryGirl.create(:reshare, :root => FactoryGirl.build(:status_message, :author => bob.person, :public => true))
@root = @reshare.root
end
it 'increments the reshare count' do
receive_reshare
expect(@root.resharers.count).to eq(1)
end
it 'adds the resharer to the re-sharers of the post' do
receive_reshare
expect(@root.resharers).to include(@reshare.author)
end
it 'does not error if the root author has a contact for the resharer' do
bob.share_with @reshare.author, bob.aspects.first
expect {
Timeout.timeout(5) do
receive_reshare #This doesn't ever terminate on my machine before it was fixed.
end
}.not_to raise_error
end
end
describe '#nsfw' do
before do
sfw = FactoryGirl.build(:status_message, :author => alice.person, :public => true)
nsfw = FactoryGirl.build(:status_message, :author => alice.person, :public => true, :text => "This is #nsfw")
@sfw_reshare = FactoryGirl.build(:reshare, :root => sfw)
@nsfw_reshare = FactoryGirl.build(:reshare, :root => nsfw)
end
it 'deletates #nsfw to the root post' do
expect(@sfw_reshare.nsfw).not_to be true
expect(@nsfw_reshare.nsfw).to be_truthy
end
end
describe '#notification_type' do
before do
sm = FactoryGirl.build(:status_message, :author => alice.person, :public => true)
@reshare = FactoryGirl.build(:reshare, :root => sm)
end
it 'does not return anything for non-author of the original post' do
expect(@reshare.notification_type(bob, @reshare.author)).to be_nil
end
it 'returns "Reshared" for the original post author' do
expect(@reshare.notification_type(alice, @reshare.author)).to eq(Notifications::Reshared)
end
end
describe '#absolute_root' do
before do
@sm = FactoryGirl.build(:status_message, :author => alice.person, :public => true)
rs1 = FactoryGirl.build(:reshare, :root=>@sm)
rs2 = FactoryGirl.build(:reshare, :root=>rs1)
@rs3 = FactoryGirl.build(:reshare, :root=>rs2)
sm = FactoryGirl.create(:status_message, :author => alice.person, :public => true)
rs1 = FactoryGirl.create(:reshare, :root => sm)
@of_deleted = FactoryGirl.build(:reshare, :root => rs1)
sm.destroy
rs1.reload
end
it 'resolves root posts to the top level' do
expect(@rs3.absolute_root).to eq(@sm)
end
it 'can handle deleted reshares' do
expect(@of_deleted.absolute_root).to be_nil
end
it 'is used everywhere' do
expect(@rs3.message).to eq @sm.message
expect(@of_deleted.message).to be_nil
expect(@rs3.photos).to eq @sm.photos
expect(@of_deleted.photos).to be_empty
expect(@rs3.o_embed_cache).to eq @sm.o_embed_cache
expect(@of_deleted.o_embed_cache).to be_nil
expect(@rs3.open_graph_cache).to eq @sm.open_graph_cache
expect(@of_deleted.open_graph_cache).to be_nil
expect(@rs3.mentioned_people).to eq @sm.mentioned_people
expect(@of_deleted.mentioned_people).to be_empty
expect(@rs3.nsfw).to eq @sm.nsfw
expect(@of_deleted.nsfw).to be_nil
expect(@rs3.address).to eq @sm.location.try(:address)
expect(@of_deleted.address).to be_nil
end
end
describe "XML" do
before do
@reshare = FactoryGirl.build(:reshare)
@xml = @reshare.to_xml.to_s
end
context 'serialization' do
it 'serializes root_diaspora_id' do
expect(@xml).to include("root_diaspora_id")
expect(@xml).to include(@reshare.author.diaspora_handle)
end
it 'serializes root_guid' do
expect(@xml).to include("root_guid")
expect(@xml).to include(@reshare.root.guid)
end
end
context 'marshalling' do
context 'local' do
before do
@original_author = @reshare.root.author
@root_object = @reshare.root
end
it 'marshals the guid' do
expect(Reshare.from_xml(@xml).root_guid).to eq(@root_object.guid)
end
it 'fetches the root post from root_guid' do
expect(Reshare.from_xml(@xml).root).to eq(@root_object)
end
it 'fetches the root author from root_diaspora_id' do
expect(Reshare.from_xml(@xml).root.author).to eq(@original_author)
end
end
describe 'destroy' do
it 'allows you to destroy the reshare if the root post is missing' do
reshare = FactoryGirl.build(:reshare)
reshare.root = nil
expect{
reshare.destroy
}.to_not raise_error
end
end
context 'remote' do
before do
@root_object = @reshare.root
@root_object.delete
@response = double
allow(@response).to receive(:status).and_return(200)
allow(@response).to receive(:success?).and_return(true)
end
it 'fetches the root author from root_diaspora_id' do
@original_profile = @reshare.root.author.profile.dup
@reshare.root.author.profile.delete
@original_author = @reshare.root.author.dup
@reshare.root.author.delete
@original_author.profile = @original_profile
wf_prof_double = double
expect(wf_prof_double).to receive(:fetch).and_return(@original_author)
expect(Webfinger).to receive(:new).and_return(wf_prof_double)
allow(@response).to receive(:body).and_return(@root_object.to_diaspora_xml)
expect(Faraday.default_connection).to receive(:get).with(@original_author.url + short_post_path(@root_object.guid, :format => "xml")).and_return(@response)
Reshare.from_xml(@xml)
end
context "fetching post" do
it "raises if the post is not found" do
allow(@response).to receive(:status).and_return(404)
expect(Faraday.default_connection).to receive(:get).and_return(@response)
expect {
Reshare.from_xml(@xml)
}.to raise_error(Diaspora::PostNotFetchable)
end
it "raises if there's another error receiving the post" do
allow(@response).to receive(:status).and_return(500)
allow(@response).to receive(:success?).and_return(false)
expect(Faraday.default_connection).to receive(:get).and_return(@response)
expect {
Reshare.from_xml(@xml)
}.to raise_error RuntimeError
end
end
context 'saving the post' do
before do
allow(@response).to receive(:body).and_return(@root_object.to_diaspora_xml)
allow(Faraday.default_connection).to receive(:get).with(@reshare.root.author.url + short_post_path(@root_object.guid, :format => "xml")).and_return(@response)
end
it 'fetches the root post from root_guid' do
root = Reshare.from_xml(@xml).root
[:text, :guid, :diaspora_handle, :type, :public].each do |attr|
expect(root.send(attr)).to eq(@reshare.root.send(attr))
end
end
it 'correctly saves the type' do
expect(Reshare.from_xml(@xml).root.reload.type).to eq("StatusMessage")
end
it 'correctly sets the author' do
@original_author = @reshare.root.author
expect(Reshare.from_xml(@xml).root.reload.author.reload).to eq(@original_author)
end
it 'verifies that the author of the post received is the same as the author in the reshare xml' do
@original_author = @reshare.root.author.dup
@xml = @reshare.to_xml.to_s
different_person = FactoryGirl.build(:person)
wf_prof_double = double
expect(wf_prof_double).to receive(:fetch).and_return(different_person)
expect(Webfinger).to receive(:new).and_return(wf_prof_double)
allow(different_person).to receive(:url).and_return(@original_author.url)
expect{
Reshare.from_xml(@xml)
}.to raise_error /^Diaspora ID \(.+\) in the root does not match the Diaspora ID \(.+\) specified in the reshare!$/
end
end
end
end
end
end