watir 7.0.0.beta1 → 7.0.0.beta5

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 (76) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/tests.yml +7 -3
  3. data/.rubocop.yml +2 -7
  4. data/CHANGES.md +32 -0
  5. data/lib/watir/browser.rb +21 -7
  6. data/lib/watir/capabilities.rb +52 -7
  7. data/lib/watir/elements/date_field.rb +4 -1
  8. data/lib/watir/elements/date_time_field.rb +4 -1
  9. data/lib/watir/elements/element.rb +32 -3
  10. data/lib/watir/elements/font.rb +1 -0
  11. data/lib/watir/elements/iframe.rb +0 -1
  12. data/lib/watir/elements/radio.rb +2 -2
  13. data/lib/watir/elements/select.rb +63 -40
  14. data/lib/watir/has_window.rb +2 -0
  15. data/lib/watir/locators.rb +4 -0
  16. data/lib/watir/locators/element/matcher.rb +1 -1
  17. data/lib/watir/locators/element/selector_builder.rb +0 -3
  18. data/lib/watir/locators/element/selector_builder/xpath.rb +2 -1
  19. data/lib/watir/locators/option/matcher.rb +24 -0
  20. data/lib/watir/locators/option/selector_builder.rb +8 -0
  21. data/lib/watir/locators/option/selector_builder/xpath.rb +37 -0
  22. data/lib/watir/logger.rb +3 -74
  23. data/lib/watir/radio_set.rb +1 -0
  24. data/lib/watir/screenshot.rb +2 -8
  25. data/lib/watir/user_editable.rb +10 -3
  26. data/lib/watir/version.rb +1 -1
  27. data/lib/watir/window.rb +15 -4
  28. data/lib/watir/window_collection.rb +9 -0
  29. data/lib/watirspec.rb +4 -2
  30. data/lib/watirspec/guards.rb +1 -1
  31. data/lib/watirspec/remote_server.rb +2 -6
  32. data/lib/watirspec/server.rb +1 -1
  33. data/spec/spec_helper.rb +0 -10
  34. data/spec/unit/capabilities_spec.rb +198 -48
  35. data/spec/unit/match_elements/element_spec.rb +11 -0
  36. data/spec/watirspec/after_hooks_spec.rb +22 -45
  37. data/spec/watirspec/browser_spec.rb +185 -206
  38. data/spec/watirspec/cookies_spec.rb +47 -52
  39. data/spec/watirspec/drag_and_drop_spec.rb +5 -7
  40. data/spec/watirspec/elements/area_spec.rb +1 -5
  41. data/spec/watirspec/elements/button_spec.rb +4 -8
  42. data/spec/watirspec/elements/checkbox_spec.rb +2 -4
  43. data/spec/watirspec/elements/date_field_spec.rb +13 -16
  44. data/spec/watirspec/elements/date_time_field_spec.rb +14 -13
  45. data/spec/watirspec/elements/dd_spec.rb +3 -4
  46. data/spec/watirspec/elements/del_spec.rb +10 -12
  47. data/spec/watirspec/elements/div_spec.rb +41 -50
  48. data/spec/watirspec/elements/dl_spec.rb +4 -12
  49. data/spec/watirspec/elements/element_spec.rb +155 -89
  50. data/spec/watirspec/elements/elements_spec.rb +8 -9
  51. data/spec/watirspec/elements/filefield_spec.rb +5 -7
  52. data/spec/watirspec/elements/form_spec.rb +1 -1
  53. data/spec/watirspec/elements/forms_spec.rb +3 -5
  54. data/spec/watirspec/elements/frame_spec.rb +17 -22
  55. data/spec/watirspec/elements/iframe_spec.rb +21 -27
  56. data/spec/watirspec/elements/ins_spec.rb +10 -12
  57. data/spec/watirspec/elements/link_spec.rb +24 -26
  58. data/spec/watirspec/elements/links_spec.rb +8 -9
  59. data/spec/watirspec/elements/radio_spec.rb +11 -14
  60. data/spec/watirspec/elements/select_list_spec.rb +248 -117
  61. data/spec/watirspec/elements/span_spec.rb +10 -12
  62. data/spec/watirspec/elements/table_nesting_spec.rb +31 -34
  63. data/spec/watirspec/elements/table_spec.rb +11 -13
  64. data/spec/watirspec/elements/tbody_spec.rb +10 -12
  65. data/spec/watirspec/elements/td_spec.rb +4 -6
  66. data/spec/watirspec/elements/text_field_spec.rb +10 -12
  67. data/spec/watirspec/elements/tr_spec.rb +5 -7
  68. data/spec/watirspec/support/rspec_matchers.rb +1 -1
  69. data/spec/watirspec/user_editable_spec.rb +26 -28
  70. data/spec/watirspec/wait_spec.rb +255 -258
  71. data/spec/watirspec/window_switching_spec.rb +199 -200
  72. data/spec/watirspec_helper.rb +34 -31
  73. data/watir.gemspec +1 -1
  74. metadata +7 -8
  75. data/spec/implementation_spec.rb +0 -24
  76. data/spec/unit/logger_spec.rb +0 -81
@@ -1,5 +1,7 @@
1
1
  module Watir
2
2
  module HasWindow
3
+ attr_writer :original_window
4
+
3
5
  #
4
6
  # Returns browser windows array.
5
7
  #
@@ -14,6 +14,10 @@ require 'watir/locators/button/matcher'
14
14
  require 'watir/locators/cell/selector_builder'
15
15
  require 'watir/locators/cell/selector_builder/xpath'
16
16
 
17
+ require 'watir/locators/option/matcher'
18
+ require 'watir/locators/option/selector_builder'
19
+ require 'watir/locators/option/selector_builder/xpath'
20
+
17
21
  require 'watir/locators/row/selector_builder'
