1
0
Fork 0
mirror of https://github.com/mastodon/mastodon.git synced 2024-08-20 21:08:15 -07:00

Improve spec coverage for collection of workers/ classes (#27874)

This commit is contained in:
Matt Jankowski 2023-11-16 09:36:59 -05:00 committed by GitHub
parent 0a6ec048a8
commit 155fb84141
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 460 additions and 8 deletions

View file

@ -0,0 +1,5 @@
# frozen_string_literal: true
Fabricator(:account_deletion_request) do
account
end

View file

@ -0,0 +1,7 @@
# frozen_string_literal: true
Fabricator(:import) do
account
type :following
data { attachment_fixture('imports.txt') }
end

View file

@ -0,0 +1,52 @@
# frozen_string_literal: true
require 'rails_helper'
describe AccountRefreshWorker do
let(:worker) { described_class.new }
let(:service) { instance_double(ResolveAccountService, call: true) }
describe '#perform' do
before do
allow(ResolveAccountService).to receive(:new).and_return(service)
end
context 'when account does not exist' do
it 'returns immediately without processing' do
worker.perform(123_123_123)
expect(service).to_not have_received(:call)
end
end
context 'when account exists' do
context 'when account does not need refreshing' do
let(:account) { Fabricate(:account, last_webfingered_at: recent_webfinger_at) }
it 'returns immediately without processing' do
worker.perform(account.id)
expect(service).to_not have_received(:call)
end
end
context 'when account needs refreshing' do
let(:account) { Fabricate(:account, last_webfingered_at: outdated_webfinger_at) }
it 'schedules an account update' do
worker.perform(account.id)
expect(service).to have_received(:call)
end
end
def recent_webfinger_at
(Account::BACKGROUND_REFRESH_INTERVAL - 3.days).ago
end
def outdated_webfinger_at
(Account::BACKGROUND_REFRESH_INTERVAL + 3.days).ago
end
end
end
end

View file

@ -0,0 +1,18 @@
# frozen_string_literal: true
require 'rails_helper'
describe ActivityPub::PostUpgradeWorker do
let(:worker) { described_class.new }
describe '#perform' do
let(:domain) { 'host.example' }
it 'updates relevant values' do
account = Fabricate(:account, domain: domain, last_webfingered_at: 1.day.ago, protocol: :ostatus)
worker.perform(domain)
expect(account.reload.last_webfingered_at).to be_nil
end
end
end

View file

@ -0,0 +1,29 @@
# frozen_string_literal: true
require 'rails_helper'
describe ActivityPub::SynchronizeFeaturedTagsCollectionWorker do
let(:worker) { described_class.new }
let(:service) { instance_double(ActivityPub::FetchFeaturedTagsCollectionService, call: true) }
describe '#perform' do
before do
allow(ActivityPub::FetchFeaturedTagsCollectionService).to receive(:new).and_return(service)
end
let(:account) { Fabricate(:account) }
let(:url) { 'https://host.example' }
it 'sends the account and url to the service' do
worker.perform(account.id, url)
expect(service).to have_received(:call).with(account, url)
end
it 'returns true for non-existent record' do
result = worker.perform(123_123_123, url)
expect(result).to be(true)
end
end
end

View file

@ -0,0 +1,28 @@
# frozen_string_literal: true
require 'rails_helper'
describe Admin::SuspensionWorker do
let(:worker) { described_class.new }
let(:service) { instance_double(SuspendAccountService, call: true) }
describe '#perform' do
before do
allow(SuspendAccountService).to receive(:new).and_return(service)
end
let(:account) { Fabricate(:account) }
it 'sends the account to the service' do
worker.perform(account.id)
expect(service).to have_received(:call).with(account)
end
it 'returns true for non-existent record' do
result = worker.perform(123_123_123)
expect(result).to be(true)
end
end
end

View file

@ -0,0 +1,29 @@
# frozen_string_literal: true
require 'rails_helper'
describe AfterAccountDomainBlockWorker do
let(:worker) { described_class.new }
let(:service) { instance_double(AfterBlockDomainFromAccountService, call: true) }
describe '#perform' do
before do
allow(AfterBlockDomainFromAccountService).to receive(:new).and_return(service)
end
let(:account) { Fabricate(:account) }
let(:domain) { 'host.example' }
it 'sends the account and domain to the service' do
worker.perform(account.id, domain)
expect(service).to have_received(:call).with(account, domain)
end
it 'returns true for non-existent record' do
result = worker.perform(123_123_123, domain)
expect(result).to be(true)
end
end
end

View file

@ -0,0 +1,36 @@
# frozen_string_literal: true
require 'rails_helper'
describe BackupWorker do
let(:worker) { described_class.new }
let(:service) { instance_double(BackupService, call: true) }
describe '#perform' do
before do
allow(BackupService).to receive(:new).and_return(service)
end
let(:backup) { Fabricate(:backup) }
let!(:other_backup) { Fabricate(:backup, user: backup.user) }
it 'sends the backup to the service and removes other backups' do
expect do
worker.perform(backup.id)
end.to change(UserMailer.deliveries, :size).by(1)
expect(service).to have_received(:call).with(backup)
expect { other_backup.reload }.to raise_error(ActiveRecord::RecordNotFound)
end
context 'when sidekiq retries are exhausted' do
it 'destroys the backup' do
described_class.within_sidekiq_retries_exhausted_block({ 'args' => [backup.id] }) do
worker.perform(backup.id)
end
expect { backup.reload }.to raise_error(ActiveRecord::RecordNotFound)
end
end
end
end

View file

@ -0,0 +1,42 @@
# frozen_string_literal: true
require 'rails_helper'
describe DeleteMuteWorker do
let(:worker) { described_class.new }
let(:service) { instance_double(UnmuteService, call: true) }
describe '#perform' do
before do
allow(UnmuteService).to receive(:new).and_return(service)
end
context 'with an expired mute' do
let(:mute) { Fabricate(:mute, expires_at: 1.day.ago) }
it 'sends the mute to the service' do
worker.perform(mute.id)
expect(service).to have_received(:call).with(mute.account, mute.target_account)
end
end
context 'with an unexpired mute' do
let(:mute) { Fabricate(:mute, expires_at: 1.day.from_now) }
it 'does not send the mute to the service' do
worker.perform(mute.id)
expect(service).to_not have_received(:call)
end
end
context 'with a non-existent mute' do
it 'does not send the mute to the service' do
worker.perform(123_123_123)
expect(service).to_not have_received(:call)
end
end
end
end

View file

@ -8,6 +8,7 @@ describe FeedInsertWorker do
describe 'perform' do describe 'perform' do
let(:follower) { Fabricate(:account) } let(:follower) { Fabricate(:account) }
let(:status) { Fabricate(:status) } let(:status) { Fabricate(:status) }
let(:list) { Fabricate(:list) }
context 'when there are no records' do context 'when there are no records' do
it 'skips push with missing status' do it 'skips push with missing status' do
@ -42,11 +43,29 @@ describe FeedInsertWorker do
it 'pushes the status onto the home timeline without filter' do it 'pushes the status onto the home timeline without filter' do
instance = instance_double(FeedManager, push_to_home: nil, filter?: false) instance = instance_double(FeedManager, push_to_home: nil, filter?: false)
allow(FeedManager).to receive(:instance).and_return(instance) allow(FeedManager).to receive(:instance).and_return(instance)
result = subject.perform(status.id, follower.id) result = subject.perform(status.id, follower.id, :home)
expect(result).to be_nil expect(result).to be_nil
expect(instance).to have_received(:push_to_home).with(follower, status, update: nil) expect(instance).to have_received(:push_to_home).with(follower, status, update: nil)
end end
it 'pushes the status onto the tags timeline without filter' do
instance = instance_double(FeedManager, push_to_home: nil, filter?: false)
allow(FeedManager).to receive(:instance).and_return(instance)
result = subject.perform(status.id, follower.id, :tags)
expect(result).to be_nil
expect(instance).to have_received(:push_to_home).with(follower, status, update: nil)
end
it 'pushes the status onto the list timeline without filter' do
instance = instance_double(FeedManager, push_to_list: nil, filter?: false)
allow(FeedManager).to receive(:instance).and_return(instance)
result = subject.perform(status.id, list.id, :list)
expect(result).to be_nil
expect(instance).to have_received(:push_to_list).with(list, status, update: nil)
end
end end
end end
end end

View file

@ -0,0 +1,23 @@
# frozen_string_literal: true
require 'rails_helper'
describe ImportWorker do
let(:worker) { described_class.new }
let(:service) { instance_double(ImportService, call: true) }
describe '#perform' do
before do
allow(ImportService).to receive(:new).and_return(service)
end
let(:import) { Fabricate(:import) }
it 'sends the import to the service' do
worker.perform(import.id)
expect(service).to have_received(:call).with(import)
expect { import.reload }.to raise_error(ActiveRecord::RecordNotFound)
end
end
end

View file

@ -2,12 +2,38 @@
require 'rails_helper' require 'rails_helper'
describe PostProcessMediaWorker do describe PostProcessMediaWorker, :paperclip_processing do
let(:worker) { described_class.new } let(:worker) { described_class.new }
describe 'perform' do describe '#perform' do
it 'runs without error for missing record' do let(:media_attachment) { Fabricate(:media_attachment) }
expect { worker.perform(nil) }.to_not raise_error
it 'reprocesses and updates the media attachment' do
worker.perform(media_attachment.id)
expect(media_attachment.processing).to eq('complete')
end
it 'returns true for non-existent record' do
result = worker.perform(123_123_123)
expect(result).to be(true)
end
context 'when sidekiq retries are exhausted' do
it 'sets state to failed' do
described_class.within_sidekiq_retries_exhausted_block({ 'args' => [media_attachment.id] }) do
worker.perform(media_attachment.id)
end
expect(media_attachment.reload.processing).to eq('failed')
end
it 'returns true for non-existent record' do
described_class.within_sidekiq_retries_exhausted_block({ 'args' => [123_123_123] }) do
expect(worker.perform(123_123_123)).to be(true)
end
end
end end
end end
end end

View file

@ -0,0 +1,38 @@
# frozen_string_literal: true
require 'rails_helper'
describe PublishAnnouncementReactionWorker do
let(:worker) { described_class.new }
describe '#perform' do
before { Fabricate(:account, user: Fabricate(:user, current_sign_in_at: 1.hour.ago)) }
let(:announcement) { Fabricate(:announcement) }
let(:name) { 'name value' }
it 'sends the announcement and name to the service when subscribed' do
allow(redis).to receive(:exists?).and_return(true)
allow(redis).to receive(:publish)
worker.perform(announcement.id, name)
expect(redis).to have_received(:publish)
end
it 'does not send the announcement and name to the service when not subscribed' do
allow(redis).to receive(:exists?).and_return(false)
allow(redis).to receive(:publish)
worker.perform(announcement.id, name)
expect(redis).to_not have_received(:publish)
end
it 'returns true for non-existent record' do
result = worker.perform(123_123_123, name)
expect(result).to be(true)
end
end
end

View file

@ -0,0 +1,28 @@
# frozen_string_literal: true
require 'rails_helper'
describe RemovalWorker do
let(:worker) { described_class.new }
let(:service) { instance_double(RemoveStatusService, call: true) }
describe '#perform' do
before do
allow(RemoveStatusService).to receive(:new).and_return(service)
end
let(:status) { Fabricate(:status) }
it 'sends the status to the service' do
worker.perform(status.id)
expect(service).to have_received(:call).with(status)
end
it 'returns true for non-existent record' do
result = worker.perform(123_123_123)
expect(result).to be(true)
end
end
end

View file

@ -0,0 +1,60 @@
# frozen_string_literal: true
require 'rails_helper'
describe Scheduler::SelfDestructScheduler do
let(:worker) { described_class.new }
describe '#perform' do
let!(:account) { Fabricate(:account, domain: nil, suspended_at: nil) }
context 'when not in self destruct mode' do
before do
allow(SelfDestructHelper).to receive(:self_destruct?).and_return(false)
end
it 'returns without processing' do
worker.perform
expect(account.reload.suspended_at).to be_nil
end
end
context 'when in self-destruct mode' do
before do
allow(SelfDestructHelper).to receive(:self_destruct?).and_return(true)
end
context 'when sidekiq is overwhelmed' do
before do
stats = instance_double(Sidekiq::Stats, enqueued: described_class::MAX_ENQUEUED**2)
allow(Sidekiq::Stats).to receive(:new).and_return(stats)
end
it 'returns without processing' do
worker.perform
expect(account.reload.suspended_at).to be_nil
end
end
context 'when sidekiq is operational' do
it 'suspends local non-suspended accounts' do
worker.perform
expect(account.reload.suspended_at).to_not be_nil
end
it 'suspends local suspended accounts marked for deletion' do
account.update(suspended_at: 10.days.ago)
deletion_request = Fabricate(:account_deletion_request, account: account)
worker.perform
expect(account.reload.suspended_at).to be > 1.day.ago
expect { deletion_request.reload }.to raise_error(ActiveRecord::RecordNotFound)
end
end
end
end
end

View file

@ -5,9 +5,21 @@ require 'rails_helper'
describe Webhooks::DeliveryWorker do describe Webhooks::DeliveryWorker do
let(:worker) { described_class.new } let(:worker) { described_class.new }
describe 'perform' do describe '#perform' do
it 'runs without error' do let(:webhook) { Fabricate(:webhook) }
expect { worker.perform(nil, nil) }.to_not raise_error
it 'reprocesses and updates the webhook' do
stub_request(:post, webhook.url).to_return(status: 200, body: '')
worker.perform(webhook.id, 'body')
expect(a_request(:post, webhook.url)).to have_been_made.at_least_once
end
it 'returns true for non-existent record' do
result = worker.perform(123_123_123, '')
expect(result).to be(true)
end end
end end
end end