druid-s 1.0.0

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 (219) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +7 -0
  3. data/.rspec +1 -0
  4. data/.rvmrc +1 -0
  5. data/.travis.yml +27 -0
  6. data/ChangeLog +541 -0
  7. data/Gemfile +8 -0
  8. data/README.md +78 -0
  9. data/Rakefile +33 -0
  10. data/cucumber.yml +6 -0
  11. data/druid.gemspec +30 -0
  12. data/features/area.feature +33 -0
  13. data/features/async.feature +16 -0
  14. data/features/audio.feature +61 -0
  15. data/features/bold.feature +20 -0
  16. data/features/button.feature +81 -0
  17. data/features/canvas.feature +34 -0
  18. data/features/checkbox.feature +48 -0
  19. data/features/div.feature +45 -0
  20. data/features/element.feature +281 -0
  21. data/features/file_field.feature +38 -0
  22. data/features/form.feature +37 -0
  23. data/features/frames.feature +76 -0
  24. data/features/generic_elements.feature +29 -0
  25. data/features/heading.feature +160 -0
  26. data/features/hidden_field.feature +39 -0
  27. data/features/html/async.html +31 -0
  28. data/features/html/frame_1.html +18 -0
  29. data/features/html/frame_2.html +16 -0
  30. data/features/html/frame_3.html +14 -0
  31. data/features/html/frames.html +12 -0
  32. data/features/html/hover.html +11 -0
  33. data/features/html/iframes.html +12 -0
  34. data/features/html/images/circle.png +0 -0
  35. data/features/html/images/img_pulpit.jpg +0 -0
  36. data/features/html/modal.html +17 -0
  37. data/features/html/modal_1.html +38 -0
  38. data/features/html/modal_2.html +27 -0
  39. data/features/html/multi_elements.html +145 -0
  40. data/features/html/nested_elements.html +75 -0
  41. data/features/html/nested_frame_1.html +1 -0
  42. data/features/html/nested_frame_2.html +11 -0
  43. data/features/html/nested_frame_3.html +14 -0
  44. data/features/html/nested_frames.html +10 -0
  45. data/features/html/planets.gif +0 -0
  46. data/features/html/static_elements.html +203 -0
  47. data/features/html/success.html +8 -0
  48. data/features/html/sun.gif +0 -0
  49. data/features/html/sun.html +7 -0
  50. data/features/image.feature +47 -0
  51. data/features/italic.feature +20 -0
  52. data/features/javascript.feature +28 -0
  53. data/features/label.feature +43 -0
  54. data/features/link.feature +56 -0
  55. data/features/list_item.feature +37 -0
  56. data/features/modal_dialog.feature +9 -0
  57. data/features/multi_elements.feature +498 -0
  58. data/features/nested_elements.feature +121 -0
  59. data/features/ordered_list.feature +46 -0
  60. data/features/page_level_actions.feature +116 -0
  61. data/features/paragraph.feature +33 -0
  62. data/features/populate_page_with.feature +25 -0
  63. data/features/radio_button.feature +51 -0
  64. data/features/radio_button_group.feature +28 -0
  65. data/features/sample-app/public/04-Death_Becomes_Fur.mp4 +0 -0
  66. data/features/sample-app/public/04-Death_Becomes_Fur.oga +0 -0
  67. data/features/sample-app/public/audio_video.html +19 -0
  68. data/features/sample-app/public/jquery-1.3.2.js +4376 -0
  69. data/features/sample-app/public/jquery.html +28 -0
  70. data/features/sample-app/public/movie.mp4 +0 -0
  71. data/features/sample-app/public/movie.ogg +0 -0
  72. data/features/sample-app/public/prototype-1.6.0.3.js +4320 -0
  73. data/features/sample-app/public/prototype.html +32 -0
  74. data/features/sample-app/sample_app.rb +35 -0
  75. data/features/section.feature +132 -0
  76. data/features/select_list.feature +84 -0
  77. data/features/span.feature +43 -0
  78. data/features/step_definations/area_steps.rb +23 -0
  79. data/features/step_definations/async_steps.rb +80 -0
  80. data/features/step_definations/audio_steps.rb +47 -0
  81. data/features/step_definations/bold_steps.rb +11 -0
  82. data/features/step_definations/button_steps.rb +52 -0
  83. data/features/step_definations/canvas_steps.rb +19 -0
  84. data/features/step_definations/checkbox_steps.rb +39 -0
  85. data/features/step_definations/div_steps.rb +28 -0
  86. data/features/step_definations/element_steps.rb +217 -0
  87. data/features/step_definations/file_field_steps.rb +31 -0
  88. data/features/step_definations/form_steps.rb +23 -0
  89. data/features/step_definations/frame_steps.rb +189 -0
  90. data/features/step_definations/generic_element_steps.rb +31 -0
  91. data/features/step_definations/heading_steps.rb +39 -0
  92. data/features/step_definations/hidden_field_steps.rb +27 -0
  93. data/features/step_definations/image_steps.rb +35 -0
  94. data/features/step_definations/italic_steps.rb +11 -0
  95. data/features/step_definations/javasript_steps.rb +52 -0
  96. data/features/step_definations/label_steps.rb +19 -0
  97. data/features/step_definations/link_steps.rb +42 -0
  98. data/features/step_definations/list_item_steps.rb +24 -0
  99. data/features/step_definations/modal_dialog_steps.rb +38 -0
  100. data/features/step_definations/multi_elements_steps.rb +557 -0
  101. data/features/step_definations/nested_elements_steps.rb +219 -0
  102. data/features/step_definations/ordered_list_steps.rb +49 -0
  103. data/features/step_definations/page_level_actions_steps.rb +172 -0
  104. data/features/step_definations/page_traversal_steps.rb +4 -0
  105. data/features/step_definations/paragraph_steps.rb +19 -0
  106. data/features/step_definations/populate_page_with_steps.rb +3 -0
  107. data/features/step_definations/radio_button_group_steps.rb +32 -0
  108. data/features/step_definations/radio_button_steps.rb +31 -0
  109. data/features/step_definations/section_steps.rb +271 -0
  110. data/features/step_definations/select_list_steps.rb +91 -0
  111. data/features/step_definations/span_steps.rb +23 -0
  112. data/features/step_definations/table_cell_steps.rb +27 -0
  113. data/features/step_definations/table_row_steps.rb +23 -0
  114. data/features/step_definations/table_steps.rb +109 -0
  115. data/features/step_definations/text_area_steps.rb +39 -0
  116. data/features/step_definations/text_field_steps.rb +39 -0
  117. data/features/step_definations/unordered_list_steps.rb +27 -0
  118. data/features/step_definations/video_steps.rb +27 -0
  119. data/features/support/ajax_test_environment.rb +26 -0
  120. data/features/support/audio_video_page.rb +23 -0
  121. data/features/support/env.rb +5 -0
  122. data/features/support/hooks.rb +3 -0
  123. data/features/support/page.rb +372 -0
  124. data/features/support/persistent_browser.rb +58 -0
  125. data/features/support/targets/firefox14_osx.rb +5 -0
  126. data/features/support/targets/firefox14_windows7.rb +5 -0
  127. data/features/support/url_helper.rb +50 -0
  128. data/features/table.feature +127 -0
  129. data/features/table_cell.feature +42 -0
  130. data/features/table_row.feature +30 -0
  131. data/features/text_area.feature +44 -0
  132. data/features/text_field.feature +53 -0
  133. data/features/unordered_list.feature +46 -0
  134. data/features/video.feature +66 -0
  135. data/lib/druid/accessors.rb +1082 -0
  136. data/lib/druid/assist.rb +653 -0
  137. data/lib/druid/element_locators.rb +21 -0
  138. data/lib/druid/elements/area.rb +9 -0
  139. data/lib/druid/elements/audio.rb +9 -0
  140. data/lib/druid/elements/bold.rb +8 -0
  141. data/lib/druid/elements/button.rb +12 -0
  142. data/lib/druid/elements/canvas.rb +9 -0
  143. data/lib/druid/elements/check_box.rb +9 -0
  144. data/lib/druid/elements/div.rb +9 -0
  145. data/lib/druid/elements/element.rb +187 -0
  146. data/lib/druid/elements/file_field.rb +9 -0
  147. data/lib/druid/elements/form.rb +9 -0
  148. data/lib/druid/elements/heading.rb +14 -0
  149. data/lib/druid/elements/hidden_field.rb +9 -0
  150. data/lib/druid/elements/image.rb +9 -0
  151. data/lib/druid/elements/italic.rb +9 -0
  152. data/lib/druid/elements/label.rb +8 -0
  153. data/lib/druid/elements/link.rb +9 -0
  154. data/lib/druid/elements/list_item.rb +9 -0
  155. data/lib/druid/elements/media.rb +11 -0
  156. data/lib/druid/elements/option.rb +9 -0
  157. data/lib/druid/elements/ordered_list.rb +29 -0
  158. data/lib/druid/elements/paragraph.rb +9 -0
  159. data/lib/druid/elements/radio_button.rb +9 -0
  160. data/lib/druid/elements/select_list.rb +30 -0
  161. data/lib/druid/elements/span.rb +9 -0
  162. data/lib/druid/elements/table.rb +92 -0
  163. data/lib/druid/elements/table_cell.rb +11 -0
  164. data/lib/druid/elements/table_row.rb +50 -0
  165. data/lib/druid/elements/text_area.rb +10 -0
  166. data/lib/druid/elements/text_field.rb +11 -0
  167. data/lib/druid/elements/unordered_list.rb +32 -0
  168. data/lib/druid/elements/video.rb +8 -0
  169. data/lib/druid/elements.rb +55 -0
  170. data/lib/druid/javascript/angularjs.rb +12 -0
  171. data/lib/druid/javascript/jquery.rb +12 -0
  172. data/lib/druid/javascript/prototype.rb +12 -0
  173. data/lib/druid/javascript/yui.rb +19 -0
  174. data/lib/druid/javascript_framework_facade.rb +76 -0
  175. data/lib/druid/locator_generator.rb +181 -0
  176. data/lib/druid/nested_elements.rb +56 -0
  177. data/lib/druid/page_factory.rb +115 -0
  178. data/lib/druid/page_populator.rb +104 -0
  179. data/lib/druid/section_collection.rb +17 -0
  180. data/lib/druid/version.rb +3 -0
  181. data/lib/druid.rb +452 -0
  182. data/spec/druid/accessors_spec.rb +1209 -0
  183. data/spec/druid/druid_spec.rb +295 -0
  184. data/spec/druid/element_locators_spec.rb +750 -0
  185. data/spec/druid/elements/bold_spec.rb +12 -0
  186. data/spec/druid/elements/button_spec.rb +23 -0
  187. data/spec/druid/elements/check_box_spec.rb +14 -0
  188. data/spec/druid/elements/div_spec.rb +10 -0
  189. data/spec/druid/elements/element_spec.rb +250 -0
  190. data/spec/druid/elements/file_field_spec.rb +13 -0
  191. data/spec/druid/elements/form_spec.rb +18 -0
  192. data/spec/druid/elements/heading_spec.rb +30 -0
  193. data/spec/druid/elements/hidden_field_spec.rb +10 -0
  194. data/spec/druid/elements/image_spec.rb +23 -0
  195. data/spec/druid/elements/itatic_spec.rb +11 -0
  196. data/spec/druid/elements/label_spec.rb +10 -0
  197. data/spec/druid/elements/link_spec.rb +10 -0
  198. data/spec/druid/elements/list_item_spec.rb +10 -0
  199. data/spec/druid/elements/media_spec.rb +12 -0
  200. data/spec/druid/elements/option_spec.rb +21 -0
  201. data/spec/druid/elements/ordered_list_spec.rb +38 -0
  202. data/spec/druid/elements/page_factory_spec.rb +40 -0
  203. data/spec/druid/elements/paragraph_spec.rb +12 -0
  204. data/spec/druid/elements/radio_button_spec.rb +14 -0
  205. data/spec/druid/elements/select_list_spec.rb +51 -0
  206. data/spec/druid/elements/span_spec.rb +10 -0
  207. data/spec/druid/elements/table_cell_spec.rb +14 -0
  208. data/spec/druid/elements/table_row_spec.rb +34 -0
  209. data/spec/druid/elements/table_spec.rb +47 -0
  210. data/spec/druid/elements/text_area_spec.rb +13 -0
  211. data/spec/druid/elements/text_field_spec.rb +22 -0
  212. data/spec/druid/elements/unordered_list_spec.rb +39 -0
  213. data/spec/druid/javascript_framework_facade_spec.rb +59 -0
  214. data/spec/druid/nested_element_spec.rb +128 -0
  215. data/spec/druid/page_factory_spec.rb +235 -0
  216. data/spec/druid/page_populator_spec.rb +173 -0
  217. data/spec/druid/page_section_spec.rb +70 -0
  218. data/spec/spec_helper.rb +9 -0
  219. metadata +517 -0
