about summary refs log tree commit diff
path: root/spec/services/activitypub
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/services/activitypub
parent65c1e53a32cabcdbb7bca57002bb0f6acdebe07e (diff)
parentbed63f6dae0879ac840066b031229e0d139089cd (diff)
Merge remote-tracking branch 'glitch/main' HEAD main
Diffstat (limited to 'spec/services/activitypub')
-rw-r--r--spec/services/activitypub/fetch_featured_collection_service_spec.rb8
-rw-r--r--spec/services/activitypub/fetch_featured_tags_collection_service_spec.rb10
-rw-r--r--spec/services/activitypub/fetch_remote_account_service_spec.rb2
-rw-r--r--spec/services/activitypub/fetch_remote_actor_service_spec.rb2
-rw-r--r--spec/services/activitypub/fetch_remote_key_service_spec.rb2
-rw-r--r--spec/services/activitypub/fetch_remote_status_service_spec.rb138
-rw-r--r--spec/services/activitypub/fetch_replies_service_spec.rb8
-rw-r--r--spec/services/activitypub/process_account_service_spec.rb18
-rw-r--r--spec/services/activitypub/process_collection_service_spec.rb124
-rw-r--r--spec/services/activitypub/process_status_update_service_spec.rb84
-rw-r--r--spec/services/activitypub/synchronize_followers_service_spec.rb8
11 files changed, 258 insertions, 146 deletions
diff --git a/spec/services/activitypub/fetch_featured_collection_service_spec.rb b/spec/services/activitypub/fetch_featured_collection_service_spec.rb
index e6336dc1b..59d332599 100644
--- a/spec/services/activitypub/fetch_featured_collection_service_spec.rb
+++ b/spec/services/activitypub/fetch_featured_collection_service_spec.rb
@@ -1,6 +1,10 @@
+# frozen_string_literal: true
+
 require 'rails_helper'
 
 RSpec.describe ActivityPub::FetchFeaturedCollectionService, type: :service do
+  subject { described_class.new }
+
   let(:actor) { Fabricate(:account, domain: 'example.com', uri: 'https://example.com/account', featured_collection_url: 'https://example.com/account/pinned') }
 
   let!(:known_status) { Fabricate(:status, account: actor, uri: 'https://example.com/account/pinned/1') }
@@ -56,8 +60,6 @@ RSpec.describe ActivityPub::FetchFeaturedCollectionService, type: :service do
     }.with_indifferent_access
   end
 
-  subject { described_class.new }
-
   shared_examples 'sets pinned posts' do
     before do
       stub_request(:get, 'https://example.com/account/pinned/1').to_return(status: 200, body: Oj.dump(status_json_1))
@@ -109,7 +111,7 @@ RSpec.describe ActivityPub::FetchFeaturedCollectionService, type: :service do
             type: 'CollectionPage',
             partOf: actor.featured_collection_url,
             items: items,
-          }
+          },
         }.with_indifferent_access
       end
 
diff --git a/spec/services/activitypub/fetch_featured_tags_collection_service_spec.rb b/spec/services/activitypub/fetch_featured_tags_collection_service_spec.rb
index 6ca22c9fc..071e4d92d 100644
--- a/spec/services/activitypub/fetch_featured_tags_collection_service_spec.rb
+++ b/spec/services/activitypub/fetch_featured_tags_collection_service_spec.rb
@@ -1,6 +1,10 @@
+# frozen_string_literal: true
+
 require 'rails_helper'
 
 RSpec.describe ActivityPub::FetchFeaturedTagsCollectionService, type: :service do
+  subject { described_class.new }
+
   let(:collection_url) { 'https://example.com/account/tags' }
   let(:actor) { Fabricate(:account, domain: 'example.com', uri: 'https://example.com/account') }
 
@@ -21,15 +25,13 @@ RSpec.describe ActivityPub::FetchFeaturedTagsCollectionService, type: :service d
     }.with_indifferent_access
   end
 
-  subject { described_class.new }
-
   shared_examples 'sets featured tags' do
     before do
       subject.call(actor, collection_url)
     end
 
     it 'sets expected tags as pinned tags' do
-      expect(actor.featured_tags.map(&:display_name)).to match_array ['Foo', 'bar', 'baZ']
+      expect(actor.featured_tags.map(&:display_name)).to match_array %w(Foo bar baZ)
     end
   end
 
@@ -81,7 +83,7 @@ RSpec.describe ActivityPub::FetchFeaturedTagsCollectionService, type: :service d
             type: 'CollectionPage',
             partOf: collection_url,
             items: items,
-          }
+          },
         }.with_indifferent_access
       end
 
diff --git a/spec/services/activitypub/fetch_remote_account_service_spec.rb b/spec/services/activitypub/fetch_remote_account_service_spec.rb
index ec6f1f41d..868bc2a58 100644
--- a/spec/services/activitypub/fetch_remote_account_service_spec.rb
+++ b/spec/services/activitypub/fetch_remote_account_service_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
 require 'rails_helper'
 
 RSpec.describe ActivityPub::FetchRemoteAccountService, type: :service do
