diff --git a/rb/lib/selenium/webdriver/bidi/log_handler.rb b/rb/lib/selenium/webdriver/bidi/log_handler.rb index 5054a28ed416f..0ba7382927f2e 100644 --- a/rb/lib/selenium/webdriver/bidi/log_handler.rb +++ b/rb/lib/selenium/webdriver/bidi/log_handler.rb @@ -21,8 +21,8 @@ module Selenium module WebDriver class BiDi class LogHandler - ConsoleLogEntry = BiDi::Struct.new(:level, :text, :timestamp, :method, :args, :type) - JavaScriptLogEntry = BiDi::Struct.new(:level, :text, :timestamp, :stack_trace, :type) + ConsoleLogEntry = BiDi::Struct.new(:level, :text, :timestamp, :stack_trace, :type, :source, :method, :args) + JavaScriptLogEntry = BiDi::Struct.new(:level, :text, :timestamp, :stack_trace, :type, :source) def initialize(bidi) @bidi = bidi diff --git a/rb/spec/integration/selenium/webdriver/bidi/script_spec.rb b/rb/spec/integration/selenium/webdriver/bidi/script_spec.rb index eb660f9b4d763..578659befa1f5 100644 --- a/rb/spec/integration/selenium/webdriver/bidi/script_spec.rb +++ b/rb/spec/integration/selenium/webdriver/bidi/script_spec.rb @@ -25,6 +25,20 @@ module WebDriver only: {browser: %i[chrome edge firefox]} do after { |example| reset_driver!(example: example) } + # Helper to match the expected pattern of `script.StackFrame` objects. + # https://w3c.github.io/webdriver-bidi/#type-script-StackFrame + # + # Pass in any fields you want to check more specific values for, e.g: + # a_stack_frame('functionName' => 'someFunction') + def a_stack_frame(**options) + include({ + 'columnNumber' => an_instance_of(Integer), + 'functionName' => an_instance_of(String), + 'lineNumber' => an_instance_of(Integer), + 'url' => an_instance_of(String) + }.merge(options)) + end + it 'errors when bidi not enabled' do reset_driver!(web_socket_url: false) do |driver| msg = /BiDi must be enabled by setting #web_socket_url to true in options class/ @@ -45,10 +59,27 @@ module WebDriver expect(log_entries.size).to eq(1) log_entry = log_entries.first expect(log_entry).to be_a BiDi::LogHandler::ConsoleLogEntry + expect(log_entry.type).to eq 'console' expect(log_entry.level).to eq 'info' expect(log_entry.method).to eq 'log' expect(log_entry.text).to eq 'Hello, world!' - expect(log_entry.type).to eq 'console' + expect(log_entry.args).to eq [ + {'type' => 'string', 'value' => 'Hello, world!'} + ] + expect(log_entry.timestamp).to be_an_integer + expect(log_entry.source).to match( + 'context' => an_instance_of(String), + 'realm' => an_instance_of(String) + ) + # Stack traces on console messages are optional. + expect(log_entry.stack_trace).to be_nil.or match( + # Some browsers include stack traces from parts of the runtime, so we + # just check the first frames that come from user code. + 'callFrames' => start_with( + a_stack_frame('functionName' => 'helloWorld'), + a_stack_frame('functionName' => 'onclick') + ) + ) end it 'logs multiple console messages' do @@ -97,10 +128,22 @@ module WebDriver expect(log_entries.size).to eq(1) log_entry = log_entries.first expect(log_entry).to be_a BiDi::LogHandler::JavaScriptLogEntry - expect(log_entry.level).to eq 'error' expect(log_entry.type).to eq 'javascript' + expect(log_entry.level).to eq 'error' expect(log_entry.text).to eq 'Error: Not working' - expect(log_entry.stack_trace).not_to be_empty + expect(log_entry.timestamp).to be_an_integer + expect(log_entry.source).to match( + 'context' => an_instance_of(String), + 'realm' => an_instance_of(String) + ) + expect(log_entry.stack_trace).to match( + # Some browsers include stack traces from parts of the runtime, so we + # just check the first frames that come from user code. + 'callFrames' => start_with( + a_stack_frame('functionName' => 'createError'), + a_stack_frame('functionName' => 'onclick') + ) + ) end it 'errors removing non-existent handler' do