about summary refs log tree commit diff
path: root/spec/workers
diff options
context:
space:
mode:
authorStarfall <us@starfall.systems>2023-04-14 19:22:47 -0500
committerStarfall <us@starfall.systems>2023-04-14 19:22:47 -0500
commit4fe1689de43f4404eb9530fcfbcbfb26d6c1c13a (patch)
tree6811b845bb7f4966b10dcefa3dea404246f161c7 /spec/workers
parent65c1e53a32cabcdbb7bca57002bb0f6acdebe07e (diff)
parentbed63f6dae0879ac840066b031229e0d139089cd (diff)
Merge remote-tracking branch 'glitch/main' HEAD main
Diffstat (limited to 'spec/workers')
-rw-r--r--spec/workers/activitypub/distribute_poll_update_worker_spec.rb2
-rw-r--r--spec/workers/activitypub/distribution_worker_spec.rb4
-rw-r--r--spec/workers/activitypub/move_distribution_worker_spec.rb10
-rw-r--r--spec/workers/activitypub/processing_worker_spec.rb2
-rw-r--r--spec/workers/activitypub/status_update_distribution_worker_spec.rb2
-rw-r--r--spec/workers/activitypub/update_distribution_worker_spec.rb2
-rw-r--r--spec/workers/admin/account_deletion_worker_spec.rb19
-rw-r--r--spec/workers/cache_buster_worker_spec.rb19
-rw-r--r--spec/workers/domain_block_worker_spec.rb2
-rw-r--r--spec/workers/domain_clear_media_worker_spec.rb2
-rw-r--r--spec/workers/feed_insert_worker_spec.rb10
-rw-r--r--spec/workers/move_worker_spec.rb4
-rw-r--r--spec/workers/poll_expiration_notify_worker_spec.rb72
-rw-r--r--spec/workers/post_process_media_worker_spec.rb13
-rw-r--r--spec/workers/push_conversation_worker_spec.rb13
-rw-r--r--spec/workers/push_encrypted_message_worker_spec.rb13
-rw-r--r--spec/workers/push_update_worker_spec.rb16
-rw-r--r--spec/workers/redownload_avatar_worker_spec.rb13
-rw-r--r--spec/workers/redownload_header_worker_spec.rb13
-rw-r--r--spec/workers/refollow_worker_spec.rb1
-rw-r--r--spec/workers/regeneration_worker_spec.rb2
-rw-r--r--spec/workers/remove_featured_tag_worker_spec.rb15
-rw-r--r--spec/workers/resolve_account_worker_spec.rb13
-rw-r--r--spec/workers/scheduler/accounts_statuses_cleanup_scheduler_spec.rb18
-rw-r--r--spec/workers/scheduler/follow_recommendations_scheduler_spec.rb43
-rw-r--r--spec/workers/scheduler/indexing_scheduler_spec.rb13
-rw-r--r--spec/workers/scheduler/instance_refresh_scheduler_spec.rb13
-rw-r--r--spec/workers/scheduler/ip_cleanup_scheduler_spec.rb13
-rw-r--r--spec/workers/scheduler/pghero_scheduler_spec.rb13
-rw-r--r--spec/workers/scheduler/scheduled_statuses_scheduler_spec.rb13
-rw-r--r--spec/workers/scheduler/suspended_user_cleanup_scheduler_spec.rb13
-rw-r--r--spec/workers/scheduler/trends/refresh_scheduler_spec.rb13
-rw-r--r--spec/workers/scheduler/trends/review_notifications_scheduler_spec.rb13
-rw-r--r--spec/workers/scheduler/user_cleanup_scheduler_spec.rb41
-rw-r--r--spec/workers/scheduler/vacuum_scheduler_spec.rb13
-rw-r--r--spec/workers/unfollow_follow_worker_spec.rb4
-rw-r--r--spec/workers/unpublish_announcement_worker_spec.rb13
-rw-r--r--spec/workers/verify_account_links_worker_spec.rb13
-rw-r--r--spec/workers/web/push_notification_worker_spec.rb2
-rw-r--r--spec/workers/webhooks/delivery_worker_spec.rb13
40 files changed, 495 insertions, 31 deletions
diff --git a/spec/workers/activitypub/distribute_poll_update_worker_spec.rb b/spec/workers/activitypub/distribute_poll_update_worker_spec.rb
index d68a695b7..947acab3b 100644
--- a/spec/workers/activitypub/distribute_poll_update_worker_spec.rb
+++ b/spec/workers/activitypub/distribute_poll_update_worker_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
 require 'rails_helper'
 
 describe ActivityPub::DistributePollUpdateWorker do