18
22
  require 'watir/locators/row/selector_builder/xpath'
19
23
 
@@ -82,7 +82,7 @@ module Watir
82
82
  when :tag_name
83
83
  element.tag_name.downcase
84
84
  when :text
85
- execute_js(:getTextContent, element)
85
+ execute_js(:getTextContent, element).gsub(/\s+/, ' ').strip
86
86
  when :visible
87
87
  element.displayed?
88
88
  when :visible_text
@@ -88,9 +88,6 @@ module Watir
88
88
 
89
89
  def normalize_locator(how, what)
90
90
  case how
91
- when 'text'
92
- Watir.logger.deprecate "String 'text' as a locator", 'Symbol :text', ids: [:text_string]
93
- [:text, what]
94
91
  when :tag_name
95
92
  what = what.to_s if what.is_a?(::Symbol)
96
93
  [how, what]
@@ -218,7 +218,8 @@ module Watir
218
218
 
219
219
  def equal_pair(key, value)
220
220
  if key == :class
221
- negate_xpath = value =~ /^!/ && value.slice!(0)
221
+ negate_xpath = value =~ /^!/
222
+ value = value[1..-1] if negate_xpath
222
223
  expression = "contains(concat(' ', @class, ' '), #{XpathSupport.escape " #{value} "})"
223
224
 
224
225
  negate_xpath ? "not(#{expression})" : expression
@@ -0,0 +1,24 @@
1
+ module Watir
2
+ module Locators
3
+ class Option
4
+ class Matcher < Element::Matcher
5
+ def fetch_value(element, how)
6
+ case how
7
+ when :any
8
+ [element.attribute(:value),
9
+ execute_js(:getTextContent, element).gsub(/\s+/, ' ').strip,
10
+ element.attribute(:label)]
11
+ else
12
+ super
13
+ end
14
+ end
15
+
16
+ def matches_values?(found, expected)
17
+ return super unless found.is_a?(Array)
18
+
19
+ found.find { |possible| matches_values?(possible, expected) }
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,8 @@
1
+ module Watir
2
+ module Locators
3
+ class Option
4
+ class SelectorBuilder < Element::SelectorBuilder
5
+ end
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,37 @@
1
+ module Watir
2
+ module Locators
3
+ class Option
4
+ class SelectorBuilder
5
+ class XPath < Element::SelectorBuilder::XPath
6
+ private
7
+
8
+ def attribute_string
9
+ result = if @selector.key?(:any)
10
+ to_match = @selector.delete :any
11
+ value = process_attribute(:value, to_match)
12
+ text = process_attribute(:text, to_match)
13
+ label = process_attribute(:label, to_match)
14
+ "[#{value} or #{text} or #{label}]"
15
+ else
16
+ ''
17
+ end
18
+
19
+ attributes = @selector.keys.map { |key|
20
+ process_attribute(key, @selector.delete(key))
21
+ }.flatten.compact
22
+ attribute_values = attributes.empty? ? '' : "[#{attributes.join(' and ')}]"
23
+ "#{result}#{attribute_values}"
24
+ end
25
+
26
+ def add_to_matching(key, regexp, results = nil)
27
+ return unless results.nil? || requires_matching?(results, regexp)
28
+
29
+ return super unless %i[value text label].include? key
30
+
31
+ @built[:any] = regexp
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
data/lib/watir/logger.rb CHANGED
@@ -16,84 +16,13 @@ module Watir
16
16
  # Watir.logger.info('This is info message')
17
17
  # Watir.logger.warn('This is warning message')
18
18
  #
19
- class Logger
20
- extend Forwardable
21
- include ::Logger::Severity
22
-
23
- def_delegators :@logger, :debug, :debug?,
24
- :info, :info?,
25
- :warn?,
26
- :error, :error?,
27
- :fatal, :fatal?,
28
- :level, :level=
29
-
30
- def initialize(progname = 'Watir')
31
- @logger = create_logger($stdout)
32
- @logger.progname = progname
33
- @ignored = []
34
- end
35
-
36
- def ignore(ids)
37
- @ignored.concat Array(ids).map(&:to_s)
38
- end
39
-
40
- def output=(io)
41
- @logger.reopen(io)
42
- end
43
-
44
- #
45
- # Only log a warn message if it is not set to be ignored.
46
- #
47
- def warn(message, ids: [], &block)
48
- msg = ids.empty? ? '' : "[#{ids.map!(&:to_s).map(&:inspect).join(', ')}] "
49
- msg += message
50
- @logger.warn(msg, &block) unless (@ignored & ids).any?
51
- end
52
-
53
- #
54
- # Returns IO object used by logger internally.
55
- #
56
- # Normally, we would have never needed it, but we want to
57
- # use it as IO object for all child processes to ensure their
58
- # output is redirected there.
59
- #
60
- # It is only used in debug level, in other cases output is suppressed.
61
- #
62
- # @api private
63
- #
64
- def io
65
- @logger.instance_variable_get(:@logdev).instance_variable_get(:@dev)
66
- end
67
-
68
- #
69
- # Marks code as deprecated with replacement.
70
- #
71
- # @param [String] old
72
- # @param [String] new
73
- #
74
- def deprecate(old, new, reference: '', ids: [])
75
- return if @ignored.include?('deprecations') || (@ignored & ids.map!(&:to_s)).any?
76
-
77
- msg = ids.empty? ? '' : "[#{ids.map(&:inspect).join(', ')}] "
78
- ref_msg = reference.empty? ? '.' : "; see explanation for this deprecation: #{reference}."
79
- warn "[DEPRECATION] #{msg}#{old} is deprecated. Use #{new} instead#{ref_msg}"
19
+ class Logger < Selenium::WebDriver::Logger
20
+ def initialize
21
+ super('Watir')
80
22
  end
81
23
 
82
24
  def selenium=(val)
