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
@@ -21,9 +21,8 @@ module Watir
21
21
  #
22
22
 
23
23
  def value=(path)
24
- assert_exists
25
24
  path = path.gsub(File::SEPARATOR, File::ALT_SEPARATOR) if File::ALT_SEPARATOR
26
- @element.send_keys path
25
+ send_keys path
27
26
  end
28
27
 
29
28
  end # FileField
@@ -10,7 +10,8 @@ module Watir
10
10
 
11
11
  def submit
12
12
  assert_exists
13
- @element.submit
13
+ element_call { @element.submit }
14
+ run_checkers
14
15
  end
15
16
 
16
17
  end # Form
@@ -19,8 +19,6 @@ module Watir
19
19
  attribute(String, :access_key_label, :accessKeyLabel)
20
20
  attribute("Boolean", :draggable?, :draggable)
21
21
  attribute(String, :dropzone, :dropzone)
22
- attribute(String, :content_editable, :contentEditable)
23
- attribute("Boolean", :content_editable?, :isContentEditable)
24
22
  attribute(String, :context_menu, :contextMenu)
25
23
  attribute("Boolean", :spellcheck?, :spellcheck)
26
24
  attribute(String, :command_type, :commandType)
@@ -92,6 +90,8 @@ module Watir
92
90
  attribute(String, :ontoggle, :ontoggle)
93
91
  attribute(String, :onvolumechange, :onvolumechange)
94
92
  attribute(String, :onwaiting, :onwaiting)
93
+ attribute(String, :content_editable, :contentEditable)
94
+ attribute("Boolean", :content_editable?, :isContentEditable)
95
95
  end
96
96
  class HTMLElementCollection < ElementCollection
97
97
  def element_class
@@ -662,6 +662,7 @@ module Watir
662
662
  class Media < HTMLElement
663
663
  attribute(String, :error, :error)
664
664
  attribute(String, :src, :src)
665
+ attribute(String, :src_object, :srcObject)
665
666
  attribute(String, :current_src, :currentSrc)
666
667
  attribute(String, :cross_origin, :crossOrigin)
667
668
  attribute(Fixnum, :network_state, :networkState)
@@ -727,15 +728,6 @@ module Watir
727
728
  Track
728
729
  end
729
730
  end
730
- class Source < HTMLElement
731
- attribute(String, :src, :src)
732
- attribute(String, :type, :type)
733
- end
734
- class SourceCollection < ElementCollection
735
- def element_class
736
- Source
737
- end
738
- end
739
731
  class Param < HTMLElement
740
732
  attribute(String, :name, :name)
741
733
  attribute(String, :value, :value)
@@ -817,6 +809,7 @@ module Watir
817
809
  attribute(String, :alt, :alt)
818
810
  attribute(String, :src, :src)
819
811
  attribute(String, :srcset, :srcset)
812
+ attribute(String, :sizes, :sizes)
820
813
  attribute(String, :cross_origin, :crossOrigin)
821
814
  attribute(String, :use_map, :useMap)
822
815
  attribute("Boolean", :map?, :isMap)
@@ -825,6 +818,7 @@ module Watir
825
818
  attribute(Fixnum, :natural_width, :naturalWidth)
826
819
  attribute(Fixnum, :natural_height, :naturalHeight)
827
820
  attribute("Boolean", :complete?, :complete)
821
+ attribute(String, :current_src, :currentSrc)
828
822
  attribute(String, :name, :name)
829
823
  attribute(String, :lowsrc, :lowsrc)
830
824
  attribute(String, :align, :align)
@@ -838,6 +832,25 @@ module Watir
838
832
  Image
839
833
  end
840
834
  end
835
+ class Source < HTMLElement
836
+ attribute(String, :srcset, :srcset)
837
+ attribute(String, :sizes, :sizes)
838
+ attribute(String, :media, :media)
839
+ attribute(String, :src, :src)
840
+ attribute(String, :type, :type)
841
+ end
842
+ class SourceCollection < ElementCollection
843
+ def element_class
844
+ Source
845
+ end
846
+ end
847
+ class Picture < HTMLElement
848
+ end
849
+ class PictureCollection < ElementCollection
850
+ def element_class
851
+ Picture
852
+ end
853
+ end
841
854
  class Mod < HTMLElement
842
855
  attribute(String, :cite, :cite)
843
856
  attribute(String, :date_time, :dateTime)