diff --git a/spec/services/activitypub/fetch_remote_actor_service_spec.rb b/spec/services/activitypub/fetch_remote_actor_service_spec.rb
index 20117c66d..a72c6941e 100644
--- a/spec/services/activitypub/fetch_remote_actor_service_spec.rb
+++ b/spec/services/activitypub/fetch_remote_actor_service_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
 require 'rails_helper'
 
 RSpec.describe ActivityPub::FetchRemoteActorService, type: :service do
diff --git a/spec/services/activitypub/fetch_remote_key_service_spec.rb b/spec/services/activitypub/fetch_remote_key_service_spec.rb
index 3186c4270..0ec0c2736 100644
--- a/spec/services/activitypub/fetch_remote_key_service_spec.rb
+++ b/spec/services/activitypub/fetch_remote_key_service_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
 require 'rails_helper'
 
 RSpec.describe ActivityPub::FetchRemoteKeyService, type: :service do
diff --git a/spec/services/activitypub/fetch_remote_status_service_spec.rb b/spec/services/activitypub/fetch_remote_status_service_spec.rb
index 7359ca0b4..1c39db21f 100644
--- a/spec/services/activitypub/fetch_remote_status_service_spec.rb
+++ b/spec/services/activitypub/fetch_remote_status_service_spec.rb
@@ -1,8 +1,12 @@
+# frozen_string_literal: true
+
 require 'rails_helper'
 
 RSpec.describe ActivityPub::FetchRemoteStatusService, type: :service do
   include ActionView::Helpers::TextHelper
 
+  subject { described_class.new }
+
   let!(:sender) { Fabricate(:account, domain: 'foo.bar', uri: 'https://foo.bar') }
   let!(:recipient) { Fabricate(:account) }
 
@@ -11,15 +15,13 @@ RSpec.describe ActivityPub::FetchRemoteStatusService, type: :service do
   let(:note) do
     {
       '@context': 'https://www.w3.org/ns/activitystreams',
-      id: "https://foo.bar/@foo/1234",
+      id: 'https://foo.bar/@foo/1234',
       type: 'Note',
       content: 'Lorem ipsum',
       attributedTo: ActivityPub::TagManager.instance.uri_for(sender),
     }
   end
 
-  subject { described_class.new }
-
   before do
     stub_request(:get, 'https://foo.bar/watch?v=12345').to_return(status: 404, body: '')
     stub_request(:get, object[:id]).to_return(body: Oj.dump(object))
@@ -46,7 +48,7 @@ RSpec.describe ActivityPub::FetchRemoteStatusService, type: :service do
       let(:object) do
         {
           '@context': 'https://www.w3.org/ns/activitystreams',
-          id: "https://foo.bar/@foo/1234",
+          id: 'https://foo.bar/@foo/1234',
           type: 'Video',
           name: 'Nyan Cat 10 hours remix',
           attributedTo: ActivityPub::TagManager.instance.uri_for(sender),
@@ -54,13 +56,13 @@ RSpec.describe ActivityPub::FetchRemoteStatusService, type: :service do
             {
               type: 'Link',
               mimeType: 'application/x-bittorrent',
-              href: "https://foo.bar/12345.torrent",
+              href: 'https://foo.bar/12345.torrent',
             },
 
             {
               type: 'Link',
               mimeType: 'text/html',
-              href: "https://foo.bar/watch?v=12345",
+              href: 'https://foo.bar/watch?v=12345',
             },
           ],
         }
@@ -70,8 +72,8 @@ RSpec.describe ActivityPub::FetchRemoteStatusService, type: :service do
         status = sender.statuses.first
 
         expect(status).to_not be_nil
-        expect(status.url).to eq "https://foo.bar/watch?v=12345"
-        expect(strip_tags(status.text)).to eq "Nyan Cat 10 hours remixhttps://foo.bar/watch?v=12345"
+        expect(status.url).to eq 'https://foo.bar/watch?v=12345'
+        expect(strip_tags(status.text)).to eq 'Nyan Cat 10 hours remixhttps://foo.bar/watch?v=12345'
       end
     end
 
@@ -79,7 +81,7 @@ RSpec.describe ActivityPub::FetchRemoteStatusService, type: :service do
       let(:object) do
         {
           '@context': 'https://www.w3.org/ns/activitystreams',
-          id: "https://foo.bar/@foo/1234",
+          id: 'https://foo.bar/@foo/1234',
           type: 'Audio',
           name: 'Nyan Cat 10 hours remix',
           attributedTo: ActivityPub::TagManager.instance.uri_for(sender),
@@ -87,13 +89,13 @@ RSpec.describe ActivityPub::FetchRemoteStatusService, type: :service do
             {
               type: 'Link',
               mimeType: 'application/x-bittorrent',
-              href: "https://foo.bar/12345.torrent",
+              href: 'https://foo.bar/12345.torrent',
             },
 
             {
               type: 'Link',
               mimeType: 'text/html',
-              href: "https://foo.bar/watch?v=12345",
+              href: 'https://foo.bar/watch?v=12345',
             },
           ],
         }
@@ -103,8 +105,8 @@ RSpec.describe ActivityPub::FetchRemoteStatusService, type: :service do
         status = sender.statuses.first
 
         expect(status).to_not be_nil
