selenium-webdriver 4.17.0 → 4.26.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 +92 -0
 - data/Gemfile +1 -0
 - data/README.md +2 -2
 - 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/atoms/findElements.js +26 -26
 - data/lib/selenium/webdriver/atoms/getAttribute.js +2 -2
 - data/lib/selenium/webdriver/atoms/isDisplayed.js +24 -97
 - data/lib/selenium/webdriver/bidi/log/javascript_log_entry.rb +1 -1
 - data/lib/selenium/webdriver/bidi/log_handler.rb +63 -0
 - data/lib/selenium/webdriver/bidi/log_inspector.rb +5 -1
 - data/lib/selenium/webdriver/bidi/session.rb +7 -7
 - data/lib/selenium/webdriver/bidi/struct.rb +44 -0
 - data/lib/selenium/webdriver/bidi.rb +10 -0
 - data/lib/selenium/webdriver/chrome/service.rb +1 -0
 - data/lib/selenium/webdriver/chromium/driver.rb +1 -0
 - data/lib/selenium/webdriver/common/child_process.rb +8 -2
 - data/lib/selenium/webdriver/common/driver.rb +21 -15
 - data/lib/selenium/webdriver/common/driver_extensions/has_bidi.rb +1 -1
 - data/lib/selenium/webdriver/common/driver_extensions/has_fedcm_dialog.rb +55 -0
 - data/lib/selenium/webdriver/common/driver_finder.rb +66 -14
 - data/lib/selenium/webdriver/common/error.rb +21 -21
 - data/lib/selenium/webdriver/common/fedcm/account.rb +50 -0
 - data/lib/selenium/webdriver/common/fedcm/dialog.rb +74 -0
 - data/lib/selenium/webdriver/common/fedcm.rb +27 -0
 - data/lib/selenium/webdriver/common/interactions/pointer_cancel.rb +1 -1
 - data/lib/selenium/webdriver/common/interactions/wheel_input.rb +1 -1
 - data/lib/selenium/webdriver/common/local_driver.rb +8 -1
 - data/lib/selenium/webdriver/common/logger.rb +2 -2
 - data/lib/selenium/webdriver/common/manager.rb +1 -1
 - data/lib/selenium/webdriver/common/options.rb +1 -1
 - data/lib/selenium/webdriver/common/platform.rb +3 -1
 - data/lib/selenium/webdriver/common/script.rb +45 -0
 - data/lib/selenium/webdriver/common/search_context.rb +10 -2
 - data/lib/selenium/webdriver/common/selenium_manager.rb +36 -73
 - data/lib/selenium/webdriver/common/service.rb +11 -4
 - data/lib/selenium/webdriver/common/socket_poller.rb +1 -1
 - data/lib/selenium/webdriver/common/target_locator.rb +1 -2
 - data/lib/selenium/webdriver/common/wait.rb +1 -1
 - data/lib/selenium/webdriver/common/websocket_connection.rb +12 -0
 - data/lib/selenium/webdriver/common.rb +4 -0
 - data/lib/selenium/webdriver/devtools/network_interceptor.rb +1 -1
 - data/lib/selenium/webdriver/edge/service.rb +1 -1
 - data/lib/selenium/webdriver/firefox/options.rb +3 -0
 - data/lib/selenium/webdriver/firefox/profile.rb +11 -5
 - data/lib/selenium/webdriver/firefox/profiles_ini.rb +1 -1
 - data/lib/selenium/webdriver/firefox/service.rb +1 -0
 - data/lib/selenium/webdriver/ie/options.rb +3 -2
 - data/lib/selenium/webdriver/ie/service.rb +1 -0
 - data/lib/selenium/webdriver/remote/bidi_bridge.rb +44 -0
 - data/lib/selenium/webdriver/remote/bridge/commands.rb +13 -1
 - data/lib/selenium/webdriver/remote/bridge/locator_converter.rb +76 -0
 - data/lib/selenium/webdriver/remote/bridge.rb +87 -46
 - data/lib/selenium/webdriver/remote/capabilities.rb +1 -1
 - data/lib/selenium/webdriver/remote/http/common.rb +21 -3
 - data/lib/selenium/webdriver/remote/http/curb.rb +11 -5
 - data/lib/selenium/webdriver/remote/response.rb +12 -19
 - data/lib/selenium/webdriver/remote/server_error.rb +1 -1
 - data/lib/selenium/webdriver/remote.rb +2 -1
 - data/lib/selenium/webdriver/safari/service.rb +1 -1
 - data/lib/selenium/webdriver/support/guards/guard.rb +8 -9
 - data/lib/selenium/webdriver/version.rb +1 -1
 - data/lib/selenium/webdriver.rb +1 -1
 - data/selenium-webdriver.gemspec +9 -6
 - metadata +70 -7
 
| 
         @@ -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 
     | 
    
         
             
                    #
         
     | 
| 
         @@ -278,6 +301,7 @@ module Selenium 
     | 
|
| 
       278 
301 
     | 
    
         
             
                    #
         
     | 
| 
       279 
