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/lib/watir/cookies.rb CHANGED
@@ -61,7 +61,7 @@ module Watir
61
61
  cookie[:path] = opts[:path] if opts.key?(:path)
62
62
  expires = opts[:expires]
63
63
  if expires
64
- cookie[:expires] = ::Time.parse(expires) if expires.is_a?(String) else expires
64
+ cookie[:expires] = expires.is_a?(String) ? ::Time.parse(expires) : expires
65
65
  end
66
66
  cookie[:domain] = opts[:domain] if opts.key?(:domain)
67
67
 
@@ -105,6 +105,8 @@ module Watir
105
105
  IO.write(file, to_a.to_yaml)
106
106
  end
107
107
 
108
+ #
109
+ # TODO: Use :permitted_classes keyword when minimum supported Ruby is 2.6
108
110
  #
109
111
  # Load cookies from file
110
112
  #
@@ -7,17 +7,19 @@ module Watir
7
7
  include Enumerable
8
8
  include Exception
9
9
  include JSSnippets
10
+ include Waitable
10
11
  include Locators::ClassHelpers
11
12
 
12
13
  def initialize(query_scope, selector)
13
14
  @query_scope = query_scope
14
15
  @selector = selector
16
+ @to_a = nil
15
17
 
16
18
  build unless @selector.key?(:element)
17
19
  end
18
20
 
19
21
  #
20
- # Yields each element in collection.
22
+ # Relocates elements then yields each element in resulting collection.
21
23
  #
22
24
  # @example
23
25
  # divs = browser.divs(class: 'kls')
@@ -29,6 +31,7 @@ module Watir
29
31
  #
30
32
 
31
33
  def each(&blk)
34
+ reset!
32
35
  to_a.each(&blk)
33
36
  end
34
37
 
@@ -37,6 +40,9 @@ module Watir
37
40
 
38
41
  alias empty? none?
39
42
 
43
+ alias exist? any?
44
+ alias exists? any?
45
+
40
46
  def build
41
47
  selector_builder.build(@selector.dup)
42
48
  end
@@ -145,14 +151,19 @@ module Watir
145
151
  alias eql? ==
146
152
 
147
153
  #
148
- # Creates a Collection containing elements of two collections.
154
+ # Removes cache of previously located elements in the collection.
149
155
  #
150
156
  # @example
151
157
  # options = browser.select_list(name: "new_user_languages").options
152
- # (options + browser.select_list(id: "new_user_role").options).size
153
- # #=> 8
158
+ # options.reset!
159
+ # options[0]
160
+ # #=> nil
154
161
  #
155
162
 
163
+ def reset!
164
+ @to_a = nil
165
+ end
166
+
156
167
  private
157
168
 
158
169
  def elements
@@ -182,7 +193,11 @@ module Watir
182
193
  end
183
194
 
184
195
  def ensure_context
185
- @query_scope.locate if @query_scope.is_a?(Browser) || @query_scope.located? && @query_scope.stale?
196
+ if @query_scope.is_a?(Browser) || !@query_scope.located? && @query_scope.is_a?(IFrame)
197
+ @query_scope.browser.locate
198
+ elsif @query_scope.located? && @query_scope.stale?
199
+ @query_scope.locate
200
+ end
186
201
  @query_scope.switch_to! if @query_scope.is_a?(IFrame)
187
202
  end
188
203
 
@@ -191,7 +206,7 @@ module Watir
191
206
  end
192
207
 
193
208
  def element_class
194
- Kernel.const_get(self.class.name.sub(/Collection$/, ''))
209
+ Watir.const_get(self.class.name.sub(/Collection$/, ''))
195
210
  end
196
211
 
197
212
  def construct_subtype(element, hash, tag_name)
@@ -18,6 +18,17 @@ module Watir
18
18
  attr_accessor :keyword
19
19
  attr_reader :selector
20
20
 