-        expect(status.url).to eq "https://foo.bar/watch?v=12345"
-        expect(strip_tags(status.text)).to eq "Nyan Cat 10 hours remixhttps://foo.bar/watch?v=12345"
+        expect(status.url).to eq 'https://foo.bar/watch?v=12345'
+        expect(strip_tags(status.text)).to eq 'Nyan Cat 10 hours remixhttps://foo.bar/watch?v=12345'
       end
     end
 
@@ -112,10 +114,10 @@ RSpec.describe ActivityPub::FetchRemoteStatusService, type: :service do
       let(:object) do
         {
           '@context': 'https://www.w3.org/ns/activitystreams',
-          id: "https://foo.bar/@foo/1234",
+          id: 'https://foo.bar/@foo/1234',
           type: 'Event',
           name: "Let's change the world",
-          attributedTo: ActivityPub::TagManager.instance.uri_for(sender)
+          attributedTo: ActivityPub::TagManager.instance.uri_for(sender),
         }
       end
 
@@ -123,7 +125,7 @@ RSpec.describe ActivityPub::FetchRemoteStatusService, type: :service do
         status = sender.statuses.first
 
         expect(status).to_not be_nil
-        expect(status.url).to eq "https://foo.bar/@foo/1234"
+        expect(status.url).to eq 'https://foo.bar/@foo/1234'
         expect(strip_tags(status.text)).to eq "Let's change the worldhttps://foo.bar/@foo/1234"
       end
     end
@@ -132,7 +134,7 @@ RSpec.describe ActivityPub::FetchRemoteStatusService, type: :service do
       let(:note) do
         {
           '@context': 'https://www.w3.org/ns/activitystreams',
-          id: "https://real.address/@foo/1234",
+          id: 'https://real.address/@foo/1234',
           type: 'Note',
           content: 'Lorem ipsum',
           attributedTo: ActivityPub::TagManager.instance.uri_for(sender),
@@ -154,7 +156,7 @@ RSpec.describe ActivityPub::FetchRemoteStatusService, type: :service do
       let(:object) do
         {
           '@context': 'https://www.w3.org/ns/activitystreams',
-          id: "https://foo.bar/@foo/1234/create",
+          id: 'https://foo.bar/@foo/1234/create',
           type: 'Create',
           actor: ActivityPub::TagManager.instance.uri_for(sender),
           object: note,
@@ -174,11 +176,11 @@ RSpec.describe ActivityPub::FetchRemoteStatusService, type: :service do
       let(:object) do
         {
           '@context': 'https://www.w3.org/ns/activitystreams',
-          id: "https://foo.bar/@foo/1234/create",
+          id: 'https://foo.bar/@foo/1234/create',
           type: 'Create',
           actor: ActivityPub::TagManager.instance.uri_for(sender),
           object: {
-            id: "https://real.address/@foo/1234",
+            id: 'https://real.address/@foo/1234',
             type: 'Note',
             content: 'Lorem ipsum',
             attributedTo: ActivityPub::TagManager.instance.uri_for(sender),
@@ -208,7 +210,7 @@ RSpec.describe ActivityPub::FetchRemoteStatusService, type: :service do
         let(:object) do
           {
             '@context': 'https://www.w3.org/ns/activitystreams',
-            id: "https://foo.bar/@foo/1234/create",
+            id: 'https://foo.bar/@foo/1234/create',
             type: 'Create',
             actor: ActivityPub::TagManager.instance.uri_for(sender),
             object: note.merge(updated: '2021-09-08T22:39:25Z'),
@@ -223,4 +225,98 @@ RSpec.describe ActivityPub::FetchRemoteStatusService, type: :service do
       end
     end
   end
+
+  context 'statuses referencing other statuses' do
+    before do
+      stub_const 'ActivityPub::FetchRemoteStatusService::DISCOVERIES_PER_REQUEST', 5
+    end
+
+    context 'using inReplyTo' do
+      let(:object) do
+        {
+          '@context': 'https://www.w3.org/ns/activitystreams',
+          id: 'https://foo.bar/@foo/1',
+          type: 'Note',
+          content: 'Lorem ipsum',
+          inReplyTo: 'https://foo.bar/@foo/2',
+          attributedTo: ActivityPub::TagManager.instance.uri_for(sender),
+        }
+      end
+
+      before do
+        8.times do |i|
+          status_json = {
+            '@context': 'https://www.w3.org/ns/activitystreams',
+            id: "https://foo.bar/@foo/#{i}",
+            type: 'Note',
+            content: 'Lorem ipsum',
+            inReplyTo: "https://foo.bar/@foo/#{i + 1}",
+            attributedTo: ActivityPub::TagManager.instance.uri_for(sender),
+            to: 'as:Public',
+          }.with_indifferent_access
+          stub_request(:get, "https://foo.bar/@foo/#{i}").to_return(status: 200, body: status_json.to_json, headers: { 'Content-Type': 'application/activity+json' })
+        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)
+      end
+    end
+
+    context 'using replies' do
+      let(:object) do
+        {
+          '@context': 'https://www.w3.org/ns/activitystreams',
+          id: 'https://foo.bar/@foo/1',
+          type: 'Note',
+          content: 'Lorem ipsum',
+          replies: {
+            type: 'Collection',
+            id: 'https://foo.bar/@foo/1/replies',
+            first: {
+              type: 'CollectionPage',
+              partOf: 'https://foo.bar/@foo/1/replies',
+              items: ['https://foo.bar/@foo/2'],
+            },
+          },
+          attributedTo: ActivityPub::TagManager.instance.uri_for(sender),
+        }
+      end
+
+      before do
+        8.times do |i|
+          status_json = {
+            '@context': 'https://www.w3.org/ns/activitystreams',
+            id: "https://foo.bar/@foo/#{i}",
+            type: 'Note',
+            content: 'Lorem ipsum',
+            replies: {
+              type: 'Collection',
+              id: "https://foo.bar/@foo/#{i}/replies",
+              first: {
+                type: 'CollectionPage',
+                partOf: "https://foo.bar/@foo/#{i}/replies",
+                items: ["https://foo.bar/@foo/#{i + 1}"],
+              },
+            },
+            attributedTo: ActivityPub::TagManager.instance.uri_for(sender),
+            to: 'as:Public',
+          }.with_indifferent_access
+          stub_request(:get, "https://foo.bar/@foo/#{i}").to_return(status: 200, body: status_json.to_json, headers: { 'Content-Type': 'application/activity+json' })
+        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)
+      end
+    end
+  end
 end
diff --git a/spec/services/activitypub/fetch_replies_service_spec.rb b/spec/services/activitypub/fetch_replies_service_spec.rb
index fe49b18c1..bf8e29676 100644
--- a/spec/services/activitypub/fetch_replies_service_spec.rb
+++ b/spec/services/activitypub/fetch_replies_service_spec.rb
@@ -1,6 +1,10 @@
+# frozen_string_literal: true
+
 require 'rails_helper'
 
 RSpec.describe ActivityPub::FetchRepliesService, type: :service do
+  subject { described_class.new }
+
   let(:actor)          { Fabricate(:account, domain: 'example.com', uri: 'http://example.com/account') }
   let(:status)         { Fabricate(:status, account: actor) }
   let(:collection_uri) { 'http://example.com/replies/1' }
@@ -28,8 +32,6 @@ RSpec.describe ActivityPub::FetchRepliesService, type: :service do
     }.with_indifferent_access
   end
 
-  subject { described_class.new }
-
   describe '#call' do
     context 'when the payload is a Collection with inlined replies' do
       context 'when passing the collection itself' do
@@ -90,7 +92,7 @@ RSpec.describe ActivityPub::FetchRepliesService, type: :service do
             type: 'CollectionPage',
             partOf: collection_uri,
             items: items,
-          }
+          },
         }.with_indifferent_access
       end
 
