diff options
Diffstat (limited to 'spec/lib')
-rw-r--r-- | spec/lib/activitypub/activity/create_spec.rb | 10 | ||||
-rw-r--r-- | spec/lib/delivery_failure_tracker_spec.rb | 71 | ||||
-rw-r--r-- | spec/lib/feed_manager_spec.rb | 109 |
3 files changed, 187 insertions, 3 deletions
diff --git a/spec/lib/activitypub/activity/create_spec.rb b/spec/lib/activitypub/activity/create_spec.rb index cdd499150..3c3991c13 100644 --- a/spec/lib/activitypub/activity/create_spec.rb +++ b/spec/lib/activitypub/activity/create_spec.rb @@ -290,7 +290,9 @@ RSpec.describe ActivityPub::Activity::Create do tag: [ { type: 'Emoji', - href: 'http://example.com/emoji.png', + icon: { + url: 'http://example.com/emoji.png', + }, name: 'tinking', }, ], @@ -314,7 +316,9 @@ RSpec.describe ActivityPub::Activity::Create do tag: [ { type: 'Emoji', - href: 'http://example.com/emoji.png', + icon: { + url: 'http://example.com/emoji.png', + }, }, ], } @@ -326,7 +330,7 @@ RSpec.describe ActivityPub::Activity::Create do end end - context 'with emojis missing href' do + context 'with emojis missing icon' do let(:object_json) do { id: 'bar', diff --git a/spec/lib/delivery_failure_tracker_spec.rb b/spec/lib/delivery_failure_tracker_spec.rb new file mode 100644 index 000000000..39c8c7aaf --- /dev/null +++ b/spec/lib/delivery_failure_tracker_spec.rb @@ -0,0 +1,71 @@ +# frozen_string_literal: true + +require 'rails_helper' + +describe DeliveryFailureTracker do + subject { described_class.new('http://example.com/inbox') } + + describe '#track_success!' do + before do + subject.track_failure! + subject.track_success! + end + + it 'marks URL as available again' do + expect(described_class.available?('http://example.com/inbox')).to be true + end + + it 'resets days to 0' do + expect(subject.days).to be_zero + end + end + + describe '#track_failure!' do + it 'marks URL as unavailable after 7 days of being called' do + 6.times { |i| Redis.current.sadd('exhausted_deliveries:http://example.com/inbox', i) } + subject.track_failure! + + expect(subject.days).to eq 7 + expect(described_class.unavailable?('http://example.com/inbox')).to be true + end + + it 'repeated calls on the same day do not count' do + subject.track_failure! + subject.track_failure! + + expect(subject.days).to eq 1 + end + end + + describe '.filter' do + before do + Redis.current.sadd('unavailable_inboxes', 'http://example.com/unavailable/inbox') + end + + it 'removes URLs that are unavailable' do + result = described_class.filter(['http://example.com/good/inbox', 'http://example.com/unavailable/inbox']) + + expect(result).to include('http://example.com/good/inbox') + expect(result).to_not include('http://example.com/unavailable/inbox') + end + end + + describe '.track_inverse_success!' do + let(:from_account) { Fabricate(:account, inbox_url: 'http://example.com/inbox', shared_inbox_url: 'http://example.com/shared/inbox') } + + before do + Redis.current.sadd('unavailable_inboxes', 'http://example.com/inbox') + Redis.current.sadd('unavailable_inboxes', 'http://example.com/shared/inbox') + + described_class.track_inverse_success!(from_account) + end + + it 'marks inbox URL as available again' do + expect(described_class.available?('http://example.com/inbox')).to be true + end + + it 'marks shared inbox URL as available again' do + expect(described_class.available?('http://example.com/shared/inbox')).to be true + end + end +end diff --git a/spec/lib/feed_manager_spec.rb b/spec/lib/feed_manager_spec.rb index 22439cf35..923894ccb 100644 --- a/spec/lib/feed_manager_spec.rb +++ b/spec/lib/feed_manager_spec.rb @@ -1,6 +1,10 @@ require 'rails_helper' RSpec.describe FeedManager do + it 'tracks at least as many statuses as reblogs' do + expect(FeedManager::REBLOG_FALLOFF).to be <= FeedManager::MAX_ITEMS + end + describe '#key' do subject { FeedManager.instance.key(:home, 1) } @@ -150,5 +154,110 @@ RSpec.describe FeedManager do expect(Redis.current.zcard("feed:type:#{account.id}")).to eq FeedManager::MAX_ITEMS end + + it 'sends push updates for non-home timelines' do + account = Fabricate(:account) + status = Fabricate(:status) + allow(Redis.current).to receive_messages(publish: nil) + + FeedManager.instance.push('type', account, status) + + expect(Redis.current).to have_received(:publish).with("timeline:#{account.id}", any_args).at_least(:once) + end + + context 'reblogs' do + it 'saves reblogs of unseen statuses' do + account = Fabricate(:account) + reblogged = Fabricate(:status) + reblog = Fabricate(:status, reblog: reblogged) + + expect(FeedManager.instance.push('type', account, reblog)).to be true + end + + it 'does not save a new reblog of a recent status' do + account = Fabricate(:account) + reblogged = Fabricate(:status) + reblog = Fabricate(:status, reblog: reblogged) + + FeedManager.instance.push('type', account, reblogged) + + expect(FeedManager.instance.push('type', account, reblog)).to be false + end + + it 'saves a new reblog of an old status' do + account = Fabricate(:account) + reblogged = Fabricate(:status) + reblog = Fabricate(:status, reblog: reblogged) + + FeedManager.instance.push('type', account, reblogged) + + # Fill the feed with intervening statuses + FeedManager::REBLOG_FALLOFF.times do + FeedManager.instance.push('type', account, Fabricate(:status)) + end + + expect(FeedManager.instance.push('type', account, reblog)).to be true + end + + it 'does not save a new reblog of a recently-reblogged status' do + account = Fabricate(:account) + reblogged = Fabricate(:status) + reblogs = 2.times.map { Fabricate(:status, reblog: reblogged) } + + # The first reblog will be accepted + FeedManager.instance.push('type', account, reblogs.first) + + # The second reblog should be ignored + expect(FeedManager.instance.push('type', account, reblogs.last)).to be false + end + + it 'saves a new reblog of a long-ago-reblogged status' do + account = Fabricate(:account) + reblogged = Fabricate(:status) + reblogs = 2.times.map { Fabricate(:status, reblog: reblogged) } + + # The first reblog will be accepted + FeedManager.instance.push('type', account, reblogs.first) + + # Fill the feed with intervening statuses + FeedManager::REBLOG_FALLOFF.times do + FeedManager.instance.push('type', account, Fabricate(:status)) + end + + # The second reblog should also be accepted + expect(FeedManager.instance.push('type', account, reblogs.last)).to be true + end + end + end + + describe '#unpush' do + it 'leaves a reblogged status when deleting the reblog' do + account = Fabricate(:account) + reblogged = Fabricate(:status) + status = Fabricate(:status, reblog: reblogged) + + FeedManager.instance.push('type', account, status) + + # The reblogging status should show up under normal conditions. + expect(Redis.current.zrange("feed:type:#{account.id}", 0, -1)).to eq [status.id.to_s] + + FeedManager.instance.unpush('type', account, status) + + # Because we couldn't tell if the status showed up any other way, + # we had to stick the reblogged status in by itself. + expect(Redis.current.zrange("feed:type:#{account.id}", 0, -1)).to eq [reblogged.id.to_s] + end + + it 'sends push updates' do + account = Fabricate(:account) + status = Fabricate(:status) + FeedManager.instance.push('type', account, status) + + allow(Redis.current).to receive_messages(publish: nil) + FeedManager.instance.unpush('type', account, status) + + deletion = Oj.dump(event: :delete, payload: status.id.to_s) + expect(Redis.current).to have_received(:publish).with("timeline:#{account.id}", deletion) + end end end |