diff --git a/plugins/chat/spec/system/page_objects/chat/chat.rb b/plugins/chat/spec/system/page_objects/chat/chat.rb
index 694d0719507..6a77ed8402b 100644
--- a/plugins/chat/spec/system/page_objects/chat/chat.rb
+++ b/plugins/chat/spec/system/page_objects/chat/chat.rb
@@ -50,8 +50,7 @@ module PageObjects
 
       def visit_thread(thread)
         visit(thread.url)
-        has_css?(".chat-skeleton")
-        has_no_css?(".chat-skeleton")
+        has_css?(".chat-thread:not(.loading)[data-id=\"#{thread.id}\"]")
       end
 
       def visit_channel_settings(channel)
diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb
index 2d0550dd8f2..c965f488436 100644
--- a/spec/rails_helper.rb
+++ b/spec/rails_helper.rb
@@ -283,6 +283,33 @@ RSpec.configure do |config|
 
     Capybara::Session.class_eval { prepend IgnoreUnicornCapturedErrors }
 
+    module CapybaraTimeoutExtension
+      class CapybaraTimedOut < StandardError
+        def initialize(wait_time)
+          super "Capybara waited for the full wait duration (#{wait_time}s). " +
+                  "This will slow down the test suite. " +
+                  "Beware of negating the result of selenium's RSpec matchers."
+        end
+      end
+
+      def synchronize(seconds = nil, errors: nil)
+        return super if session.synchronized # Nested synchronize. We only want our logic on the outermost call.
+        begin
+          super
+        rescue StandardError => e
+          seconds = session_options.default_max_wait_time if [nil, true].include? seconds
+          if catch_error?(e, errors) && seconds != 0
+            # This error will only have been raised if the timer expired. Raise our own error instead.
+            raise CapybaraTimedOut.new(seconds)
+          else
+            raise
+          end
+        end
+      end
+    end
+
+    Capybara::Node::Base.prepend(CapybaraTimeoutExtension)
+
     # possible values: OFF, SEVERE, WARNING, INFO, DEBUG, ALL
     browser_log_level = ENV["SELENIUM_BROWSER_LOG_LEVEL"] || "SEVERE"