From 76c2c5c748ba47c2b7bc13570cd4301516290d90 Mon Sep 17 00:00:00 2001
From: Matt Jankowski <matt@jankowski.online>
Date: Wed, 17 Jul 2024 04:09:34 -0400
Subject: [PATCH] Reduce extra round trips in `activitypub` controller specs
 (#31041)

---
 .../collections_controller_spec.rb            |  32 ++----
 ...lowers_synchronizations_controller_spec.rb |  27 ++---
 .../activitypub/outboxes_controller_spec.rb   | 107 +++++-------------
 .../activitypub/replies_controller_spec.rb    |  16 +--
 4 files changed, 56 insertions(+), 126 deletions(-)

diff --git a/spec/controllers/activitypub/collections_controller_spec.rb b/spec/controllers/activitypub/collections_controller_spec.rb
index 11ef03c84..a5718fbd7 100644
--- a/spec/controllers/activitypub/collections_controller_spec.rb
+++ b/spec/controllers/activitypub/collections_controller_spec.rb
@@ -25,14 +25,12 @@ RSpec.describe ActivityPub::CollectionsController do
       context 'without signature' do
         let(:remote_account) { nil }
 
-        it 'returns http success and correct media type' do
-          expect(response).to have_http_status(200)
-          expect(response.media_type).to eq 'application/activity+json'
-        end
-
         it_behaves_like 'cacheable response'
 
-        it 'returns orderedItems with correct items' do
+        it 'returns http success and correct media type and correct items' do
+          expect(response).to have_http_status(200)
+          expect(response.media_type).to eq 'application/activity+json'
+
           expect(body_as_json[:orderedItems])
             .to be_an(Array)
             .and have_attributes(size: 3)
@@ -66,14 +64,12 @@ RSpec.describe ActivityPub::CollectionsController do
         let(:remote_account) { Fabricate(:account, domain: 'example.com') }
 
         context 'when getting a featured resource' do
-          it 'returns http success and correct media type' do
-            expect(response).to have_http_status(200)
-            expect(response.media_type).to eq 'application/activity+json'
-          end
-
           it_behaves_like 'cacheable response'
 
-          it 'returns orderedItems with expected items' do
+          it 'returns http success and correct media type and expected items' do
+            expect(response).to have_http_status(200)
+            expect(response.media_type).to eq 'application/activity+json'
+
             expect(body_as_json[:orderedItems])
               .to be_an(Array)
               .and have_attributes(size: 3)
@@ -92,16 +88,14 @@ RSpec.describe ActivityPub::CollectionsController do
               account.block!(remote_account)
             end
 
-            it 'returns http success and correct media type and cache headers' do
+            it 'returns http success and correct media type and cache headers and empty items' do
               expect(response).to have_http_status(200)
               expect(response.media_type).to eq 'application/activity+json'
               expect(response.headers['Cache-Control']).to include 'private'
-            end
 
-            it 'returns empty orderedItems' do
               expect(body_as_json[:orderedItems])
                 .to be_an(Array)
-                .and have_attributes(size: 0)
+                .and be_empty
             end
           end
 
@@ -110,16 +104,14 @@ RSpec.describe ActivityPub::CollectionsController do
               account.block_domain!(remote_account.domain)
             end
 
-            it 'returns http success and correct media type and cache headers' do
+            it 'returns http success and correct media type and cache headers and empty items' do
               expect(response).to have_http_status(200)
               expect(response.media_type).to eq 'application/activity+json'
               expect(response.headers['Cache-Control']).to include 'private'
-            end
 
-            it 'returns empty orderedItems' do
               expect(body_as_json[:orderedItems])
                 .to be_an(Array)
-                .and have_attributes(size: 0)
+                .and be_empty
             end
           end
         end
diff --git a/spec/controllers/activitypub/followers_synchronizations_controller_spec.rb b/spec/controllers/activitypub/followers_synchronizations_controller_spec.rb
index b50c7b9cd..c030078d4 100644
--- a/spec/controllers/activitypub/followers_synchronizations_controller_spec.rb
+++ b/spec/controllers/activitypub/followers_synchronizations_controller_spec.rb
@@ -37,25 +37,18 @@ RSpec.describe ActivityPub::FollowersSynchronizationsController do
       let(:body) { body_as_json }
       let(:remote_account) { Fabricate(:account, domain: 'example.com', uri: 'https://example.com/instance') }
 
-      it 'returns http success' do
+      it 'returns http success and cache control and activity json types and correct items' do
         expect(response).to have_http_status(200)
-      end
-
-      it 'returns application/activity+json' do
-        expect(response.media_type).to eq 'application/activity+json'
-      end
-
-      it 'returns orderedItems with followers from example.com' do
-        expect(body[:orderedItems]).to be_an Array
-        expect(body[:orderedItems]).to contain_exactly(
-          follower_example_com_instance_actor.uri,
-          follower_example_com_user_a.uri,
-          follower_example_com_user_b.uri
-        )
-      end
-
-      it 'returns private Cache-Control header' do
         expect(response.headers['Cache-Control']).to eq 'max-age=0, private'
+        expect(response.media_type).to eq 'application/activity+json'
+
+        expect(body[:orderedItems])
+          .to be_an(Array)
+          .and contain_exactly(
+            follower_example_com_instance_actor.uri,
+            follower_example_com_user_a.uri,
+            follower_example_com_user_b.uri
+          )
       end
 
       context 'when account is permanently suspended' do
diff --git a/spec/controllers/activitypub/outboxes_controller_spec.rb b/spec/controllers/activitypub/outboxes_controller_spec.rb
index ead231f29..3c8e8e399 100644
--- a/spec/controllers/activitypub/outboxes_controller_spec.rb
+++ b/spec/controllers/activitypub/outboxes_controller_spec.rb
@@ -25,22 +25,13 @@ RSpec.describe ActivityPub::OutboxesController do
       context 'with page not requested' do
         let(:page) { nil }
 
-        it 'returns http success' do
-          expect(response).to have_http_status(200)
-        end
-
-        it 'returns application/activity+json' do
-          expect(response.media_type).to eq 'application/activity+json'
-        end
-
-        it 'returns totalItems' do
-          expect(body[:totalItems]).to eq 4
-        end
-
         it_behaves_like 'cacheable response'
 
-        it 'does not have a Vary header' do
+        it 'returns http success and correct media type and headers and items count' do
+          expect(response).to have_http_status(200)
+          expect(response.media_type).to eq 'application/activity+json'
           expect(response.headers['Vary']).to be_nil
+          expect(body[:totalItems]).to eq 4
         end
 
         context 'when account is permanently suspended' do
@@ -68,26 +59,18 @@ RSpec.describe ActivityPub::OutboxesController do
       context 'with page requested' do
         let(:page) { 'true' }
 
-        it 'returns http success' do
+        it_behaves_like 'cacheable response'
+
+        it 'returns http success and correct media type and vary header and items' do
           expect(response).to have_http_status(200)
-        end
-
-        it 'returns application/activity+json' do
           expect(response.media_type).to eq 'application/activity+json'
-        end
+          expect(response.headers['Vary']).to include 'Signature'
 
-        it 'returns orderedItems with public or unlisted statuses' do
           expect(body[:orderedItems]).to be_an Array
           expect(body[:orderedItems].size).to eq 2
           expect(body[:orderedItems].all? { |item| targets_public_collection?(item) }).to be true
         end
 
-        it_behaves_like 'cacheable response'
-
-        it 'returns Vary header with Signature' do
-          expect(response.headers['Vary']).to include 'Signature'
-        end
-
         context 'when account is permanently suspended' do
           before do
             account.suspend!
@@ -120,23 +103,14 @@ RSpec.describe ActivityPub::OutboxesController do
           get :show, params: { account_username: account.username, page: page }
         end
 
-        it 'returns http success' do
+        it 'returns http success and correct media type and headers and items' do
           expect(response).to have_http_status(200)
-        end
-
-        it 'returns application/activity+json' do
           expect(response.media_type).to eq 'application/activity+json'
-        end
-
-        it 'returns orderedItems with public or unlisted statuses' do
-          json = body_as_json
-          expect(json[:orderedItems]).to be_an Array
-          expect(json[:orderedItems].size).to eq 2
-          expect(json[:orderedItems].all? { |item| targets_public_collection?(item) }).to be true
-        end
-
-        it 'returns private Cache-Control header' do
           expect(response.headers['Cache-Control']).to eq 'max-age=60, private'
+
+          expect(body_as_json[:orderedItems]).to be_an Array
+          expect(body_as_json[:orderedItems].size).to eq 2
+          expect(body_as_json[:orderedItems].all? { |item| targets_public_collection?(item) }).to be true
         end
       end
 
@@ -146,23 +120,14 @@ RSpec.describe ActivityPub::OutboxesController do
           get :show, params: { account_username: account.username, page: page }
         end
 
-        it 'returns http success' do
+        it 'returns http success and correct media type and headers and items' do
           expect(response).to have_http_status(200)
-        end
-
-        it 'returns application/activity+json' do
           expect(response.media_type).to eq 'application/activity+json'
-        end
-
-        it 'returns orderedItems with private statuses' do
-          json = body_as_json
-          expect(json[:orderedItems]).to be_an Array
-          expect(json[:orderedItems].size).to eq 3
-          expect(json[:orderedItems].all? { |item| targets_public_collection?(item) || targets_followers_collection?(item, account) }).to be true
-        end
-
-        it 'returns private Cache-Control header' do
           expect(response.headers['Cache-Control']).to eq 'max-age=60, private'
+
+          expect(body_as_json[:orderedItems]).to be_an Array
+          expect(body_as_json[:orderedItems].size).to eq 3
+          expect(body_as_json[:orderedItems].all? { |item| targets_public_collection?(item) || targets_followers_collection?(item, account) }).to be true
         end
       end
 
@@ -172,22 +137,14 @@ RSpec.describe ActivityPub::OutboxesController do
           get :show, params: { account_username: account.username, page: page }
         end
 
-        it 'returns http success' do
+        it 'returns http success and correct media type and headers and items' do
           expect(response).to have_http_status(200)
-        end
-
-        it 'returns application/activity+json' do
           expect(response.media_type).to eq 'application/activity+json'
-        end
-
-        it 'returns empty orderedItems' do
-          json = body_as_json
-          expect(json[:orderedItems]).to be_an Array
-          expect(json[:orderedItems].size).to eq 0
-        end
-
-        it 'returns private Cache-Control header' do
           expect(response.headers['Cache-Control']).to eq 'max-age=60, private'
+
+          expect(body_as_json[:orderedItems])
+            .to be_an(Array)
+            .and be_empty
         end
       end
 
@@ -197,22 +154,14 @@ RSpec.describe ActivityPub::OutboxesController do
           get :show, params: { account_username: account.username, page: page }
         end
 
-        it 'returns http success' do
+        it 'returns http success and correct media type and headers and items' do
           expect(response).to have_http_status(200)
-        end
-
-        it 'returns application/activity+json' do
           expect(response.media_type).to eq 'application/activity+json'
-        end
-
-        it 'returns empty orderedItems' do
-          json = body_as_json
-          expect(json[:orderedItems]).to be_an Array
-          expect(json[:orderedItems].size).to eq 0
-        end
-
-        it 'returns private Cache-Control header' do
           expect(response.headers['Cache-Control']).to eq 'max-age=60, private'
+
+          expect(body_as_json[:orderedItems])
+            .to be_an(Array)
+            .and be_empty
         end
       end
     end
diff --git a/spec/controllers/activitypub/replies_controller_spec.rb b/spec/controllers/activitypub/replies_controller_spec.rb
index db7f60d3f..c556e0727 100644
--- a/spec/controllers/activitypub/replies_controller_spec.rb
+++ b/spec/controllers/activitypub/replies_controller_spec.rb
@@ -66,19 +66,15 @@ RSpec.describe ActivityPub::RepliesController do
 
     context 'when status is public' do
       let(:parent_visibility) { :public }
-      let(:json) { body_as_json }
-      let(:page_json) { json[:first] }
-
-      it 'returns http success' do
-        expect(response).to have_http_status(200)
-      end
-
-      it 'returns application/activity+json' do
-        expect(response.media_type).to eq 'application/activity+json'
-      end
+      let(:page_json) { body_as_json[:first] }
 
       it_behaves_like 'cacheable response'
 
+      it 'returns http success and correct media type' do
+        expect(response).to have_http_status(200)
+        expect(response.media_type).to eq 'application/activity+json'
+      end
+
       context 'without only_other_accounts' do
         it "returns items with thread author's replies" do
           expect(page_json).to be_a Hash