selenium-webdriver 4.0.0.alpha1 → 4.0.0.alpha6

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.
Files changed (137) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGES +139 -1
  3. data/LICENSE +1 -1
  4. data/lib/selenium/server.rb +3 -3
  5. data/lib/selenium/webdriver.rb +11 -7
  6. data/lib/selenium/webdriver/atoms/findElements.js +122 -0
  7. data/lib/selenium/webdriver/atoms/getAttribute.js +84 -7
  8. data/lib/selenium/webdriver/atoms/isDisplayed.js +75 -77
  9. data/lib/selenium/webdriver/chrome.rb +10 -9
  10. data/lib/selenium/webdriver/chrome/bridge.rb +20 -4
  11. data/lib/selenium/webdriver/chrome/driver.rb +3 -52
  12. data/lib/selenium/webdriver/chrome/options.rb +97 -57
  13. data/lib/selenium/webdriver/chrome/profile.rb +2 -2
  14. data/lib/selenium/webdriver/chrome/service.rb +0 -4
  15. data/lib/selenium/webdriver/common.rb +3 -0
  16. data/lib/selenium/webdriver/common/driver.rb +76 -17
  17. data/lib/selenium/webdriver/common/driver_extensions/{has_touch_screen.rb → has_devtools.rb} +10 -8
  18. data/lib/selenium/webdriver/common/driver_extensions/takes_screenshot.rb +2 -1
  19. data/lib/selenium/webdriver/common/logger.rb +48 -16
  20. data/lib/selenium/webdriver/common/manager.rb +5 -0
  21. data/lib/selenium/webdriver/common/options.rb +60 -121
  22. data/lib/selenium/webdriver/common/platform.rb +3 -0
  23. data/lib/selenium/webdriver/common/port_prober.rb +4 -6
  24. data/lib/selenium/webdriver/common/profile_helper.rb +10 -2
  25. data/lib/selenium/webdriver/common/proxy.rb +0 -0
  26. data/lib/selenium/webdriver/common/search_context.rb +3 -2
  27. data/lib/selenium/webdriver/common/service.rb +30 -113
  28. data/lib/selenium/webdriver/common/service_manager.rb +151 -0
  29. data/lib/selenium/webdriver/common/socket_lock.rb +2 -2
  30. data/lib/selenium/webdriver/common/wait.rb +1 -1
  31. data/lib/selenium/webdriver/devtools.rb +118 -0
  32. data/lib/selenium/webdriver/devtools/accessibility.rb +62 -0
  33. data/lib/selenium/webdriver/devtools/animation.rb +98 -0
  34. data/lib/selenium/webdriver/devtools/application_cache.rb +64 -0
  35. data/lib/selenium/webdriver/devtools/audits.rb +61 -0
  36. data/lib/selenium/webdriver/devtools/background_service.rb +67 -0
  37. data/lib/selenium/webdriver/devtools/browser.rb +123 -0
  38. data/lib/selenium/webdriver/devtools/cache_storage.rb +73 -0
  39. data/lib/selenium/webdriver/devtools/cast.rb +70 -0
  40. data/lib/selenium/webdriver/devtools/console.rb +57 -0
  41. data/lib/selenium/webdriver/devtools/css.rb +165 -0
  42. data/lib/selenium/webdriver/devtools/database.rb +64 -0
  43. data/lib/selenium/webdriver/devtools/debugger.rb +229 -0
  44. data/lib/selenium/webdriver/devtools/device_orientation.rb +53 -0
  45. data/lib/selenium/webdriver/devtools/dom.rb +320 -0
  46. data/lib/selenium/webdriver/devtools/domdebugger.rb +93 -0
  47. data/lib/selenium/webdriver/devtools/domsnapshot.rb +65 -0
  48. data/lib/selenium/webdriver/devtools/domstorage.rb +79 -0
  49. data/lib/selenium/webdriver/devtools/emulation.rb +180 -0
  50. data/lib/selenium/webdriver/devtools/fetch.rb +97 -0
  51. data/lib/selenium/webdriver/devtools/headless_experimental.rb +61 -0
  52. data/lib/selenium/webdriver/devtools/heap_profiler.rb +107 -0
  53. data/lib/selenium/webdriver/devtools/indexed_db.rb +100 -0
  54. data/lib/selenium/webdriver/devtools/input.rb +140 -0
  55. data/lib/selenium/webdriver/devtools/inspector.rb +55 -0
  56. data/lib/selenium/webdriver/devtools/io.rb +59 -0
  57. data/lib/selenium/webdriver/devtools/layer_tree.rb +95 -0
  58. data/lib/selenium/webdriver/devtools/log.rb +66 -0
  59. data/lib/selenium/webdriver/devtools/media.rb +57 -0
  60. data/lib/selenium/webdriver/devtools/memory.rb +86 -0
  61. data/lib/selenium/webdriver/devtools/network.rb +228 -0
  62. data/lib/selenium/webdriver/devtools/overlay.rb +157 -0
  63. data/lib/selenium/webdriver/devtools/page.rb +374 -0
  64. data/lib/selenium/webdriver/devtools/performance.rb +63 -0
  65. data/lib/selenium/webdriver/devtools/profiler.rb +111 -0
  66. data/lib/selenium/webdriver/devtools/runtime.rb +193 -0
  67. data/lib/selenium/webdriver/devtools/schema.rb +46 -0
  68. data/lib/selenium/webdriver/devtools/security.rb +71 -0
  69. data/lib/selenium/webdriver/devtools/service_worker.rb +116 -0
  70. data/lib/selenium/webdriver/devtools/storage.rb +95 -0
  71. data/lib/selenium/webdriver/devtools/system_info.rb +50 -0
  72. data/lib/selenium/webdriver/devtools/target.rb +141 -0
  73. data/lib/selenium/webdriver/devtools/tethering.rb +55 -0
  74. data/lib/selenium/webdriver/devtools/tracing.rb +76 -0
  75. data/lib/selenium/webdriver/devtools/web_audio.rb +70 -0
  76. data/lib/selenium/webdriver/devtools/web_authn.rb +94 -0
  77. data/lib/selenium/webdriver/edge.rb +29 -9
  78. data/lib/selenium/webdriver/{firefox/util.rb → edge_chrome/bridge.rb} +11 -20
  79. data/lib/selenium/webdriver/{common/w3c_options.rb → edge_chrome/driver.rb} +14 -17
  80. data/lib/selenium/webdriver/edge_chrome/options.rb +36 -0
  81. data/lib/selenium/webdriver/edge_chrome/profile.rb +33 -0
  82. data/lib/selenium/webdriver/edge_chrome/service.rb +36 -0
  83. data/lib/selenium/webdriver/{common/w3c_manager.rb → edge_html/driver.rb} +11 -17
  84. data/lib/selenium/webdriver/{edge → edge_html}/options.rb +26 -22
  85. data/lib/selenium/webdriver/{edge → edge_html}/service.rb +2 -6
  86. data/lib/selenium/webdriver/firefox.rb +18 -15
  87. data/lib/selenium/webdriver/firefox/bridge.rb +1 -1
  88. data/lib/selenium/webdriver/firefox/driver.rb +2 -30
  89. data/lib/selenium/webdriver/firefox/extension.rb +8 -0
  90. data/lib/selenium/webdriver/firefox/options.rb +47 -52
  91. data/lib/selenium/webdriver/firefox/profile.rb +7 -78
  92. data/lib/selenium/webdriver/firefox/service.rb +0 -4
  93. data/lib/selenium/webdriver/ie.rb +8 -7
  94. data/lib/selenium/webdriver/ie/driver.rb +0 -32
  95. data/lib/selenium/webdriver/ie/options.rb +10 -33
  96. data/lib/selenium/webdriver/ie/service.rb +5 -9
  97. data/lib/selenium/webdriver/remote.rb +16 -10
  98. data/lib/selenium/webdriver/remote/bridge.rb +34 -42
  99. data/lib/selenium/webdriver/remote/capabilities.rb +22 -6
  100. data/lib/selenium/webdriver/remote/driver.rb +6 -12
  101. data/lib/selenium/webdriver/remote/http/default.rb +9 -4
  102. data/lib/selenium/webdriver/remote/http/persistent.rb +5 -6
  103. data/lib/selenium/webdriver/safari.rb +9 -8
  104. data/lib/selenium/webdriver/safari/bridge.rb +4 -4
  105. data/lib/selenium/webdriver/safari/driver.rb +3 -29
  106. data/lib/selenium/webdriver/safari/options.rb +18 -19
  107. data/lib/selenium/webdriver/safari/service.rb +0 -4
  108. data/lib/selenium/webdriver/support.rb +1 -0
  109. data/lib/selenium/webdriver/support/cdp_client_generator.rb +77 -0
  110. data/lib/selenium/webdriver/support/color.rb +2 -2
  111. data/lib/selenium/webdriver/support/event_firing_bridge.rb +1 -1
  112. data/lib/selenium/webdriver/support/relative_locator.rb +51 -0
  113. data/lib/selenium/webdriver/version.rb +1 -1
  114. data/selenium-webdriver.gemspec +5 -4
  115. metadata +81 -42
  116. data/lib/selenium/webdriver/common/bridge_helper.rb +0 -82
  117. data/lib/selenium/webdriver/common/keyboard.rb +0 -70
  118. data/lib/selenium/webdriver/common/mouse.rb +0 -89
  119. data/lib/selenium/webdriver/common/touch_action_builder.rb +0 -78
  120. data/lib/selenium/webdriver/common/touch_screen.rb +0 -123
  121. data/lib/selenium/webdriver/common/w3c_action_builder.rb +0 -212
  122. data/lib/selenium/webdriver/edge/bridge.rb +0 -76
  123. data/lib/selenium/webdriver/edge/driver.rb +0 -70
  124. data/lib/selenium/webdriver/firefox/binary.rb +0 -110
  125. data/lib/selenium/webdriver/firefox/extension/prefs.json +0 -69
  126. data/lib/selenium/webdriver/firefox/extension/webdriver.xpi +0 -0
  127. data/lib/selenium/webdriver/firefox/launcher.rb +0 -111
  128. data/lib/selenium/webdriver/firefox/legacy/driver.rb +0 -83
  129. data/lib/selenium/webdriver/firefox/marionette/bridge.rb +0 -49
  130. data/lib/selenium/webdriver/firefox/marionette/driver.rb +0 -90
  131. data/lib/selenium/webdriver/firefox/native/linux/amd64/x_ignore_nofocus.so +0 -0
  132. data/lib/selenium/webdriver/firefox/native/linux/x86/x_ignore_nofocus.so +0 -0
  133. data/lib/selenium/webdriver/remote/oss/bridge.rb +0 -594
  134. data/lib/selenium/webdriver/remote/oss/commands.rb +0 -223
  135. data/lib/selenium/webdriver/remote/w3c/bridge.rb +0 -605
  136. data/lib/selenium/webdriver/remote/w3c/capabilities.rb +0 -310
  137. data/lib/selenium/webdriver/remote/w3c/commands.rb +0 -157
