ayanko-watir-webdriver 0.1.1.1

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 (74) hide show
  1. data/.document +5 -0
  2. data/.gitignore +5 -0
  3. data/.gitmodules +3 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE +20 -0
  6. data/README.rdoc +55 -0
  7. data/Rakefile +139 -0
  8. data/VERSION +1 -0
  9. data/lib/watir-webdriver.rb +71 -0
  10. data/lib/watir-webdriver/attribute_helper.rb +128 -0
  11. data/lib/watir-webdriver/browser.rb +164 -0
  12. data/lib/watir-webdriver/browserbot.js +49 -0
  13. data/lib/watir-webdriver/cell_container.rb +19 -0
  14. data/lib/watir-webdriver/container.rb +40 -0
  15. data/lib/watir-webdriver/core_ext/string.rb +22 -0
  16. data/lib/watir-webdriver/element_collection.rb +96 -0
  17. data/lib/watir-webdriver/elements/button.rb +75 -0
  18. data/lib/watir-webdriver/elements/checkbox.rb +73 -0
  19. data/lib/watir-webdriver/elements/element.rb +265 -0
  20. data/lib/watir-webdriver/elements/file_field.rb +69 -0
  21. data/lib/watir-webdriver/elements/font.rb +11 -0
  22. data/lib/watir-webdriver/elements/form.rb +17 -0
  23. data/lib/watir-webdriver/elements/frame.rb +110 -0
  24. data/lib/watir-webdriver/elements/generated.rb +2541 -0
  25. data/lib/watir-webdriver/elements/hidden.rb +24 -0
  26. data/lib/watir-webdriver/elements/image.rb +51 -0
  27. data/lib/watir-webdriver/elements/input.rb +42 -0
  28. data/lib/watir-webdriver/elements/link.rb +7 -0
  29. data/lib/watir-webdriver/elements/option.rb +55 -0
  30. data/lib/watir-webdriver/elements/radio.rb +49 -0
  31. data/lib/watir-webdriver/elements/select.rb +216 -0
  32. data/lib/watir-webdriver/elements/table.rb +37 -0
  33. data/lib/watir-webdriver/elements/table_cell.rb +36 -0
  34. data/lib/watir-webdriver/elements/table_row.rb +45 -0
  35. data/lib/watir-webdriver/elements/table_section.rb +9 -0
  36. data/lib/watir-webdriver/elements/text_field.rb +97 -0
  37. data/lib/watir-webdriver/exception.rb +21 -0
  38. data/lib/watir-webdriver/extensions/alerts.rb +69 -0
  39. data/lib/watir-webdriver/extensions/cookies.rb +39 -0
  40. data/lib/watir-webdriver/extensions/firefox/webdriver.xpi +0 -0
  41. data/lib/watir-webdriver/extensions/nokogiri.rb +14 -0
  42. data/lib/watir-webdriver/extensions/performance.rb +54 -0
  43. data/lib/watir-webdriver/extensions/wait.rb +141 -0
  44. data/lib/watir-webdriver/html.rb +19 -0
  45. data/lib/watir-webdriver/html/generator.rb +112 -0
  46. data/lib/watir-webdriver/html/idl_sorter.rb +49 -0
  47. data/lib/watir-webdriver/html/spec_extractor.rb +111 -0
  48. data/lib/watir-webdriver/html/util.rb +22 -0
  49. data/lib/watir-webdriver/html/visitor.rb +174 -0
  50. data/lib/watir-webdriver/locators/button_locator.rb +74 -0
  51. data/lib/watir-webdriver/locators/child_cell_locator.rb +32 -0
  52. data/lib/watir-webdriver/locators/child_row_locator.rb +37 -0
  53. data/lib/watir-webdriver/locators/element_locator.rb +352 -0
  54. data/lib/watir-webdriver/locators/text_field_locator.rb +65 -0
  55. data/lib/watir-webdriver/row_container.rb +34 -0
  56. data/lib/watir-webdriver/window_switching.rb +105 -0
  57. data/lib/watir-webdriver/xpath_support.rb +28 -0
  58. data/lib/yard/handlers/watir.rb +57 -0
  59. data/spec/alert_spec.rb +49 -0
  60. data/spec/browser_spec.rb +42 -0
  61. data/spec/container_spec.rb +42 -0
  62. data/spec/element_locator_spec.rb +304 -0
  63. data/spec/element_spec.rb +13 -0
  64. data/spec/html/alerts.html +11 -0
  65. data/spec/html/keylogger.html +15 -0
  66. data/spec/html/wait.html +27 -0
  67. data/spec/implementation.rb +17 -0
  68. data/spec/input_spec.rb +39 -0
  69. data/spec/locator_spec_helper.rb +51 -0
  70. data/spec/spec_helper.rb +14 -0
  71. data/spec/wait_spec.rb +98 -0
  72. data/support/html5.html +90243 -0
  73. data/watir-webdriver.gemspec +59 -0
  74. metadata +238 -0