diff --git a/spec/services/activitypub/process_account_service_spec.rb b/spec/services/activitypub/process_account_service_spec.rb
index 2b20d17b1..491b8ed5a 100644
--- a/spec/services/activitypub/process_account_service_spec.rb
+++ b/spec/services/activitypub/process_account_service_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
 require 'rails_helper'
 
 RSpec.describe ActivityPub::ProcessAccountService, type: :service do
@@ -12,7 +14,7 @@ RSpec.describe ActivityPub::ProcessAccountService, type: :service do
         attachment: [
           { type: 'PropertyValue', name: 'Pronouns', value: 'They/them' },
           { type: 'PropertyValue', name: 'Occupation', value: 'Unit test' },
-          { type: 'PropertyValue', name: 'non-string', value: ['foo', 'bar'] },
+          { type: 'PropertyValue', name: 'non-string', value: %w(foo bar) },
         ],
       }.with_indifferent_access
     end
@@ -31,6 +33,8 @@ RSpec.describe ActivityPub::ProcessAccountService, type: :service do
   end
 
   context 'when account is not suspended' do
+    subject { described_class.new.call('alice', 'example.com', payload) }
+
     let!(:account) { Fabricate(:account, username: 'alice', domain: 'example.com') }
 
     let(:payload) do
@@ -46,8 +50,6 @@ RSpec.describe ActivityPub::ProcessAccountService, type: :service do
       allow(Admin::SuspensionWorker).to receive(:perform_async)
     end
 
-    subject { described_class.new.call('alice', 'example.com', payload) }
-
     it 'suspends account remotely' do
       expect(subject.suspended?).to be true
       expect(subject.suspension_origin_remote?).to be true
@@ -60,6 +62,8 @@ RSpec.describe ActivityPub::ProcessAccountService, type: :service do
   end
 
   context 'when account is suspended' do
+    subject { described_class.new.call('alice', 'example.com', payload) }
+
     let!(:account) { Fabricate(:account, username: 'alice', domain: 'example.com', display_name: '') }
 
     let(:payload) do
@@ -78,8 +82,6 @@ RSpec.describe ActivityPub::ProcessAccountService, type: :service do
       account.suspend!(origin: suspension_origin)
     end
 
-    subject { described_class.new.call('alice', 'example.com', payload) }
-
     context 'locally' do
       let(:suspension_origin) { :local }
 
@@ -172,10 +174,10 @@ RSpec.describe ActivityPub::ProcessAccountService, type: :service do
             {
               type: 'Mention',
               href: "https://foo.test/users/#{i + 1}",
-              name: "@user#{i + 1 }",
-            }
+              name: "@user#{i + 1}",
+            },
           ],