diff --git a/spec/workers/activitypub/distribution_worker_spec.rb b/spec/workers/activitypub/distribution_worker_spec.rb
index 3a5900d9b..06d6ac738 100644
--- a/spec/workers/activitypub/distribution_worker_spec.rb
+++ b/spec/workers/activitypub/distribution_worker_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
 require 'rails_helper'
 
 describe ActivityPub::DistributionWorker do
@@ -34,7 +36,7 @@ describe ActivityPub::DistributionWorker do
     end
 
     context 'with direct status' do
-      let(:mentioned_account) { Fabricate(:account, protocol: :activitypub, inbox_url: 'https://foo.bar/inbox')}
+      let(:mentioned_account) { Fabricate(:account, protocol: :activitypub, inbox_url: 'https://foo.bar/inbox') }
 
       before do
         status.update(visibility: :direct)
diff --git a/spec/workers/activitypub/move_distribution_worker_spec.rb b/spec/workers/activitypub/move_distribution_worker_spec.rb
index af8c44cc0..4df6b2f16 100644
--- a/spec/workers/activitypub/move_distribution_worker_spec.rb
+++ b/spec/workers/activitypub/move_distribution_worker_spec.rb
@@ -1,9 +1,11 @@
+# frozen_string_literal: true
+
 require 'rails_helper'
 
 describe ActivityPub::MoveDistributionWorker do
   subject { described_class.new }
 
-  let(:migration)   { Fabricate(:account_migration) }
+  let(:migration) { Fabricate(:account_migration) }
   let(:follower) { Fabricate(:account, protocol: :activitypub, inbox_url: 'http://example.com') }
   let(:blocker) { Fabricate(:account, protocol: :activitypub, inbox_url: 'http://example2.com') }
 
@@ -15,9 +17,9 @@ describe ActivityPub::MoveDistributionWorker do
 
     it 'delivers to followers and known blockers' do
       expect_push_bulk_to_match(ActivityPub::DeliveryWorker, [
-        [kind_of(String), migration.account.id, 'http://example.com'],
-        [kind_of(String), migration.account.id, 'http://example2.com']
-      ])
+                                  [kind_of(String), migration.account.id, 'http://example.com'],
+                                  [kind_of(String), migration.account.id, 'http://example2.com'],
+                                ])
       subject.perform(migration.id)
     end
   end
diff --git a/spec/workers/activitypub/processing_worker_spec.rb b/spec/workers/activitypub/processing_worker_spec.rb
index b42c0bdbc..6b57f16a9 100644
--- a/spec/workers/activitypub/processing_worker_spec.rb
+++ b/spec/workers/activitypub/processing_worker_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
 require 'rails_helper'
 
 describe ActivityPub::ProcessingWorker do
diff --git a/spec/workers/activitypub/status_update_distribution_worker_spec.rb b/spec/workers/activitypub/status_update_distribution_worker_spec.rb
index c014c6790..cf55a461d 100644
--- a/spec/workers/activitypub/status_update_distribution_worker_spec.rb
+++ b/spec/workers/activitypub/status_update_distribution_worker_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
 require 'rails_helper'
 
 describe ActivityPub::StatusUpdateDistributionWorker do
diff --git a/spec/workers/activitypub/update_distribution_worker_spec.rb b/spec/workers/activitypub/update_distribution_worker_spec.rb
index 0e057fd0b..7b1e6ff54 100644
--- a/spec/workers/activitypub/update_distribution_worker_spec.rb
+++ b/spec/workers/activitypub/update_distribution_worker_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
 require 'rails_helper'
 
 describe ActivityPub::UpdateDistributionWorker do