@@ -5,29 +5,22 @@ module Watir
5
5
  def locate
6
6
  @parent.assert_exists
7
7
 
8
- locator = locator_class.new(@parent.wd, @selector.merge(:tag_name => tag_name), self.class.attribute_list)
8
+ locator = locator_class.new(@parent.wd, @selector.merge(:tag_name => frame_tag), self.class.attribute_list)
9
9
  element = locator.locate
10
10
  element or raise UnknownFrameException, "unable to locate #{@selector[:tag_name]} using #{selector_string}"
11
11
 
12
- @parent.reset!
13
-
14
12
  FramedDriver.new(element, driver)
15
13
  end
16
14
 
15
+ def switch_to!
16
+ locate.send :switch!
17
+ end
18
+
17
19
  def assert_exists
18
20
  if @selector.has_key? :element
19
21
  raise UnknownFrameException, "wrapping a WebDriver element as a Frame is not currently supported"
20
22
  end
21
23
 
22
- if @element && !Watir.always_locate?
23
- begin
24
- @element.tag_name # rpc
25
- return @element
26
- rescue Selenium::WebDriver::Error::ObsoleteElementError
27
- @element = nil # re-locate
28
- end
29
- end
30
-
31
24
  super
32
25
  end
33
26
 
@@ -36,7 +29,7 @@ module Watir
36
29
 
37
30
  # this will actually give us the innerHTML instead of the outerHTML of the <frame>,
38
31
  # but given the choice this seems more useful
39
- execute_atom(:getOuterHtml, @element.find_element(:tag_name => "html")).strip
32
+ element_call { execute_atom(:getOuterHtml, @element.find_element(:tag_name => "html")).strip }
40
33
  end
41
34
 
42
35
  def execute_script(*args)
@@ -45,7 +38,7 @@ module Watir
45
38
 
46
39
  private
47
40
 
48
- def tag_name
41
+ def frame_tag
49
42
  'iframe'
50
43
  end
51
44
 
@@ -55,13 +48,28 @@ module Watir
55
48
  class IFrameCollection < ElementCollection
56
49
 
57
50
  def to_a
58
- (0...elements.size).map { |idx| element_class.new @parent, :index => idx }
51
+ # In case `#all_elements` returns empty array, but `#elements`
52
+ # returns non-empty array (i.e. any frame has loaded between these two calls),
53
+ # index will return nil. That's why `#all_elements` should always
54
+ # be called after `#elements.`
55
+ element_indexes = elements.map { |el| all_elements.index(el) }
56
+ element_indexes.map { |idx| element_class.new(@parent, tag_name: @selector[:tag_name], :index => idx) }
59
57
  end
60
58
 
61
59
  def element_class
62
60
  IFrame
63
61
  end
64
62
 
63
+ private
64
+
65
+ def all_elements
66
+ locator_class.new(
67
+ @parent.wd,
68
+ { tag_name: @selector[:tag_name] },
69
+ element_class.attribute_list
70
+ ).locate_all
71
+ end
72
+
65
73
  end # IFrameCollection
66
74
 
67
75
 
@@ -69,7 +77,7 @@ module Watir
69
77
 
70
78
  private
71
79
 
72
- def tag_name
80
+ def frame_tag
73
81
  'frame'
74
82
  end
75
83
 
@@ -110,7 +118,7 @@ module Watir
110
118
  end
111
119
 
112
120
  def ==(other)
113
- @element == other.wd
121
+ wd == other.wd
114
122
  end
115
123
  alias_method :eql?, :==
116
124
 
@@ -14,10 +14,7 @@ module Watir
14
14
  # browser.select(:id => "foo").options.first.select
15
15
  #
16
16
 
17
- def select
18
- assert_exists
19
- @element.click
20
- end
17
+ alias_method :select, :click
21
18
 
22
19
  #
23
20
  # Toggles the selected state of this option.
@@ -26,10 +23,7 @@ module Watir
26
23
  # browser.select(:id => "foo").options.first.toggle
27
24
  #
28
25
 
29
- def toggle
30
- assert_exists
31
- @element.click
32
- end
26
+ alias_method :toggle, :click
33
27
 
34
28
  #
35
29
  # Clears (i.e. toggles selected state) option.
@@ -39,7 +33,7 @@ module Watir
39
33
  #
40
34
 
41
35
  def clear
