Merge remote-tracking branch 'parent/main' into upstream-20240226

This commit is contained in:
KMY 2024-02-26 12:23:46 +09:00
commit 1802e318f9
85 changed files with 814 additions and 212 deletions

View file

@ -325,7 +325,7 @@ RSpec.describe ActivityPub::ProcessAccountService, type: :service do
end
end
context 'with property values' do
context 'with property values, an avatar, and a profile header' do
let(:payload) do
{
id: 'https://foo.test',
@ -336,14 +336,30 @@ RSpec.describe ActivityPub::ProcessAccountService, type: :service do
{ type: 'PropertyValue', name: 'Occupation', value: 'Unit test' },
{ type: 'PropertyValue', name: 'non-string', value: %w(foo bar) },
],
image: {
type: 'Image',
mediaType: 'image/png',
url: 'https://foo.test/image.png',
},
icon: {
type: 'Image',
url: [
{
mediaType: 'image/png',
href: 'https://foo.test/icon.png',
},
],
},
}.with_indifferent_access
end
before do
stub_request(:get, 'https://example.com/.well-known/nodeinfo').to_return(body: '{}')
stub_request(:get, 'https://foo.test/image.png').to_return(request_fixture('avatar.txt'))
stub_request(:get, 'https://foo.test/icon.png').to_return(request_fixture('avatar.txt'))
end
it 'parses out of attachment' do
it 'parses property values, avatar and profile header as expected' do
account = subject.call('alice', 'example.com', payload)
expect(account.fields)
@ -361,6 +377,10 @@ RSpec.describe ActivityPub::ProcessAccountService, type: :service do
name: eq('Occupation'),
value: eq('Unit test')
)
expect(account).to have_attributes(
avatar_remote_url: 'https://foo.test/icon.png',
header_remote_url: 'https://foo.test/image.png'
)
end
end

View file

@ -0,0 +1,30 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe ApproveAppealService do
describe '#call' do
context 'with an existing appeal' do
let(:appeal) { Fabricate(:appeal) }
let(:account) { Fabricate(:account) }
it 'processes the appeal approval' do
expect { subject.call(appeal, account) }
.to mark_overruled
.and record_approver
end
def mark_overruled
change(appeal.strike, :overruled_at)
.from(nil)
.to(be > 1.minute.ago)
end
def record_approver
change(appeal, :approved_by_account)
.from(nil)
.to(account)
end
end
end
end

View file

@ -0,0 +1,48 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe MoveService do
subject { described_class.new.call(migration) }
context 'with a valid migration record' do
let(:migration) { Fabricate(:account_migration, account: source_account, target_account: target_account) }
let(:source_account) { Fabricate(:account) }
let(:target_account) { Fabricate(:account, also_known_as: [source_account_uri]) }
it 'migrates the account to a new account' do
expect { subject }
.to change_source_moved_value
.and process_local_updates
.and distribute_updates
.and distribute_move
end
end
def source_account_uri
ActivityPub::TagManager
.instance
.uri_for(source_account)
end
def change_source_moved_value
change(source_account.reload, :moved_to_account)
.from(nil)
.to(target_account)
end
def process_local_updates
enqueue_sidekiq_job(MoveWorker)
.with(source_account.id, target_account.id)
end
def distribute_updates
enqueue_sidekiq_job(ActivityPub::UpdateDistributionWorker)
.with(source_account.id)
end
def distribute_move
enqueue_sidekiq_job(ActivityPub::MoveDistributionWorker)
.with(migration.id)
end
end

View file

@ -0,0 +1,28 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe RemoveDomainsFromFollowersService do
describe '#call' do
context 'with account followers' do
let(:account) { Fabricate(:account, domain: nil) }
let(:good_domain_account) { Fabricate(:account, domain: 'good.example', protocol: :activitypub) }
let(:bad_domain_account) { Fabricate(:account, domain: 'bad.example', protocol: :activitypub) }
before do
Fabricate :follow, target_account: account, account: good_domain_account
Fabricate :follow, target_account: account, account: bad_domain_account
end
it 'removes followers from supplied domains and sends a notification' do
subject.call(account, ['bad.example'])
expect(account.followers)
.to include(good_domain_account)
.and not_include(bad_domain_account)
expect(ActivityPub::DeliveryWorker)
.to have_enqueued_sidekiq_job(anything, account.id, bad_domain_account.inbox_url)
end
end
end
end

View file

@ -0,0 +1,37 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe RemoveFeaturedTagService do
describe '#call' do
context 'with a featured tag' do
let(:featured_tag) { Fabricate(:featured_tag) }
context 'when called by a local account' do
let(:account) { Fabricate(:account, domain: nil) }
it 'destroys the featured tag and sends a distribution' do
subject.call(account, featured_tag)
expect { featured_tag.reload }
.to raise_error(ActiveRecord::RecordNotFound)
expect(ActivityPub::AccountRawDistributionWorker)
.to have_enqueued_sidekiq_job(anything, account.id)
end
end
context 'when called by a non local account' do
let(:account) { Fabricate(:account, domain: 'host.example') }
it 'destroys the featured tag and does not send a distribution' do
subject.call(account, featured_tag)
expect { featured_tag.reload }
.to raise_error(ActiveRecord::RecordNotFound)
expect(ActivityPub::AccountRawDistributionWorker)
.to_not have_enqueued_sidekiq_job
end
end
end
end
end

View file

