watir 7.0.0.beta1 → 7.0.0.beta2
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 +16 -0
- data/lib/watir/browser.rb +18 -4
- data/lib/watir/capabilities.rb +1 -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/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/server.rb +1 -1
- data/spec/spec_helper.rb +0 -10
- data/spec/unit/capabilities_spec.rb +1 -1
- 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/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
- metadata +5 -6
- 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: 58e502e12250523b603418f4d352663d893762126b5cdb48e046e58a8a19bc20
|
4
|
+
data.tar.gz: cd3405850e28a040968c7df99f93d87a2593ff7b2c34da4b8f0789cbe023df42
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0557ff99666998a7104b51ae07439d7245e645e2fe543d8a50ed2c191f3c8d5a04423e52c22b8065e3a5f7793ee7ce9101d64f54c0ca4349eec23d1b5057c3e7
|
7
|
+
data.tar.gz: 1d36608975ae96d51ce119cd55f96a2d28eb0c9de2cb1194e33d9fe1429c09c5fdd86022c07bf1350617e60c6f667ce0bd818428f545e37f8eaebf65361fb883
|
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,19 @@
|
|
1
|
+
### 7.0.0.beta2 (2021-03-28)
|
2
|
+
|
3
|
+
* Replace Watir Logger implementation with Selenium Logger subclass
|
4
|
+
* Change Watir Guards to use Selenium's new Guards. Tests run as pending when guarded.
|
5
|
+
* Implement `#set` as standard interface for each Input Element (#405)
|
6
|
+
* Implement `Element#set` to take correct `#set` behavior based on evaluated element (#664)
|
7
|
+
* Optimize Performance for Select Lists (#846)
|
8
|
+
* Allow user to set values on Select List exclusively by `:label`, `:text`, or `:value` (#846)
|
9
|
+
* Allow user to check if option selected in Select List by `:label`, `:text`, or `:value` (#929)
|
10
|
+
* Implement `Window#restore!` to return to original Window and close all others (#923)
|
11
|
+
* Minor performance improvement for iterating over windows (#923)
|
12
|
+
* Implement `Browser#closed?`; same as `Browser#exists?` without the Windows checks (#923)
|
13
|
+
* Update methods that use Selenium's Actions class to scroll element into view before acting (#847)
|
14
|
+
* Fix bug for `:text` locator with `Regexp` value based on whitespace (#924)
|
15
|
+
* Remove executing after hooks when changing frames (#888)
|
16
|
+
|
1
17
|
### 7.0.0.beta1 (2021-03-18)
|
2
18
|
|
3
19
|
* Requires Selenium 4
|
data/lib/watir/browser.rb
CHANGED
@@ -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'
|
@@ -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
|