From ac8552081345aff2387ea392036b57989183a4d2 Mon Sep 17 00:00:00 2001 From: David Taylor Date: Wed, 9 Aug 2023 11:56:09 +0100 Subject: [PATCH] DEV: Only reveal capybara finder timeouts if the spec otherwise passes (#23026) Followup to edb276b9a95845e81c9b799cb66c72103115c003 --- spec/rails_helper.rb | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index c965f488436..ea0057ef5ac 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -285,8 +285,11 @@ RSpec.configure do |config| module CapybaraTimeoutExtension class CapybaraTimedOut < StandardError - def initialize(wait_time) - super "Capybara waited for the full wait duration (#{wait_time}s). " + + attr_reader :cause + + def initialize(wait_time, cause) + @cause = cause + super "This spec passed, but capybara waited for the full wait duration (#{wait_time}s) at least once. " + "This will slow down the test suite. " + "Beware of negating the result of selenium's RSpec matchers." end @@ -299,8 +302,16 @@ RSpec.configure do |config| 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) + # This error will only have been raised if the timer expired + timeout_error = CapybaraTimedOut.new(seconds, e) + if RSpec.current_example + # Store timeout for later, we'll only raise it if the test otherwise passes + RSpec.current_example.metadata[:_capybara_timeout_exception] ||= timeout_error + raise # re-raise original error + else + # Outside an example... maybe a `before(:all)` hook? + raise timeout_error + end else raise end @@ -310,6 +321,14 @@ RSpec.configure do |config| Capybara::Node::Base.prepend(CapybaraTimeoutExtension) + config.after(:each, type: :system) do |example| + # If test passed, but we had a capybara finder timeout, raise it now + if example.exception.nil? && + (capybara_timout_error = example.metadata[:_capybara_timeout_exception]) + raise capybara_timout_error + end + end + # possible values: OFF, SEVERE, WARNING, INFO, DEBUG, ALL browser_log_level = ENV["SELENIUM_BROWSER_LOG_LEVEL"] || "SEVERE"