watir-webdriver 0.6.11 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
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