@@ -20,17 +20,19 @@
20
20
  module Selenium
21
21
  module WebDriver
22
22
  module DriverExtensions
23
- module HasTouchScreen
24
- def touch
25
- TouchActionBuilder.new Mouse.new(@bridge), Keyboard.new(@bridge), touch_screen
26
- end
23
+ module HasDevTools
27
24
 
28
- private
25
+ #
26
+ # Retrieves connection to DevTools.
27
+ #
28
+ # @return [DevTools]
29
+ #
29
30
 
30
- def touch_screen
31
- TouchScreen.new @bridge
31
+ def devtools
32
+ @devtools ||= DevTools.new(capabilities['goog:chromeOptions']['debuggerAddress'])
32
33
  end
33
- end # HasTouchScreen
34
+
35
+ end # HasDevTools
34
36
  end # DriverExtensions
35
37
  end # WebDriver
36
38
  end # Selenium
@@ -35,7 +35,8 @@ module Selenium
35
35
  extension = File.extname(png_path).downcase
36
36
  if extension != '.png'
37
37
  WebDriver.logger.warn "name used for saved screenshot does not match file type. "\
38
- "It should end with .png extension"
38
+ "It should end with .png extension",
39
+ id: :screenshot
39
40
  end
40
41
  File.open(png_path, 'wb') { |f| f << screenshot_as(:png) }
