watir 5.0.0 → 6.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (118) hide show
  1. checksums.yaml +4 -4
  2. data/.document +5 -0
  3. data/.gitignore +21 -0
  4. data/.gitmodules +3 -0
  5. data/.travis.yml +35 -0
  6. data/CHANGES.md +1756 -0
  7. data/Gemfile +12 -0
  8. data/LICENSE +23 -0
  9. data/README.md +92 -0
  10. data/Rakefile +161 -32
  11. data/lib/watir.rb +127 -1
  12. data/lib/watir/after_hooks.rb +132 -0
  13. data/lib/watir/alert.rb +104 -0
  14. data/lib/watir/aliases.rb +6 -0
  15. data/lib/watir/atoms.rb +24 -0
  16. data/lib/watir/atoms/README +3 -0
  17. data/lib/watir/atoms/fireEvent.js +29 -0
  18. data/lib/watir/atoms/getAttribute.js +18 -0
  19. data/lib/watir/atoms/getInnerHtml.js +18 -0
  20. data/lib/watir/atoms/getOuterHtml.js +18 -0
  21. data/lib/watir/atoms/getParentElement.js +17 -0
  22. data/lib/watir/atoms/selectText.js +61 -0
  23. data/lib/watir/attribute_helper.rb +98 -0
  24. data/lib/watir/browser.rb +346 -0
  25. data/lib/watir/cell_container.rb +25 -0
  26. data/lib/watir/container.rb +51 -0
  27. data/lib/watir/cookies.rb +132 -0
  28. data/lib/watir/element_collection.rb +126 -0
  29. data/lib/watir/elements/area.rb +12 -0
  30. data/lib/watir/elements/button.rb +37 -0
  31. data/lib/watir/elements/cell.rb +17 -0
  32. data/lib/watir/elements/checkbox.rb +54 -0
  33. data/lib/watir/elements/dlist.rb +12 -0
  34. data/lib/watir/elements/element.rb +646 -0
  35. data/lib/watir/elements/file_field.rb +41 -0
  36. data/lib/watir/elements/font.rb +11 -0
  37. data/lib/watir/elements/form.rb +17 -0
  38. data/lib/watir/elements/hidden.rb +20 -0
  39. data/lib/watir/elements/html_elements.rb +2063 -0
  40. data/lib/watir/elements/iframe.rb +163 -0
  41. data/lib/watir/elements/image.rb +62 -0
  42. data/lib/watir/elements/input.rb +7 -0
  43. data/lib/watir/elements/link.rb +18 -0
  44. data/lib/watir/elements/option.rb +74 -0
  45. data/lib/watir/elements/radio.rb +42 -0
  46. data/lib/watir/elements/row.rb +17 -0
  47. data/lib/watir/elements/select.rb +238 -0
  48. data/lib/watir/elements/svg_elements.rb +667 -0
  49. data/lib/watir/elements/table.rb +42 -0
  50. data/lib/watir/elements/table_cell.rb +6 -0
  51. data/lib/watir/elements/table_row.rb +15 -0
  52. data/lib/watir/elements/table_section.rb +15 -0
  53. data/lib/watir/elements/text_area.rb +5 -0
  54. data/lib/watir/elements/text_field.rb +37 -0
  55. data/lib/watir/exception.rb +17 -0
  56. data/lib/watir/extensions/nokogiri.rb +14 -0
  57. data/lib/watir/extensions/select_text.rb +10 -0
  58. data/lib/watir/generator.rb +3 -0
  59. data/lib/watir/generator/base.rb +11 -0
  60. data/lib/watir/generator/base/generator.rb +115 -0
  61. data/lib/watir/generator/base/idl_sorter.rb +47 -0
  62. data/lib/watir/generator/base/spec_extractor.rb +138 -0
  63. data/lib/watir/generator/base/util.rb +21 -0
  64. data/lib/watir/generator/base/visitor.rb +157 -0
  65. data/lib/watir/generator/html.rb +15 -0
  66. data/lib/watir/generator/html/generator.rb +36 -0
  67. data/lib/watir/generator/html/spec_extractor.rb +50 -0
  68. data/lib/watir/generator/html/visitor.rb +21 -0
  69. data/lib/watir/generator/svg.rb +7 -0
  70. data/lib/watir/generator/svg/generator.rb +38 -0
  71. data/lib/watir/generator/svg/spec_extractor.rb +46 -0
  72. data/lib/watir/generator/svg/visitor.rb +21 -0
  73. data/lib/watir/has_window.rb +53 -0
  74. data/lib/watir/locators.rb +22 -0
  75. data/lib/watir/locators/button/locator.rb +38 -0
  76. data/lib/watir/locators/button/selector_builder.rb +27 -0
  77. data/lib/watir/locators/button/selector_builder/xpath.rb +29 -0
  78. data/lib/watir/locators/button/validator.rb +15 -0
  79. data/lib/watir/locators/cell/locator.rb +17 -0
  80. data/lib/watir/locators/cell/selector_builder.rb +24 -0
  81. data/lib/watir/locators/element/locator.rb +249 -0
  82. data/lib/watir/locators/element/selector_builder.rb +147 -0
  83. data/lib/watir/locators/element/selector_builder/css.rb +65 -0
  84. data/lib/watir/locators/element/selector_builder/xpath.rb +72 -0
  85. data/lib/watir/locators/element/validator.rb +23 -0
  86. data/lib/watir/locators/row/locator.rb +17 -0
  87. data/lib/watir/locators/row/selector_builder.rb +29 -0
  88. data/lib/watir/locators/text_area/locator.rb +13 -0
  89. data/lib/watir/locators/text_area/selector_builder.rb +22 -0
  90. data/lib/watir/locators/text_field/locator.rb +44 -0
  91. data/lib/watir/locators/text_field/selector_builder.rb +34 -0
  92. data/lib/watir/locators/text_field/selector_builder/xpath.rb +19 -0
  93. data/lib/watir/locators/text_field/validator.rb +20 -0
  94. data/lib/watir/row_container.rb +36 -0
  95. data/lib/watir/screenshot.rb +50 -0
  96. data/lib/watir/user_editable.rb +38 -0
  97. data/lib/watir/version.rb +3 -3
  98. data/lib/watir/wait.rb +250 -0
  99. data/lib/watir/wait/timer.rb +19 -0
  100. data/lib/watir/window.rb +244 -0
  101. data/lib/watir/xpath_support.rb +20 -0
  102. data/spec/always_locate_spec.rb +43 -0
  103. data/spec/browser_spec.rb +130 -0
  104. data/spec/click_spec.rb +19 -0
  105. data/spec/container_spec.rb +34 -0
  106. data/spec/element_locator_spec.rb +532 -0
  107. data/spec/element_spec.rb +136 -0
  108. data/spec/implementation.rb +216 -0
  109. data/spec/input_spec.rb +14 -0
  110. data/spec/locator_spec_helper.rb +57 -0
  111. data/spec/spec_helper.rb +35 -0
  112. data/spec/special_chars_spec.rb +13 -0
  113. data/support/doctest_helper.rb +78 -0
  114. data/support/travis.sh +44 -0
  115. data/support/version_differ.rb +59 -0
  116. data/watir.gemspec +37 -25
  117. metadata +288 -23
  118. data/lib/watir/loader.rb +0 -64