83
25
  Selenium::WebDriver.logger.level = val
84
26
  end
85
-
86
- private
87
-
88
- def create_logger(output)
89
- logger = ::Logger.new(output)
90
- logger.progname = 'Watir'
91
- logger.level = ($DEBUG ? DEBUG : WARN)
92
- logger.formatter = proc do |severity, time, progname, msg|
93
- "#{time.strftime('%F %T')} #{severity} #{progname} #{msg}\n"
94
- end
95
-
96
- logger
97
- end
98
27
  end
99
28
  end
@@ -139,6 +139,7 @@ module Watir
139
139
  end
140
140
  raise UnknownObjectException, "Unable to locate radio matching #{str_or_rx.inspect}"
141
141
  end
142
+ alias set select
142
143
 
143
144
  #
144
145
  # Returns true if any of the radio button label matches the given value.
@@ -1,14 +1,8 @@
1
1
  module Watir
2
2
  class Screenshot
3
3
  def initialize(browser)
4
- if browser.is_a? Selenium::WebDriver::Driver
5
- msg = 'Initializing `Watir::Screenshot` with a `Selenium::Driver` instance', 'a `Watir::Browser` instance'
6
- Watir.logger.deprecate msg, ids: [:screenshot_driver]
7
- @driver = browser
8
- else
9
- @browser = browser
10
- @driver = browser.wd
11
- end
4
+ @browser = browser
5
+ @driver = browser.wd
12
6
  end
13
7
 
14
8
  #
@@ -15,16 +15,23 @@ module Watir
15
15
  alias value= set
16
16
 
17
17
  #
18
- # Uses JavaScript to enter most of the given value.
19
- # Selenium is used to enter the first and last characters
18
+ # Returns true if element is user_editable because it has a content_editable attribute set
20
19
  #
21
- # @param [String, Symbol] args
20
+ # @return [Boolean]
22
21
  #
23
22
 
24
23
  def content_editable
25
24
  defined?(@content_editable) && content_editable?
26
25
  end
27
26
 
27
+ #
28
+ # Uses JavaScript to enter most of the given value.
29
+ # Selenium is used to enter the first and last characters
30
+ # This might provide a performance improvement when entering a lot of text on a local machine
31
+ #
32
+ # @param [String, Symbol] args
33
+ #
34
+
28
35
  def set!(*args)
29
36
  msg = '#set! does not support special keys, use #set instead'
30
37
  raise ArgumentError, msg if args.any? { |v| v.is_a?(::Symbol) }
data/lib/watir/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Watir
2
- VERSION = '7.0.0.beta1'.freeze
2
+ VERSION = '7.0.0.beta5'.freeze
3
3
  end
data/lib/watir/window.rb CHANGED
@@ -179,10 +179,21 @@ module Watir
179
179
  # end
180
180
  #
181
181
 
182
- def use(&blk)
183
- @browser.original_window ||= current_window
182
+ def use
184
183
  wait_for_exists
185
- @driver.switch_to.window(handle, &blk)
184
+ cache_current = current_window
185
+ @browser.original_window ||= cache_current
186
+ restore_to = unless cache_current == handle
187
+ @driver.switch_to.window(handle)
188
+ cache_current
189
+ end
190
+ if block_given?
191
+ begin
192
+ yield
193
+ ensure
194
+ @driver.switch_to.window(restore_to) if restore_to
195
+ end
196
+ end
186
197
  self
187
198
  end
188
199
 
@@ -205,7 +216,7 @@ module Watir
205
216
  end
206
217
 
207
218
  def assert_exists
208
- return if @driver.window_handles.include?(handle)
219
+ return if !handle.nil? && @driver.window_handles.include?(handle)
209
220
 
210
221
  raise(NoMatchingWindowFoundException, selector_string)
211
222
  end
@@ -39,6 +39,15 @@ module Watir
39
39
  end
40
40
  alias eql? ==
41
41
 
42
+ def restore!
43
+ return if @browser.closed?
44
+
45
+ window_list.reject { |win| win.handle == @browser.original_window.handle }.each(&:close)
46
+ @browser.original_window.use
47
+ rescue StandardError
48
+ @browser.close
49
+ end
50
+
42
51
  def reset!
43
52
  @window_list = nil
44
53
  end
data/lib/watirspec.rb CHANGED
@@ -53,7 +53,9 @@ module WatirSpec
53
53
  @implementation = imp
54
54
  end
55
55
 
56
- def new_browser
56
+ def new_browser(pause = 1)
57
+ sleep pause
58
+
57
59
  klass = WatirSpec.implementation.browser_class
58
60
  args = Array(WatirSpec.implementation.browser_args).map { |e| e.is_a?(Hash) ? e.dup : e }
59
61
 
@@ -80,7 +82,7 @@ module WatirSpec
80
82
  info << @implementation.driver_info
81
83
 
82
84
  Watir.logger.warn "running watirspec against #{info.join ' '} using:\n#{WatirSpec.implementation.inspect_args}",
83
- ids: [:browser_info]
85
+ id: [:browser_info]
84
86
  rescue StandardError
85
87
  # ignored
86
88
  end
@@ -21,7 +21,7 @@ module WatirSpec
21
21
  guard_name = "#{guard[:name]}:".ljust(15)
22
22
  str << " \t#{guard_name} #{guard[:data].inspect}\n"
23
23
  end
24
- Watir.logger.warn str, ids: [:guard_names]
24
+ Watir.logger.warn str, id: [:guard_names]
25
25
  end
26
26
  end
27
27
  end # class << self
@@ -20,14 +20,10 @@ module WatirSpec
20
20
  private
21
21
 
22
22
  def jar
