selenium-webdriver 4.20.0 → 4.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGES +17 -0
- data/bin/linux/selenium-manager +0 -0
- data/bin/macos/selenium-manager +0 -0
- data/bin/windows/selenium-manager.exe +0 -0
- data/lib/selenium/server.rb +2 -1
- data/lib/selenium/webdriver/common/driver_finder.rb +6 -0
- data/lib/selenium/webdriver/common/search_context.rb +10 -2
- data/lib/selenium/webdriver/remote/bridge/locator_converter.rb +76 -0
- data/lib/selenium/webdriver/remote/bridge.rb +32 -46
- data/lib/selenium/webdriver/remote/http/common.rb +21 -3
- data/lib/selenium/webdriver/version.rb +1 -1
- metadata +6 -5
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 4f5e5266f21804cd7520e61a6036171a3bda203460d944ac61cfd324283f72ae
         | 
| 4 | 
            +
              data.tar.gz: 8a58672a580239e27c909e781b16ff588f216f535dda5e495eff5123224e36b2
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 78473145c4ce27a7acf22c58e6c204f7beac53b47a3b18139bb895c08c5d1da90ec5ac558bab429f5284604bba717415be0d8606bb298a68278a22a57947a546
         | 
| 7 | 
            +
              data.tar.gz: b1ae030703351b2b799881b041c9554e0c23c8cfc60a6e8eb32e7f679a7ea23f1c72c7cdbca203b2830439e2488a1ff56c6763df960f8eb873f08356f79ccf91
         | 
    
        data/CHANGES
    CHANGED
    
    | @@ -1,3 +1,20 @@ | |
| 1 | 
            +
            4.21.0 (2024-05-16)
         | 
| 2 | 
            +
            =========================
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            * Add CDP for Chrome 125 and remove 122
         | 
| 5 | 
            +
            * Initial extensibility points for Appium
         | 
| 6 | 
            +
              * Support registering extra headers in HTTP client
         | 
| 7 | 
            +
              * Support overriding User-Agent in HTTP client
         | 
| 8 | 
            +
              * Support registering extra bridge commands
         | 
| 9 | 
            +
              * Support overriding default locator conversion
         | 
| 10 | 
            +
              * Support registering custom finders for SearchContext
         | 
| 11 | 
            +
              * Support using custom element classes
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            4.20.1 (2024-04-25)
         | 
| 14 | 
            +
            =========================
         | 
| 15 | 
            +
             | 
| 16 | 
            +
            * Returned accidentally removed DriverFinder.path and deprecated it.
         | 
| 17 | 
            +
             | 
| 1 18 | 
             
            4.20.0 (2024-04-24)
         | 
| 2 19 | 
             
            =========================
         | 
| 3 20 |  | 
    
        data/bin/linux/selenium-manager
    CHANGED
    
    | Binary file | 
    
        data/bin/macos/selenium-manager
    CHANGED
    
    | Binary file | 
| Binary file | 
    
        data/lib/selenium/server.rb
    CHANGED
    
    | @@ -183,6 +183,7 @@ module Selenium | |
| 183 183 | 
             
                def initialize(jar, opts = {})
         | 
| 184 184 | 
             
                  raise Errno::ENOENT, jar unless File.exist?(jar)
         | 
| 185 185 |  | 
| 186 | 
            +
                  @java = opts.fetch(:java, 'java')
         | 
| 186 187 | 
             
                  @jar = jar
         | 
| 187 188 | 
             
                  @host = '127.0.0.1'
         | 
| 188 189 | 
             
                  @role = opts.fetch(:role, 'standalone')
         | 
| @@ -241,7 +242,7 @@ module Selenium | |
| 241 242 | 
             
                    # extract any additional_args that start with -D as options
         | 
| 242 243 | 
             
                    properties = @additional_args.dup - @additional_args.delete_if { |arg| arg[/^-D/] }
         | 
| 243 244 | 
             
                    args = ['-jar', @jar, @role, '--port', @port.to_s]
         | 
