watir 7.0.0.beta1 → 7.0.0.beta5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|