selenium-webdriver 2.53.4 → 3.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (122) hide show
  1. data/CHANGES +24 -18
  2. data/README.md +2 -3
  3. data/lib/selenium/server.rb +64 -68
  4. data/lib/selenium/webdriver.rb +5 -9
  5. data/lib/selenium/webdriver/chrome.rb +18 -3
  6. data/lib/selenium/webdriver/chrome/bridge.rb +13 -16
  7. data/lib/selenium/webdriver/chrome/profile.rb +7 -9
  8. data/lib/selenium/webdriver/chrome/service.rb +8 -84
  9. data/lib/selenium/webdriver/common.rb +1 -2
  10. data/lib/selenium/webdriver/common/action_builder.rb +28 -38
  11. data/lib/selenium/webdriver/common/alert.rb +7 -10
  12. data/lib/selenium/webdriver/common/bridge_helper.rb +10 -15
  13. data/lib/selenium/webdriver/common/driver.rb +19 -28
  14. data/lib/selenium/webdriver/common/driver_extensions/has_input_devices.rb +0 -3
  15. data/lib/selenium/webdriver/common/driver_extensions/has_location.rb +4 -6
  16. data/lib/selenium/webdriver/common/driver_extensions/has_network_connection.rb +4 -5
  17. data/lib/selenium/webdriver/common/driver_extensions/has_remote_status.rb +0 -2
  18. data/lib/selenium/webdriver/common/driver_extensions/has_session_id.rb +0 -2
  19. data/lib/selenium/webdriver/common/driver_extensions/has_touch_screen.rb +0 -2
  20. data/lib/selenium/webdriver/common/driver_extensions/has_web_storage.rb +0 -3
  21. data/lib/selenium/webdriver/common/driver_extensions/rotatable.rb +3 -6
  22. data/lib/selenium/webdriver/common/driver_extensions/takes_screenshot.rb +2 -5
  23. data/lib/selenium/webdriver/common/driver_extensions/uploads_files.rb +2 -5
  24. data/lib/selenium/webdriver/common/element.rb +27 -29
  25. data/lib/selenium/webdriver/common/error.rb +17 -20
  26. data/lib/selenium/webdriver/common/file_reaper.rb +3 -9
  27. data/lib/selenium/webdriver/common/html5/local_storage.rb +6 -8
  28. data/lib/selenium/webdriver/common/html5/session_storage.rb +6 -8
  29. data/lib/selenium/webdriver/common/html5/shared_web_storage.rb +6 -15
  30. data/lib/selenium/webdriver/common/keyboard.rb +7 -12
  31. data/lib/selenium/webdriver/common/keys.rb +67 -69
  32. data/lib/selenium/webdriver/common/log_entry.rb +3 -4
  33. data/lib/selenium/webdriver/common/logs.rb +2 -4
  34. data/lib/selenium/webdriver/common/mouse.rb +9 -12
  35. data/lib/selenium/webdriver/common/navigation.rb +2 -4
  36. data/lib/selenium/webdriver/common/options.rb +16 -19
  37. data/lib/selenium/webdriver/common/platform.rb +61 -90
  38. data/lib/selenium/webdriver/common/port_prober.rb +1 -2
  39. data/lib/selenium/webdriver/common/profile_helper.rb +5 -8
  40. data/lib/selenium/webdriver/common/proxy.rb +58 -70
  41. data/lib/selenium/webdriver/common/search_context.rb +15 -19
  42. data/lib/selenium/webdriver/common/service.rb +127 -0
  43. data/lib/selenium/webdriver/common/socket_lock.rb +5 -11
  44. data/lib/selenium/webdriver/common/socket_poller.rb +4 -9
  45. data/lib/selenium/webdriver/common/target_locator.rb +11 -13
  46. data/lib/selenium/webdriver/common/timeouts.rb +4 -6
  47. data/lib/selenium/webdriver/common/touch_action_builder.rb +2 -4
  48. data/lib/selenium/webdriver/common/touch_screen.rb +15 -18
  49. data/lib/selenium/webdriver/common/w3c_error.rb +3 -6
  50. data/lib/selenium/webdriver/common/wait.rb +6 -11
  51. data/lib/selenium/webdriver/common/window.rb +12 -15
  52. data/lib/selenium/webdriver/common/zipper.rb +6 -8
  53. data/lib/selenium/webdriver/edge.rb +18 -3
  54. data/lib/selenium/webdriver/edge/bridge.rb +11 -16
  55. data/lib/selenium/webdriver/edge/legacy_support.rb +38 -39
  56. data/lib/selenium/webdriver/edge/service.rb +8 -82
  57. data/lib/selenium/webdriver/firefox.rb +25 -6
  58. data/lib/selenium/webdriver/firefox/binary.rb +37 -53
  59. data/lib/selenium/webdriver/firefox/bridge.rb +3 -6
  60. data/lib/selenium/webdriver/firefox/extension.rb +4 -6
  61. data/lib/selenium/webdriver/firefox/extension/prefs.json +1 -10
  62. data/lib/selenium/webdriver/firefox/extension/webdriver.xpi +0 -0
  63. data/lib/selenium/webdriver/firefox/launcher.rb +8 -11
  64. data/lib/selenium/webdriver/firefox/profile.rb +40 -42
  65. data/lib/selenium/webdriver/firefox/profiles_ini.rb +8 -15
  66. data/lib/selenium/webdriver/firefox/service.rb +23 -79
  67. data/lib/selenium/webdriver/firefox/util.rb +0 -2
  68. data/lib/selenium/webdriver/firefox/w3c_bridge.rb +2 -4
  69. data/lib/selenium/webdriver/ie.rb +16 -7
  70. data/lib/selenium/webdriver/ie/bridge.rb +16 -23
  71. data/lib/selenium/webdriver/{iphone.rb → ie/service.rb} +26 -4
  72. data/lib/selenium/webdriver/phantomjs.rb +8 -3
  73. data/lib/selenium/webdriver/phantomjs/bridge.rb +9 -11
  74. data/lib/selenium/webdriver/phantomjs/service.rb +17 -81
  75. data/lib/selenium/webdriver/remote.rb +0 -2
  76. data/lib/selenium/webdriver/remote/bridge.rb +193 -191
  77. data/lib/selenium/webdriver/remote/capabilities.rb +60 -90
  78. data/lib/selenium/webdriver/remote/commands.rb +197 -192
  79. data/lib/selenium/webdriver/remote/http/common.rb +15 -13
  80. data/lib/selenium/webdriver/remote/http/curb.rb +5 -9
  81. data/lib/selenium/webdriver/remote/http/default.rb +32 -37
  82. data/lib/selenium/webdriver/remote/http/persistent.rb +4 -6
  83. data/lib/selenium/webdriver/remote/response.rb +13 -21
  84. data/lib/selenium/webdriver/remote/server_error.rb +1 -3
  85. data/lib/selenium/webdriver/remote/w3c_bridge.rb +200 -195
  86. data/lib/selenium/webdriver/remote/w3c_capabilities.rb +38 -46
  87. data/lib/selenium/webdriver/remote/w3c_commands.rb +116 -113
  88. data/lib/selenium/webdriver/safari.rb +23 -7
  89. data/lib/selenium/{client/javascript_frameworks/jquery.rb → webdriver/safari/apple_bridge.rb} +28 -9
  90. data/lib/selenium/webdriver/safari/browser.rb +0 -2
  91. data/lib/selenium/webdriver/safari/{bridge.rb → legacy_bridge.rb} +12 -9
  92. data/lib/selenium/webdriver/safari/options.rb +3 -4
  93. data/lib/selenium/webdriver/safari/resources/client.js +56 -7255
  94. data/lib/selenium/webdriver/safari/server.rb +18 -24
  95. data/lib/selenium/{client/javascript_frameworks/prototype.rb → webdriver/safari/service.rb} +27 -9
  96. data/lib/selenium/webdriver/support.rb +1 -0
  97. data/lib/selenium/webdriver/support/abstract_event_listener.rb +17 -2
  98. data/lib/selenium/webdriver/support/block_event_listener.rb +1 -3
  99. data/lib/selenium/webdriver/support/color.rb +55 -38
  100. data/lib/selenium/webdriver/{android.rb → support/escaper.rb} +19 -4
  101. data/lib/selenium/webdriver/support/event_firing_bridge.rb +36 -38
  102. data/lib/selenium/webdriver/support/select.rb +33 -84
  103. data/selenium-webdriver.gemspec +23 -23
  104. metadata +19 -30
  105. data/lib/selenium-client.rb +0 -21
  106. data/lib/selenium/client.rb +0 -57
  107. data/lib/selenium/client/base.rb +0 -151
  108. data/lib/selenium/client/driver.rb +0 -29
  109. data/lib/selenium/client/errors.rb +0 -28
  110. data/lib/selenium/client/extensions.rb +0 -132
  111. data/lib/selenium/client/idiomatic.rb +0 -507
  112. data/lib/selenium/client/javascript_expression_builder.rb +0 -135
  113. data/lib/selenium/client/legacy_driver.rb +0 -1722
  114. data/lib/selenium/client/protocol.rb +0 -123
  115. data/lib/selenium/client/selenium_helper.rb +0 -49
  116. data/lib/selenium/rake/server_task.rb +0 -176
  117. data/lib/selenium/webdriver/android/bridge.rb +0 -68
  118. data/lib/selenium/webdriver/common/core_ext/base64.rb +0 -28
  119. data/lib/selenium/webdriver/common/core_ext/dir.rb +0 -61
  120. data/lib/selenium/webdriver/common/html5/location.rb +0 -19
  121. data/lib/selenium/webdriver/ie/server.rb +0 -133
  122. data/lib/selenium/webdriver/iphone/bridge.rb +0 -64
