diff --git a/rb/lib/selenium/webdriver/common/script.rb b/rb/lib/selenium/webdriver/common/script.rb index 4b58b1bbea2c7..74d19b574e727 100644 --- a/rb/lib/selenium/webdriver/common/script.rb +++ b/rb/lib/selenium/webdriver/common/script.rb @@ -21,7 +21,8 @@ module Selenium module WebDriver class Script def initialize(bridge) - @log_handler = BiDi::LogHandler.new(bridge.bidi) + @bidi = bridge.bidi + @log_handler = BiDi::LogHandler.new(@bidi) end # @return [int] id of the handler @@ -40,6 +41,26 @@ def remove_console_message_handler(id) end alias remove_javascript_error_handler remove_console_message_handler + + # Pins a script that is evaluated on every fresh browsing context (page) + # before the page's own scripts run. Useful for injecting helpers, + # polyfills, or instrumentation that should be present on every navigation. + # + # @param [String] script the function declaration to pin, + # e.g. "() => { window.helper = () => 42; }" + # @return [String] the id of the pinned script, for use with #unpin + def pin(script) + result = @bidi.send_cmd('script.addPreloadScript', functionDeclaration: script) + result['script'] + end + + # Unpins a previously pinned script so it no longer runs on new pages. + # + # @param [String] script_id the id returned by #pin + # @return [void] + def unpin(script_id) + @bidi.send_cmd('script.removePreloadScript', script: script_id) + end end # Script end # WebDriver end # Selenium diff --git a/rb/sig/lib/selenium/webdriver/common/script.rbs b/rb/sig/lib/selenium/webdriver/common/script.rbs index 37b1a1d8c9b74..571170680bb98 100644 --- a/rb/sig/lib/selenium/webdriver/common/script.rbs +++ b/rb/sig/lib/selenium/webdriver/common/script.rbs @@ -33,6 +33,10 @@ module Selenium def remove_console_message_handler: (Integer id) -> bool? alias remove_javascript_error_handler remove_console_message_handler + + def pin: (String script) -> String + + def unpin: (String script_id) -> void end end end diff --git a/rb/spec/integration/selenium/webdriver/bidi/script_spec.rb b/rb/spec/integration/selenium/webdriver/bidi/script_spec.rb index fb6c1b419d145..b04e96fc85ccd 100644 --- a/rb/spec/integration/selenium/webdriver/bidi/script_spec.rb +++ b/rb/spec/integration/selenium/webdriver/bidi/script_spec.rb @@ -157,6 +157,22 @@ def a_stack_frame(**options) driver.script.remove_console_message_handler(12345) }.to raise_error(Error::WebDriverError, /Callback with ID 12345 does not exist/) end + + it 'pins a script that runs on every new document' do + script_id = driver.script.pin('() => { window.pinnedValue = "pinned!"; }') + expect(script_id).to be_a(String) + + driver.navigate.to url_for('formPage.html') + expect(driver.execute_script('return window.pinnedValue')).to eq('pinned!') + end + + it 'unpins a script so it no longer runs' do + script_id = driver.script.pin('() => { window.pinnedValue = "pinned!"; }') + driver.script.unpin(script_id) + + driver.navigate.to url_for('formPage.html') + expect(driver.execute_script('return window.pinnedValue')).to be_nil + end end end end