watir 7.0.0.beta1 → 7.0.0.beta5

Sign up to get free protection for your applications and to get access to all the features.
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