@@ -23,8 +23,8 @@ module Selenium
23
23
  module Http
24
24
  class Common
25
25
  MAX_REDIRECTS = 20 # same as chromium/gecko
26
- CONTENT_TYPE = "application/json"
27
- DEFAULT_HEADERS = { "Accept" => CONTENT_TYPE }
26
+ CONTENT_TYPE = 'application/json'.freeze
27
+ DEFAULT_HEADERS = {'Accept' => CONTENT_TYPE}.freeze
28
28
 
29
29
  attr_accessor :timeout
30
30
  attr_writer :server_url
@@ -38,22 +38,22 @@ module Selenium
38
38
  end
39
39
 
40
40
  def call(verb, url, command_hash)
41
- url = server_url.merge(url) unless url.kind_of?(URI)
41
+ url = server_url.merge(url) unless url.is_a?(URI)
42
42
  headers = DEFAULT_HEADERS.dup
43
- headers['Cache-Control'] = "no-cache" if verb == :get
43
+ headers['Cache-Control'] = 'no-cache' if verb == :get
44
44
 
45
45
  if command_hash
46
46
  payload = JSON.generate(command_hash)
47
- headers["Content-Type"] = "#{CONTENT_TYPE}; charset=utf-8"
48
- headers["Content-Length"] = payload.bytesize.to_s if [:post, :put].include?(verb)
47
+ headers['Content-Type'] = "#{CONTENT_TYPE}; charset=utf-8"
48
+ headers['Content-Length'] = payload.bytesize.to_s if [:post, :put].include?(verb)
49
49
 
50
50
  if $DEBUG
51
51
  puts " >>> #{url} | #{payload}"
52
52
  puts " > #{headers.inspect}"
53
53
  end
54
54
  elsif verb == :post
55
- payload = "{}"
56
- headers["Content-Length"] = "2"
55
+ payload = '{}'
56
+ headers['Content-Length'] = '2'
57
57
  end
58
58
 
59
59
  request verb, url, headers, payload
@@ -62,15 +62,18 @@ module Selenium
62
62
  private
63
63
 
64
64
  def server_url
65
- @server_url or raise Error::WebDriverError, "server_url not set"
65
+ return @server_url if @server_url
66
+ raise Error::WebDriverError, 'server_url not set'
66
67
  end
67
68
 
68
- def request(verb, url, headers, payload)
69
- raise NotImplementedError, "subclass responsibility"
69
+ def request(*)
70
+ raise NotImplementedError, 'subclass responsibility'
70
71
  end
71
72
 
72
73
  def create_response(code, body, content_type)
73
- code, body, content_type = code.to_i, body.to_s.strip, content_type.to_s
74
+ code = code.to_i
75
+ body = body.to_s.strip
76
+ content_type = content_type.to_s
74
77
  puts "<- #{body}\n" if $DEBUG
75
78
 
76
79
  if content_type.include? CONTENT_TYPE
