ayanko-watir-webdriver 0.1.1.1

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