-          to: [ 'as:Public', "https://foo.test/users/#{i + 1}" ]
+          to: ['as:Public', "https://foo.test/users/#{i + 1}"],
         }.with_indifferent_access
         featured_json = {
           '@context': ['https://www.w3.org/ns/activitystreams'],
diff --git a/spec/services/activitypub/process_collection_service_spec.rb b/spec/services/activitypub/process_collection_service_spec.rb
index 093a188a2..1433d0c50 100644
--- a/spec/services/activitypub/process_collection_service_spec.rb
+++ b/spec/services/activitypub/process_collection_service_spec.rb
@@ -1,6 +1,10 @@
+# frozen_string_literal: true
+
 require 'rails_helper'
 
 RSpec.describe ActivityPub::ProcessCollectionService, type: :service do
+  subject { described_class.new }
+
   let(:actor) { Fabricate(:account, domain: 'example.com', uri: 'http://example.com/account') }
 
   let(:payload) do
@@ -19,8 +23,6 @@ RSpec.describe ActivityPub::ProcessCollectionService, type: :service do
 
   let(:json) { Oj.dump(payload) }
 
-  subject { described_class.new }
-
   describe '#call' do
     context 'when actor is suspended' do
       before do
@@ -39,7 +41,7 @@ RSpec.describe ActivityPub::ProcessCollectionService, type: :service do
           end
 
           it 'does not process payload' do
-            expect(ActivityPub::Activity).not_to receive(:factory)
+            expect(ActivityPub::Activity).to_not receive(:factory)
             subject.call(json, actor)
           end
         end
@@ -69,7 +71,7 @@ RSpec.describe ActivityPub::ProcessCollectionService, type: :service do
 
       it 'does not process payload if no signature exists' do
         expect_any_instance_of(ActivityPub::LinkedDataSignature).to receive(:verify_actor!).and_return(nil)
-        expect(ActivityPub::Activity).not_to receive(:factory)
+        expect(ActivityPub::Activity).to_not receive(:factory)
 
         subject.call(json, forwarder)
       end
@@ -87,7 +89,7 @@ RSpec.describe ActivityPub::ProcessCollectionService, type: :service do
         payload['signature'] = { 'type' => 'RsaSignature2017' }
 
         expect_any_instance_of(ActivityPub::LinkedDataSignature).to receive(:verify_actor!).and_return(nil)
-        expect(ActivityPub::Activity).not_to receive(:factory)
+        expect(ActivityPub::Activity).to_not receive(:factory)
 
         subject.call(json, forwarder)
       end
@@ -95,11 +97,11 @@ RSpec.describe ActivityPub::ProcessCollectionService, type: :service do
       context 'when receiving a fabricated status' do
         let!(:actor) do
           Fabricate(:account,
-            username: 'bob',
-            domain: 'example.com',
-            uri: 'https://example.com/users/bob',
-            public_key: "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuuYyoyfsRkYnXRotMsId\nW3euBDDfiv9oVqOxUVC7bhel8KednIMrMCRWFAkgJhbrlzbIkjVr68o1MP9qLcn7\nCmH/BXHp7yhuFTr4byjdJKpwB+/i2jNEsvDH5jR8WTAeTCe0x/QHg21V3F7dSI5m\nCCZ/1dSIyOXLRTWVlfDlm3rE4ntlCo+US3/7oSWbg/4/4qEnt1HC32kvklgScxua\n4LR5ATdoXa5bFoopPWhul7MJ6NyWCyQyScUuGdlj8EN4kmKQJvphKHrI9fvhgOuG\nTvhTR1S5InA4azSSchY0tXEEw/VNxraeX0KPjbgr6DPcwhPd/m0nhVDq0zVyVBBD\nMwIDAQAB\n-----END PUBLIC KEY-----\n",
-            private_key: nil)
+                    username: 'bob',
+                    domain: 'example.com',
+                    uri: 'https://example.com/users/bob',
+                    public_key: "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuuYyoyfsRkYnXRotMsId\nW3euBDDfiv9oVqOxUVC7bhel8KednIMrMCRWFAkgJhbrlzbIkjVr68o1MP9qLcn7\nCmH/BXHp7yhuFTr4byjdJKpwB+/i2jNEsvDH5jR8WTAeTCe0x/QHg21V3F7dSI5m\nCCZ/1dSIyOXLRTWVlfDlm3rE4ntlCo+US3/7oSWbg/4/4qEnt1HC32kvklgScxua\n4LR5ATdoXa5bFoopPWhul7MJ6NyWCyQyScUuGdlj8EN4kmKQJvphKHrI9fvhgOuG\nTvhTR1S5InA4azSSchY0tXEEw/VNxraeX0KPjbgr6DPcwhPd/m0nhVDq0zVyVBBD\nMwIDAQAB\n-----END PUBLIC KEY-----\n",
+                    private_key: nil)
         end
 
         let(:payload) do
@@ -107,48 +109,48 @@ RSpec.describe ActivityPub::ProcessCollectionService, type: :service do
             '@context': [
               'https://www.w3.org/ns/activitystreams',
               nil,
-              {'object': 'https://www.w3.org/ns/activitystreams#object'}
+              { object: 'https://www.w3.org/ns/activitystreams#object' },
             ],