@@ -85,7 +88,6 @@ module Selenium
85
88
  raise Error::WebDriverError, msg
86
89
  end
87
90
  end
88
-
89
91
  end # Common
90
92
  end # Http
91
93
  end # Remote
@@ -22,12 +22,10 @@ require 'curb'
22
22
  module Selenium
23
23
  module WebDriver
24
24
  module Remote
25
-
26
25
  # added for rescue
27
26
  Bridge::QUIT_ERRORS << Curl::Err::RecvError
28
27
 
29
28
  module Http
30
-
31
29
  #
32
30
  # An alternative to the default Net::HTTP client.
33
31
  #
@@ -42,15 +40,14 @@ module Selenium
42
40
  #
43
41
 
44
42
  class Curb < Common
45
-
46
43
  private
47
44
 
48
45
  def request(verb, url, headers, payload)
49
- client.url = url.to_s
46
+ client.url = url.to_s
50
47
 
51
48
  # workaround for http://github.com/taf2/curb/issues/issue/40
52
49
  # curb will handle this for us anyway
53
- headers.delete "Content-Length"
50
+ headers.delete 'Content-Length'
54
51
 
55
52
  client.headers = headers
56
53
 
@@ -62,10 +59,10 @@ module Selenium
62
59
  when :get
63
60
  client.http_get
64
61
  when :post
65
- client.post_body = payload || ""
62
+ client.post_body = payload || ''
66
63
  client.http_post
67
64
  when :put
68
- client.put_data = payload || ""
65
+ client.put_data = payload || ''
69
66
  client.http_put
70
67
  when :delete
71
68
  client.http_delete
@@ -85,12 +82,11 @@ module Selenium
85
82
  c.max_redirects = MAX_REDIRECTS
86
83
  c.follow_location = true
87
84
  c.timeout = @timeout if @timeout
88
- c.verbose = !!$DEBUG
85
+ c.verbose = $DEBUG
89
86
 
90
87
  c
91
88
  )
92
89
  end
93
-
94
90
  end # Curb
95
91
  end # Http
96
92
  end # Remote
@@ -24,7 +24,6 @@ module Selenium
24
24
  module WebDriver
25
25
  module Remote
26
26
  module Http
27
-
28
27
  # @api private
29
28
  class Default < Common
30
29
  attr_accessor :proxy
@@ -33,18 +32,18 @@ module Selenium
33
32
 
34
33
  def http
35
34
  @http ||= (
36
- http = new_http_client
37
- if server_url.scheme == "https"
38
- http.use_ssl = true
39
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE
40
- end
35
+ http = new_http_client
36
+ if server_url.scheme == 'https'
37
+ http.use_ssl = true
38
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
39
+ end
41
40
 
42
- if @timeout
43
- http.open_timeout = @timeout
44
- http.read_timeout = @timeout
45
- end
41
+ if @timeout
42
+ http.open_timeout = @timeout
43
+ http.read_timeout = @timeout
44
+ end
46
45
 
47
- http
46
+ http
48
47
  )
49
48
  end
50
49
 
@@ -76,15 +75,12 @@ module Selenium
76
75
  retry
77
76
 
78
77
  rescue Errno::ECONNREFUSED => ex
79
- if use_proxy?
80
- raise ex.class, "using proxy: #{proxy.http}"
81
- else
82
- raise
83
- end
78
+ raise ex.class, "using proxy: #{proxy.http}" if use_proxy?
79
+ raise
84
80
  end
85
81
 
86
- if response.kind_of? Net::HTTPRedirection
87
- raise Error::WebDriverError, "too many redirects" if redirects >= MAX_REDIRECTS
82
+ if response.is_a? Net::HTTPRedirection
83
+ raise Error::WebDriverError, 'too many redirects' if redirects >= MAX_REDIRECTS
88
84
  request(:get, URI.parse(response['Location']), DEFAULT_HEADERS.dup, nil, redirects + 1)
89
85
  else
90
86
  create_response response.code, response.body, response.content_type
@@ -109,7 +105,8 @@ module Selenium
109
105
 
110
106
  def new_http_client
111
107
  if use_proxy?
112
- unless proxy.respond_to?(:http) && url = @proxy.http
108
+ url = @proxy.http
109
+ unless proxy.respond_to?(:http) && url
113
110
  raise Error::WebDriverError, "expected HTTP proxy, got #{@proxy.inspect}"
114
111
  end
115
112
 
@@ -124,13 +121,13 @@ module Selenium
124
121
 
125
122
  def proxy
126
123
  @proxy ||= (
127
- proxy = ENV['http_proxy'] || ENV['HTTP_PROXY']
128
- no_proxy = ENV['no_proxy'] || ENV['NO_PROXY']
124
+ proxy = ENV['http_proxy'] || ENV['HTTP_PROXY']
125
+ no_proxy = ENV['no_proxy'] || ENV['NO_PROXY']
129
126
 
130
- if proxy
131
- proxy = "http://#{proxy}" unless proxy.start_with?("http://")
132
- Proxy.new(:http => proxy, :no_proxy => no_proxy)
133
- end
127
+ if proxy
128
+ proxy = "http://#{proxy}" unless proxy.start_with?('http://')
129
+ Proxy.new(http: proxy, no_proxy: no_proxy)
130
+ end
134
131
  )
135
132
  end
136
133
 
@@ -138,24 +135,22 @@ module Selenium
138
135
  return false if proxy.nil?
139
136
 
140
137
  if proxy.no_proxy
141
- ignored = proxy.no_proxy.split(",").any? do |host|
142
- host == "*" ||
143
- host == server_url.host || (
144
- begin
145
- IPAddr.new(host).include?(server_url.host)
146
- rescue ArgumentError
147
- false
148
- end
149
- )
150
-
138
+ ignored = proxy.no_proxy.split(',').any? do |host|
139
+ host == '*' ||
140
+ host == server_url.host || (
141
+ begin
142
+ IPAddr.new(host).include?(server_url.host)
143
+ rescue ArgumentError
144
+ false
145
+ end
146
+ )
151
147
  end
152
148
 
153
- not ignored
149
+ !ignored
154
150
  else
155
151
  true
156
152
  end
157
153
  end
158
-
159
154
  end # Default
160
155
  end # Http
161
156
  end # Remote
@@ -23,10 +23,8 @@ module Selenium
23
23
  module WebDriver
