watir-webdriver 0.0.1.dev

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 (125) hide show
  1. data/.document +5 -0
  2. data/.gitignore +5 -0
  3. data/.gitmodules +3 -0
  4. data/LICENSE +20 -0
  5. data/README.rdoc +32 -0
  6. data/Rakefile +107 -0
  7. data/TODO +15 -0
  8. data/VERSION +1 -0
  9. data/lib/watir-webdriver.rb +74 -0
  10. data/lib/watir-webdriver/base_element.rb +347 -0
  11. data/lib/watir-webdriver/browser.rb +130 -0
  12. data/lib/watir-webdriver/browserbot.js +34 -0
  13. data/lib/watir-webdriver/collections/buttons_collection.rb +13 -0
  14. data/lib/watir-webdriver/collections/element_collection.rb +45 -0
  15. data/lib/watir-webdriver/collections/table_rows_collection.rb +14 -0
  16. data/lib/watir-webdriver/collections/text_fields_collection.rb +13 -0
  17. data/lib/watir-webdriver/container.rb +24 -0
  18. data/lib/watir-webdriver/core_ext/string.rb +22 -0
  19. data/lib/watir-webdriver/elements/button.rb +27 -0
  20. data/lib/watir-webdriver/elements/checkbox.rb +23 -0
  21. data/lib/watir-webdriver/elements/file_field.rb +20 -0
  22. data/lib/watir-webdriver/elements/form.rb +11 -0
  23. data/lib/watir-webdriver/elements/generated.rb +941 -0
  24. data/lib/watir-webdriver/elements/headings.rb +48 -0
  25. data/lib/watir-webdriver/elements/hidden.rb +18 -0
  26. data/lib/watir-webdriver/elements/image.rb +33 -0
  27. data/lib/watir-webdriver/elements/input.rb +39 -0
  28. data/lib/watir-webdriver/elements/link.rb +13 -0
  29. data/lib/watir-webdriver/elements/option.rb +36 -0
  30. data/lib/watir-webdriver/elements/radio.rb +23 -0
  31. data/lib/watir-webdriver/elements/select_list.rb +73 -0
  32. data/lib/watir-webdriver/elements/shared_radio_checkbox.rb +13 -0
  33. data/lib/watir-webdriver/elements/table.rb +18 -0
  34. data/lib/watir-webdriver/elements/table_row.rb +17 -0
  35. data/lib/watir-webdriver/elements/text_field.rb +60 -0
  36. data/lib/watir-webdriver/exception.rb +20 -0
  37. data/lib/watir-webdriver/locators/button_locator.rb +57 -0
  38. data/lib/watir-webdriver/locators/element_locator.rb +269 -0
  39. data/lib/watir-webdriver/locators/table_row_locator.rb +25 -0
  40. data/lib/watir-webdriver/locators/text_field_locator.rb +61 -0
  41. data/lib/watir-webdriver/xpath_support.rb +23 -0
  42. data/spec/element_locator_spec.rb +11 -0
  43. data/spec/spec_helper.rb +16 -0
  44. data/spec/watirspec/area_spec.rb +78 -0
  45. data/spec/watirspec/areas_spec.rb +31 -0
  46. data/spec/watirspec/browser_spec.rb +262 -0
  47. data/spec/watirspec/button_spec.rb +242 -0
  48. data/spec/watirspec/buttons_spec.rb +48 -0
  49. data/spec/watirspec/checkbox_spec.rb +272 -0
  50. data/spec/watirspec/checkboxes_spec.rb +32 -0
  51. data/spec/watirspec/dd_spec.rb +136 -0
  52. data/spec/watirspec/dds_spec.rb +31 -0
  53. data/spec/watirspec/div_spec.rb +222 -0
  54. data/spec/watirspec/divs_spec.rb +31 -0
  55. data/spec/watirspec/dl_spec.rb +136 -0
  56. data/spec/watirspec/dls_spec.rb +32 -0
  57. data/spec/watirspec/dt_spec.rb +136 -0
  58. data/spec/watirspec/dts_spec.rb +31 -0
  59. data/spec/watirspec/element_spec.rb +87 -0
  60. data/spec/watirspec/em_spec.rb +110 -0
  61. data/spec/watirspec/ems_spec.rb +32 -0
  62. data/spec/watirspec/filefield_spec.rb +119 -0
  63. data/spec/watirspec/filefields_spec.rb +32 -0
  64. data/spec/watirspec/form_spec.rb +63 -0
  65. data/spec/watirspec/forms_spec.rb +33 -0
  66. data/spec/watirspec/frame_spec.rb +140 -0
  67. data/spec/watirspec/frames_spec.rb +62 -0
  68. data/spec/watirspec/hidden_spec.rb +102 -0
  69. data/spec/watirspec/hiddens_spec.rb +32 -0
  70. data/spec/watirspec/hn_spec.rb +93 -0
  71. data/spec/watirspec/hns_spec.rb +38 -0
  72. data/spec/watirspec/image_spec.rb +207 -0
  73. data/spec/watirspec/images_spec.rb +31 -0
  74. data/spec/watirspec/label_spec.rb +75 -0
  75. data/spec/watirspec/labels_spec.rb +31 -0
  76. data/spec/watirspec/li_spec.rb +127 -0
  77. data/spec/watirspec/lib/guards.rb +59 -0
  78. data/spec/watirspec/lib/server.rb +127 -0
  79. data/spec/watirspec/lib/spec_helper.rb +79 -0
  80. data/spec/watirspec/lib/watirspec.rb +72 -0
  81. data/spec/watirspec/link_spec.rb +165 -0
  82. data/spec/watirspec/links_spec.rb +35 -0
  83. data/spec/watirspec/lis_spec.rb +31 -0
  84. data/spec/watirspec/map_spec.rb +92 -0
  85. data/spec/watirspec/maps_spec.rb +32 -0
  86. data/spec/watirspec/meta_spec.rb +22 -0
  87. data/spec/watirspec/metas_spec.rb +30 -0
  88. data/spec/watirspec/ol_spec.rb +78 -0
  89. data/spec/watirspec/ols_spec.rb +31 -0
  90. data/spec/watirspec/option_spec.rb +173 -0
  91. data/spec/watirspec/p_spec.rb +143 -0
  92. data/spec/watirspec/pre_spec.rb +125 -0
  93. data/spec/watirspec/pres_spec.rb +31 -0
  94. data/spec/watirspec/ps_spec.rb +31 -0
  95. data/spec/watirspec/radio_spec.rb +278 -0
  96. data/spec/watirspec/radios_spec.rb +32 -0
  97. data/spec/watirspec/select_list_spec.rb +318 -0
  98. data/spec/watirspec/select_lists_spec.rb +35 -0
  99. data/spec/watirspec/span_spec.rb +157 -0
  100. data/spec/watirspec/spans_spec.rb +57 -0
  101. data/spec/watirspec/spec_helper.rb +17 -0
  102. data/spec/watirspec/strong_spec.rb +89 -0
  103. data/spec/watirspec/strongs_spec.rb +32 -0
  104. data/spec/watirspec/table_bodies_spec.rb +45 -0
  105. data/spec/watirspec/table_body_spec.rb +98 -0
  106. data/spec/watirspec/table_cell_spec.rb +68 -0
  107. data/spec/watirspec/table_cells_spec.rb +47 -0
  108. data/spec/watirspec/table_footer_spec.rb +85 -0
  109. data/spec/watirspec/table_footers_spec.rb +47 -0
  110. data/spec/watirspec/table_header_spec.rb +85 -0
  111. data/spec/watirspec/table_headers_spec.rb +45 -0
  112. data/spec/watirspec/table_row_spec.rb +87 -0
  113. data/spec/watirspec/table_rows_spec.rb +50 -0
  114. data/spec/watirspec/table_spec.rb +166 -0
  115. data/spec/watirspec/tables_spec.rb +33 -0
  116. data/spec/watirspec/text_field_spec.rb +276 -0
  117. data/spec/watirspec/text_fields_spec.rb +35 -0
  118. data/spec/watirspec/ul_spec.rb +76 -0
  119. data/spec/watirspec/uls_spec.rb +33 -0
  120. data/spec/xpath_builder_spec.rb +49 -0
  121. data/support/html5/html5.idl +815 -0
  122. data/support/html5/html5_extras.idl +147 -0
  123. data/support/html5/idl_extractor.rb +73 -0
  124. data/support/html5/watir_visitor.rb +169 -0
  125. metadata +220 -0
