watir-webdriver 0.0.1.dev

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