24
24
  module Remote
25
25
  module Http
26
-
27
26
  # @api private
28
27
  class Persistent < Default
29
-
30
28
  def close
31
29
  @http.shutdown if @http
32
30
  end
@@ -37,19 +35,19 @@ module Selenium
37
35
  proxy = nil
38
36
 
39
37
  if @proxy
40
- unless @proxy.respond_to?(:http) && url = @proxy.http
41
- raise Error::WebDriverError, "expected HTTP proxy, got #{@proxy.inspect}"
38
+ unless @proxy.respond_to?(:http)
39
+ url = @proxy.http
40
+ raise Error::WebDriverError, "expected HTTP proxy, got #{@proxy.inspect}" unless url
42
41
  end
43
42
  proxy = URI.parse(url)
44
43
  end
45
44
 
46
- Net::HTTP::Persistent.new "webdriver", proxy
45
+ Net::HTTP::Persistent.new 'webdriver', proxy
47
46
  end
48
47
 
49
48
  def response_for(request)
50
49
  http.request server_url, request
51
50
  end
52
-
53
51
  end # Persistent
54
52
  end # Http
55
53
  end # Remote
@@ -20,10 +20,8 @@
20
20
  module Selenium
21
21
  module WebDriver
22
22
  module Remote
23
-
24
23
  # @api private
25
24
  class Response
26
-
27
25
  attr_reader :code, :payload
28
26
  attr_writer :payload
29
27
 
@@ -49,9 +47,10 @@ module Selenium
49
47
 
50
48
  case val
51
49
  when Hash
52
- msg = val['message'] or return "unknown error"
53
- msg << ": #{val['alert']['text'].inspect}" if val['alert'].kind_of?(Hash) && val['alert']['text']
54
- msg << " (#{ val['class'] })" if val['class']
50
+ msg = val['message']
51
+ return 'unknown error' unless msg
52
+ msg << ": #{val['alert']['text'].inspect}" if val['alert'].is_a?(Hash) && val['alert']['text']
53
+ msg << " (#{val['class']})" if val['class']
55
54
  msg
56
55
  when String
57
56
  val
@@ -67,34 +66,28 @@ module Selenium
67
66
  private
68
67
 
69
68
  def assert_ok
70
- if e = error()
71
- raise e
72
- elsif @code.nil? || @code >= 400
73
- raise Error::ServerError, self
74
- end
69
+ e = error
70
+ raise e if e
71
+ return unless @code.nil? || @code >= 400
72
+ raise Error::ServerError, self
75
73
  end
76
74
 
77
75
  def add_backtrace(ex)
78
- unless value.kind_of?(Hash) && value['stackTrace']
79
- return
80
- end
76
+ return unless value.is_a?(Hash) && value['stackTrace']
81
77
 
82
78
  server_trace = value['stackTrace']
83
79
 
84
80
  backtrace = server_trace.map do |frame|
85
- next unless frame.kind_of?(Hash)
81
+ next unless frame.is_a?(Hash)
86
82
 
87
83
  file = frame['fileName']
88
84
  line = frame['lineNumber']
89
85
  meth = frame['methodName']
90
86
 
91
- if class_name = frame['className']
92
- file = "#{class_name}(#{file})"
93
- end
87
+ class_name = frame['className']
88
+ file = "#{class_name}(#{file})" if class_name
94
89
 
95
- if meth.nil? || meth.empty?
96
- meth = 'unknown'
97
- end
90
+ meth = 'unknown' if meth.nil? || meth.empty?
98
91
 
99
92
  "[remote server] #{file}:#{line}:in `#{meth}'"
100
93
  end.compact
@@ -109,7 +102,6 @@ module Selenium
109
102
  def value
110
103
  @payload['value'] || @payload['message']
111
104
  end
112
-
113
105
  end # Response
114
106
  end # Remote
115
107
  end # WebDriver
@@ -21,15 +21,13 @@ module Selenium
21
21
  module WebDriver
22
22
  module Error
23
23
  class ServerError < StandardError
24
-
25
24
  def initialize(response)
26
- if response.kind_of? String
25
+ if response.is_a? String
27
26
  super(response)
28
27
  else
29
28
  super("status code #{response.code}")
30
29
  end
31
30
  end
32
-
33
31
  end # ServerError
34
32
  end # Error
35
33
  end # WebDriver
@@ -22,7 +22,6 @@ require 'json'
22
22
  module Selenium
23
23
  module WebDriver
24
24
  module Remote
25
-
26
25
  #
27
26
  # Low level bridge to the remote server, through which the rest of the API works.
28
27
  #
@@ -32,6 +31,7 @@ module Selenium
32
31
  class W3CBridge
33
32
  include BridgeHelper
34
33
 
34
+ # TODO: constant shouldn't be modified in class
35
35
  COMMANDS = {}
36
36
 
37
37
  #
@@ -62,16 +62,13 @@ module Selenium
62
62
  #
63
63
 
64
64
  def initialize(opts = {})
65
- if opts.fetch(:desired_capabilities, {})[:browser_name] == 'MicrosoftEdge'
66
- require_relative '../edge/legacy_support'
67
- extend Edge::LegacySupport
68
- end
65
+ edge_check(opts)
69
66
 
70
67
  opts = opts.dup
71
68
 
72
- http_client = opts.delete(:http_client) { Http::Default.new }
69
+ http_client = opts.delete(:http_client) { Http::Default.new }
73
70
  desired_capabilities = opts.delete(:desired_capabilities) { W3CCapabilities.firefox }
74
- url = opts.delete(:url) { "http://#{Platform.localhost}:4444/wd/hub" }
71
+ url = opts.delete(:url) { "http://#{Platform.localhost}:4444/wd/hub" }
75
72
 
76
73
  desired_capabilities = W3CCapabilities.send(desired_capabilities) if desired_capabilities.is_a? Symbol
77
74
 
@@ -81,23 +78,30 @@ module Selenium
81
78
  raise ArgumentError, "unknown option#{'s' if opts.size != 1}: #{opts.inspect}"
82
79
  end
83
80
 
84
- uri = url.kind_of?(URI) ? url : URI.parse(url)
85
- uri.path += "/" unless uri.path =~ /\/$/
81
+ uri = url.is_a?(URI) ? url : URI.parse(url)
82
+ uri.path += '/' unless uri.path =~ %r{\/$}
86
83
 
