watir 6.16.3 → 6.19.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (109) hide show
  1. checksums.yaml +5 -5
  2. data/.github/actions/enable-safari/action.yml +11 -0
  3. data/.github/actions/install-chrome/action.yml +11 -0
  4. data/.github/workflows/linux.yml +61 -0
  5. data/.github/workflows/mac.yml +55 -0
  6. data/.github/workflows/unit.yml +37 -0
  7. data/.github/workflows/windows.yml +39 -0
  8. data/.rubocop.yml +32 -107
  9. data/.rubocop_todo.yml +36 -0
  10. data/CHANGES.md +55 -0
  11. data/Gemfile +3 -1
  12. data/LICENSE +2 -2
  13. data/README.md +9 -10
  14. data/Rakefile +4 -4
  15. data/lib/watir-webdriver.rb +1 -1
  16. data/lib/watir.rb +3 -1
  17. data/lib/watir/adjacent.rb +8 -10
  18. data/lib/watir/after_hooks.rb +4 -4
  19. data/lib/watir/alert.rb +1 -0
  20. data/lib/watir/attribute_helper.rb +2 -0
  21. data/lib/watir/browser.rb +7 -3
  22. data/lib/watir/capabilities.rb +245 -97
  23. data/lib/watir/cookies.rb +3 -1
  24. data/lib/watir/element_collection.rb +21 -6
  25. data/lib/watir/elements/element.rb +66 -53
  26. data/lib/watir/elements/file_field.rb +1 -0
  27. data/lib/watir/elements/html_elements.rb +0 -1
  28. data/lib/watir/elements/iframe.rb +4 -3
  29. data/lib/watir/elements/link.rb +0 -9
  30. data/lib/watir/elements/radio.rb +1 -1
  31. data/lib/watir/elements/select.rb +22 -7
  32. data/lib/watir/generator/base/spec_extractor.rb +4 -4
  33. data/lib/watir/generator/html/generator.rb +1 -1
  34. data/lib/watir/has_window.rb +17 -15
  35. data/lib/watir/http_client.rb +17 -0
  36. data/lib/watir/js_execution.rb +3 -3
  37. data/lib/watir/js_snippets.rb +2 -2
  38. data/lib/watir/legacy_wait.rb +1 -1
  39. data/lib/watir/locators.rb +1 -3
  40. data/lib/watir/locators/element/locator.rb +12 -6
  41. data/lib/watir/locators/element/selector_builder.rb +12 -13
  42. data/lib/watir/locators/element/selector_builder/xpath.rb +40 -13
  43. data/lib/watir/locators/text_field/selector_builder/xpath.rb +3 -1
  44. data/lib/watir/logger.rb +7 -20
  45. data/lib/watir/radio_set.rb +2 -2
  46. data/lib/watir/user_editable.rb +6 -2
  47. data/lib/watir/version.rb +1 -1
  48. data/lib/watir/wait.rb +2 -0
  49. data/lib/watir/wait/timer.rb +1 -1
  50. data/lib/watir/window.rb +8 -4
  51. data/lib/watir/window_collection.rb +114 -0
  52. data/lib/watirspec.rb +2 -1
  53. data/lib/watirspec/guards.rb +1 -1
  54. data/lib/watirspec/implementation.rb +3 -5
  55. data/lib/watirspec/rake_tasks.rb +2 -0
  56. data/lib/watirspec/runner.rb +6 -2
  57. data/lib/watirspec/server.rb +1 -1
  58. data/spec/spec_helper.rb +2 -7
  59. data/spec/unit/capabilities_spec.rb +1234 -18
  60. data/spec/unit/container_spec.rb +1 -1
  61. data/spec/unit/logger_spec.rb +5 -7
  62. data/spec/unit/match_elements/element_spec.rb +17 -15
  63. data/spec/unit/selector_builder/button_spec.rb +16 -15
  64. data/spec/unit/selector_builder/element_spec.rb +58 -9
  65. data/spec/unit/selector_builder/text_field_spec.rb +14 -14
  66. data/spec/unit/unit_helper.rb +2 -4
  67. data/spec/watirspec/after_hooks_spec.rb +58 -68
  68. data/spec/watirspec/alert_spec.rb +69 -79
  69. data/spec/watirspec/browser_spec.rb +51 -48
  70. data/spec/watirspec/cookies_spec.rb +52 -37
  71. data/spec/watirspec/drag_and_drop_spec.rb +14 -38
  72. data/spec/watirspec/elements/button_spec.rb +2 -0
  73. data/spec/watirspec/elements/buttons_spec.rb +1 -1
  74. data/spec/watirspec/elements/checkbox_spec.rb +8 -4
  75. data/spec/watirspec/elements/date_field_spec.rb +18 -9
  76. data/spec/watirspec/elements/date_time_field_spec.rb +3 -4
  77. data/spec/watirspec/elements/div_spec.rb +62 -54
  78. data/spec/watirspec/elements/element_spec.rb +73 -88
  79. data/spec/watirspec/elements/elements_spec.rb +12 -3
  80. data/spec/watirspec/elements/filefield_spec.rb +25 -50
  81. data/spec/watirspec/elements/form_spec.rb +6 -8
  82. data/spec/watirspec/elements/frame_spec.rb +10 -13
  83. data/spec/watirspec/elements/iframe_spec.rb +12 -9
  84. data/spec/watirspec/elements/iframes_spec.rb +2 -2
  85. data/spec/watirspec/elements/link_spec.rb +23 -12
  86. data/spec/watirspec/elements/links_spec.rb +11 -3
  87. data/spec/watirspec/elements/option_spec.rb +15 -17
  88. data/spec/watirspec/elements/select_list_spec.rb +222 -117
  89. data/spec/watirspec/elements/text_field_spec.rb +8 -4
  90. data/spec/watirspec/elements/tr_spec.rb +0 -9
  91. data/spec/watirspec/html/forms_with_input_elements.html +1 -0
  92. data/spec/watirspec/html/iframes.html +3 -0
  93. data/spec/watirspec/html/non_control_elements.html +4 -4
  94. data/spec/watirspec/html/right_click.html +12 -0
  95. data/spec/watirspec/html/wait.html +6 -6
  96. data/spec/watirspec/html/window_switching.html +10 -0
  97. data/spec/watirspec/legacy_wait_spec.rb +216 -0
  98. data/spec/watirspec/support/rspec_matchers.rb +33 -14
  99. data/spec/watirspec/user_editable_spec.rb +1 -1
  100. data/spec/watirspec/wait_spec.rb +257 -305
  101. data/spec/watirspec/window_switching_spec.rb +338 -211
  102. data/spec/watirspec_helper.rb +17 -20
  103. data/support/doctest_helper.rb +0 -2
  104. data/watir.gemspec +6 -7
  105. metadata +37 -26
  106. data/.travis.yml +0 -84
  107. data/appveyor.yml +0 -12
  108. data/lib/watir/elements/area.rb +0 -10
  109. data/spec/watirspec/relaxed_locate_spec.rb +0 -113