23
- if ENV['LOCAL_SELENIUM']
24
- local = File.expand_path('../selenium/buck-out/gen/java/server/src/org/openqa/grid/selenium/selenium.jar')
25
- end
26
-
27
23
  if File.exist?(ENV['REMOTE_SERVER_BINARY'] || '')
28
24
  ENV['REMOTE_SERVER_BINARY']
29
- elsif ENV['LOCAL_SELENIUM'] && File.exist?(local)
30
- local
25
+ elsif ENV['LOCAL_SELENIUM']
26
+ File.expand_path('../selenium/bazel-bin/java/server/src/org/openqa/selenium/grid/selenium_server_deploy.jar')
31
27
  elsif !Dir.glob('*selenium*.jar').empty?
32
28
  Dir.glob('*selenium*.jar').first
33
29
  else
@@ -56,7 +56,7 @@ module WatirSpec
56
56
 
57
57
  client.write(response(status, headers, body))
58
58
  rescue Errno::ECONNRESET
59
- Watir.logger.warn 'Client reset connection, skipping.', ids: [:reset_connection]
59
+ Watir.logger.warn 'Client reset connection, skipping.', id: [:reset_connection]
60
60
  ensure
61
61
  client.close
62
62
  end
data/spec/spec_helper.rb CHANGED
@@ -20,13 +20,3 @@ end
20
20
  require 'watir'
21
21
  require 'locator_spec_helper'
22
22
  require 'rspec'
23
-
24
- if ENV['AUTOMATIC_RETRY']
25
- require 'rspec/retry'
26
- RSpec.configure do |config|
27
- config.verbose_retry = true
28
- config.display_try_failure_messages = true
29
- config.default_retry_count = 3
30
- config.exceptions_to_retry = [IOError, Net::ReadTimeout]
31
- end
32
- end
@@ -1,4 +1,4 @@
1
- require 'watirspec_helper'
1
+ require_relative 'unit_helper'
2
2
 
3
3
  describe Watir::Capabilities do
4
4
  before(:all) { Watir.logger.ignore(:watir_client) }
@@ -39,16 +39,17 @@ describe Watir::Capabilities do
39
39
  # :listener
40
40
  # :service (Built from Hash)
41
41
  # :http_client (Generated or Built from Hash)
42
+ # :proxy (Built from Hash and added to :options)
42
43
  # :options (Generated or Built from Hash)
43
44
  # :capabilities (incompatible with options)
44
45
 
45
46
  supported_browsers.each do |browser_symbol|
46
- it 'just browser has client & capabilities not service' do
47
+ it 'just browser has client & options not service' do
47
48
  capabilities = Watir::Capabilities.new(browser_symbol)
48
49
 
49
50
  args = capabilities.to_args
50
51
  expect(args.last[:http_client]).to be_a Watir::HttpClient
51
- expect(args.last[:capabilities]).to be_a options_class(browser_symbol)
52
+ expect(args.last[:capabilities].first).to be_a options_class(browser_symbol)
52
53
  expect(args.last).not_to include(:service)
53
54
  end
54
55
 
@@ -58,7 +59,7 @@ describe Watir::Capabilities do
58
59
  args = capabilities.to_args
59
60
 
60
61
  expect(args.last[:http_client]).to be_a Watir::HttpClient
61
- expect(args.last[:capabilities]).to be_a options_class(browser_symbol)
62
+ expect(args.last[:capabilities].first).to be_a options_class(browser_symbol)
62
63
  expect(args.last).not_to include(:service)
63
64
  end
64
65
 
@@ -74,7 +75,7 @@ describe Watir::Capabilities do
74
75
  expect(args.last).not_to include(:service)
75
76
  end
76
77
 
77
- context 'service' do
78
+ describe 'service' do
78
79
  it 'uses provided service' do
79
80
  halt_service(browser_symbol)
80
81
 
@@ -106,7 +107,7 @@ describe Watir::Capabilities do
106
107
  end
107
108
  end
108
109
 
109
- context 'http_client' do
110
+ describe 'http_client' do
110
111
  it 'uses default HTTP Client' do
111
112
  capabilities = Watir::Capabilities.new(browser_symbol)
112
113
  args = capabilities.to_args
@@ -152,6 +153,114 @@ describe Watir::Capabilities do
152
153
  Watir::Capabilities.new(browser_symbol, capabilities: caps, options: opts)
153
154
  }.to raise_exception(ArgumentError, ':capabilities and :options are not both allowed')
154
155
  end
