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.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +14 -12
  3. data/CHANGES.md +17 -0
  4. data/LICENSE +1 -1
  5. data/README.md +8 -1
  6. data/Rakefile +7 -2
  7. data/lib/watir-webdriver/alert.rb +5 -1
  8. data/lib/watir-webdriver/attribute_helper.rb +4 -8
  9. data/lib/watir-webdriver/browser.rb +41 -21
  10. data/lib/watir-webdriver/element_collection.rb +1 -2
  11. data/lib/watir-webdriver/elements/button.rb +3 -5
  12. data/lib/watir-webdriver/elements/checkbox.rb +2 -11
  13. data/lib/watir-webdriver/elements/element.rb +93 -86
  14. data/lib/watir-webdriver/elements/file_field.rb +1 -2
  15. data/lib/watir-webdriver/elements/form.rb +2 -1
  16. data/lib/watir-webdriver/elements/generated.rb +24 -11
  17. data/lib/watir-webdriver/elements/iframe.rb +25 -17
  18. data/lib/watir-webdriver/elements/option.rb +6 -14
  19. data/lib/watir-webdriver/elements/radio.rb +2 -5
  20. data/lib/watir-webdriver/elements/select.rb +15 -7
  21. data/lib/watir-webdriver/exception.rb +0 -2
  22. data/lib/watir-webdriver/extensions/alerts.rb +0 -14
  23. data/lib/watir-webdriver/has_window.rb +2 -4
  24. data/lib/watir-webdriver/html/spec_extractor.rb +3 -2
  25. data/lib/watir-webdriver/html/visitor.rb +2 -2
  26. data/lib/watir-webdriver/locators/element_locator.rb +22 -21
  27. data/lib/watir-webdriver/locators/text_field_locator.rb +11 -3
  28. data/lib/watir-webdriver/user_editable.rb +5 -10
  29. data/lib/watir-webdriver/version.rb +1 -1
  30. data/lib/watir-webdriver/wait.rb +26 -26
  31. data/lib/watir-webdriver/window.rb +30 -25
  32. data/spec/always_locate_spec.rb +42 -0
  33. data/spec/browser_spec.rb +1 -1
  34. data/spec/element_locator_spec.rb +13 -1
  35. data/spec/element_spec.rb +43 -8
  36. data/spec/input_spec.rb +0 -31
  37. data/spec/spec_helper.rb +0 -1
  38. data/support/doctest_helper.rb +72 -0
  39. data/support/travis.sh +4 -0
  40. data/watir-webdriver.gemspec +2 -1
  41. metadata +50 -35
  42. data/spec/html/inner_outer.html +0 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f701ec966d5fba22ef3505c0df91d8db1581b04e
4
- data.tar.gz: c5002bc487ed49c06385469e0b531b23ecd6b11b
3
+ metadata.gz: 3c59e0947d61d3444072fba9199dbb1923ef78bb
4
+ data.tar.gz: cea68a6afbae78f341d70c43e276697cd297b42a
5
5
  SHA512:
6
- metadata.gz: ad1194e189f237e24d3ff125332b038ca9361ed427d5dd51c15c61da29c9d7da24cd5a3df8303434d1eeea4f0d622e82a7d8932dd1510966a4763e2878a19047
7
- data.tar.gz: 79f65f913cc04a54ed1a5f25a4717bbed04ba1a3529679c9647a40d752491f17cdb96b24254584def0a78b6af1b6ece720e602b5111317fe4fb71ede41540e06
6
+ metadata.gz: 118d8dac0739c61e992e684c3f7ea86744142bf27f68f10bd766f3f930724c5d7c7475b9ba02d2fb11dda3ff33c582ddf02227a5933e23b8c07d39409fcb1473
7
+ data.tar.gz: 76b6e52b21db799697ccf8777debbeaebd14bbb5e19e60825c6f7c6a5ccce387c964dd647e1506f5dc4c8a6315264b8f9816f77cd234987e219be7741399b723
@@ -9,18 +9,20 @@ notifications:
9
9
  irc: "irc.freenode.net#watir"
10
10
  before_script:
11
11
  - support/travis.sh
12
+ script: bundle exec rake $RAKE_TASK
12
13
  env:
13
- - WATIR_WEBDRIVER_BROWSER=firefox
14
- - WATIR_WEBDRIVER_BROWSER=firefox ALWAYS_LOCATE=false
15
- - WATIR_WEBDRIVER_BROWSER=firefox PREFER_CSS=1 SELECTOR_STATS=1
16
- - WATIR_WEBDRIVER_BROWSER=chrome
17
- - WATIR_WEBDRIVER_BROWSER=chrome ALWAYS_LOCATE=false
18
- - WATIR_WEBDRIVER_BROWSER=chrome PREFER_CSS=1 SELECTOR_STATS=1
19
- - WATIR_WEBDRIVER_BROWSER=phantomjs
20
- - WATIR_WEBDRIVER_BROWSER=phantomjs ALWAYS_LOCATE=false
21
- - WATIR_WEBDRIVER_BROWSER=phantomjs PREFER_CSS=1 SELECTOR_STATS=1
14
+ - RAKE_TASK=spec WATIR_WEBDRIVER_BROWSER=firefox
15
+ - RAKE_TASK=spec WATIR_WEBDRIVER_BROWSER=firefox ALWAYS_LOCATE=false
16
+ - RAKE_TASK=spec WATIR_WEBDRIVER_BROWSER=firefox PREFER_CSS=1 SELECTOR_STATS=1
17
+ - RAKE_TASK=spec WATIR_WEBDRIVER_BROWSER=chrome
18
+ - RAKE_TASK=spec WATIR_WEBDRIVER_BROWSER=chrome ALWAYS_LOCATE=false
19
+ - RAKE_TASK=spec WATIR_WEBDRIVER_BROWSER=chrome PREFER_CSS=1 SELECTOR_STATS=1
20
+ # - RAKE_TASK=spec WATIR_WEBDRIVER_BROWSER=phantomjs
21
+ # - RAKE_TASK=spec WATIR_WEBDRIVER_BROWSER=phantomjs ALWAYS_LOCATE=false
22
+ # - RAKE_TASK=spec WATIR_WEBDRIVER_BROWSER=phantomjs PREFER_CSS=1 SELECTOR_STATS=1
23
+ - RAKE_TASK=yard:doctest
22
24
  matrix:
23
25
  allow_failures:
