diff --git a/rb/lib/selenium/webdriver/common/error.rb b/rb/lib/selenium/webdriver/common/error.rb index 7e3de39f2d6f4..deece7d2e3b0f 100644 --- a/rb/lib/selenium/webdriver/common/error.rb +++ b/rb/lib/selenium/webdriver/common/error.rb @@ -77,11 +77,7 @@ class UnknownCommandError < WebDriverError; end # A command failed because the referenced element is no longer attached to the DOM. # - class StaleElementReferenceError < WebDriverError - def initialize(msg = '') - super("#{msg}; #{SUPPORT_MSG} #{URLS[:StaleElementReferenceError]}") - end - end + class StaleElementReferenceError < WebDriverError; end # # A command failed because the referenced shadow root is no longer attached to the DOM. diff --git a/rb/lib/selenium/webdriver/remote/response.rb b/rb/lib/selenium/webdriver/remote/response.rb index 93e95f8576306..453a04a2c0695 100644 --- a/rb/lib/selenium/webdriver/remote/response.rb +++ b/rb/lib/selenium/webdriver/remote/response.rb @@ -28,7 +28,7 @@ class Response attr_reader :code, :payload def initialize(code, payload = nil) - @code = code + @code = code @payload = payload || {} assert_ok @@ -37,11 +37,8 @@ def initialize(code, payload = nil) def error error, message, backtrace = process_error klass = Error.for_error(error) || return - ex = klass.new(message) - ex.set_backtrace(caller) - add_backtrace ex, backtrace - + add_cause(ex, error, backtrace) ex end @@ -59,34 +56,12 @@ def assert_ok raise Error::ServerError, self end - def add_backtrace(ex, server_trace) - return unless server_trace - - backtrace = case server_trace - when Array - backtrace_from_remote(server_trace) - when String - server_trace.split("\n") - end - - ex.set_backtrace(backtrace + ex.backtrace) - end - - def backtrace_from_remote(server_trace) - server_trace.filter_map do |frame| - next unless frame.is_a?(Hash) - - file = frame['fileName'] - line = frame['lineNumber'] - meth = frame['methodName'] - - class_name = frame['className'] - file = "#{class_name}(#{file})" if class_name - - meth = 'unknown' if meth.nil? || meth.empty? - - "[remote server] #{file}:#{line}:in `#{meth}'" - end + def add_cause(ex, error, backtrace) + cause = Error::WebDriverError.new + cause.set_backtrace(backtrace) + raise ex, cause: cause + rescue Error.for_error(error) + ex end def process_error diff --git a/rb/sig/lib/selenium/webdriver/common/error.rbs b/rb/sig/lib/selenium/webdriver/common/error.rbs index 16c7caf9d033a..da8be68ee9f8c 100644 --- a/rb/sig/lib/selenium/webdriver/common/error.rbs +++ b/rb/sig/lib/selenium/webdriver/common/error.rbs @@ -1,7 +1,7 @@ module Selenium module WebDriver module Error - def self.for_error: (untyped error) -> untyped + def self.for_error: (String? error) -> Class? SUPPORT_MSG: String @@ -10,11 +10,12 @@ module Selenium URLS: Hash[Symbol, String] class WebDriverError < StandardError + def initialize: (?String | Array[String] msg) -> void + def class_name: -> Symbol? end class NoSuchElementError < WebDriverError - def initialize: (?String msg) -> void end class NoSuchFrameError < WebDriverError @@ -24,7 +25,6 @@ module Selenium end class StaleElementReferenceError < WebDriverError - def initialize: (?String msg) -> void end class DetachedShadowRootError < WebDriverError @@ -61,7 +61,6 @@ module Selenium end class InvalidSelectorError < WebDriverError - def initialize: (?::String msg) -> void end class SessionNotCreatedError < WebDriverError @@ -101,7 +100,6 @@ module Selenium end class NoSuchDriverError < WebDriverError - def initialize: (?String msg) -> void end end end diff --git a/rb/sig/lib/selenium/webdriver/remote/response.rbs b/rb/sig/lib/selenium/webdriver/remote/response.rbs index 2fb2cb8756483..c2955447fa993 100644 --- a/rb/sig/lib/selenium/webdriver/remote/response.rbs +++ b/rb/sig/lib/selenium/webdriver/remote/response.rbs @@ -12,19 +12,17 @@ module Selenium def initialize: (String code, ?Hash[untyped, untyped]? payload) -> void - def error: () -> (nil | untyped) + def error: () -> Error::WebDriverError? def []: (untyped key) -> untyped private - def assert_ok: () -> (nil | untyped) + def assert_ok: () -> Error::WebDriverError - def add_backtrace: (untyped ex, untyped server_trace) -> (nil | untyped) + def add_cause: (Error::WebDriverError ex, String error, Array[String] backtrace) -> Error::WebDriverError - def backtrace_from_remote: (untyped server_trace) -> String - - def process_error: () -> (nil | untyped) + def process_error: () -> Array[Hash[untyped, untyped]] end end end diff --git a/rb/spec/integration/selenium/webdriver/error_spec.rb b/rb/spec/integration/selenium/webdriver/error_spec.rb index ad5fd3ae0ff65..936b2186e6491 100644 --- a/rb/spec/integration/selenium/webdriver/error_spec.rb +++ b/rb/spec/integration/selenium/webdriver/error_spec.rb @@ -29,6 +29,24 @@ module WebDriver driver.find_element(id: 'nonexistent') }.to raise_error(WebDriver::Error::NoSuchElementError, /#no-such-element-exception/) end + + it 'has backtrace locations' do + driver.find_element(id: 'nonexistent') + rescue WebDriver::Error::NoSuchElementError => e + expect(e.backtrace_locations).not_to be_empty + end + + it 'has cause' do + driver.find_element(id: 'nonexistent') + rescue WebDriver::Error::NoSuchElementError => e + expect(e.cause).to be_a(WebDriver::Error::WebDriverError) + end + + it 'has backtrace' do + driver.find_element(id: 'nonexistent') + rescue WebDriver::Error::NoSuchElementError => e + expect(e.backtrace).not_to be_empty + end end end # WebDriver end # Selenium