156
+
157
+ describe 'timeout options' do
158
+ it 'accepts page load and script timeouts in seconds' do
159
+ options = {page_load_timeout: 11,
160
+ script_timeout: 12}
161
+ capabilities = Watir::Capabilities.new(browser_symbol, options: options)
162
+ args = capabilities.to_args
163
+ actual_options = args.last[:capabilities].first
164
+ expect(actual_options.timeouts[:page_load]).to eq 11_000
165
+ expect(actual_options.timeouts[:script]).to eq 12_000
166
+ end
167
+
168
+ it 'has deprecated timeouts key with page load warning' do
169
+ options = {timeouts: {page_load: 11}}
170
+ capabilities = Watir::Capabilities.new(browser_symbol, options: options)
171
+ msg = 'timeouts has been deprecated, use page_load_timeout (in seconds) directly instead'
172
+ expect {
173
+ capabilities.to_args
174
+ }.to have_deprecated_timeouts(msg)
175
+ end
176
+
177
+ it 'has deprecated timeouts key with script warning' do
178
+ options = {timeouts: {script: 11}}
179
+ expect {
180
+ capabilities = Watir::Capabilities.new(browser_symbol, options: options)
181
+ capabilities.to_args
182
+ }.to have_deprecated_timeouts('timeouts has been deprecated, use script_timeout (in seconds) directly instead')
183
+ end
184
+
185
+ it 'does not allow implicit wait timeout in timeouts hash' do
186
+ options = {timeouts: {implicit: 1}}
187
+ capabilities = Watir::Capabilities.new(browser_symbol, options: options)
188
+ expect {
189
+ capabilities.to_args
190
+ }.to raise_exception(ArgumentError, 'do not set implicit wait, Watir handles waiting automatically')
191
+ end
192
+ end
193
+
194
+ it 'unhandled prompt behavior defaults to ignore' do
195
+ capabilities = Watir::Capabilities.new(browser_symbol)
196
+ args = capabilities.to_args
197
+ actual_options = args.last[:capabilities].first
198
+ expect(actual_options.unhandled_prompt_behavior).to eq :ignore
199
+ end
200
+
201
+ it 'unhandled prompt behavior can be overridden' do
202
+ capabilities = Watir::Capabilities.new(browser_symbol, options: {unhandled_prompt_behavior: :accept_and_notify})
203
+ args = capabilities.to_args
204
+ actual_options = args.last[:capabilities].first
205
+ expect(actual_options.unhandled_prompt_behavior).to eq :accept_and_notify
206
+ end
207
+
208
+ describe 'proxy' do
209
+ it 'adds Selenium Proxy to empty Options' do
210
+ proxy = Selenium::WebDriver::Proxy.new(http: '127.0.0.1:8080', ssl: '127.0.0.1:443')
211
+ capabilities = Watir::Capabilities.new(browser_symbol, proxy: proxy)
212
+ args = capabilities.to_args
213
+ proxy = args.last[:capabilities].first.proxy
214
+
215
+ expect(proxy).to be_a Selenium::WebDriver::Proxy
216
+ expect(proxy.type).to eq(:manual)
217
+ expect(proxy.http).to eq('127.0.0.1:8080')
218
+ expect(proxy.ssl).to eq('127.0.0.1:443')
219
+ end
220
+
221
+ it 'builds a Proxy from Hash for Options' do
222
+ proxy = {http: '127.0.0.1:8080', ssl: '127.0.0.1:443'}
223
+ capabilities = Watir::Capabilities.new(browser_symbol, proxy: proxy)
224
+ args = capabilities.to_args
225
+ proxy = args.last[:capabilities].first.proxy
226
+
227
+ expect(proxy).to be_a Selenium::WebDriver::Proxy
228
+ expect(proxy.type).to eq(:manual)
229
+ expect(proxy.http).to eq('127.0.0.1:8080')
230
+ expect(proxy.ssl).to eq('127.0.0.1:443')
231
+ end
232
+
233
+ it 'builds a Proxy from Hash and adds to Options' do
234
+ proxy = {http: '127.0.0.1:8080', ssl: '127.0.0.1:443'}
235
+ options = {unhandled_prompt_behavior: :accept,
236
+ page_load_strategy: :eager}
237
+
238
+ capabilities = Watir::Capabilities.new(browser_symbol, options: options, proxy: proxy)
239
+ args = capabilities.to_args
240
+ actual_options = args.last[:capabilities].first
241
+
242
+ expect(actual_options.proxy).to be_a Selenium::WebDriver::Proxy
243
+ expect(actual_options.proxy.type).to eq(:manual)
244
+ expect(actual_options.proxy.http).to eq('127.0.0.1:8080')
245
+ expect(actual_options.proxy.ssl).to eq('127.0.0.1:443')
246
+ expect(actual_options.unhandled_prompt_behavior).to eq :accept
247
+ expect(actual_options.page_load_strategy).to eq :eager
248
+ end
249
+ end
250
+
251
+ it 'errors on bad proxy key' do
252
+ proxy = {bad_key: 'foo'}
253
+ capabilities = Watir::Capabilities.new(browser_symbol, proxy: proxy)
254
+
255
+ expect { capabilities.to_args }.to raise_error(ArgumentError, /unknown option/)
256
+ end
257
+
258
+ it 'errors on bad proxy object' do
259
+ capabilities = Watir::Capabilities.new(browser_symbol, proxy: 7)
260
+ expect {
261
+ capabilities.to_args
262
+ }.to raise_exception(TypeError, '7 needs to be Selenium Proxy or Hash instance')
263
+ end
155
264
  end
156
265
 
157
266
  # Options:
@@ -159,6 +268,7 @@ describe Watir::Capabilities do
159
268
  # :service (Errors)
160
269
  # :listener
161
270
  # :http_client (Generated or Built from Hash)
271
+ # :proxy (Built from Hash and added to :options)
162
272
  # :options (Generated or Built from Hash)
163
273
  # :capabilities (incompatible with options)
164
274
 
@@ -167,11 +277,11 @@ describe Watir::Capabilities do
167
277
  capabilities = Watir::Capabilities.new(url: 'http://example.com')
168
278
  args = capabilities.to_args
169
279
  expect(args.first).to eq :remote
170
- actual_options = args.last[:capabilities]
280
+ actual_options = args.last[:capabilities].first
171
281
  expect(actual_options.browser_name).to eq 'chrome'
172
282
  end
173
283
 
174
- it 'browser name with url has capabilities and client but not service' do
284
+ it 'just url & browser name has capabilities and client but not service' do
175
285
  capabilities = Watir::Capabilities.new(:firefox,
176
286
  url: 'https://example.com/wd/hub/')
177
287
  args = capabilities.to_args
@@ -179,7 +289,7 @@ describe Watir::Capabilities do
179
289
  expect(args.last[:url]).to eq 'https://example.com/wd/hub/'
180
290
  expect(args.last[:http_client]).to be_a Watir::HttpClient
181
291
 
182
- expect(args.last[:capabilities]).to be_a Selenium::WebDriver::Firefox::Options
292
+ expect(args.last[:capabilities].first).to be_a Selenium::WebDriver::Firefox::Options
183
293
  expect(args.last).not_to include(:service)
184
294
  end
185
295
 