-            'id': 'https://example.com/users/bob/fake-status/activity',
-            'type': 'Create',
-            'actor': 'https://example.com/users/bob',
-            'published': '2022-01-22T15:00:00Z',
-            'to': [
-              'https://www.w3.org/ns/activitystreams#Public'
+            id: 'https://example.com/users/bob/fake-status/activity',
+            type: 'Create',
+            actor: 'https://example.com/users/bob',
+            published: '2022-01-22T15:00:00Z',
+            to: [
+              'https://www.w3.org/ns/activitystreams#Public',
             ],
-            'cc': [
-              'https://example.com/users/bob/followers'
+            cc: [
+              'https://example.com/users/bob/followers',
             ],
-            'signature': {
-              'type': 'RsaSignature2017',
-              'creator': 'https://example.com/users/bob#main-key',
-              'created': '2022-03-09T21:57:25Z',
-              'signatureValue': 'WculK0LelTQ0MvGwU9TPoq5pFzFfGYRDCJqjZ232/Udj4CHqDTGOSw5UTDLShqBOyycCkbZGrQwXG+dpyDpQLSe1UVPZ5TPQtc/9XtI57WlS2nMNpdvRuxGnnb2btPdesXZ7n3pCxo0zjaXrJMe0mqQh5QJO22mahb4bDwwmfTHgbD3nmkD+fBfGi+UV2qWwqr+jlV4L4JqNkh0gWljF5KTePLRRZCuWiQ/FAt7c67636cdIPf7fR+usjuZltTQyLZKEGuK8VUn2Gkfsx5qns7Vcjvlz1JqlAjyO8HPBbzTTHzUG2nUOIgC3PojCSWv6mNTmRGoLZzOscCAYQA6cKw=='
+            signature: {
+              type: 'RsaSignature2017',
+              creator: 'https://example.com/users/bob#main-key',
+              created: '2022-03-09T21:57:25Z',
+              signatureValue: 'WculK0LelTQ0MvGwU9TPoq5pFzFfGYRDCJqjZ232/Udj4CHqDTGOSw5UTDLShqBOyycCkbZGrQwXG+dpyDpQLSe1UVPZ5TPQtc/9XtI57WlS2nMNpdvRuxGnnb2btPdesXZ7n3pCxo0zjaXrJMe0mqQh5QJO22mahb4bDwwmfTHgbD3nmkD+fBfGi+UV2qWwqr+jlV4L4JqNkh0gWljF5KTePLRRZCuWiQ/FAt7c67636cdIPf7fR+usjuZltTQyLZKEGuK8VUn2Gkfsx5qns7Vcjvlz1JqlAjyO8HPBbzTTHzUG2nUOIgC3PojCSWv6mNTmRGoLZzOscCAYQA6cKw==',
             },
             '@id': 'https://example.com/users/bob/statuses/107928807471117876/activity',
             '@type': 'https://www.w3.org/ns/activitystreams#Create',
             'https://www.w3.org/ns/activitystreams#actor': {
-              '@id': 'https://example.com/users/bob'
+              '@id': 'https://example.com/users/bob',
             },
             'https://www.w3.org/ns/activitystreams#cc': {
-              '@id': 'https://example.com/users/bob/followers'
+              '@id': 'https://example.com/users/bob/followers',
             },
-            'object': {
-              'id': 'https://example.com/users/bob/fake-status',
-              'type': 'Note',
-              'published': '2022-01-22T15:00:00Z',
-              'url': 'https://www.youtube.com/watch?v=dQw4w9WgXcQ&feature=puck-was-here',
-              'attributedTo': 'https://example.com/users/bob',
-              'to': [
-                'https://www.w3.org/ns/activitystreams#Public'
+            object: {
+              id: 'https://example.com/users/bob/fake-status',
+              type: 'Note',
+              published: '2022-01-22T15:00:00Z',
+              url: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ&feature=puck-was-here',
+              attributedTo: 'https://example.com/users/bob',
+              to: [
+                'https://www.w3.org/ns/activitystreams#Public',
               ],
-              'cc': [
-                'https://example.com/users/bob/followers'
+              cc: [
+                'https://example.com/users/bob/followers',
               ],
-              'sensitive': false,
-              'atomUri': 'https://example.com/users/bob/fake-status',
-              'conversation': 'tag:example.com,2022-03-09:objectId=15:objectType=Conversation',
-              'content': '<p>puck was here</p>',
+              sensitive: false,
+              atomUri: 'https://example.com/users/bob/fake-status',
+              conversation: 'tag:example.com,2022-03-09:objectId=15:objectType=Conversation',
+              content: '<p>puck was here</p>',
 
               '@id': 'https://example.com/users/bob/statuses/107928807471117876',
               '@type': 'https://www.w3.org/ns/activitystreams#Note',
@@ -156,21 +158,21 @@ RSpec.describe ActivityPub::ProcessCollectionService, type: :service do
               'http://ostatus.org#conversation': 'tag:example.com,2022-03-09:objectId=15:objectType=Conversation',
               'https://www.w3.org/ns/activitystreams#attachment': [],
               'https://www.w3.org/ns/activitystreams#attributedTo': {
-                '@id': 'https://example.com/users/bob'
+                '@id': 'https://example.com/users/bob',
               },
               'https://www.w3.org/ns/activitystreams#cc': {
-                '@id': 'https://example.com/users/bob/followers'
+                '@id': 'https://example.com/users/bob/followers',
               },
               'https://www.w3.org/ns/activitystreams#content': [
                 '<p>hello world</p>',
                 {
                   '@value': '<p>hello world</p>',
-                  '@language': 'en'
-                }
+                  '@language': 'en',
+                },
               ],
               'https://www.w3.org/ns/activitystreams#published': {
                 '@type': 'http://www.w3.org/2001/XMLSchema#dateTime',
-                '@value': '2022-03-09T21:55:07Z'
+                '@value': '2022-03-09T21:55:07Z',
               },
               'https://www.w3.org/ns/activitystreams#replies': {
                 '@id': 'https://example.com/users/bob/statuses/107928807471117876/replies',
@@ -179,51 +181,51 @@ RSpec.describe ActivityPub::ProcessCollectionService, type: :service do
                   '@type': 'https://www.w3.org/ns/activitystreams#CollectionPage',
                   'https://www.w3.org/ns/activitystreams#items': [],
                   'https://www.w3.org/ns/activitystreams#next': {
-                    '@id': 'https://example.com/users/bob/statuses/107928807471117876/replies?only_other_accounts=true&page=true'
+                    '@id': 'https://example.com/users/bob/statuses/107928807471117876/replies?only_other_accounts=true&page=true',
                   },
                   'https://www.w3.org/ns/activitystreams#partOf': {
-                    '@id': 'https://example.com/users/bob/statuses/107928807471117876/replies'
-                  }
-                }
+                    '@id': 'https://example.com/users/bob/statuses/107928807471117876/replies',
+                  },
+                },
               },
               'https://www.w3.org/ns/activitystreams#sensitive': false,
               'https://www.w3.org/ns/activitystreams#tag': [],
               'https://www.w3.org/ns/activitystreams#to': {
-                '@id': 'https://www.w3.org/ns/activitystreams#Public'
+                '@id': 'https://www.w3.org/ns/activitystreams#Public',
               },
               'https://www.w3.org/ns/activitystreams#url': {
-                '@id': 'https://example.com/@bob/107928807471117876'
-              }
+                '@id': 'https://example.com/@bob/107928807471117876',
+              },
             },
             'https://www.w3.org/ns/activitystreams#published': {
               '@type': 'http://www.w3.org/2001/XMLSchema#dateTime',
-              '@value': '2022-03-09T21:55:07Z'
+              '@value': '2022-03-09T21:55:07Z',
             },
             'https://www.w3.org/ns/activitystreams#to': {
-              '@id': 'https://www.w3.org/ns/activitystreams#Public'
-            }
+              '@id': 'https://www.w3.org/ns/activitystreams#Public',
+            },
           }
         end
 
         it 'does not process forged payload' do