@ -0,0 +1,36 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe UnfavouriteService do
describe '#call' do
context 'with a favourited status' do
let(:status) { Fabricate(:status, account: account) }
let!(:favourite) { Fabricate(:favourite, status: status) }
context 'when the status account is local' do
let(:account) { Fabricate(:account, domain: nil) }
it 'destroys the favourite' do
subject.call(favourite.account, status)
expect { favourite.reload }
.to raise_error(ActiveRecord::RecordNotFound)
end
end
context 'when the status account is a remote activitypub account' do
let(:account) { Fabricate(:account, domain: 'host.example', protocol: :activitypub) }
it 'destroys the favourite and sends a notification' do
subject.call(favourite.account, status)
expect { favourite.reload }
.to raise_error(ActiveRecord::RecordNotFound)
expect(ActivityPub::DeliveryWorker)
.to have_enqueued_sidekiq_job(anything, favourite.account.id, status.account.inbox_url)
end
end
end
end
end

View file

@ -0,0 +1,46 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe UnmuteService do
describe '#call' do
let!(:account) { Fabricate(:account) }
let!(:target_account) { Fabricate(:account) }
context 'when account is muting target account' do
before { Fabricate :mute, account: account, target_account: target_account }
context 'when account follows target_account' do
before { Fabricate :follow, account: account, target_account: target_account }
it 'removes the account mute and sets up a merge' do
expect { subject.call(account, target_account) }
.to remove_account_mute
expect(MergeWorker).to have_enqueued_sidekiq_job(target_account.id, account.id)
end
end
context 'when account does not follow target_account' do
it 'removes the account mute and does not create a merge' do
expect { subject.call(account, target_account) }
.to remove_account_mute
expect(MergeWorker).to_not have_enqueued_sidekiq_job
end
end
def remove_account_mute
change { account.reload.muting?(target_account) }
.from(true)
.to(false)
end
end
context 'when account is not muting target account' do
it 'does nothing and returns' do
expect { subject.call(account, target_account) }
.to_not(change { account.reload.muting?(target_account) })
expect(MergeWorker).to_not have_enqueued_sidekiq_job
end
end
end
end

View file

@ -77,27 +77,28 @@ RSpec.describe VerifyLinkService, type: :service do
context 'when a document is truncated but the link back is valid' do
let(:html) do
"
<<-HTML
<!doctype html>
<body>
<a rel=\"me\" href=\"#{ActivityPub::TagManager.instance.url_for(account)}\"
"
<a rel="me" href="#{ActivityPub::TagManager.instance.url_for(account)}">
HTML
end
it 'marks the field as not verified' do
expect(field.verified?).to be false
it 'marks the field as verified' do
expect(field.verified?).to be true
end
end
context 'when a link back might be truncated' do
context 'when a link tag might be truncated' do
let(:html) do
"
<<-HTML_TRUNCATED
<!doctype html>
<body>
<a rel=\"me\" href=\"#{ActivityPub::TagManager.instance.url_for(account)}"
<a rel="me" href="#{ActivityPub::TagManager.instance.url_for(account)}"
HTML_TRUNCATED
end
it 'does not mark the field as verified' do
it 'marks the field as not verified' do
expect(field.verified?).to be false
end
end
@ -165,7 +166,11 @@ RSpec.describe VerifyLinkService, type: :service do
#
# apparently github allows the user to enter website URLs with a single
# slash and makes no attempts to correct that.
let(:html) { '<a href="http:/unrelated.example">Hello</a>' }
let(:html) do
<<-HTML
<a href="http:/unrelated.example">Hello</a>
HTML
end
it 'does not crash' do
# We could probably put more effort into perhaps auto-correcting the

View file

@ -0,0 +1,40 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe VoteService do
describe '#call' do
subject { described_class.new.call(voter, poll, [0]) }
context 'with a poll and poll options' do
let(:poll) { Fabricate(:poll, account: account, options: %w(Fun UnFun)) }
let(:fun_vote) { Fabricate(:poll_vote, poll: poll) }
let(:not_fun_vote) { Fabricate(:poll_vote, poll: poll) }
let(:voter) { Fabricate(:account, domain: nil) }
context 'when the poll was created by a local account' do
let(:account) { Fabricate(:account, domain: nil) }
it 'stores the votes and distributes the poll' do
expect { subject }
.to change(PollVote, :count).by(1)
expect(ActivityPub::DistributePollUpdateWorker)
.to have_enqueued_sidekiq_job(poll.status.id)
end
end
context 'when the poll was created by a remote account' do
let(:account) { Fabricate(:account, domain: 'host.example') }
it 'stores the votes and processes delivery' do
expect { subject }
.to change(PollVote, :count).by(1)
expect(ActivityPub::DeliveryWorker)
.to have_enqueued_sidekiq_job(anything, voter.id, poll.account.inbox_url)
end
end
end
end
end

View file

@ -0,0 +1,30 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe WebhookService do
describe '#call' do
context 'with a relevant event webhook' do
let!(:report) { Fabricate(:report) }
let!(:webhook) { Fabricate(:webhook, events: ['report.created']) }
it 'finds and delivers webhook payloads' do
expect { subject.call('report.created', report) }
.to enqueue_sidekiq_job(Webhooks::DeliveryWorker)
.with(
webhook.id,
anything
)
end
end
context 'without any relevant event webhooks' do
let!(:report) { Fabricate(:report) }
it 'does not deliver webhook payloads' do
expect { subject.call('report.created', report) }
.to_not enqueue_sidekiq_job(Webhooks::DeliveryWorker)
end
end
end
end