@@ -192,7 +302,7 @@ describe Watir::Capabilities do
192
302
  expect(args.last[:listener]).to eq listener
193
303
  end
194
304
 
195
- it 'browser name with url and http client object' do
305
+ it 'accepts http client object' do
196
306
  client = Watir::HttpClient.new
197
307
  capabilities = Watir::Capabilities.new(:chrome,
198
308
  url: 'https://example.com/wd/hub',
@@ -200,33 +310,61 @@ describe Watir::Capabilities do
200
310
  args = capabilities.to_args
201
311
  expect(args.first).to eq :remote
202
312
  expect(args.last[:http_client]).to eq client
203
- actual_options = args.last[:capabilities]
313
+ actual_options = args.last[:capabilities].first
204
314
  expect(actual_options.browser_name).to eq 'chrome'
205
315
  end
206
316
 
207
- it 'browser name with url and http client Hash' do
317
+ it 'accepts http client Hash' do
208
318
  capabilities = Watir::Capabilities.new(:chrome,
209
319
  url: 'https://example.com/wd/hub',
210
320
  http_client: {read_timeout: 30})
211
321
  args = capabilities.to_args
212
322
  expect(args.first).to eq :remote
213
323
  expect(args.last[:http_client].instance_variable_get('@read_timeout')).to eq 30
214
- actual_options = args.last[:capabilities]
324
+ actual_options = args.last[:capabilities].first
215
325
  expect(actual_options.browser_name).to eq 'chrome'
216
326
  end
217
327
 
218
- it 'browser name with url and options object' do
328
+ it 'accepts proxy object' do
329
+ proxy = Selenium::WebDriver::Proxy.new(http: '127.0.0.1:8080', ssl: '127.0.0.1:443')
330
+ capabilities = Watir::Capabilities.new(:chrome,
331
+ url: 'https://example.com/wd/hub',
332
+ proxy: proxy)
333
+ args = capabilities.to_args
334
+ expect(args.first).to eq :remote
335
+ proxy = args.last[:capabilities].first.proxy
336
+ expect(proxy).to be_a Selenium::WebDriver::Proxy
337
+ expect(proxy.type).to eq(:manual)
338
+ expect(proxy.http).to eq('127.0.0.1:8080')
339
+ expect(proxy.ssl).to eq('127.0.0.1:443')
340
+ end
341
+
342
+ it 'accepts proxy Hash' do
343
+ proxy = {http: '127.0.0.1:8080', ssl: '127.0.0.1:443'}
344
+ capabilities = Watir::Capabilities.new(:chrome,
345
+ url: 'https://example.com/wd/hub',
346
+ proxy: proxy)
347
+ args = capabilities.to_args
348
+ expect(args.first).to eq :remote
349
+ proxy = args.last[:capabilities].first.proxy
350
+ expect(proxy).to be_a Selenium::WebDriver::Proxy
351
+ expect(proxy.type).to eq(:manual)
352
+ expect(proxy.http).to eq('127.0.0.1:8080')
353
+ expect(proxy.ssl).to eq('127.0.0.1:443')
354
+ end
355
+
356
+ it 'accepts options object' do
219
357
  capabilities = Watir::Capabilities.new(:chrome,
220
358
  url: 'https://example.com/wd/hub',
221
359
  options: Selenium::WebDriver::Chrome::Options.new(args: ['--foo']))
222
360
  args = capabilities.to_args
223
361
  expect(args.first).to eq :remote
224
- actual_options = args.last[:capabilities]
362
+ actual_options = args.last[:capabilities].first
225
363
  expect(actual_options.browser_name).to eq 'chrome'
226
364
  expect(actual_options.args).to include('--foo')
227
365
  end
228
366
 
229
- it 'browser name with url and options hash' do
367
+ it 'accepts options hash' do
230
368
  options = {prefs: {foo: 'bar'}}
231
369
  capabilities = Watir::Capabilities.new(:chrome,
232
370
  url: 'http://example.com',
@@ -234,12 +372,12 @@ describe Watir::Capabilities do
234
372
  args = capabilities.to_args
235
373
  expect(args.first).to eq :remote
236
374
  expect(args.last[:url]).to eq 'http://example.com'
237
- actual_options = args.last[:capabilities]
375
+ actual_options = args.last[:capabilities].first
238
376
  expect(actual_options).to be_a(Selenium::WebDriver::Chrome::Options)
239
377
  expect(actual_options.prefs).to eq(foo: 'bar')
240
378
  end
241
379
 
242
- it 'browser name with url and capabilities' do
380
+ it 'accepts capabilities object' do
243
381
  caps = Watir::Capabilities.new(:chrome,
244
382
  url: 'https://example.com/wd/hub',
245
383
  capabilities: Selenium::WebDriver::Remote::Capabilities.chrome)
@@ -250,7 +388,7 @@ describe Watir::Capabilities do
250
388
  expect(actual_capabilities.browser_name).to eq 'chrome'
251
389
  end
252
390
 
253
- it 'browser name with http client & capabilities' do
391
+ it 'accepts http client & capabilities objects' do
254
392
  client = Watir::HttpClient.new
255
393
  caps = Watir::Capabilities.new(:chrome,
256
394
  url: 'https://example.com/wd/hub',
@@ -265,23 +403,30 @@ describe Watir::Capabilities do
265
403
  expect(actual_capabilities.browser_name).to eq 'chrome'
266
404
  end
267
405
 
268
- it 'browser name with http client & options object' do
406
+ it 'accepts http client & proxy & options objects' do
269
407
  client = Watir::HttpClient.new
408
+ proxy = {http: '127.0.0.1:8080', ssl: '127.0.0.1:443'}
270
409
  options = Selenium::WebDriver::Chrome::Options.new(prefs: {foo: 'bar'})
271
410
  caps = Watir::Capabilities.new(:chrome,
272
411
  url: 'https://example.com/wd/hub',
412
+ proxy: proxy,
273
413
  options: options,
274
414
  http_client: client)
275
415
 
276
416
  args = caps.to_args
277
417
  expect(args.first).to eq :remote
278
418
  expect(args.last[:http_client]).to eq client
279
- actual_options = args.last[:capabilities]
419
+ actual_options = args.last[:capabilities].first
280
420
  expect(actual_options).to be_a(Selenium::WebDriver::Chrome::Options)
281
421
  expect(actual_options.prefs).to eq(foo: 'bar')
422
+ proxy = args.last[:capabilities].first.proxy
423
+ expect(proxy).to be_a Selenium::WebDriver::Proxy
424
+ expect(proxy.type).to eq(:manual)
425
+ expect(proxy.http).to eq('127.0.0.1:8080')
426
+ expect(proxy.ssl).to eq('127.0.0.1:443')
282
427
  end
283
428
 
284
- it 'browser name with options & capabilities' do
429
+ it 'raises exception when both options & capabilities defined' do
285
430
  options = {prefs: {foo: 'bar'}}
286
431
 
287
432
  expect {
@@ -297,7 +442,7 @@ describe Watir::Capabilities do
297
442
  headless: true,
298
443
  url: 'http://example.com')
299
444
  args = capabilities.to_args
300
- actual_options = args.last[:capabilities]
445
+ actual_options = args.last[:capabilities].first
301
446
  expect(actual_options.args).to include '--headless', '--disable-gpu'
302
447
  end
303
448
 
@@ -307,17 +452,22 @@ describe Watir::Capabilities do
307
452
  url: 'http://example.com')
308
453
  args = capabilities.to_args
309
454
 
310
- expect(args.last[:capabilities].args).to include '-headless'
455
+ expect(args.last[:capabilities].first.args).to include '-headless'
311
456
  end
312
457
 
313
- it 'allows sending to Browser Service Provider via options' do
458
+ it 'supports multiple vendor capabilities' do
459
+ sauce_options = {'sauce:options': {username: ENV['SAUCE_USERNAME'],
460
+ access_key: ENV['SAUCE_ACCESS_KEY']}}
461
+ other_options = {'other:options': {foo: 'bar'}}
462
+
314
463
  capabilities = Watir::Capabilities.new(:chrome,
315
- options: {'sauce:options': {username: ENV['SAUCE_USERNAME'],
316
- access_key: ENV['SAUCE_ACCESS_KEY']}},
464
+ options: sauce_options.merge(other_options),
317
465
  url: 'https://ondemand.us-west-1.saucelabs.com')
318
- args = capabilities.to_args
319
- actual_options = args.last[:capabilities].instance_variable_get('@options')
320
- expect(actual_options[:'sauce:options']).to include :username, :access_key
466
+
467
+ se_caps = capabilities.to_args.last[:capabilities]
468
+ expect(se_caps).to include(Selenium::WebDriver::Chrome::Options.new(unhandled_prompt_behavior: :ignore))
469
+ expect(se_caps).to include(Selenium::WebDriver::Remote::Capabilities.new(sauce_options))
470
+ expect(se_caps).to include(Selenium::WebDriver::Remote::Capabilities.new(other_options))
321
471
  end
322
472
  end
323
473
 
@@ -326,14 +476,14 @@ describe Watir::Capabilities do
326
476
  capabilities = Watir::Capabilities.new
327
477
  args = capabilities.to_args
328
478
  expect(args.last[:http_client]).to be_a Watir::HttpClient
329
- expect(args.last[:capabilities]).to be_a Selenium::WebDriver::Chrome::Options
479
+ expect(args.last[:capabilities].first).to be_a Selenium::WebDriver::Chrome::Options
330
480
  expect(args.last).not_to include(:service)
331
481
  end
332
482
 
333
483
  it 'sets headless by creating options' do
334
484
  capabilities = Watir::Capabilities.new(:chrome, headless: true)
335
485
  args = capabilities.to_args
336
- actual_options = args.last[:capabilities]
486
+ actual_options = args.last[:capabilities].first
337
487
  expect(actual_options.args).to include '--headless', '--disable-gpu'
338
488
  end
339
489
 
@@ -342,7 +492,7 @@ describe Watir::Capabilities do
342
492
  options: Selenium::WebDriver::Chrome::Options.new,
343
493
  headless: true)
344
494
  args = capabilities.to_args
345
- actual_options = args.last[:capabilities]
495
+ actual_options = args.last[:capabilities].first
346
496
  expect(actual_options.args).to include '--headless', '--disable-gpu'
347
497
  end
348
498
 
@@ -352,7 +502,7 @@ describe Watir::Capabilities do
352
502
  options: options,
353
503
  headless: true)