-          expect(ActivityPub::Activity).not_to receive(:factory).with(
+          expect(ActivityPub::Activity).to_not receive(:factory).with(
             hash_including(
               'object' => hash_including(
                 'id' => 'https://example.com/users/bob/fake-status'
               )
             ),
-            anything(),
-            anything()
+            anything,
+            anything
           )
 
-          expect(ActivityPub::Activity).not_to receive(:factory).with(
+          expect(ActivityPub::Activity).to_not receive(:factory).with(
             hash_including(
               'object' => hash_including(
                 'content' => '<p>puck was here</p>'
               )
             ),
-            anything(),
-            anything()
+            anything,
+            anything
           )
 
           subject.call(json, forwarder)
diff --git a/spec/services/activitypub/process_status_update_service_spec.rb b/spec/services/activitypub/process_status_update_service_spec.rb
index 750369d57..e9f23b9cf 100644
--- a/spec/services/activitypub/process_status_update_service_spec.rb
+++ b/spec/services/activitypub/process_status_update_service_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
 require 'rails_helper'
 
 def poll_option_json(name, votes)
@@ -5,21 +7,9 @@ def poll_option_json(name, votes)
 end
 
 RSpec.describe ActivityPub::ProcessStatusUpdateService, type: :service do
-  let!(:status) { Fabricate(:status, text: 'Hello world', account: Fabricate(:account, domain: 'example.com')) }
-
-  let(:alice) { Fabricate(:account) }
-  let(:bob) { Fabricate(:account) }
-
-  let(:mentions) { [] }
-  let(:tags) { [] }
-  let(:media_attachments) { [] }
-
-  before do
-    mentions.each { |a| Fabricate(:mention, status: status, account: a) }
-    tags.each { |t| status.tags << t }
-    media_attachments.each { |m| status.media_attachments << m }
-  end
+  subject { described_class.new }
 
+  let!(:status) { Fabricate(:status, text: 'Hello world', account: Fabricate(:account, domain: 'example.com')) }
   let(:payload) do
     {
       '@context': 'https://www.w3.org/ns/activitystreams',
@@ -34,10 +24,20 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService, type: :service do
       ],
     }
   end
-
   let(:json) { Oj.load(Oj.dump(payload)) }
 
-  subject { described_class.new }
+  let(:alice) { Fabricate(:account) }
+  let(:bob) { Fabricate(:account) }
+
+  let(:mentions) { [] }
+  let(:tags) { [] }
+  let(:media_attachments) { [] }
+
+  before do
+    mentions.each { |a| Fabricate(:mention, status: status, account: a) }
+    tags.each { |t| status.tags << t }
+    media_attachments.each { |m| status.media_attachments << m }
+  end
 
   describe '#call' do
     it 'updates text' do
@@ -104,20 +104,19 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService, type: :service do
     end
 
     context 'when the status has not been explicitly edited and features a poll' do
-      let(:account)    { Fabricate(:account, domain: 'example.com') }
+      let(:account) { Fabricate(:account, domain: 'example.com') }
       let!(:expiration) { 10.days.from_now.utc }
       let!(:status) do
         Fabricate(:status,
-          text: 'Hello world',
-          account: account,
-          poll_attributes: {
-            options: %w(Foo Bar),
-            account: account,
-            multiple: false,
-            hide_totals: false,
-            expires_at: expiration
-          }
-        )
+                  text: 'Hello world',
+                  account: account,
+                  poll_attributes: {
+                    options: %w(Foo Bar),
+                    account: account,
+                    multiple: false,
+                    hide_totals: false,
+                    expires_at: expiration,
+                  })
       end
 
       let(:payload) do