87
84
  http_client.server_url = uri
88
85
 
89
- @http = http_client
90
- @capabilities = create_session(desired_capabilities)
86
+ @http = http_client
87
+ @capabilities = create_session(desired_capabilities)
91
88
  @file_detector = nil
92
89
  end
93
90
 
94
91
  def browser
95
92
  @browser ||= (
96
- name = @capabilities.browser_name
97
- name ? name.gsub(" ", "_").to_sym : 'unknown'
93
+ name = @capabilities.browser_name
94
+ name ? name.tr(' ', '_').to_sym : 'unknown'
98
95
  )
99
96
  end
100
97
 
98
+ def edge_check(opts)
99
+ caps = opts[:desired_capabilities]
100
+ return unless caps && caps[:browser_name] && caps[:browser_name] == 'MicrosoftEdge'
101
+ require_relative '../edge/legacy_support'
102
+ extend Edge::LegacySupport
103
+ end
104
+
101
105
  def driver_extensions
102
106
  [
103
107
  DriverExtensions::HasInputDevices,
@@ -116,14 +120,15 @@ module Selenium
116
120
  #
117
121
 
118
122
  def session_id
119
- @session_id || raise(Error::WebDriverError, "no current session exists")
123
+ @session_id || raise(Error::WebDriverError, 'no current session exists')
120
124
  end
121
125
 
122
126
  def create_session(desired_capabilities)
123
- resp = raw_execute :newSession, {}, :desiredCapabilities => desired_capabilities
124
- @session_id = resp['sessionId'] or raise Error::WebDriverError, 'no sessionId in returned payload'
127
+ resp = raw_execute :newSession, {}, {desiredCapabilities: desired_capabilities}
128
+ @session_id = resp['sessionId']
129
+ return W3CCapabilities.json_create resp['value'] if @session_id
125
130
 
126
- W3CCapabilities.json_create resp['value']
131
+ raise Error::WebDriverError, 'no sessionId in returned payload'
127
132
  end
128
133
 
129
134
  def status
@@ -133,38 +138,38 @@ module Selenium
133
138
  end
134
139
 
135
140
  def get(url)
136
- execute :get, {}, :url => url
141
+ execute :get, {}, {url: url}
137
142
  end
138
143
 
139
- def setImplicitWaitTimeout(milliseconds)
140
- setTimeout('implicit', milliseconds)
144
+ def implicit_wait_timeout=(milliseconds)
145
+ timeout('implicit', milliseconds)
141
146
  end
142
147
 
143
- def setScriptTimeout(milliseconds)
144
- setTimeout('script', milliseconds)
148
+ def script_timeout=(milliseconds)
149
+ timeout('script', milliseconds)
145
150
  end
146
151
 
147
- def setTimeout(type, milliseconds)
148
- execute :setTimeout, {}, :type => type, :ms => milliseconds
152
+ def timeout(type, milliseconds)
153
+ execute :setTimeout, {}, {type: type, ms: milliseconds}
149
154
  end
150
155
 
151
156
  #
152
157
  # alerts
153
158
  #
154
159
 
155
- def acceptAlert
160
+ def accept_alert
156
161
  execute :acceptAlert
157
162
  end
158
163
 
159
- def dismissAlert
164
+ def dismiss_alert
160
165
  execute :dismissAlert
161
166
  end
162
167
 
163
- def setAlertValue(keys)
164
- execute :sendAlertText, {}, {:handler => 'prompt', :message => keys}
168
+ def alert=(keys)
169
+ execute :sendAlertText, {}, {handler: 'prompt', text: keys}
165
170
  end
166
171
 
167
- def getAlertText
172
+ def alert_text
168
173
  execute :getAlertText
169
174
  end
170
175
 
@@ -172,46 +177,46 @@ module Selenium
172
177
  # navigation
173
178
  #
174
179
 
175
- def goBack
180
+ def go_back
176
181
  execute :back
177
182
  end
178
183
 
179
- def goForward
184
+ def go_forward
180
185
  execute :forward
181
186
  end
182
187
 
183
- def getCurrentUrl
188
+ def url
184
189
  execute :getCurrentUrl
185
190
  end
186
191
 
187
- def getTitle
192
+ def title
188
193
  execute :getTitle
189
194
  end
190
195
 
191
- def getPageSource
192
- executeScript("var source = document.documentElement.outerHTML;" +
193
- "if (!source) { source = new XMLSerializer().serializeToString(document); }" +
194
- "return source;")
196
+ def page_source
197
+ execute_script('var source = document.documentElement.outerHTML;' \
198
+ 'if (!source) { source = new XMLSerializer().serializeToString(document); }' \
199
+ 'return source;')
195
200
  end
196
201
 
197
- def switchToWindow(name)
198
- execute :switchToWindow, {}, :handle => name
202
+ def switch_to_window(name)
203
+ execute :switchToWindow, {}, {handle: name}
199
204
  end
200
205
 
201
- def switchToFrame(id)
206
+ def switch_to_frame(id)
202
207
  id = find_element_by('id', id) if id.is_a? String
203
- execute :switchToFrame, {}, :id => id
208
+ execute :switchToFrame, {}, {id: id}
204
209
  end
205
210
 
206
- def switchToParentFrame
211
+ def switch_to_parent_frame
207
212
  execute :switchToParentFrame
208
213
  end
209
214
 
210
- def switchToDefaultContent
211
- switchToFrame nil
215
+ def switch_to_default_content
216
+ switch_to_frame nil
212
217
  end
213
218
 
214
- QUIT_ERRORS = [IOError]
219
+ QUIT_ERRORS = [IOError].freeze
215
220
 
216
221
  def quit
217
222
  execute :deleteSession
@@ -231,34 +236,34 @@ module Selenium
231
236
  # window handling
232
237
  #
233
238
 
234
- def getWindowHandles
239
+ def window_handles
235
240
  execute :getWindowHandles
236
241
  end
237
242
 
238
- def getCurrentWindowHandle
243
+ def window_handle
239
244
  execute :getWindowHandle
240
245
  end
241
246
 
242
- def setWindowSize(width, height, handle = :current)
247
+ def resize_window(width, height, handle = :current)
243
248
  unless handle == :current
244
249
  raise Error::WebDriverError, 'Switch to desired window before changing its size'
245
250
  end
246
- execute :setWindowSize, {}, {:width => width,
247
- :height => height}
251
+ execute :setWindowSize, {}, {width: width,
252
+ height: height}
248
253
  end
249
254
 
250
- def maximizeWindow(handle = :current)
255
+ def maximize_window(handle = :current)
251
256
  unless handle == :current
252
257
  raise Error::UnsupportedOperationError, 'Switch to desired window before changing its size'
253
258
  end
254
259
  execute :maximizeWindow
255
260
  end
256
261
 
257
- def fullscreenWindow
262
+ def full_screen_window
258
263
  execute :fullscreenWindow
259
264
  end
260
265
 
261
- def getWindowSize(handle = :current)
266
+ def window_size(handle = :current)
262
267
  unless handle == :current
263
268
  raise Error::UnsupportedOperationError, 'Switch to desired window before getting its size'
264
269
  end
@@ -267,15 +272,15 @@ module Selenium
267
272
  Dimension.new data['width'], data['height']
268
273
  end
269
274
 
270
- def setWindowPosition(_x, _y, _handle = nil)
275
+ def reposition_window(_x, _y, _handle = nil)
271
276
  raise Error::UnsupportedOperationError, 'The W3C standard does not currently support setting the Window Position'
272
277
  end
273
278
 
274
- def getWindowPosition(_handle = nil)
279
+ def window_position(_handle = nil)
275
280
  raise Error::UnsupportedOperationError, 'The W3C standard does not currently support getting the Window Position'
276
281
  end
277
282
 
278
- def getScreenshot
283
+ def screenshot
279
284
  execute :takeScreenshot
280
285
  end
281
286
 
@@ -283,67 +288,67 @@ module Selenium
283
288
  # HTML 5
284
289
  #
285
290
 
286
- def getLocalStorageItem(key)
287
- executeScript("return localStorage.getItem('#{key}')")
288
- end
289
-
290
- def removeLocalStorageItem(key)
291
- executeScript("localStorage.removeItem('#{key}')")
292
- end
293
-
294
- def getLocalStorageKeys
295
- executeScript("return Object.keys(localStorage)")
291
+ def local_storage_item(key, value = nil)
292
+ if value
293
+ execute_script("localStorage.setItem('#{key}', '#{value}')")
294
+ else
295
+ execute_script("return localStorage.getItem('#{key}')")
296
+ end
296
297
  end
297
298
 
298
- def setLocalStorageItem(key, value)
299
- executeScript("localStorage.setItem('#{key}', '#{value}')")
299
+ def remove_local_storage_item(key)
300
+ execute_script("localStorage.removeItem('#{key}')")
300
301
  end
301
302
 
302
- def clearLocalStorage
303
- executeScript("localStorage.clear()")
303
+ def local_storage_keys
304
+ execute_script('return Object.keys(localStorage)')
304
305
  end
305
306
 
306
- def getLocalStorageSize
307
- executeScript("return localStorage.length")
307
+ def clear_local_storage
308
+ execute_script('localStorage.clear()')
308
309
  end
309
310
 
310
- def getSessionStorageItem(key)
311
- executeScript("return sessionStorage.getItem('#{key}')")
311
+ def local_storage_size
312
+ execute_script('return localStorage.length')
312
313
  end
313
314
 
314
- def removeSessionStorageItem(key)
315
- executeScript("sessionStorage.removeItem('#{key}')")
315
+ def session_storage_item(key, value = nil)
316
+ if value
317
+ execute_script("sessionStorage.setItem('#{key}', '#{value}')")
318
+ else
319
+ execute_script("return sessionStorage.getItem('#{key}')")
320
+ end
316
321
  end
317
322
 
318
- def getSessionStorageKeys
319
- executeScript("return Object.keys(sessionStorage)")
323
+ def remove_session_storage_item(key)
324
+ execute_script("sessionStorage.removeItem('#{key}')")
320
325
  end
321
326
 
322
- def setSessionStorageItem(key, value)
323
- executeScript("sessionStorage.setItem('#{key}', '#{value}')")
327
+ def session_storage_keys
328
+ execute_script('return Object.keys(sessionStorage)')
324
329
  end
325
330
 
326
- def clearSessionStorage
327
- executeScript("sessionStorage.clear()")
331
+ def clear_session_storage
332
+ execute_script('sessionStorage.clear()')
328
333
  end
329
334
 
330
- def getSessionStorageSize
331
- executeScript("return sessionStorage.length")
335
+ def session_storage_size
336
+ execute_script('return sessionStorage.length')
332
337
  end
333
338
 
334
- def getLocation
339
+ def location
335
340
  raise Error::UnsupportedOperationError, 'The W3C standard does not currently support getting location'
336
341
  end
337
342
 
338
- def setLocation(_lat, _lon, _alt)
343
+ def set_location(_lat, _lon, _alt)
339
344
  raise Error::UnsupportedOperationError, 'The W3C standard does not currently support setting location'
340
345
  end
341
346
 
342
- def getNetworkConnection
347
+ def network_connection
343
348
  raise Error::UnsupportedOperationError, 'The W3C standard does not currently support getting network connection'
344
349
  end
345
350
 
346
- def setNetworkConnection(_type)
351
+ def network_connection=(_type)
347
352
  raise Error::UnsupportedOperationError, 'The W3C standard does not currently support setting network connection'
348
353
  end
349
354
 
@@ -351,13 +356,13 @@ module Selenium
351
356
  # javascript execution
352
357
  #
353
358
 
354
- def executeScript(script, *args)
355
- result = execute :executeScript, {}, :script => script, :args => args
359
+ def execute_script(script, *args)
360
+ result = execute :executeScript, {}, {script: script, args: args}
356
361
  unwrap_script_result result
357
362
  end
358
363
 
359
- def executeAsyncScript(script, *args)
360
- result = execute :executeAsyncScript, {}, :script => script, :args => args
364
+ def execute_async_script(script, *args)
365
+ result = execute :executeAsyncScript, {}, {script: script, args: args}
361
366
  unwrap_script_result result
362
367
  end
363
368
 
@@ -365,139 +370,139 @@ module Selenium
365
370
  # cookies
366
371
  #
367
372
 
368
- def addCookie(cookie)
369
- execute :addCookie, {}, :cookie => cookie
373
+ def add_cookie(cookie)
374
+ execute :addCookie, {}, {cookie: cookie}
370
375
  end
371
376
 
372
- def deleteCookie(name)
373
- execute :deleteCookie, :name => name
377
+ def delete_cookie(name)
378
+ execute :deleteCookie, name: name
374
379
  end
375
380
 
376
- # TODO - write specs
377
- def getCookie(name)
378
- execute :getCookie, :name => name
381
+ # TODO: - write specs
382
+ def cookie(name)
383
+ execute :getCookie, name: name
379
384
  end
380
385
 
381
- def getAllCookies
386
+ def cookies
382
387
  execute :getAllCookies
383
388
  end
384
389
 
385
- def deleteAllCookies
386
- getAllCookies.each { |cookie| deleteCookie(cookie['name'])}
390
+ def delete_all_cookies
391
+ cookies.each { |cookie| delete_cookie(cookie['name']) }
387
392
  end
388
393
 
389
394
  #
390
395
  # actions
391
396
  #
392
397
 
393
- def clickElement(element)
394
- execute :elementClick, :id => element
398
+ def click_element(element)
399
+ execute :elementClick, id: element
395
400
  end
396
401
 
397
402
  def click
398
- execute :click, {}, :button => 0
403
+ execute :click, {}, {button: 0}
399
404
  end
400
405
 
401
- def doubleClick
406
+ def double_click
402
407
  execute :doubleClick
403
408
  end
404
409
 
405
- def contextClick
406
- execute :click, {}, :button => 2
410
+ def context_click
411
+ execute :click, {}, {button: 2}
407
412
  end
408
413
 
409
- def mouseDown
414
+ def mouse_down
410
415
  execute :mouseDown
411
416
  end
412
417
 
413
- def mouseUp
418
+ def mouse_up
414
419
  execute :mouseUp
415
420
  end
416
421
 
417
- def mouseMoveTo(element, x = nil, y = nil)
418
- params = { :element => element }
422
+ def mouse_move_to(element, x = nil, y = nil)
423
+ params = {element: element}
419
424
 
420
425
  if x && y
421
- params.merge! :xoffset => x, :yoffset => y
426
+ params[:xoffset] = x
427
+ params[:yoffset] = y
422
428
  end
423
429
 
424
430
  execute :mouseMoveTo, {}, params
425
431
  end
426
432
 
427
- def sendKeysToActiveElement(keys)
428
- sendKeysToElement(getActiveElement, keys)
433
+ def send_keys_to_active_element(keys)
434
+ send_keys_to_element(active_element, keys)
429
435
  end
430
436
 
431
- # TODO - Implement file verification
432
- def sendKeysToElement(element, keys)
433
- execute :elementSendKeys, {:id => element}, {:value => keys.join('').split(//)}
437
+ # TODO: - Implement file verification
438
+ def send_keys_to_element(element, keys)
439
+ execute :elementSendKeys, {id: element}, {value: keys.join('').split(//)}
434
440
  end
435
441
 
436
- def clearElement(element)
437
- execute :elementClear, :id => element
442
+ def clear_element(element)
443
+ execute :elementClear, id: element
438
444
  end
439
445
 
440
- def submitElement(element)
441
- executeScript("var e = arguments[0].ownerDocument.createEvent('Event');" +
442
- "e.initEvent('submit', true, true);" +
443
- "if (arguments[0].dispatchEvent(e)) { arguments[0].submit() }", element)
446
+ def submit_element(element)
447
+ execute_script("var e = arguments[0].ownerDocument.createEvent('Event');" \
448
+ "e.initEvent('submit', true, true);" \
449
+ 'if (arguments[0].dispatchEvent(e)) { arguments[0].submit() }', element)
444
450
  end
445
451
 
446
- def dragElement(element, right_by, down_by)
447
- execute :dragElement, {:id => element}, :x => right_by, :y => down_by
452
+ def drag_element(element, right_by, down_by)
453
+ execute :dragElement, {id: element}, {x: right_by, y: down_by}
448
454
  end
449
455
 
450
- def touchSingleTap(element)
451
- execute :touchSingleTap, {}, :element => element
456
+ def touch_single_tap(element)
457
+ execute :touchSingleTap, {}, {element: element}
452
458
  end
453
459
 
454
- def touchDoubleTap(element)
455
- execute :touchDoubleTap, {}, :element => element
460
+ def touch_double_tap(element)
461
+ execute :touchDoubleTap, {}, {element: element}
456
462
  end
457
463
 
458
- def touchLongPress(element)
459
- execute :touchLongPress, {}, :element => element
464
+ def touch_long_press(element)
465
+ execute :touchLongPress, {}, {element: element}
460
466
  end
461
467
 
462
- def touchDown(x, y)
463
- execute :touchDown, {}, :x => x, :y => y
468
+ def touch_down(x, y)
469
+ execute :touchDown, {}, {x: x, y: y}
464
470
  end
465
471
 
466
- def touchUp(x, y)
467
- execute :touchUp, {}, :x => x, :y => y
472
+ def touch_up(x, y)
473
+ execute :touchUp, {}, {x: x, y: y}
468
474
  end
469
475
 
470
- def touchMove(x, y)
471
- execute :touchMove, {}, :x => x, :y => y
476
+ def touch_move(x, y)
477
+ execute :touchMove, {}, {x: x, y: y}
472
478
  end
473
479
 
474
- def touchScroll(element, x, y)
480
+ def touch_scroll(element, x, y)
475
481
  if element
476
- execute :touchScroll, {}, :element => element,
477
- :xoffset => x,
478
- :yoffset => y
482
+ execute :touchScroll, {}, {element: element,
483
+ xoffset: x,
484
+ yoffset: y}
479
485
  else
480
- execute :touchScroll, {}, :xoffset => x, :yoffset => y
486
+ execute :touchScroll, {}, {xoffset: x, yoffset: y}
481
487
  end
482
488
  end
483
489
 
484
- def touchFlick(xspeed, yspeed)
485
- execute :touchFlick, {}, :xspeed => xspeed, :yspeed => yspeed
490
+ def touch_flick(xspeed, yspeed)
491
+ execute :touchFlick, {}, {xspeed: xspeed, yspeed: yspeed}
486
492
  end
487
493
 
488
- def touchElementFlick(element, right_by, down_by, speed)
489
- execute :touchFlick, {}, :element => element,
490
- :xoffset => right_by,
491
- :yoffset => down_by,
492
- :speed => speed
493
-
494
+ def touch_element_flick(element, right_by, down_by, speed)
495
+ execute :touchFlick, {}, {element: element,
496
+ xoffset: right_by,
497
+ yoffset: down_by,
498
+ speed: speed}
494
499
  end
495
500
 
496
- def setScreenOrientation(orientation)
497
- execute :setScreenOrientation, {}, :orientation => orientation
501
+ def screen_orientation=(orientation)
502
+ execute :setScreenOrientation, {}, {orientation: orientation}
498
503
  end
499
504
 
500
- def getScreenOrientation
505
+ def screen_orientation
501
506
  execute :getScreenOrientation
502
507
  end
503
508
 
@@ -505,74 +510,75 @@ module Selenium
505
510
  # element properties
506
511
  #
507
512
 
508
- def getElementTagName(element)
509
- execute :getElementTagName, :id => element
513
+ def element_tag_name(element)
514
+ execute :getElementTagName, id: element
510
515
  end
511
516
 
512
- def getElementAttribute(element, name)
513
- execute :getElementAttribute, :id => element, :name => name
517
+ def element_attribute(element, name)
518
+ execute :getElementAttribute, id: element, name: name
514
519
  end
515
520
 
516
- def getElementValue(element)
517
- execute :getElementProperty, :id => element, :name => 'value'
521
+ def element_value(element)
522
+ execute :getElementProperty, id: element, name: 'value'
518
523
  end
519
524
 
520
- def getElementText(element)
521
- execute :getElementText, :id => element
525
+ def element_text(element)
526
+ execute :getElementText, id: element
522
527
  end
523
528
 
524
- def getElementLocation(element)
525
- data = execute :getElementRect, :id => element
529
+ def element_location(element)
530
+ data = execute :getElementRect, id: element
526
531
 
527
532
  Point.new data['x'], data['y']
528
533
  end
529
534
 
530
- def getElementLocationOnceScrolledIntoView(element)
531
- sendKeysToElement(element, [''])
532
- getElementLocation(element)
535
+ def element_location_once_scrolled_into_view(element)
536
+ send_keys_to_element(element, [''])
537
+ element_location(element)
533
538
  end
534
539
 
535
- def getElementSize(element)
536
- data = execute :getElementRect, :id => element
540
+ def element_size(element)
541
+ data = execute :getElementRect, id: element
537
542
 
538
543
  Dimension.new data['width'], data['height']
539
544
  end
540
545
 
541
- def isElementEnabled(element)
542
- execute :isElementEnabled, :id => element
546
+ def element_enabled?(element)
547
+ execute :isElementEnabled, id: element
543
548
  end
544
549
 
545
- def isElementSelected(element)
546
- execute :isElementSelected, :id => element
550
+ def element_selected?(element)
551
+ execute :isElementSelected, id: element
547
552
  end
548
553
 
549
- def isElementDisplayed(element)
554
+ def element_displayed?(element)
550
555
  jwp = Selenium::WebDriver::Remote::Bridge::COMMANDS[:isElementDisplayed]
551
556
  self.class.command(:isElementDisplayed, jwp.first, jwp.last)
552
- execute :isElementDisplayed, :id => element
557
+ execute :isElementDisplayed, id: element
553
558
  end
554
559
 
555
- def getElementValueOfCssProperty(element, prop)
556
- execute :getElementCssValue, :id => element, :property_name => prop
560
+ def element_value_of_css_property(element, prop)
561
+ execute :getElementCssValue, id: element, property_name: prop
557
562
  end
558
563
 
559
564
  #
560
565
  # finding elements
561
566
  #
562
567
 
563
- def getActiveElement
568
+ def active_element
564
569
  Element.new self, element_id_from(execute(:getActiveElement))
565
570
  end
566
- alias_method :switchToActiveElement, :getActiveElement
571
+
572
+ alias_method :switch_to_active_element, :active_element
567
573
 
568
574
  def find_element_by(how, what, parent = nil)
569
575
  how, what = convert_locators(how, what)
570
576
 
571
- if parent
572
- id = execute :findChildElement, {:id => parent}, {:using => how, :value => what}
573
- else
574
- id = execute :findElement, {}, {:using => how, :value => what}
575
- end
577
+ id = if parent
578
+ execute :findChildElement, {id: parent}, {using: how, value: what}
579
+ else
580
+ execute :findElement, {}, {using: how, value: what}
581
+ end
576
582
 
577
583
  Element.new self, element_id_from(id)
578
584
  end
@@ -580,11 +586,11 @@ module Selenium
580
586
  def find_elements_by(how, what, parent = nil)
581
587
  how, what = convert_locators(how, what)
582
588
 
583
- if parent
584
- ids = execute :findChildElements, {:id => parent}, {:using => how, :value => what}
585
- else
586
- ids = execute :findElements, {}, {:using => how, :value => what}
587
- end
589
+ ids = if parent
590
+ execute :findChildElements, {id: parent}, {using: how, value: what}
591
+ else
592
+ execute :findElements, {}, {using: how, value: what}
593
+ end
588
594
 
589
595
  ids.map { |id| Element.new self, element_id_from(id) }
590
596
  end
@@ -605,7 +611,7 @@ module Selenium
605
611
  when 'tag name'
606
612
  how = 'css selector'
607
613
  end
608
- return how, what
614
+ [how, what]
609
615
  end
610
616
 
611
617
  #
@@ -628,14 +634,14 @@ module Selenium
628
634
 
629
635
  def raw_execute(command, opts = {}, command_hash = nil)
630
636
  verb, path = COMMANDS[command] || raise(ArgumentError, "unknown command: #{command.inspect}")
631
- path = path.dup
637
+ path = path.dup
632
638
 
633
- path[':session_id'] = @session_id if path.include?(":session_id")
639
+ path[':session_id'] = @session_id if path.include?(':session_id')
634
640
 
635
641
  begin
636
- opts.each { |key, value|
642
+ opts.each do |key, value|
637
643
  path[key.inspect] = escaper.escape(value.to_s)
638
- }
644
+ end
639
645
  rescue IndexError
640
646
  raise ArgumentError, "#{opts.inspect} invalid for #{command.inspect}"
641
647
  end
@@ -661,7 +667,6 @@ module Selenium
661
667
 
662
668
  string
663
669
  end
664
-
665
670
  end # W3CBridge
666
671
  end # Remote
667
672
  end # WebDriver