| 244 | 
            -
                    server_command = [ | 
| 245 | 
            +
                    server_command = [@java] + properties + args + @additional_args
         | 
| 245 246 | 
             
                    cp = WebDriver::ChildProcess.build(*server_command)
         | 
| 246 247 |  | 
| 247 248 | 
             
                    if @log.is_a?(String)
         | 
| @@ -20,6 +20,12 @@ | |
| 20 20 | 
             
            module Selenium
         | 
| 21 21 | 
             
              module WebDriver
         | 
| 22 22 | 
             
                class DriverFinder
         | 
| 23 | 
            +
                  def self.path(options, service_class)
         | 
| 24 | 
            +
                    WebDriver.logger.deprecate('DriverFinder.path(options, service_class)',
         | 
| 25 | 
            +
                                               'DriverFinder.new(options, service).driver_path')
         | 
| 26 | 
            +
                    new(options, service_class.new).driver_path
         | 
| 27 | 
            +
                  end
         | 
| 28 | 
            +
             | 
| 23 29 | 
             
                  def initialize(options, service)
         | 
| 24 30 | 
             
                    @options = options
         | 
| 25 31 | 
             
                    @service = service
         | 
| @@ -35,6 +35,14 @@ module Selenium | |
| 35 35 | 
             
                    xpath: 'xpath'
         | 
| 36 36 | 
             
                  }.freeze
         | 
| 37 37 |  | 
| 38 | 
            +
                  class << self
         | 
| 39 | 
            +
                    attr_accessor :extra_finders
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                    def finders
         | 
| 42 | 
            +
                      FINDERS.merge(extra_finders || {})
         | 
| 43 | 
            +
                    end
         | 
| 44 | 
            +
                  end
         | 
| 45 | 
            +
             | 
| 38 46 | 
             
                  #
         | 
| 39 47 | 
             
                  # Find the first element matching the given arguments
         | 
| 40 48 | 
             
                  #
         | 
| @@ -57,7 +65,7 @@ module Selenium | |
| 57 65 | 
             
                  def find_element(*args)
         | 
| 58 66 | 
             
                    how, what = extract_args(args)
         | 
| 59 67 |  | 
| 60 | 
            -
                    by =  | 
| 68 | 
            +
                    by = SearchContext.finders[how.to_sym]
         | 
| 61 69 | 
             
                    raise ArgumentError, "cannot find element by #{how.inspect}" unless by
         | 
| 62 70 |  | 
| 63 71 | 
             
                    bridge.find_element_by by, what, ref
         | 
| @@ -72,7 +80,7 @@ module Selenium | |
| 72 80 | 
             
                  def find_elements(*args)
         | 
| 73 81 | 
             
                    how, what = extract_args(args)
         | 
| 74 82 |  | 
| 75 | 
            -
                    by =  | 
| 83 | 
            +
                    by = SearchContext.finders[how.to_sym]
         | 
| 76 84 | 
             
                    raise ArgumentError, "cannot find elements by #{how.inspect}" unless by
         | 
| 77 85 |  | 
| 78 86 | 
             
                    bridge.find_elements_by by, what, ref
         | 
| @@ -0,0 +1,76 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            # Licensed to the Software Freedom Conservancy (SFC) under one
         | 
| 4 | 
            +
            # or more contributor license agreements.  See the NOTICE file
         | 
| 5 | 
            +
            # distributed with this work for additional information
         | 
| 6 | 
            +
            # regarding copyright ownership.  The SFC licenses this file
         | 
| 7 | 
            +
            # to you under the Apache License, Version 2.0 (the
         | 
| 8 | 
            +
            # "License"); you may not use this file except in compliance
         | 
| 9 | 
            +
            # with the License.  You may obtain a copy of the License at
         | 
| 10 | 
            +
            #
         | 
| 11 | 
            +
            #   http://www.apache.org/licenses/LICENSE-2.0
         | 