diff --git a/spec/workers/admin/account_deletion_worker_spec.rb b/spec/workers/admin/account_deletion_worker_spec.rb
new file mode 100644
index 000000000..631cab664
--- /dev/null
+++ b/spec/workers/admin/account_deletion_worker_spec.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe Admin::AccountDeletionWorker do
+  let(:worker) { described_class.new }
+
+  describe 'perform' do
+    let(:account) { Fabricate(:account) }
+    let(:service) { instance_double(DeleteAccountService, call: true) }
+
+    it 'calls delete account service' do
+      allow(DeleteAccountService).to receive(:new).and_return(service)
+      worker.perform(account.id)
+
+      expect(service).to have_received(:call).with(account, { reserve_email: true, reserve_username: true })
+    end
+  end
+end
diff --git a/spec/workers/cache_buster_worker_spec.rb b/spec/workers/cache_buster_worker_spec.rb
new file mode 100644
index 000000000..adeb287fa
--- /dev/null
+++ b/spec/workers/cache_buster_worker_spec.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe CacheBusterWorker do
+  let(:worker) { described_class.new }
+
+  describe 'perform' do
+    let(:path) { 'https://example.com' }
+    let(:service) { instance_double(CacheBuster, bust: true) }
+
+    it 'calls the cache buster' do
+      allow(CacheBuster).to receive(:new).and_return(service)
+      worker.perform(path)
+
+      expect(service).to have_received(:bust).with(path)
+    end
+  end
+end
diff --git a/spec/workers/domain_block_worker_spec.rb b/spec/workers/domain_block_worker_spec.rb
index bd8fc4a62..8b98443fa 100644
--- a/spec/workers/domain_block_worker_spec.rb
+++ b/spec/workers/domain_block_worker_spec.rb
@@ -20,7 +20,7 @@ describe DomainBlockWorker do
     it 'returns true for non-existent domain block' do
       result = subject.perform('aaa')
 
-      expect(result).to eq(true)
+      expect(result).to be(true)
     end
   end
 end
diff --git a/spec/workers/domain_clear_media_worker_spec.rb b/spec/workers/domain_clear_media_worker_spec.rb
index 36251b1ec..f21d1fe18 100644
--- a/spec/workers/domain_clear_media_worker_spec.rb
+++ b/spec/workers/domain_clear_media_worker_spec.rb
@@ -20,7 +20,7 @@ describe DomainClearMediaWorker do
     it 'returns true for non-existent domain block' do
       result = subject.perform('aaa')
 
-      expect(result).to eq(true)
+      expect(result).to be(true)
     end
   end
 end
diff --git a/spec/workers/feed_insert_worker_spec.rb b/spec/workers/feed_insert_worker_spec.rb
index fb34970fc..16f7d73e0 100644
--- a/spec/workers/feed_insert_worker_spec.rb
+++ b/spec/workers/feed_insert_worker_spec.rb
@@ -15,8 +15,8 @@ describe FeedInsertWorker do
         allow(FeedManager).to receive(:instance).and_return(instance)
         result = subject.perform(nil, follower.id)
 
-        expect(result).to eq true
-        expect(instance).not_to have_received(:push_to_home)
+        expect(result).to be true
+        expect(instance).to_not have_received(:push_to_home)
       end
 
       it 'skips push with missing account' do
@@ -24,8 +24,8 @@ describe FeedInsertWorker do
         allow(FeedManager).to receive(:instance).and_return(instance)
         result = subject.perform(status.id, nil)
 
-        expect(result).to eq true
-        expect(instance).not_to have_received(:push_to_home)
+        expect(result).to be true
+        expect(instance).to_not have_received(:push_to_home)
       end
     end
 
@@ -36,7 +36,7 @@ describe FeedInsertWorker do
         result = subject.perform(status.id, follower.id)
 
         expect(result).to be_nil
-        expect(instance).not_to have_received(:push_to_home)
+        expect(instance).to_not have_received(:push_to_home)
       end
 
       it 'pushes the status onto the home timeline without filter' do
diff --git a/spec/workers/move_worker_spec.rb b/spec/workers/move_worker_spec.rb
index 3ca6aaf4d..e93060adb 100644
--- a/spec/workers/move_worker_spec.rb
+++ b/spec/workers/move_worker_spec.rb
@@ -3,6 +3,8 @@
 require 'rails_helper'
 
 describe MoveWorker do
+  subject { described_class.new }
+
   let(:local_follower)   { Fabricate(:account) }
   let(:blocking_account) { Fabricate(:account) }
   let(:muting_account)   { Fabricate(:account) }
@@ -14,8 +16,6 @@ describe MoveWorker do
 
   let(:block_service) { double }
 
-  subject { described_class.new }
-
   before do
     local_follower.follow!(source_account)
     blocking_account.block!(source_account)