24
- - env: WATIR_WEBDRIVER_BROWSER=phantomjs
25
- - env: WATIR_WEBDRIVER_BROWSER=phantomjs ALWAYS_LOCATE=false
26
- - env: WATIR_WEBDRIVER_BROWSER=phantomjs PREFER_CSS=1 SELECTOR_STATS=1
26
+ - env: RAKE_TASK=spec WATIR_WEBDRIVER_BROWSER=phantomjs
27
+ - env: RAKE_TASK=spec WATIR_WEBDRIVER_BROWSER=phantomjs ALWAYS_LOCATE=false
28
+ - env: RAKE_TASK=spec WATIR_WEBDRIVER_BROWSER=phantomjs PREFER_CSS=1 SELECTOR_STATS=1
data/CHANGES.md CHANGED
@@ -1,3 +1,20 @@
1
+ ### 0.7.0
2
+
3
+ * Allow finding all elements with prefer_css
4
+ * Add support for yard-doctest (#287)
5
+ * Update from HTML spec (#296)
6
+ * Support tag_name call on Frames and IFrames (#293 & #294)
7
+ * Increased performance by caching elements by default where possible (#307)
8
+ * Improved handling of elements that go stale during lookup (#291, thanks @titusfortner)
9
+ * Fix element location issues when switching between IFrames (#286, thanks @titusfortner)
10
+ * Fix creation of an IFrameCollection based on selector (#299, thanks @titusfortner)
11
+ * Fix window handling with closed windows (#290 & 282, thanks @titusfortner)
12
+ * Prevent running checkers on a closed window (#283, thanks @titusfortner)
13
+ * Allow taking actions without triggering run checkers (#283, thanks @titusfortner)
14
+ * Fix bug when ElementCollection#[] returns existing elements for non-existing selector (#309)
15
+ * Fix bug when Wait would never execute block with 0 timeout (#312)
16
+ * Fix race condition with IFrameCollection#to_a (#317)
17
+
1
18
  ### 0.6.11 (2014-09-23)
2
19
 
3
20
  * Fix namespacing issue (#265, thanks @titusfortner)
data/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  (the MIT License)
2
2
 
3
- Copyright (c) 2009-2014 Jari Bakken
3
+ Copyright (c) 2009-2015 Jari Bakken
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining
6
6
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -38,6 +38,13 @@ watir-webdriver uses [watirspec](http://github.com/watir/watirspec) for testing.
38
38
 
39
39
  Specs specific to watir-webdriver are found in spec/*_spec.rb, with watirspec in spec/watirspec.
40
40
 
41
+ Doctests
42
+ --------
43
+
44
+ watir-webdriver uses [yard-doctest](https://github.com/p0deje/yard-doctest) for testing documentation examples.
45
+
46
+ rake yard:doctest
47
+
41
48
  API docs
42
49
  --------
43
50
 
@@ -71,4 +78,4 @@ Note on Patches/Pull Requests
71
78
  Copyright
72
79
  ---------
73
80
 
74
- Copyright (c) 2009-2014 Jari Bakken. See LICENSE for details.
81
+ Copyright (c) 2009-2015 Jari Bakken. See LICENSE for details.
data/Rakefile CHANGED
@@ -20,10 +20,10 @@ namespace :spec do
20
20
  end
21
21
  end
22
22
 
23
- task :default => :spec
23
+ task :default => [:spec, 'yard:doctest']
24
24
 
25
25
  namespace :html5 do
26
- SPEC_URI = "http://www.whatwg.org/specs/web-apps/current-work/"
26
+ SPEC_URI = "https://www.whatwg.org/specs/web-apps/current-work/"
27
27
  SPEC_PATH = "support/html5.html"
28
28
 
29
29
  task :html_lib => :lib do
@@ -91,6 +91,11 @@ YARD::Rake::YardocTask.new do |task|
91
91
  task.options = %w[--debug] # this is pretty slow, so nice with some output
92
92
  end
93
93
 
94
+ require 'yard-doctest'
95
+ YARD::Doctest::RakeTask.new do |task|
96
+ task.doctest_opts = ['-v']
97
+ end
98
+
94
99
  namespace :changes do
95
100
  task :differ do
96
101
  require './support/version_differ'
@@ -14,7 +14,7 @@ module Watir
14
14
  #
15
15
  # @example
16
16
  # browser.alert.text
17
- # #=> "This is alert text"
17
+ # #=> "ok"
18
18
  #
19
19
  # @return [String]
20
20
  #
@@ -70,6 +70,10 @@ module Watir
70
70
  #
71
71
  # Returns true if alert, confirm or prompt is present and false otherwise.
72
72
  #
73
+ # @example
74
+ # browser.alert.exists?
75
+ # #=> true
76
+ #
73
77
 
74
78
  def exists?
75
79
  assert_exists
@@ -68,30 +68,26 @@ module Watir
68
68
 
69
69
  def define_string_attribute(mname, aname)
70
70
  define_method mname do
71
- assert_exists
72
- @element.attribute(aname).to_s
71
+ attribute_value(aname).to_s
73
72
  end
74
73
  end
75
74
 
76
75
  def define_boolean_attribute(mname, aname)
77
76
  define_method mname do
78
- assert_exists
79
- @element.attribute(aname) == "true"
77
+ attribute_value(aname) == "true"
80
78
  end
81
79
  end
82
80
 
83
81
  def define_int_attribute(mname, aname)
84
82
  define_method mname do
85
- assert_exists
86
- value = @element.attribute(aname)
83
+ value = attribute_value(aname)
87
84
  value && Integer(value)
88
85
  end
89
86
  end
90
87
 
91
88
  def define_float_attribute(mname, aname)
92
89
  define_method mname do
93
- assert_exists
94
- value = @element.attribute(aname)
90
+ value = attribute_value(aname)
95
91
  value && Float(value)
96
92
  end
97
93
  end
@@ -18,7 +18,7 @@ module Watir
18
18
  # Creates a Watir::Browser instance and goes to URL.
19
19
  #
20
20
  # @example
21
- # browser = Watir::Browser.start "www.google.com", :chrome
21
+ # browser = Watir::Browser.start "www.google.com", :firefox
22
22
  # #=> #<Watir::Browser:0x..fa45a499cb41e1752 url="http://www.google.com" title="Google">
23
23
  #
24
24
  # @param [String] url
@@ -65,7 +65,7 @@ module Watir
65
65
  # Goes to the given URL.
66
66
  #
67
67
  # @example
68
- # browser.goto "www.google.com"
68
+ # browser.goto "www.watir.com"
69
69
  #
70
70
  # @param [String] uri The url.
71
71
  # @return [String] The url you end up at.
@@ -100,9 +100,9 @@ module Watir
100
100
  # Returns URL of current page.
101
101
  #
102
102
  # @example
103
- # browser.goto "http://www.google.com"
103
+ # browser.goto "www.watir.com"
104
104
  # browser.url
105
- # #=> "http://www.google.com"
105
+ # #=> "http://watir.com/"
106
106
  #
107
107
  # @return [String]
108
108
  #
@@ -116,9 +116,9 @@ module Watir
116
116
  # Returns title of current page.
117
117
  #
118
118
  # @example
119
- # browser.goto "http://www.google.com"
119
+ # browser.goto "www.watir.com"
120
120
  # browser.title
121
- # #=> "Google"
121
+ # #=> "Watir.com | Web Application Testing in Ruby"
122
122
  #
123
123
  # @return [String]
124
124
  #
@@ -152,9 +152,9 @@ module Watir
152
152
  # Returns browser name.
153
153
  #
154
154
  # @example
155
- # browser = Watir::Browser.new :chrome
155
+ # browser = Watir::Browser.new :firefox
156
156
  # browser.name
157
- # #=> :chrome
157
+ # #=> :firefox
158
158
  #
159
159
  # @return [Symbol]
160
160
  #
@@ -243,14 +243,9 @@ module Watir
243
243
  # `return` explicitly.
244
244
  #
245
245
  # @example Check that Ajax requests are completed with jQuery
246
- # browser.execute_script("return jQuery.active") == '0'
246
+ # browser.execute_script("return jQuery.active") == 0
247
247
  # #=> true
248
248
  #
249
- # @example Get inner HTML of element
250
- # span = browser.span(class: "someclass")
251
- # browser.execute_script "return arguments[0].innerHTML", span
252
- # #=> "Span innerHTML"
253
- #
254
249
  # @param [String] script JavaScript snippet to execute
255
250
  # @param *args Arguments will be available in the given script in the 'arguments' pseudo-array
256
251
  #
@@ -266,7 +261,7 @@ module Watir
266
261
  # Sends sequence of keystrokes to currently active element.
267
262
  #
268
263
  # @example
269
- # browser.goto "http://www.google.com"
264
+ # browser.goto "www.google.com"
270
265
  # browser.send_keys "Watir", :return
271
266
  #
272
267
  # @param [String, Symbol] *args
@@ -299,8 +294,8 @@ module Watir
299
294
  # browser.add_checker do |page|
300
295
  # page.text.include?("Server Error") and puts "Application exception or 500 error!"
301
296
  # end
302
- # browser.goto "www.mywebsite.com/page-with-error"
303
- # "Server error! (RuntimeError)"
297
+ # browser.goto "www.watir.com/404"
298
+ # "Application exception or 500 error!"
304
299
  #
305
300
  # @param [#call] checker Object responding to call
306
301
  # @yield Checker block
@@ -325,8 +320,8 @@ module Watir
325
320
  # page.text.include?("Server Error") and puts "Application exception or 500 error!"
326
321
  # end
327
322
  # browser.add_checker checker
328
- # browser.goto "www.mywebsite.com/page-with-error"
329
- # "Server error! (RuntimeError)"
323
+ # browser.goto "www.watir.com/404"
324
+ # "Application exception or 500 error!"
330
325
  # browser.disable_checker checker
331
326
  # browser.refresh
332
327
  #
@@ -340,7 +335,26 @@ module Watir
340
335
  #
341
336
 
342
337
  def run_checkers
343
- @error_checkers.each { |e| e.call(self) }
338
+ @error_checkers.each { |e| e.call(self) } if !@error_checkers.empty? && window.present?
339
+ end
340
+
341
+ #
342
+ # Executes a block without running error checkers.
343
+ #
344
+ # @example
345
+ # browser.without_checkers do
346
+ # browser.element(:name => "new_user_button").click
347
+ # end
348
+ #
349
+ # @yieldparam [Watir::Browser]
350
+ #
351
+
352
+ def without_checkers
353
+ current_checkers = @error_checkers
354
+ @error_checkers = []
355
+ yield(self)
356
+ ensure
357
+ @error_checkers = current_checkers
344
358
  end
345
359
 
346
360
  #
@@ -350,7 +364,10 @@ module Watir
350
364
  #
351
365
 
352
366
  def exist?
353
- not @closed
367
+ assert_exists
368
+ true
369
+ rescue Exception::NoMatchingWindowFoundException, Exception::Error
370
+ false
354
371
  end
355
372
  alias_method :exists?, :exist?
356
373
 
@@ -363,11 +380,14 @@ module Watir
363
380
  def assert_exists
364
381
  if @closed
365
382
  raise Exception::Error, "browser was closed"
383
+ elsif !window.present?
384
+ raise Exception::NoMatchingWindowFoundException, "browser window was closed"
366
385
  else
367
386
  driver.switch_to.default_content
368
387
  true
369
388
  end
370
389
  end
390
+ alias_method :assert_not_stale, :assert_exists
371
391
 
372
392
  def reset!
373
393
  # no-op
@@ -42,7 +42,6 @@ module Watir
42
42
 
43
43
  #
44
44
  # Get the element at the given index.
45
- # Note that this is 0-indexed and not compatible with older Watir implementations.
46
45
  #
47
46
  # Also note that because of Watir's lazy loading, this will return an Element
48
47
  # instance even if the index is out of bounds.
@@ -52,7 +51,7 @@ module Watir
52
51
  #
53
52
 
54
53
  def [](idx)
55
- to_a[idx] || element_class.new(@parent, :index => idx)
54
+ to_a[idx] || element_class.new(@parent, @selector.merge(:index => idx))
56
55
  end
57
56
 
58
57
  #
@@ -23,15 +23,13 @@ module Watir
23
23
  #
24
24
 
25
25
  def text
26
- assert_exists
27
-
28
- tn = @element.tag_name.downcase
26
+ tn = tag_name
29
27
 
30
28
  case tn
31
29
  when 'input'
32
- @element.attribute(:value)
30
+ value
33
31
  when 'button'
34
- @element.text
32
+ super
35
33
  else
36
34
  raise Exception::Error, "unknown tag name for button: #{tn}"
37
35
  end
@@ -17,14 +17,7 @@ module Watir
17
17
  #
18
18
 
19
19
  def set(bool = true)
20
- assert_exists
21
- assert_enabled
22
-
23
- if @element.selected?
24
- @element.click unless bool
25
- else
26
- @element.click if bool
27
- end
20
+ set? == bool ? assert_enabled : click
28
21
  end
29
22
 
30
23
  #
@@ -34,14 +27,12 @@ module Watir
34
27
 
35
28
  def set?
36
29
  assert_exists
37
- @element.selected?
30
+ element_call { @element.selected? }
38
31
  end
39
32
 
40
33
  #
41
34
  # Unsets checkbox.
42
35
  #
43
- # Same as +set(false)+
44
- #
45
36
 
46
37
  def clear
47
38
  set false
@@ -60,15 +60,12 @@ module Watir
60
60
  # Returns true if two elements are equal.
61
61
  #
62
62
  # @example
63
- # browser.a(:id => "foo") == browser.a(:id => "foo")
63
+ # browser.text_field(:name => "new_user_first_name") == browser.text_field(:name => "new_user_first_name")
64
64
  # #=> true
65
65
  #
66
66
 
67
67
  def ==(other)
68
- return false unless other.kind_of? self.class
69
-
70
- assert_exists
71
- @element == other.wd
68
+ other.kind_of?(self.class) && wd == other.wd
72
69
  end
73
70
  alias_method :eql?, :==
74
71
 
@@ -84,7 +81,7 @@ module Watir
84
81
 
85
82
  def text
86
83
  assert_exists
87
- @element.text
84
+ element_call { @element.text }
88
85
  end
89
86
 
90
87
  #
@@ -95,7 +92,7 @@ module Watir
95
92
 
96
93
  def tag_name
97
94
  assert_exists
98
- @element.tag_name.downcase
95
+ element_call { @element.tag_name.downcase }
99
96
  end
100
97
 
101
98
  #
@@ -104,13 +101,13 @@ module Watir
104
101
  # and may not work at all.
105
102
  #
106
103
  # @example Click an element
107
- # element.click
104
+ # browser.element(:name => "new_user_button").click
108
105
  #
109
106
  # @example Click an element with shift key pressed
110
- # element.click(:shift)
107
+ # browser.element(:name => "new_user_button").click(:shift)
111
108
  #
112
109
  # @example Click an element with several modifier keys pressed
113
- # element.click(:shift, :control)
110
+ # browser.element(:name => "new_user_button").click(:shift, :control)
114
111
  #
115
112
  # @param [:shift, :alt, :control, :command, :meta] Modifier key(s) to press while clicking.
116
113
  #
@@ -119,17 +116,19 @@ module Watir
119
116
  assert_exists
120
117
  assert_enabled
121
118
 
122
- if modifiers.any?
123
- assert_has_input_devices_for "click(#{modifiers.join ', '})"
119
+ element_call do
120
+ if modifiers.any?
121
+ assert_has_input_devices_for "click(#{modifiers.join ', '})"
124
122
 
125
- action = driver.action
126
- modifiers.each { |mod| action.key_down mod }
127
- action.click @element
128
- modifiers.each { |mod| action.key_up mod }
123
+ action = driver.action
124
+ modifiers.each { |mod| action.key_down mod }
125
+ action.click @element
126
+ modifiers.each { |mod| action.key_up mod }
129
127
 
130
- action.perform
131
- else
132
- @element.click
128
+ action.perform
129
+ else
130
+ @element.click
131
+ end
133
132
  end
134
133
 
135
134
  run_checkers
@@ -140,14 +139,14 @@ module Watir
140
139
  # Note that browser support may vary.
141
140
  #
142
141
  # @example
143
- # browser.a(:id => "foo").double_click
142
+ # browser.element(:name => "new_user_button").double_click
144
143
  #
145
144
 
146
145
  def double_click
147
146
  assert_exists
148
147
  assert_has_input_devices_for :double_click
149
148
 
150
- driver.action.double_click(@element).perform
149
+ element_call { driver.action.double_click(@element).perform }
151
150
  run_checkers
152
151
  end
153
152
 
@@ -156,14 +155,14 @@ module Watir
156
155
  # Note that browser support may vary.
157
156
  #
158
157
  # @example
159
- # browser.a(:id => "foo").right_click
158
+ # browser.element(:name => "new_user_button").right_click
160
159
  #
161
160
 
162
161
  def right_click
163
162
  assert_exists
164
163
  assert_has_input_devices_for :right_click
165
164
 
166
- driver.action.context_click(@element).perform
165
+ element_call { driver.action.context_click(@element).perform }
167
166
  run_checkers
168
167
  end
169
168
 
@@ -172,14 +171,14 @@ module Watir
172
171
  # Note that browser support may vary.
173
172
  #
174
173
  # @example
175
- # browser.a(:id => "foo").hover
174
+ # browser.element(:name => "new_user_button").hover
176
175
  #
177
176
 
178
177
  def hover
179
178
  assert_exists
180
179
  assert_has_input_devices_for :hover
181
180
 
182
- driver.action.move_to(@element).perform
181
+ element_call { driver.action.move_to(@element).perform }
183
182
  end
184
183
 
185
184
  #
@@ -187,9 +186,9 @@ module Watir
187
186
  # Note that browser support may vary.
188
187
  #
189
188
  # @example
190
- # a = browser.div(:id => "draggable")
191
- # b = browser.div(:id => "droppable")
192
- # a.drag_and_drop_on b
189
+ # a = browser.div(:id => "draggable")
190
+ # b = browser.div(:id => "droppable")
191
+ # a.drag_and_drop_on b
193
192
  #
194
193
 
195
194
  def drag_and_drop_on(other)
@@ -197,9 +196,11 @@ module Watir
197
196
  assert_exists
198
197
  assert_has_input_devices_for :drag_and_drop_on
199
198
 
200
- driver.action.
201
- drag_and_drop(@element, other.wd).
202
- perform
199
+ element_call do
200
+ driver.action.
201
+ drag_and_drop(@element, other.wd).
202
+ perform
203
+ end
203
204
  end
204
205
 
205
206
  #
@@ -207,7 +208,7 @@ module Watir
207
208
  # Note that browser support may vary.
208
209
  #
209
210
  # @example
210
- # browser.div(:id => "draggable").drag_and_drop_by 100, -200
211
+ # browser.div(:id => "draggable").drag_and_drop_by 100, -200
211
212
  #
212
213
  # @param [Fixnum] right_by
213
214
  # @param [Fixnum] down_by
@@ -217,16 +218,18 @@ module Watir
217
218
  assert_exists
218
219
  assert_has_input_devices_for :drag_and_drop_by
219
220
 
220
- driver.action.
221
- drag_and_drop_by(@element, right_by, down_by).
222
- perform
221
+ element_call do
222
+ driver.action.
223
+ drag_and_drop_by(@element, right_by, down_by).
224
+ perform
225
+ end
223
226
  end
224
227
 
225
228
  #
226
229
  # Flashes (change background color far a moment) element.
227
230
  #
228
231
  # @example
229
- # browser.div(:id => "draggable").flash
232
+ # browser.text_field(:name => "new_user_first_name").flash
230
233
  #
231
234
 
232
235
  def flash
@@ -250,44 +253,40 @@ module Watir
250
253
  #
251
254
 
252
255
  def value
253
- assert_exists
254
-
255
- begin
256
- @element.attribute('value') || ''
257
- rescue Selenium::WebDriver::Error::InvalidElementStateError
258
- ""
259
- end
256
+ attribute_value('value') || ''
257
+ rescue Selenium::WebDriver::Error::InvalidElementStateError
258
+ ''
260
259
  end
261
260
 
262
261
  #
263
262
  # Returns given attribute value of element.
264
263
  #
265
264
  # @example
266
- # browser.a(:id => "foo").attribute_value "href"
267
- # #=> "http://watir.com"
265
+ # browser.a(:id => "link_2").attribute_value "title"
266
+ # #=> "link_title_2"
268
267
  #
269
268
  # @param [String] attribute_name
270
- # @return [String]
269
+ # @return [String, nil]
271
270
  #
272
271
 
273
272
  def attribute_value(attribute_name)
274
273
  assert_exists
275
- @element.attribute attribute_name
274
+ element_call { @element.attribute attribute_name }
276
275
  end
277
276
 
278
277
  #
279
278
  # Returns outer (inner + element itself) HTML code of element.
280
279
  #
281
280
  # @example
282
- # browser.div(:id => "foo").html
283
- # #=> "<div id=\"foo\"><a>Click</a></div>"
281
+ # browser.div(:id => 'foo').outer_html
282
+ # #=> "<div id=\"foo\"><a href=\"#\">hello</a></div>"
284
283
  #
285
284
  # @return [String]
286
285
  #
287
286
 
288
287
  def outer_html
289
288
  assert_exists
290
- execute_atom(:getOuterHtml, @element).strip
289
+ element_call { execute_atom(:getOuterHtml, @element) }.strip
291
290
  end
292
291
 
293
292
  alias_method :html, :outer_html
@@ -296,29 +295,30 @@ module Watir
296
295
  # Returns inner HTML code of element.
297
296
  #
298
297
  # @example
299
- # browser.div(:id => "foo").html
300
- # #=> "<a>Click</a>"
298
+ # browser.div(:id => 'foo').inner_html
299
+ # #=> "<a href=\"#\">hello</a>"
301
300
  #
302
301
  # @return [String]
303
302
  #
304
303
 
305
304
  def inner_html
306
305
  assert_exists
307
- execute_atom(:getInnerHtml, @element).strip
306
+ element_call { execute_atom(:getInnerHtml, @element) }.strip
308
307
  end
309
308
 
310
309
  #
311
310
  # Sends sequence of keystrokes to element.
312
311
  #
313
312
  # @example
314
- # browser.div(:id => "foo").send_keys "Watir", :return
313
+ # browser.text_field(:name => "new_user_first_name").send_keys "Watir", :return
315
314
  #
316
315
  # @param [String, Symbol] *args
317
316
  #
318
317
 
319
318
  def send_keys(*args)
320
319
  assert_exists
321
- @element.send_keys(*args)
320
+ assert_writable
321
+ element_call { @element.send_keys(*args) }
322
322
  end
323
323
 
324
324
  #
@@ -330,7 +330,7 @@ module Watir
330
330
 
331
331
  def focus
332
332
  assert_exists
333
- driver.execute_script "return arguments[0].focus()", @element
333
+ element_call { driver.execute_script "return arguments[0].focus()", @element }
334
334
  end
335
335
 
336
336
  #
@@ -341,7 +341,7 @@ module Watir
341
341
 
342
342
  def focused?
343
343
  assert_exists
344
- @element == driver.switch_to.active_element
344
+ element_call { @element == driver.switch_to.active_element }
345
345
  end
346
346
 
347
347
  #
@@ -349,9 +349,9 @@ module Watir
349
349
  # Note that you may omit "on" from event name.
350
350
  #
351
351
  # @example
352
- # browser.a(:id => "foo").fire_event :click
353
- # browser.a(:id => "foo").fire_event "mousemove"
354
- # browser.a(:id => "foo").fire_event "onmouseover"
352
+ # browser.button(:name => "new_user_button").fire_event :click
353
+ # browser.button(:name => "new_user_button").fire_event "mousemove"
354
+ # browser.button(:name => "new_user_button").fire_event "onmouseover"
355
355
  #
356
356
  # @param [String, Symbol] event_name
357
357
  #
@@ -360,7 +360,7 @@ module Watir
360
360
  assert_exists
361
361
  event_name = event_name.to_s.sub(/^on/, '').downcase
362
362
 
363
- execute_atom :fireEvent, @element, event_name
363
+ element_call { execute_atom :fireEvent, @element, event_name }
364
364
  end
365
365
 
366
366
  #
@@ -370,7 +370,7 @@ module Watir
370
370
  def parent
371
371
  assert_exists
372
372
 
373
- e = execute_atom :getParentElement, @element
373
+ e = element_call { execute_atom :getParentElement, @element }
374
374
 
375
375
  if e.kind_of?(Selenium::WebDriver::Element)
376
376
  Watir.element_class_for(e.tag_name.downcase).new(@parent, :element => e)
@@ -402,7 +402,7 @@ module Watir
402
402
 
403
403
  def visible?
404
404
  assert_exists
405
- @element.displayed?
405
+ element_call { @element.displayed? }
406
406
  end
407
407
 
408
408
  #
@@ -414,7 +414,7 @@ module Watir
414
414
 
415
415
  def present?
416
416
  exists? && visible?
417
- rescue Selenium::WebDriver::Error::ObsoleteElementError, UnknownObjectException
417
+ rescue Selenium::WebDriver::Error::StaleElementReferenceError, UnknownObjectException
418
418
  # if the element disappears between the exists? and visible? calls,
419
419
  # consider it not present.
420
420
  false
@@ -424,10 +424,8 @@ module Watir
424
424
  # Returns given style property of this element.
425
425
  #
426
426
  # @example
427
- # browser.a(:id => "foo").style
428
- # #=> "display: block"
429
- # browser.a(:id => "foo").style "display"
430
- # #=> "block"
427
+ # browser.button(:value => "Delete").style #=> "border: 4px solid red;"
428
+ # browser.button(:value => "Delete").style("border") #=> "4px solid red"
431
429
  #
432
430
  # @param [String] property
433
431
  # @return [String]
@@ -436,7 +434,7 @@ module Watir
436
434
  def style(property = nil)
437
435
  if property
438
436
  assert_exists
439
- @element.style property
437
+ element_call { @element.style property }
440
438
  else
441
439
  attribute_value("style").to_s.strip
442
440
  end
@@ -497,39 +495,35 @@ module Watir
497
495
  protected
498
496
 
499
497
  def assert_exists
500
- if @element and not Watir.always_locate?
501
- assert_not_stale
502
- return
498
+ begin
499
+ assert_not_stale if @element ||= @selector[:element]
500
+ rescue UnknownObjectException => ex
501
+ raise ex if @selector[:element] || !Watir.always_locate?
503
502
  end
504
503
 
505
- @element = @selector[:element]
506
-
507
- if @element
508
- assert_not_stale
509
- else
510
- @element = locate
504
+ @element ||= locate
511
505
 
512
- unless @element
513
- raise UnknownObjectException, "unable to locate element, using #{selector_string}"
514
- end
506
+ unless @element
507
+ raise UnknownObjectException, "unable to locate element, using #{selector_string}"
515
508
  end
516
509
  end
517
510
 
518
511
  def assert_not_stale
512
+ @parent.assert_not_stale
513
+ @parent.switch_to! if @parent.is_a? IFrame
519
514
  @element.enabled? # do a staleness check - any wire call will do.
520
515
  rescue Selenium::WebDriver::Error::ObsoleteElementError => ex
521
516
  # don't cache a stale element - it will never come back
522
- @element = nil
517
+ reset!
523
518
  raise UnknownObjectException, "#{ex.message} - #{selector_string}"
524
519
  end
525
520
 
526
521
  def reset!
527
- @parent.reset!
528
522
  @element = nil
529
523
  end
530
524
 
531
525
  def locate
532
- @parent.assert_exists
526
+ @parent.is_a?(IFrame) ? @parent.switch_to! : @parent.assert_exists
533
527
  locator_class.new(@parent.wd, @selector, self.class.attribute_list).locate
534
528
  end
535
529
 
@@ -545,11 +539,15 @@ module Watir
545
539
 
546
540
  def attribute?(attribute)
547
541
  assert_exists
548
- !!execute_atom(:getAttribute, @element, attribute.to_s.downcase)
542
+ element_call do
543
+ !!execute_atom(:getAttribute, @element, attribute.to_s.downcase)
544
+ end
549
545
  end
550
546
 
551
547
  def assert_enabled
552
- raise ObjectDisabledException, "object is disabled #{selector_string}" unless @element.enabled?
548
+ unless element_call { @element.enabled? }
549
+ raise ObjectDisabledException, "object is disabled #{selector_string}"
550
+ end
553
551
  end
554
552
 
555
553
  def assert_writable
@@ -572,6 +570,15 @@ module Watir
572
570
  end
573
571
  end
574
572
 
573
+ def element_call
574
+ yield
575
+ rescue Selenium::WebDriver::Error::StaleElementReferenceError
576
+ raise unless Watir.always_locate?
577
+ reset!
578
+ assert_exists
579
+ retry
580
+ end
581
+
575
582
  def method_missing(meth, *args, &blk)
576
583
  method = meth.to_s
577
584
  if method =~ ElementLocator::WILDCARD_ATTRIBUTE