watir-webdriver 0.6.11 → 0.7.0
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/.travis.yml +14 -12
- data/CHANGES.md +17 -0
- data/LICENSE +1 -1
- data/README.md +8 -1
- data/Rakefile +7 -2
- data/lib/watir-webdriver/alert.rb +5 -1
- data/lib/watir-webdriver/attribute_helper.rb +4 -8
- data/lib/watir-webdriver/browser.rb +41 -21
- data/lib/watir-webdriver/element_collection.rb +1 -2
- data/lib/watir-webdriver/elements/button.rb +3 -5
- data/lib/watir-webdriver/elements/checkbox.rb +2 -11
- data/lib/watir-webdriver/elements/element.rb +93 -86
- data/lib/watir-webdriver/elements/file_field.rb +1 -2
- data/lib/watir-webdriver/elements/form.rb +2 -1
- data/lib/watir-webdriver/elements/generated.rb +24 -11
- data/lib/watir-webdriver/elements/iframe.rb +25 -17
- data/lib/watir-webdriver/elements/option.rb +6 -14
- data/lib/watir-webdriver/elements/radio.rb +2 -5
- data/lib/watir-webdriver/elements/select.rb +15 -7
- data/lib/watir-webdriver/exception.rb +0 -2
- data/lib/watir-webdriver/extensions/alerts.rb +0 -14
- data/lib/watir-webdriver/has_window.rb +2 -4
- data/lib/watir-webdriver/html/spec_extractor.rb +3 -2
- data/lib/watir-webdriver/html/visitor.rb +2 -2
- data/lib/watir-webdriver/locators/element_locator.rb +22 -21
- data/lib/watir-webdriver/locators/text_field_locator.rb +11 -3
- data/lib/watir-webdriver/user_editable.rb +5 -10
- data/lib/watir-webdriver/version.rb +1 -1
- data/lib/watir-webdriver/wait.rb +26 -26
- data/lib/watir-webdriver/window.rb +30 -25
- data/spec/always_locate_spec.rb +42 -0
- data/spec/browser_spec.rb +1 -1
- data/spec/element_locator_spec.rb +13 -1
- data/spec/element_spec.rb +43 -8
- data/spec/input_spec.rb +0 -31
- data/spec/spec_helper.rb +0 -1
- data/support/doctest_helper.rb +72 -0
- data/support/travis.sh +4 -0
- data/watir-webdriver.gemspec +2 -1
- metadata +50 -35
- data/spec/html/inner_outer.html +0 -5
@@ -27,7 +27,6 @@ module Watir
|
|
27
27
|
def locate
|
28
28
|
e = by_id and return e # short-circuit if :id is given
|
29
29
|
|
30
|
-
|
31
30
|
if @selector.size == 1
|
32
31
|
element = find_first_by_one
|
33
32
|
else
|
@@ -39,7 +38,7 @@ module Watir
|
|
39
38
|
# It is also used to alter behavior of methods locating more than one type of element
|
40
39
|
# (e.g. text_field locates both input and textarea)
|
41
40
|
validate_element(element) if element
|
42
|
-
rescue Selenium::WebDriver::Error::NoSuchElementError, Selenium::WebDriver::Error::
|
41
|
+
rescue Selenium::WebDriver::Error::NoSuchElementError, Selenium::WebDriver::Error::StaleElementReferenceError
|
43
42
|
nil
|
44
43
|
end
|
45
44
|
|
@@ -253,8 +252,6 @@ module Watir
|
|
253
252
|
return if tag_name && !tag_name_matches?(element.tag_name.downcase, tag_name)
|
254
253
|
|
255
254
|
element
|
256
|
-
rescue Selenium::WebDriver::Error::NoSuchElementError
|
257
|
-
nil
|
258
255
|
end
|
259
256
|
|
260
257
|
def all_elements
|
@@ -298,26 +295,30 @@ module Watir
|
|
298
295
|
def build_css(selectors)
|
299
296
|
return unless use_css?(selectors)
|
300
297
|
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
298
|
+
if selectors.empty?
|
299
|
+
css = '*'
|
300
|
+
else
|
301
|
+
css = ''
|
302
|
+
css << (selectors.delete(:tag_name) || '')
|
303
|
+
|
304
|
+
klass = selectors.delete(:class)
|
305
|
+
if klass
|
306
|
+
if klass.include? ' '
|
307
|
+
css << %([class="#{css_escape klass}"])
|
308
|
+
else
|
309
|
+
css << ".#{klass}"
|
310
|
+
end
|
310
311
|
end
|
311
|
-
end
|
312
312
|
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
313
|
+
href = selectors.delete(:href)
|
314
|
+
if href
|
315
|
+
css << %([href~="#{css_escape href}"])
|
316
|
+
end
|
317
317
|
|
318
|
-
|
319
|
-
|
320
|
-
|
318
|
+
selectors.each do |key, value|
|
319
|
+
key = key.to_s.gsub("_", "-")
|
320
|
+
css << %([#{key}="#{css_escape value}"]) # TODO: proper escaping
|
321
|
+
end
|
321
322
|
end
|
322
323
|
|
323
324
|
[:css, css]
|
@@ -65,15 +65,23 @@ module Watir
|
|
65
65
|
end
|
66
66
|
|
67
67
|
def by_id
|
68
|
-
|
69
|
-
|
68
|
+
element = super
|
69
|
+
|
70
|
+
if element && !NON_TEXT_TYPES.include?(element.attribute(:type))
|
71
|
+
check_deprecation(element)
|
72
|
+
element
|
73
|
+
end
|
70
74
|
end
|
71
75
|
|
72
76
|
def validate_element(element)
|
77
|
+
check_deprecation(element)
|
78
|
+
super
|
79
|
+
end
|
80
|
+
|
81
|
+
def check_deprecation(element)
|
73
82
|
if element.tag_name.downcase == 'textarea'
|
74
83
|
warn "Locating textareas with '#text_field' is deprecated. Please, use '#textarea' method instead."
|
75
84
|
end
|
76
|
-
super
|
77
85
|
end
|
78
86
|
|
79
87
|
end # TextFieldLocator
|
@@ -8,11 +8,8 @@ module Watir
|
|
8
8
|
#
|
9
9
|
|
10
10
|
def set(*args)
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
@element.clear
|
15
|
-
@element.send_keys(*args)
|
11
|
+
clear
|
12
|
+
element_call { @element.send_keys(*args) }
|
16
13
|
end
|
17
14
|
alias_method :value=, :set
|
18
15
|
|
@@ -23,10 +20,7 @@ module Watir
|
|
23
20
|
#
|
24
21
|
|
25
22
|
def append(*args)
|
26
|
-
|
27
|
-
assert_writable
|
28
|
-
|
29
|
-
@element.send_keys(*args)
|
23
|
+
send_keys(*args)
|
30
24
|
end
|
31
25
|
alias_method :<<, :append
|
32
26
|
|
@@ -36,7 +30,8 @@ module Watir
|
|
36
30
|
|
37
31
|
def clear
|
38
32
|
assert_exists
|
39
|
-
|
33
|
+
assert_writable
|
34
|
+
element_call { @element.clear }
|
40
35
|
end
|
41
36
|
|
42
37
|
end # UserEditable
|
data/lib/watir-webdriver/wait.rb
CHANGED
@@ -29,22 +29,15 @@ module Watir
|
|
29
29
|
# Waits until the block evaluates to true or times out.
|
30
30
|
#
|
31
31
|
# @example
|
32
|
-
# Watir::Wait.until { browser.
|
32
|
+
# Watir::Wait.until { browser.text_field(:name => "new_user_first_name").visible? }
|
33
33
|
#
|
34
34
|
# @param [Fixnum] timeout How long to wait in seconds
|
35
35
|
# @param [String] message Message to raise if timeout is exceeded
|
36
36
|
# @raise [TimeoutError] if timeout is exceeded
|
37
37
|
#
|
38
38
|
|
39
|
-
def until(timeout = nil, message = nil
|
40
|
-
timeout
|
41
|
-
|
42
|
-
timer.wait(timeout) do
|
43
|
-
result = yield(self)
|
44
|
-
return result if result
|
45
|
-
sleep INTERVAL
|
46
|
-
end
|
47
|
-
|
39
|
+
def until(timeout = nil, message = nil)
|
40
|
+
run_with_timer(timeout) { return true if yield(self) }
|
48
41
|
raise TimeoutError, message_for(timeout, message)
|
49
42
|
end
|
50
43
|
|
@@ -52,21 +45,15 @@ module Watir
|
|
52
45
|
# Wait while the block evaluates to true or times out.
|
53
46
|
#
|
54
47
|
# @example
|
55
|
-
# Watir::Wait.while { browser.
|
48
|
+
# Watir::Wait.while { browser.text_field(:name => "abrakadbra").present? }
|
56
49
|
#
|
57
50
|
# @param [Fixnum] timeout How long to wait in seconds
|
58
51
|
# @param [String] message Message to raise if timeout is exceeded
|
59
52
|
# @raise [TimeoutError] if timeout is exceeded
|
60
53
|
#
|
61
54
|
|
62
|
-
def while(timeout = nil, message = nil
|
63
|
-
timeout
|
64
|
-
|
65
|
-
timer.wait(timeout) do
|
66
|
-
return unless yield(self)
|
67
|
-
sleep INTERVAL
|
68
|
-
end
|
69
|
-
|
55
|
+
def while(timeout = nil, message = nil)
|
56
|
+
run_with_timer(timeout) { return unless yield(self) }
|
70
57
|
raise TimeoutError, message_for(timeout, message)
|
71
58
|
end
|
72
59
|
|
@@ -79,6 +66,19 @@ module Watir
|
|
79
66
|
err
|
80
67
|
end
|
81
68
|
|
69
|
+
def run_with_timer(timeout = nil, &block)
|
70
|
+
timeout ||= Watir.default_timeout
|
71
|
+
|
72
|
+
if timeout == 0
|
73
|
+
block.call
|
74
|
+
else
|
75
|
+
timer.wait(timeout) do
|
76
|
+
block.call
|
77
|
+
sleep INTERVAL
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
82
|
end # self
|
83
83
|
end # Wait
|
84
84
|
|
@@ -134,9 +134,9 @@ module Watir
|
|
134
134
|
# Waits until the element is present.
|
135
135
|
#
|
136
136
|
# @example
|
137
|
-
# browser.
|
138
|
-
# browser.
|
139
|
-
# browser.
|
137
|
+
# browser.text_field(:name => "new_user_first_name").when_present.click
|
138
|
+
# browser.text_field(:name => "new_user_first_name").when_present { |field| field.set "Watir" }
|
139
|
+
# browser.text_field(:name => "new_user_first_name").when_present(60).text
|
140
140
|
#
|
141
141
|
# @param [Fixnum] timeout seconds to wait before timing out
|
142
142
|
#
|
@@ -160,7 +160,7 @@ module Watir
|
|
160
160
|
# Waits until the element is present.
|
161
161
|
#
|
162
162
|
# @example
|
163
|
-
# browser.
|
163
|
+
# browser.text_field(:name => "new_user_first_name").wait_until_present
|
164
164
|
#
|
165
165
|
# @param [Fixnum] timeout seconds to wait before timing out
|
166
166
|
#
|
@@ -178,9 +178,9 @@ module Watir
|
|
178
178
|
# Waits while the element is present.
|
179
179
|
#
|
180
180
|
# @example
|
181
|
-
# browser.
|
181
|
+
# browser.text_field(:name => "abrakadbra").wait_while_present
|
182
182
|
#
|
183
|
-
# @param [
|
183
|
+
# @param [Fixnum] timeout seconds to wait before timing out
|
184
184
|
#
|
185
185
|
# @see Watir::Wait
|
186
186
|
# @see Watir::Element#present?
|
@@ -190,7 +190,7 @@ module Watir
|
|
190
190
|
timeout ||= Watir.default_timeout
|
191
191
|
message = "waiting for #{selector_string} to disappear"
|
192
192
|
Watir::Wait.while(timeout, message) { present? }
|
193
|
-
rescue Selenium::WebDriver::Error::
|
193
|
+
rescue Selenium::WebDriver::Error::StaleElementReferenceError
|
194
194
|
# it's not present
|
195
195
|
end
|
196
196
|
|
@@ -3,11 +3,11 @@ module Watir
|
|
3
3
|
include EventuallyPresent
|
4
4
|
|
5
5
|
def initialize(driver, selector)
|
6
|
-
@driver
|
6
|
+
@driver = driver
|
7
7
|
@selector = selector
|
8
8
|
|
9
9
|
if selector.empty?
|
10
|
-
@handle =
|
10
|
+
@handle = current_window
|
11
11
|
elsif selector.has_key? :handle
|
12
12
|
@handle = selector.delete :handle
|
13
13
|
else
|
@@ -103,29 +103,21 @@ module Watir
|
|
103
103
|
#
|
104
104
|
|
105
105
|
def exists?
|
106
|
-
|
106
|
+
assert_exists
|
107
107
|
true
|
108
108
|
rescue Exception::NoMatchingWindowFoundException
|
109
109
|
false
|
110
110
|
end
|
111
111
|
|
112
|
-
|
113
|
-
|
114
|
-
#
|
115
|
-
# @return [Boolean]
|
116
|
-
#
|
117
|
-
|
118
|
-
def present?
|
119
|
-
@handle = nil # relocate
|
120
|
-
|
121
|
-
exists?
|
122
|
-
end
|
112
|
+
alias_method :present?, :exists?
|
113
|
+
alias_method :exist?, :exists?
|
123
114
|
|
124
115
|
#
|
125
116
|
# Returns true if two windows are equal.
|
126
117
|
#
|
127
118
|
# @example
|
128
|
-
# browser.window(:index =>
|
119
|
+
# browser.window(:index => 0) == browser.window(:index => 1)
|
120
|
+
# #=> false
|
129
121
|
#
|
130
122
|
# @param [Window] other
|
131
123
|
#
|
@@ -150,11 +142,11 @@ module Watir
|
|
150
142
|
#
|
151
143
|
|
152
144
|
def current?
|
153
|
-
|
145
|
+
current_window == handle
|
154
146
|
end
|
155
147
|
|
156
148
|
#
|
157
|
-
#
|
149
|
+
# Closes window.
|
158
150
|
#
|
159
151
|
|
160
152
|
def close
|
@@ -191,12 +183,13 @@ module Watir
|
|
191
183
|
# Switches to given window and executes block, then switches back.
|
192
184
|
#
|
193
185
|
# @example
|
194
|
-
# browser.window(:title => "
|
195
|
-
# browser.
|
186
|
+
# browser.window(:title => "closeable window").use do
|
187
|
+
# browser.a(:id => "close").click
|
196
188
|
# end
|
197
189
|
#
|
198
190
|
|
199
191
|
def use(&blk)
|
192
|
+
assert_exists
|
200
193
|
@driver.switch_to.window(handle, &blk)
|
201
194
|
self
|
202
195
|
end
|
@@ -209,18 +202,30 @@ module Watir
|
|
209
202
|
|
210
203
|
private
|
211
204
|
|
205
|
+
# Referenced in EventuallyPresent
|
212
206
|
def selector_string
|
213
207
|
@selector.inspect
|
214
208
|
end
|
215
209
|
|
216
210
|
def locate
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
211
|
+
if @selector.empty?
|
212
|
+
nil
|
213
|
+
elsif @selector.has_key?(:index)
|
214
|
+
@driver.window_handles[Integer(@selector[:index])]
|
215
|
+
else
|
216
|
+
@driver.window_handles.find { |wh| matches?(wh) }
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
def assert_exists
|
221
|
+
raise(Exception::NoMatchingWindowFoundException, @selector.inspect) unless @driver.window_handles.include?(handle)
|
222
|
+
end
|
222
223
|
|
223
|
-
|
224
|
+
# return a handle to the currently active window if it is still open; otherwise nil
|
225
|
+
def current_window
|
226
|
+
@driver.window_handle
|
227
|
+
rescue Selenium::WebDriver::Error::NoSuchWindowError
|
228
|
+
nil
|
224
229
|
end
|
225
230
|
|
226
231
|
def matches?(handle)
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require File.expand_path('watirspec/spec_helper', File.dirname(__FILE__))
|
2
|
+
|
3
|
+
describe 'Watir' do
|
4
|
+
describe '#always_locate?' do
|
5
|
+
|
6
|
+
before do
|
7
|
+
browser.goto WatirSpec.url_for('removed_element.html', :needs_server => true)
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'determines whether #exist? returns false for stale element' do
|
11
|
+
element = browser.div(:id => "text")
|
12
|
+
expect(element.exists?).to be true
|
13
|
+
|
14
|
+
browser.refresh
|
15
|
+
|
16
|
+
expect(element.exists?).to be Watir.always_locate?
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'allows using cached elements regardless of setting, when element is not stale' do
|
20
|
+
element = browser.div(:id => "text")
|
21
|
+
expect(element.exists?).to be true
|
22
|
+
|
23
|
+
# exception raised if element is re-looked up
|
24
|
+
allow(browser.driver).to receive(:find_element).with(:id, 'text') { raise }
|
25
|
+
|
26
|
+
expect { element.exists? }.to_not raise_error
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'determines whether an exception is raised when taking an action on a stale element' do
|
30
|
+
element = browser.div(:id => "text")
|
31
|
+
expect(element.exists?).to be true
|
32
|
+
|
33
|
+
browser.refresh
|
34
|
+
|
35
|
+
if Watir.always_locate?
|
36
|
+
expect { element.text }.to_not raise_error
|
37
|
+
else
|
38
|
+
expect { element.text }.to raise_error
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/spec/browser_spec.rb
CHANGED
@@ -70,7 +70,7 @@ describe Watir::Browser do
|
|
70
70
|
b.goto WatirSpec.url_for "definition_lists.html"
|
71
71
|
b.close
|
72
72
|
|
73
|
-
expect { b.dl(:id => "experience-list").id }.to raise_error(Error, "browser was closed")
|
73
|
+
expect { b.dl(:id => "experience-list").id }.to raise_error(Watir::Exception::Error, "browser was closed")
|
74
74
|
end
|
75
75
|
|
76
76
|
describe "#wait_while" do
|
@@ -368,7 +368,7 @@ describe Watir::ElementLocator do
|
|
368
368
|
valid_attributes = Watir::Input.attributes
|
369
369
|
|
370
370
|
expect { locate_one(bad_selector, valid_attributes) }.to \
|
371
|
-
raise_error(MissingWayOfFindingObjectException, "invalid attribute: :href")
|
371
|
+
raise_error(Watir::Exception::MissingWayOfFindingObjectException, "invalid attribute: :href")
|
372
372
|
end
|
373
373
|
end
|
374
374
|
end
|
@@ -383,6 +383,18 @@ describe Watir::ElementLocator do
|
|
383
383
|
end
|
384
384
|
end
|
385
385
|
|
386
|
+
describe "with an empty selector" do
|
387
|
+
it "finds all when an empty selctor is given" do
|
388
|
+
if Watir.prefer_css?
|
389
|
+
expect_all :css, '*'
|
390
|
+
else
|
391
|
+
expect_all :xpath, './/*'
|
392
|
+
end
|
393
|
+
|
394
|
+
locate_all({})
|
395
|
+
end
|
396
|
+
end
|
397
|
+
|
386
398
|
describe "with selectors not supported by webdriver" do
|
387
399
|
it "handles selector with tag name and a single attribute" do
|
388
400
|
if Watir.prefer_css?
|