302 
     | 
    
         | 
| 
       280 
303 
     | 
    
         
             
                    def local_storage_item(key, value = nil)
         
     | 
| 
      
 304 
     | 
    
         
            +
                      WebDriver.logger.deprecate('local_storage_item(key, value)', id: :local_storage_item)
         
     | 
| 
       281 
305 
     | 
    
         
             
                      if value
         
     | 
| 
       282 
306 
     | 
    
         
             
                        execute_script("localStorage.setItem('#{key}', '#{value}')")
         
     | 
| 
       283 
307 
     | 
    
         
             
                      else
         
     | 
| 
         @@ -286,22 +310,27 @@ module Selenium 
     | 
|
| 
       286 
310 
     | 
    
         
             
                    end
         
     | 
| 
       287 
311 
     | 
    
         | 
| 
       288 
312 
     | 
    
         
             
                    def remove_local_storage_item(key)
         
     | 
| 
      
 313 
     | 
    
         
            +
                      WebDriver.logger.deprecate('remove_local_storage_item(key)', id: :remove_local_storage_item)
         
     | 
| 
       289 
314 
     | 
    
         
             
                      execute_script("localStorage.removeItem('#{key}')")
         
     | 
| 
       290 
315 
     | 
    
         
             
                    end
         
     | 
| 
       291 
316 
     | 
    
         | 
| 
       292 
317 
     | 
    
         
             
                    def local_storage_keys
         
     | 
| 
      
 318 
     | 
    
         
            +
                      WebDriver.logger.deprecate('local_storage_keys', id: :local_storage_keys)
         
     | 
| 
       293 
319 
     | 
    
         
             
                      execute_script('return Object.keys(localStorage)')
         
     | 
| 
       294 
320 
     | 
    
         
             
                    end
         
     | 
| 
       295 
321 
     | 
    
         | 
| 
       296 
322 
     | 
    
         
             
                    def clear_local_storage
         
     | 
| 
      
 323 
     | 
    
         
            +
                      WebDriver.logger.deprecate('clear_local_storage', id: :clear_local_storage)
         
     | 
| 
       297 
324 
     | 
    
         
             
                      execute_script('localStorage.clear()')
         
     | 
| 
       298 
325 
     | 
    
         
             
                    end
         
     | 
| 
       299 
326 
     | 
    
         | 
| 
       300 
327 
     | 
    
         
             
                    def local_storage_size
         
     | 
| 
      
 328 
     | 
    
         
            +
                      WebDriver.logger.deprecate('local_storage_size', id: :local_storage_size)
         
     | 
| 
       301 
329 
     | 
    
         
             
                      execute_script('return localStorage.length')
         
     | 
| 
       302 
330 
     | 
    
         
             
                    end
         
     | 
| 
       303 
331 
     | 
    
         | 
| 
       304 
332 
     | 
    
         
             
                    def session_storage_item(key, value = nil)
         
     | 
| 
      
 333 
     | 
    
         
            +
                      WebDriver.logger.deprecate('session_storage_item(key, value)', id: :session_storage_item)
         
     | 
| 
       305 
334 
     | 
    
         
             
                      if value
         
     | 
| 
       306 
335 
     | 
    
         
             
                        execute_script("sessionStorage.setItem('#{key}', '#{value}')")
         
     | 
| 
       307 
336 
     | 
    
         
             
                      else
         
     | 
| 
         @@ -310,18 +339,22 @@ module Selenium 
     | 
|
| 
       310 
339 
     | 
    
         
             
                    end
         
     | 
| 
       311 
340 
     | 
    
         | 
| 
       312 
341 
     | 
    
         
             
                    def remove_session_storage_item(key)
         
     | 
| 
      
 342 
     | 
    
         
            +
                      WebDriver.logger.deprecate('remove_session_storage_item(key)', id: :remove_session_storage_item)
         
     | 
| 
       313 
343 
     | 
    
         
             
                      execute_script("sessionStorage.removeItem('#{key}')")
         
     | 
| 
       314 
344 
     | 
    
         
             
                    end
         
     | 
| 
       315 
345 
     | 
    
         | 
| 
       316 
346 
     | 
    
         
             
                    def session_storage_keys
         
     | 
| 
      
 347 
     | 
    
         
            +
                      WebDriver.logger.deprecate('session_storage_keys', id: :session_storage_keys)
         
     | 
| 
       317 
348 
     | 
    
         
             
                      execute_script('return Object.keys(sessionStorage)')
         
     | 
| 
       318 
349 
     | 
    
         
             
                    end
         
     | 
| 
       319 
350 
     | 
    
         | 
| 
       320 
351 
     | 
    
         
             
                    def clear_session_storage
         
     | 
| 
      
 352 
     | 
    
         
            +
                      WebDriver.logger.deprecate('clear_session_storage', id: :clear_session_storage)
         
     | 
| 
       321 
353 
     | 
    
         
             
                      execute_script('sessionStorage.clear()')
         
     | 
| 
       322 
354 
     | 
    
         
             
                    end
         
     | 
| 
       323 