21
+ # https://www.w3.org/TR/html52/single-page.html#casesensitivity
22
+ CASE_INSENSITIVE_ATTRIBUTES = %i[accept accept_charset align alink axis
23
+ bgcolor charset checked clear codetype
24
+ color compact declare defer dir direction
25
+ disabled enctype face frame hreflang
26
+ http_equiv lang language link media
27
+ method multiple nohref noresize noshade
28
+ nowrap readonly rel rev rules scope
29
+ scrolling selected shape target text
30
+ type valign valuetype vlink].freeze
31
+
21
32
  #
22
33
  # temporarily add :id and :class_name manually since they're no longer specified in the HTML spec.
23
34
  #
@@ -54,12 +65,9 @@ module Watir
54
65
 
55
66
  def exists?
56
67
  if located? && stale?
57
- Watir.logger.deprecate 'Checking `#exists? == false` to determine a stale element',
58
- '`#stale? == true`',
59
- reference: 'http://watir.com/staleness-changes',
60
- ids: [:stale_exists]
61
- # TODO: Change this to `reset!` after removing deprecation
62
- return false
68
+ reset!
69
+ elsif located?
70
+ return true
63
71
  end
64
72
 
65
73
  assert_exists
@@ -141,7 +149,6 @@ module Watir
141
149
  #
142
150
 
143
151
  def click(*modifiers)
144
- # TODO: Should wait_for_enabled be default, or `Button` specific behavior?
145
152
  element_call(:wait_for_enabled) do
146
153
  if modifiers.any?
147
154
  action = driver.action
@@ -196,15 +203,35 @@ module Watir
196
203
  end
197
204
 
198
205
  #
199
- # Right clicks the element.
200
- # Note that browser support may vary.
206
+ # Right clicks the element, optionally while pressing the given modifier keys.
207
+ # Note that support for holding a modifier key is currently experimental,
208
+ # and may not work at all. Also, the browser support may vary.
201
209
  #
202
210
  # @example
203
211
  # browser.element(name: "new_user_button").right_click
204
212
  #
213
+ # @example Right click an element with shift key pressed
214
+ # browser.element(name: "new_user_button").right_click(:shift)
215
+ #
216
+ # @example Click an element with several modifier keys pressed
217
+ # browser.element(name: "new_user_button").right_click(:shift, :alt)
218
+ #
219
+ # @param [:shift, :alt, :control, :command, :meta] modifiers to press while right clicking.
220
+ #
221
+
222
+ def right_click(*modifiers)
223
+ element_call(:wait_for_present) do
224
+ action = driver.action
225
+ if modifiers.any?
226
+ modifiers.each { |mod| action.key_down mod }
227
+ action.context_click(@element)
228
+ modifiers.each { |mod| action.key_up mod }
229
+ action.perform
230
+ else
231
+ action.context_click(@element).perform
232
+ end
233
+ end
205
234
 
206
- def right_click
207
- element_call(:wait_for_present) { driver.action.context_click(@element).perform }
208
235
  browser.after_hooks.run
209
236
  end
210
237
 
@@ -247,7 +274,7 @@ module Watir
247
274
  # Note that browser support may vary.
248
275
  #
249
276
  # @example
250
- # browser.div(id: "draggable").drag_and_drop_by 100, -200
277
+ # browser.div(id: "draggable").drag_and_drop_by 100, 25
251
278
  #
252
279
  # @param [Integer] right_by
253
280
  # @param [Integer] down_by
@@ -358,6 +385,8 @@ module Watir
358
385
  #
359
386
 
360
387
  def scroll_into_view
388
+ Watir.logger.deprecate 'Element#scroll_into_view', 'Element#scroll methods', ids: [:scroll_into_view]
389
+
361
390
  element_call { @element.location_once_scrolled_into_view }
362
391
  end
363
392
 
@@ -460,16 +489,7 @@ module Watir
460
489
  msg = '#visible? behavior will be changing slightly, consider switching to #present? ' \
461
490
  '(more details: http://watir.com/element-existentialism/)'
462
491
  Watir.logger.warn msg, ids: [:visible_element]
463
- displayed = display_check
464
- if displayed.nil? && display_check
465
- Watir.logger.deprecate 'Checking `#visible? == false` to determine a stale element',
466
- '`#stale? == true`',
467
- reference: 'http://watir.com/staleness-changes',
468
- ids: [:stale_visible]
469
- end
470
- raise unknown_exception if displayed.nil?
471
-
472
- displayed
492
+ display_check
473
493
  end
