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.
- checksums.yaml +4 -4
- data/.github/workflows/tests.yml +7 -3
- data/.rubocop.yml +2 -7
- data/CHANGES.md +32 -0
- data/lib/watir/browser.rb +21 -7
- data/lib/watir/capabilities.rb +52 -7
- data/lib/watir/elements/date_field.rb +4 -1
- data/lib/watir/elements/date_time_field.rb +4 -1
- data/lib/watir/elements/element.rb +32 -3
- data/lib/watir/elements/font.rb +1 -0
- data/lib/watir/elements/iframe.rb +0 -1
- data/lib/watir/elements/radio.rb +2 -2
- data/lib/watir/elements/select.rb +63 -40
- data/lib/watir/has_window.rb +2 -0
- data/lib/watir/locators.rb +4 -0
- data/lib/watir/locators/element/matcher.rb +1 -1
- data/lib/watir/locators/element/selector_builder.rb +0 -3
- data/lib/watir/locators/element/selector_builder/xpath.rb +2 -1
- data/lib/watir/locators/option/matcher.rb +24 -0
- data/lib/watir/locators/option/selector_builder.rb +8 -0
- data/lib/watir/locators/option/selector_builder/xpath.rb +37 -0
- data/lib/watir/logger.rb +3 -74
- data/lib/watir/radio_set.rb +1 -0
- data/lib/watir/screenshot.rb +2 -8
- data/lib/watir/user_editable.rb +10 -3
- data/lib/watir/version.rb +1 -1
- data/lib/watir/window.rb +15 -4
- data/lib/watir/window_collection.rb +9 -0
- data/lib/watirspec.rb +4 -2
- data/lib/watirspec/guards.rb +1 -1
- data/lib/watirspec/remote_server.rb +2 -6
- data/lib/watirspec/server.rb +1 -1
- data/spec/spec_helper.rb +0 -10
- data/spec/unit/capabilities_spec.rb +198 -48
- data/spec/unit/match_elements/element_spec.rb +11 -0
- data/spec/watirspec/after_hooks_spec.rb +22 -45
- data/spec/watirspec/browser_spec.rb +185 -206
- data/spec/watirspec/cookies_spec.rb +47 -52
- data/spec/watirspec/drag_and_drop_spec.rb +5 -7
- data/spec/watirspec/elements/area_spec.rb +1 -5
- data/spec/watirspec/elements/button_spec.rb +4 -8
- data/spec/watirspec/elements/checkbox_spec.rb +2 -4
- data/spec/watirspec/elements/date_field_spec.rb +13 -16
- data/spec/watirspec/elements/date_time_field_spec.rb +14 -13
- data/spec/watirspec/elements/dd_spec.rb +3 -4
- data/spec/watirspec/elements/del_spec.rb +10 -12
- data/spec/watirspec/elements/div_spec.rb +41 -50
- data/spec/watirspec/elements/dl_spec.rb +4 -12
- data/spec/watirspec/elements/element_spec.rb +155 -89
- data/spec/watirspec/elements/elements_spec.rb +8 -9
- data/spec/watirspec/elements/filefield_spec.rb +5 -7
- data/spec/watirspec/elements/form_spec.rb +1 -1
- data/spec/watirspec/elements/forms_spec.rb +3 -5
- data/spec/watirspec/elements/frame_spec.rb +17 -22
- data/spec/watirspec/elements/iframe_spec.rb +21 -27
- data/spec/watirspec/elements/ins_spec.rb +10 -12
- data/spec/watirspec/elements/link_spec.rb +24 -26
- data/spec/watirspec/elements/links_spec.rb +8 -9
- data/spec/watirspec/elements/radio_spec.rb +11 -14
- data/spec/watirspec/elements/select_list_spec.rb +248 -117
- data/spec/watirspec/elements/span_spec.rb +10 -12
- data/spec/watirspec/elements/table_nesting_spec.rb +31 -34
- data/spec/watirspec/elements/table_spec.rb +11 -13
- data/spec/watirspec/elements/tbody_spec.rb +10 -12
- data/spec/watirspec/elements/td_spec.rb +4 -6
- data/spec/watirspec/elements/text_field_spec.rb +10 -12
- data/spec/watirspec/elements/tr_spec.rb +5 -7
- data/spec/watirspec/support/rspec_matchers.rb +1 -1
- data/spec/watirspec/user_editable_spec.rb +26 -28
- data/spec/watirspec/wait_spec.rb +255 -258
- data/spec/watirspec/window_switching_spec.rb +199 -200
- data/spec/watirspec_helper.rb +34 -31
- data/watir.gemspec +1 -1
- metadata +7 -8
- data/spec/implementation_spec.rb +0 -24
- data/spec/unit/logger_spec.rb +0 -81
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: af4906be1ae9d2713b91037006f964eddcac08ccb7a3cc341752132dea109b0f
|
4
|
+
data.tar.gz: 52ece209164c1ff75eeaec71efe8c70f03dd27f4fb1c791761e77c9ac600b333
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5623e2ac22fd67b0c7f147333ed0c0e8ce3b87cf66ecb8d40a3f85672ce647d480bfe0114986a83d1a0bdc59510ad2d164c046769eea5c44a12252b3578a4d23
|
7
|
+
data.tar.gz: 9e95f5db40c379040dabb329c64dc4032c9c290193c3804e401cbfaabecec9550fa524c50e6483a9b597240a99f542549c1b823d91c99128dbab16b44f1c4d39
|
data/.github/workflows/tests.yml
CHANGED
@@ -61,13 +61,17 @@ jobs:
|
|
61
61
|
task: [ chrome, firefox, edge ]
|
62
62
|
include:
|
63
63
|
- os: 'macos-latest'
|
64
|
-
task: 'safari'
|
65
64
|
ruby: 2.6
|
65
|
+
task: 'safari'
|
66
66
|
- os: 'macos-latest'
|
67
|
+
ruby: 3.0
|
67
68
|
task: 'safari'
|
69
|
+
- os: 'windows-latest'
|
70
|
+
ruby: 2.6
|
71
|
+
task: 'ie'
|
72
|
+
- os: 'windows-latest'
|
68
73
|
ruby: 3.0
|
69
|
-
|
70
|
-
# task: 'ie'
|
74
|
+
task: 'ie'
|
71
75
|
exclude:
|
72
76
|
- os: 'ubuntu-latest'
|
73
77
|
task: 'edge'
|
data/.rubocop.yml
CHANGED
@@ -19,17 +19,12 @@ Lint/UnifiedInteger:
|
|
19
19
|
|
20
20
|
# Default: 17
|
21
21
|
Metrics/AbcSize:
|
22
|
-
Max:
|
22
|
+
Max: 22
|
23
23
|
Exclude:
|
24
|
-
- 'lib/watir/capabilities.rb'
|
25
24
|
- 'lib/watir/locators/element/selector_builder.rb'
|
26
|
-
- 'lib/watir/locators/element/selector_builder
|
27
|
-
- 'lib/watir/locators/element/selector_builder/xpath.rb'
|
28
|
-
- 'lib/watir/locators/element/locator.rb'
|
25
|
+
- 'lib/watir/locators/element/selector_builder/*.rb'
|
29
26
|
- 'lib/watir/generator/base/generator.rb'
|
30
|
-
- 'lib/watir/generator/base/visitor.rb'
|
31
27
|
- 'spec/locator_spec_helper.rb'
|
32
|
-
- 'spec/watirspec_helper.rb'
|
33
28
|
|
34
29
|
Metrics/BlockLength:
|
35
30
|
Exclude:
|
data/CHANGES.md
CHANGED
@@ -1,3 +1,35 @@
|
|
1
|
+
### 7.0.0.beta5 (2021-08-02)
|
2
|
+
|
3
|
+
* Add support for passing in Proxy and proxy Hash to Capabilities (#933)
|
4
|
+
* Trigger change event when setting values on date and date-time fields (#938)
|
5
|
+
* Allow user to obtain Capabilities instance from Browser instance
|
6
|
+
|
7
|
+
### 7.0.0.beta4 (2021-05-29)
|
8
|
+
|
9
|
+
* Fix Bug in using negative class names within a collection (#934)
|
10
|
+
|
11
|
+
### 7.0.0.beta3 (2021-05-05)
|
12
|
+
|
13
|
+
* Fix Bug preventing proper use of vendor extension capabilities
|
14
|
+
* Changed how timeouts are supported in Watir Capabilities (#932)
|
15
|
+
* Changed the default Alert Behavior not to automatically get dismissed when an exception happens (#931)
|
16
|
+
|
17
|
+
### 7.0.0.beta2 (2021-03-28)
|
18
|
+
|
19
|
+
* Replace Watir Logger implementation with Selenium Logger subclass
|
20
|
+
* Change Watir Guards to use Selenium's new Guards. Tests run as pending when guarded.
|
21
|
+
* Implement `#set` as standard interface for each Input Element (#405)
|
22
|
+
* Implement `Element#set` to take correct `#set` behavior based on evaluated element (#664)
|
23
|
+
* Optimize Performance for Select Lists (#846)
|
24
|
+
* Allow user to set values on Select List exclusively by `:label`, `:text`, or `:value` (#846)
|
25
|
+
* Allow user to check if option selected in Select List by `:label`, `:text`, or `:value` (#929)
|
26
|
+
* Implement `Window#restore!` to return to original Window and close all others (#923)
|
27
|
+
* Minor performance improvement for iterating over windows (#923)
|
28
|
+
* Implement `Browser#closed?`; same as `Browser#exists?` without the Windows checks (#923)
|
29
|
+
* Update methods that use Selenium's Actions class to scroll element into view before acting (#847)
|
30
|
+
* Fix bug for `:text` locator with `Regexp` value based on whitespace (#924)
|
31
|
+
* Remove executing after hooks when changing frames (#888)
|
32
|
+
|
1
33
|
### 7.0.0.beta1 (2021-03-18)
|
2
34
|
|
3
35
|
* Requires Selenium 4
|
data/lib/watir/browser.rb
CHANGED
@@ -12,7 +12,7 @@ module Watir
|
|
12
12
|
include Scrolling
|
13
13
|
|
14
14
|
attr_writer :default_context, :original_window, :locator_namespace, :timer
|
15
|
-
attr_reader :driver, :after_hooks
|
15
|
+
attr_reader :driver, :after_hooks, :capabilities
|
16
16
|
alias wd driver # ensures duck typing with Watir::Element
|
17
17
|
|
18
18
|
class << self
|
@@ -42,8 +42,8 @@ module Watir
|
|
42
42
|
def initialize(browser = :chrome, *args)
|
43
43
|
case browser
|
44
44
|
when ::Symbol, String
|
45
|
-
|
46
|
-
@driver = Selenium::WebDriver.for(
|
45
|
+
@capabilities = Capabilities.new(browser, *args)
|
46
|
+
@driver = Selenium::WebDriver.for(*@capabilities.to_args)
|
47
47
|
when Selenium::WebDriver::Driver
|
48
48
|
@driver = browser
|
49
49
|
else
|
@@ -55,16 +55,21 @@ module Watir
|
|
55
55
|
@default_context = true
|
56
56
|
end
|
57
57
|
|
58
|
+
# rubocop:disable Metrics/AbcSize
|
59
|
+
# TODO: w3c default behavior does not like checking if alert exists
|
58
60
|
def inspect
|
59
61
|
if alert.exists?
|
60
62
|
format('#<%s:0x%x alert=true>', self.class, hash * 2)
|
61
63
|
else
|
62
64
|
format('#<%s:0x%x url=%s title=%s>', self.class, hash * 2, url.inspect, title.inspect)
|
63
65
|
end
|
66
|
+
rescue Selenium::WebDriver::Error::NoSuchWindowError
|
67
|
+
format('#<%s:0x%x closed=%s>', self.class, hash * 2, closed?)
|
64
68
|
rescue Errno::ECONNREFUSED
|
65
69
|
format('#<%s:0x%x closed=true>', self.class, hash * 2)
|
66
70
|
end
|
67
71
|
alias selector_string inspect
|
72
|
+
# rubocop:enable Metrics/AbcSize
|
68
73
|
|
69
74
|
#
|
70
75
|
# Returns URL of current page.
|
@@ -101,13 +106,23 @@ module Watir
|
|
101
106
|
#
|
102
107
|
|
103
108
|
def close
|
104
|
-
return if
|
109
|
+
return if closed?
|
105
110
|
|
106
111
|
@driver.quit
|
107
112
|
@closed = true
|
108
113
|
end
|
109
114
|
alias quit close
|
110
115
|
|
116
|
+
#
|
117
|
+
# Returns true if browser is closed and false otherwise.
|
118
|
+
#
|
119
|
+
# @return [Boolean]
|
120
|
+
#
|
121
|
+
|
122
|
+
def closed?
|
123
|
+
@closed
|
124
|
+
end
|
125
|
+
|
111
126
|
#
|
112
127
|
# Handles cookies.
|
113
128
|
#
|
@@ -252,12 +267,12 @@ module Watir
|
|
252
267
|
#
|
253
268
|
|
254
269
|
def exist?
|
255
|
-
|
270
|
+
!closed? && window.present?
|
256
271
|
end
|
257
272
|
alias exists? exist?
|
258
273
|
|
259
274
|
def locate
|
260
|
-
raise Error, 'browser was closed' if
|
275
|
+
raise Error, 'browser was closed' if closed?
|
261
276
|
|
262
277
|
ensure_context
|
263
278
|
end
|
@@ -267,7 +282,6 @@ module Watir
|
|
267
282
|
|
268
283
|
driver.switch_to.default_content
|
269
284
|
@default_context = true
|
270
|
-
after_hooks.run
|
271
285
|
end
|
272
286
|
|
273
287
|
def browser
|
data/lib/watir/capabilities.rb
CHANGED
@@ -55,7 +55,7 @@ module Watir
|
|
55
55
|
http_client
|
56
56
|
when Selenium::WebDriver::Remote::Http::Common
|
57
57
|
Watir.logger.warn 'Check out the new Watir::HttpClient and let us know if there are missing features you need',
|
58
|
-
|
58
|
+
id: [:watir_client]
|
59
59
|
http_client
|
60
60
|
else
|
61
61
|
raise TypeError, ':http_client must be a Hash or a Selenium HTTP Client instance'
|
@@ -63,15 +63,60 @@ module Watir
|
|
63
63
|
end
|
64
64
|
|
65
65
|
def process_browser_options
|
66
|
-
browser_options = @options.delete(:options) || {}
|
67
|
-
|
68
|
-
|
69
|
-
options
|
70
|
-
|
66
|
+
browser_options = @options.delete(:options).dup || {}
|
67
|
+
vendor_caps = process_vendor_capabilities(browser_options)
|
68
|
+
|
69
|
+
options = if browser_options.is_a? Selenium::WebDriver::Options
|
70
|
+
browser_options
|
71
|
+
else
|
72
|
+
convert_timeouts(browser_options)
|
73
|
+
Selenium::WebDriver::Options.send(@browser, **browser_options)
|
74
|
+
end
|
75
|
+
|
76
|
+
options.unhandled_prompt_behavior ||= :ignore
|
77
|
+
process_proxy_options(options)
|
71
78
|
browser_specific_options(options)
|
72
79
|
raise ArgumentError, "#{@options} are unrecognized arguments for Browser constructor" unless @options.empty?
|
73
80
|
|
74
|
-
options
|
81
|
+
vendor_caps << options
|
82
|
+
end
|
83
|
+
|
84
|
+
def process_proxy_options(options)
|
85
|
+
proxy = @options.delete(:proxy)
|
86
|
+
return if proxy.nil?
|
87
|
+
|
88
|
+
proxy &&= Selenium::WebDriver::Proxy.new(proxy) if proxy.is_a?(Hash)
|
89
|
+
|
90
|
+
unless proxy.is_a?(Selenium::WebDriver::Proxy)
|
91
|
+
raise TypeError, "#{proxy} needs to be Selenium Proxy or Hash instance"
|
92
|
+
end
|
93
|
+
|
94
|
+
options.proxy = proxy
|
95
|
+
end
|
96
|
+
|
97
|
+
def process_vendor_capabilities(opts)
|
98
|
+
return [] unless opts.is_a? Hash
|
99
|
+
|
100
|
+
vendor = opts.select { |key, _val| key.to_s.include?(':') && opts.delete(key) }
|
101
|
+
vendor.map { |k, v| Selenium::WebDriver::Remote::Capabilities.new(k => v) }
|
102
|
+
end
|
103
|
+
|
104
|
+
def convert_timeouts(browser_options)
|
105
|
+
browser_options[:timeouts] ||= {}
|
106
|
+
browser_options[:timeouts].keys.each do |key|
|
107
|
+
raise(ArgumentError, 'do not set implicit wait, Watir handles waiting automatically') if key.to_s == 'implicit'
|
108
|
+
|
109
|
+
Watir.logger.deprecate('using timeouts directly in options',
|
110
|
+
":#{key}_timeout",
|
111
|
+
id: 'timeouts')
|
112
|
+
end
|
113
|
+
if browser_options.key?(:page_load_timeout)
|
114
|
+
browser_options[:timeouts][:page_load] = browser_options.delete(:page_load_timeout) * 1000
|
115
|
+
end
|
116
|
+
|
117
|
+
return unless browser_options.key?(:script_timeout)
|
118
|
+
|
119
|
+
browser_options[:timeouts][:script] = browser_options.delete(:script_timeout) * 1000
|
75
120
|
end
|
76
121
|
|
77
122
|
def browser_specific_options(options)
|
@@ -11,7 +11,10 @@ module Watir
|
|
11
11
|
raise ArgumentError, message unless [Date, ::Time].include?(date.class)
|
12
12
|
|
13
13
|
date_string = date.strftime('%Y-%m-%d')
|
14
|
-
element_call(:wait_for_writable)
|
14
|
+
element_call(:wait_for_writable) do
|
15
|
+
execute_js(:setValue, @element, date_string)
|
16
|
+
execute_js(:fireEvent, @element, :change)
|
17
|
+
end
|
15
18
|
end
|
16
19
|
alias set set!
|
17
20
|
alias value= set
|
@@ -11,7 +11,10 @@ module Watir
|
|
11
11
|
raise ArgumentError, message unless [DateTime, ::Time].include?(date.class)
|
12
12
|
|
13
13
|
date_time_string = date.strftime('%Y-%m-%dT%H:%M')
|
14
|
-
element_call(:wait_for_writable)
|
14
|
+
element_call(:wait_for_writable) do
|
15
|
+
execute_js(:setValue, @element, date_time_string)
|
16
|
+
execute_js(:fireEvent, @element, :change)
|
17
|
+
end
|
15
18
|
end
|
16
19
|
alias set set!
|
17
20
|
alias value= set
|
@@ -163,6 +163,26 @@ module Watir
|
|
163
163
|
browser.after_hooks.run
|
164
164
|
end
|
165
165
|
|
166
|
+
#
|
167
|
+
# Determines the correct action based on subtype and takes it.
|
168
|
+
# Default is to click element
|
169
|
+
#
|
170
|
+
|
171
|
+
def set(*args)
|
172
|
+
subtype = to_subtype
|
173
|
+
if subtype.is_a?(Radio) && [String, Regexp].include?(args.first.class)
|
174
|
+
RadioSet.new(@query_scope, selector).set(*args)
|
175
|
+
elsif subtype.class.included_modules.include?(UserEditable) || subtype.public_methods(false).include?(:set)
|
176
|
+
subtype.set(*args)
|
177
|
+
elsif @content_editable || content_editable?
|
178
|
+
@content_editable = true
|
179
|
+
extend UserEditable
|
180
|
+
set(*args)
|
181
|
+
elsif args.empty? || args.first
|
182
|
+
click(*args)
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
166
186
|
#
|
167
187
|
# Simulates JavaScript click event on element.
|
168
188
|
#
|
@@ -184,7 +204,10 @@ module Watir
|
|
184
204
|
#
|
185
205
|
|
186
206
|
def double_click
|
187
|
-
element_call(:wait_for_present)
|
207
|
+
element_call(:wait_for_present) do
|
208
|
+
scroll.to
|
209
|
+
driver.action.double_click(@element).perform
|
210
|
+
end
|
188
211
|
browser.after_hooks.run
|
189
212
|
end
|
190
213
|
|
@@ -219,6 +242,7 @@ module Watir
|
|
219
242
|
|
220
243
|
def right_click(*modifiers)
|
221
244
|
element_call(:wait_for_present) do
|
245
|
+
scroll.to
|
222
246
|
action = driver.action
|
223
247
|
if modifiers.any?
|
224
248
|
modifiers.each { |mod| action.key_down mod }
|
@@ -242,7 +266,10 @@ module Watir
|
|
242
266
|
#
|
243
267
|
|
244
268
|
def hover
|
245
|
-
element_call(:wait_for_present)
|
269
|
+
element_call(:wait_for_present) do
|
270
|
+
scroll.to
|
271
|
+
driver.action.move_to(@element).perform
|
272
|
+
end
|
246
273
|
end
|
247
274
|
|
248
275
|
#
|
@@ -259,6 +286,7 @@ module Watir
|
|
259
286
|
assert_is_element other
|
260
287
|
|
261
288
|
value = element_call(:wait_for_present) do
|
289
|
+
scroll.to
|
262
290
|
driver.action
|
263
291
|
.drag_and_drop(@element, other.wd)
|
264
292
|
.perform
|
@@ -280,6 +308,7 @@ module Watir
|
|
280
308
|
|
281
309
|
def drag_and_drop_by(right_by, down_by)
|
282
310
|
element_call(:wait_for_present) do
|
311
|
+
scroll.to
|
283
312
|
driver.action
|
284
313
|
.drag_and_drop_by(@element, right_by, down_by)
|
285
314
|
.perform
|
@@ -672,7 +701,7 @@ module Watir
|
|
672
701
|
|
673
702
|
def wait_for_enabled
|
674
703
|
wait_for_exists
|
675
|
-
return unless [Input, Button, Select, Option].any? { |c| is_a? c } || content_editable
|
704
|
+
return unless [Input, Button, Select, Option].any? { |c| is_a? c } || @content_editable
|
676
705
|
return if enabled?
|
677
706
|
|
678
707
|
begin
|
data/lib/watir/elements/font.rb
CHANGED
data/lib/watir/elements/radio.rb
CHANGED
@@ -5,7 +5,7 @@ module Watir
|
|
5
5
|
#
|
6
6
|
|
7
7
|
def clear
|
8
|
-
raise Exception::Error, 'you can only clear multi-selects' unless
|
8
|
+
raise Exception::Error, 'you can only clear multi-selects' unless multiple_select_list?
|
9
9
|
|
10
10
|
selected_options.each(&:click)
|
11
11
|
end
|
@@ -18,7 +18,7 @@ module Watir
|
|
18
18
|
#
|
19
19
|
|
20
20
|
def include?(str_or_rx)
|
21
|
-
option(text: str_or_rx).exist? || option(label: str_or_rx).exist?
|
21
|
+
option(text: str_or_rx).exist? || option(label: str_or_rx).exist? || option(value: str_or_rx).exist?
|
22
22
|
end
|
23
23
|
|
24
24
|
#
|
@@ -29,14 +29,16 @@ module Watir
|
|
29
29
|
# @return [String] The text of the option selected. If multiple options match, returns the first match.
|
30
30
|
#
|
31
31
|
|
32
|
-
def select(*str_or_rx)
|
33
|
-
|
34
|
-
|
32
|
+
def select(*str_or_rx, text: nil, value: nil, label: nil)
|
33
|
+
key, value = parse_select_args(str_or_rx, text, value, label)
|
34
|
+
|
35
|
+
if value.size > 1 || value.first.is_a?(Array)
|
36
|
+
value.flatten.map { |v| select_all_by key, v }.first
|
35
37
|
else
|
36
|
-
|
37
|
-
select_matching([found])
|
38
|
+
select_matching([find_option(key, value.flatten.first)])
|
38
39
|
end
|
39
40
|
end
|
41
|
+
alias set select
|
40
42
|
|
41
43
|
#
|
42
44
|
# Uses JavaScript to select the option whose text matches the given string.
|
@@ -45,11 +47,13 @@ module Watir
|
|
45
47
|
# @raise [Watir::Exception::NoValueFoundException] if the value does not exist.
|
46
48
|
#
|
47
49
|
|
48
|
-
def select!(*str_or_rx)
|
49
|
-
|
50
|
-
|
50
|
+
def select!(*str_or_rx, text: nil, value: nil, label: nil)
|
51
|
+
key, value = parse_select_args(str_or_rx, text, value, label)
|
52
|
+
|
53
|
+
if value.size > 1 || value.first.is_a?(Array)
|
54
|
+
value.flatten.map { |v| select_by! key, v, :multiple }.first
|
51
55
|
else
|
52
|
-
|
56
|
+
value.flatten.map { |v| select_by! key, v, :single }.first
|
53
57
|
end
|
54
58
|
end
|
55
59
|
|
@@ -61,16 +65,10 @@ module Watir
|
|
61
65
|
# @return [Boolean]
|
62
66
|
#
|
63
67
|
|
64
|
-
def selected?(str_or_rx)
|
65
|
-
|
66
|
-
return true if by_text.find(&:selected?)
|
67
|
-
|
68
|
-
by_label = options(label: str_or_rx)
|
69
|
-
return true if by_label.find(&:selected?)
|
68
|
+
def selected?(*str_or_rx, text: nil, value: nil, label: nil)
|
69
|
+
key, value = parse_select_args(str_or_rx, text, value, label)
|
70
70
|
|
71
|
-
|
72
|
-
|
73
|
-
raise(UnknownObjectException, "Unable to locate option matching #{str_or_rx.inspect}")
|
71
|
+
find_option(key, value.first).selected?
|
74
72
|
end
|
75
73
|
|
76
74
|
#
|
@@ -81,8 +79,7 @@ module Watir
|
|
81
79
|
#
|
82
80
|
|
83
81
|
def value
|
84
|
-
|
85
|
-
option&.value
|
82
|
+
selected_options.first&.value
|
86
83
|
end
|
87
84
|
|
88
85
|
#
|
@@ -92,9 +89,9 @@ module Watir
|
|
92
89
|
# @return [String, nil]
|
93
90
|
#
|
94
91
|
|
92
|
+
# TODO: What is default behavior without #first ?
|
95
93
|
def text
|
96
|
-
|
97
|
-
option&.text
|
94
|
+
selected_options.first&.text
|
98
95
|
end
|
99
96
|
|
100
97
|
# Returns an array of currently selected options.
|
@@ -108,10 +105,29 @@ module Watir
|
|
108
105
|
|
109
106
|
private
|
110
107
|
|
111
|
-
def
|
108
|
+
def multiple_select_list?
|
109
|
+
@multiple_select = @multiple_select.nil? ? multiple? : @multiple_select
|
110
|
+
end
|
111
|
+
|
112
|
+
def parse_select_args(str_or_rx, text, value, label)
|
113
|
+
selectors = {}
|
114
|
+
selectors[:any] = str_or_rx unless str_or_rx.empty?
|
115
|
+
selectors[:text] = Array[text] if text
|
116
|
+
selectors[:value] = Array[value] if value
|
117
|
+
selectors[:label] = Array[label] if label
|
118
|
+
|
119
|
+
raise ArgumentError, "too many arguments used for Select#select: #{selectors}" if selectors.size > 1
|
120
|
+
|
121
|
+
selectors.first
|
122
|
+
end
|
123
|
+
|
124
|
+
def select_by!(key, str_or_rx, number)
|
125
|
+
str_or_rx = type_check(str_or_rx)
|
126
|
+
|
112
127
|
js_rx = process_str_or_rx(str_or_rx)
|
128
|
+
approaches = key == :any ? %w[Text Label Value] : [key.to_s.capitalize]
|
113
129
|
|
114
|
-
|
130
|
+
approaches.each do |approach|
|
115
131
|
element_call { execute_js("selectOptions#{approach}", self, js_rx, number.to_s) }
|
116
132
|
return selected_options.first.text if matching_option?(approach.downcase, str_or_rx)
|
117
133
|
end
|
@@ -147,34 +163,41 @@ module Watir
|
|
147
163
|
false
|
148
164
|
end
|
149
165
|
|
150
|
-
def select_all_by(str_or_rx)
|
151
|
-
raise Error, 'you can only use #select_all on multi-selects' unless
|
166
|
+
def select_all_by(key, str_or_rx)
|
167
|
+
raise Error, 'you can only use #select_all on multi-selects' unless multiple_select_list?
|
152
168
|
|
153
|
-
select_matching(find_options(
|
169
|
+
select_matching(find_options(key, str_or_rx))
|
154
170
|
end
|
155
171
|
|
156
|
-
def
|
157
|
-
|
158
|
-
raise TypeError, msg unless [String, Numeric, Regexp].any? { |k| str_or_rx.is_a?(k) }
|
172
|
+
def find_option(key, str_or_rx)
|
173
|
+
val = type_check(str_or_rx)
|
159
174
|
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
175
|
+
option(key => val).wait_until(&:exists?)
|
176
|
+
rescue Wait::TimeoutError
|
177
|
+
raise_no_value_found(str_or_rx)
|
178
|
+
end
|
179
|
+
|
180
|
+
def find_options(key, str_or_rx)
|
181
|
+
val = type_check(str_or_rx)
|
182
|
+
|
183
|
+
options(key => val).wait_until(&:exists?)
|
167
184
|
rescue Wait::TimeoutError
|
168
185
|
raise_no_value_found(str_or_rx)
|
169
186
|
end
|
170
187
|
|
188
|
+
def type_check(str_or_rx)
|
189
|
+
str_or_rx = str_or_rx.to_s if str_or_rx.is_a?(Numeric)
|
190
|
+
return str_or_rx if [String, Regexp].any? { |k| str_or_rx.is_a?(k) }
|
191
|
+
|
192
|
+
raise TypeError, "expected String, Numeric or Regexp, got #{str_or_rx.inspect}:#{str_or_rx.class}"
|
193
|
+
end
|
194
|
+
|
171
195
|
# TODO: Consider locating the Select List before throwing the exception
|
172
196
|
def raise_no_value_found(str_or_rx)
|
173
197
|
raise NoValueFoundException, "#{str_or_rx.inspect} not found in #{inspect}"
|
174
198
|
end
|
175
199
|
|
176
200
|
def select_matching(elements)
|
177
|
-
elements = [elements.first] unless multiple?
|
178
201
|
elements.each { |e| e.click unless e.selected? }
|
179
202
|
elements.first.exists? ? elements.first.text : ''
|
180
203
|
end
|