@@ -0,0 +1,269 @@
1
+ # encoding: utf-8
2
+ module Watir
3
+ class ElementLocator
4
+ include Watir::Exception
5
+ include Selenium
6
+
7
+ WD_FINDERS = [ :class, :class_name, :id, :link_text, :link,
8
+ :partial_link_text, :name, :tag_name, :xpath ]
9
+
10
+ def initialize(wd, selector, valid_attributes)
11
+ @wd = wd
12
+ @selector = selector.dup
13
+ @valid_attributes = valid_attributes
14
+ end
15
+
16
+ def locate
17
+ # short-circuit if :id is given
18
+ if e = by_id
19
+ return e
20
+ end
21
+
22
+ if @selector.size == 1
23
+ find_first_by_one
24
+ else
25
+ find_first_by_multiple
26
+ end
27
+ rescue WebDriver::Error::WebDriverError => wde
28
+ nil
29
+ end
30
+
31
+ def locate_all
32
+ if @selector.size == 1
33
+ find_all_by_one
34
+ else
35
+ find_all_by_multiple
36
+ end
37
+ end
38
+
39
+ def find_first_by_one
40
+ how, what = @selector.shift
41
+ check_type how, what
42
+
43
+ if WD_FINDERS.include?(how)
44
+ wd_find_first_by(how, what)
45
+ else
46
+ raise NotImplementedError, "find first by attribute/other"
47
+ end
48
+ end
49
+
50
+ def find_all_by_one
51
+ how, what = @selector.shift
52
+ check_type how, what
53
+
54
+ if WD_FINDERS.include?(how)
55
+ wd_find_all_by(how, what)
56
+ else
57
+ raise NotImplementedError, "find all by attribute/other"
58
+ end
59
+ end
60
+
61
+ def find_first_by_multiple
62
+ selector = normalized_selector
63
+
64
+ idx = selector.delete(:index)
65
+ xpath = selector[:xpath] || build_xpath(selector)
66
+
67
+ if xpath
68
+ # could build xpath for selector
69
+ if idx
70
+ @wd.find_elements(:xpath, xpath)[idx]
71
+ else
72
+ @wd.find_element(:xpath, xpath)
73
+ end
74
+ else
75
+ # can't use xpath, probably a regexp in there
76
+ if idx
77
+ wd_find_by_regexp_selector(selector, :select)[idx]
78
+ else
79
+ wd_find_by_regexp_selector(selector, :find)
80
+ end
81
+ end
82
+ end
83
+
84
+ def find_all_by_multiple
85
+ selector = normalized_selector
86
+
87
+ if selector.has_key? :index
88
+ raise Error, "can't locate all elements by :index"
89
+ end
90
+
91
+ xpath = selector[:xpath] || build_xpath(selector)
92
+ if xpath
93
+ @wd.find_elements(:xpath, xpath)
94
+ else
95
+ wd_find_by_regexp_selector(selector, :select)
96
+ end
97
+ end
98
+
99
+ def wd_find_first_by(how, what)
100
+ if what.kind_of? String
101
+ @wd.find_element(how, what)
102
+ else
103
+ all_elements.find { |e| fetch_value(how, e) =~ what }
104
+ end
105
+ end
106
+
107
+ def wd_find_all_by(how, what)
108
+ if what.kind_of? String
109
+ @wd.find_elements(how, what)
110
+ else
111
+ all_elements.select { |e| fetch_value(how, e) =~ what }
112
+ end
113
+ end
114
+
115
+ def wd_find_by_regexp_selector(selector, method = :find)
116
+ rx_selector = delete_regexps_from(selector)
117
+ xpath = build_xpath(selector) || raise("internal error: unable to build xpath from #{@selector.inspect}")
118
+
119
+ elements = @wd.find_elements(:xpath, xpath)
120
+ elements.send(method) { |e| matches_selector?(rx_selector, e) }
121
+ end
122
+
123
+ def check_type(how, what)
124
+ case how
125
+ when :index
126
+ raise TypeError, "expected Fixnum, got #{what.class}" unless what.kind_of?(Fixnum)
127
+ else
128
+ unless [String, Regexp].any? { |t| what.kind_of? t }
129
+ raise TypeError, "expected String or Regexp, got #{what.inspect}:#{what.class}"
130
+ end
131
+ end
132
+ end
133
+
134
+ def fetch_value(how, element)
135
+ case how
136
+ when :text
137
+ element.text
138
+ when :tag_name
139
+ element.tag_name
140
+ else
141
+ element.attribute(how) rescue "" # TODO: rescue specific exception
142
+ end
143
+ end
144
+
145
+ def matches_selector?(selector, element)
146
+ # p :start => selector
147
+ selector.all? do |how, what|
148
+ # p :comparing => [how, what], :to => fetch_value(how, element)
149
+ what === fetch_value(how, element)
150
+ end
151
+ end
152
+
153
+ def normalized_selector
154
+ selector = {}
155
+
156
+ @selector.each do |how, what|
157
+ check_type(how, what)
158
+
159
+ how, what = normalize_selector(how, what)
160
+ selector[how] = what
161
+ end
162
+
163
+ selector
164
+ end
165
+
166
+ def normalize_selector(how, what)
167
+ case how
168
+ when :url
169
+ [:href, what]
170
+ when :caption
171
+ [:text, what]
172
+ when :class_name
173
+ [:class, what]
174
+ when :tag_name, :text, :xpath, :index, :class # include class since the attribute method is 'class_name'
175
+ [how, what]
176
+ else
177
+ assert_valid_as_attribute how
178
+ [how, what]
179
+ end
180
+ end
181
+
182
+ def delete_regexps_from(selector)
183
+ rx_selector = {}
184
+
185
+ selector.dup.each do |how, what|
186
+ next unless what.kind_of?(Regexp)
187
+ rx_selector[how] = what
188
+ selector.delete how
189
+ end
190
+
191
+ rx_selector
192
+ end
193
+
194
+ def assert_valid_as_attribute(attribute)
195
+ if @valid_attributes && !@valid_attributes.include?(attribute)
196
+ raise MissingWayOfFindingObjectException, "invalid attribute: #{attribute.inspect}"
197
+ end
198
+ end
199
+
200
+ def by_id
201
+ selector = @selector.dup
202
+ id = selector.delete(:id)
203
+ return unless id && id.kind_of?(String)
204
+
205
+ tag_name = selector.delete(:tag_name)
206
+ return unless selector.empty? # multiple attributes
207
+
208
+ element = @wd.find_element(:id, id)
209
+ return if tag_name && !tag_name_matches?(element, tag_name)
210
+
211
+ element
212
+ rescue WebDriver::Error::WebDriverError => wde
213
+ nil
214
+ end
215
+
216
+ def tag_name_matches?(element, tag_name)
217
+ tag_name === element.tag_name
218
+ end
219
+
220
+ def build_xpath(selectors)
221
+ return if selectors.values.any? { |e| e.kind_of? Regexp }
222
+
223
+ xpath = ".//"
224
+ xpath << (selectors.delete(:tag_name) || '*').to_s
225
+
226
+ idx = selectors.delete(:index)
227
+
228
+ # the remaining entries should be attributes
229
+ unless selectors.empty?
230
+ xpath << "[" << attribute_expression(selectors) << "]"
231
+ end
232
+
233
+ if idx
234
+ xpath << "[#{idx + 1}]"
235
+ end
236
+
237
+ p :xpath => xpath, :selectors => selectors if $DEBUG
238
+
239
+ xpath
240
+ end
241
+
242
+ def attribute_expression(selectors)
243
+ selectors.map do |key, val|
244
+ if val.kind_of?(Array)
245
+ "( " + val.map { |v| equal_pair(key, v) }.join(" or ") + " )"
246
+ else
247
+ equal_pair(key, val)
248
+ end
249
+ end.join(" and ")
250
+ end
251
+
252
+ def equal_pair(key, value)
253
+ "#{lhs_for(key)}='#{value}'"
254
+ end
255
+
256
+ def lhs_for(key)
257
+ case key
258
+ when :text, 'text'
259
+ 'normalize-space()'
260
+ when :href
261
+ # TODO: change this behaviour?
262
+ 'normalize-space(@href)'
263
+ else
264
+ "@#{key.to_s.gsub("_", "-")}"
265
+ end
266
+ end
267
+
268
+ end # ElementLocator
269
+ end # Watir
@@ -0,0 +1,25 @@
1
+ module Watir
2
+ class TableRowLocator < ElementLocator
3
+
4
+ def locate_all
5
+ find_all_by_multiple
6
+ end
7
+
8
+ def build_xpath(selectors)
9
+ return if selectors.values.any? { |e| e.kind_of? Regexp }
10
+
11
+ selectors.delete(:tag_name) || raise("internal error: no tag_name?!")
12
+
13
+ attr_expr = attribute_expression(selectors)
14
+
15
+
16
+ xpath = "./*/child::tr"
17
+ xpath << "[#{attr_expr}]" unless attr_expr.empty?
18
+
19
+ p :build_xpath => xpath if $DEBUG
20
+
21
+ xpath
22
+ end
23
+
24
+ end # TableRowLocator
25
+ end # Watir
@@ -0,0 +1,61 @@
1
+ module Watir
2
+ class TextFieldLocator < ElementLocator
3
+
4
+ NON_TEXT_TYPES = %w[file radio checkbox submit reset image button hidden url datetime date month week time datetime-local range color]
5
+ # TODO: better way of finding input text fields?
6
+ NEGATIVE_TYPE_EXPR = NON_TEXT_TYPES.map { |t| "@type!=#{t.inspect}" }.join(" and ")
7
+
8
+ def locate_all
9
+ find_all_by_multiple
10
+ end
11
+
12
+ def build_xpath(selectors)
13
+ return if selectors.values.any? { |e| e.kind_of? Regexp }
14
+
15
+ selectors.delete(:tag_name) || raise("internal error: no tag_name?!")
16
+
17
+ @building = :textarea
18
+ textarea_attr_exp = attribute_expression(selectors)
19
+
20
+ @building = :input
21
+ input_attr_exp = attribute_expression(selectors)
22
+
23
+ xpath = ".//textarea"
24
+ xpath << "[#{textarea_attr_exp}]" unless textarea_attr_exp.empty?
25
+ xpath << " | .//input[(not(@type) or (#{NEGATIVE_TYPE_EXPR}))"
26
+ xpath << " and #{input_attr_exp}" unless input_attr_exp.empty?
27
+ xpath << "]"
28
+
29
+ p :build_xpath => xpath if $DEBUG
30
+
31
+ xpath
32
+ end
33
+
34
+ def lhs_for(key)
35
+ if @building == :input && [:text, :label].include?(key)
36
+ "@value"
37
+ elsif @building == :textarea && [:value, :label].include?(key)
38
+ "text()"
39
+ else
40
+ super
41
+ end
42
+ end
43
+
44
+ def matches_selector?(rx_selector, element)
45
+ rx_selector = rx_selector.dup
46
+
47
+ [:text, :value, :label].each do |key|
48
+ if rx_selector.has_key?(key)
49
+ correct_key = element.tag_name == 'input' ? :value : :text
50
+ rx_selector[correct_key] = rx_selector.delete(key)
51
+ end
52
+ end
53
+
54
+ super
55
+ end
56
+
57
+ def tag_name_matches?(element, _)
58
+ !!(/^(input|textarea)$/ === element.tag_name)
59
+ end
60
+ end # TextFieldLocator
61
+ end # Watir
@@ -0,0 +1,23 @@
1
+ # encoding: utf-8
2
+ module Watir
3
+ module XpathSupport
4
+ include Selenium
5
+
6
+ def element_by_xpath(xpath)
7
+ e = wd.find_element(:xpath, xpath)
8
+ Watir.element_class_for(e.tag_name).new(self, :element, e)
9
+ rescue WebDriver::Error::WebDriverError
10
+ BaseElement.new(self, :xpath, xpath)
11
+ end
12
+
13
+ def elements_by_xpath(xpath)
14
+ # TODO: find the correct element class
15
+ wd.find_elements(:xpath, xpath).map do |e|
16
+ Watir.element_class_for(e.tag_name).new(self, :element, e)
17
+ end
18
+ rescue WebDriver::Error::WebDriverError
19
+ []
20
+ end
21
+
22
+ end # XpathSupport
23
+ end # Watir
@@ -0,0 +1,11 @@
1
+ # encoding: utf-8
2
+ require "#{File.dirname(__FILE__)}/spec_helper"
3
+
4
+ describe Watir::ElementLocator do
5
+ def setup(selector)
6
+ driver = mock("Driver")
7
+ locator = Watir::ElementLocator.new(driver, selector)
8
+
9
+ [driver, locator]
10
+ end
11
+ end
@@ -0,0 +1,16 @@
1
+ # encoding: utf-8
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
4
+
5
+ require 'rubygems'
6
+ require 'watir-webdriver'
7
+ require 'spec'
8
+ require 'spec/autorun'
9
+
10
+ include Watir
11
+ include Watir::Exception
12
+
13
+ if defined?(WatirSpec)
14
+ WatirSpec.browser_args = [:firefox]
15
+ WatirSpec.implementation = :webdriver
16
+ end
@@ -0,0 +1,78 @@
1
+ # encoding: utf-8
2
+ require File.dirname(__FILE__) + '/spec_helper'
3
+
4
+ describe "Area" do
5
+
6
+ before :each do
7
+ browser.goto(WatirSpec.files + "/images.html")
8
+ end
9
+
10
+ # Exists method
11
+ describe "#exist?" do
12
+ it "returns true if the area exists" do
13
+ browser.area(:id, "NCE").should exist
14
+ browser.area(:id, /NCE/).should exist
15
+ browser.area(:title, "Tables").should exist
16
+ browser.area(:title, /Tables/).should exist
17
+
18
+ bug "WTR-342", :watir do
19
+ browser.area(:url, "tables.html").should exist
20
+ browser.area(:url, /tables/).should exist
21
+ browser.area(:href, "tables.html").should exist
22
+ browser.area(:href, /tables/).should exist
23
+ end
24
+
25
+ browser.area(:index, 0).should exist
26
+ browser.area(:xpath, "//area[@id='NCE']").should exist
27
+ end
28
+
29
+ it "returns false if the area doesn't exist" do
30
+ browser.area(:id, "no_such_id").should_not exist
31
+ browser.area(:id, /no_such_id/).should_not exist
32
+ browser.area(:title, "no_such_title").should_not exist
33
+ browser.area(:title, /no_such_title/).should_not exist
34
+
35
+ bug "WTR-342", :watir do
36
+ browser.area(:url, "no_such_href").should_not exist
37
+ browser.area(:url, /no_such_href/).should_not exist
38
+ browser.area(:href, "tables.html").should exist
39
+ browser.area(:href, /tables/).should exist
40
+ end
41
+
42
+ browser.area(:index, 1337).should_not exist
43
+ browser.area(:xpath, "//area[@id='no_such_id']").should_not exist
44
+ end
45
+
46
+ it "raises TypeError when 'what' argument is invalid" do
47
+ lambda { browser.area(:id, 3.14).exists? }.should raise_error(TypeError)
48
+ end
49
+
50
+ it "raises MissingWayOfFindingObjectException when 'how' argument is invalid" do
51
+ lambda { browser.area(:no_such_how, 'some_value').exists? }.should raise_error(MissingWayOfFindingObjectException)
52
+ end
53
+ end
54
+
55
+ # Attribute methods
56
+ describe "#id" do
57
+ it "returns the id attribute" do
58
+ browser.area(:index, 0).id.should == "NCE"
59
+ end
60
+
61
+ it "returns an empty string if the element exists and the attribute doesn't" do
62
+ browser.area(:index, 2).id.should == ''
63
+ end
64
+
65
+ it "raises UnknownObjectException if the area doesn't exist" do
66
+ lambda { browser.area(:id, "no_such_id").id }.should raise_error(UnknownObjectException)
67
+ lambda { browser.area(:index, 1337).id }.should raise_error(UnknownObjectException)
68
+ end
69
+
70
+ end
71
+
72
+ describe "#respond_to?" do
73
+ it "returns true for all attribute methods" do
74
+ browser.area(:index, 0).should respond_to(:id)
75
+ end
76
+ end
77
+
78
+ end