watir 7.0.0.beta1 → 7.0.0.beta2
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 +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
data/lib/watir/has_window.rb
CHANGED
data/lib/watir/locators.rb
CHANGED
@@ -14,6 +14,10 @@ require 'watir/locators/button/matcher'
|
|
14
14
|
require 'watir/locators/cell/selector_builder'
|
15
15
|
require 'watir/locators/cell/selector_builder/xpath'
|
16
16
|
|
17
|
+
require 'watir/locators/option/matcher'
|
18
|
+
require 'watir/locators/option/selector_builder'
|
19
|
+
require 'watir/locators/option/selector_builder/xpath'
|
20
|
+
|
17
21
|
require 'watir/locators/row/selector_builder'
|
18
22
|
require 'watir/locators/row/selector_builder/xpath'
|
19
23
|
|
@@ -88,9 +88,6 @@ module Watir
|
|
88
88
|
|
89
89
|
def normalize_locator(how, what)
|
90
90
|
case how
|
91
|
-
when 'text'
|
92
|
-
Watir.logger.deprecate "String 'text' as a locator", 'Symbol :text', ids: [:text_string]
|
93
|
-
[:text, what]
|
94
91
|
when :tag_name
|
95
92
|
what = what.to_s if what.is_a?(::Symbol)
|
96
93
|
[how, what]
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Watir
|
2
|
+
module Locators
|
3
|
+
class Option
|
4
|
+
class Matcher < Element::Matcher
|
5
|
+
def fetch_value(element, how)
|
6
|
+
case how
|
7
|
+
when :any
|
8
|
+
[element.attribute(:value),
|
9
|
+
execute_js(:getTextContent, element).gsub(/\s+/, ' ').strip,
|
10
|
+
element.attribute(:label)]
|
11
|
+
else
|
12
|
+
super
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def matches_values?(found, expected)
|
17
|
+
return super unless found.is_a?(Array)
|
18
|
+
|
19
|
+
found.find { |possible| matches_values?(possible, expected) }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Watir
|
2
|
+
module Locators
|
3
|
+
class Option
|
4
|
+
class SelectorBuilder
|
5
|
+
class XPath < Element::SelectorBuilder::XPath
|
6
|
+
private
|
7
|
+
|
8
|
+
def attribute_string
|
9
|
+
result = if @selector.key?(:any)
|
10
|
+
to_match = @selector.delete :any
|
11
|
+
value = process_attribute(:value, to_match)
|
12
|
+
text = process_attribute(:text, to_match)
|
13
|
+
label = process_attribute(:label, to_match)
|
14
|
+
"[#{value} or #{text} or #{label}]"
|
15
|
+
else
|
16
|
+
''
|
17
|
+
end
|
18
|
+
|
19
|
+
attributes = @selector.keys.map { |key|
|
20
|
+
process_attribute(key, @selector.delete(key))
|
21
|
+
}.flatten.compact
|
22
|
+
attribute_values = attributes.empty? ? '' : "[#{attributes.join(' and ')}]"
|
23
|
+
"#{result}#{attribute_values}"
|
24
|
+
end
|
25
|
+
|
26
|
+
def add_to_matching(key, regexp, results = nil)
|
27
|
+
return unless results.nil? || requires_matching?(results, regexp)
|
28
|
+
|
29
|
+
return super unless %i[value text label].include? key
|
30
|
+
|
31
|
+
@built[:any] = regexp
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/watir/logger.rb
CHANGED
@@ -16,84 +16,13 @@ module Watir
|
|
16
16
|
# Watir.logger.info('This is info message')
|
17
17
|
# Watir.logger.warn('This is warning message')
|
18
18
|
#
|
19
|
-
class Logger
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
def_delegators :@logger, :debug, :debug?,
|
24
|
-
:info, :info?,
|
25
|
-
:warn?,
|
26
|
-
:error, :error?,
|
27
|
-
:fatal, :fatal?,
|
28
|
-
:level, :level=
|
29
|
-
|
30
|
-
def initialize(progname = 'Watir')
|
31
|
-
@logger = create_logger($stdout)
|
32
|
-
@logger.progname = progname
|
33
|
-
@ignored = []
|
34
|
-
end
|
35
|
-
|
36
|
-
def ignore(ids)
|
37
|
-
@ignored.concat Array(ids).map(&:to_s)
|
38
|
-
end
|
39
|
-
|
40
|
-
def output=(io)
|
41
|
-
@logger.reopen(io)
|
42
|
-
end
|
43
|
-
|
44
|
-
#
|
45
|
-
# Only log a warn message if it is not set to be ignored.
|
46
|
-
#
|
47
|
-
def warn(message, ids: [], &block)
|
48
|
-
msg = ids.empty? ? '' : "[#{ids.map!(&:to_s).map(&:inspect).join(', ')}] "
|
49
|
-
msg += message
|
50
|
-
@logger.warn(msg, &block) unless (@ignored & ids).any?
|
51
|
-
end
|
52
|
-
|
53
|
-
#
|
54
|
-
# Returns IO object used by logger internally.
|
55
|
-
#
|
56
|
-
# Normally, we would have never needed it, but we want to
|
57
|
-
# use it as IO object for all child processes to ensure their
|
58
|
-
# output is redirected there.
|
59
|
-
#
|
60
|
-
# It is only used in debug level, in other cases output is suppressed.
|
61
|
-
#
|
62
|
-
# @api private
|
63
|
-
#
|
64
|
-
def io
|
65
|
-
@logger.instance_variable_get(:@logdev).instance_variable_get(:@dev)
|
66
|
-
end
|
67
|
-
|
68
|
-
#
|
69
|
-
# Marks code as deprecated with replacement.
|
70
|
-
#
|
71
|
-
# @param [String] old
|
72
|
-
# @param [String] new
|
73
|
-
#
|
74
|
-
def deprecate(old, new, reference: '', ids: [])
|
75
|
-
return if @ignored.include?('deprecations') || (@ignored & ids.map!(&:to_s)).any?
|
76
|
-
|
77
|
-
msg = ids.empty? ? '' : "[#{ids.map(&:inspect).join(', ')}] "
|
78
|
-
ref_msg = reference.empty? ? '.' : "; see explanation for this deprecation: #{reference}."
|
79
|
-
warn "[DEPRECATION] #{msg}#{old} is deprecated. Use #{new} instead#{ref_msg}"
|
19
|
+
class Logger < Selenium::WebDriver::Logger
|
20
|
+
def initialize
|
21
|
+
super('Watir')
|
80
22
|
end
|
81
23
|
|
82
24
|
def selenium=(val)
|
83
25
|
Selenium::WebDriver.logger.level = val
|
84
26
|
end
|
85
|
-
|
86
|
-
private
|
87
|
-
|
88
|
-
def create_logger(output)
|
89
|
-
logger = ::Logger.new(output)
|
90
|
-
logger.progname = 'Watir'
|
91
|
-
logger.level = ($DEBUG ? DEBUG : WARN)
|
92
|
-
logger.formatter = proc do |severity, time, progname, msg|
|
93
|
-
"#{time.strftime('%F %T')} #{severity} #{progname} #{msg}\n"
|
94
|
-
end
|
95
|
-
|
96
|
-
logger
|
97
|
-
end
|
98
27
|
end
|
99
28
|
end
|
data/lib/watir/radio_set.rb
CHANGED
data/lib/watir/screenshot.rb
CHANGED
@@ -1,14 +1,8 @@
|
|
1
1
|
module Watir
|
2
2
|
class Screenshot
|
3
3
|
def initialize(browser)
|
4
|
-
|
5
|
-
|
6
|
-
Watir.logger.deprecate msg, ids: [:screenshot_driver]
|
7
|
-
@driver = browser
|
8
|
-
else
|
9
|
-
@browser = browser
|
10
|
-
@driver = browser.wd
|
11
|
-
end
|
4
|
+
@browser = browser
|
5
|
+
@driver = browser.wd
|
12
6
|
end
|
13
7
|
|
14
8
|
#
|
data/lib/watir/user_editable.rb
CHANGED
@@ -15,16 +15,23 @@ module Watir
|
|
15
15
|
alias value= set
|
16
16
|
|
17
17
|
#
|
18
|
-
#
|
19
|
-
# Selenium is used to enter the first and last characters
|
18
|
+
# Returns true if element is user_editable because it has a content_editable attribute set
|
20
19
|
#
|
21
|
-
# @
|
20
|
+
# @return [Boolean]
|
22
21
|
#
|
23
22
|
|
24
23
|
def content_editable
|
25
24
|
defined?(@content_editable) && content_editable?
|
26
25
|
end
|
27
26
|
|
27
|
+
#
|
28
|
+
# Uses JavaScript to enter most of the given value.
|
29
|
+
# Selenium is used to enter the first and last characters
|
30
|
+
# This might provide a performance improvement when entering a lot of text on a local machine
|
31
|
+
#
|
32
|
+
# @param [String, Symbol] args
|
33
|
+
#
|
34
|
+
|
28
35
|
def set!(*args)
|
29
36
|
msg = '#set! does not support special keys, use #set instead'
|
30
37
|
raise ArgumentError, msg if args.any? { |v| v.is_a?(::Symbol) }
|
data/lib/watir/version.rb
CHANGED
data/lib/watir/window.rb
CHANGED
@@ -179,10 +179,21 @@ module Watir
|
|
179
179
|
# end
|
180
180
|
#
|
181
181
|
|
182
|
-
def use
|
183
|
-
@browser.original_window ||= current_window
|
182
|
+
def use
|
184
183
|
wait_for_exists
|
185
|
-
|
184
|
+
cache_current = current_window
|
185
|
+
@browser.original_window ||= cache_current
|
186
|
+
restore_to = unless cache_current == handle
|
187
|
+
@driver.switch_to.window(handle)
|
188
|
+
cache_current
|
189
|
+
end
|
190
|
+
if block_given?
|
191
|
+
begin
|
192
|
+
yield
|
193
|
+
ensure
|
194
|
+
@driver.switch_to.window(restore_to) if restore_to
|
195
|
+
end
|
196
|
+
end
|
186
197
|
self
|
187
198
|
end
|
188
199
|
|
@@ -205,7 +216,7 @@ module Watir
|
|
205
216
|
end
|
206
217
|
|
207
218
|
def assert_exists
|
208
|
-
return if @driver.window_handles.include?(handle)
|
219
|
+
return if !handle.nil? && @driver.window_handles.include?(handle)
|
209
220
|
|
210
221
|
raise(NoMatchingWindowFoundException, selector_string)
|
211
222
|
end
|
@@ -39,6 +39,15 @@ module Watir
|
|
39
39
|
end
|
40
40
|
alias eql? ==
|
41
41
|
|
42
|
+
def restore!
|
43
|
+
return if @browser.closed?
|
44
|
+
|
45
|
+
window_list.reject { |win| win.handle == @browser.original_window.handle }.each(&:close)
|
46
|
+
@browser.original_window.use
|
47
|
+
rescue StandardError
|
48
|
+
@browser.close
|
49
|
+
end
|
50
|
+
|
42
51
|
def reset!
|
43
52
|
@window_list = nil
|
44
53
|
end
|
data/lib/watirspec.rb
CHANGED
@@ -53,7 +53,9 @@ module WatirSpec
|
|
53
53
|
@implementation = imp
|
54
54
|
end
|
55
55
|
|
56
|
-
def new_browser
|
56
|
+
def new_browser(pause = 1)
|
57
|
+
sleep pause
|
58
|
+
|
57
59
|
klass = WatirSpec.implementation.browser_class
|
58
60
|
args = Array(WatirSpec.implementation.browser_args).map { |e| e.is_a?(Hash) ? e.dup : e }
|
59
61
|
|
@@ -80,7 +82,7 @@ module WatirSpec
|
|
80
82
|
info << @implementation.driver_info
|
81
83
|
|
82
84
|
Watir.logger.warn "running watirspec against #{info.join ' '} using:\n#{WatirSpec.implementation.inspect_args}",
|
83
|
-
|
85
|
+
id: [:browser_info]
|
84
86
|
rescue StandardError
|
85
87
|
# ignored
|
86
88
|
end
|
data/lib/watirspec/guards.rb
CHANGED
data/lib/watirspec/server.rb
CHANGED
@@ -56,7 +56,7 @@ module WatirSpec
|
|
56
56
|
|
57
57
|
client.write(response(status, headers, body))
|
58
58
|
rescue Errno::ECONNRESET
|
59
|
-
Watir.logger.warn 'Client reset connection, skipping.',
|
59
|
+
Watir.logger.warn 'Client reset connection, skipping.', id: [:reset_connection]
|
60
60
|
ensure
|
61
61
|
client.close
|
62
62
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -20,13 +20,3 @@ end
|
|
20
20
|
require 'watir'
|
21
21
|
require 'locator_spec_helper'
|
22
22
|
require 'rspec'
|
23
|
-
|
24
|
-
if ENV['AUTOMATIC_RETRY']
|
25
|
-
require 'rspec/retry'
|
26
|
-
RSpec.configure do |config|
|
27
|
-
config.verbose_retry = true
|
28
|
-
config.display_try_failure_messages = true
|
29
|
-
config.default_retry_count = 3
|
30
|
-
config.exceptions_to_retry = [IOError, Net::ReadTimeout]
|
31
|
-
end
|
32
|
-
end
|
@@ -332,6 +332,17 @@ describe Watir::Locators::Element::Matcher do
|
|
332
332
|
end
|
333
333
|
|
334
334
|
context 'when matching Regular Expressions' do
|
335
|
+
it 'with white space' do
|
336
|
+
allow(browser).to receive(:execute_script).and_return("\n match this \n", 'no', 'match this')
|
337
|
+
|
338
|
+
elements = [wd_element,
|
339
|
+
wd_element,
|
340
|
+
wd_element]
|
341
|
+
@values_to_match = {text: /^match this$/}
|
342
|
+
|
343
|
+
expect(matcher.match(elements, values_to_match, @filter)).to eq [elements[0], elements[2]]
|
344
|
+
end
|
345
|
+
|
335
346
|
it 'with tag_name' do
|
336
347
|
elements = [wd_element(tag_name: 'div'),
|
337
348
|
wd_element(tag_name: 'span'),
|
@@ -85,14 +85,12 @@ describe 'Browser::AfterHooks' do
|
|
85
85
|
expect(@yield).to be true
|
86
86
|
end
|
87
87
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
expect(@yield).to be true
|
95
|
-
end
|
88
|
+
it 'runs after_hooks after Element#submit' do
|
89
|
+
browser.goto(WatirSpec.url_for('forms_with_input_elements.html'))
|
90
|
+
@page_after_hook = proc { @yield = browser.div(id: 'messages').text == 'submit' }
|
91
|
+
browser.after_hooks.add @page_after_hook
|
92
|
+
browser.form(id: 'new_user').submit
|
93
|
+
expect(@yield).to be true
|
96
94
|
end
|
97
95
|
|
98
96
|
it 'runs after_hooks after Element#double_click' do
|
@@ -115,28 +113,6 @@ describe 'Browser::AfterHooks' do
|
|
115
113
|
expect(@yield).to be true
|
116
114
|
end
|
117
115
|
|
118
|
-
it 'runs after_hooks after FramedDriver#switch!' do
|
119
|
-
browser.goto(WatirSpec.url_for('iframes.html'))
|
120
|
-
@page_after_hook = proc { @yield = browser.title == 'Iframes' }
|
121
|
-
browser.after_hooks.add @page_after_hook
|
122
|
-
|
123
|
-
browser.iframe.element(css: '#senderElement').exists?
|
124
|
-
|
125
|
-
expect(@yield).to be true
|
126
|
-
end
|
127
|
-
|
128
|
-
it 'runs after_hooks after Browser#ensure_context if not @default_context' do
|
129
|
-
browser.goto(WatirSpec.url_for('iframes.html'))
|
130
|
-
browser.iframe.element(css: '#senderElement').locate
|
131
|
-
|
132
|
-
@page_after_hook = proc { @yield = browser.title == 'Iframes' }
|
133
|
-
browser.after_hooks.add @page_after_hook
|
134
|
-
|
135
|
-
browser.locate
|
136
|
-
|
137
|
-
expect(@yield).to be true
|
138
|
-
end
|
139
|
-
|
140
116
|
it 'runs after_hooks after Alert#ok' do
|
141
117
|
browser.goto(WatirSpec.url_for('alerts.html'))
|
142
118
|
@page_after_hook = proc { @yield = browser.title == 'Alerts' }
|
@@ -187,21 +163,22 @@ describe 'Browser::AfterHooks' do
|
|
187
163
|
browser.alert.ok
|
188
164
|
end
|
189
165
|
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
166
|
+
it 'does not raise error when running error checks on closed window',
|
167
|
+
except: {browser: :safari,
|
168
|
+
reason: 'Clicking an Element that Closes a Window is returning NoMatchingWindowFoundException'},
|
169
|
+
exclude: {browser: :firefox,
|
170
|
+
platform: :windows,
|
171
|
+
reason: 'https://github.com/mozilla/geckodriver/issues/1847'} do
|
172
|
+
url = WatirSpec.url_for('window_switching.html')
|
173
|
+
@page_after_hook = proc { browser.url }
|
174
|
+
browser.after_hooks.add @page_after_hook
|
175
|
+
browser.goto url
|
176
|
+
browser.a(id: 'open').click
|
177
|
+
|
178
|
+
window = browser.window(title: 'closeable window')
|
179
|
+
window.use
|
180
|
+
expect { browser.a(id: 'close').click }.to_not raise_error
|
181
|
+
browser.original_window.use
|
205
182
|
end
|
206
183
|
end
|
207
184
|
|