41
42
  end
@@ -40,13 +40,17 @@ module Selenium
40
40
  :close,
41
41
  :debug, :debug?,
42
42
  :info, :info?,
43
- :warn, :warn?,
43
+ :warn?,
44
44
  :error, :error?,
45
45
  :fatal, :fatal?,
46
46
  :level, :level=
47
47
 
48
- def initialize
49
- @logger = create_logger($stdout)
48
+ #
49
+ # @param [String] progname Allow child projects to use Selenium's Logger pattern
50
+ #
51
+ def initialize(progname = 'Selenium')
52
+ @logger = create_logger(progname)
53
+ @ignored = []
50
54
  end
51
55
 
52
56
  #
@@ -73,28 +77,60 @@ module Selenium
73
77
  @logger.instance_variable_get(:@logdev).dev
74
78
  end
75
79
 
80
+ #
81
+ # Will not log the provided ID.
82
+ #
83
+ # @param [Array, Symbol] id
84
+ #
85
+ def ignore(id)
86
+ Array(id).each { |ignore| @ignored << ignore }
87
+ end
88
+
89
+ #
90
+ # Overrides default #warn to skip ignored messages by provided id
91
+ #
92
+ # @param [String] message
93
+ # @param [Symbol, Array<Sybmol>] id
94
+ # @yield see #deprecate
95
+ #
96
+ def warn(message, id: [])
97
+ id = Array(id)
98
+ return if (@ignored & id).any?
99
+
100
+ msg = id.empty? ? message : "[#{id.map(&:inspect).join(', ')}] #{message} "
101
+ msg += " #{yield}" if block_given?
102
+
103
+ @logger.warn { msg }
104
+ end
105
+
76
106
  #