42
- @element.click if selected?
36
+ click if selected?
43
37
  end
44
38
 
45
39
  #
@@ -50,7 +44,7 @@ module Watir
50
44
 
51
45
  def selected?
52
46
  assert_exists
53
- @element.selected?
47
+ element_call { @element.selected? }
54
48
  end
55
49
 
56
50
  #
@@ -65,17 +59,15 @@ module Watir
65
59
  #
66
60
 
67
61
  def text
68
- assert_exists
69
-
70
62
  # A little unintuitive - we'll return the 'label' or 'text' attribute if
71
63
  # they exist, otherwise the inner text of the element
72
64
 
73
65
  attribute = [:label, :text].find { |a| attribute? a }
74
66
 
75
67
  if attribute
76
- @element.attribute(attribute)
68
+ attribute_value(attribute)
77
69
  else
78
- @element.text
70
+ super
79
71
  end
80
72
  end
81
73
 
@@ -7,10 +7,7 @@ module Watir
7
7
  #
8
8
 
9
9
  def set
10
- assert_exists
11
- assert_enabled
12
-
13
- @element.click unless set?
10
+ click unless set?
14
11
  end
15
12
 
16
13
  #
@@ -21,7 +18,7 @@ module Watir
21
18
 
22
19
  def set?
23
20
  assert_exists
24
- @element.selected?
21
+ element_call { @element.selected? }
25
22
  end
26
23
 
27
24
  end # Radio
@@ -46,7 +46,6 @@ module Watir
46
46
  #
47
47
 
48
48
  def include?(str_or_rx)
49
- assert_exists
50
49
  # TODO: optimize similar to selected?
51
50
  options.any? { |e| str_or_rx === e.text }
52
51
  end
@@ -88,7 +87,11 @@ module Watir
88
87
 
89
88
  def selected?(str_or_rx)
90
89
  assert_exists
91
- matches = @element.find_elements(:tag_name, 'option').select { |e| str_or_rx === e.text || str_or_rx === e.attribute(:label) }
90
+ matches = element_call do
91
+ @element.find_elements(:tag_name, 'option').select do |e|
92
+ str_or_rx === e.text || str_or_rx === e.attribute(:label)
93
+ end
94
+ end
92
95
 
93
96
  if matches.empty?
94
97
  raise UnknownObjectException, "Unable to locate option matching #{str_or_rx.inspect}"
@@ -117,7 +120,6 @@ module Watir
117
120
  #
118
121
 
119
122
  def selected_options
120
- assert_exists
121
123
  options.select { |e| e.selected? }
122
124
  end
123
125
 
@@ -140,14 +142,18 @@ module Watir
140
142
  xpath = option_xpath_for(how, string)
141
143
 
142
144
  if multiple?
143
- elements = @element.find_elements(:xpath, xpath)
145
+ elements = element_call do
146
+ @element.find_elements(:xpath, xpath)
147
+ end
144
148
  no_value_found(string) if elements.empty?
145
149
 
146
150
  elements.each { |e| e.click unless e.selected? }
147
151
  elements.first.text
148
152
  else
149
153
  begin
150
- e = @element.find_element(:xpath, xpath)
154
+ e = element_call do
155
+ @element.find_element(:xpath, xpath)
156
+ end
151
157
  rescue Selenium::WebDriver::Error::NoSuchElementError
152
158
  no_value_found(string)
153
159
  end
@@ -159,7 +165,9 @@ module Watir
159
165
  end
160
166
 
161
167
  def select_by_regexp(how, exp)
162
- elements = @element.find_elements(:tag_name, 'option')
168
+ elements = element_call do
169
+ @element.find_elements(:tag_name, 'option')
170
+ end
163
171
  no_value_found(nil, "no options in select list") if elements.empty?
164
172
 
165
173
  if multiple?
@@ -208,7 +216,7 @@ module Watir
208
216
 
209
217
  def safe_text(element)
210
218
  element.text
211
- rescue Selenium::WebDriver::Error::ObsoleteElementError, Selenium::WebDriver::Error::UnhandledAlertError
219
+ rescue Selenium::WebDriver::Error::StaleElementReferenceError, Selenium::WebDriver::Error::UnhandledAlertError
212
220
  # guard for scenario where selecting the element changes the page, making our element obsolete
213
221
 
214
222
  ''
@@ -12,8 +12,6 @@ module Watir
12
12
  class MissingWayOfFindingObjectException < Error; end