diff --git a/spec/workers/poll_expiration_notify_worker_spec.rb b/spec/workers/poll_expiration_notify_worker_spec.rb
new file mode 100644
index 000000000..78cbc1ee4
--- /dev/null
+++ b/spec/workers/poll_expiration_notify_worker_spec.rb
@@ -0,0 +1,72 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe PollExpirationNotifyWorker do
+  let(:worker) { described_class.new }
+  let(:account) { Fabricate(:account, domain: remote? ? 'example.com' : nil) }
+  let(:status) { Fabricate(:status, account: account) }
+  let(:poll) { Fabricate(:poll, status: status, account: account) }
+  let(:remote?) { false }
+  let(:poll_vote) { Fabricate(:poll_vote, poll: poll) }
+
+  describe '#perform' do
+    around do |example|
+      Sidekiq::Testing.fake! do
+        example.run
+      end
+    end
+
+    it 'runs without error for missing record' do
+      expect { worker.perform(nil) }.to_not raise_error
+    end
+
+    context 'when poll is not expired' do
+      it 'requeues job' do
+        worker.perform(poll.id)
+        expect(described_class.sidekiq_options_hash['lock']).to be :until_executing
+        expect(described_class).to have_enqueued_sidekiq_job(poll.id).at(poll.expires_at + 5.minutes)
+      end
+    end
+
+    context 'when poll is expired' do
+      before do
+        poll_vote
+
+        travel_to poll.expires_at + 5.minutes
+
+        worker.perform(poll.id)
+      end
+
+      context 'when poll is local' do
+        it 'notifies voters' do
+          expect(ActivityPub::DistributePollUpdateWorker).to have_enqueued_sidekiq_job(poll.status.id)
+        end
+
+        it 'notifies owner' do
+          expect(LocalNotificationWorker).to have_enqueued_sidekiq_job(poll.account.id, poll.id, 'Poll', 'poll')
+        end
+
+        it 'notifies local voters' do
+          expect(LocalNotificationWorker).to have_enqueued_sidekiq_job(poll_vote.account.id, poll.id, 'Poll', 'poll')
+        end
+      end
+
+      context 'when poll is remote' do
+        let(:remote?) { true }
+
+        it 'does not notify remote voters' do
+          expect(ActivityPub::DistributePollUpdateWorker).to_not have_enqueued_sidekiq_job(poll.status.id)
+        end
+
+        it 'does not notify owner' do
+          expect(LocalNotificationWorker).to_not have_enqueued_sidekiq_job(poll.account.id, poll.id, 'Poll', 'poll')
+        end
+
+        it 'notifies local voters' do
+          expect(LocalNotificationWorker).to have_enqueued_sidekiq_job(poll_vote.account.id, poll.id, 'Poll', 'poll')
+        end
+      end
+    end
+  end
+end
diff --git a/spec/workers/post_process_media_worker_spec.rb b/spec/workers/post_process_media_worker_spec.rb
new file mode 100644
index 000000000..33072704b
--- /dev/null
+++ b/spec/workers/post_process_media_worker_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe PostProcessMediaWorker do
+  let(:worker) { described_class.new }
+
+  describe 'perform' do
+    it 'runs without error for missing record' do
+      expect { worker.perform(nil) }.to_not raise_error
+    end
+  end
+end
diff --git a/spec/workers/push_conversation_worker_spec.rb b/spec/workers/push_conversation_worker_spec.rb
new file mode 100644
index 000000000..5fbb4c685
--- /dev/null
+++ b/spec/workers/push_conversation_worker_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe PushConversationWorker do
+  let(:worker) { described_class.new }
+
+  describe 'perform' do
+    it 'runs without error for missing record' do
+      expect { worker.perform(nil) }.to_not raise_error
+    end
+  end
+end
diff --git a/spec/workers/push_encrypted_message_worker_spec.rb b/spec/workers/push_encrypted_message_worker_spec.rb
new file mode 100644
index 000000000..3cd04ce7b
--- /dev/null
+++ b/spec/workers/push_encrypted_message_worker_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe PushEncryptedMessageWorker do
+  let(:worker) { described_class.new }
+
+  describe 'perform' do
+    it 'runs without error for missing record' do
+      expect { worker.perform(nil) }.to_not raise_error
+    end
+  end
+end
diff --git a/spec/workers/push_update_worker_spec.rb b/spec/workers/push_update_worker_spec.rb
new file mode 100644
index 000000000..c8f94fa82
--- /dev/null
+++ b/spec/workers/push_update_worker_spec.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe PushUpdateWorker do
+  let(:worker) { described_class.new }
+
+  describe 'perform' do
+    it 'runs without error for missing record' do
+      account_id = nil
+      status_id = nil
+
+      expect { worker.perform(account_id, status_id) }.to_not raise_error
+    end
+  end
+end
diff --git a/spec/workers/redownload_avatar_worker_spec.rb b/spec/workers/redownload_avatar_worker_spec.rb
new file mode 100644
index 000000000..b44ae9f03
--- /dev/null
+++ b/spec/workers/redownload_avatar_worker_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe RedownloadAvatarWorker do
+  let(:worker) { described_class.new }
+
+  describe 'perform' do
+    it 'runs without error for missing record' do
+      expect { worker.perform(nil) }.to_not raise_error
+    end
+  end
+end
diff --git a/spec/workers/redownload_header_worker_spec.rb b/spec/workers/redownload_header_worker_spec.rb
new file mode 100644
index 000000000..767ae7a5a
--- /dev/null
+++ b/spec/workers/redownload_header_worker_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe RedownloadHeaderWorker do
+  let(:worker) { described_class.new }
+
+  describe 'perform' do
+    it 'runs without error for missing record' do
+      expect { worker.perform(nil) }.to_not raise_error
+    end
+  end
+end
diff --git a/spec/workers/refollow_worker_spec.rb b/spec/workers/refollow_worker_spec.rb
index d9c2293b6..1dac15385 100644
--- a/spec/workers/refollow_worker_spec.rb
+++ b/spec/workers/refollow_worker_spec.rb
@@ -4,6 +4,7 @@ require 'rails_helper'
 
 describe RefollowWorker do
   subject { described_class.new }