77
107
  # Marks code as deprecated with/without replacement.
78
108
  #
79
109
  # @param [String] old
80
110
  # @param [String, nil] new
111
+ # @param [Symbol, Array<Sybmol>] id
112
+ # @yield appends additional message to end of provided template
81
113
  #
82
- def deprecate(old, new = nil)
83
- message = +"[DEPRECATION] #{old} is deprecated"
114
+ def deprecate(old, new = nil, id: [], &block)
115
+ id = Array(id)
116
+ return if @ignored.include?(:deprecations) || (@ignored & id).any?
117
+
118
+ ids = id.empty? ? '' : "[#{id.map(&:inspect).join(', ')}] "
119
+
120
+ message = +"[DEPRECATION] #{ids}#{old} is deprecated"
84
121
  message << if new
85
122
  ". Use #{new} instead."
86
123
  else
87
- ' and will be removed in the next releases.'
124
+ ' and will be removed in a future release.'
88
125
  end
89
-
90
- warn message
126
+ warn message, &block
91
127
  end
92
128
 
93
129
  private
94
130
 
95
- def create_logger(output)
96
- logger = ::Logger.new(output)
97
- logger.progname = 'Selenium'
131
+ def create_logger(name)
132
+ logger = ::Logger.new($stdout)
133
+ logger.progname = name
98
134
  logger.level = default_level
99
135
  logger.formatter = proc do |severity, time, progname, msg|
100
136
  "#{time.strftime('%F %T')} #{severity} #{progname} #{msg}\n"
@@ -104,11 +140,7 @@ module Selenium
104
140
  end
105
141
 
106
142
  def default_level
107
- if $DEBUG || ENV.key?('DEBUG')
108
- :debug
109
- else
110
- :warn
111
- end
143
+ $DEBUG || ENV.key?('DEBUG') ? :debug : :warn
112
144
  end
113
145
  end # Logger
114
146
  end # WebDriver
@@ -36,6 +36,7 @@ module Selenium
36
36
  # @option opts [String] :value A value
37
37
  # @option opts [String] :path ('/') A path
38
38
  # @option opts [String] :secure (false) A boolean