355 
     | 
    
         | 
| 
       324 
356 
     | 
    
         
             
                    def session_storage_size
         
     | 
| 
      
 357 
     | 
    
         
            +
                      WebDriver.logger.deprecate('session_storage_size', id: :session_storage_size)
         
     | 
| 
       325 
358 
     | 
    
         
             
                      execute_script('return sessionStorage.length')
         
     | 
| 
       326 
359 
     | 
    
         
             
                    end
         
     | 
| 
       327 
360 
     | 
    
         | 
| 
         @@ -413,7 +446,7 @@ module Selenium 
     | 
|
| 
       413 
446 
     | 
    
         
             
                               "e.initEvent('submit', true, true);\n" \
         
     | 
| 
       414 
447 
     | 
    
         
             
                               "if (form.dispatchEvent(e)) { HTMLFormElement.prototype.submit.call(form) }\n"
         
     | 
| 
       415 
448 
     | 
    
         | 
| 
       416 
     | 
    
         
            -
                      execute_script(script,  
     | 
| 
      
 449 
     | 
    
         
            +
                      execute_script(script, Bridge.element_class::ELEMENT_KEY => element)
         
     | 
| 
       417 
450 
     | 
    
         
             
                    rescue Error::JavascriptError
         
     | 
| 
       418 
451 
     | 
    
         
             
                      raise Error::UnsupportedOperationError, 'To submit an element, it must be nested inside a form element'
         
     | 
| 
       419 
452 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -500,13 +533,13 @@ module Selenium 
     | 
|
| 
       500 
533 
     | 
    
         
             
                    #
         
     | 
| 
       501 
534 
     | 
    
         | 
| 
       502 
535 
     | 
    
         
             
                    def active_element
         
     | 
| 
       503 
     | 
    
         
            -
                       
     | 
| 
      
 536 
     | 
    
         
            +
                      Bridge.element_class.new self, element_id_from(execute(:get_active_element))
         
     | 
| 
       504 
537 
     | 
    
         
             
                    end
         
     | 
| 
       505 
538 
     | 
    
         | 
| 
       506 
539 
     | 
    
         
             
                    alias switch_to_active_element active_element
         
     | 
| 
       507 
540 
     | 
    
         | 
| 
       508 
541 
     | 
    
         
             
                    def find_element_by(how, what, parent_ref = [])
         
     | 
| 
       509 
     | 
    
         
            -
                      how, what =  
     | 
| 
      
 542 
     | 
    
         
            +
                      how, what = @locator_converter.convert(how, what)
         
     | 
| 
       510 
543 
     | 
    
         | 
| 
       511 
544 
     | 
    
         
             
                      return execute_atom(:findElements, Support::RelativeLocator.new(what).as_json).first if how == 'relative'
         
     | 
| 
       512 
545 
     | 
    
         | 
| 
         @@ -520,11 +553,11 @@ module Selenium 
     | 
|
| 
       520 
553 
     | 
    
         
             
                             execute :find_element, {}, {using: how, value: what.to_s}
         
     | 
| 
       521 
554 
     | 
    
         
             
                           end
         
     | 
| 
       522 
555 
     | 
    
         | 
| 
       523 
     | 
    
         
            -
                       
     | 
| 
      
 556 
     | 
    
         
            +
                      Bridge.element_class.new self, element_id_from(id)
         
     | 
| 
       524 
557 
     | 
    
         
             
                    end
         
     | 
| 
       525 
558 
     | 
    
         | 
| 
       526 
559 
     | 
    
         
             
                    def find_elements_by(how, what, parent_ref = [])
         
     | 
| 
       527 
     | 
    
         
            -
                      how, what =  
     | 
| 
      
 560 
     | 
    
         
            +
                      how, what = @locator_converter.convert(how, what)
         
     | 
| 
       528 
561 
     | 
    
         | 
| 
       529 
562 
     | 
    
         
             
                      return execute_atom :findElements, Support::RelativeLocator.new(what).as_json if how == 'relative'
         
     | 
| 
       530 
563 
     | 
    
         | 
| 
         @@ -538,7 +571,7 @@ module Selenium 
     | 
|
| 
       538 
571 
     | 
    
         
             
                              execute :find_elements, {}, {using: how, value: what.to_s}
         
     | 
| 
       539 
572 
     | 
    
         
             
                            end
         
     | 
| 
       540 
573 
     | 
    
         | 
| 
       541 
     | 
    
         
            -
                      ids.map { |id|  
     | 
| 
      
 574 
     | 
    
         
            +
                      ids.map { |id| Bridge.element_class.new self, element_id_from(id) }
         
     | 
| 
       542 
575 
     | 
    
         
             
                    end
         
     | 
| 
       543 
576 
     | 
    
         | 
| 
       544 
577 
     | 
    
         
             
                    def shadow_root(element)
         
     | 
| 
         @@ -579,6 +612,51 @@ module Selenium 
     | 
|
| 
       579 
612 
     | 
    
         
             
                      execute :set_user_verified, {authenticatorId: authenticator_id}, {isUserVerified: verified}
         
     | 
| 
       580 
613 
     | 
    
         
             
                    end
         
     | 
| 
       581 
614 
     | 
    
         | 
| 
      
 615 
     | 
    
         
            +
                    #
         
     | 
| 
      
 616 
     | 
    
         
            +
                    # federated-credential management
         
     | 
| 
      
 617 
     | 
    
         
            +
                    #
         
     | 
| 
      
 618 
     | 
    
         
            +
             
     | 
| 
      
 619 
     | 
    
         
            +
                    def cancel_fedcm_dialog
         
     | 
| 
      
 620 
     | 
    
         
            +
                      execute :cancel_fedcm_dialog
         
     | 
| 
      
 621 
     | 
    
         
            +
                    end
         
     | 
| 
      
 622 
     | 
    
         
            +
             
     | 
| 
      
 623 
     | 
    
         
            +
                    def select_fedcm_account(index)
         
     | 
| 
      
 624 
     | 
    
         
            +
                      execute :select_fedcm_account, {}, {accountIndex: index}
         
     | 
| 
      
 625 
     | 
    
         
            +
                    end
         
     | 
| 
      
 626 
     | 
    
         
            +
             
     | 
| 
      
 627 
     | 
    
         
            +
                    def fedcm_dialog_type
         
     | 
| 
      
 628 
     | 
    
         
            +
                      execute :get_fedcm_dialog_type
         
     | 
| 
      
 629 
     | 
    
         
            +
                    end
         
     | 
| 
      
 630 
     | 
    
         
            +
             
     | 
| 
      
 631 
     | 
    
         
            +
                    def fedcm_title
         
     | 
| 
      
 632 
     | 
    
         
            +
                      execute(:get_fedcm_title).fetch('title')
         
     | 
| 
      
 633 
     | 
    
         
            +
                    end
         
     | 
| 
      
 634 
     | 
    
         
            +
             
     | 
| 
      
 635 
     | 
    
         
            +
                    def fedcm_subtitle
         
     | 
| 
      
 636 
     | 
    
         
            +
                      execute(:get_fedcm_title).fetch('subtitle', nil)
         
     | 
| 
      
 637 
     | 
    
         
            +
                    end
         
     | 
| 
      
 638 
     | 
    
         
            +
             
     | 
| 
      
 639 
     | 
    
         
            +
                    def fedcm_account_list
         
     | 
| 
      
 640 
     | 
    
         
            +
                      execute :get_fedcm_account_list
         
     | 
| 
      
 641 
     | 
    
         
            +
                    end
         
     | 
| 
      
 642 
     | 
    
         
            +
             
     | 
| 
      
 643 
     | 
    
         
            +
                    def fedcm_delay(enabled)
         
     | 
| 
      
 644 
     | 
    
         
            +
                      execute :set_fedcm_delay, {}, {enabled: enabled}
         
     | 
| 
      
 645 
     | 
    
         
            +
                    end
         
     | 
| 
      
 646 
     | 
    
         
            +
             
     | 
| 
      
 647 
     | 
    
         
            +
                    def reset_fedcm_cooldown
         
     | 
| 
      
 648 
     | 
    
         
            +
                      execute :reset_fedcm_cooldown
         
     | 
| 
      
 649 
     | 
    
         
            +
                    end
         
     | 
| 
      
 650 
     | 
    
         
            +
             
     | 
| 
      
 651 
     | 
    
         
            +
                    def click_fedcm_dialog_button
         
     | 
| 
      
 652 
     | 
    
         
            +
                      execute :click_fedcm_dialog_button, {}, {dialogButton: 'ConfirmIdpLoginContinue'}
         
     | 
| 
      
 653 
     | 
    
         
            +
                    end
         
     | 
| 
      
 654 
     | 
    
         
            +
             
     | 
| 
      
 655 
     | 
    
         
            +
                    def bidi
         
     | 
| 
      
 656 
     | 
    
         
            +
                      msg = 'BiDi must be enabled by setting #web_socket_url to true in options class'
         
     | 
| 
      
 657 
     | 
    
         
            +
                      raise(WebDriver::Error::WebDriverError, msg)
         
     | 
| 
      
 658 
     | 
    
         
            +
                    end
         
     | 
| 
      
 659 
     | 
    
         
            +
             
     | 
| 
       582 
660 
     | 
    
         
             
                    def command_list
         
     | 
| 
       583 
661 
     | 
    
         
             
                      COMMANDS
         
     | 
| 
       584 
662 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -612,7 +690,7 @@ module Selenium 
     | 
|
| 
       612 
690 
     | 
    
         
             
                    end
         
     | 
| 
       613 
691 
     | 
    
         | 
| 
       614 
692 
     | 
    
         
             
                    def commands(command)
         
     | 
| 
       615 
     | 
    
         
            -
                      command_list[command]
         
     | 
| 
      
 693 
     | 
    
         
            +
                      command_list[command] || Bridge.extra_commands[command]
         
     | 
| 
       616 
694 
     | 
    
         
             
                    end
         
     | 
| 
       617 
695 
     | 
    
         | 
| 
       618 
696 
     | 
    
         
             
                    def unwrap_script_result(arg)
         
     | 
| 
         @@ -621,7 +699,7 @@ module Selenium 
     | 
|
| 
       621 
699 
     | 
    
         
             
                        arg.map { |e| unwrap_script_result(e) }
         
     | 
| 
       622 
700 
     | 
    
         
             
                      when Hash
         
     | 
| 
       623 
701 
     | 
    
         
             
                        element_id = element_id_from(arg)
         
     | 
| 
       624 
     | 
    
         
            -
                        return  
     | 
| 
      
 702 
     | 
    
         
            +
                        return Bridge.element_class.new(self, element_id) if element_id
         
     | 
| 
       625 
703 
     | 
    
         | 
| 
       626 
704 
     | 
    
         
             
                        shadow_root_id = shadow_root_id_from(arg)
         
     | 
| 
       627 
705 
     | 
    
         
             
                        return ShadowRoot.new self, shadow_root_id if shadow_root_id
         
     | 
| 
         @@ -633,7 +711,7 @@ module Selenium 
     | 
|
| 
       633 
711 
     | 
    
         
             
                    end
         
     | 
| 
       634 
712 
     | 
    
         | 
| 
       635 
713 
     | 
    
         
             
                    def element_id_from(id)
         
     | 
| 
       636 
     | 
    
         
            -
                      id['ELEMENT'] || id[ 
     | 
| 
      
 714 
     | 
    
         
            +
                      id['ELEMENT'] || id[Bridge.element_class::ELEMENT_KEY]
         
     | 
| 
       637 
715 
     | 
    
         
             
                    end
         
     | 
| 
       638 
716 
     | 
    
         | 
| 
       639 
717 
     | 
    
         
             
                    def shadow_root_id_from(id)
         
     | 
| 
         @@ -644,43 +722,6 @@ module Selenium 
     | 
|
| 
       644 
722 
     | 
    
         
             
                      capabilities = {alwaysMatch: capabilities} if !capabilities['alwaysMatch'] && !capabilities['firstMatch']
         
     | 
| 
       645 
723 
     | 
    
         
             
                      {capabilities: capabilities}
         
     | 
| 
       646 
724 
     | 
    
         
             
                    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 
725 
     | 
    
         
             
                  end # Bridge
         
     | 
| 
       685 
726 
     | 
    
         
             
                end # Remote
         
     | 
| 
       686 
727 
     | 
    
         
             
              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 
     | 
    
         | 
| 
         @@ -37,6 +37,13 @@ module Selenium 
     | 
|
| 
       37 
37 
     | 
    
         
             
                    #
         
     | 
| 
       38 
38 
     | 
    
         | 
| 
       39 
39 
     | 
    
         
             
                    class Curb < Common
         
     | 
| 
      
 40 
     | 
    
         
            +
                      attr_accessor :timeout
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                      def initialize(timeout: nil)
         
     | 
| 
      
 43 
     | 
    
         
            +
                        @timeout = timeout
         
     | 
| 
      
 44 
     | 
    
         
            +
                        super()
         
     | 
| 
      
 45 
     | 
    
         
            +
                      end
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
       40 
47 
     | 
    
         
             
                      def quit_errors
         
     | 
| 
       41 
48 
     | 
    
         
             
                        [Curl::Err::RecvError] + super
         
     | 
| 
       42 
49 
     | 
    
         
             
                      end
         
     | 
| 
         @@ -53,7 +60,7 @@ module Selenium 
     | 
|
| 
       53 
60 
     | 
    
         
             
                        client.headers = headers
         
     | 
| 
       54 
61 
     | 
    
         | 
| 
       55 
62 
     | 
    
         
             
                        # http://github.com/taf2/curb/issues/issue/33
         
     | 
| 
       56 
     | 
    
         
            -
                        client.head 
     | 
| 
      
 63 
     | 
    
         
            +
                        client.head = false
         
     | 
| 
       57 
64 
     | 
    
         
             
                        client.delete = false
         
     | 
| 
       58 
65 
     | 
    
         | 
| 
       59 
66 
     | 
    
         
             
                        case verb
         
     | 
| 
         @@ -80,11 +87,10 @@ module Selenium 
     | 
|
| 
       80 
87 
     | 
    
         
             
                        @client ||= begin
         
     | 
| 
       81 
88 
     | 
    
         
             
                          c = Curl::Easy.new
         
     | 
| 
       82 
89 
     | 
    
         | 
| 
       83 
     | 
    
         
            -
                          c.max_redirects 
     | 
| 
      
 90 
     | 
    
         
            +
                          c.max_redirects = MAX_REDIRECTS
         
     | 
| 
       84 
91 
     | 
    
         
             
                          c.follow_location = true
         
     | 
| 
       85 
     | 
    
         
            -
                          c.timeout 
     | 
| 
       86 
     | 
    
         
            -
                          c.verbose 
     | 
| 
       87 
     | 
    
         
            -
             
     | 
| 
      
 92 
     | 
    
         
            +
                          c.timeout = timeout if timeout
         
     | 
| 
      
 93 
     | 
    
         
            +
                          c.verbose = WebDriver.logger.debug?
         
     | 
| 
       88 
94 
     | 
    
         
             
                          c
         
     | 
| 
       89 
95 
     | 
    
         
             
                        end
         
     | 
| 
       90 
96 
     | 
    
         
             
                      end
         
     | 
| 
         @@ -28,7 +28,7 @@ module Selenium 
     | 
|
| 
       28 
28 
     | 
    
         
             
                    attr_reader :code, :payload
         
     | 
| 
       29 
29 
     | 
    
         | 
| 
       30 
30 
     | 
    
         
             
                    def initialize(code, payload = nil)
         
     | 
| 
       31 
     | 
    
         
            -
                      @code 
     | 
| 
      
 31 
     | 
    
         
            +
                      @code = code
         
     | 
| 
       32 
32 
     | 
    
         
             
                      @payload = payload || {}
         
     | 
| 
       33 
33 
     | 
    
         | 
| 
       34 
34 
     | 
    
         
             
                      assert_ok
         
     | 
| 
         @@ -37,11 +37,8 @@ module Selenium 
     | 
|
| 
       37 
37 
     | 
    
         
             
                    def error
         
     | 
| 
       38 
38 
     | 
    
         
             
                      error, message, backtrace = process_error
         
     | 
| 
       39 
39 
     | 
    
         
             
                      klass = Error.for_error(error) || return
         
     | 
| 
       40 
     | 
    
         
            -
             
     | 
| 
       41 
40 
     | 
    
         
             
                      ex = klass.new(message)
         
     | 
| 
       42 
     | 
    
         
            -
                      ex 
     | 
| 
       43 
     | 
    
         
            -
                      add_backtrace ex, backtrace
         
     | 
| 
       44 
     | 
    
         
            -
             
     | 
| 
      
 41 
     | 
    
         
            +
                      add_cause(ex, error, backtrace)
         
     | 
| 
       45 
42 
     | 
    
         
             
                      ex
         
     | 
| 
       46 
43 
     | 
    
         
             
                    end
         
     | 
| 
       47 
44 
     | 
    
         | 
| 
         @@ -59,17 +56,13 @@ module Selenium 
     | 
|
| 
       59 
56 
     | 
    
         
             
                      raise Error::ServerError, self
         
     | 
| 
       60 
57 
     | 
    
         
             
                    end
         
     | 
| 
       61 
58 
     | 
    
         | 
| 
       62 
     | 
    
         
            -
                    def  
     | 
| 
       63 
     | 
    
         
            -
                       
     | 
| 
       64 
     | 
    
         
            -
             
     | 
| 
       65 
     | 
    
         
            -
                      backtrace 
     | 
| 
       66 
     | 
    
         
            -
             
     | 
| 
       67 
     | 
    
         
            -
             
     | 
| 
       68 
     | 
    
         
            -
             
     | 
| 
       69 
     | 
    
         
            -
                                    server_trace.split("\n")
         
     | 
| 
       70 
     | 
    
         
            -
                                  end
         
     | 
| 
       71 
     | 
    
         
            -
             
     | 
| 
       72 
     | 
    
         
            -
                      ex.set_backtrace(backtrace + ex.backtrace)
         
     | 
| 
      
 59 
     | 
    
         
            +
                    def add_cause(ex, error, backtrace)
         
     | 
| 
      
 60 
     | 
    
         
            +
                      cause = Error::WebDriverError.new
         
     | 
| 
      
 61 
     | 
    
         
            +
                      backtrace = backtrace_from_remote(backtrace) if backtrace.is_a?(Array)
         
     | 
| 
      
 62 
     | 
    
         
            +
                      cause.set_backtrace(backtrace)
         
     | 
| 
      
 63 
     | 
    
         
            +
                      raise ex, cause: cause
         
     | 
| 
      
 64 
     | 
    
         
            +
                    rescue Error.for_error(error)
         
     | 
| 
      
 65 
     | 
    
         
            +
                      ex
         
     | 
| 
       73 
66 
     | 
    
         
             
                    end
         
     | 
| 
       74 
67 
     | 
    
         | 
| 
       75 
68 
     | 
    
         
             
                    def backtrace_from_remote(server_trace)
         
     | 
| 
         @@ -78,14 +71,14 @@ module Selenium 
     | 
|
| 
       78 
71 
     | 
    
         | 
| 
       79 
72 
     | 
    
         
             
                        file = frame['fileName']
         
     | 
| 
       80 
73 
     | 
    
         
             
                        line = frame['lineNumber']
         
     | 
| 
       81 
     | 
    
         
            -
                         
     | 
| 
      
 74 
     | 
    
         
            +
                        method = frame['methodName']
         
     | 
| 
       82 
75 
     | 
    
         | 
| 
       83 
76 
     | 
    
         
             
                        class_name = frame['className']
         
     | 
| 
       84 
77 
     | 
    
         
             
                        file = "#{class_name}(#{file})" if class_name
         
     | 
| 
       85 
78 
     | 
    
         | 
| 
       86 
     | 
    
         
            -
                         
     | 
| 
      
 79 
     | 
    
         
            +
                        method = 'unknown' if method.nil? || method.empty?
         
     | 
| 
       87 
80 
     | 
    
         | 
| 
       88 
     | 
    
         
            -
                        "[remote server] #{file}:#{line}:in `#{ 
     | 
| 
      
 81 
     | 
    
         
            +
                        "[remote server] #{file}:#{line}:in `#{method}'"
         
     | 
| 
       89 
82 
     | 
    
         
             
                      end
         
     | 
| 
       90 
83 
     | 
    
         
             
                    end
         
     | 
| 
       91 
84 
     | 
    
         | 
| 
         @@ -25,12 +25,13 @@ module Selenium 
     | 
|
| 
       25 
25 
     | 
    
         
             
                module Remote
         
     | 
| 
       26 
26 
     | 
    
         
             
                  autoload :Features,     'selenium/webdriver/remote/features'
         
     | 
| 
       27 
27 
     | 
    
         
             
                  autoload :Bridge,       'selenium/webdriver/remote/bridge'
         
     | 
| 
      
 28 
     | 
    
         
            +
                  autoload :BiDiBridge,   'selenium/webdriver/remote/bidi_bridge'
         
     | 
| 
       28 
29 
     | 
    
         
             
                  autoload :Driver,       'selenium/webdriver/remote/driver'
         
     | 
| 
       29 
30 
     | 
    
         
             
                  autoload :Response,     'selenium/webdriver/remote/response'
         
     | 
| 
       30 
31 
     | 
    
         
             
                  autoload :Capabilities, 'selenium/webdriver/remote/capabilities'
         
     | 
| 
       31 
32 
     | 
    
         | 
| 
       32 
33 
     | 
    
         
             
                  module Http
         
     | 
| 
       33 
     | 
    
         
            -
                    autoload :Common, 
     | 
| 
      
 34 
     | 
    
         
            +
                    autoload :Common, 'selenium/webdriver/remote/http/common'
         
     | 
| 
       34 
35 
     | 
    
         
             
                    autoload :Default, 'selenium/webdriver/remote/http/default'
         
     | 
| 
       35 
36 
     | 
    
         
             
                  end
         
     | 
| 
       36 
37 
     | 
    
         
             
                end
         
     | 
| 
         @@ -24,7 +24,7 @@ module Selenium 
     | 
|
| 
       24 
24 
     | 
    
         
             
                    DEFAULT_PORT = 7050
         
     | 
| 
       25 
25 
     | 
    
         
             
                    EXECUTABLE = 'safaridriver'
         
     | 
| 
       26 
26 
     | 
    
         
             
                    SHUTDOWN_SUPPORTED = false
         
     | 
| 
       27 
     | 
    
         
            -
             
     | 
| 
      
 27 
     | 
    
         
            +
                    DRIVER_PATH_ENV_KEY = 'SE_SAFARIDRIVER'
         
     | 
| 
       28 
28 
     | 
    
         
             
                    def initialize(path: nil, port: nil, log: nil, args: nil)
         
     | 
| 
       29 
29 
     | 
    
         
             
                      raise Error::WebDriverError, 'Safari Service does not support setting log output' if log
         
     | 
| 
       30 
30 
     | 
    
         | 
| 
         @@ -27,7 +27,7 @@ module Selenium 
     | 
|
| 
       27 
27 
     | 
    
         
             
                    #
         
     | 
| 
       28 
28 
     | 
    
         | 
| 
       29 
29 
     | 
    
         
             
                    class Guard
         
     | 
| 
       30 
     | 
    
         
            -
                      attr_reader :guarded, :type, :messages, :reason
         
     | 
| 
      
 30 
     | 
    
         
            +
                      attr_reader :guarded, :type, :messages, :reason, :tracker
         
     | 
| 
       31 
31 
     | 
    
         | 
| 
       32 
32 
     | 
    
         
             
                      def initialize(guarded, type, guards = nil)
         
     | 
| 
       33 
33 
     | 
    
         
             
                        @guarded = guarded
         
     | 
| 
         @@ -36,22 +36,21 @@ module Selenium 
     | 
|
| 
       36 
36 
     | 
    
         
             
                        @messages[:unknown] = 'TODO: Investigate why this is failing and file a bug report'
         
     | 
| 
       37 
37 
     | 
    
         
             
                        @type = type
         
     | 
| 
       38 
38 
     | 
    
         | 
| 
       39 
     | 
    
         
            -
                        @reason = @guarded 
     | 
| 
      
 39 
     | 
    
         
            +
                        @reason = @guarded[:reason] || 'No reason given'
         
     | 
| 
      
 40 
     | 
    
         
            +
                        @guarded[:reason] = @reason
         
     | 
| 
       40 
41 
     | 
    
         
             
                      end
         
     | 
| 
       41 
42 
     | 
    
         | 
| 
       42 
43 
     | 
    
         
             
                      def message
         
     | 
| 
       43 
     | 
    
         
            -
                        details = case  
     | 
| 
      
 44 
     | 
    
         
            +
                        details = case reason
         
     | 
| 
       44 
45 
     | 
    
         
             
                                  when Integer
         
     | 
| 
       45 
     | 
    
         
            -
                                    "Bug Filed: #{ 
     | 
| 
      
 46 
     | 
    
         
            +
                                    "Bug Filed: #{tracker}/#{reason}"
         
     | 
| 
       46 
47 
     | 
    
         
             
                                  when Symbol
         
     | 
| 
       47 
     | 
    
         
            -
                                     
     | 
| 
       48 
     | 
    
         
            -
                                  when String
         
     | 
| 
       49 
     | 
    
         
            -
                                    @reason
         
     | 
| 
      
 48 
     | 
    
         
            +
                                    messages[reason]
         
     | 
| 
       50 
49 
     | 
    
         
             
                                  else
         
     | 
| 
       51 
     | 
    
         
            -
                                     
     | 
| 
      
 50 
     | 
    
         
            +
                                    "Guarded by #{guarded};"
         
     | 
| 
       52 
51 
     | 
    
         
             
                                  end
         
     | 
| 
       53 
52 
     | 
    
         | 
| 
       54 
     | 
    
         
            -
                        case  
     | 
| 
      
 53 
     | 
    
         
            +
                        case type
         
     | 
| 
       55 
54 
     | 
    
         
             
                        when :exclude
         
     | 
| 
       56 
55 
     | 
    
         
             
                          "Test skipped because it breaks test run; #{details}"
         
     | 
| 
       57 
56 
     | 
    
         
             
                        when :flaky
         
     | 
    
        data/lib/selenium/webdriver.rb
    CHANGED
    
    
    
        data/selenium-webdriver.gemspec
    CHANGED
    
    | 
         @@ -47,18 +47,21 @@ Gem::Specification.new do |s| 
     | 
|
| 
       47 
47 
     | 
    
         
             
              s.bindir = 'bin'
         
     | 
| 
       48 
48 
     | 
    
         
             
              s.require_paths = ['lib']
         
     | 
| 
       49 
49 
     | 
    
         | 
| 
       50 
     | 
    
         
            -
              s. 
     | 
| 
       51 
     | 
    
         
            -
              s. 
     | 
| 
       52 
     | 
    
         
            -
              s. 
     | 
| 
       53 
     | 
    
         
            -
              s. 
     | 
| 
      
 50 
     | 
    
         
            +
              s.add_dependency 'base64', ['~> 0.2']
         
     | 
| 
      
 51 
     | 
    
         
            +
              s.add_dependency 'logger', ['~> 1.4']
         
     | 
| 
      
 52 
     | 
    
         
            +
              s.add_dependency 'rexml', ['~> 3.2', '>= 3.2.5']
         
     | 
| 
      
 53 
     | 
    
         
            +
              s.add_dependency 'rubyzip', ['>= 1.2.2', '< 3.0']
         
     | 
| 
      
 54 
     | 
    
         
            +
              s.add_dependency 'websocket', ['~> 1.0']
         
     | 
| 
       54 
55 
     | 
    
         | 
| 
      
 56 
     | 
    
         
            +
              s.add_development_dependency 'git', ['~> 1.19']
         
     | 
| 
       55 
57 
     | 
    
         
             
              s.add_development_dependency 'rack', ['~> 2.0']
         
     | 
| 
       56 
58 
     | 
    
         
             
              s.add_development_dependency 'rake', ['~> 13.0']
         
     | 
| 
       57 
59 
     | 
    
         
             
              s.add_development_dependency 'rspec', ['~> 3.0']
         
     | 
| 
       58 
     | 
    
         
            -
              s.add_development_dependency 'rubocop', ['~> 1. 
     | 
| 
      
 60 
     | 
    
         
            +
              s.add_development_dependency 'rubocop', ['~> 1.60', '>=1.60.2']
         
     | 
| 
       59 
61 
     | 
    
         
             
              s.add_development_dependency 'rubocop-performance', ['~> 1.15']
         
     | 
| 
      
 62 
     | 
    
         
            +
              s.add_development_dependency 'rubocop-rake', ['~> 0.6.0']
         
     | 
| 
       60 
63 
     | 
    
         
             
              s.add_development_dependency 'rubocop-rspec', ['~> 2.16']
         
     | 
| 
       61 
64 
     | 
    
         
             
              s.add_development_dependency 'webmock', ['~> 3.5']
         
     | 
| 
       62 
65 
     | 
    
         
             
              s.add_development_dependency 'webrick', ['~> 1.7']
         
     | 
| 
       63 
     | 
    
         
            -
              s.add_development_dependency 'yard', ['~> 0.9.11']
         
     | 
| 
      
 66 
     | 
    
         
            +
              s.add_development_dependency 'yard', ['~> 0.9.11', '>= 0.9.36']
         
     | 
| 
       64 
67 
     | 
    
         
             
            end
         
     |