watir-nokogiri 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. data/LICENSE +22 -0
  2. data/README.md +65 -0
  3. data/lib/watir-nokogiri.rb +69 -0
  4. data/lib/watir-nokogiri/aliases.rb +6 -0
  5. data/lib/watir-nokogiri/attribute_helper.rb +145 -0
  6. data/lib/watir-nokogiri/cell_container.rb +31 -0
  7. data/lib/watir-nokogiri/container.rb +50 -0
  8. data/lib/watir-nokogiri/document.rb +171 -0
  9. data/lib/watir-nokogiri/element_collection.rb +93 -0
  10. data/lib/watir-nokogiri/elements/button.rb +71 -0
  11. data/lib/watir-nokogiri/elements/checkbox.rb +61 -0
  12. data/lib/watir-nokogiri/elements/dlist.rb +12 -0
  13. data/lib/watir-nokogiri/elements/element.rb +319 -0
  14. data/lib/watir-nokogiri/elements/file_field.rb +45 -0
  15. data/lib/watir-nokogiri/elements/font.rb +11 -0
  16. data/lib/watir-nokogiri/elements/form.rb +17 -0
  17. data/lib/watir-nokogiri/elements/frame.rb +75 -0
  18. data/lib/watir-nokogiri/elements/generated.rb +2662 -0
  19. data/lib/watir-nokogiri/elements/hidden.rb +24 -0
  20. data/lib/watir-nokogiri/elements/image.rb +59 -0
  21. data/lib/watir-nokogiri/elements/input.rb +34 -0
  22. data/lib/watir-nokogiri/elements/link.rb +7 -0
  23. data/lib/watir-nokogiri/elements/option.rb +83 -0
  24. data/lib/watir-nokogiri/elements/radio.rb +44 -0
  25. data/lib/watir-nokogiri/elements/select.rb +126 -0
  26. data/lib/watir-nokogiri/elements/table.rb +44 -0
  27. data/lib/watir-nokogiri/elements/table_cell.rb +36 -0
  28. data/lib/watir-nokogiri/elements/table_row.rb +46 -0
  29. data/lib/watir-nokogiri/elements/table_section.rb +15 -0
  30. data/lib/watir-nokogiri/elements/text_area.rb +22 -0
  31. data/lib/watir-nokogiri/elements/text_field.rb +44 -0
  32. data/lib/watir-nokogiri/exception.rb +20 -0
  33. data/lib/watir-nokogiri/locators/button_locator.rb +54 -0
  34. data/lib/watir-nokogiri/locators/child_cell_locator.rb +24 -0
  35. data/lib/watir-nokogiri/locators/child_row_locator.rb +29 -0
  36. data/lib/watir-nokogiri/locators/element_locator.rb +298 -0
  37. data/lib/watir-nokogiri/locators/text_area_locator.rb +20 -0
  38. data/lib/watir-nokogiri/locators/text_field_locator.rb +71 -0
  39. data/lib/watir-nokogiri/row_container.rb +42 -0
  40. data/lib/watir-nokogiri/user_editable.rb +38 -0
  41. data/lib/watir-nokogiri/version.rb +3 -0
  42. data/lib/watir-nokogiri/xpath_support.rb +22 -0
  43. metadata +102 -0