39
+ # @option opts [String] :same_site (Strict or Lax) currently supported only in chrome 80+ versions
39
40
  # @option opts [Time,DateTime,Numeric,nil] :expires (nil) Expiry date, either as a Time, DateTime, or seconds since epoch.
40
41
  #
41
42
  # @raise [ArgumentError] if :name or :value is not specified
@@ -48,6 +49,9 @@ module Selenium
48
49
  opts[:path] ||= '/'
49
50
  opts[:secure] ||= false
50
51
 
52
+ same_site = opts.delete(:same_site)
53
+ opts[:sameSite] = same_site if same_site
54
+
51
55
  obj = opts.delete(:expires)
52
56
  opts[:expiry] = seconds_from(obj).to_i if obj
53
57
 
@@ -169,6 +173,7 @@ module Selenium
169
173
  path: cookie['path'],
170
174
  domain: cookie['domain'] && strip_port(cookie['domain']),
171
175
  expires: cookie['expiry'] && datetime_at(cookie['expiry']),
176
+ same_site: cookie['sameSite'],
172
177
  secure: cookie['secure']
173
178
  }
174
179
  end
@@ -20,157 +20,96 @@
20
20
  module Selenium
21
21
  module WebDriver
22
22
  class Options
23
- #
24
- # @api private
25
- #
26
-
27
- def initialize(bridge)
28
- @bridge = bridge
29
- end
30
-
31
- #
32
- # Add a cookie to the browser
33
- #
34
- # @param [Hash] opts the options to create a cookie with.
35
- # @option opts [String] :name A name
36
- # @option opts [String] :value A value
37
- # @option opts [String] :path ('/') A path
38
- # @option opts [String] :secure (false) A boolean
39
- # @option opts [Time,DateTime,Numeric,nil] :expires (nil) Expiry date, either as a Time, DateTime, or seconds since epoch.
40
- #
41
- # @raise [ArgumentError] if :name or :value is not specified
42
- #
43
-
44
- def add_cookie(opts = {})
45
- raise ArgumentError, 'name is required' unless opts[:name]
46
- raise ArgumentError, 'value is required' unless opts[:value]
23
+ W3C_OPTIONS = %i[browser_name browser_version platform_name accept_insecure_certs page_load_strategy proxy
24
+ set_window_rect timeouts unhandled_prompt_behavior strict_file_interactability].freeze
47
25
 
48
- opts[:path] ||= '/'
49
- opts[:secure] ||= false
50
-
51
- obj = opts.delete(:expires)
52
- opts[:expiry] = seconds_from(obj).to_i if obj
26
+ W3C_OPTIONS.each do |key|
27
+ define_method key do
28
+ @options[key]
29
+ end
53
30
 
54
- @bridge.add_cookie opts
31
+ define_method "#{key}=" do |value|
32
+ @options[key] = value
33
+ end
55
34
  end
56
35
 
57
- #
58
- # Get the cookie with the given name
59
- #
60
- # @param [String] name the name of the cookie
61
- # @return [Hash, nil] the cookie, or nil if it wasn't found.
62
- #
63
-
64
- def cookie_named(name)
65
- all_cookies.find { |c| c[:name] == name }
36
+ attr_accessor :options
37
+
38
+ def initialize(options: nil, **opts)
39
+ @options = if options
40
+ WebDriver.logger.deprecate(":options as keyword for initializing #{self.class}",
41
+ "custom values directly in #new constructor",
42
+ id: :options_options)
43
+ opts.merge(options)
44
+ else
45
+ opts
46
+ end
47
+ @options[:browser_name] = self.class::BROWSER
66
48
  end
67
49
 
68
50
  #
69
- # Delete the cookie with the given name
70
- #
71
- # @param [String] name the name of the cookie to delete
51
+ # Add a new option not yet handled by bindings.
72
52
  #
73
-
74
- def delete_cookie(name)
75
- @bridge.delete_cookie name
76
- end
77
-
53
+ # @example Leave Chrome open when chromedriver is killed
54
+ # options = Selenium::WebDriver::Chrome::Options.new
55
+ # options.add_option(:detach, true)
78
56
  #
79
- # Delete all cookies
57
+ # @param [String, Symbol] name Name of the option
58
+ # @param [Boolean, String, Integer] value Value of the option
80
59
  #