data/lib/druid.rb ADDED
@@ -0,0 +1,452 @@
1
+ require 'watir'
2
+ require 'druid/accessors'
3
+ require 'druid/assist'
4
+ require 'druid/page_factory'
5
+ require 'druid/element_locators'
6
+ require 'druid/page_populator'
7
+ require 'druid/section_collection'
8
+ require 'druid/javascript_framework_facade'
9
+
10
+ # require 'watir/extensions/alerts'
11
+ #
12
+ # Module that when included adds functionality to a page object. This module
13
+ # will add numerous class and instance methods that you use to define and
14
+ # interact with web pages.
15
+ #
16
+ # If we have a login page with a username and password textfield and a login
17
+ # button we might define our page like the one below. We can then interact with
18
+ # the object using the generated methods.
19
+ #
20
+ # @example Login page example
21
+ # class LoginPage
22
+ # include Druid
23
+ #
24
+ # text_field(:username, :id => 'user')
25
+ # text_field(:password, :id => 'pass')
26
+ # button(:login, :value => 'Login')
27
+ # end
28
+ #
29
+ # ...
30
+ #
31
+ # browser = Watir::Browser.new :firefox
32
+ # login_page = LoginPage.new(browser)
33
+ # login_page.username = 'tim'
34
+ # login_page.password = 'sheng'
35
+ # login_page.login
36
+ #
37
+ # @see Druid::Accessors to see what class level methods are added to this module at runtime.
38
+ #
39
+ module Druid
40
+ include Assist
41
+ include ElementLocators
42
+ include PagePopulator
43
+ # extend Forwardable
44
+
45
+ def method_missing(method, *args, &block)
46
+ @root_element.send(method, *args, &block)
47
+ end
48
+
49
+ def respond_to_missing?(method, include_all = false)
50
+ @root_element && @root_element.respond_to?(method) || super
51
+ end
52
+
53
+ # Forward visibility checks to root so page sections can be tested for existence.
54
+ # def_delegators :root, :visible?, :exist?
55
+
56
+
57
+ # @return [Watir::Browser] the drvier passed to the constructor
58
+ attr_reader :driver
59
+
60
+ #
61
+ # Construct a new druid. Prior to browser initialization it will call
62
+ # a method named initialize_accessors if it exists. Upon initialization of
63
+ # the page it will call a method named initialize_page if it exists
64
+ #
65
+ # @param [Watir::Browser, Watir:HTMLElement] the driver/element to use
66
+ # @param [bool] open the page if page_url is set
67
+ #
68
+ def initialize(root, visit=false)
69
+ initialize_accessors if respond_to?(:initialize_accessors)
70
+ initialize_driver root
71
+ goto if visit && respond_to?(:goto)
72
+ initialize_page if respond_to?(:initialize_page)
73
+ end
74
+
75
+ def initialize_driver root
76
+ @driver = root if root.is_a? Watir::HTMLElement or root.is_a? Watir::Browser
77
+ @root_element = Elements::Element.new root if root.is_a? Watir::HTMLElement
78
+ raise "expect Watir::Browser or Watir::HTMLElement" if not root.is_a? Watir::HTMLElement and not root.is_a? Watir::Browser
79
+ end
80
+
81
+ # @private
82
+ def self.included(cls)
83
+ cls.extend Druid::Accessors
84
+ end
85
+
86
+ #
87
+ # navigate to the provided url
88
+ #
89
+ # @param [String] the full url to navigate to
90
+ #
91
+ def navigate_to url
92
+ driver.goto url
93
+ end
94
+
95
+ #
96
+ # Set the default timeout for page level Waits
97
+ #
98
+ def self.default_page_wait=(timeout)
99
+ @page_wait = timeout
100
+ end
101
+
102
+ #
103
+ # Return the default timeout for page level Waits
104
+ #
105
+ def self.default_page_wait
106
+ @page_wait ||= 30
107
+ end
108
+
109
+ #
110
+ # Sets the default timeout for element level Waits
111
+ #
112
+ def self.default_element_wait=(timeout)
113
+ @element_wait = timeout
114
+ end
115
+
116
+ #
117
+ # Returns the default timeout for element level Waits
118
+ #
119
+ def self.default_element_wait
120
+ @element_wait ||= 5
121
+ end
122
+
123
+ #
124
+ # Set the javascript framework to use when determining number of
125
+ # ajax requests. Valid frameworks are :jquery, :prototype, and :yui,
126
+ # and :angularjs
127
+ #
128
+ def self.javascript_framework=(framework)
129
+ Druid::JavascriptFrameworkFacade.framework = framework
130
+ end
131
+
132
+ #
133
+ # Add a new javascript framework to druid. The module passed
134
+ # in must adhere to the same prototype as the JQuery and Prototype
135
+ # modules.
136
+ #
137
+ # @param [Symbol] the name used to reference the framework in
138
+ # subsequent calls
139
+ # @param [Module] a module that has the necessary methods to perform
140
+ # the required actions.
141
+ #
142
+ def self.add_framework(key, framework)
143
+ Druid::JavascriptFrameworkFacade.add_framework(key, framework)
144
+ end
145
+ #
146
+ # get the current page url
147
+ #
148
+ def current_url
149
+ driver.url
150
+ end
151
+
152
+ #
153
+ # Returns the text of the current page
154
+ #
155
+ def text
156
+ driver.text
157
+ end
158
+
159
+ #
160
+ # Returns the html of the current page
161
+ #
162
+ def html
163
+ driver.html
164
+ end
165
+
166
+ #
167
+ # Returns the title of the current page
168
+ #
169
+ def title
170
+ driver.title
171
+ end
172
+
173
+ #
174
+ # Refresh current page
175
+ #
176
+ def refresh
177
+ driver.refresh
178
+ end
179
+
180
+ #
181
+ # Waits until readyState of document is complete
182
+ #
183
+ # @example
184
+ # @page.wait
185
+ #
186
+ # @param [Integer] timeout
187
+ #
188
+ def wait(timeout = 5)
189
+ driver.wait(timeout = 5)
190
+ end
191
+
192
+ #
193
+ # Go back to the previous page
194
+ #
195
+ def back
196
+ driver.back
197
+ end
198
+
199
+ #
200
+ # Go forward to the next page
201
+ #
202
+ def forward
203
+ driver.forward
204
+ end
205
+ #
206
+ # Wait until the block returns true or times out
207
+ #
208
+ # @example
209
+ # @page.wait_until(5, 'Success not found on page') do
210
+ # @page.text.include? 'Success'
211
+ # end
212
+ #
213
+ # @param [Numeric] the amount of time to wait for the block to return true
214
+ # @param [String] the message to include with the error if we exceed the timeout duration
215
+ # @param block the block to execute. It should return true when successful.
216
+ #
217
+ def wait_until(timeout = Druid.default_page_wait, message = nil, &block)
218
+ driver.wait_until(timeout: timeout, message: message, &block)
219
+ end
220
+
221
+ #
222
+ # wait until there are no pending ajax requests. This requires you to set the javascript framework in advance.
223
+ #
224
+ # @param [Numeric] the amount of time to wait for the block to return true.
225
+ # @param [String] the message to include with the error if we exceed the timeout duration
226
+ #
227
+ def wait_for_ajax(timeout = Druid.default_page_wait, message = nil)
228
+ end_time = ::Time.now + timeout
229
+ until ::Time.now > end_time
230
+ return if driver.execute_script(Druid::JavascriptFrameworkFacade.pending_requests) == 0
231
+ sleep 1
232
+ end
233
+ message = "Timed out waiting for ajax requests to complete" unless message
234
+ raise message
235
+ end
236
+
237
+ #
238
+ # Override the normal alert popup so it does not occur.
239
+ #
240
+ # @example
241
+ # message = @page.alert do
242
+ # @page.button_that_causes_alert
243
+ # end
244
+ #
245
+ # @param block a block that has the call that will cause the alert to display
246
+ # @return [String] the message that was contained in the alert
247
+ #
248
+ def alert(&block)
249
+ # switch_to_frame(frame)
250
+ yield
251
+ value = nil
252
+ if driver.alert.exists?
253
+ value = driver.alert.text
254
+ driver.alert.ok
255
+ end
256
+ # switch_to_default_content(frame)
257
+ value
258
+ end
259
+
260
+ #
261
+ # Override the normal confirm popup so it does not occur
262
+ #
263
+ # @example
264
+ # message = @popup.confirm(true) do
265
+ # @page.button_that_causes_confirm
266
+ # end
267
+ #
268
+ # @param [boolean] what response you want to return back from the confirm popup
269
+ # @param block a block that has the call that will cause the confirm to display
270
+ # @return [String] the message that was contained in the confirm
271
+ #
272
+ def confirm(response, &block)
273
+ yield
274
+ value = nil
275
+ if driver.alert.exists?
276
+ value = driver.alert.text
277
+ response ? driver.alert.ok : driver.alert.close
278
+ end
279
+ value
280
+ end
281
+
282
+ #
283
+ # Override the normal prompt popup so it does not occur
284
+ #
285
+ # @example
286
+ # message = @popup.prompt("Some Value") do
287
+ # @page.button_that_causes_prompt
288
+ # end
289
+ #
290
+ # @param [String] the value will be setted in the prompt field
291
+ # @param block a block that has the call that will cause the prompt to display
292
+ # @return [String] the message that was contained in the prompt
293
+ #
294
+ def prompt(answer, &block)
295
+ yield
296
+ value = nil
297
+ if driver.alert.exists?
298
+ value = driver.alert.text
299
+ driver.alert.set answer
300
+ driver.alert.ok
301
+ end
302
+ value
303
+ end
304
+
305
+ #
306
+ # Execute javascript on the browser
307
+ #
308
+ def execute_script(script, *args)
309
+ args.map! { |e| e.kind_of?(Druid::Elements::Element) ? e.element : e }
310
+ driver.execute_script(script, *args)
311
+ end
312
+
313
+ #
314
+ # Attach to a running window. You can locate the window using either
315
+ # the window's title or url or index, If it fails to connect to a window it will
316
+ # pause for 1 second and try again.
317
+ #
318
+ # @example
319
+ # @page.attach_to_window(:title => "other window's title")
320
+ #
321
+ # @param [Hash] either :title or :url or index of the other window. The url does not need to
322
+ # be the entire url - it can just be the page name like index.html
323
+ #
324
+ def attach_to_window(identifier, &block)
325
+ if identifier.keys.first == :url
326
+ win_id = {identifier.keys.first => /#{Regexp.escape(identifier.values.first)}/}
327
+ else
328
+ win_id = {identifier.keys.first => identifier.values.first}
329
+ end
330
+ begin
331
+ driver.window(win_id).use &block
332
+ rescue
333
+ sleep 1
334
+ driver.window(win_id).use &block
335
+ end
336
+ end
337
+
338
+ #
339
+ # Find the element that has focus on the page
340
+ #
341
+ def element_with_focus
342
+ element = driver.execute_script("return document.activeElement")
343
+ type = element.type.to_sym if element.tag_name.to_sym == :input
344
+ cls = Druid::Elements.element_class_for(element.tag_name, type)
345
+ cls.new(element)
346
+ end
347
+
348
+ #
349
+ # Override the normal showModalDialog call is it opens a window instead of a dialog.
350
+ # You will need to attach to the new window in order to continue.
351
+ #
352
+ # @example
353
+ # @page.modal_dialog do
354
+ # @page.action_that_spawns_the_modal
355
+ # end
356
+ #
357
+ # @param block a block that contains the call that will cause the modal dialog.
358
+ #
359
+ def modal_dialog(&block)
360
+ script =
361
+ %Q{
362
+ window.showModalDialog = function(sURL, vArguments, sFeatures) {
363
+ window.dialogArguments = vArguments;
364
+ modalWin = window.open(sURL, 'modal', sFeatures);
365
+ return modalWin;
366
+ }
367
+ }
368
+ driver.execute_script script
369
+ yield if block_given?
370
+ end
371
+
372
+ #
373
+ # Handle cookies
374
+ #
375
+ # @return [Watir::Cookies]
376
+ #
377
+ def cookies
378
+ driver.cookies
379
+ end
380
+
381
+ #
382
+ # Save the current screenshot to the provided path. File is saved as a png file.
383
+
384
+ def save_screenshot(file_name)
385
+ driver.screenshot.save(file_name)
386
+ end
387
+
388
+ #
389
+ # Identify an element as existing within a frame. A frame parameter is
390
+ # passed to the block and must be passed to the other calls to Druid.
391
+ # You can nest calls to in_frame by passing the frame to the next level.
392
+ #
393
+ # @example
394
+ # @page.in_frame(:id => 'frame_id') do |frame|
395
+ # @page.text_field_element(:id=> 'fname', :frame => frame)
396
+ # end
397
+ #
398
+ # @param [Hash] identifier how we find the frame. The valid keys are:
399
+ # * :id
400
+ # * :index
401
+ # * :name
402
+ # @param block that contains the calls to elements that exist inside the frame.
403
+ #
404
+ def in_frame(identifier, frame=nil, &block)
405
+ frame = [] if frame.nil?
406
+ frame << {frame: identifier}
407
+ block.call(frame)
408
+ end
409
+
410
+ #
411
+ # Identify an element as existing within an iframe. Aframe parameter is
412
+ # passed to the block and must be passed to the other calls to Druid.
413
+ # You can nest calls to in_iframe by passing the frame to the next level.
414
+ #
415
+ # @example
416
+ # @page.in_iframe(:id => 'frame_id') do |frame|
417
+ # @page.text_field_element(:id=> 'fname', :frame => frame)
418
+ # end
419
+ #
420
+ # @param [Hash] identifier how we find the frame. The valid keys are:
421
+ # * :id
422
+ # * :index
423
+ # * :name
424
+ # @param block that contains the calls to elements that exist inside the frame.
425
+ #
426
+ def in_iframe(identifier, frame=nil, &block)
427
+ frame = [] if frame.nil?
428
+ frame << {iframe: identifier}
429
+ block.call(frame)
430
+ end
431
+
432
+ def switch_to_frame(frame_identifiers)
433
+ unless frame_identifiers.nil?
434
+ frame_identifiers.each do |frame|
435
+ frame_id = frame.values.first
436
+ value = frame_id.values.first
437
+ driver.wd.switch_to.frame(value)
438
+ end
439
+ end
440
+ end
441
+
442
+ def call_block(&block)
443
+ block.arity == 1 ? block.call(self) : self.instance_eval(&block)
444
+ end
445
+
446
+ private
447
+
448
+ def root
449
+ @root_element || driver
450
+ end
451
+
452
+ end