selenium-webdriver 4.17.0 → 4.26.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +92 -0
  3. data/Gemfile +1 -0
  4. data/README.md +2 -2
  5. data/bin/linux/selenium-manager +0 -0
  6. data/bin/macos/selenium-manager +0 -0
  7. data/bin/windows/selenium-manager.exe +0 -0
  8. data/lib/selenium/server.rb +2 -1
  9. data/lib/selenium/webdriver/atoms/findElements.js +26 -26
  10. data/lib/selenium/webdriver/atoms/getAttribute.js +2 -2
  11. data/lib/selenium/webdriver/atoms/isDisplayed.js +24 -97
  12. data/lib/selenium/webdriver/bidi/log/javascript_log_entry.rb +1 -1
  13. data/lib/selenium/webdriver/bidi/log_handler.rb +63 -0
  14. data/lib/selenium/webdriver/bidi/log_inspector.rb +5 -1
  15. data/lib/selenium/webdriver/bidi/session.rb +7 -7
  16. data/lib/selenium/webdriver/bidi/struct.rb +44 -0
  17. data/lib/selenium/webdriver/bidi.rb +10 -0
  18. data/lib/selenium/webdriver/chrome/service.rb +1 -0
  19. data/lib/selenium/webdriver/chromium/driver.rb +1 -0
  20. data/lib/selenium/webdriver/common/child_process.rb +8 -2
  21. data/lib/selenium/webdriver/common/driver.rb +21 -15
  22. data/lib/selenium/webdriver/common/driver_extensions/has_bidi.rb +1 -1
  23. data/lib/selenium/webdriver/common/driver_extensions/has_fedcm_dialog.rb +55 -0
  24. data/lib/selenium/webdriver/common/driver_finder.rb +66 -14
  25. data/lib/selenium/webdriver/common/error.rb +21 -21
  26. data/lib/selenium/webdriver/common/fedcm/account.rb +50 -0
  27. data/lib/selenium/webdriver/common/fedcm/dialog.rb +74 -0
  28. data/lib/selenium/webdriver/common/fedcm.rb +27 -0
  29. data/lib/selenium/webdriver/common/interactions/pointer_cancel.rb +1 -1
  30. data/lib/selenium/webdriver/common/interactions/wheel_input.rb +1 -1
  31. data/lib/selenium/webdriver/common/local_driver.rb +8 -1
  32. data/lib/selenium/webdriver/common/logger.rb +2 -2
  33. data/lib/selenium/webdriver/common/manager.rb +1 -1
  34. data/lib/selenium/webdriver/common/options.rb +1 -1
  35. data/lib/selenium/webdriver/common/platform.rb +3 -1
  36. data/lib/selenium/webdriver/common/script.rb +45 -0
  37. data/lib/selenium/webdriver/common/search_context.rb +10 -2
  38. data/lib/selenium/webdriver/common/selenium_manager.rb +36 -73
  39. data/lib/selenium/webdriver/common/service.rb +11 -4
  40. data/lib/selenium/webdriver/common/socket_poller.rb +1 -1
  41. data/lib/selenium/webdriver/common/target_locator.rb +1 -2
  42. data/lib/selenium/webdriver/common/wait.rb +1 -1
  43. data/lib/selenium/webdriver/common/websocket_connection.rb +12 -0
  44. data/lib/selenium/webdriver/common.rb +4 -0
  45. data/lib/selenium/webdriver/devtools/network_interceptor.rb +1 -1
  46. data/lib/selenium/webdriver/edge/service.rb +1 -1
  47. data/lib/selenium/webdriver/firefox/options.rb +3 -0
  48. data/lib/selenium/webdriver/firefox/profile.rb +11 -5
  49. data/lib/selenium/webdriver/firefox/profiles_ini.rb +1 -1
  50. data/lib/selenium/webdriver/firefox/service.rb +1 -0
  51. data/lib/selenium/webdriver/ie/options.rb +3 -2
  52. data/lib/selenium/webdriver/ie/service.rb +1 -0
  53. data/lib/selenium/webdriver/remote/bidi_bridge.rb +44 -0
  54. data/lib/selenium/webdriver/remote/bridge/commands.rb +13 -1
  55. data/lib/selenium/webdriver/remote/bridge/locator_converter.rb +76 -0
  56. data/lib/selenium/webdriver/remote/bridge.rb +87 -46
  57. data/lib/selenium/webdriver/remote/capabilities.rb +1 -1
  58. data/lib/selenium/webdriver/remote/http/common.rb +21 -3
  59. data/lib/selenium/webdriver/remote/http/curb.rb +11 -5
  60. data/lib/selenium/webdriver/remote/response.rb +12 -19
  61. data/lib/selenium/webdriver/remote/server_error.rb +1 -1
  62. data/lib/selenium/webdriver/remote.rb +2 -1
  63. data/lib/selenium/webdriver/safari/service.rb +1 -1
  64. data/lib/selenium/webdriver/support/guards/guard.rb +8 -9
  65. data/lib/selenium/webdriver/version.rb +1 -1
  66. data/lib/selenium/webdriver.rb +1 -1
  67. data/selenium-webdriver.gemspec +9 -6
  68. 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, Element::ELEMENT_KEY => element)
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
- Element.new self, element_id_from(execute(:get_active_element))
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 = convert_locator(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
- Element.new self, element_id_from(id)
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 = convert_locator(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| Element.new self, element_id_from(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 Element.new(self, element_id) if element_id
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[Element::ELEMENT_KEY]
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
@@ -99,7 +99,7 @@ module Selenium
99
99
  end
100
100
 
101
101
  def camel_case(str_or_sym)
102
- str_or_sym.to_s.gsub(/_([a-z])/) { Regexp.last_match(1).upcase }
102
+ str_or_sym.to_s.gsub(/_([a-z])/) { Regexp.last_match(1)&.upcase }
103
103
  end
104
104
 
105
105
  private
@@ -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 = DEFAULT_HEADERS.dup
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 = false
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 = MAX_REDIRECTS
90
+ c.max_redirects = MAX_REDIRECTS
84
91
  c.follow_location = true
85
- c.timeout = @timeout if @timeout
86
- c.verbose = WebDriver.logger.debug?
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 = 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.set_backtrace(caller)
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 add_backtrace(ex, server_trace)
63
- return unless server_trace
64
-
65
- backtrace = case server_trace
66
- when Array
67
- backtrace_from_remote(server_trace)
68
- when String
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
- meth = frame['methodName']
74
+ method = frame['methodName']
82
75
 
83
76
  class_name = frame['className']
84
77
  file = "#{class_name}(#{file})" if class_name
85
78
 
86
- meth = 'unknown' if meth.nil? || meth.empty?
79
+ method = 'unknown' if method.nil? || method.empty?
87
80
 
88
- "[remote server] #{file}:#{line}:in `#{meth}'"
81
+ "[remote server] #{file}:#{line}:in `#{method}'"
89
82
  end
90
83
  end
91
84
 
@@ -23,7 +23,7 @@ module Selenium
23
23
  class ServerError < StandardError
24
24
  def initialize(response)
25
25
  if response.is_a? String
26
- super(response)
26
+ super
27
27
  else
28
28
  super("status code #{response.code}; payload #{response.payload}")
29
29
  end
@@ -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, 'selenium/webdriver/remote/http/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.delete(:reason)
39
+ @reason = @guarded[:reason] || 'No reason given'
40
+ @guarded[:reason] = @reason
40
41
  end
41
42
 
42
43
  def message
43
- details = case @reason
44
+ details = case reason
44
45
  when Integer
45
- "Bug Filed: #{@tracker}/#{@reason}"
46
+ "Bug Filed: #{tracker}/#{reason}"
46
47
  when Symbol
47
- @messages[@reason]
48
- when String
49
- @reason
48
+ messages[reason]
50
49
  else
51
- 'no reason given'
50
+ "Guarded by #{guarded};"
52
51
  end
53
52
 
54
- case @type
53
+ case type
55
54
  when :exclude
56
55
  "Test skipped because it breaks test run; #{details}"
57
56
  when :flaky
@@ -19,6 +19,6 @@
19
19
 
20
20
  module Selenium
21
21
  module WebDriver
22
- VERSION = '4.17.0'
22
+ VERSION = '4.26.0'
23
23
  end # WebDriver
24
24
  end # Selenium
@@ -49,7 +49,7 @@ module Selenium
49
49
  # @api private
50
50
 
51
51
  def self.root
52
- @root ||= File.expand_path('..', __dir__)
52
+ @root ||= File.expand_path('..', __dir__.to_s)
53
53
  end
54
54
 
55
55
  #
@@ -47,18 +47,21 @@ Gem::Specification.new do |s|
47
47
  s.bindir = 'bin'
48
48
  s.require_paths = ['lib']
49
49
 
50
- s.add_runtime_dependency 'base64', ['~> 0.2']
51
- s.add_runtime_dependency 'rexml', ['~> 3.2', '>= 3.2.5']
52
- s.add_runtime_dependency 'rubyzip', ['>= 1.2.2', '< 3.0']
53
- s.add_runtime_dependency 'websocket', ['~> 1.0']
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.42']
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