81
60
 
82
- def delete_all_cookies
83
- @bridge.delete_all_cookies
61
+ def add_option(name, value)
62
+ @options[name] = value
84
63
  end
85
64
 
86
65
  #
87
- # Get all cookies
88
- #
89
- # @return [Array<Hash>] list of cookies
66
+ # @api private
90
67
  #
91
68
 
92
- def all_cookies
93
- @bridge.cookies.map { |cookie| convert_cookie(cookie) }
94
- end
69
+ def as_json(*)
70
+ options = @options.dup
95
71
 
96
- def timeouts
97
- @timeouts ||= Timeouts.new(@bridge)
98
- end
72
+ w3c_options = options.select { |key, _val| W3C_OPTIONS.include?(key) }
73
+ options.delete_if { |key, _val| W3C_OPTIONS.include?(key) }
99
74
 
100
- #
101
- # @api beta This API may be changed or removed in a future release.
102
- #
103
-
104
- def logs
105
- @logs ||= Logs.new(@bridge)
106
- end
107
-
108
- #
109
- # Create a new top-level browsing context
110
- # https://w3c.github.io/webdriver/#new-window
111
- # @param type [Symbol] Supports two values: :tab and :window.
112
- # Use :tab if you'd like the new window to share an OS-level window
113
- # with the current browsing context.
114
- # Use :window otherwise
115
- # @return [String] The value of the window handle
116
- #
117
- def new_window(type = :tab)
118
- case type
119
- when :tab, :window
120
- result = @bridge.new_window(type)
121
- unless result.key?('handle')
122
- raise UnknownError, "the driver did not return a handle. " \
123
- "The returned result: #{result.inspect}"
124
- end
125
- result['handle']
126
- else
127
- raise ArgumentError, "invalid argument for type. Got: '#{type.inspect}'. " \
128
- "Try :tab or :window"
75
+ self.class::CAPABILITIES.each do |capability_alias, capability_name|
76
+ capability_value = options.delete(capability_alias)
77
+ options[capability_name] = capability_value unless capability_value.nil?
129
78
  end
130
- end
131
-
132
- #
133
- # @api beta This API may be changed or removed in a future release.
134
- #
79
+ browser_options = defined?(self.class::KEY) ? {self.class::KEY => options} : options
135
80
 
136
- def window
137
- @window ||= Window.new(@bridge)
81
+ process_browser_options(browser_options) if private_methods(false).include?(:process_browser_options)
82
+ generate_as_json(w3c_options.merge(browser_options))
138
83
  end
139
84
 
140
85
  private
141
86
 
142
- SECONDS_PER_DAY = 86_400.0
143
-
144
- def datetime_at(int)
145
- DateTime.civil(1970) + (int / SECONDS_PER_DAY)
146
- end
147
-
148
- def seconds_from(obj)
149
- case obj
150
- when Time
151
- obj.to_f
152
- when DateTime
153
- (obj - DateTime.civil(1970)) * SECONDS_PER_DAY
154
- when Numeric
155
- obj
87
+ def generate_as_json(value, camelize_keys: true)
88
+ if value.respond_to?(:as_json)
89
+ value.as_json
90
+ elsif value.is_a?(Hash)
91
+ value.each_with_object({}) do |(key, val), hash|
92
+ hash[convert_json_key(key, camelize: camelize_keys)] = generate_as_json(val, camelize_keys: camelize_keys)
93
+ end
94
+ elsif value.is_a?(Array)
95
+ value.map { |val| generate_as_json(val, camelize_keys: camelize_keys) }
96
+ elsif value.is_a?(Symbol)
97
+ value.to_s
156
98
  else
157
- raise ArgumentError, "invalid value for expiration date: #{obj.inspect}"
99
+ value
158
100
  end
159
101
  end
160
102
 
161
- def strip_port(str)
162
- str.split(':', 2).first
103
+ def convert_json_key(key, camelize: true)
104
+ key = key.to_s if key.is_a?(Symbol)
105
+ key = camel_case(key) if camelize
106
+ return key if key.is_a?(String)
107
+
108
+ raise TypeError, "expected String or Symbol, got #{key.inspect}:#{key.class}"
163
109
  end