@@ -0,0 +1,38 @@
1
+ module Watir
2
+ module UserEditable
3
+
4
+ #
5
+ # Clear the element, the type in the given value.
6
+ #
7
+ # @param [String, Symbol] *args
8
+ #
9
+
10
+ def set(*args)
11
+ clear
12
+ element_call { @element.send_keys(*args) }
13
+ end
14
+ alias_method :value=, :set
15
+
16
+ #
17
+ # Appends the given value to the text in the text field.
18
+ #
19
+ # @param [String, Symbol] *args
20
+ #
21
+
22
+ def append(*args)
23
+ send_keys(*args)
24
+ end
25
+ alias_method :<<, :append
26
+
27
+ #
28
+ # Clears the text field.
29
+ #
30
+
31
+ def clear
32
+ assert_exists
33
+ assert_writable
34
+ element_call { @element.clear }
35
+ end
36
+
37
+ end # UserEditable
38
+ end # Watir
@@ -1,3 +1,3 @@
1
- module Watir
2
- BUNDLE_VERSION = '5.0.0'
3
- end
1
+ module Watir
2
+ VERSION = '0.9.9'
3
+ end
@@ -0,0 +1,250 @@
1
+ require 'forwardable'
2
+ require 'watir/wait/timer'
3
+
4
+ module Watir
5
+ module Wait
6
+
7
+ class TimeoutError < StandardError ; end
8
+
9
+ INTERVAL = 0.1
10
+
11
+
12
+ class << self
13
+
14
+ #
15
+ # @!attribute timer
16
+ # Access Watir timer implementation in use.
17
+ # @see Timer
18
+ # @return [#wait]
19
+ #
20
+
21
+ attr_writer :timer
22
+
23
+ def timer
24
+ @timer ||= Timer.new
25
+ end
26
+
27
+ #
28
+ # Waits until the block evaluates to true or times out.
29
+ #
30
+ # @example
31
+ # Watir::Wait.until { browser.text_field(name: "new_user_first_name").visible? }
32
+ #
33
+ # @param [Fixnum] timeout How long to wait in seconds
34
+ # @param [String] message Message to raise if timeout is exceeded
35
+ # @raise [TimeoutError] if timeout is exceeded
36
+ #
37
+
38
+ def until(timeout = nil, message = nil)
39
+ timeout ||= Watir.default_timeout
40
+ run_with_timer(timeout) do
41
+ result = yield(self)
42
+ return result if result
43
+ end
44
+ raise TimeoutError, message_for(timeout, message)
45
+ end
46
+
47
+ #
48
+ # Wait while the block evaluates to true or times out.
49
+ #
50
+ # @example
51
+ # Watir::Wait.while { browser.text_field(name: "abrakadbra").present? }
52
+ #
53
+ # @param [Fixnum] timeout How long to wait in seconds
54
+ # @param [String] message Message to raise if timeout is exceeded
55
+ # @raise [TimeoutError] if timeout is exceeded
56
+ #
57
+
58
+ def while(timeout = nil, message = nil)
59
+ timeout ||= Watir.default_timeout
60
+ run_with_timer(timeout) { return unless yield(self) }
61
+ raise TimeoutError, message_for(timeout, message)
62
+ end
63
+
64
+ private
65
+
66
+ def message_for(timeout, message)
67
+ err = "timed out after #{timeout} seconds"
68
+ err << ", #{message}" if message
69
+
70
+ err
71
+ end
72
+
73
+ def run_with_timer(timeout, &block)
74
+ if timeout == 0
75
+ block.call
76
+ else
77
+ timer.wait(timeout) do
78
+ block.call
79
+ sleep INTERVAL
80
+ end
81
+ end
82
+ end
83
+
84
+ end # self
85
+ end # Wait
86
+
87
+ module Waitable
88
+ def wait_until(*args, &blk)
89
+ Wait.until(*args, &blk)
90
+ end
91
+
92
+ def wait_while(*args, &blk)
93
+ Wait.while(*args, &blk)
94
+ end
95
+ end
96
+
97
+ class BaseDecorator
98
+
99
+ def initialize(element, timeout, message = nil)
100
+ @element = element
101
+ @timeout = timeout
102
+ @message = message
103
+ end
104
+
105
+ def respond_to?(*args)
106
+ @element.respond_to?(*args)
107
+ end
108
+
109
+ def method_missing(m, *args, &block)
110
+ unless @element.respond_to?(m)
111
+ raise NoMethodError, "undefined method `#{m}' for #{@element.inspect}:#{@element.class}"
112
+ end
113
+
114
+ Watir::Wait.until(@timeout, @message) { wait_until }
115
+
116
+ @element.__send__(m, *args, &block)
117
+ end
118
+ end
119
+
120
+ #
121
+ # Wraps an Element so that any subsequent method calls are
122
+ # put on hold until the element is present (exists and is visible) on the page.
123
+ #
124
+
125
+ class WhenPresentDecorator < BaseDecorator
126
+ def present?
127
+ Watir::Wait.until(@timeout, @message) { wait_until }
128
+ true
129
+ rescue Watir::Wait::TimeoutError
130
+ false
131
+ end
132
+
133
+ private
134
+
135
+ def wait_until
136
+ @element.present?
137
+ end
138
+ end # WhenPresentDecorator
139
+
140
+ #
141
+ # Wraps an Element so that any subsequent method calls are
142
+ # put on hold until the element is enabled (exists and is enabled) on the page.
143
+ #
144
+
145
+ class WhenEnabledDecorator < BaseDecorator
146
+
147
+ private
148
+
149
+ def wait_until
150
+ @element.enabled?
151
+ end
152
+ end # WhenEnabledDecorator
153
+
154
+ #
155
+ # Convenience methods for things that eventually become present.
156
+ #
157
+ # Includers should implement a public #present? and a (possibly private) #selector_string method.
158
+ #
159
+
160
+ module EventuallyPresent
161
+ #
162
+ # Waits until the element is present.
163
+ #
164
+ # @example
165
+ # browser.text_field(name: "new_user_first_name").when_present.click
166
+ # browser.text_field(name: "new_user_first_name").when_present { |field| field.set "Watir" }
167
+ # browser.text_field(name: "new_user_first_name").when_present(60).text
168
+ #
169
+ # @param [Fixnum] timeout seconds to wait before timing out
170
+ #
171
+ # @see Watir::Wait
172
+ # @see Watir::Element#present?
173
+ #
174
+
175
+ def when_present(timeout = nil)
176
+ timeout ||= Watir.default_timeout
177
+ message = "waiting for #{selector_string} to become present"
178
+
179
+ if block_given?
180
+ Watir::Wait.until(timeout, message) { present? }
181
+ yield self
182
+ else
183
+ WhenPresentDecorator.new(self, timeout, message)
184
+ end
185
+ end
186
+
187
+ #
188
+ # Waits until the element is enabled.
189
+ #
190
+ # @example
191
+ # browser.button(name: "new_user_button_2").when_enabled.click
192
+ #
193
+ # @param [Fixnum] timeout seconds to wait before timing out
194
+ #
195
+ # @see Watir::Wait
196
+ # @see Watir::Element#enabled?
197
+ #
198
+
199
+ def when_enabled(timeout = nil)
200
+ timeout ||= Watir.default_timeout
201
+ message = "waiting for #{selector_string} to become enabled"
202
+
203
+ if block_given?
204
+ Watir::Wait.until(timeout, message) { enabled? }
205
+ yield self
206
+ else
207
+ WhenEnabledDecorator.new(self, timeout, message)
208
+ end
209
+ end
210
+
211
+ #
212
+ # Waits until the element is present.
213
+ #
214
+ # @example
215
+ # browser.text_field(name: "new_user_first_name").wait_until_present
216
+ #
217
+ # @param [Fixnum] timeout seconds to wait before timing out
218
+ #
219
+ # @see Watir::Wait
220
+ # @see Watir::Element#present?
221
+ #
222
+
223
+ def wait_until_present(timeout = nil)
224
+ timeout ||= Watir.default_timeout
225
+ message = "waiting for #{selector_string} to become present"
226
+ Watir::Wait.until(timeout, message) { present? }
227
+ end
228
+
229
+ #
230
+ # Waits while the element is present.
231
+ #
232
+ # @example
233
+ # browser.text_field(name: "abrakadbra").wait_while_present
234
+ #
235
+ # @param [Fixnum] timeout seconds to wait before timing out
236
+ #
237
+ # @see Watir::Wait
238
+ # @see Watir::Element#present?
239
+ #
240
+
241
+ def wait_while_present(timeout = nil)
242
+ timeout ||= Watir.default_timeout
243
+ message = "waiting for #{selector_string} to disappear"
244
+ Watir::Wait.while(timeout, message) { present? }
245
+ rescue Selenium::WebDriver::Error::StaleElementReferenceError
246
+ # it's not present
247
+ end
248
+
249
+ end # EventuallyPresent
250
+ end # Watir
@@ -0,0 +1,19 @@
1
+ module Watir
2
+ module Wait
3
+ class Timer
4
+
5
+ #
6
+ # Executes given block until it returns true or exceeds timeout.
7
+ # @param [Fixnum] timeout
8
+ # @yield block
9
+ # @api private
10
+ #
11
+
12
+ def wait(timeout, &block)
13
+ end_time = ::Time.now + timeout
14
+ yield(block) until ::Time.now > end_time
15
+ end
16
+
17
+ end # Timer
18
+ end # Wait
19
+ end # Watir
@@ -0,0 +1,244 @@
1
+ module Watir
2
+ class Window
3
+ include EventuallyPresent
4
+
5
+ def initialize(driver, selector)
6
+ @driver = driver
7
+ @selector = selector
8
+
9
+ if selector.empty?
10
+ @handle = current_window
11
+ elsif selector.key? :handle
12
+ @handle = selector.delete :handle
13
+ else
14
+ unless selector.keys.all? { |k| [:title, :url, :index].include? k }
15
+ raise ArgumentError, "invalid window selector: #{selector.inspect}"
16
+ end
17
+ end
18
+ end
19
+
20
+ def inspect
21
+ '#<%s:0x%x located=%s>' % [self.class, hash*2, !!@handle]
22
+ end
23
+
24
+ #
25
+ # Returns window size.
26
+ #
27
+ # @example
28
+ # size = browser.window.size
29
+ # [size.width, size.height] #=> [1600, 1200]
30
+ #
31
+
32
+ def size
33
+ size = nil
34
+ use { size = @driver.manage.window.size }
35
+
36
+ size
37
+ end
38
+
39
+ #
40
+ # Returns window position.
41
+ #
42
+ # @example
43
+ # position = browser.window.position
44
+ # [position.x, position.y] #=> [92, 76]
45
+ #
46
+
47
+ def position
48
+ pos = nil
49
+ use { pos = @driver.manage.window.position }
50
+
51
+ pos
52
+ end
53
+
54
+ #
55
+ # Resizes window to given width and height.
56
+ #
57
+ # @example
58
+ # browser.window.resize_to 1600, 1200
59
+ #
60
+ # @param [Fixnum] width
61
+ # @param [Fixnum] height
62
+ #
63
+
64
+ def resize_to(width, height)
65
+ dimension = Selenium::WebDriver::Dimension.new(Integer(width), Integer(height))
66
+ use { @driver.manage.window.size = dimension }
67
+
68
+ dimension
69
+ end
70
+
71
+ #
72
+ # Moves window to given x and y coordinates.
73
+ #
74
+ # @example
75
+ # browser.window.move_to 300, 200
76
+ #
77
+ # @param [Fixnum] x
78
+ # @param [Fixnum] y
79
+ #
80
+
81
+ def move_to(x, y)
82
+ point = Selenium::WebDriver::Point.new(Integer(x), Integer(y))
83
+ use { @driver.manage.window.position = point }
84
+
85
+ point
86
+ end
87
+
88
+ #
89
+ # Maximizes window.
90
+ #
91
+ # @example
92
+ # browser.window.maximize
93
+ #
94
+
95
+ def maximize
96
+ use { @driver.manage.window.maximize }
97
+ end
98
+
99
+ #
100
+ # Returns true if window exists.
101
+ #
102
+ # @return [Boolean]
103
+ #
104
+
105
+ def exists?
106
+ assert_exists
107
+ true
108
+ rescue Exception::NoMatchingWindowFoundException
109
+ false
110
+ end
111
+
112
+ alias_method :present?, :exists?
113
+ alias_method :exist?, :exists?
114
+
115
+ #
116
+ # Returns true if two windows are equal.
117
+ #
118
+ # @example
119
+ # browser.window(index: 0) == browser.window(index: 1)
120
+ # #=> false
121
+ #
122
+ # @param [Window] other
123
+ #
124
+
125
+ def ==(other)
126
+ return false unless other.kind_of?(self.class)
127
+
128
+ handle == other.handle
129
+ end
130
+ alias_method :eql?, :==
131
+
132
+ def hash
133
+ handle.hash ^ self.class.hash
134
+ end
135
+
136
+ #
137
+ # Returns true if window is current.
138
+ #
139
+ # @example
140
+ # browser.window.current?
141
+ # #=> true
142
+ #
143
+
144
+ def current?
145
+ current_window == handle
146
+ end
147
+
148
+ #
149
+ # Closes window.
150
+ #
151
+
152
+ def close
153
+ use { @driver.close }
154
+ end
155
+
156
+ #
157
+ # Returns window title.
158
+ #
159
+ # @return [String]
160
+ #
161
+
162
+ def title
163
+ title = nil
164
+ use { title = @driver.title }
165
+
166
+ title
167
+ end
168
+
169
+ #
170
+ # Returns window URL.
171
+ #
172
+ # @return [String]
173
+ #
174
+
175
+ def url
176
+ url = nil
177
+ use { url = @driver.current_url }
178
+
179
+ url
180
+ end
181
+
182
+ #
183
+ # Switches to given window and executes block, then switches back.
184
+ #
185
+ # @example
186
+ # browser.window(title: "closeable window").use do
187
+ # browser.a(id: "close").click
188
+ # end
189
+ #
190
+
191
+ def use(&blk)
192
+ assert_exists
193
+ @driver.switch_to.window(handle, &blk)
194
+ self
195
+ end
196
+
197
+ protected
198
+
199
+ def handle
200
+ @handle ||= locate
201
+ end
202
+
203
+ private
204
+
205
+ # Referenced in EventuallyPresent
206
+ def selector_string
207
+ @selector.inspect
208
+ end
209
+
210
+ def locate
211
+ if @selector.empty?
212
+ nil
213
+ elsif @selector.key?(:index)
214
+ @driver.window_handles[Integer(@selector[:index])]
215
+ else
216
+ @driver.window_handles.find { |wh| matches?(wh) }
217
+ end
218
+ end
219
+
220
+ def assert_exists
221
+ raise(Exception::NoMatchingWindowFoundException, @selector.inspect) unless @driver.window_handles.include?(handle)
222
+ end
223
+
224
+ # return a handle to the currently active window if it is still open; otherwise nil
225
+ def current_window
226
+ @driver.window_handle
227
+ rescue Selenium::WebDriver::Error::NoSuchWindowError
228
+ nil
229
+ end
230
+
231
+ def matches?(handle)
232
+ @driver.switch_to.window(handle) {
233
+ matches_title = @selector[:title].nil? || @selector[:title] === @driver.title
234
+ matches_url = @selector[:url].nil? || @selector[:url] === @driver.current_url
235
+
236
+ matches_title && matches_url
237
+ }
238
+ rescue Selenium::WebDriver::Error::NoSuchWindowError, Selenium::WebDriver::Error::NoSuchDriverError
239
+ # the window may disappear while we're iterating.
240
+ false
241
+ end
242
+
243
+ end # Window
244
+ end # Watir