@@ -0,0 +1,93 @@
1
+ module WatirNokogiri
2
+
3
+ #
4
+ # Base class for element collections.
5
+ #
6
+
7
+ class ElementCollection
8
+ include Enumerable
9
+
10
+ def initialize(parent, selector)
11
+ @parent = parent
12
+ @selector = selector
13
+ end
14
+
15
+ #
16
+ # Yields each element in collection.
17
+ #
18
+ # @yieldparam [WatirNokogiri::Element] element Iterate through the elements in this collection.
19
+ #
20
+
21
+ def each(&blk)
22
+ to_a.each(&blk)
23
+ end
24
+
25
+ #
26
+ # Returns number of elements in collection.
27
+ #
28
+ # @return [Fixnum]
29
+ #
30
+
31
+ def length
32
+ elements.length
33
+ end
34
+ alias_method :size, :length
35
+
36
+ #
37
+ # Get the element at the given index.
38
+ # Note that this is 0-indexed.
39
+ #
40
+ # @param [Fixnum] idx Index of wanted element, 0-indexed
41
+ # @return [WatirNokogiri::Element] Returns an instance of a WatirNokogiri::Element subclass
42
+ #
43
+
44
+ def [](idx)
45
+ to_a[idx] || element_class.new(@parent, :index => idx)
46
+ end
47
+
48
+ #
49
+ # First element of this collection
50
+ #
51
+ # @return [WatirNokogiri::Element] Returns an instance of a WatirNokogiri::Element subclass
52
+ #
53
+
54
+ def first
55
+ self[0]
56
+ end
57
+
58
+ #
59
+ # Last element of the collection
60
+ #
61
+ # @return [WatirNokogiri::Element] Returns an instance of a WatirNokogiri::Element subclass
62
+ #
63
+
64
+ def last
65
+ self[-1]
66
+ end
67
+
68
+ #
69
+ # This collection as an Array.
70
+ #
71
+ # @return [Array<WatirNokogiri::Element>]
72
+ #
73
+
74
+ def to_a()
75
+ @to_a ||= elements.map{ |e| element_class.new(@parent, :element => e) }
76
+ end
77
+
78
+ private
79
+
80
+ def elements()
81
+ @elements ||= locator_class.new(@parent.nokogiri, @selector, element_class.attribute_list).locate_all
82
+ end
83
+
84
+ def element_class()
85
+ Element
86
+ end
87
+
88
+ def locator_class()
89
+ ElementLocator
90
+ end
91
+
92
+ end
93
+ end
@@ -0,0 +1,71 @@
1
+ # encoding: utf-8
2
+ module WatirNokogiri
3
+
4
+ #
5
+ # Class representing button elements.
6
+ #
7
+ # This class covers both <button> and <input type="submit|reset|image|button" /> elements.
8
+ #
9
+
10
+ class Button < HTMLElement
11
+
12
+ # add the attributes from <input>
13
+ attributes WatirNokogiri::Input.typed_attributes
14
+
15
+ VALID_TYPES = %w[button reset submit image]
16
+
17
+ #
18
+ # Returns the text of the button.
19
+ #
20
+ # For input elements, returns the "value" attribute.
21
+ # For button elements, returns the inner text.
22
+ #
23
+ # @return [String]
24
+ #
25
+
26
+ def text
27
+ assert_exists
28
+
29
+ tn = @element.node_name.downcase
30
+
31
+ case tn
32
+ when 'input'
33
+ @element.get_attribute(:value)
34
+ when 'button'
35
+ @element.text
36
+ else
37
+ raise Exception::Error, "unknown tag name for button: #{tn}"
38
+ end
39
+ end
40
+
41
+ #
42
+ # Returns true if this element is enabled.
43
+ #
44
+ # @return [Boolean]
45
+ #
46
+
47
+ def enabled?
48
+ !disabled?
49
+ end
50
+
51
+ private
52
+
53
+ def locate
54
+ @parent.assert_exists
55
+ ButtonLocator.new(@parent.nokogiri, @selector, self.class.attribute_list).locate
56
+ end
57
+
58
+ end # Button
59
+
60
+ class ButtonCollection < ElementCollection
61
+ private
62
+
63
+ def locator_class
64
+ ButtonLocator
65
+ end
66
+
67
+ def element_class
68
+ Button
69
+ end
70
+ end # ButtonsCollection
71
+ end # Watir
@@ -0,0 +1,61 @@
1
+ # encoding: utf-8
2
+
3
+ module WatirNokogiri
4
+ class CheckBox < Input
5
+
6
+ #
7
+ # Sets checkbox to the given value.
8
+ #
9
+ # @example
10
+ # checkbox.set? #=> false
11
+ # checkbox.set
12
+ # checkbox.set? #=> true
13
+ # checkbox.set(false)
14
+ # checkbox.set? #=> false
15
+ #
16
+ # @param [Boolean] bool
17
+ #
18
+
19
+ def set(bool = true)
20
+ assert_exists
21
+ raise NotImplementedError, "not currently supported by WatirNokogiri"
22
+ end
23
+
24
+ #
25
+ # Returns true if the element is checked
26
+ # @return [Boolean]
27
+ #
28
+
29
+ def set?
30
+ assert_exists
31
+ !@element.get_attribute('checked').nil?
32
+ end
33
+
34
+ #
35
+ # Unsets checkbox.
36
+ #
37
+ # Same as +set(false)+
38
+ #
39
+
40
+ def clear
41
+ set false
42
+ end
43
+
44
+ end # CheckBox
45
+
46
+ module Container
47
+ def checkbox(*args)
48
+ CheckBox.new(self, extract_selector(args).merge(:tag_name => "input", :type => "checkbox"))
49
+ end
50
+
51
+ def checkboxes(*args)
52
+ CheckBoxCollection.new(self, extract_selector(args).merge(:tag_name => "input", :type => "checkbox"))
53
+ end
54
+ end # Container
55
+
56
+ class CheckBoxCollection < InputCollection
57
+ def element_class
58
+ CheckBox
59
+ end
60
+ end # CheckBoxCollection
61
+ end # Watir
@@ -0,0 +1,12 @@
1
+ module WatirNokogiri
2
+ class DList < HTMLElement
3
+
4
+ def to_hash
5
+ keys = dts.map { |e| e.text }
6
+ values = dds.map { |e| e.text }
7
+
8
+ Hash[keys.zip(values)]
9
+ end
10
+
11
+ end # DList
12
+ end # WatirNokogiri
@@ -0,0 +1,319 @@
1
+ # encoding: utf-8
2
+
3
+ module WatirNokogiri
4
+
5
+ #
6
+ # Base class for HTML elements.
7
+ #
8
+
9
+ class Element
10
+ extend AttributeHelper
11
+
12
+ include Exception
13
+ include Container
14
+
15
+ attributes :string => [:id, :class_name]
16
+
17
+ def initialize(parent, selector)
18
+ @parent = parent
19
+ @selector = selector
20
+ @element = nil
21
+
22
+ unless @selector.kind_of? Hash
23
+ raise ArgumentError, "invalid argument: #{selector.inspect}"
24
+ end
25
+ end
26
+
27
+ #
28
+ # Returns true if two elements are equal.
29
+ #
30
+ # @example
31
+ # html.a(:id => "foo") == html.a(:id => "foo")
32
+ # #=> true
33
+ #
34
+
35
+ def ==(other)
36
+ return false unless other.kind_of? self.class
37
+
38
+ assert_exists
39
+ @element == other.nokogiri
40
+ end
41
+ alias_method :eql?, :==
42
+
43
+ #
44
+ # Returns given attribute value of element.
45
+ #
46
+ # @example
47
+ # html.a(:id => "foo").attribute_value "href"
48
+ # #=> "http://watir.com"
49
+ #
50
+ # @param [String] attribute_name
51
+ # @return [String]
52
+ #
53
+
54
+ def attribute_value(attribute_name)
55
+ assert_exists
56
+ @element.get_attribute(attribute_name) || ''
57
+ end
58
+
59
+ def click(*modifiers)
60
+ assert_exists
61
+ raise "Not implemented"
62
+ end
63
+
64
+ #
65
+ # Returns the css path for the element
66
+ #
67
+
68
+ def css_path()
69
+ assert_exists
70
+ @element.css_path
71
+ end
72
+
73
+ #
74
+ # @api private
75
+ #
76
+
77
+ def document
78
+ @parent.document
79
+ end
80
+
81
+ #
82
+ # @api private
83
+ #
84
+
85
+ def driver
86
+ @parent.driver
87
+ end
88
+
89
+ #
90
+ # Returns true if element exists.
91
+ #
92
+ # @return [Boolean]
93
+ #
94
+
95
+ def exists?()
96
+ begin
97
+ assert_exists
98
+ return true
99
+ rescue UnknownObjectException, UnknownFrameException
100
+ return false
101
+ end
102
+ end
103
+ alias_method :exist?, :exists?
104
+
105
+ #
106
+ # Returns outer (inner + element itself) HTML code of element.
107
+ #
108
+ # @example
109
+ # html.div(:id => "foo").html
110
+ # #=> "<div id=\"foo\"><a>Click</a></div>"
111
+ #
112
+ # @return [String]
113
+ #
114
+
115
+ def html
116
+ assert_exists
117
+ @element.to_html
118
+ end
119
+
120
+ def id()
121
+ assert_exists
122
+ attribute_value('id')
123
+ end
124
+
125
+ def inspect()
126
+ if @selector.has_key?(:element)
127
+ '#<%s:0x%x located=%s selector=%s>' % [self.class, hash*2, !!@element, '{:element=>(nokogiri element)}']
128
+ else
129
+ '#<%s:0x%x located=%s selector=%s>' % [self.class, hash*2, !!@element, @selector.inspect]
130
+ end
131
+ end
132
+
133
+ #
134
+ # @api private
135
+ #
136
+
137
+ def nokogiri()
138
+ assert_exists
139
+ @element
140
+ end
141
+
142
+ #
143
+ # Returns given style property of this element.
144
+ #
145
+ # @example
146
+ # html.a(:id => "foo").style
147
+ # #=> "display: block"
148
+ # html.a(:id => "foo").style "display"
149
+ # #=> "block"
150
+ #
151
+ # @param [String] property
152
+ # @return [String]
153
+ #
154
+
155
+ def style(property = nil)
156
+ assert_exists
157
+ styles = attribute_value('style').to_s.strip
158
+ if property
159
+ properties = Hash[styles.downcase.split(";").map { |p| p.split(":").map(&:strip) }]
160
+ properties[property]
161
+ else
162
+ styles
163
+ end
164
+ end
165
+
166
+ #
167
+ # Returns parent element of current element.
168
+ #
169
+
170
+ def parent
171
+ assert_exists
172
+
173
+ e = @element.parent
174
+
175
+ if e.kind_of?(Nokogiri::XML::Element)
176
+ WatirNokogiri.element_class_for(e.node_name.downcase).new(@parent, :element => e)
177
+ end
178
+ end
179
+
180
+ #
181
+ # Returns true if the element exists and is visible on the page.
182
+ #
183
+ # @return [Boolean]
184
+ #
185
+
186
+ def present?
187
+ assert_exists
188
+ raise "Not implemented"
189
+ end
190
+
191
+ #
192
+ # Returns tag name of the element.
193
+ #
194
+ # @return [String]
195
+ #
196
+
197
+ def tag_name
198
+ assert_exists
199
+ @element.node_name.downcase
200
+ end
201
+
202
+ #
203
+ # Returns the text of the element.
204
+ #
205
+ # @return [String]
206
+ #
207
+
208
+ def text()
209
+ assert_exists
210
+ @element.text.strip.gsub(/\s+/, ' ')
211
+ end
212
+
213
+ #
214
+ # Cast this Element instance to a more specific subtype.
215
+ #
216
+ # @example
217
+ # browser.element(:xpath => "//input[@type='submit']").to_subtype
218
+ # #=> #<WatirNokogiri::Button>
219
+ #
220
+
221
+ def to_subtype
222
+ elem = nokogiri()
223
+ tag_name = elem.node_name.downcase
224
+
225
+ klass = nil
226
+
227
+ if tag_name == "input"
228
+ klass = case elem.get_attribute(:type)
229
+ when *Button::VALID_TYPES
230
+ Button
231
+ when 'checkbox'
232
+ CheckBox
233
+ when 'radio'
234
+ Radio
235
+ when 'file'
236
+ FileField
237
+ else
238
+ TextField
239
+ end
240
+ else
241
+ klass = WatirNokogiri.element_class_for(tag_name)
242
+ end
243
+
244
+ klass.new(@parent, :element => elem)
245
+ end
246
+
247
+ #
248
+ # Returns value of the element.
249
+ #
250
+ # @return [String]
251
+ #
252
+
253
+ def value
254
+ assert_exists
255
+ attribute_value('value')
256
+ end
257
+
258
+ #
259
+ # Returns true if this element is visible on the page.
260
+ #
261
+ # @return [Boolean]
262
+ #
263
+
264
+ def visible?
265
+ assert_exists
266
+ raise "Not implemented"
267
+ end
268
+
269
+ #
270
+ # Returns the xpath of the current element.
271
+ #
272
+
273
+ def xpath()
274
+ assert_exists
275
+ @element.path
276
+ end
277
+
278
+ protected
279
+
280
+ def assert_exists()
281
+ return if @element
282
+
283
+ @element = @selector[:element] || locate
284
+
285
+ unless @element
286
+ raise UnknownObjectException, "unable to locate element, using #{@selector.inspect}"
287
+ end
288
+ end
289
+
290
+ def locate
291
+ @parent.assert_exists
292
+ locator_class.new(@parent.nokogiri, @selector, self.class.attribute_list).locate
293
+ end
294
+
295
+ private
296
+
297
+ #
298
+ # Returns attribute value if attribute exists; nil otherwise
299
+ #
300
+ def attribute?(attribute)
301
+ assert_exists
302
+ @element.get_attribute(attribute.to_s.downcase)
303
+ end
304
+
305
+ def locator_class
306
+ ElementLocator
307
+ end
308
+
309
+ def method_missing(meth, *args, &blk)
310
+ method = meth.to_s
311
+ if method =~ /^data_(.+)$/
312
+ attribute_value(method.gsub(/_/, '-'), *args)
313
+ else
314
+ super
315
+ end
316
+ end
317
+ end
318
+
319
+ end