13
13
  class UnknownCellException < Error; end
14
14
  class NoMatchingWindowFoundException < Error; end
15
- class NoStatusBarException < Error; end
16
- class NavigationException < Error; end
17
15
  class UnknownFrameException < Error; end
18
16
  class UnknownRowException < Error; end
19
17
 
@@ -15,11 +15,6 @@ module Watir
15
15
  #
16
16
  # This method is provided by an optional require - API is subject to change.
17
17
  #
18
- # @example
19
- # browser.alert do
20
- # browser.button(:value => "Alert").click
21
- # end #=> "the alert message"
22
- #
23
18
 
24
19
  def alert(&blk)
25
20
  warn 'AlertHelper is deprecated. Use the new Alert API instead (e.g. browser.alert.ok)'
@@ -33,10 +28,6 @@ module Watir
33
28
  #
34
29
  # This method is provided by an optional require - API is subject to change.
35
30
  #
36
- # @example
37
- # browser.confirm(true) do
38
- # browser.button(:value => "Confirm").click
39
- # end #=> "the confirm message"
40
31
 
41
32
  def confirm(bool, &blk)
42
33
  warn 'AlertHelper is deprecated. Use the new Alert API instead (e.g. browser.alert.ok)'
@@ -50,11 +41,6 @@ module Watir
50
41
  #
51
42
  # This method is provided by an optional require - API is subject to change.
52
43
  #
53
- # @example
54
- # browser.prompt("hello") do
55
- # browser.button(:value => "Prompt").click
56
- # end #=> { :message => "foo", :default_value => "bar" }
57
- #
58
44
 
59
45
  def prompt(answer, &blk)
60
46
  warn 'AlertHelper is deprecated. Use the new Alert API instead (e.g. browser.alert.ok)'
@@ -5,8 +5,7 @@ module Watir
5
5
  # Returns browser windows array.
6
6
  #
7
7
  # @example
8
- # browser.a(:id => "open_new_window").click
9
- # browser.windows(:title => "new")
8
+ # browser.windows(:title => 'closeable window')
10
9
  #
11
10
  # @return [Array<Window>]
12
11
  #
@@ -25,8 +24,7 @@ module Watir
25
24
  # Returns browser window.
26
25
  #
27
26
  # @example
28
- # browser.a(:id => "open_new_window").click
29
- # browser.window(:title => "new")
27
+ # browser.window(:title => 'closeable window')
30
28
  #
31
29
  # @return [Window]
32
30
  #
@@ -74,8 +74,8 @@ module Watir
74
74
 
75
75
  def extract_interface_map
76
76
  # http://www.whatwg.org/specs/web-apps/current-work/#elements-1
77
- table = @doc.search("//h3[@id='elements-1']/following-sibling::table[1]").first
78
- table or raise "could not find elements-1 table"
77
+ table = @doc.search("//h3[@id='elements-3']/following-sibling::table[1]").first
78
+ table or raise "could not find elements-3 table"
79
79
 
80
80
  @interface_map = {}
81
81
 
@@ -143,6 +143,7 @@ module Watir
143
143
 
144
144
  duplicates.each do |intf|
145
145
  final = non_duplicates.find { |i| i.name == intf.name }
146
+ final.inherits += intf.inherits
146
147
  final.members += intf.members
147
148
  final.extended_attributes += intf.extended_attributes
148
149
  end
@@ -148,9 +148,9 @@ module Watir
148
148
  Float
149
149
  when 'Boolean'
150
150
  'Boolean'
151
- when 'WindowProxy', 'ValidityState', 'MediaError', 'TimeRanges', 'Location',
151
+ when 'WindowProxy', 'ValidityState', 'TimeRanges', 'Location',
152
152
  'Any', 'TimedTrackArray', 'TimedTrack', 'TextTrackArray', 'TextTrack',
153
- 'MediaController', 'TextTrackKind', 'Function', /.*EventHandler$/,
153
+ /Media.+/, 'TextTrackKind', 'Function', /.*EventHandler$/,
154
154
  'Document', 'DocumentFragment', 'DOMTokenList', 'DOMSettableTokenList',
155
155
  'DOMStringMap', 'HTMLPropertiesCollection', /HTML(.*)Element/, /HTML(.*)Collection/,
156
156
  'CSSStyleDeclaration', /.+List$/, 'Date', 'Element'