474
494
 
475
495
  #
@@ -492,14 +512,7 @@ module Watir
492
512
  #
493
513
 
494
514
  def present?
495
- displayed = display_check
496
- if displayed.nil? && display_check
497
- Watir.logger.deprecate 'Checking `#present? == false` to determine a stale element',
498
- '`#stale? == true`',
499
- reference: 'http://watir.com/staleness-changes',
500
- ids: [:stale_present]
501
- end
502
- displayed
515
+ display_check
503
516
  rescue UnknownObjectException, UnknownFrameException
504
517
  false
505
518
  end
@@ -547,7 +560,7 @@ module Watir
547
560
  #
548
561
 
549
562
  def to_subtype
550
- tag = tag_name()
563
+ tag = tag_name
551
564
  klass = if tag == 'input'
552
565
  case attribute_value(:type)
553
566
  when 'checkbox'
@@ -595,7 +608,7 @@ module Watir
595
608
  def stale_in_context?
596
609
  @element.css_value('staleness_check') # any wire call will check for staleness
597
610
  false
598
- rescue Selenium::WebDriver::Error::ObsoleteElementError
611
+ rescue Selenium::WebDriver::Error::StaleElementReferenceError
599
612
  true
600
613
  end
601
614
 
@@ -686,7 +699,7 @@ module Watir
686
699
  return assert_enabled unless Watir.relaxed_locate?
687
700
 
688
701
  wait_for_exists
689
- return unless [Input, Button, Select, Option].any? { |c| is_a? c } || @content_editable
702
+ return unless [Input, Button, Select, Option].any? { |c| is_a? c } || content_editable
690
703
  return if enabled?
691
704
 
692
705
  begin
@@ -698,9 +711,7 @@ module Watir
698
711
 
699
712
  def wait_for_writable
700
713
  wait_for_enabled
701
- unless Watir.relaxed_locate?
702
- raise_writable unless !respond_to?(:readonly?) || !readonly?
703
- end
714
+ raise_writable unless Watir.relaxed_locate? || (!respond_to?(:readonly?) || !readonly?)
704
715
 
705
716
  return if !respond_to?(:readonly?) || !readonly?
706
717
 
@@ -720,7 +731,11 @@ module Watir
720
731
  end
721
732
 
722
733
  def ensure_context
723
- @query_scope.locate if @query_scope.is_a?(Browser) || @query_scope.located? && @query_scope.stale?
734
+ if @query_scope.is_a?(Browser) || !@query_scope.located? && @query_scope.is_a?(IFrame)
735
+ @query_scope.browser.locate
736
+ elsif @query_scope.located? && @query_scope.stale?
737
+ @query_scope.locate
738
+ end
724
739
  @query_scope.switch_to! if @query_scope.is_a?(IFrame)
725
740
  end
726
741
 
@@ -770,54 +785,52 @@ module Watir
770
785
  @element.displayed?
771
786
  rescue Selenium::WebDriver::Error::StaleElementReferenceError
772
787
  reset!
773
- nil
788
+ retry
774
789
  end
775
790
 
776
791
  # TODO: - this will get addressed with Watir::Executor implementation
777
792
  # rubocop:disable Metrics/AbcSize
778
793
  # rubocop:disable Metrics/MethodLength
779
- # rubocop:disable Metrics/PerceivedComplexity
780
794
  # rubocop:disable Metrics/CyclomaticComplexity:
795
+ # rubocop:disable Metrics/PerceivedComplexity::
781
796
  def element_call(precondition = nil, &block)
782
797
  caller = caller_locations(1, 1)[0].label
783
- already_locked = Wait.timer.locked?
784
- Wait.timer = Wait::Timer.new(timeout: Watir.default_timeout) unless already_locked
798
+ already_locked = browser.timer.locked?
799
+ browser.timer = Wait::Timer.new(timeout: Watir.default_timeout) unless already_locked
785
800
 
786
801
  begin
