Skip to content

Commit

Permalink
[rb] Add backtrace locations and cause to errors (#14170)
Browse files Browse the repository at this point in the history
Co-authored-by: aguspe <agustin.pe94@gmail.com>
  • Loading branch information
aguspe and aguspe authored Jul 16, 2024
1 parent 4a17ec3 commit d883028
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 49 deletions.
6 changes: 1 addition & 5 deletions rb/lib/selenium/webdriver/common/error.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
41 changes: 8 additions & 33 deletions rb/lib/selenium/webdriver/remote/response.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class Response
attr_reader :code, :payload

def initialize(code, payload = nil)
@code = code
@code = code
@payload = payload || {}

assert_ok
Expand All @@ -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

Expand All @@ -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
Expand Down
8 changes: 3 additions & 5 deletions rb/sig/lib/selenium/webdriver/common/error.rbs
Original file line number Diff line number Diff line change
@@ -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

Expand All @@ -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
Expand All @@ -24,7 +25,6 @@ module Selenium
end

class StaleElementReferenceError < WebDriverError
def initialize: (?String msg) -> void
end

class DetachedShadowRootError < WebDriverError
Expand Down Expand Up @@ -61,7 +61,6 @@ module Selenium
end

class InvalidSelectorError < WebDriverError
def initialize: (?::String msg) -> void
end

class SessionNotCreatedError < WebDriverError
Expand Down Expand Up @@ -101,7 +100,6 @@ module Selenium
end

class NoSuchDriverError < WebDriverError
def initialize: (?String msg) -> void
end
end
end
Expand Down
10 changes: 4 additions & 6 deletions rb/sig/lib/selenium/webdriver/remote/response.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
18 changes: 18 additions & 0 deletions rb/spec/integration/selenium/webdriver/error_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit d883028

Please sign in to comment.