+
   let(:account) { Fabricate(:account, domain: 'example.org', protocol: :activitypub) }
   let(:alice)   { Fabricate(:account, domain: nil, username: 'alice') }
   let(:bob)     { Fabricate(:account, domain: nil, username: 'bob') }
diff --git a/spec/workers/regeneration_worker_spec.rb b/spec/workers/regeneration_worker_spec.rb
index c6bdfa0e5..147a76be5 100644
--- a/spec/workers/regeneration_worker_spec.rb
+++ b/spec/workers/regeneration_worker_spec.rb
@@ -20,7 +20,7 @@ describe RegenerationWorker do
     it 'fails when account does not exist' do
       result = subject.perform('aaa')
 
-      expect(result).to eq(true)
+      expect(result).to be(true)
     end
   end
 end
diff --git a/spec/workers/remove_featured_tag_worker_spec.rb b/spec/workers/remove_featured_tag_worker_spec.rb
new file mode 100644
index 000000000..a64bd0605
--- /dev/null
+++ b/spec/workers/remove_featured_tag_worker_spec.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe RemoveFeaturedTagWorker do
+  let(:worker) { described_class.new }
+
+  describe 'perform' do
+    it 'runs without error for missing record' do
+      account_id = nil
+      featured_tag_id = nil
+      expect { worker.perform(account_id, featured_tag_id) }.to_not raise_error
+    end
+  end
+end
diff --git a/spec/workers/resolve_account_worker_spec.rb b/spec/workers/resolve_account_worker_spec.rb
new file mode 100644
index 000000000..6f3cff099
--- /dev/null
+++ b/spec/workers/resolve_account_worker_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe ResolveAccountWorker do
+  let(:worker) { described_class.new }
+
+  describe 'perform' do
+    it 'runs without error for missing record' do
+      expect { worker.perform(nil) }.to_not raise_error
+    end
+  end
+end
diff --git a/spec/workers/scheduler/accounts_statuses_cleanup_scheduler_spec.rb b/spec/workers/scheduler/accounts_statuses_cleanup_scheduler_spec.rb
index 8f20725c8..9ed8da1ba 100644
--- a/spec/workers/scheduler/accounts_statuses_cleanup_scheduler_spec.rb
+++ b/spec/workers/scheduler/accounts_statuses_cleanup_scheduler_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
 require 'rails_helper'
 
 describe Scheduler::AccountsStatusesCleanupScheduler do
@@ -19,11 +21,10 @@ describe Scheduler::AccountsStatusesCleanupScheduler do
     [
       {
         'concurrency' => 2,
-        'queues' => ['push', 'default'],
+        'queues' => %w(push default),
       },
     ]
   end
-  let(:retry_size) { 0 }
 
   before do
     queue_stub = double
@@ -33,7 +34,6 @@ describe Scheduler::AccountsStatusesCleanupScheduler do
     allow(Sidekiq::ProcessSet).to receive(:new).and_return(process_set_stub)
 
     sidekiq_stats_stub = double
-    allow(sidekiq_stats_stub).to receive(:retry_size).and_return(retry_size)
     allow(Sidekiq::Stats).to receive(:new).and_return(sidekiq_stats_stub)
 
     # Create a bunch of old statuses