787
802
  check_condition(precondition, caller)
788
803
  Watir.logger.debug "-> `Executing #{inspect}##{caller}`"
789
804
  yield
790
- rescue unknown_exception => ex
805
+ rescue unknown_exception => e
791
806
  element_call(:wait_for_exists, &block) if precondition.nil?
792
- msg = ex.message
807
+ msg = e.message
793
808
  msg += '; Maybe look in an iframe?' if @query_scope.iframe.exists?
794
- custom_attributes = @locator.nil? ? [] : selector_builder.custom_attributes
809
+ custom_attributes = !defined?(@locator) || @locator.nil? ? [] : selector_builder.custom_attributes
795
810
  unless custom_attributes.empty?
796
811
  msg += "; Watir treated #{custom_attributes} as a non-HTML compliant attribute, ensure that was intended"
797
812
  end
798
813
  raise unknown_exception, msg
799
- rescue Selenium::WebDriver::Error::StaleElementReferenceError
814
+ rescue Selenium::WebDriver::Error::StaleElementReferenceError, Selenium::WebDriver::Error::NoSuchElementError
800
815
  reset!
801
816
  retry
802
- rescue Selenium::WebDriver::Error::ElementNotVisibleError, Selenium::WebDriver::Error::ElementNotInteractableError
803
- raise_present unless Wait.timer.remaining_time.positive?
817
+ # TODO: - InvalidElementStateError is deprecated, so no longer calling `raise_disabled`
818
+ # need a better way to handle this
819
+ rescue Selenium::WebDriver::Error::ElementNotInteractableError
820
+ raise_present unless browser.timer.remaining_time.positive?
804
821
  raise_present unless %i[wait_for_present wait_for_enabled wait_for_writable].include?(precondition)
805
822
  retry
806
- rescue Selenium::WebDriver::Error::InvalidElementStateError
807
- raise_disabled unless Wait.timer.remaining_time.positive?
808
- raise_disabled unless %i[wait_for_present wait_for_enabled wait_for_writable].include?(precondition)
809
- retry
810
823
  rescue Selenium::WebDriver::Error::NoSuchWindowError
811
824
  raise NoMatchingWindowFoundException, 'browser window was closed'
812
825
  ensure
813
826
  Watir.logger.debug "<- `Completed #{inspect}##{caller}`"
814
- Wait.timer.reset! unless already_locked
827
+ browser.timer.reset! unless already_locked
815
828
  end
816
829
  end
817
830
  # rubocop:enable Metrics/AbcSize
818
831
  # rubocop:enable Metrics/MethodLength
832
+ # rubocop:enable Metrics/CyclomaticComplexity
819
833
  # rubocop:enable Metrics/PerceivedComplexity
820
- # rubocop:enable Metrics/CyclomaticComplexity:
821
834
 
822
835
  def check_condition(condition, caller)
823
836
  Watir.logger.debug "<- `Verifying precondition #{inspect}##{condition} for #{caller}`"
@@ -12,6 +12,7 @@ module Watir
12
12
 
13
13
  self.value = path
14
14
  end
15
+ alias upload set
15
16
 
16
17
  #
17
18
  # Sets the file field to the given path
@@ -272,7 +272,6 @@ module Watir
272
272
  attribute(String, :form, :form)
273
273
  attribute(String, :label, :label)
274
274
  attribute("Boolean", :defaultselected?, :defaultSelected)
275
- attribute("Boolean", :selected?, :selected)
276
275
  attribute(String, :value, :value)
277
276
  attribute(Integer, :index, :index)
278
277
  end
@@ -44,8 +44,9 @@ module Watir
44
44
  # @see Watir::Browser#execute_script
45
45
  #
46
46
 
47
- def execute_script(script, *args)
47
+ def execute_script(script, *args, function_name: nil)
48
48
  args.map! do |e|
49
+ Watir.logger.info "Executing Script on Frame: #{function_name}" if function_name
49
50
  e.is_a?(Element) ? e.wait_until(&:exists?).wd : e
50
51
  end
51
52
  returned = driver.execute_script(script, *args)