354
504
  args = capabilities.to_args
355
- actual_options = args.last[:capabilities]
505
+ actual_options = args.last[:capabilities].first
356
506
  expect(actual_options.args).to include '--headless', '--disable-gpu', '--foo'
357
507
  end
358
508
 
@@ -360,7 +510,7 @@ describe Watir::Capabilities do
360
510
  options = {args: %w[--foo --bar]}
361
511
  capabilities = Watir::Capabilities.new(:chrome, options: options)
362
512
  args = capabilities.to_args
363
- actual_options = args.last[:capabilities]
513
+ actual_options = args.last[:capabilities].first
364
514
  expect(actual_options).to be_a Selenium::WebDriver::Chrome::Options
365
515
  expect(actual_options.args).to include '--foo', '--bar'
366
516
  end
@@ -371,7 +521,7 @@ describe Watir::Capabilities do
371
521
  capabilities = Watir::Capabilities.new(:chrome,
372
522
  options: opts)
373
523
  args = capabilities.to_args
374
- actual_options = args.last[:capabilities]
524
+ actual_options = args.last[:capabilities].first
375
525
  expect(actual_options.page_load_strategy).to eq 'eager'
376
526
  expect(actual_options.args).to include '--foo', '--bar'
377
527
  end
@@ -384,7 +534,7 @@ describe Watir::Capabilities do
384
534
 