@@ -70,19 +70,11 @@ describe Scheduler::AccountsStatusesCleanupScheduler do
         expect(subject.under_load?).to be true
       end
     end
-
-    context 'when there is a huge amount of jobs to retry' do
-      let(:retry_size) { 1_000_000 }
-
-      it 'returns true' do
-        expect(subject.under_load?).to be true
-      end
-    end
   end
 
   describe '#get_budget' do
     context 'on a single thread' do
-      let(:process_set_stub) { [ { 'concurrency' => 1, 'queues' => ['push', 'default'] } ] }
+      let(:process_set_stub) { [{ 'concurrency' => 1, 'queues' => %w(push default) }] }
 
       it 'returns a low value' do
         expect(subject.compute_budget).to be < 10
@@ -92,7 +84,7 @@ describe Scheduler::AccountsStatusesCleanupScheduler do
     context 'on a lot of threads' do
       let(:process_set_stub) do
         [
-          { 'concurrency' => 2, 'queues' => ['push', 'default'] },
+          { 'concurrency' => 2, 'queues' => %w(push default) },
           { 'concurrency' => 2, 'queues' => ['push'] },
           { 'concurrency' => 2, 'queues' => ['push'] },
           { 'concurrency' => 2, 'queues' => ['push'] },
diff --git a/spec/workers/scheduler/follow_recommendations_scheduler_spec.rb b/spec/workers/scheduler/follow_recommendations_scheduler_spec.rb
new file mode 100644
index 000000000..18d5260e4
--- /dev/null
+++ b/spec/workers/scheduler/follow_recommendations_scheduler_spec.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe Scheduler::FollowRecommendationsScheduler do
+  let!(:target_accounts) do
+    Fabricate.times(3, :account) do
+      statuses(count: 6)
+    end
+  end
+  let!(:follower_accounts) do
+    Fabricate.times(5, :account) do
+      statuses(count: 6)
+    end
+  end
+
+  describe '#perform' do
+    subject(:scheduled_run) { described_class.new.perform }
+
+    context 'when there are accounts to recommend' do
+      before do
+        # Follow the target accounts by follow accounts to make them recommendable
+        follower_accounts.each do |follower_account|
+          target_accounts.each do |target_account|
+            Fabricate(:follow, account: follower_account, target_account: target_account)
+          end
+        end
+      end
+
+      it 'creates recommendations' do
+        expect { scheduled_run }.to change(FollowRecommendation, :count).from(0).to(target_accounts.size)
+        expect(redis.zrange('follow_recommendations:en', 0, -1)).to match_array(target_accounts.pluck(:id).map(&:to_s))
+      end
+    end
+
+    context 'when there are no accounts to recommend' do
+      it 'does not create follow recommendations' do
+        expect { scheduled_run }.to_not change(FollowRecommendation, :count)
+        expect(redis.zrange('follow_recommendations:en', 0, -1)).to be_empty
+      end
+    end
+  end
+end
diff --git a/spec/workers/scheduler/indexing_scheduler_spec.rb b/spec/workers/scheduler/indexing_scheduler_spec.rb
new file mode 100644
index 000000000..568f0fc84
--- /dev/null
+++ b/spec/workers/scheduler/indexing_scheduler_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe Scheduler::IndexingScheduler do
+  let(:worker) { described_class.new }
+
+  describe 'perform' do
+    it 'runs without error' do
+      expect { worker.perform }.to_not raise_error
+    end
+  end
+end
diff --git a/spec/workers/scheduler/instance_refresh_scheduler_spec.rb b/spec/workers/scheduler/instance_refresh_scheduler_spec.rb
new file mode 100644
index 000000000..8f686a699
--- /dev/null
+++ b/spec/workers/scheduler/instance_refresh_scheduler_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe Scheduler::InstanceRefreshScheduler do
+  let(:worker) { described_class.new }
+
+  describe 'perform' do
+    it 'runs without error' do
+      expect { worker.perform }.to_not raise_error
+    end
+  end
+end
diff --git a/spec/workers/scheduler/ip_cleanup_scheduler_spec.rb b/spec/workers/scheduler/ip_cleanup_scheduler_spec.rb
new file mode 100644
index 000000000..50af03011
--- /dev/null
+++ b/spec/workers/scheduler/ip_cleanup_scheduler_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe Scheduler::IpCleanupScheduler do
+  let(:worker) { described_class.new }
+
+  describe 'perform' do
+    it 'runs without error' do
+      expect { worker.perform }.to_not raise_error
+    end
+  end
+end
diff --git a/spec/workers/scheduler/pghero_scheduler_spec.rb b/spec/workers/scheduler/pghero_scheduler_spec.rb
new file mode 100644
index 000000000..e404e5fe4
--- /dev/null
+++ b/spec/workers/scheduler/pghero_scheduler_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe Scheduler::PgheroScheduler do
+  let(:worker) { described_class.new }
+
+  describe 'perform' do
+    it 'runs without error' do
+      expect { worker.perform }.to_not raise_error
+    end
+  end
+end
diff --git a/spec/workers/scheduler/scheduled_statuses_scheduler_spec.rb b/spec/workers/scheduler/scheduled_statuses_scheduler_spec.rb
new file mode 100644
index 000000000..13c853c62
--- /dev/null
+++ b/spec/workers/scheduler/scheduled_statuses_scheduler_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe Scheduler::ScheduledStatusesScheduler do
+  let(:worker) { described_class.new }
+
+  describe 'perform' do
+    it 'runs without error' do
+      expect { worker.perform }.to_not raise_error
+    end
+  end
+end
diff --git a/spec/workers/scheduler/suspended_user_cleanup_scheduler_spec.rb b/spec/workers/scheduler/suspended_user_cleanup_scheduler_spec.rb
new file mode 100644
index 000000000..25f0e1fce
--- /dev/null
+++ b/spec/workers/scheduler/suspended_user_cleanup_scheduler_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe Scheduler::SuspendedUserCleanupScheduler do
+  let(:worker) { described_class.new }
+
+  describe 'perform' do
+    it 'runs without error' do
+      expect { worker.perform }.to_not raise_error
+    end
+  end
+end
diff --git a/spec/workers/scheduler/trends/refresh_scheduler_spec.rb b/spec/workers/scheduler/trends/refresh_scheduler_spec.rb
new file mode 100644
index 000000000..c0c5f032b
--- /dev/null
+++ b/spec/workers/scheduler/trends/refresh_scheduler_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe Scheduler::Trends::RefreshScheduler do
+  let(:worker) { described_class.new }
+
+  describe 'perform' do
+    it 'runs without error' do
+      expect { worker.perform }.to_not raise_error
+    end
+  end
+end
diff --git a/spec/workers/scheduler/trends/review_notifications_scheduler_spec.rb b/spec/workers/scheduler/trends/review_notifications_scheduler_spec.rb
new file mode 100644
index 000000000..cc971c24b
--- /dev/null
+++ b/spec/workers/scheduler/trends/review_notifications_scheduler_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe Scheduler::Trends::ReviewNotificationsScheduler do
+  let(:worker) { described_class.new }
+
+  describe 'perform' do
+    it 'runs without error' do
+      expect { worker.perform }.to_not raise_error
+    end
+  end
+end
diff --git a/spec/workers/scheduler/user_cleanup_scheduler_spec.rb b/spec/workers/scheduler/user_cleanup_scheduler_spec.rb
new file mode 100644
index 000000000..990979500
--- /dev/null
+++ b/spec/workers/scheduler/user_cleanup_scheduler_spec.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe Scheduler::UserCleanupScheduler do
+  subject { described_class.new }
+
+  let!(:new_unconfirmed_user) { Fabricate(:user) }
+  let!(:old_unconfirmed_user) { Fabricate(:user) }
+  let!(:confirmed_user)       { Fabricate(:user) }
+  let!(:moderation_note)      { Fabricate(:account_moderation_note, account: Fabricate(:account), target_account: old_unconfirmed_user.account) }
+
+  describe '#perform' do
+    before do
+      # Need to update the already-existing users because their initialization overrides confirmation_sent_at
+      new_unconfirmed_user.update!(confirmed_at: nil, confirmation_sent_at: Time.now.utc)
+      old_unconfirmed_user.update!(confirmed_at: nil, confirmation_sent_at: 1.week.ago)
+      confirmed_user.update!(confirmed_at: 1.day.ago)
+    end
+
+    it 'deletes the old unconfirmed user' do
+      expect { subject.perform }.to change { User.exists?(old_unconfirmed_user.id) }.from(true).to(false)
+    end
+
+    it "deletes the old unconfirmed user's account" do
+      expect { subject.perform }.to change { Account.exists?(old_unconfirmed_user.account_id) }.from(true).to(false)
+    end
+
+    it 'does not delete the new unconfirmed user or their account' do
+      subject.perform
+      expect(User.exists?(new_unconfirmed_user.id)).to be true
+      expect(Account.exists?(new_unconfirmed_user.account_id)).to be true
+    end
+
+    it 'does not delete the confirmed user or their account' do
+      subject.perform
+      expect(User.exists?(confirmed_user.id)).to be true
+      expect(Account.exists?(confirmed_user.account_id)).to be true
+    end
+  end
+end
diff --git a/spec/workers/scheduler/vacuum_scheduler_spec.rb b/spec/workers/scheduler/vacuum_scheduler_spec.rb
new file mode 100644
index 000000000..36ecc93d8
--- /dev/null
+++ b/spec/workers/scheduler/vacuum_scheduler_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe Scheduler::VacuumScheduler do
+  let(:worker) { described_class.new }
+
+  describe 'perform' do
+    it 'runs without error' do
+      expect { worker.perform }.to_not raise_error
+    end
+  end
+end
diff --git a/spec/workers/unfollow_follow_worker_spec.rb b/spec/workers/unfollow_follow_worker_spec.rb
index 5ea4256a9..8025b88c0 100644
--- a/spec/workers/unfollow_follow_worker_spec.rb
+++ b/spec/workers/unfollow_follow_worker_spec.rb
@@ -3,13 +3,13 @@
 require 'rails_helper'
 
 describe UnfollowFollowWorker do
+  subject { described_class.new }
+
   let(:local_follower)   { Fabricate(:account) }
   let(:source_account)   { Fabricate(:account) }
   let(:target_account)   { Fabricate(:account) }
   let(:show_reblogs)     { true }
 
-  subject { described_class.new }
-
   before do
     local_follower.follow!(source_account, reblogs: show_reblogs)
   end
diff --git a/spec/workers/unpublish_announcement_worker_spec.rb b/spec/workers/unpublish_announcement_worker_spec.rb
new file mode 100644
index 000000000..c742c30bc
--- /dev/null
+++ b/spec/workers/unpublish_announcement_worker_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe UnpublishAnnouncementWorker do
+  let(:worker) { described_class.new }
+
+  describe 'perform' do
+    it 'runs without error for missing record' do
+      expect { worker.perform(nil) }.to_not raise_error
+    end
+  end
+end
diff --git a/spec/workers/verify_account_links_worker_spec.rb b/spec/workers/verify_account_links_worker_spec.rb
new file mode 100644
index 000000000..227591392
--- /dev/null
+++ b/spec/workers/verify_account_links_worker_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe VerifyAccountLinksWorker do
+  let(:worker) { described_class.new }
+
+  describe 'perform' do
+    it 'runs without error for missing record' do
+      expect { worker.perform(nil) }.to_not raise_error
+    end
+  end
+end
diff --git a/spec/workers/web/push_notification_worker_spec.rb b/spec/workers/web/push_notification_worker_spec.rb
index 5bc24f888..822ef5257 100644
--- a/spec/workers/web/push_notification_worker_spec.rb
+++ b/spec/workers/web/push_notification_worker_spec.rb
@@ -37,7 +37,7 @@ describe Web::PushNotificationWorker do
       expect(a_request(:post, endpoint).with(headers: {
         'Content-Encoding' => 'aesgcm',
         'Content-Type' => 'application/octet-stream',
-        'Crypto-Key' => 'dh=BAgtUks5d90kFmxGevk9tH7GEmvz9DB0qcEMUsOBgKwMf-TMjsKIIG6LQvGcFAf6jcmAod15VVwmYwGIIxE4VWE;p256ecdsa=' + vapid_public_key.delete('='),
+        'Crypto-Key' => "dh=BAgtUks5d90kFmxGevk9tH7GEmvz9DB0qcEMUsOBgKwMf-TMjsKIIG6LQvGcFAf6jcmAod15VVwmYwGIIxE4VWE;p256ecdsa=#{vapid_public_key.delete('=')}",
         'Encryption' => 'salt=WJeVM-RY-F9351SVxTFx_g',
         'Ttl' => '172800',
         'Urgency' => 'normal',
diff --git a/spec/workers/webhooks/delivery_worker_spec.rb b/spec/workers/webhooks/delivery_worker_spec.rb
new file mode 100644
index 000000000..daf8a3e28
--- /dev/null
+++ b/spec/workers/webhooks/delivery_worker_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe Webhooks::DeliveryWorker do
+  let(:worker) { described_class.new }
+
+  describe 'perform' do
+    it 'runs without error' do
+      expect { worker.perform(nil, nil) }.to_not raise_error
+    end
+  end
+end