@@ -156,20 +155,19 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService, type: :service do
     end
 
     context 'when the status changes a poll despite being not explicitly marked as updated' do
-      let(:account)    { Fabricate(:account, domain: 'example.com') }
+      let(:account) { Fabricate(:account, domain: 'example.com') }
       let!(:expiration) { 10.days.from_now.utc }
       let!(:status) do
         Fabricate(:status,
-          text: 'Hello world',
-          account: account,
-          poll_attributes: {
-            options: %w(Foo Bar),
-            account: account,
-            multiple: false,
-            hide_totals: false,
-            expires_at: expiration
-          }
-        )
+                  text: 'Hello world',
+                  account: account,
+                  poll_attributes: {
+                    options: %w(Foo Bar),
+                    account: account,
+                    multiple: false,
+                    hide_totals: false,
+                    expires_at: expiration,
+                  })
       end
 
       let(:payload) do
@@ -216,11 +214,11 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService, type: :service do
       end
 
       it 'does not create any edits' do
-        expect { subject.call(status, json) }.not_to change { status.reload.edits.pluck(&:id) }
+        expect { subject.call(status, json) }.to_not change { status.reload.edits.pluck(&:id) }
       end
 
       it 'does not update the text, spoiler_text or edited_at' do
-        expect { subject.call(status, json) }.not_to change { s = status.reload; [s.text, s.spoiler_text, s.edited_at] }
+        expect { subject.call(status, json) }.to_not change { s = status.reload; [s.text, s.spoiler_text, s.edited_at] }
       end
     end
 
@@ -344,7 +342,7 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService, type: :service do
           updated: '2021-09-08T22:39:25Z',
           attachment: [
             { type: 'Image', mediaType: 'image/png', url: 'https://example.com/foo.png' },
-          ]
+          ],
         }
       end
 
@@ -376,7 +374,7 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService, type: :service do
           updated: '2021-09-08T22:39:25Z',
           attachment: [
             { type: 'Image', mediaType: 'image/png', url: 'https://example.com/foo.png', name: 'A picture' },
-          ]
+          ],
         }
       end
 
@@ -414,7 +412,7 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService, type: :service do
       end
 
       it 'removes poll' do
-        expect(status.reload.poll).to eq nil
+        expect(status.reload.poll).to be_nil
       end
 
       it 'records media change in edit' do
diff --git a/spec/services/activitypub/synchronize_followers_service_spec.rb b/spec/services/activitypub/synchronize_followers_service_spec.rb
index 75dcf204b..c9a513e24 100644
--- a/spec/services/activitypub/synchronize_followers_service_spec.rb
+++ b/spec/services/activitypub/synchronize_followers_service_spec.rb
@@ -1,6 +1,10 @@
+# frozen_string_literal: true
+
 require 'rails_helper'
 
 RSpec.describe ActivityPub::SynchronizeFollowersService, type: :service do
+  subject { described_class.new }
+
   let(:actor)          { Fabricate(:account, domain: 'example.com', uri: 'http://example.com/account', inbox_url: 'http://example.com/inbox') }
   let(:alice)          { Fabricate(:account, username: 'alice') }
   let(:bob)            { Fabricate(:account, username: 'bob') }
@@ -25,8 +29,6 @@ RSpec.describe ActivityPub::SynchronizeFollowersService, type: :service do
     }.with_indifferent_access
   end
 
-  subject { described_class.new }
-
   shared_examples 'synchronizes followers' do
     before do
       alice.follow!(actor)
@@ -91,7 +93,7 @@ RSpec.describe ActivityPub::SynchronizeFollowersService, type: :service do
             type: 'CollectionPage',
             partOf: collection_uri,
             items: items,
-          }
+          },
         }.with_indifferent_access
       end