164
110
 
165
- def convert_cookie(cookie)
166
- {
167
- name: cookie['name'],
168
- value: cookie['value'],
169
- path: cookie['path'],
170
- domain: cookie['domain'] && strip_port(cookie['domain']),
171
- expires: cookie['expiry'] && datetime_at(cookie['expiry']),
172
- secure: cookie['secure']
173
- }
111
+ def camel_case(str)
112
+ str.gsub(/_([a-z])/) { Regexp.last_match(1).upcase }
174
113
  end
175
114
  end # Options
176
115
  end # WebDriver
@@ -96,6 +96,9 @@ module Selenium
96
96
  return false unless linux?
97
97
 
98
98
  File.read('/proc/version').include?('Microsoft')
99
+ rescue Errno::EACCES
100
+ # the file cannot be accessed on Linux on DeX
101
+ false
99
102
  end
100
103
 
101
104
  def cygwin?
@@ -32,12 +32,10 @@ module Selenium
32
32
 
33
33
  def self.free?(port)
34
34
  Platform.interfaces.each do |host|
35
- begin
36
- TCPServer.new(host, port).close
37
- rescue *IGNORED_ERRORS => ex
38
- WebDriver.logger.debug("port prober could not bind to #{host}:#{port} (#{ex.message})")
39
- # ignored - some machines appear unable to bind to some of their interfaces
40
- end
35
+ TCPServer.new(host, port).close
36
+ rescue *IGNORED_ERRORS => e
37
+ WebDriver.logger.debug("port prober could not bind to #{host}:#{port} (#{e.message})")
38
+ # ignored - some machines appear unable to bind to some of their interfaces
41
39
  end
42
40
 
43
41
  true
@@ -31,8 +31,16 @@ module Selenium
31
31
  base.extend ClassMethods
32
32
  end
33
33
 
34
+ def self.decoded(json)
35
+ JSON.parse(json).fetch('zip')
36
+ end
37
+
38
+ def encoded
39
+ Zipper.zip(layout_on_disk)
40
+ end
41
+
34
42
  def as_json(*)
35
- {"zip" => Zipper.zip(layout_on_disk)}
43
+ {"zip" => encoded}
36
44
  end
37
45
 
38
46
  def to_json(*)
@@ -63,7 +71,7 @@ module Selenium
63
71
 
64
72
  module ClassMethods
65
73
  def from_json(json)
66
- data = JSON.parse(json).fetch('zip')
74
+ data = decoded(json)
67
75
 
68
76
  # can't use Tempfile here since it doesn't support File::BINARY mode on 1.8
69
77
  # can't use Dir.mktmpdir(&blk) because of http://jira.codehaus.org/browse/JRUBY-4082
File without changes
@@ -30,6 +30,7 @@ module Selenium
30
30
  link_text: 'link text',
31
31
  name: 'name',
32
32
  partial_link_text: 'partial link text',
33
+ relative: 'relative',
33
34
  tag_name: 'tag name',
34
35
  xpath: 'xpath'
35
36
  }.freeze
@@ -59,7 +60,7 @@ module Selenium
59
60
  by = FINDERS[how.to_sym]
60
61
  raise ArgumentError, "cannot find element by #{how.inspect}" unless by
61
62
 
62
- bridge.find_element_by by, what.to_s, ref
63
+ bridge.find_element_by by, what, ref
63
64
  rescue Selenium::WebDriver::Error::TimeoutError
64
65
  # Implicit Wait times out in Edge
65
66
  raise Selenium::WebDriver::Error::NoSuchElementError
@@ -77,7 +78,7 @@ module Selenium
77
78
  by = FINDERS[how.to_sym]
78
79
  raise ArgumentError, "cannot find elements by #{how.inspect}" unless by
79
80
 
80
- bridge.find_elements_by by, what.to_s, ref
81
+ bridge.find_elements_by by, what, ref
81
82
  rescue Selenium::WebDriver::Error::TimeoutError
82
83
  # Implicit Wait times out in Edge
83
84
  []