data/CHANGES.md CHANGED
@@ -1,3 +1,58 @@
1
+ ### 6.19.0 (2021-03-12)
2
+
3
+ * Create custom Watir HTTP Client
4
+ * Require minimum of Selenium 3.142.7
5
+ * Add support for starting browser with :http_client and :service hashes
6
+ * Allow inferring desired browser from Capabilities or Options if browser not specified
7
+ * Deprecate WindowCollection#to_a method
8
+ * Deprecate starting browser with both Capabilities and Options
9
+ * Deprecate starting browser with both URL and Service
10
+ * Deprecate using :desired_capabilities
11
+ * Deprecate starting browser service keywords in top level Hash
12
+ * Deprecate using :remote to start a browser; browser name must be specified
13
+ * Deprecate sending unknown keywords into the top level
14
+ * Fix bug preventing Safari Options from being recognized
15
+ * Fix bug preventing options provided without :remote keyword from being properly recognized (#812, #870)
16
+ * Fix bug preventing :headless from being recognized when :options specified (#692)
17
+
18
+ ### 6.18.0 (2021-02-26)
19
+
20
+ * Implement `WindowCollection` to manage multiple `Window` objects
21
+ * Add support for locating `Window` by `:element`
22
+ * Deprecate locating `Window` by `:index`
23
+ * Deprecate `Select#select_all` in favor of `#select` and an `Array`
24
+ * Implement `Browser#switch_window` (#849)
25
+ * Add support for `Numeric` attribute values to `Waitable`
26
+ * Allow users to specify Selenium 4 in their projects
27
+ * Update stale element handling behavior to match webdriver spec (#905 #909)
28
+ * Implement `Waitable` for `ElementCollection` (#853 #857)
29
+ * Improve performance for nested elements (#843)
30
+ * Less strict version check for `regexp_parser` gem (thanks Pavel Lobashov)
31
+
32
+ ### 6.17.0 (2020-08-27)
33
+ * Require Ruby > 2.5
34
+ * Implement Logger#selenium= to set selenium level from Watir
35
+ * Implement FileField#upload
36
+ * Fix bug with staleness handling in #exist and #present? (#853 & #852)
37
+ * Fix bug when locating elements by text with RegExp (#866 #871)
38
+ * Implement modifiers for `Element#right_click` (thanks Lakshya Kapoor #861)
39
+ * Updated locator code to adhere to spec on what attributes are case sensitive (#507 #856)
40
+ * Fix locating bug when iframe is nested under another element (thanks Matthew Mazaika #885 #886)
41
+ * Deprecate Element#scroll_into_view in favor of the new Scroll methods (#884)
42
+ * Fix threading bugs by allowing each Browser instance its own Timer (#881)
43
+ * Allow adjacent locators to return Input subtype when applicable (#878)
44
+ * Removed unnecessary reference to rubyforge (thanks olleolleolle #874)
45
+ * Removed deprecated Selenium classes (thanks joesho112358 #867)
46
+ * Add support for :service parameter for initializing Browser
47
+
48
+ ### 6.16.5 (2018-12-25)
49
+
50
+ * Fix bug with nested elements using scopes (#842)
51
+
52
+ ### 6.16.4 (2018-12-24)
53
+
54
+ * Minor adjustments to support locator extensions
55
+
1
56
  ### 6.16.3 (2018-12-24)
2
57
 
3
58
  * Minor adjustments to support locator extensions
data/Gemfile CHANGED
@@ -1,8 +1,10 @@
1
- source 'http://rubygems.org'
1
+ source 'https://rubygems.org'
2
2
 
3
3
  gem 'webidl', path: File.expand_path('../webidl') if ENV['LOCAL_WEBIDL']
4
4
 
5
5
  gem 'selenium-webdriver', path: File.expand_path('../selenium/build/rb') if ENV['LOCAL_SELENIUM']
6
6
 
7
+ gem 'ffi' if Gem.win_platform? # For selenium-webdriver on Windows
8
+
7
9
  # Specify your gem's dependencies in watir.gemspec
8
10
  gemspec
data/LICENSE CHANGED
@@ -1,8 +1,8 @@
1
1
  (the MIT License)
2
2
 
3
3
  Copyright (c) 2009-2015 Jari Bakken
4
- Copyright (c) 2015-2018 Alex Rodionov, Titus Fortner
5
- Copyright (c) 2018 Justin Ko
4
+ Copyright (c) 2015-2021 Alex Rodionov, Titus Fortner
5
+ Copyright (c) 2018-2021 Justin Ko
6
6
 
7
7
  Permission is hereby granted, free of charge, to any person obtaining
8
8
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -3,10 +3,12 @@
3
3
  Watir Powered By Selenium!
4
4
 
5
5
  [![Gem Version](https://badge.fury.io/rb/watir.svg)](http://badge.fury.io/rb/watir)
6
- [![Travis Status](https://travis-ci.org/watir/watir.svg?branch=master)](https://travis-ci.org/watir/watir)
7
- [![AppVeyor status](https://ci.appveyor.com/api/projects/status/9vbb7pp5p4uyoott/branch/master?svg=true)](https://ci.appveyor.com/project/p0deje/watir)
6
+ [![Unit Tests](https://github.com/watir/watir/workflows/Unit%20Tests/badge.svg)](https://github.com/watir/watir/actions?query=workflow%3A%22Unit+Tests%22)
7
+ [![Mac Tests](https://github.com/watir/watir/workflows/Mac%20Tests/badge.svg)](https://github.com/watir/watir/actions?query=workflow%3A%22Mac+Tests%22)
8
+ [![Windows Tests](https://github.com/watir/watir/workflows/Windows%20Tests/badge.svg)](https://github.com/watir/watir/actions?query=workflow%3A%22Windows+Tests%22)
9
+ [![Linux Tests](https://github.com/watir/watir/workflows/Linux%20Tests/badge.svg)](https://github.com/watir/watir/actions?query=workflow%3A%22Linux+Tests%22)
8
10
  [![Code Climate](https://codeclimate.com/github/watir/watir.svg)](https://codeclimate.com/github/watir/watir)
9
- [![Coverage Status](https://coveralls.io/repos/github/watir/watir/badge.svg?branch=master)](https://coveralls.io/github/watir/watir?branch=master)
11
+ [![Coverage Status](https://coveralls.io/repos/github/watir/watir/badge.svg?branch=main)](https://coveralls.io/github/watir/watir?branch=main)
10
12
 
11
13
  ## Using Watir
12
14
 
@@ -69,11 +71,11 @@ $ bundle exec rake svg:update
69
71
 
70
72
  ## Specs
71
73
 
72
- #### Travis CI
74
+ #### Github Actions
73
75
 
74
- Watir specs are run on [Travis CI](https://travis-ci.org/watir/watir).
76
+ Watir specs are run with [Github Actions](https://github.com/watir/watir/workflows).
75
77
 
76
- Watir code is tested with 2.3, 2.4 and 2.5 versions in multiple browsers and with multiple configurations.
78
+ Watir code is tested on Linux with latest versions of supported browsers and all active Ruby versions.
77
79
 
78
80
  #### Doctests
79
81
 
@@ -95,7 +97,7 @@ to ensure all paths in their code have tests associated with them.
95
97
 
96
98
  Watir is using [Rubocop](https://github.com/rubocop-hq/rubocop) to ensure a consistent style across the
97
99
  code base. It is run with our minimum supported Ruby version (2.3)
98
- We have some [established exceptions](https://github.com/watir/watir/blob/master/.rubocop.yml)
100
+ We have some [established exceptions](https://github.com/watir/watir/blob/main/.rubocop.yml)
99
101
  that might need to be tweaked for new code submissions. This can be addressed in the PR as necessary.
100
102
 
101
103
  #### Statistics
@@ -107,7 +109,4 @@ on wire calls.
107
109
 
108
110
  ## Copyright
109
111
 
110
- Copyright (c) 2009-2015 Jari Bakken
111
- Copyright (c) 2015-2018 Alex Rodionov, Titus Fortner
112
- Copyright (c) 2018 Justin Ko
113
112
  See LICENSE for details
data/Rakefile CHANGED
@@ -5,7 +5,7 @@ Bundler::GemHelper.install_tasks
5
5
 
6
6
  require 'rspec/core/rake_task'
7
7
  RSpec::Core::RakeTask.new(:spec) do |spec|
8
- spec.rspec_opts = %w[--color --require fuubar --format Fuubar]
8
+ spec.rspec_opts = %w[--color --format doc]
9
9
  spec.pattern = 'spec/**/*_spec.rb'
10
10
  spec.exclude_pattern = 'spec/unit/**/*_spec.rb'
11
11
  end
@@ -61,7 +61,7 @@ end
61
61
 
62
62
  if extractor.errors.any?
63
63
  puts "\n\n<======================= ERRORS =======================>\n\n"
64
- puts extractor.errors.join("\n" + '=' * 80 + "\n")
64
+ puts extractor.errors.join("\n#{'=' * 80}\n")
65
65
  end
66
66
  end
67
67
 
@@ -93,7 +93,7 @@ YARD::Rake::YardocTask.new do |task|
93
93
  task.options = %w[--debug] # this is pretty slow, so nice with some output
94
94
  end
95
95
 
96
- require 'yard-doctest'
96
+ require 'yard/doctest/rake'
97
97
  YARD::Doctest::RakeTask.new do |task|
98
98
  task.doctest_opts = ['-v']
99
99
  end
@@ -115,7 +115,7 @@ namespace :changes do
115
115
 
116
116
  desc 'Print latest diff'
117
117
  task print: :differ do
118
- VersionDiffer.new.print_latest(STDOUT)
118
+ VersionDiffer.new.print_latest($stdout)
119
119
  end
120
120
  end
121
121
 
@@ -1,2 +1,2 @@
1
1
  require 'watir'
2
- warn Kernel.caller.first + ': `require "watir-webdriver"` is deprecated. Please, use `require "watir"`.'
2
+ warn "#{Kernel.caller.first}: `require 'watir-webdriver'` is deprecated. Please, use `require 'watir'`."
data/lib/watir.rb CHANGED
@@ -6,6 +6,7 @@ require 'watir/legacy_wait'
6
6
  require 'watir/wait'
7
7
  require 'watir/exception'
8
8
  require 'watir/window'
9
+ require 'watir/window_collection'
9
10
  require 'watir/has_window'
10
11
  require 'watir/adjacent'
11
12
  require 'watir/js_execution'
@@ -13,12 +14,14 @@ require 'watir/alert'
13
14
  require 'watir/js_snippets'
14
15
  require 'watir/container'
15
16
  require 'watir/cookies'
17
+ require 'watir/http_client'
16
18
  require 'watir/capabilities'
17
19
  require 'watir/navigation'
18
20
  require 'watir/browser'
19
21
  require 'watir/screenshot'
20
22
  require 'watir/after_hooks'
21
23
  require 'watir/logger'
24
+ require 'watir/version'
22
25
 
23
26
  module Watir
24
27
  @relaxed_locate = true
@@ -114,7 +117,6 @@ require 'watir/elements/element'
114
117
  require 'watir/elements/html_elements'
115
118
  require 'watir/elements/svg_elements'
116
119
 
117
- require 'watir/elements/area'
118
120
  require 'watir/elements/button'
119
121
  require 'watir/elements/cell'
120
122
  require 'watir/elements/checkbox'
@@ -113,16 +113,14 @@ module Watir
113
113
  def xpath_adjacent(opt = {})
114
114
  plural = opt.delete(:plural)
115
115
  opt[:index] ||= 0 unless plural || opt.values.any? { |e| e.is_a? Regexp }
116
- klass = if !plural && opt[:tag_name]
117
- Watir.element_class_for(opt[:tag_name])
118
- elsif !plural
119
- HTMLElement
120
- elsif opt[:tag_name]
121
- Object.const_get("#{Watir.element_class_for(opt[:tag_name])}Collection")
122
- else
123
- HTMLElementCollection
124
- end
125
- klass.new(self, opt)
116
+ if !plural
117
+ el = Watir.element_class_for(opt[:tag_name] || '').new(self, opt)
118
+ el.is_a?(Input) ? el.to_subtype : el
119
+ elsif opt[:tag_name]
120
+ Watir.const_get("#{Watir.element_class_for(opt[:tag_name])}Collection").new(self, opt)
121
+ else
122
+ HTMLElementCollection.new(self, opt)
123
+ end
126
124
  end
127
125
  end # Adjacent
128
126
  end # Watir
@@ -69,8 +69,8 @@ module Watir
69
69
  return unless @after_hooks.any? && !@browser.alert.exists?
70
70
 
71
71
  each { |after_hook| after_hook.call(@browser) }
72
- rescue Selenium::WebDriver::Error::NoSuchWindowError => ex
73
- Watir.logger.info "Could not execute After Hooks because browser window was closed #{ex}"
72
+ rescue Selenium::WebDriver::Error::NoSuchWindowError => e
73
+ Watir.logger.info "Could not execute After Hooks because browser window was closed #{e}"
74
74
  end
75
75
 
76
76
  #
@@ -99,8 +99,8 @@ module Watir
99
99
  # @yieldparam [#call] after_hook Object responding to call
100
100
  #
101
101
 
102
- def each
103
- @after_hooks.each { |after_hook| yield after_hook }
102
+ def each(&blk)
103
+ @after_hooks.each { |after_hook| blk.call(after_hook) }
104
104
  end
105
105
 
106
106
  #
data/lib/watir/alert.rb CHANGED
@@ -84,6 +84,7 @@ module Watir
84
84
  false
85
85
  end
86
86
  alias present? exists?
87
+ alias exist? exists?
87
88
 
88
89
  #
89
90
  # @api private
@@ -46,6 +46,8 @@ module Watir
46
46
  # @return [$1] value of $3 property
47
47
  #
48
48
  def attribute(type, method, attr)
49
+ return if method_defined?(method)
50
+
49
51
  typed_attributes[type] << [method, attr]
50
52
  define_attribute(type, method, attr)
51
53
  end
data/lib/watir/browser.rb CHANGED
@@ -11,7 +11,7 @@ module Watir
11
11
  include Exception
12
12
  include Scrolling
13
13
 
14
- attr_writer :default_context, :original_window, :locator_namespace
14
+ attr_writer :default_context, :original_window, :locator_namespace, :timer
15
15
  attr_reader :driver, :after_hooks
16
16
  alias wd driver # ensures duck typing with Watir::Element
17
17
 
@@ -213,11 +213,11 @@ module Watir
213
213
  # @param args Arguments will be available in the given script in the 'arguments' pseudo-array
214
214
  #
215
215
 
216
- def execute_script(script, *args)
216
+ def execute_script(script, *args, function_name: nil)
217
217
  args.map! do |e|
218
218
  e.is_a?(Element) ? e.wait_until(&:exists?).wd : e
219
219
  end
220
-
220
+ Watir.logger.info "Executing Script on Browser: #{function_name}" if function_name
221
221
  wrap_elements_in(self, @driver.execute_script(script, *args))
222
222
  end
223
223
 
@@ -300,6 +300,10 @@ module Watir
300
300
  end
301
301
  end
302
302
 
303
+ def timer
304
+ @timer ||= Wait::Timer.new
305
+ end
306
+
303
307
  private
304
308
 
305
309
  def wrap_element(scope, element)
@@ -2,18 +2,22 @@ module Watir
2
2
  class Capabilities
3
3
  attr_reader :options
4
4
 
5
- def initialize(browser, options = {})
5
+ def initialize(browser = nil, options = {})
6
+ if browser.is_a?(Hash)
7
+ options = browser
8
+ browser = nil
9
+ end
10
+
6
11
  @options = options.dup
7
12
  Watir.logger.info "Creating Browser instance of #{browser} with user provided options: #{@options.inspect}"
8
- @browser = if browser == :remote && @options.key?(:browser)
9
- @options.delete(:browser)
10
- elsif browser == :remote && @options.key?(:desired_capabilities)
11
- @options[:desired_capabilities].browser_name.to_sym
12
- else
13
- browser.to_sym
14
- end
15
- @selenium_browser = browser == :remote || options[:url] ? :remote : browser
16
13
 
14
+ deprecate_options_capabilities
15
+ deprecate_desired_capabilities
16
+ deprecate_url_service if @options.key?(:service) && @options.key?(:url)
17
+
18
+ @browser = deprecate_remote(browser) || browser.nil? && infer_browser || browser.to_sym
19
+
20
+ @selenium_browser = options[:url] ? :remote : @browser
17
21
  @selenium_opts = {}
18
22
  end
19
23
 
@@ -24,15 +28,15 @@ module Watir
24
28
  private
25
29
 
26
30
  def process_arguments
27
- url = @options.delete(:url)
28
- @selenium_opts[:url] = url if url
29
-
30
- create_http_client
31
-
32
- @selenium_opts[:port] = @options.delete(:port) if @options.key?(:port)
33
- @selenium_opts[:driver_opts] = @options.delete(:driver_opts) if @options.key?(:driver_opts)
34
31
  @selenium_opts[:listener] = @options.delete(:listener) if @options.key?(:listener)
35
32
 
33
+ if @options.key?(:url)
34
+ @selenium_opts[:url] = @options.delete(:url)
35
+ else
36
+ process_service(@options.delete(:service))
37
+ end
38
+
39
+ process_http_client
36
40
  process_browser_options
37
41
  process_capabilities
38
42
  Watir.logger.info "Creating Browser instance with Watir processed options: #{@selenium_opts.inspect}"
@@ -40,110 +44,254 @@ module Watir
40
44
  @selenium_opts
41
45
  end
42
46
 
43
- def create_http_client
44
- client_timeout = @options.delete(:client_timeout)
45
- open_timeout = @options.delete(:open_timeout)
46
- read_timeout = @options.delete(:read_timeout)
47
-
48
- http_client = @options.delete(:http_client)
49
-
50
- %i[open_timeout read_timeout client_timeout].each do |t|
51
- next if http_client.nil? || !respond_to?(t)
52
-
53
- msg = "You can pass #{t} value directly into Watir::Browser opt without needing to use :http_client"
54
- Watir.logger.warn msg, ids: %i[http_client use_capabilities]
47
+ def process_http_client
48
+ http_client = @options.delete(:http_client) || Watir::HttpClient.new
49
+ if http_client.is_a?(Hash)
50
+ http_client = Watir::HttpClient.new(http_client)
51
+ elsif !http_client.is_a?(Selenium::WebDriver::Remote::Http::Common)
52
+ raise TypeError, ':http_client must be a Hash or a Selenium HTTP Client instance'
55
53
  end
56
54
 
57
- http_client ||= Selenium::WebDriver::Remote::Http::Default.new
55
+ unless http_client.is_a?(Watir::HttpClient)
56
+ Watir.logger.warn 'Check out the new Watir::HttpClient and let us know if there are missing features you need',
57
+ ids: [:watir_client]
58
+ end
58
59
 
59
- http_client.timeout = client_timeout if client_timeout
60
- http_client.open_timeout = open_timeout if open_timeout
61
- http_client.read_timeout = read_timeout if read_timeout
60
+ process_http_client_timeouts(http_client)
62
61
  @selenium_opts[:http_client] = http_client
63
62
  end
64
63
 
65
- # TODO: - this will get addressed with Capabilities Update
66
- # rubocop:disable Metrics/AbcSize
67
- # rubocop:disable Metrics/MethodLength
68
- # rubocop:disable Metrics/PerceivedComplexity:
69
- # rubocop:disable Metrics/CyclomaticComplexity::
70
64
  def process_browser_options
71
65
  browser_options = @options.delete(:options) || {}
66
+ process_w3c_capabilities(browser_options)
72
67
 
73
- case @selenium_browser
68
+ case @browser
74
69
  when :chrome
75
- if @options.key?(:args) || @options.key?(:switches)
76
- browser_options ||= {}
77
- browser_options[:args] = (@options.delete(:args) || @options.delete(:switches)).dup
78
- end
79
- if @options.delete(:headless)
80
- browser_options ||= {}
81
- browser_options[:args] ||= []
82
- browser_options[:args] += ['--headless', '--disable-gpu']
83
- end
84
- @selenium_opts[:options] = browser_options if browser_options.is_a? Selenium::WebDriver::Chrome::Options
85
- @selenium_opts[:options] ||= Selenium::WebDriver::Chrome::Options.new(browser_options)
70
+ process_chrome_options(browser_options)
86
71
  when :firefox
87
- profile = @options.delete(:profile)
88
- if browser_options.is_a? Selenium::WebDriver::Firefox::Options
89
- @selenium_opts[:options] = browser_options
90
- if profile
91
- msg = 'Initializing Browser with both :profile and :option', ':profile as a key inside :option'
92
- Watir.logger.deprecate msg, ids: [:firefox_profile]
93
- end
94
- end
95
- if @options.delete(:headless)
96
- browser_options ||= {}
97
- browser_options[:args] ||= []
98
- browser_options[:args] += ['--headless']
99
- end
100
- @selenium_opts[:options] ||= Selenium::WebDriver::Firefox::Options.new(browser_options)
101
- @selenium_opts[:options].profile = profile if profile
72
+ process_firefox_options(browser_options)
102
73
  when :safari
103
- Selenium::WebDriver::Safari.technology_preview! if @options.delete(:technology_preview)
104
- when :remote
105
- if @browser == :chrome && @options.delete(:headless)
106
- args = @options.delete(:args) || @options.delete(:switches) || []
107
- @options['chromeOptions'] = {'args' => args + ['--headless', '--disable-gpu']}
108
- end
109
- if @browser == :firefox && @options.delete(:headless)
110
- args = @options.delete(:args) || @options.delete(:switches) || []
111
- @options[Selenium::WebDriver::Firefox::Options::KEY] = {'args' => args + ['--headless']}
112
- end
113
- if @browser == :safari && @options.delete(:technology_preview)
114
- @options['safari.options'] = {'technologyPreview' => true}
115
- end
116
- when :ie
117
- if @options.key?(:args)
118
- browser_options ||= {}
119
- browser_options[:args] = @options.delete(:args).dup
120
- end
121
- unless browser_options.is_a? Selenium::WebDriver::IE::Options
122
- ie_caps = browser_options.select { |k| Selenium::WebDriver::IE::Options::CAPABILITIES.include?(k) }
123
- browser_options = Selenium::WebDriver::IE::Options.new(browser_options)
124
- ie_caps.each { |k, v| browser_options.add_option(k, v) }
125
- end
126
- @selenium_opts[:options] = browser_options
74
+ process_safari_options(browser_options)
75
+ when :ie, :internet_explorer
76
+ process_ie_options(browser_options)
127
77
  end
128
78
  end
129
- # rubocop:enable Metrics/AbcSize
130
- # rubocop:enable Metrics/MethodLength
131
- # rubocop:enable Metrics/PerceivedComplexity:
132
- # rubocop:enable Metrics/CyclomaticComplexity::
133
79
 
134
80
  def process_capabilities
135
- caps = @options.delete(:desired_capabilities)
81
+ caps = @options.delete(:capabilities)
82
+
83
+ unless @options.empty?
84
+ Watir.logger.deprecate('passing unrecognized arguments into Browser constructor',
85
+ 'appropriate keyword to nest all arguments',
86
+ ids: %i[unknown_keyword capabilities],
87
+ reference: 'http://watir.com/guides/capabilities.html')
88
+ end
136
89
 
137
90
  if caps
138
- msg = 'You can pass values directly into Watir::Browser opt without needing to use :desired_capabilities'
139
- Watir.logger.warn msg,
140
- ids: [:use_capabilities]
141
91
  @selenium_opts.merge!(@options)
142
92
  else
143
- caps = Selenium::WebDriver::Remote::Capabilities.send @browser, @options
93
+ caps = Selenium::WebDriver::Remote::Capabilities.send @browser, @options.merge(@w3c_caps)
144
94
  end
145
95
 
146
96
  @selenium_opts[:desired_capabilities] = caps
147
97
  end
98
+
99
+ def deprecate_desired_capabilities
100
+ return unless @options.key?(:desired_capabilities)
101
+
102
+ Watir.logger.deprecate(':desired_capabilities to initialize Browser',
103
+ ':capabilities or preferably :options',
104
+ ids: [:desired_capabilities],
105
+ reference: 'http://watir.com/guides/capabilities.html')
106
+ @options[:capabilities] = @options.delete(:desired_capabilities)
107
+ end
108
+
109
+ def deprecate_url_service
110
+ Watir.logger.deprecate('allowing Browser initialization with both :url & :service',
111
+ 'just :service',
112
+ ids: [:url_service],
113
+ reference: 'http://watir.com/guides/capabilities.html')
114
+ end
115
+
116
+ def process_http_client_timeouts(http_client)
117
+ deprecate_client_timeout(http_client) if @options.key? :client_timeout
118
+ deprecate_open_timeout(http_client) if @options.key? :open_timeout
119
+ deprecate_read_timeout(http_client) if @options.key? :read_timeout
120
+ end
121
+
122
+ def deprecate_client_timeout(http_client)
123
+ Watir.logger.deprecate(':client_timeout to initialize Browser',
124
+ ':open_timeout and/or :read_timeout in a Hash with :http_client key',
125
+ ids: [:http_client_timeout],
126
+ reference: 'http://watir.com/guides/capabilities.html')
127
+ timeout = @options.delete(:client_timeout)
128
+ http_client.open_timeout = timeout
129
+ http_client.read_timeout = timeout
130
+ end
131
+
132
+ def deprecate_open_timeout(http_client)
133
+ Watir.logger.deprecate(':open_timeout to initialize Browser',
134
+ ':open_timeout in a Hash with :http_client key',
135
+ ids: %i[http_open_timeout capabilities],
136
+ reference: 'http://watir.com/guides/capabilities.html')
137
+ http_client.open_timeout = @options.delete(:open_timeout)
138
+ end
139
+
140
+ def deprecate_read_timeout(http_client)
141
+ Watir.logger.deprecate(':read_timeout to initialize Browser',
142
+ ':read_timeout in a Hash with :http_client key',
143
+ ids: %i[http_read_timeout capabilities],
144
+ reference: 'http://watir.com/guides/capabilities.html')
145
+ http_client.read_timeout = @options.delete(:read_timeout)
146
+ end
147
+
148
+ def process_chrome_options(browser_options)
149
+ @selenium_opts[:options] = browser_options if browser_options.is_a? Selenium::WebDriver::Chrome::Options
150
+ @selenium_opts[:options] ||= Selenium::WebDriver::Chrome::Options.new(**browser_options)
151
+
152
+ process_args
153
+
154
+ return unless @options.delete(:headless)
155
+
156
+ @selenium_opts[:options].args << '--headless'
157
+ @selenium_opts[:options].args << '--disable-gpu'
158
+ end
159
+
160
+ def process_firefox_options(browser_options)
161
+ @selenium_opts[:options] = browser_options if browser_options.is_a? Selenium::WebDriver::Firefox::Options
162
+
163
+ @selenium_opts[:options] ||= Selenium::WebDriver::Firefox::Options.new(**browser_options)
164
+ if @options.key?(:profile)
165
+ new = 'Initializing Browser with both :profile and :option'
166
+ old = ':profile as a key inside :option'
167
+ Watir.logger.deprecate new, old, ids: [:firefox_profile]
168
+
169
+ @selenium_opts[:options].profile = @options.delete(:profile)
170
+ end
171
+
172
+ @selenium_opts[:options].args << '--headless' if @options.delete(:headless)
173
+ end
174
+
175
+ def process_safari_options(browser_options)
176
+ @selenium_opts[:options] = browser_options if browser_options.is_a? Selenium::WebDriver::Safari::Options
177
+ @selenium_opts[:options] ||= Selenium::WebDriver::Safari::Options.new(**browser_options)
178
+ Selenium::WebDriver::Safari.technology_preview! if @options.delete(:technology_preview)
179
+ end
180
+
181
+ def process_ie_options(browser_options)
182
+ @selenium_opts[:options] = browser_options if browser_options.is_a? Selenium::WebDriver::IE::Options
183
+ @selenium_opts[:options] ||= Selenium::WebDriver::IE::Options.new(**browser_options)
184
+
185
+ process_args
186
+ end
187
+
188
+ def process_service(service)
189
+ service = deprecate_service_keywords if service.nil?
190
+
191
+ @selenium_opts[:service] = case service
192
+ when Hash
193
+ return if service.empty?
194
+
195
+ Selenium::WebDriver::Service.send(@browser, service)
196
+ when Selenium::WebDriver::Service
197
+ service
198
+ else
199
+ raise TypeError, "#{service} needs to be Selenium Service or Hash instance"
200
+ end
201
+ end
202
+
203
+ def deprecate_service_keywords
204
+ service = {}
205
+ if @options.key?(:port)
206
+ Watir.logger.deprecate(':port to initialize Browser',
207
+ ':port in a Hash with :service key',
208
+ ids: %i[port_keyword capabilities],
209
+ reference: 'http://watir.com/guides/capabilities.html')
210
+ service[:port] = @options.delete(:port)
211
+ end
212
+ if @options.key?(:driver_opts)
213
+ Watir.logger.deprecate(':driver_opts to initialize Browser',
214
+ ':args as Array in a Hash with :service key',
215
+ ids: %i[driver_opts_keyword capabilities],
216
+ reference: 'http://watir.com/guides/capabilities.html')
217
+ service[:args] = @options.delete(:driver_opts)
218
+ end
219
+ service
220
+ end
221
+
222
+ def process_args
223
+ args = if @options.key?(:args)
224
+ deprecate_args
225
+ @options.delete(:args)
226
+ elsif @options.key?(:switches)
227
+ deprecate_switches
228
+ @options.delete(:switches)
229
+ else
230
+ []
231
+ end
232
+ args.each { |arg| @selenium_opts[:options].args << arg }
233
+ end
234
+
235
+ def deprecate_args
236
+ Watir.logger.deprecate(':args to initialize Browser',
237
+ ':args inside Hash with :options key',
238
+ ids: %i[args_keyword capabilities],
239
+ reference: 'http://watir.com/guides/capabilities.html')
240
+ end
241
+
242
+ def deprecate_switches
243
+ Watir.logger.deprecate(':switches to initialize Browser',
244
+ ':switches inside Hash with :options key',
245
+ ids: %i[switches_keyword capabilities],
246
+ reference: 'http://watir.com/guides/capabilities.html')
247
+ end
248
+
249
+ def deprecate_remote(browser)
250
+ return unless browser == :remote
251
+
252
+ Watir.logger.deprecate(':remote to initialize Browser',
253
+ 'browser key along with remote url',
254
+ ids: %i[remote_keyword capabilities],
255
+ reference: 'http://watir.com/guides/capabilities.html')
256
+ infer_browser
257
+ end
258
+
259
+ def infer_browser
260
+ if @options.key?(:browser)
261
+ @options.delete(:browser)
262
+ elsif @options.key?(:capabilities)
263
+ @options[:capabilities].browser_name.tr(' ', '_').to_sym
264
+ elsif @options.key?(:options)
265
+ @options[:options].class.to_s.split('::')[-2].downcase.to_sym
266
+ else
267
+ :chrome
268
+ end
269
+ end
270
+
271
+ def process_w3c_capabilities(opts)
272
+ @w3c_caps = {}
273
+ return unless opts.is_a?(Hash)
274
+
275
+ w3c_keys = %i[browser_version platform_name accept_insecure_certs page_load_strategy proxy set_window_rect
276
+ timeouts unhandled_prompt_behavior strict_file_interactibility]
277
+
278
+ opts.each do |key, _val|
279
+ next unless key.to_s.include?(':') || w3c_keys.include?(key)
280
+
281
+ @w3c_caps[key] = opts.delete(key)
282
+ end
283
+ end
284
+
285
+ def deprecate_options_capabilities
286
+ return unless @options.key?(:capabilities) && @options.key?(:options)
287
+
288
+ old = 'initializing Browser with both options and capabilities'
289
+ new = 'Hash with :options, Selenium Options instance with :options or' \
290
+ 'Selenium Capabilities instance with :capabilities'
291
+ Watir.logger.deprecate(old,
292
+ new,
293
+ ids: %i[options_capabilities capabilities],
294
+ reference: 'http://watir.com/guides/capabilities.html')
295
+ end
148
296
  end
149
297
  end