Merge commit '9e04007020' into upstream-20240725

This commit is contained in:
KMY 2024-07-25 13:06:26 +09:00
commit a99f174d98
322 changed files with 8093 additions and 1586 deletions

View file

@ -33,7 +33,7 @@ RSpec.describe ActivityPub::FetchRemoteAccountService do
end
context 'when the account does not have a inbox' do
let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/alice' }] } }
let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/alice', type: 'application/activity+json' }] } }
before do
actor[:inbox] = nil
@ -52,7 +52,7 @@ RSpec.describe ActivityPub::FetchRemoteAccountService do
end
context 'when URI and WebFinger share the same host' do
let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/alice' }] } }
let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/alice', type: 'application/activity+json' }] } }
before do
stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' })
@ -74,7 +74,7 @@ RSpec.describe ActivityPub::FetchRemoteAccountService do
end
context 'when WebFinger presents different domain than URI' do
let!(:webfinger) { { subject: 'acct:alice@iscool.af', links: [{ rel: 'self', href: 'https://example.com/alice' }] } }
let!(:webfinger) { { subject: 'acct:alice@iscool.af', links: [{ rel: 'self', href: 'https://example.com/alice', type: 'application/activity+json' }] } }
before do
stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' })
@ -98,7 +98,7 @@ RSpec.describe ActivityPub::FetchRemoteAccountService do
end
context 'when WebFinger returns a different URI' do
let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/bob' }] } }
let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/bob', type: 'application/activity+json' }] } }
before do
stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' })
@ -115,7 +115,7 @@ RSpec.describe ActivityPub::FetchRemoteAccountService do
end
context 'when WebFinger returns a different URI after a redirection' do
let!(:webfinger) { { subject: 'acct:alice@iscool.af', links: [{ rel: 'self', href: 'https://example.com/bob' }] } }
let!(:webfinger) { { subject: 'acct:alice@iscool.af', links: [{ rel: 'self', href: 'https://example.com/bob', type: 'application/activity+json' }] } }
before do
stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' })

View file

@ -33,7 +33,7 @@ RSpec.describe ActivityPub::FetchRemoteActorService do
end
context 'when the account does not have a inbox' do
let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/alice' }] } }
let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/alice', type: 'application/activity+json' }] } }
before do
actor[:inbox] = nil
@ -52,7 +52,7 @@ RSpec.describe ActivityPub::FetchRemoteActorService do
end
context 'when URI and WebFinger share the same host' do
let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/alice' }] } }
let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/alice', type: 'application/activity+json' }] } }
before do
stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' })
@ -74,7 +74,7 @@ RSpec.describe ActivityPub::FetchRemoteActorService do
end
context 'when WebFinger presents different domain than URI' do
let!(:webfinger) { { subject: 'acct:alice@iscool.af', links: [{ rel: 'self', href: 'https://example.com/alice' }] } }
let!(:webfinger) { { subject: 'acct:alice@iscool.af', links: [{ rel: 'self', href: 'https://example.com/alice', type: 'application/activity+json' }] } }
before do
stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' })
@ -98,7 +98,7 @@ RSpec.describe ActivityPub::FetchRemoteActorService do
end
context 'when WebFinger returns a different URI' do
let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/bob' }] } }
let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/bob', type: 'application/activity+json' }] } }
before do
stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' })
@ -115,7 +115,7 @@ RSpec.describe ActivityPub::FetchRemoteActorService do
end
context 'when WebFinger returns a different URI after a redirection' do
let!(:webfinger) { { subject: 'acct:alice@iscool.af', links: [{ rel: 'self', href: 'https://example.com/bob' }] } }
let!(:webfinger) { { subject: 'acct:alice@iscool.af', links: [{ rel: 'self', href: 'https://example.com/bob', type: 'application/activity+json' }] } }
before do
stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' })

View file