@@ -134,8 +135,8 @@ module Watir
134
135
  @element
135
136
  end
136
137
 
137
- def respond_to_missing?(meth, _include_private = false)
138
- @driver.respond_to?(meth) || @element.respond_to?(meth) || super
138
+ def respond_to_missing?(meth, _include_private)
139
+ @driver.respond_to?(meth) || @element.respond_to?(meth) || super(meth, false)
139
140
  end
140
141
 
141
142
  def method_missing(meth, *args, &blk)
@@ -3,13 +3,4 @@ module Watir
3
3
  alias link a
4
4
  alias links as
5
5
  end # Container
6
-
7
- class Anchor < HTMLElement
8
- #
9
- # @todo temporarily add href attribute
10
- #
11
- # @see https://www.w3.org/Bugs/Public/show_bug.cgi?id=23192
12
- #
13
- attribute String, :href, :href
14
- end # Anchor
15
6
  end # Watir
@@ -33,7 +33,7 @@ module Watir
33
33
  #
34
34
 
35
35
  def text
36
- l = label()
36
+ l = label
37
37
  l.exist? ? l.text : ''
38
38
  end
39
39
  end # Radio
@@ -30,8 +30,11 @@ module Watir
30
30
  #
31
31
 
32
32
  def select(*str_or_rx)
33
- results = str_or_rx.flatten.map { |v| select_by v }
34
- results.first
33
+ if str_or_rx.size > 1 || str_or_rx.first.is_a?(Array)
34
+ str_or_rx.flatten.map { |v| select_all_by v }.first
35
+ else
36
+ str_or_rx.flatten.map { |v| select_by v }.first
37
+ end
35
38
  end
36
39
 
37
40
  #
@@ -43,6 +46,10 @@ module Watir
43
46
  #
44
47
 
45
48
  def select_all(*str_or_rx)
49
+ Watir.logger.deprecate('#select_all',
50
+ '#select with an Array instance',
51
+ ids: [:select_all])
52
+
46
53
  results = str_or_rx.flatten.map { |v| select_all_by v }
47
54
  results.first
48
55
  end
@@ -55,8 +62,11 @@ module Watir
55
62
  #
56
63
 
57
64
  def select!(*str_or_rx)
58
- results = str_or_rx.flatten.map { |v| select_by!(v, :single) }
59
- results.first
65
+ if str_or_rx.size > 1 || str_or_rx.first.is_a?(Array)
66
+ str_or_rx.flatten.map { |v| select_by! v, :multiple }.first
67
+ else
68
+ str_or_rx.flatten.map { |v| select_by! v, :single }.first
69
+ end
60
70
  end
61
71
 
62
72
  #
@@ -67,6 +77,10 @@ module Watir
67
77
  #
68
78
 
69
79
  def select_all!(*str_or_rx)
80
+ Watir.logger.deprecate('#select_all!',
81
+ '#select! with an Array instance',
82
+ ids: [:select_all])
83
+
70
84
  results = str_or_rx.flatten.map { |v| select_by!(v, :multiple) }
71
85
  results.first
72
86
  end
@@ -145,7 +159,8 @@ module Watir
145
159
  found = find_options(:value, str_or_rx)
146
160
 
147
161
  if found.size > 1
148
- Watir.logger.deprecate 'Selecting Multiple Options with #select', '#select_all',
162
+ Watir.logger.deprecate 'Selecting multiple options with #select using a String or Regexp value',
163
+ '#select with the desired values in an Array instance',
149
164
  ids: [:select_by]
150
165
  end
151
166
  select_matching(found)
@@ -170,8 +185,8 @@ module Watir
170
185
  str_or_rx.inspect.sub('\\A', '^')
171
186
  .sub('\\Z', '$')
172
187
  .sub('\\z', '$')
173
- .sub(%r{^\/}, '')
174
- .sub(%r{\/[a-z]*$}, '')
188
+ .sub(%r{^/}, '')
189
+ .sub(%r{/[a-z]*$}, '')
175
190
  .gsub(/\(\?#.+\)/, '')
176
191
  .gsub(/\(\?-\w+:/, '(')
177
192
  else