385
535
  capabilities = Watir::Capabilities.new(:firefox, options: options)
386
536
 
387
- actual_options = capabilities.to_args.last[:capabilities]
537
+ actual_options = capabilities.to_args.last[:capabilities].first
388
538
  expect(actual_options.args).to include '--foo'
389
539
  expect(actual_options.profile).to eq profile
390
540
  end
@@ -395,7 +545,7 @@ describe Watir::Capabilities do
395
545
 
396
546
  capabilities = Watir::Capabilities.new(:firefox, options: options)
397
547
 
398
- actual_options = capabilities.to_args.last[:capabilities]
548
+ actual_options = capabilities.to_args.last[:capabilities].first
399
549
  expect(actual_options.args).to include '--foo'
400
550
  expect(actual_options.profile).to eq profile
401
551
  end
@@ -403,7 +553,7 @@ describe Watir::Capabilities do
403
553
  it 'sets headless by creating options' do
404
554
  capabilities = Watir::Capabilities.new(:firefox, headless: true)
405
555
  args = capabilities.to_args
406
- actual_options = args.last[:capabilities]
556
+ actual_options = args.last[:capabilities].first
407
557
  expect(actual_options.args).to include '-headless'
408
558
  end
409
559
 
@@ -412,7 +562,7 @@ describe Watir::Capabilities do
412
562
  options: Selenium::WebDriver::Firefox::Options.new,
413
563
  headless: true)
414
564
  args = capabilities.to_args
415
- actual_options = args.last[:capabilities]
565
+ actual_options = args.last[:capabilities].first
416
566
  expect(actual_options.args).to include '-headless'
417
567
  end
418
568
 
@@ -422,7 +572,7 @@ describe Watir::Capabilities do
422
572
  options: options,
423
573
  headless: true)
424
574
  args = capabilities.to_args
425
- actual_options = args.last[:capabilities]
575
+ actual_options = args.last[:capabilities].first
426
576
  expect(actual_options.args).to include '-headless', '-foo'
427
577
  end
428
578
 
@@ -430,7 +580,7 @@ describe Watir::Capabilities do
430
580
  options = {args: %w[--foo --bar]}
431
581
  capabilities = Watir::Capabilities.new(:firefox, options: options)
432
582
  args = capabilities.to_args
433
- actual_options = args.last[:capabilities]
583
+ actual_options = args.last[:capabilities].first
434
584
  expect(actual_options).to be_a Selenium::WebDriver::Firefox::Options
435
585
  expect(actual_options.args).to include '--foo', '--bar'
436
586
  end
@@ -441,7 +591,7 @@ describe Watir::Capabilities do
441
591
  capabilities = Watir::Capabilities.new(:firefox,
442
592
  options: opts)
443
593
  args = capabilities.to_args
444
- actual_options = args.last[:capabilities]
594
+ actual_options = args.last[:capabilities].first
445
595
  expect(actual_options.args).to include '--foo', '--bar'
446
596
  expect(actual_options.page_load_strategy).to eq 'eager'
447
597
  end
@@ -460,7 +610,7 @@ describe Watir::Capabilities do
460
610
  options = {automatic_inspection: true}
461
611
  capabilities = Watir::Capabilities.new(:safari, options: options)
462
612
  args = capabilities.to_args
463
- actual_options = args.last[:capabilities]
613
+ actual_options = args.last[:capabilities].first
464
614
  expect(actual_options).to be_a Selenium::WebDriver::Safari::Options
465
615
  expect(actual_options.automatic_inspection).to eq true
466
616
  end
@@ -471,7 +621,7 @@ describe Watir::Capabilities do
471
621
  capabilities = Watir::Capabilities.new(:safari,
472
622
  options: opts)
473
623
  args = capabilities.to_args
474
- actual_options = args.last[:capabilities]
624
+ actual_options = args.last[:capabilities].first
475
625
  expect(actual_options.automatic_inspection).to eq true
476
626
  expect(actual_options.page_load_strategy).to eq 'eager'
477
627
  end
@@ -482,7 +632,7 @@ describe Watir::Capabilities do
482
632
  options = {args: %w[--foo --bar]}
483
633
  capabilities = Watir::Capabilities.new(:ie, options: options)
484
634
  args = capabilities.to_args
485
- actual_options = args.last[:capabilities]
635
+ actual_options = args.last[:capabilities].first
486
636
  expect(actual_options).to be_a Selenium::WebDriver::IE::Options
487
637
  expect(actual_options.args).to include '--foo', '--bar'
488
638
  end
@@ -491,7 +641,7 @@ describe Watir::Capabilities do
491
641
  options = {browser_attach_timeout: true}
492
642
  capabilities = Watir::Capabilities.new(:ie, options: options)
493
643
  args = capabilities.to_args
494
- actual_options = args.last[:capabilities]
644
+ actual_options = args.last[:capabilities].first
495
645
  expect(actual_options).to be_a Selenium::WebDriver::IE::Options
496
646
  expect(actual_options.options[:browser_attach_timeout]).to eq true
497
647
  end
@@ -502,7 +652,7 @@ describe Watir::Capabilities do
502
652
  capabilities = Watir::Capabilities.new(:ie,
503
653
  options: opts)
504
654
  args = capabilities.to_args
505
- actual_options = args.last[:capabilities]
655
+ actual_options = args.last[:capabilities].first
506
656
  expect(actual_options.args).to include '--foo'
507
657
  expect(actual_options.page_load_strategy).to eq 'eager'
508
658
  end