From 63112f89a3d98a5fa058c55462567b2824920fa7 Mon Sep 17 00:00:00 2001
From: Daniel Waterworth <me@danielwaterworth.com>
Date: Fri, 3 Dec 2021 14:54:07 -0600
Subject: [PATCH] PERF: Shave off some test-suite time (#15183)

---
 spec/components/post_action_creator_spec.rb |  4 +-
 spec/models/post_action_spec.rb             | 10 +----
 spec/models/topic_spec.rb                   |  6 +--
 spec/requests/groups_controller_spec.rb     | 42 ++++++++-------------
 spec/requests/users_controller_spec.rb      |  2 +-
 spec/services/user_destroyer_spec.rb        |  2 -
 spec/services/user_merger_spec.rb           | 34 +++++++----------
 7 files changed, 33 insertions(+), 67 deletions(-)

diff --git a/spec/components/post_action_creator_spec.rb b/spec/components/post_action_creator_spec.rb
index dd4ef73f946..488b47effad 100644
--- a/spec/components/post_action_creator_spec.rb
+++ b/spec/components/post_action_creator_spec.rb
@@ -3,6 +3,7 @@
 require 'rails_helper'
 
 describe PostActionCreator do
+  fab!(:admin) { Fabricate(:admin) }
   fab!(:user) { Fabricate(:user) }
   fab!(:post) { Fabricate(:post) }
   let(:like_type_id) { PostActionType.types[:like] }
@@ -147,8 +148,6 @@ describe PostActionCreator do
       end
 
       describe "When the post was already reviewed by staff" do
-        fab!(:admin) { Fabricate(:admin) }
-
         before { reviewable.perform(admin, :ignore) }
 
         it "fails because the post was recently reviewed" do
@@ -221,7 +220,6 @@ describe PostActionCreator do
   end
 
   context "queue_for_review" do
-    fab!(:admin) { Fabricate(:admin) }
 
     it 'fails if the user is not a staff member' do
       creator = PostActionCreator.new(
diff --git a/spec/models/post_action_spec.rb b/spec/models/post_action_spec.rb
index 82f7ea92f59..f4a258dd6a0 100644
--- a/spec/models/post_action_spec.rb
+++ b/spec/models/post_action_spec.rb
@@ -492,7 +492,7 @@ describe PostAction do
     it "shouldn't change given_likes unless likes are given or removed" do
       freeze_time(Time.zone.now)
 
-      PostActionCreator.like(codinghorror, Fabricate(:post))
+      PostActionCreator.like(codinghorror, post)
       expect(value_for(codinghorror.id, Date.today)).to eq(1)
 
       PostActionType.types.each do |type_name, type_id|
@@ -513,20 +513,17 @@ describe PostAction do
   describe 'flagging' do
 
     it 'does not allow you to flag stuff twice, even if the reason is different' do
-      post = Fabricate(:post)
       expect(PostActionCreator.spam(eviltrout, post)).to be_success
       expect(PostActionCreator.off_topic(eviltrout, post)).to be_failed
     end
 
     it 'allows you to flag stuff again if your previous flag was removed' do
-      post = Fabricate(:post)
       PostActionCreator.spam(eviltrout, post)
       PostActionDestroyer.destroy(eviltrout, post, :spam)
       expect(PostActionCreator.spam(eviltrout, post)).to be_success
     end
 
     it 'should update counts when you clear flags' do
-      post = Fabricate(:post)
       reviewable = PostActionCreator.spam(eviltrout, post).reviewable
 
       expect(post.reload.spam_count).to eq(1)
@@ -874,7 +871,6 @@ describe PostAction do
   describe ".lookup_for" do
     it "returns the correct map" do
       user = Fabricate(:user)
-      post = Fabricate(:post)
       post_action = PostActionCreator.create(user, post, :bookmark).post_action
       map = PostAction.lookup_for(user, [post.topic], post_action.post_action_type_id)
 
@@ -898,7 +894,6 @@ describe PostAction do
 
     it "should create a notification in the related topic" do
       Jobs.run_immediately!
-      post = Fabricate(:post)
       user = Fabricate(:user)
       stub_image_size
       result = PostActionCreator.create(user, post, :spam, message: "WAT")
@@ -915,7 +910,6 @@ describe PostAction do
 
     skip "should not add a moderator post when post is flagged via private message" do
       Jobs.run_immediately!
-      post = Fabricate(:post)
       user = Fabricate(:user)
       result = PostActionCreator.create(user, post, :notify_user, message: "WAT")
       action = result.post_action
@@ -986,8 +980,6 @@ describe PostAction do
   end
 
   describe "triggers Discourse events" do
-    fab!(:post) { Fabricate(:post) }
-
     it 'triggers a flag_created event' do
       event = DiscourseEvent.track(:flag_created) { PostActionCreator.spam(eviltrout, post) }
       expect(event).to be_present
diff --git a/spec/models/topic_spec.rb b/spec/models/topic_spec.rb
index de3086ed46d..75131283913 100644
--- a/spec/models/topic_spec.rb
+++ b/spec/models/topic_spec.rb
@@ -6,6 +6,7 @@ require 'rails_helper'
 describe Topic do
   let(:now) { Time.zone.local(2013, 11, 20, 8, 0) }
   fab!(:user) { Fabricate(:user) }
+  fab!(:admin) { Fabricate(:admin) }
   fab!(:another_user) { Fabricate(:user) }
   fab!(:trust_level_2) { Fabricate(:user, trust_level: SiteSetting.min_trust_level_to_allow_invite) }
 
@@ -249,8 +250,6 @@ describe Topic do
   end
 
   context 'admin topic title' do
-    let(:admin) { Fabricate(:admin) }
-
     it 'allows really short titles' do
       pm = Fabricate.build(:private_message_topic, user: admin, title: 'a')
       expect(pm).to be_valid
@@ -747,7 +746,6 @@ describe Topic do
 
         context "when invited_user has enabled allow_list" do
           fab!(:user2) { Fabricate(:user) }
-          fab!(:admin) { Fabricate(:admin) }
           fab!(:pm) { Fabricate(:private_message_topic, user: user, topic_allowed_users: [
             Fabricate.build(:topic_allowed_user, user: user),
             Fabricate.build(:topic_allowed_user, user: user2)
@@ -1864,7 +1862,6 @@ describe Topic do
       Fabricate(:topic_timer, execute_at: 5.hours.from_now).topic
     end
 
-    fab!(:admin) { Fabricate(:admin) }
     fab!(:trust_level_4) { Fabricate(:trust_level_4) }
 
     it 'can take a number of hours as an integer' do
@@ -2955,7 +2952,6 @@ describe Topic do
   describe "#cannot_permanently_delete_reason" do
     fab!(:post) { Fabricate(:post) }
     let!(:topic) { post.topic }
-    fab!(:admin) { Fabricate(:admin) }
 
     before do
       freeze_time
diff --git a/spec/requests/groups_controller_spec.rb b/spec/requests/groups_controller_spec.rb
index ff7b00a4a70..7dc0d1cb59c 100644
--- a/spec/requests/groups_controller_spec.rb
+++ b/spec/requests/groups_controller_spec.rb
@@ -4,7 +4,7 @@ require 'rails_helper'
 
 describe GroupsController do
   fab!(:user) { Fabricate(:user) }
-  let(:other_user) { Fabricate(:user) }
+  fab!(:other_user) { Fabricate(:user) }
   let(:group) { Fabricate(:group, users: [user]) }
   let(:moderator_group_id) { Group::AUTO_GROUPS[:moderators] }
   fab!(:admin) { Fabricate(:admin) }
@@ -92,7 +92,7 @@ describe GroupsController do
         sign_in(user)
       end
 
-      let!(:other_group) { Fabricate(:group, name: "other_group", users: [user, other_user]) }
+      fab!(:other_group) { Fabricate(:group, name: "other_group", users: [user, other_user]) }
 
       context "with default (descending) order" do
         it "sorts by name" do
@@ -213,7 +213,7 @@ describe GroupsController do
         expect(group_names).to contain_exactly("0_0")
 
         # logged in user
-        sign_in(Fabricate(:user))
+        sign_in(user)
         get "/groups.json", params: { username: u.username }
 
         expect(response.status).to eq(200)
@@ -256,8 +256,6 @@ describe GroupsController do
     end
 
     context 'viewing as an admin' do
-      fab!(:admin) { Fabricate(:admin) }
-
       before do
         sign_in(admin)
         group.add(admin)
@@ -356,7 +354,7 @@ describe GroupsController do
 
   describe '#show' do
     it "ensures the group can be seen" do
-      sign_in(Fabricate(:user))
+      sign_in(user)
       group.update!(visibility_level: Group.visibility_levels[:owners])
 
       get "/groups/#{group.name}.json"
@@ -397,7 +395,7 @@ describe GroupsController do
 
     context 'as an admin' do
       it "returns the right response" do
-        sign_in(Fabricate(:admin))
+        sign_in(admin)
         get "/groups/#{group.name}.json"
 
         expect(response.status).to eq(200)
@@ -448,7 +446,7 @@ describe GroupsController do
 
   describe "#posts" do
     it "ensures the group can be seen" do
-      sign_in(Fabricate(:user))
+      sign_in(user)
       group.update!(visibility_level: Group.visibility_levels[:owners])
 
       get "/groups/#{group.name}/posts.json"
@@ -457,7 +455,7 @@ describe GroupsController do
     end
 
     it "ensures the group members can be seen" do
-      sign_in(Fabricate(:user))
+      sign_in(user)
       group.update!(members_visibility_level: Group.visibility_levels[:owners])
 
       get "/groups/#{group.name}/posts.json"
@@ -487,7 +485,7 @@ describe GroupsController do
   describe "#members" do
 
     it "returns correct error code with invalid params" do
-      sign_in(Fabricate(:user))
+      sign_in(user)
 
       get "/groups/#{group.name}/members.json?limit=-1"
       expect(response.status).to eq(400)
@@ -500,7 +498,7 @@ describe GroupsController do
     end
 
     it "ensures the group can be seen" do
-      sign_in(Fabricate(:user))
+      sign_in(user)
       group.update!(visibility_level: Group.visibility_levels[:owners])
 
       get "/groups/#{group.name}/members.json"
@@ -1188,7 +1186,7 @@ describe GroupsController do
     end
 
     it "can show group requests" do
-      sign_in(Fabricate(:admin))
+      sign_in(admin)
 
       user4 = Fabricate(:user)
       request4 = Fabricate(:group_request, user: user4, group: group)
@@ -1217,7 +1215,7 @@ describe GroupsController do
 
       describe 'as an admin' do
         before do
-          sign_in(Fabricate(:admin))
+          sign_in(admin)
         end
 
         it "should allow members to be filterable by username" do
@@ -1296,11 +1294,10 @@ describe GroupsController do
     end
 
     context 'when user is an admin' do
-      fab!(:user) { Fabricate(:admin) }
-      let(:group) { Fabricate(:group, users: [user], automatic: true) }
+      fab!(:group) { Fabricate(:group, users: [admin], automatic: true) }
 
       before do
-        sign_in(user)
+        sign_in(admin)
       end
 
       it "cannot add members to automatic groups" do
@@ -1314,8 +1311,6 @@ describe GroupsController do
   end
 
   describe "membership edits" do
-    fab!(:admin) { Fabricate(:admin) }
-
     context '#add_members' do
       before do
         sign_in(admin)
@@ -1370,7 +1365,7 @@ describe GroupsController do
         group.add_owner(user)
         sign_in(user)
 
-        put "/groups/#{group.id}/members.json", params: { usernames: Fabricate(:user).username }
+        put "/groups/#{group.id}/members.json", params: { usernames: other_user.username }
         expect(response.status).to eq(200)
       end
 
@@ -1564,8 +1559,6 @@ describe GroupsController do
       end
 
       context 'public group' do
-        fab!(:other_user) { Fabricate(:user) }
-
         before do
           group.update!(
             public_admission: true,
@@ -1713,7 +1706,6 @@ describe GroupsController do
         end
 
         context 'public group' do
-          fab!(:other_user) { Fabricate(:user) }
           let(:group) { Fabricate(:public_group, users: [other_user]) }
 
           context "admin" do
@@ -1923,8 +1915,6 @@ describe GroupsController do
     end
 
     context 'when user is an admin' do
-      fab!(:admin) { Fabricate(:admin) }
-
       before do
         sign_in(admin)
       end
@@ -2106,7 +2096,7 @@ describe GroupsController do
 
     context 'as an admin' do
       it "returns the right response" do
-        sign_in(Fabricate(:admin))
+        sign_in(admin)
 
         get '/groups/search.json?ignore_automatic=true'
 
@@ -2141,7 +2131,7 @@ describe GroupsController do
     end
 
     describe 'for an admin user' do
-      before { sign_in(Fabricate(:admin)) }
+      before { sign_in(admin) }
 
       it 'should return 200' do
         get '/groups/custom/new'
diff --git a/spec/requests/users_controller_spec.rb b/spec/requests/users_controller_spec.rb
index 637cbe399dc..096629df972 100644
--- a/spec/requests/users_controller_spec.rb
+++ b/spec/requests/users_controller_spec.rb
@@ -202,7 +202,7 @@ describe UsersController do
     end
 
     context 'valid token' do
-      let!(:user) { Fabricate(:user) }
+      fab!(:user) { Fabricate(:user) }
       let!(:user_auth_token) { UserAuthToken.generate!(user_id: user.id) }
       let!(:email_token) { Fabricate(:email_token, user: user, scope: EmailToken.scopes[:password_reset]) }
 
diff --git a/spec/services/user_destroyer_spec.rb b/spec/services/user_destroyer_spec.rb
index 3bcafc505ca..a376177fa5b 100644
--- a/spec/services/user_destroyer_spec.rb
+++ b/spec/services/user_destroyer_spec.rb
@@ -371,7 +371,6 @@ describe UserDestroyer do
 
     describe "Destroying a user with security key" do
       let!(:security_key) { Fabricate(:user_security_key_with_random_credential, user: user) }
-      fab!(:admin) { Fabricate(:admin) }
 
       it "removes the security key" do
         UserDestroyer.new(admin).destroy(user)
@@ -381,7 +380,6 @@ describe UserDestroyer do
 
     describe "Destroying a user with a bookmark" do
       let!(:bookmark) { Fabricate(:bookmark, user: user) }
-      fab!(:admin) { Fabricate(:admin) }
 
       it "removes the bookmark" do
         UserDestroyer.new(admin).destroy(user)
diff --git a/spec/services/user_merger_spec.rb b/spec/services/user_merger_spec.rb
index 06d3a51931c..3ffb7ef8479 100644
--- a/spec/services/user_merger_spec.rb
+++ b/spec/services/user_merger_spec.rb
@@ -7,6 +7,13 @@ describe UserMerger do
   fab!(:source_user) { Fabricate(:user, username: 'alice1', email: 'alice@work.com') }
   fab!(:walter) { Fabricate(:walter_white) }
 
+  fab!(:p1) { Fabricate(:post) }
+  fab!(:p2) { Fabricate(:post) }
+  fab!(:p3) { Fabricate(:post) }
+  fab!(:p4) { Fabricate(:post) }
+  fab!(:p5) { Fabricate(:post) }
+  fab!(:p6) { Fabricate(:post) }
+
   def merge_users!(source = nil, target =  nil)
     source ||= source_user
     target ||= target_user
@@ -154,13 +161,6 @@ describe UserMerger do
     end
 
     it "merges likes" do
-      p1 = Fabricate(:post)
-      p2 = Fabricate(:post)
-      p3 = Fabricate(:post)
-      p4 = Fabricate(:post)
-      p5 = Fabricate(:post)
-      p6 = Fabricate(:post)
-
       now = Time.zone.now
 
       freeze_time(now - 1.day)
@@ -334,9 +334,6 @@ describe UserMerger do
 
   context "post actions" do
     it "merges post actions" do
-      p1 = Fabricate(:post)
-      p2 = Fabricate(:post)
-      p3 = Fabricate(:post)
       type_ids = PostActionType.public_type_ids + [PostActionType.flag_types.values.first]
 
       type_ids.each do |type|
@@ -357,11 +354,6 @@ describe UserMerger do
     end
 
     it "updates post actions" do
-      p1 = Fabricate(:post)
-      p2 = Fabricate(:post)
-      p3 = Fabricate(:post)
-      p4 = Fabricate(:post)
-
       action1 = PostActionCreator.create(source_user, p1, :off_topic).post_action
       action1.update_attribute(:deleted_by_id, source_user.id)
 
@@ -384,7 +376,7 @@ describe UserMerger do
   end
 
   it "updates post revisions" do
-    post = Fabricate(:post)
+    post = p1
     post_revision = Fabricate(:post_revision, post: post, user: source_user)
 
     merge_users!
@@ -410,9 +402,9 @@ describe UserMerger do
     end
 
     it "merges post timings" do
-      post1 = Fabricate(:post)
-      post2 = Fabricate(:post)
-      post3 = Fabricate(:post)
+      post1 = p1
+      post2 = p2
+      post3 = p3
 
       create_post_timing(post1, source_user, 12345)
       create_post_timing(post2, source_user, 9876)
@@ -678,8 +670,8 @@ describe UserMerger do
     # action_type and user_id are not nullable
     # target_topic_id and acting_user_id are nullable, but always have a value
 
-    fab!(:post1) { Fabricate(:post) }
-    fab!(:post2) { Fabricate(:post) }
+    fab!(:post1) { p1 }
+    fab!(:post2) { p2 }
 
     def log_like_action(acting_user, user, post)
       UserAction.log_action!(action_type: UserAction::LIKE,