@ -5,7 +5,7 @@ require 'rails_helper'
RSpec.describe ActivityPub::FetchRemoteKeyService do
subject { described_class.new }
let(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/alice' }] } }
let(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/alice', type: 'application/activity+json' }] } }
let(:public_key_pem) do
<<~TEXT

View file

@ -227,7 +227,7 @@ RSpec.describe ActivityPub::FetchRemoteStatusService do
context 'with statuses referencing other statuses', :inline_jobs do
before do
stub_const 'ActivityPub::FetchRemoteStatusService::DISCOVERIES_PER_REQUEST', 5
stub_const 'ActivityPub::FetchRemoteStatusService::DISCOVERIES_PER_REQUEST', 3
end
context 'when using inReplyTo' do
@ -243,7 +243,7 @@ RSpec.describe ActivityPub::FetchRemoteStatusService do
end
before do
8.times do |i|
5.times do |i|
status_json = {
'@context': 'https://www.w3.org/ns/activitystreams',
id: "https://foo.bar/@foo/#{i}",
@ -257,12 +257,10 @@ RSpec.describe ActivityPub::FetchRemoteStatusService do
end
end
it 'creates at least some statuses' do
expect { subject.call(object[:id], prefetched_body: Oj.dump(object)) }.to change { sender.statuses.count }.by_at_least(2)
end
it 'creates no more account than the limit allows' do
expect { subject.call(object[:id], prefetched_body: Oj.dump(object)) }.to change { sender.statuses.count }.by_at_most(5)
it 'creates statuses but not more than limit allows' do
expect { subject.call(object[:id], prefetched_body: Oj.dump(object)) }
.to change { sender.statuses.count }.by_at_least(2)
.and change { sender.statuses.count }.by_at_most(3)
end
end
@ -287,7 +285,7 @@ RSpec.describe ActivityPub::FetchRemoteStatusService do
end
before do
8.times do |i|
5.times do |i|
status_json = {
'@context': 'https://www.w3.org/ns/activitystreams',
id: "https://foo.bar/@foo/#{i}",
@ -309,12 +307,10 @@ RSpec.describe ActivityPub::FetchRemoteStatusService do
end
end
it 'creates at least some statuses' do
expect { subject.call(object[:id], prefetched_body: Oj.dump(object)) }.to change { sender.statuses.count }.by_at_least(2)
end
it 'creates no more account than the limit allows' do
expect { subject.call(object[:id], prefetched_body: Oj.dump(object)) }.to change { sender.statuses.count }.by_at_most(5)
it 'creates statuses but not more than limit allows' do
expect { subject.call(object[:id], prefetched_body: Oj.dump(object)) }
.to change { sender.statuses.count }.by_at_least(2)
.and change { sender.statuses.count }.by_at_most(3)
end
end
end

View file

@ -601,7 +601,7 @@ RSpec.describe ActivityPub::ProcessAccountService do
}.with_indifferent_access
webfinger = {
subject: "acct:user#{i}@foo.test",
links: [{ rel: 'self', href: "https://foo.test/users/#{i}" }],
links: [{ rel: 'self', href: "https://foo.test/users/#{i}", type: 'application/activity+json' }],
}.with_indifferent_access
stub_request(:get, "https://foo.test/users/#{i}").to_return(status: 200, body: actor_json.to_json, headers: { 'Content-Type': 'application/activity+json' })
stub_request(:get, "https://foo.test/users/#{i}/featured").to_return(status: 200, body: featured_json.to_json, headers: { 'Content-Type': 'application/activity+json' })

View file

@ -46,14 +46,13 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService do
end
describe '#call' do
it 'updates text' do
it 'updates text and content warning' do
subject.call(status, json, json)
expect(status.reload.text).to eq 'Hello universe'
end
it 'updates content warning' do
subject.call(status, json, json)
expect(status.reload.spoiler_text).to eq 'Show more'
expect(status.reload)
.to have_attributes(
text: eq('Hello universe'),
spoiler_text: eq('Show more')
)
end
context 'when the changes are only in sanitized-out HTML' do
@ -73,12 +72,9 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService do
subject.call(status, json, json)
end
it 'does not create any edits' do
it 'does not create any edits and does not mark status edited' do
expect(status.reload.edits).to be_empty
end
it 'does not mark status as edited' do
expect(status.edited?).to be false
expect(status).to_not be_edited
end
end
@ -96,15 +92,9 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService do
subject.call(status, json, json)
end
it 'does not create any edits' do
it 'does not create any edits, mark status edited, or update text' do
expect(status.reload.edits).to be_empty
end
it 'does not mark status as edited' do
expect(status.reload.edited?).to be false
end
it 'does not update the text' do
expect(status.reload).to_not be_edited
expect(status.reload.text).to eq 'Hello world'
end
end
@ -143,19 +133,10 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService do
subject.call(status, json, json)
end
it 'does not create any edits' do
it 'does not create any edits, mark status edited, update text but does update tallies' do
expect(status.reload.edits).to be_empty
end
it 'does not mark status as edited' do
expect(status.reload.edited?).to be false
end
it 'does not update the text' do
expect(status.reload).to_not be_edited
expect(status.reload.text).to eq 'Hello world'
end
it 'updates tallies' do
expect(status.poll.reload.cached_tallies).to eq [4, 3]
end
end
@ -195,19 +176,10 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService do
subject.call(status, json, json)
end
it 'does not create any edits' do
it 'does not create any edits, mark status edited, update text, or update tallies' do
expect(status.reload.edits).to be_empty
end
it 'does not mark status as edited' do
expect(status.reload.edited?).to be false
end
it 'does not update the text' do
expect(status.reload).to_not be_edited
expect(status.reload.text).to eq 'Hello world'
end
it 'does not update tallies' do
expect(status.poll.reload.cached_tallies).to eq [0, 0]
end
end
@ -219,13 +191,10 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService do
status.snapshot!(rate_limit: false)
end
it 'does not create any edits' do
expect { subject.call(status, json, json) }.to_not(change { status.reload.edits.pluck(&:id) })
end
it 'does not update the text, spoiler_text or edited_at' do
it 'does not create any edits or update relevant attributes' do
expect { subject.call(status, json, json) }
.to_not(change { status.reload.attributes.slice('text', 'spoiler_text', 'edited_at').values })
.to not_change { status.reload.edits.pluck(&:id) }
.and(not_change { status.reload.attributes.slice('text', 'spoiler_text', 'edited_at').values })
end
end
@ -243,12 +212,9 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService do
subject.call(status, json, json)
end
it 'does not create any edits' do
it 'does not create any edits or mark status edited' do
expect(status.reload.edits).to be_empty
end
it 'does not mark status as edited' do
expect(status.edited?).to be false
expect(status).to_not be_edited
end
end
@ -267,12 +233,9 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService do
subject.call(status, json, json)
end
it 'does not create any edits' do
it 'does not create any edits or mark status edited' do
expect(status.reload.edits).to be_empty
end
it 'does not mark status as edited' do
expect(status.edited?).to be false
expect(status).to_not be_edited
end
end
@ -456,11 +419,8 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService do
subject.call(status, json, json)
end
it 'removes poll' do
it 'removes poll and records media change in edit' do
expect(status.reload.poll).to be_nil
end
it 'records media change in edit' do
expect(status.edits.reload.last.poll_options).to be_nil
end
end
@ -486,26 +446,21 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService do
subject.call(status, json, json)
end
it 'creates a poll' do
it 'creates a poll and records media change in edit' do
poll = status.reload.poll
expect(poll).to_not be_nil
expect(poll.options).to eq %w(Foo Bar Baz)
end
it 'records media change in edit' do
expect(status.edits.reload.last.poll_options).to eq %w(Foo Bar Baz)
end
end
it 'creates edit history' do
it 'creates edit history and sets edit timestamp' do
subject.call(status, json, json)
expect(status.edits.reload.map(&:text)).to eq ['Hello world', 'Hello universe']
end
it 'sets edited timestamp' do
subject.call(status, json, json)
expect(status.reload.edited_at.to_s).to eq '2021-09-08 22:39:25 UTC'
expect(status.edits.reload.map(&:text))
.to eq ['Hello world', 'Hello universe']
expect(status.reload.edited_at.to_s)
.to eq '2021-09-08 22:39:25 UTC'
end
describe 'ng word is set' do

View file

@ -13,11 +13,9 @@ RSpec.describe ActivityPub::SynchronizeFollowersService do
let(:collection_uri) { 'http://example.com/partial-followers' }
let(:items) do
[
ActivityPub::TagManager.instance.uri_for(alice),
ActivityPub::TagManager.instance.uri_for(eve),
ActivityPub::TagManager.instance.uri_for(mallory),
]
[alice, eve, mallory].map do |account|
ActivityPub::TagManager.instance.uri_for(account)
end
end
let(:payload) do
@ -40,20 +38,15 @@ RSpec.describe ActivityPub::SynchronizeFollowersService do
subject.call(actor, collection_uri)
end
it 'keeps expected followers' do
expect(alice.following?(actor)).to be true
end
it 'removes local followers not in the remote list' do
expect(bob.following?(actor)).to be false
end
it 'converts follow requests to follow relationships when they have been accepted' do
expect(mallory.following?(actor)).to be true
end
it 'sends an Undo Follow to the actor' do
expect(ActivityPub::DeliveryWorker).to have_received(:perform_async).with(anything, eve.id, actor.inbox_url)
it 'maintains following records and sends Undo Follow to actor' do
expect(alice)
.to be_following(actor) # Keep expected followers
expect(bob)
.to_not be_following(actor) # Remove local followers not in remote list
expect(mallory)
.to be_following(actor) # Convert follow request to follow when accepted
expect(ActivityPub::DeliveryWorker)
.to have_received(:perform_async).with(anything, eve.id, actor.inbox_url) # Send Undo Follow to actor
end
end

View file

@ -62,6 +62,7 @@ RSpec.describe BackupService do
aggregate_failures do
expect(body.scan('@context').count).to eq 1
expect(body.scan('orderedItems').count).to eq 1
expect(json['@context']).to_not be_nil
expect(json['type']).to eq 'OrderedCollection'
expect(json['totalItems']).to eq 4

View file

@ -85,29 +85,15 @@ RSpec.describe FanOutOnWriteService do
context 'when status is public' do
let(:visibility) { 'public' }
it 'is added to the home feed of its author', :inline_jobs do
expect(home_feed_of(alice)).to include status.id
end
it 'adds status to home feed of author and followers and broadcasts', :inline_jobs do
expect(status.id)
.to be_in(home_feed_of(alice))
.and be_in(home_feed_of(bob))
.and be_in(home_feed_of(tom))
.and be_in(home_feed_of(tagf))
it 'is added to the home feed of the mentioned follower', :inline_jobs do
expect(home_feed_of(bob)).to include status.id
end
it 'is added to the home feed of a follower', :inline_jobs do
expect(home_feed_of(bob)).to include status.id
expect(home_feed_of(tom)).to include status.id
end
it 'is added to the tag follower', :inline_jobs do
expect(home_feed_of(tagf)).to include status.id
end
it 'is broadcast to the hashtag stream', :inline_jobs do
expect(redis).to have_received(:publish).with('timeline:hashtag:hoge', anything)
expect(redis).to have_received(:publish).with('timeline:hashtag:hoge:local', anything)
end
it 'is broadcast to the public stream', :inline_jobs do
expect(redis).to have_received(:publish).with('timeline:public', anything)
expect(redis).to have_received(:publish).with('timeline:public:local', anything)
expect(redis).to have_received(:publish).with('timeline:public:media', anything)
@ -116,12 +102,9 @@ RSpec.describe FanOutOnWriteService do
context 'when local timeline is disabled', :inline_jobs do
let(:ltl_enabled) { false }
it 'is broadcast to the hashtag stream', :inline_jobs do
it 'does not add status to local timeline', :inline_jobs do
expect(redis).to have_received(:publish).with('timeline:hashtag:hoge', anything)
expect(redis).to_not have_received(:publish).with('timeline:hashtag:hoge:local', anything)
end
it 'is broadcast to the public stream', :inline_jobs do
expect(redis).to have_received(:publish).with('timeline:public', anything)
expect(redis).to_not have_received(:publish).with('timeline:public:local', anything)
end
@ -286,25 +269,16 @@ RSpec.describe FanOutOnWriteService do
context 'when status is limited' do
let(:visibility) { 'limited' }
it 'is added to the home feed of its author', :inline_jobs do
expect(home_feed_of(alice)).to include status.id
end
it 'adds status to home feed of author and mentioned followers and does not broadcast', :inline_jobs do
expect(status.id)
.to be_in(home_feed_of(alice))
.and be_in(home_feed_of(bob))
expect(status.id)
.to_not be_in(home_feed_of(tom))
expect(status.id)
.to_not be_in(home_feed_of(tagf))
it 'is added to the home feed of the mentioned follower', :inline_jobs do
expect(home_feed_of(bob)).to include status.id
end
it 'is not added to the home feed of the other follower', :inline_jobs do
expect(home_feed_of(tom)).to_not include status.id
end
it 'is not added to the tag follower', :inline_jobs do
expect(home_feed_of(tagf)).to_not include status.id
end
it 'is not broadcast publicly', :inline_jobs do
expect(redis).to_not have_received(:publish).with('timeline:hashtag:hoge', anything)
expect(redis).to_not have_received(:publish).with('timeline:public', anything)
expect_no_broadcasting
end
context 'with list' do
@ -349,26 +323,15 @@ RSpec.describe FanOutOnWriteService do
context 'when status is private' do
let(:visibility) { 'private' }
it 'is added to the home feed of its author', :inline_jobs do
expect(home_feed_of(alice)).to include status.id
end
it 'is added to the home feed of its author and mentioned followers and does not broadcast', :inline_jobs do
expect(status.id)
.to be_in(home_feed_of(alice))
.and be_in(home_feed_of(bob))
.and be_in(home_feed_of(tom))
expect(status.id)
.to_not be_in(home_feed_of(tagf))
it 'is added to the home feed of a follower', :inline_jobs do
expect(home_feed_of(bob)).to include status.id
expect(home_feed_of(tom)).to include status.id
end
it 'is not added to the tag follower', :inline_jobs do
expect(home_feed_of(tagf)).to_not include status.id
end
it 'is not broadcast publicly', :inline_jobs do
expect(redis).to_not have_received(:publish).with('timeline:hashtag:hoge', anything)
expect(redis).to_not have_received(:publish).with('timeline:public', anything)
end
it 'is added to the home feed of the mentioned follower', :inline_jobs do
expect(home_feed_of(bob)).to include status.id
expect_no_broadcasting
end
context 'with list' do
@ -430,20 +393,14 @@ RSpec.describe FanOutOnWriteService do
context 'when status is public_unlisted' do
let(:visibility) { 'public_unlisted' }
it 'is added to the home feed of its author', :inline_jobs do
expect(home_feed_of(alice)).to include status.id
end
it 'is added to the home feed of its author and mentioned followers and does not broadcast', :inline_jobs do
expect(status.id)
.to be_in(home_feed_of(alice))
.and be_in(home_feed_of(bob))
.and be_in(home_feed_of(tom))
expect(status.id)
.to be_in(home_feed_of(tagf))
it 'is added to the home feed of a follower', :inline_jobs do
expect(home_feed_of(bob)).to include status.id
expect(home_feed_of(tom)).to include status.id
end
it 'is added to the tag follower', :inline_jobs do
expect(home_feed_of(tagf)).to include status.id
end
it 'is broadcast publicly', :inline_jobs do
expect(redis).to have_received(:publish).with('timeline:hashtag:hoge', anything)
expect(redis).to have_received(:publish).with('timeline:public:local', anything)
expect(redis).to have_received(:publish).with('timeline:public', anything)
@ -549,20 +506,14 @@ RSpec.describe FanOutOnWriteService do
context 'when status is unlisted' do
let(:visibility) { 'unlisted' }
it 'is added to the home feed of its author', :inline_jobs do
expect(home_feed_of(alice)).to include status.id
end
it 'is added to the home feed of its author and mentioned followers and does not broadcast', :inline_jobs do
expect(status.id)
.to be_in(home_feed_of(alice))
.and be_in(home_feed_of(bob))
.and be_in(home_feed_of(tom))
expect(status.id)
.to be_in(home_feed_of(tagf))
it 'is added to the home feed of a follower', :inline_jobs do
expect(home_feed_of(bob)).to include status.id
expect(home_feed_of(tom)).to include status.id
end
it 'is added to the tag follower', :inline_jobs do
expect(home_feed_of(tagf)).to include status.id
end
it 'is not broadcast publicly', :inline_jobs do
expect(redis).to have_received(:publish).with('timeline:hashtag:hoge', anything)
expect(redis).to_not have_received(:publish).with('timeline:public', anything)
end
@ -570,27 +521,25 @@ RSpec.describe FanOutOnWriteService do
context 'with searchability public_unlisted' do
let(:searchability) { 'public_unlisted' }
it 'is broadcast to the hashtag stream', :inline_jobs do
it 'is added to the home feed of its author and mentioned followers and does not broadcast', :inline_jobs do
expect(status.id)
.to be_in(home_feed_of(tagf))
expect(redis).to have_received(:publish).with('timeline:hashtag:hoge', anything)
expect(redis).to have_received(:publish).with('timeline:hashtag:hoge:local', anything)
end
it 'is added to the tag follower', :inline_jobs do
expect(home_feed_of(tagf)).to include status.id
end
end
context 'with searchability private' do
let(:searchability) { 'private' }
it 'is not broadcast to the hashtag stream', :inline_jobs do
it 'is added to the home feed of its author and mentioned followers and does not broadcast', :inline_jobs do
expect(status.id)
.to_not be_in(home_feed_of(tagf))
expect(redis).to_not have_received(:publish).with('timeline:hashtag:hoge', anything)
expect(redis).to_not have_received(:publish).with('timeline:hashtag:hoge:local', anything)
end
it 'is not added to the tag follower', :inline_jobs do
expect(home_feed_of(tagf)).to_not include status.id
end
end
context 'when local timeline is disabled' do
@ -670,25 +619,16 @@ RSpec.describe FanOutOnWriteService do
context 'when status is direct' do
let(:visibility) { 'direct' }
it 'is added to the home feed of its author', :inline_jobs do
expect(home_feed_of(alice)).to include status.id
end
it 'is added to the home feed of its author and mentioned followers and does not broadcast', :inline_jobs do
expect(status.id)
.to be_in(home_feed_of(alice))
.and be_in(home_feed_of(bob))
expect(status.id)
.to_not be_in(home_feed_of(tom))
expect(status.id)
.to_not be_in(home_feed_of(tagf))
it 'is added to the home feed of the mentioned follower', :inline_jobs do
expect(home_feed_of(bob)).to include status.id
end
it 'is not added to the home feed of the other follower', :inline_jobs do
expect(home_feed_of(tom)).to_not include status.id
end
it 'is not added to the tag follower', :inline_jobs do
expect(home_feed_of(tagf)).to_not include status.id
end
it 'is not broadcast publicly', :inline_jobs do
expect(redis).to_not have_received(:publish).with('timeline:hashtag:hoge', anything)
expect(redis).to_not have_received(:publish).with('timeline:public', anything)
expect_no_broadcasting
end
context 'with list' do
@ -746,16 +686,15 @@ RSpec.describe FanOutOnWriteService do
expect(notification.mention.status_id).to eq status.id
end
it 'inserts home feed for reply', :inline_jobs do
expect(home_feed_of(bob)).to include status.id
end
it 'is added to the home feed of its author and mentioned followers and does not broadcast', :inline_jobs do
expect(status.id)
.to be_in(home_feed_of(alice))
.and be_in(home_feed_of(bob))
.and be_in(home_feed_of(zilu))
expect(status.id)
.to_not be_in(home_feed_of(tom))
it 'inserts home feed for non-replied but mentioned and following replied account', :inline_jobs do
expect(home_feed_of(zilu)).to include status.id
end
it 'does not insert home feed for non-replied, non-following replied account but mentioned', :inline_jobs do
expect(home_feed_of(tom)).to_not include status.id
expect_no_broadcasting
end
end
@ -776,16 +715,15 @@ RSpec.describe FanOutOnWriteService do
expect(notification.mention.status_id).to eq status.id
end
it 'inserts home feed for reply', :inline_jobs do
expect(home_feed_of(bob)).to include status.id
end
it 'is added to the home feed of its author and mentioned followers and does not broadcast', :inline_jobs do
expect(status.id)
.to be_in(home_feed_of(alice))
.and be_in(home_feed_of(bob))
.and be_in(home_feed_of(zilu))
expect(status.id)
.to_not be_in(home_feed_of(tom))
it 'inserts home feed for non-replied but mentioned and following replied account', :inline_jobs do
expect(home_feed_of(zilu)).to include status.id
end
it 'does not insert home feed for non-replied, non-following replied account but mentioned', :inline_jobs do
expect(home_feed_of(tom)).to_not include status.id
expect_no_broadcasting
end
end
end
@ -820,4 +758,13 @@ RSpec.describe FanOutOnWriteService do
expect(notification).to be_nil
end
end
def expect_no_broadcasting
expect(redis)
.to_not have_received(:publish)
.with('timeline:hashtag:hoge', anything)
expect(redis)
.to_not have_received(:publish)
.with('timeline:public', anything)
end
end

View file

@ -23,6 +23,11 @@ RSpec.describe ReportService do
stub_request(:post, 'http://example.com/inbox').to_return(status: 200)
end
it 'does not have an application' do
report = subject.call(source_account, remote_account)
expect(report.application).to be_nil
end
context 'when forward is true', :inline_jobs do
let(:forward) { true }
@ -96,6 +101,15 @@ RSpec.describe ReportService do
end
end
context 'when passed an application' do
let(:application) { Fabricate(:application) }
it 'has an application' do
report = subject.call(source_account, target_account, application: application)
expect(report.application).to eq application
end
end
context 'when the reported status is a DM' do
subject do
-> { described_class.new.call(source_account, target_account, status_ids: [status.id]) }