| 12 | 
            +
            #
         | 
| 13 | 
            +
            # Unless required by applicable law or agreed to in writing,
         | 
| 14 | 
            +
            # software distributed under the License is distributed on an
         | 
| 15 | 
            +
            # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
         | 
| 16 | 
            +
            # KIND, either express or implied.  See the License for the
         | 
| 17 | 
            +
            # specific language governing permissions and limitations
         | 
| 18 | 
            +
            # under the License.
         | 
| 19 | 
            +
             | 
| 20 | 
            +
            module Selenium
         | 
| 21 | 
            +
              module WebDriver
         | 
| 22 | 
            +
                module Remote
         | 
| 23 | 
            +
                  class Bridge
         | 
| 24 | 
            +
                    class LocatorConverter
         | 
| 25 | 
            +
                      ESCAPE_CSS_REGEXP = /(['"\\#.:;,!?+<>=~*^$|%&@`{}\-\[\]()])/
         | 
| 26 | 
            +
                      UNICODE_CODE_POINT = 30
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                      #
         | 
| 29 | 
            +
                      # Converts a locator to a specification compatible one.
         | 
| 30 | 
            +
                      # @param [String, Symbol] how
         | 
| 31 | 
            +
                      # @param [String] what
         | 
| 32 | 
            +
                      #
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                      def convert(how, what)
         | 
| 35 | 
            +
                        how = SearchContext.finders[how.to_sym] || how
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                        case how
         | 
| 38 | 
            +
                        when 'class name'
         | 
| 39 | 
            +
                          how = 'css selector'
         | 
| 40 | 
            +
                          what = ".#{escape_css(what.to_s)}"
         | 
| 41 | 
            +
                        when 'id'
         | 
| 42 | 
            +
                          how = 'css selector'
         | 
| 43 | 
            +
                          what = "##{escape_css(what.to_s)}"
         | 
| 44 | 
            +
                        when 'name'
         | 
| 45 | 
            +
                          how = 'css selector'
         | 
| 46 | 
            +
                          what = "*[name='#{escape_css(what.to_s)}']"
         | 
| 47 | 
            +
                        end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                        if what.is_a?(Hash)
         | 
| 50 | 
            +
                          what = what.each_with_object({}) do |(h, w), hash|
         | 
| 51 | 
            +
                            h, w = convert(h.to_s, w)
         | 
| 52 | 
            +
                            hash[h] = w
         | 
| 53 | 
            +
                          end
         | 
| 54 | 
            +
                        end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                        [how, what]
         | 
| 57 | 
            +
                      end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                      private
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                      #
         | 
| 62 | 
            +
                      # Escapes invalid characters in CSS selector.
         | 
| 63 | 
            +
                      # @see https://mathiasbynens.be/notes/css-escapes
         | 
| 64 | 
            +
                      #
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                      def escape_css(string)
         | 
| 67 | 
            +
                        string = string.gsub(ESCAPE_CSS_REGEXP) { |match| "\\#{match}" }
         | 
| 68 | 
            +
                        string = "\\#{UNICODE_CODE_POINT + Integer(string[0])} #{string[1..]}" if string[0]&.match?(/[[:digit:]]/)
         | 
| 69 | 
            +
             | 
| 70 | 
            +
                        string
         | 
| 71 | 
            +
                      end
         | 
| 72 | 
            +
                    end # LocatorConverter
         | 
| 73 | 
            +
                  end # Bridge
         | 
| 74 | 
            +
                end # Remote
         | 
| 75 | 
            +
              end # WebDriver
         | 
| 76 | 
            +
            end # Selenium
         | 
| @@ -22,6 +22,8 @@ module Selenium | |
| 22 22 | 
             
                module Remote
         | 
| 23 23 | 
             
                  class Bridge
         | 
| 24 24 | 
             
                    autoload :COMMANDS, 'selenium/webdriver/remote/bridge/commands'
         | 
| 25 | 
            +
                    autoload :LocatorConverter, 'selenium/webdriver/remote/bridge/locator_converter'
         | 
| 26 | 
            +
             | 
| 25 27 | 
             
                    include Atoms
         | 
| 26 28 |  | 
| 27 29 | 
             
                    PORT = 4444
         | 
| @@ -29,6 +31,25 @@ module Selenium | |
| 29 31 | 
             
                    attr_accessor :http, :file_detector
         | 
| 30 32 | 
             
                    attr_reader :capabilities
         | 
| 31 33 |  | 
| 34 | 
            +
                    class << self
         | 
| 35 | 
            +
                      attr_reader :extra_commands
         | 
| 36 | 
            +
                      attr_writer :element_class, :locator_converter
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                      def add_command(name, verb, url, &block)
         | 
| 39 | 
            +
                        @extra_commands ||= {}
         | 
| 40 | 
            +
                        @extra_commands[name] = [verb, url]
         | 
| 41 | 
            +
                        define_method(name, &block)
         | 
| 42 | 
            +
                      end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                      def locator_converter
         | 
| 45 | 
            +
                        @locator_converter ||= LocatorConverter.new
         | 
| 46 | 
            +
                      end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                      def element_class
         | 
| 49 | 
            +
                        @element_class ||= Element
         | 
| 50 | 
            +
                      end
         | 
| 51 | 
            +
                    end
         | 
| 52 | 
            +
             | 
| 32 53 | 
             
                    #
         | 
| 33 54 | 
             
                    # Initializes the bridge with the given server URL
         | 
| 34 55 | 
             
                    # @param [String, URI] url url for the remote server
         | 
| @@ -43,6 +64,8 @@ module Selenium | |
| 43 64 | 
             
                      @http = http_client || Http::Default.new
         | 
| 44 65 | 
             
                      @http.server_url = uri
         | 
| 45 66 | 
             
                      @file_detector = nil
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                      @locator_converter = self.class.locator_converter
         | 
| 46 69 | 
             
                    end
         | 
| 47 70 |  | 
| 48 71 | 
             
                    #
         | 
| @@ -413,7 +436,7 @@ module Selenium | |
| 413 436 | 
             
                               "e.initEvent('submit', true, true);\n" \
         | 
| 414 437 | 
             
                               "if (form.dispatchEvent(e)) { HTMLFormElement.prototype.submit.call(form) }\n"
         | 
| 415 438 |  | 
| 416 | 
            -
                      execute_script(script,  | 
| 439 | 
            +
                      execute_script(script, Bridge.element_class::ELEMENT_KEY => element)
         | 
| 417 440 | 
             
                    rescue Error::JavascriptError
         | 
| 418 441 | 
             
                      raise Error::UnsupportedOperationError, 'To submit an element, it must be nested inside a form element'
         | 
| 419 442 | 
             
                    end
         | 
| @@ -500,13 +523,13 @@ module Selenium | |
| 500 523 | 
             
                    #
         | 
| 501 524 |  | 
| 502 525 | 
             
                    def active_element
         | 
| 503 | 
            -
                       | 
| 526 | 
            +
                      Bridge.element_class.new self, element_id_from(execute(:get_active_element))
         | 
| 504 527 | 
             
                    end
         | 
| 505 528 |  | 
| 506 529 | 
             
                    alias switch_to_active_element active_element
         | 
| 507 530 |  | 
| 508 531 | 
             
                    def find_element_by(how, what, parent_ref = [])
         | 
| 509 | 
            -
                      how, what =  | 
| 532 | 
            +
                      how, what = @locator_converter.convert(how, what)
         | 
| 510 533 |  | 
| 511 534 | 
             
                      return execute_atom(:findElements, Support::RelativeLocator.new(what).as_json).first if how == 'relative'
         | 
| 512 535 |  | 
| @@ -520,11 +543,11 @@ module Selenium | |
| 520 543 | 
             
                             execute :find_element, {}, {using: how, value: what.to_s}
         | 
| 521 544 | 
             
                           end
         | 
| 522 545 |  | 
| 523 | 
            -
                       | 
| 546 | 
            +
                      Bridge.element_class.new self, element_id_from(id)
         | 
| 524 547 | 
             
                    end
         | 
| 525 548 |  | 
| 526 549 | 
             
                    def find_elements_by(how, what, parent_ref = [])
         | 
| 527 | 
            -
                      how, what =  | 
| 550 | 
            +
                      how, what = @locator_converter.convert(how, what)
         | 
| 528 551 |  | 
| 529 552 | 
             
                      return execute_atom :findElements, Support::RelativeLocator.new(what).as_json if how == 'relative'
         | 
| 530 553 |  | 
| @@ -538,7 +561,7 @@ module Selenium | |
| 538 561 | 
             
                              execute :find_elements, {}, {using: how, value: what.to_s}
         | 
| 539 562 | 
             
                            end
         | 
| 540 563 |  | 
| 541 | 
            -
                      ids.map { |id|  | 
| 564 | 
            +
                      ids.map { |id| Bridge.element_class.new self, element_id_from(id) }
         | 
| 542 565 | 
             
                    end
         | 
| 543 566 |  | 
| 544 567 | 
             
                    def shadow_root(element)
         | 
| @@ -612,7 +635,7 @@ module Selenium | |
| 612 635 | 
             
                    end
         | 
| 613 636 |  | 
| 614 637 | 
             
                    def commands(command)
         | 
| 615 | 
            -
                      command_list[command]
         | 
| 638 | 
            +
                      command_list[command] || Bridge.extra_commands[command]
         | 
| 616 639 | 
             
                    end
         | 
| 617 640 |  | 
| 618 641 | 
             
                    def unwrap_script_result(arg)
         | 
| @@ -621,7 +644,7 @@ module Selenium | |
| 621 644 | 
             
                        arg.map { |e| unwrap_script_result(e) }
         | 
| 622 645 | 
             
                      when Hash
         | 
| 623 646 | 
             
                        element_id = element_id_from(arg)
         | 
| 624 | 
            -
                        return  | 
| 647 | 
            +
                        return Bridge.element_class.new(self, element_id) if element_id
         | 
| 625 648 |  | 
| 626 649 | 
             
                        shadow_root_id = shadow_root_id_from(arg)
         | 
| 627 650 | 
             
                        return ShadowRoot.new self, shadow_root_id if shadow_root_id
         | 
| @@ -633,7 +656,7 @@ module Selenium | |
| 633 656 | 
             
                    end
         | 
| 634 657 |  | 
| 635 658 | 
             
                    def element_id_from(id)
         | 
| 636 | 
            -
                      id['ELEMENT'] || id[ | 
| 659 | 
            +
                      id['ELEMENT'] || id[Bridge.element_class::ELEMENT_KEY]
         | 
| 637 660 | 
             
                    end
         | 
| 638 661 |  | 
| 639 662 | 
             
                    def shadow_root_id_from(id)
         | 
| @@ -644,43 +667,6 @@ module Selenium | |
| 644 667 | 
             
                      capabilities = {alwaysMatch: capabilities} if !capabilities['alwaysMatch'] && !capabilities['firstMatch']
         | 
| 645 668 | 
             
                      {capabilities: capabilities}
         | 
| 646 669 | 
             
                    end
         | 
| 647 | 
            -
             | 
| 648 | 
            -
                    def convert_locator(how, what)
         | 
| 649 | 
            -
                      how = SearchContext::FINDERS[how.to_sym] || how
         | 
| 650 | 
            -
             | 
| 651 | 
            -
                      case how
         | 
| 652 | 
            -
                      when 'class name'
         | 
| 653 | 
            -
                        how = 'css selector'
         | 
| 654 | 
            -
                        what = ".#{escape_css(what.to_s)}"
         | 
| 655 | 
            -
                      when 'id'
         | 
| 656 | 
            -
                        how = 'css selector'
         | 
| 657 | 
            -
                        what = "##{escape_css(what.to_s)}"
         | 
| 658 | 
            -
                      when 'name'
         | 
| 659 | 
            -
                        how = 'css selector'
         | 
| 660 | 
            -
                        what = "*[name='#{escape_css(what.to_s)}']"
         | 
| 661 | 
            -
                      end
         | 
| 662 | 
            -
             | 
| 663 | 
            -
                      if what.is_a?(Hash)
         | 
| 664 | 
            -
                        what = what.each_with_object({}) do |(h, w), hash|
         | 
| 665 | 
            -
                          h, w = convert_locator(h.to_s, w)
         | 
| 666 | 
            -
                          hash[h] = w
         | 
| 667 | 
            -
                        end
         | 
| 668 | 
            -
                      end
         | 
| 669 | 
            -
             | 
| 670 | 
            -
                      [how, what]
         | 
| 671 | 
            -
                    end
         | 
| 672 | 
            -
             | 
| 673 | 
            -
                    ESCAPE_CSS_REGEXP = /(['"\\#.:;,!?+<>=~*^$|%&@`{}\-\[\]()])/
         | 
| 674 | 
            -
                    UNICODE_CODE_POINT = 30
         | 
| 675 | 
            -
             | 
| 676 | 
            -
                    # Escapes invalid characters in CSS selector.
         | 
| 677 | 
            -
                    # @see https://mathiasbynens.be/notes/css-escapes
         | 
| 678 | 
            -
                    def escape_css(string)
         | 
| 679 | 
            -
                      string = string.gsub(ESCAPE_CSS_REGEXP) { |match| "\\#{match}" }
         | 
| 680 | 
            -
                      string = "\\#{UNICODE_CODE_POINT + Integer(string[0])} #{string[1..]}" if string[0]&.match?(/[[:digit:]]/)
         | 
| 681 | 
            -
             | 
| 682 | 
            -
                      string
         | 
| 683 | 
            -
                    end
         | 
| 684 670 | 
             
                  end # Bridge
         | 
| 685 671 | 
             
                end # Remote
         | 
| 686 672 | 
             
              end # WebDriver
         | 
| @@ -26,10 +26,18 @@ module Selenium | |
| 26 26 | 
             
                      CONTENT_TYPE    = 'application/json'
         | 
| 27 27 | 
             
                      DEFAULT_HEADERS = {
         | 
| 28 28 | 
             
                        'Accept' => CONTENT_TYPE,
         | 
| 29 | 
            -
                        'Content-Type' => "#{CONTENT_TYPE}; charset=UTF-8" | 
| 30 | 
            -
                        'User-Agent' => "selenium/#{WebDriver::VERSION} (ruby #{Platform.os})"
         | 
| 29 | 
            +
                        'Content-Type' => "#{CONTENT_TYPE}; charset=UTF-8"
         | 
| 31 30 | 
             
                      }.freeze
         | 
| 32 31 |  | 
| 32 | 
            +
                      class << self
         | 
| 33 | 
            +
                        attr_accessor :extra_headers
         | 
| 34 | 
            +
                        attr_writer :user_agent
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                        def user_agent
         | 
| 37 | 
            +
                          @user_agent ||= "selenium/#{WebDriver::VERSION} (ruby #{Platform.os})"
         | 
| 38 | 
            +
                        end
         | 
| 39 | 
            +
                      end
         | 
| 40 | 
            +
             | 
| 33 41 | 
             
                      attr_writer :server_url
         | 
| 34 42 |  | 
| 35 43 | 
             
                      def quit_errors
         | 
| @@ -42,7 +50,7 @@ module Selenium | |
| 42 50 |  | 
| 43 51 | 
             
                      def call(verb, url, command_hash)
         | 
| 44 52 | 
             
                        url      = server_url.merge(url) unless url.is_a?(URI)
         | 
| 45 | 
            -
                        headers  =  | 
| 53 | 
            +
                        headers  = common_headers.dup
         | 
| 46 54 | 
             
                        headers['Cache-Control'] = 'no-cache' if verb == :get
         | 
| 47 55 |  | 
| 48 56 | 
             
                        if command_hash
         | 
| @@ -61,6 +69,16 @@ module Selenium | |
| 61 69 |  | 
| 62 70 | 
             
                      private
         | 
| 63 71 |  | 
| 72 | 
            +
                      def common_headers
         | 
| 73 | 
            +
                        @common_headers ||= begin
         | 
| 74 | 
            +
                          headers = DEFAULT_HEADERS.dup
         | 
| 75 | 
            +
                          headers['User-Agent'] = Common.user_agent
         | 
| 76 | 
            +
                          headers = headers.merge(Common.extra_headers || {})
         | 
| 77 | 
            +
             | 
| 78 | 
            +
                          headers
         | 
| 79 | 
            +
                        end
         | 
| 80 | 
            +
                      end
         | 
| 81 | 
            +
             | 
| 64 82 | 
             
                      def server_url
         | 
| 65 83 | 
             
                        return @server_url if @server_url
         | 
| 66 84 |  | 
    
        metadata
    CHANGED
    
    | @@ -1,16 +1,16 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: selenium-webdriver
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 4. | 
| 4 | 
            +
              version: 4.21.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Alex Rodionov
         | 
| 8 8 | 
             
            - Titus Fortner
         | 
| 9 9 | 
             
            - Thomas Walpole
         | 
| 10 | 
            -
            autorequire: | 
| 10 | 
            +
            autorequire:
         | 
| 11 11 | 
             
            bindir: bin
         | 
| 12 12 | 
             
            cert_chain: []
         | 
| 13 | 
            -
            date: 2024- | 
| 13 | 
            +
            date: 2024-05-16 00:00:00.000000000 Z
         | 
| 14 14 | 
             
            dependencies:
         | 
| 15 15 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 16 16 | 
             
              name: base64
         | 
| @@ -395,6 +395,7 @@ files: | |
| 395 395 | 
             
            - lib/selenium/webdriver/remote.rb
         | 
| 396 396 | 
             
            - lib/selenium/webdriver/remote/bridge.rb
         | 
| 397 397 | 
             
            - lib/selenium/webdriver/remote/bridge/commands.rb
         | 
| 398 | 
            +
            - lib/selenium/webdriver/remote/bridge/locator_converter.rb
         | 
| 398 399 | 
             
            - lib/selenium/webdriver/remote/capabilities.rb
         | 
| 399 400 | 
             
            - lib/selenium/webdriver/remote/driver.rb
         | 
| 400 401 | 
             
            - lib/selenium/webdriver/remote/features.rb
         | 
| @@ -429,7 +430,7 @@ metadata: | |
| 429 430 | 
             
              github_repo: ssh://github.com/SeleniumHQ/selenium
         | 
| 430 431 | 
             
              source_code_uri: https://github.com/SeleniumHQ/selenium/tree/trunk/rb
         | 
| 431 432 | 
             
              rubygems_mfa_required: 'true'
         | 
| 432 | 
            -
            post_install_message: | 
| 433 | 
            +
            post_install_message:
         | 
| 433 434 | 
             
            rdoc_options: []
         | 
| 434 435 | 
             
            require_paths:
         | 
| 435 436 | 
             
            - lib
         | 
| @@ -445,7 +446,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 445 446 | 
             
                  version: 1.3.1
         | 
| 446 447 | 
             
            requirements: []
         | 
| 447 448 | 
             
            rubygems_version: 3.2.33
         | 
| 448 | 
            -
            signing_key: | 
| 449 | 
            +
            signing_key:
         | 
| 449 450 | 
             
            specification_version: 4
         | 
| 450 451 | 
             
            summary: Selenium is a browser automation tool for automated testing of webapps and
         | 
| 451 452 | 
             
              more
         |