@@ -0,0 +1,49 @@
1
+ // stolen from injectableSelenium.js in WebDriver
2
+ var browserbot = {
3
+
4
+ triggerEvent: function(element, eventType, canBubble, controlKeyDown, altKeyDown, shiftKeyDown, metaKeyDown) {
5
+ canBubble = (typeof(canBubble) == undefined) ? true: canBubble;
6
+ if (element.fireEvent && element.ownerDocument && element.ownerDocument.createEventObject) {
7
+ // IE
8
+ var evt = this.createEventObject(element, controlKeyDown, altKeyDown, shiftKeyDown, metaKeyDown);
9
+ element.fireEvent('on' + eventType, evt);
10
+ } else {
11
+ var evt = document.createEvent('HTMLEvents');
12
+
13
+ try {
14
+ evt.shiftKey = shiftKeyDown;
15
+ evt.metaKey = metaKeyDown;
16
+ evt.altKey = altKeyDown;
17
+ evt.ctrlKey = controlKeyDown;
18
+ } catch(e) {
19
+ // Nothing sane to do
20
+ }
21
+
22
+ evt.initEvent(eventType, canBubble, true);
23
+ return element.dispatchEvent(evt);
24
+ }
25
+ },
26
+
27
+ getVisibleText: function() {
28
+ var selection = getSelection();
29
+ var range = document.createRange();
30
+ range.selectNodeContents(document.documentElement);
31
+ selection.addRange(range);
32
+ var string = selection.toString();
33
+ selection.removeAllRanges();
34
+
35
+ return string;
36
+ },
37
+
38
+ getOuterHTML: function(element) {
39
+ if (element.outerHTML) {
40
+ return element.outerHTML;
41
+ } else if (typeof(XMLSerializer) != undefined) {
42
+ return new XMLSerializer().serializeToString(element);
43
+ } else {
44
+ throw "can't get outerHTML in this browser";
45
+ }
46
+ }
47
+
48
+
49
+ };
@@ -0,0 +1,19 @@
1
+ module Watir
2
+ module CellContainer
3
+
4
+ def cell(*args)
5
+ cell = TableCell.new(self, extract_selector(args).merge(:tag_name => /^(th|td)$/))
6
+ cell.locator_class = ChildCellLocator
7
+
8
+ cell
9
+ end
10
+
11
+ def cells(*args)
12
+ cells = TableCellCollection.new(self, extract_selector(args).merge(:tag_name => /^(th|td)$/))
13
+ cells.locator_class = ChildCellLocator
14
+
15
+ cells
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,40 @@
1
+ # encoding: utf-8
2
+ module Watir
3
+ module Container
4
+ include XpathSupport
5
+
6
+ def element(*args)
7
+ HTMLElement.new(self, extract_selector(args))
8
+ end
9
+
10
+ def elements(*args)
11
+ HTMLElementCollection.new(self, extract_selector(args))
12
+ end
13
+
14
+ private
15
+
16
+ def browserbot(function_name, *arguments)
17
+ script = browserbot_script + "return browserbot.#{function_name}.apply(browserbot, arguments);"
18
+ driver.execute_script(script, *arguments)
19
+ end
20
+
21
+ def browserbot_script
22
+ @browserbot_script ||= File.read("#{File.dirname(__FILE__)}/browserbot.js")
23
+ end
24
+
25
+ def extract_selector(selectors)
26
+ case selectors.size
27
+ when 2
28
+ return { selectors[0] => selectors[1] }
29
+ when 1
30
+ obj = selectors.first
31
+ return obj if obj.kind_of? Hash
32
+ when 0
33
+ return {}
34
+ end
35
+
36
+ raise ArgumentError, "expected Hash or (:how, 'what'), got #{selectors.inspect}"
37
+ end
38
+
39
+ end # Container
40
+ end # Watir
@@ -0,0 +1,22 @@
1
+ # encoding: utf-8
2
+ class String
3
+ #
4
+ # Convert from camel case to snake case
5
+ #
6
+ # 'FooBar'.snake_case # => "foo_bar"
7
+ #
8
+
9
+ def snake_case
10
+ gsub(/\B[A-Z][^A-Z]/, '_\&').downcase.gsub(' ', '_')
11
+ end
12
+
13
+ #
14
+ # Convert from snake case to camel case
15
+ #
16
+ # 'foo_bar'.camel_case # => "FooBar"
17
+ #
18
+
19
+ def camel_case
20
+ split('_').map { |e| e.capitalize }.join
21
+ end
22
+ end
@@ -0,0 +1,96 @@
1
+ # encoding: utf-8
2
+ module Watir
3
+
4
+ #
5
+ # Base class for element collections.
6
+ #
7
+
8
+ class ElementCollection
9
+ include Enumerable
10
+
11
+ def initialize(parent, selector)
12
+ @parent = parent
13
+ @selector = selector
14
+ end
15
+
16
+ #
17
+ # @yieldparam [Watir::Element] element Iterate through the elements in this collection.
18
+ #
19
+
20
+ def each(&blk)
21
+ to_a.each(&blk)
22
+ end
23
+
24
+ #
25
+ # @return [Fixnum] The number of elements in this collection.
26
+ #
27
+
28
+ def length
29
+ elements.length
30
+ end
31
+ alias_method :size, :length
32
+
33
+ #
34
+ # Get the element at the given index.
35
+ # Note that this is 0-indexed and not compatible with older Watir implementations.
36
+ #
37
+ # Also note that because of Watir's lazy loading, this will return an Element
38
+ # instance even if the index is out of bounds.
39
+ #
40
+ # @param [Fixnum] n Index of wanted element, 0-indexed
41
+ # @return [Watir::Element] Returns an instance of a Watir::Element subclass
42
+ #
43
+
44
+
45
+ def [](idx)
46
+ to_a[idx] || element_class.new(@parent, :index => idx)
47
+ end
48
+
49
+ #
50
+ # First element of this collection
51
+ #
52
+ # @return [Watir::Element] Returns an instance of a Watir::Element subclass
53
+ #
54
+
55
+ def first
56
+ self[0]
57
+ end
58
+
59
+ #
60
+ # Last element of the collection
61
+ #
62
+ # @return [Watir::Element] Returns an instance of a Watir::Element subclass
63
+ #
64
+
65
+ def last
66
+ self[-1]
67
+ end
68
+
69
+ #
70
+ # This collection as an Array
71
+ #
72
+ # @return [Array<Watir::Element>]
73
+ #
74
+
75
+ def to_a
76
+ # TODO: optimize - lazy element_class instance?
77
+ @to_a ||= elements.map { |e| element_class.new(@parent, :element => e) }
78
+ end
79
+
80
+ private
81
+
82
+ def elements
83
+ @elements ||= locator_class.new(
84
+ @parent.wd,
85
+ @selector,
86
+ element_class.attribute_list
87
+ ).locate_all
88
+ end
89
+
90
+ # overridable by subclasses
91
+ def locator_class
92
+ ElementLocator
93
+ end
94
+
95
+ end # ElementCollection
96
+ end # Watir
@@ -0,0 +1,75 @@
1
+ # encoding: utf-8
2
+ module Watir
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 Watir::Input.typed_attributes
14
+
15
+ VALID_TYPES = %w[button reset submit image]
16
+
17
+ def self.from(parent, element)
18
+ if element.tag_name == "button" ||
19
+ element.tag_name == "input" && VALID_TYPES.include?(element.attribute(:type))
20
+ Button.new(parent, :element => element)
21
+ else
22
+ raise TypeError, "expected button or input[@type=#{VALID_TYPES.join("|")}] for #{element.inspect}"
23
+ end
24
+ end
25
+
26
+ #
27
+ # Returns the text of the button.
28
+ #
29
+ # For input elements, returns the "value" attribute.
30
+ # For button elements, returns the inner text.
31
+ #
32
+
33
+ def text
34
+ assert_exists
35
+ case @element.tag_name
36
+ when 'input'
37
+ @element.attribute(:value)
38
+ when 'button'
39
+ @element.text
40
+ else
41
+ raise Exception::Error, "unknown tag name for button: #{@element.tag_name}"
42
+ end
43
+ end
44
+
45
+ #
46
+ # Returns true if this element is enabled
47
+ #
48
+ # @return [Boolean]
49
+ #
50
+
51
+ def enabled?
52
+ !disabled?
53
+ end
54
+
55
+ private
56
+
57
+ def locate
58
+ @parent.assert_exists
59
+ ButtonLocator.new(@parent.wd, @selector, self.class.attribute_list).locate
60
+ end
61
+
62
+ end # Button
63
+
64
+ class ButtonCollection < ElementCollection
65
+ private
66
+
67
+ def locator_class
68
+ ButtonLocator
69
+ end
70
+
71
+ def element_class
72
+ Button
73
+ end
74
+ end # ButtonsCollection
75
+ end # Watir
@@ -0,0 +1,73 @@
1
+ # encoding: utf-8
2
+
3
+ module Watir
4
+ class CheckBox < Input
5
+
6
+ def self.from(parent, element)
7
+ if element.attribute(:type) != "checkbox"
8
+ raise TypeError, "expected type=checkbox for #{element.inspect}"
9
+ end
10
+
11
+ super
12
+ end
13
+
14
+ #
15
+ # Set this checkbox to the given value
16
+ #
17
+ # Example:
18
+ #
19
+ # checkbox.set? #=> false
20
+ # checkbox.set
21
+ # checkbox.set? #=> true
22
+ # checkbox.set(false)
23
+ # checkbox.set? #=> false
24
+ #
25
+
26
+ def set(bool = true)
27
+ assert_exists
28
+ assert_enabled
29
+
30
+ if @element.selected?
31
+ @element.click unless bool
32
+ else
33
+ @element.click if bool
34
+ end
35
+ end
36
+
37
+ #
38
+ # returns true if the element is checked
39
+ # @return [Boolean]
40
+ #
41
+
42
+ def set?
43
+ assert_exists
44
+ @element.selected?
45
+ end
46
+
47
+ #
48
+ # Unset this checkbox.
49
+ #
50
+ # Same as +set(false)+
51
+ #
52
+
53
+ def clear
54
+ set false
55
+ end
56
+ end # CheckBox
57
+
58
+ module Container
59
+ def checkbox(*args)
60
+ CheckBox.new(self, extract_selector(args).merge(:tag_name => "input", :type => "checkbox"))
61
+ end
62
+
63
+ def checkboxes(*args)
64
+ CheckBoxCollection.new(self, extract_selector(args).merge(:tag_name => "input", :type => "checkbox"))
65
+ end
66
+ end # Container
67
+
68
+ class CheckBoxCollection < InputCollection
69
+ def element_class
70
+ CheckBox
71
+ end
72
+ end # CheckBoxCollection
73
+ end
@@ -0,0 +1,265 @@
1
+ # encoding: utf-8
2
+
3
+ module Watir
4
+
5
+ #
6
+ # Base class for HTML elements.
7
+ #
8
+
9
+ class Element
10
+ include Exception
11
+ include Container
12
+ include Selenium
13
+ extend AttributeHelper
14
+
15
+ def initialize(parent, selector)
16
+ @parent = parent
17
+ @selector = selector
18
+
19
+ unless @selector.kind_of? Hash
20
+ raise ArgumentError, "invalid argument: #{selector.inspect}"
21
+ end
22
+
23
+ if @selector.has_key?(:element)
24
+ @element = @selector[:element]
25
+ end
26
+ end
27
+
28
+ def exists?
29
+ assert_exists
30
+ true
31
+ rescue UnknownObjectException, UnknownFrameException
32
+ false
33
+ end
34
+ alias_method :exist?, :exists?
35
+
36
+ def inspect
37
+ if @selector.has_key?(:element)
38
+ '#<%s:0x%x located=%s selector=%s>' % [self.class, hash*2, !!@element, '{:element=>(webdriver element)}']
39
+ else
40
+ '#<%s:0x%x located=%s selector=%s>' % [self.class, hash*2, !!@element, selector_string]
41
+ end
42
+ end
43
+
44
+ def ==(other)
45
+ return false unless other.kind_of? self.class
46
+
47
+ assert_exists
48
+ @element == other.element
49
+ end
50
+ alias_method :eql?, :==
51
+
52
+ def hash
53
+ @element ? @element.hash : super
54
+ end
55
+
56
+ def text
57
+ assert_exists
58
+ @element.text
59
+ end
60
+
61
+ def tag_name
62
+ assert_exists
63
+ @element.tag_name
64
+ end
65
+
66
+ def click
67
+ assert_exists
68
+ assert_enabled
69
+ @element.click
70
+ run_checkers
71
+ end
72
+
73
+ def double_click
74
+ assert_exists
75
+ raise NotImplementedError, "need support in WebDriver"
76
+
77
+ @element.double_click
78
+ run_checkers
79
+ end
80
+
81
+ def right_click
82
+ assert_exists
83
+ raise NotImplementedError, "need support in WebDriver"
84
+
85
+ @element.right_click
86
+ run_checkers
87
+ end
88
+
89
+ def flash
90
+ original_color = style("backgroundColor")
91
+
92
+ 10.times do |n|
93
+ color = (n % 2 == 0) ? "red" : original_color
94
+ driver.execute_script("arguments[0].style.backgroundColor = '#{color}'", @element)
95
+ end
96
+ end
97
+
98
+ def value
99
+ assert_exists
100
+
101
+ begin
102
+ @element.value || ''
103
+ rescue WebDriver::Error::ElementNotEnabledError
104
+ ""
105
+ end
106
+ end
107
+
108
+ def attribute_value(attribute_name)
109
+ assert_exists
110
+ @element.attribute attribute_name
111
+ end
112
+
113
+ def html
114
+ assert_exists
115
+ browserbot('getOuterHTML', @element).strip
116
+ end
117
+
118
+ def send_keys(*args)
119
+ assert_exists
120
+ @element.send_keys(*args)
121
+ end
122
+
123
+ #
124
+ # Note: Firefox queues focus events until the window actually has focus.
125
+ #
126
+ # See http://code.google.com/p/selenium/issues/detail?id=157
127
+ #
128
+
129
+ def focus
130
+ assert_exists
131
+ driver.execute_script "return arguments[0].focus()", @element
132
+ end
133
+
134
+ def fire_event(event_name, bubble = false)
135
+ assert_exists
136
+ event_name = event_name.to_s.sub(/^on/, '')
137
+ browserbot('triggerEvent', @element, event_name, bubble)
138
+ end
139
+
140
+ def parent
141
+ assert_exists
142
+
143
+ e = driver.execute_script "return arguments[0].parentNode", @element
144
+
145
+ if e.kind_of?(WebDriver::Element)
146
+ Watir.element_class_for(e.tag_name).new(@parent, :element => e)
147
+ end
148
+ end
149
+
150
+ def driver
151
+ @parent.driver
152
+ end
153
+
154
+ def element
155
+ assert_exists
156
+ @element
157
+ end
158
+ alias_method :wd, :element # ensures duck typing with Browser
159
+
160
+ def visible?
161
+ assert_exists
162
+ @element.displayed?
163
+ end
164
+
165
+ def style(property = nil)
166
+ if property
167
+ assert_exists
168
+ @element.style property
169
+ else
170
+ attribute_value("style") || ''
171
+ end
172
+ end
173
+
174
+ def run_checkers
175
+ @parent.run_checkers
176
+ end
177
+
178
+ #
179
+ # Cast this Element instance to a more specific subtype.
180
+ #
181
+ # Example:
182
+ #
183
+ # browser.element(:xpath => "//input[@type='submit']").to_subtype #=> #<Watir::Button>
184
+ #
185
+
186
+ def to_subtype
187
+ elem = element()
188
+ tag_name = elem.tag_name
189
+
190
+ klass = nil
191
+
192
+ if tag_name == "input"
193
+ klass = case elem.attribute(:type)
194
+ when *Button::VALID_TYPES
195
+ Button
196
+ when 'checkbox'
197
+ CheckBox
198
+ when 'radio'
199
+ Radio
200
+ when 'file'
201
+ FileField
202
+ else
203
+ TextField
204
+ end
205
+ else
206
+ klass = Watir.element_class_for(tag_name)
207
+ end
208
+
209
+ klass.new(@parent, :element => elem)
210
+ end
211
+
212
+ protected
213
+
214
+ def assert_exists
215
+ @element ||= locate
216
+
217
+ unless @element
218
+ raise UnknownObjectException, "unable to locate element, using #{selector_string}"
219
+ end
220
+ end
221
+
222
+ def browser
223
+ @parent.browser
224
+ end
225
+
226
+ def locate
227
+ @parent.assert_exists
228
+ locator_class.new(@parent.wd, @selector, self.class.attribute_list).locate
229
+ end
230
+
231
+ private
232
+
233
+ def locator_class
234
+ ElementLocator
235
+ end
236
+
237
+ def selector_string
238
+ @selector.inspect
239
+ end
240
+
241
+ def attribute?(attribute)
242
+ assert_exists
243
+ driver.execute_script "return !!arguments[0].getAttributeNode(arguments[1]);", @element, attribute.to_s.downcase
244
+ end
245
+
246
+ def assert_enabled
247
+ raise ObjectDisabledException, "object is disabled #{selector_string}" unless @element.enabled?
248
+ end
249
+
250
+ def assert_writable
251
+ assert_enabled
252
+ raise ObjectReadOnlyException if respond_to?(:readonly?) && readonly?
253
+ end
254
+
255
+ def method_missing(meth, *args, &blk)
256
+ method = meth.to_s
257
+ if method =~ /^data_(.+)$/
258
+ attribute_value(method.gsub(/_/, '-'), *args)
259
+ else
260
+ super
261
+ end
262
+ end
263
+
264
+ end # Element
265
+ end # Watir