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
@@ -0,0 +1,1082 @@
1
+ require 'druid/elements'
2
+ require 'erb'
3
+ require 'druid/locator_generator'
4
+
5
+ module Druid
6
+ #
7
+ # Contains the class level methods that are inserted into your page class
8
+ # when you include the PageObject module. These methods will generate another
9
+ # set of methods that provide access to the elements on the web pages.
10
+ #
11
+ module Accessors
12
+
13
+ #
14
+ # Set some values that can be used withing the class. This is
15
+ # typically used to provided values that help build dynamic urls in
16
+ # the page_url method
17
+ #
18
+ # @param [Hash] the value to set the params
19
+ #
20
+ def params=(the_params)
21
+ @params = the_params
22
+ end
23
+
24
+ #
25
+ # Return the params that exist on this page class
26
+ #
27
+ def params
28
+ @params ||= {}
29
+ end
30
+
31
+ #
32
+ # Specify the url for the page. A call to this method will generate a
33
+ # 'goto' method to take you to the page.
34
+ #
35
+ # @param [String] the url for the page.
36
+ # @param [Symbol] a method name to call to get the url
37
+ #
38
+ def page_url(url)
39
+ define_method("goto") do
40
+ driver.goto self.page_url_value
41
+ end
42
+
43
+ define_method("page_url_value") do
44
+ lookup = url.kind_of?(Symbol) ? self.send(url) : url
45
+ erb = ERB.new(%Q{#{lookup}})
46
+ merged_params = self.class.instance_variable_get("@merged_params")
47
+ params = merged_params ? merged_params : self.class.params
48
+ erb.result(binding)
49
+ end
50
+ end
51
+ alias_method :direct_url, :page_url
52
+
53
+ #
54
+ # Creates a method that waits the expected_title of a page to match the actual.
55
+ # @param [String] expected_title the literal expected title for the page
56
+ # @param [Regexp] expected_title the expected title pattern for the page
57
+ # @param [optional, Integer] timeout default value is nil - do not wait
58
+ # @return [boolean]
59
+ # @raise An exception if expected_title does not match actual title
60
+ #
61
+ # @example Specify 'Google' as the expected title of a page
62
+ # wait_for_expected_title "Google"
63
+ # page.wait_for_expected_title?
64
+ #
65
+ def wait_for_expected_title(expected_title, timeout=Druid.default_element_wait)
66
+ define_method("wait_for_expected_title?") do
67
+ error_message = lambda { "Expected title '#{expected_title}' instead of '#{title}'" }
68
+ has_expected_title = (expected_title === title)
69
+ wait_until(timeout, error_message.call) do
70
+ has_expected_title = (expected_title === title)
71
+ end unless has_expected_title
72
+ raise error_message.call unless has_expected_title
73
+ has_expected_title
74
+ end
75
+ end
76
+
77
+ #
78
+ # Creates a method that compares the expected_title of a page against the actual.
79
+ # @param [String] expected_title the literal expected title for the page
80
+ # @param [Regexp] expected_title the expected title pattern for the page
81
+ # @return [Boolean]
82
+ # @raise An exception if expected_title does not match actual title
83
+ #
84
+ # @example Specify 'Google' as the expected title of a page
85
+ # expected_title "Google"
86
+ # page.has_expected_title?
87
+ #
88
+ def expected_title(expected_title)
89
+ define_method("has_expected_title?") do
90
+ page_title = title
91
+ has_expected_title = (expected_title === page_title)
92
+ raise "Expected title '#{expected_title}' instead of '#{page_title}'" unless has_expected_title
93
+ has_expected_title
94
+ end
95
+ end
96
+
97
+ #
98
+ # Creates a method that provides a way to initialize a page based upon an expected element
99
+ # This is useful for pages that load dynamic content
100
+ # @param [Symbol] the name given to the element in the declaration
101
+ # @param [optional, Interger] timeout default value is 5 seconds
102
+ # @return [boolean]
103
+ #
104
+ # @example Specify a text box named :address expected on the page within 10 seconds
105
+ # expected_element(:address, 10)
106
+ # page.has_expected_element?
107
+ #
108
+ def expected_element(element_name, timeout=Druid.default_element_wait)
109
+ define_method("has_expected_element?") do
110
+ self.respond_to? "#{element_name}_element" and self.send("#{element_name}_element").when_present timeout
111
+ end
112
+ end
113
+
114
+ def expected_element_visible(element_name, timeout=Druid.default_element_wait)
115
+ define_method("has_expected_element_visible?") do
116
+ self.respond_to? "#{element_name}_element" and self.send("#{element_name}_element").when_present timeout
117
+ self.respond_to? "#{element_name}_element" and self.send("#{element_name}_element").when_visible timeout
118
+ end
119
+
120
+ end
121
+
122
+ #
123
+ # Identify an element as existing within a frame or iframe. A frame parameter
124
+ # is passed to the block and must be passed to the other calls to Druid.
125
+ # You can nest calls to in_frame by passing the frame to the next level.
126
+ #
127
+ # @example
128
+ # in_frame(:id => 'frame_id') do |frame|
129
+ # text_field(:first_name, :id=> 'fname', :frame => frame)
130
+ # end
131
+ #
132
+ # @param [Hash] identifier how we find the frame. The valid keys are:
133
+ # * :id
134
+ # * :index
135
+ # * :name
136
+ # @param frame passed from a previous call to in_frame. Used to nest calls
137
+ # @param block that contains the calls to elements that exist inside the frame.
138
+ #
139
+ def in_frame(identifier, frame=nil, &block)
140
+ frame = frame.nil? ? [] : frame.dup
141
+ frame << {frame: identifier}
142
+ block.call(frame)
143
+ end
144
+ #
145
+ # Identify an element as existing within a frame or iframe. A frame parameter
146
+ # is passed to the block and must be passed to the other calls to Druid.
147
+ # You can nest calls to in_iframe by passing the frame to the next level.
148
+ #
149
+ # @example
150
+ # in_iframe(:id => 'frame_id') do |frame|
151
+ # text_field(:first_name, :id=> 'fname', :frame => frame)
152
+ # end
153
+ #
154
+ # @param [Hash] identifier how we find the frame. The valid keys are:
155
+ # * :id
156
+ # * :index
157
+ # * :name
158
+ # @param frame passed from a previous call to in_iframe. Used to nest calls
159
+ # @param block that contains the calls to elements that exist inside the frame.
160
+ #
161
+ def in_iframe(identifier, frame=nil, &block)
162
+ frame = frame.nil? ? [] : frame.dup
163
+ frame << {iframe: identifier}
164
+ block.call(frame)
165
+ end
166
+
167
+ #
168
+ # adds three methods - one to select a link, another
169
+ # to return a PageObject::Elements::Link object representing
170
+ # the link, and another that checks the link's existence.
171
+ #
172
+ # @example
173
+ # link(:add_to_cart, :text => "Add to Cart")
174
+ # # will generate 'add_to_cart', 'add_to_cart_element', and 'add_to_cart?' methods
175
+ #
176
+ # @param [Symbol] the name used for the generated methods
177
+ # @param [Hash] identifier how we find a link. You can use a multiple parameters
178
+ # by combining of any of the following except xpath. The valid values are:
179
+ # * :class
180
+ # * :href
181
+ # * :id
182
+ # * :index
183
+ # * :name
184
+ # * :text
185
+ # * :xpath
186
+ # * :link
187
+ # * :link_text
188
+ # * :css
189
+ # * :title
190
+ # @param optional block to be invoked when element method is called
191
+ #
192
+ def link(name, identifier={:index => 0}, &block)
193
+ standard_methods(name, identifier, 'link_for', &block)
194
+ define_method(name) do
195
+ return click_link_for identifier.clone unless block_given?
196
+ self.send("#{name}_element").click
197
+ end
198
+ end
199
+
200
+ alias_method :a, :link
201
+
202
+
203
+ #
204
+ # adds four methods to the page objec - one to set text in a text field,
205
+ # another to retrieve text from a text field, another to return the text
206
+ # field element, another to check the text field's existence.
207
+ #
208
+ # @example
209
+ # text_field(:first_name, :id => "first_name")
210
+ # # will generate 'first_name', 'first_name=', 'first_name_element',
211
+ # # 'first_name?' methods
212
+ #
213
+ # @param [Symbol] the name used for the generated methods
214
+ # @param [Hash] identifier how we find a text_field. You can use a multiple parameters
215
+ # @param optional block to be invoked when element method is called
216
+ #
217
+ def text_field(name, identifier={:index => 0}, &block)
218
+ standard_methods(name, identifier, 'text_field_for', &block)
219
+ define_method(name) do
220
+ return text_field_value_for identifier.clone unless block_given?
221
+ self.send("#{name}_element").value
222
+ end
223
+ define_method("#{name}=") do |value|
224
+ return text_field_value_set(identifier.clone, value) unless block_given?
225
+ self.send("#{name}_element").value = value
226
+ end
227
+ end
228
+
229
+ #
230
+ # adds five methods - one to check, another to uncheck, another
231
+ # to return the state of a checkbox, another to return
232
+ # a PageObject::Elements::CheckBox object representing the checkbox, and
233
+ # a final method to check the checkbox's existence.
234
+ #
235
+ # @example
236
+ # checkbox(:active, :name => "is_active")
237
+ # # will generate 'check_active', 'uncheck_active', 'active_checked?',
238
+ # # 'active_element', and 'active?' methods
239
+ #
240
+ # @param [Symbol] the name used for the generated methods
241
+ # @param [Hash] identifier how we find a checkbox. You can use a multiple parameters
242
+ # @param optional block to be invoked when element method is called
243
+ #
244
+ def checkbox(name, identifier={:index => 0}, &block)
245
+ standard_methods(name, identifier, 'checkbox_for', &block)
246
+ define_method("check_#{name}") do
247
+ return check_checkbox identifier.clone unless block_given?
248
+ self.send("#{name}_element").check
249
+ end
250
+ define_method("uncheck_#{name}") do
251
+ return uncheck_checkbox identifier.clone unless block_given?
252
+ self.send("#{name}_element").uncheck
253
+ end
254
+ define_method("#{name}_checked?") do
255
+ return checkbox_checked? identifier.clone unless block_given?
256
+ self.send("#{name}_element").checked?
257
+ end
258
+ end
259
+
260
+ #
261
+ # adds five methods - one to select an item in a drop-down,
262
+ # another to fetch the currently selected item text, another
263
+ # to retrieve the select list element, and another to check the
264
+ # drop down's existence and another to get all the available options
265
+ # to select from
266
+ #
267
+ # @example
268
+ # select_list(:state, :id => "state")
269
+ # # will generate 'state', 'state=', 'state_element', 'state?', 'state_options' methods
270
+ #
271
+ # @param [Symbol] the name used for the generated methods
272
+ # @param [Hash] identifier how we find a select_list. You can use a multiple parameters
273
+ # @param optional block to be invoked when element method is called
274
+ #
275
+ def select_list(name, identifier={:index => 0}, &block)
276
+ standard_methods(name, identifier, 'select_list_for', &block)
277
+ define_method(name) do
278
+ return select_list_value_for identifier.clone unless block_given?
279
+ self.send("#{name}_element").options.each {|o| return o.text if o.selected?}
280
+ end
281
+ define_method("#{name}=") do |value|
282
+ return select_list_value_set(identifier.clone, value) unless block_given?
283
+ self.send("#{name}_element").select(value)
284
+ end
285
+ define_method("#{name}_options") do
286
+ element = self.send("#{name}_element")
287
+ (element && element.options) ? element.options.collect(&:text) : []
288
+ end
289
+ end
290
+ alias_method :select, :select_list
291
+
292
+ #
293
+ # adds four methods - one to select, another to return if a radio button
294
+ # is selected, another method to return a PageObject::Elements::RadioButton
295
+ # object representing the radio button element, and another to check
296
+ # the radio button's existence.
297
+ #
298
+ # @example
299
+ # radio_button(:north, :id => "north")
300
+ # # will generate 'select_north', 'north_selected?',
301
+ # # 'north_element', and 'north?' methods
302
+ #
303
+ # @param [Symbol] the name used for the generated methods
304
+ # @param [Hash] identifier how we find a radio_button. You can use a multiple parameters
305
+ # @param optional block to be invoked when element method is called
306
+ #
307
+ def radio_button(name, identifier={:index => 0}, &block)
308
+ standard_methods(name, identifier, 'radio_button_for', &block)
309
+ define_method("select_#{name}") do
310
+ return select_radio identifier.clone unless block_given?
311
+ self.send("#{name}_element").select
312
+ end
313
+ define_method("#{name}_selected?") do
314
+ return radio_selected? identifier.clone unless block_given?
315
+ self.send("#{name}_element").selected?
316
+ end
317
+ end
318
+ alias_method :radio, :radio_button
319
+
320
+ def radio_button_group(name, identifier)
321
+ define_method("select_#{name}") do |value|
322
+ radio_buttons_for(identifier.clone).each do |radio_elem|
323
+ return radio_elem.select if radio_elem.value == value
324
+ end
325
+ end
326
+ define_method("#{name}_values") do
327
+ radio_buttons_for(identifier.clone).collect { |e| e.value}
328
+ end
329
+ define_method("#{name}_selected?") do
330
+ radio_buttons_for(identifier.clone).each do |radio_elem|
331
+ return radio_elem.value if radio_elem.selected?
332
+ end
333
+ return false
334
+ end
335
+ define_method("#{name}_elements") do
336
+ radio_buttons_for(identifier.clone)
337
+ end
338
+ define_method("#{name}?") do
339
+ radio_buttons_for(identifier.clone).any?
340
+ end
341
+ end
342
+ #
343
+ # adds three methods - one to click a button, another to
344
+ # return the button element, and another to check the button's existence.
345
+ #
346
+ # @example
347
+ # button(:purchase, :id => 'purchase')
348
+ # # will generate 'purchase', 'purchase_element', and 'purchase?' methods
349
+ #
350
+ # @param [Symbol] the name used for the generated methods
351
+ # @param [Hash] identifier how we find a button. You can use a multiple parameters
352
+ # @param optional block to be invoked when element method is called
353
+ #
354
+ def button(name, identifier={:index => 0}, &block)
355
+ standard_methods(name, identifier, 'button_for', &block)
356
+ define_method(name) do
357
+ return click_button_for identifier.clone unless block_given?
358
+ self.send("#{name}_element").click
359
+ end
360
+ end
361
+
362
+ #
363
+ # adds three methods - one to retrieve the text from a div,
364
+ # another to return the div element, and another to check the div's existence.
365
+ #
366
+ # @example
367
+ # div(:message, :id => 'message')
368
+ # # will generate 'message', 'message_element', and 'message?' methods
369
+ #
370
+ # @param [Symbol] the name used for the generated methods
371
+ # @param [Hash] identifier how we find a div. You can use a multiple parameters
372
+ # @param optional block to be invoked when element method is called
373
+ #
374
+ def div(name, identifier={:index => 0}, &block)
375
+ standard_methods(name, identifier, 'div_for', &block)
376
+ define_method(name) do
377
+ return div_text_for identifier.clone unless block_given?
378
+ self.send("#{name}_element").text
379
+ end
380
+ end
381
+
382
+ #
383
+ # adds three methods - one to retrieve the text for the table, one
384
+ # to retrieve the table element, and another to
385
+ # check the table's existence.
386
+ #
387
+ # @example
388
+ # table(:cart, :id => 'shopping_cart')
389
+ # # will generate a 'cart', 'cart_element' and 'cart?' method
390
+ #
391
+ # @param the name used for the generated methods
392
+ # @param identifier how we find a table. You can use a multiple parameters
393
+ # @param optional block to be invoked when element method is called
394
+ #
395
+ def table(name, identifier={:index => 0}, &block)
396
+ standard_methods(name, identifier, 'table_for', &block)
397
+ define_method(name) do
398
+ return table_text_for identifier.clone unless block_given?
399
+ self.send("#{name}_element").text
400
+ end
401
+ end
402
+
403
+ #
404
+ # adds three methods - one to retrieve the text from a table cell,
405
+ # another to return the table cell element, and another to check the cell's
406
+ # existence.
407
+ #
408
+ # @example
409
+ # cell(:total, :id => 'total_cell')
410
+ # # will generate 'total', 'total_element', and 'total?' methods
411
+ #
412
+ # @param [Symbol] the name used for the generated methods
413
+ # @param [Hash] identifier how we find a cell. You can use a multiple parameters
414
+ # @param optional block to be invoked when element method is called
415
+ #
416
+ def cell(name, identifier={:index => 0}, &block)
417
+ standard_methods(name, identifier, 'cell_for', &block)
418
+ define_method(name) do
419
+ return cell_text_for identifier.clone unless block_given?
420
+ self.send("#{name}_element").text
421
+ end
422
+ end
423
+ alias_method :td, :cell
424
+
425
+ #
426
+ # adds three methods - one to retrieve the text from a table row,
427
+ # another to return the table row element, and another to check the row's
428
+ # existence.
429
+ #
430
+ # @example
431
+ # row(:sums, :id => 'sum_row')
432
+ # # will generate 'sums', 'sums_element', and 'sums?' methods
433
+ #
434
+ # @param [Symbol] the name used for the generated methods
435
+ # @param [Hash] identifier how we find a cell. You can use a multiple parameters
436
+ # @param optional block to be invoked when element method is called
437
+ #
438
+ def row(name, identifier={:index => 0}, &block)
439
+ standard_methods(name, identifier, 'row_for', &block)
440
+ define_method(name) do
441
+ return row_text_for identifier.clone unless block_given?
442
+ self.send("#{name}_element").text
443
+ end
444
+ end
445
+
446
+ #
447
+ # adds three methods - one to retrieve the text from a span,
448
+ # another to return the span element, and another to check the span's existence.
449
+ #
450
+ # @example
451
+ # span(:alert, :id => 'alert')
452
+ # # will generate 'alert', 'alert_element', and 'alert?' methods
453
+ #
454
+ # @param [Symbol] the name used for the generated methods
455
+ # @param [Hash] identifier how we find a span. You can use a multiple parameters
456
+ # @param optional block to be invoked when element method is called
457
+ #
458
+ def span(name, identifier={:index => 0}, &block)
459
+ standard_methods(name, identifier, 'span_for', &block)
460
+ define_method(name) do
461
+ return span_text_for identifier.clone unless block_given?
462
+ self.send("#{name}_element").text
463
+ end
464
+ end
465
+
466
+ #
467
+ # adds two methods - one to retrieve the image element, and another to
468
+ # check the image's existence.
469
+ #
470
+ # @example
471
+ # image(:logo, :id => 'logo')
472
+ # # will generate 'logo_element', 'logo_loaded?' and 'logo?' methods
473
+ #
474
+ # @param [Symbol] the name used for the generated methods
475
+ # @param [Hash] identifier how we find a image. You can use a multiple parameters
476
+ # @param optional block to be invoked when element method is called
477
+ #
478
+ def image(name, identifier={:index => 0}, &block)
479
+ standard_methods(name, identifier, 'image_for', &block)
480
+ define_method("#{name}_loaded?") do
481
+ return image_loaded_for identifier.clone unless block_given?
482
+ self.send("#{name}_element").loaded?
483
+ end
484
+ end
485
+ alias_method :img, :image
486
+
487
+ #
488
+ # adds two methods - one to retrieve the form element, and another to
489
+ # check the form's existence.
490
+ #
491
+ # @example
492
+ # form(:login, :id => 'login')
493
+ # # will generate 'login_element' and 'login?' methods
494
+ #
495
+ # @param [Symbol] the name used for the generated methods
496
+ # @param [Hash] identifier how we find a form. You can use a multiple parameters
497
+ # @param optional block to be invoked when element method is called
498
+ #
499
+ def form(name, identifier={:index => 0}, &block)
500
+ standard_methods(name, identifier, 'form_for', &block)
501
+ end
502
+
503
+ #
504
+ # adds three methods to the page object - one to get the text from a hidden field,
505
+ # another to retrieve the hidden field element, and another to check the hidden
506
+ # field's existence.
507
+ #
508
+ # @example
509
+ # hidden_field(:user_id, :id => "user_identity")
510
+ # # will generate 'user_id', 'user_id_element' and 'user_id?' methods
511
+ #
512
+ # @param [Symbol] the name used for the generated methods
513
+ # @param [Hash] identifier how we find a hidden field. You can use a multiple parameters
514
+ # @param optional block to be invoked when element method is called
515
+ #
516
+ def hidden_field(name, identifier={:index => 0}, &block)
517
+ standard_methods(name, identifier, 'hidden_field_for', &block)
518
+ define_method(name) do
519
+ return hidden_field_value_for identifier.clone unless block_given?
520
+ self.send("#{name}_element").value
521
+ end
522
+ end
523
+ alias_method :hidden, :hidden_field
524
+
525
+ #
526
+ # adds three methods - one to retrieve the text from a list item,
527
+ # another to return the list item element, and another to check the list item's
528
+ # existence.
529
+ #
530
+ # @example
531
+ # list_item(:item_one, :id => 'one')
532
+ # # will generate 'item_one', 'item_one_element', and 'item_one?' methods
533
+ #
534
+ # @param [Symbol] the name used for the generated methods
535
+ # @param [Hash] identifier how we find a list item. You can use a multiple parameters
536
+ # @param optional block to be invoked when element method is called
537
+ #
538
+ def list_item(name, identifier={:index => 0}, &block)
539
+ standard_methods(name, identifier, 'list_item_for', &block)
540
+ define_method(name) do
541
+ return list_item_text_for identifier.clone unless block_given?
542
+ self.send("#{name}_element").text
543
+ end
544
+ end
545
+ alias_method :li, :list_item
546
+
547
+ #
548
+ # adds three methods - one to return the text within the ordered
549
+ # list, one to retrieve the ordered list element, and another to
550
+ # test it's existence.
551
+ #
552
+ # @example
553
+ # ordered_list(:top_five, :id => 'top')
554
+ # # will generate 'top_five' 'top_five_element' and 'top_five?' methods
555
+ #
556
+ # @param [Symbol] the name used for the generated methods
557
+ # @param [Hash] identifier how we find an ordered list. You can use a multiple parameters
558
+ # @param optional block to be invoked when element method is called
559
+ #
560
+ def ordered_list(name, identifier={:index => 0}, &block)
561
+ standard_methods(name, identifier, 'ordered_list_for', &block)
562
+ define_method(name) do
563
+ return ordered_list_text_for identifier.clone unless block_given?
564
+ self.send("#{name}_element").text
565
+ end
566
+ end
567
+ alias_method :ol, :ordered_list
568
+
569
+ #
570
+ # adds four methods to the page object - one to set text in a text area,
571
+ # another to retrieve text from a text area, another to return the text
572
+ # area element, and another to check the text area's existence.
573
+ #
574
+ # @example
575
+ # text_area(:address, :id => "address")
576
+ # # will generate 'address', 'address=', 'address_element',
577
+ # # 'address?' methods
578
+ #
579
+ # @param [Symbol] the name used for the generated methods
580
+ # @param [Hash] identifier how we find a text area. You can use a multiple parameters
581
+ # @param optional block to be invoked when element method is called
582
+ #
583
+ def text_area(name, identifier={:index => 0}, &block)
584
+ standard_methods(name, identifier, 'text_area_for', &block)
585
+ define_method("#{name}=") do |value|
586
+ return text_area_value_set(identifier.clone, value) unless block_given?
587
+ self.send("#{name}_element").value = value
588
+ end
589
+ define_method(name) do
590
+ return text_area_value_for identifier.clone unless block_given?
591
+ self.send("#{name}_element").value
592
+ end
593
+ end
594
+ alias_method :textarea, :text_area
595
+
596
+ #
597
+ # adds three methods - one to return the text of unordered list, another one
598
+ # retrieve the unordered list element, and another to check it's existence.
599
+ #
600
+ # @example
601
+ # unordered_list(:menu, :id => 'main_menu')
602
+ # # will generate 'menu' 'menu_element' and 'menu?' methods
603
+ #
604
+ # @param [Symbol] the name used for the generated methods
605
+ # @param [Hash] identifier how we find an unordered list. You can use a multiple parameters
606
+ # @param optional block to be invoked when element method is called
607
+ def unordered_list(name, identifier={:index => 0}, &block)
608
+ standard_methods(name, identifier, 'unordered_list_for', &block)
609
+ define_method(name) do
610
+ return unordered_list_text_for identifier.clone unless block_given?
611
+ self.send("#{name}_element").text
612
+ end
613
+ end
614
+ alias_method :ul, :unordered_list
615
+
616
+ #
617
+ # adds three methods - one to retrieve the text of a h1 element, another to
618
+ # retrieve a h1 element, and another to check for it's existence.
619
+ #
620
+ # @example
621
+ # h1(:title, :id => 'title')
622
+ # # will generate 'title', 'title_element', and 'title?' methods
623
+ #
624
+ # @param [Symbol] the name used for the generated methods
625
+ # @param [Hash] identifier how we find a H1. You can use a multiple paramaters
626
+ # @param optional block to be invoked when element method is called
627
+ #
628
+ def h1(name, identifier={:index => 0}, &block)
629
+ standard_methods(name, identifier, 'h1_for', &block)
630
+ define_method(name) do
631
+ return h1_text_for identifier.clone unless block_given?
632
+ self.send("#{name}_element").text
633
+ end
634
+ end
635
+
636
+ #
637
+ # adds three methods - one to retrieve the text of a h2 element, another
638
+ # to retrieve a h2 element, and another to check for it's existence.
639
+ #
640
+ # @example
641
+ # h2(:title, :id => 'title')
642
+ # # will generate 'title', 'title_element', and 'title?' methods
643
+ #
644
+ # @param [Symbol] the name used for the generated methods
645
+ # @param [Hash] identifier how we find a H2. You can use a multiple paramaters
646
+ # @param optional block to be invoked when element method is called
647
+ #
648
+ def h2(name, identifier={:index => 0}, &block)
649
+ standard_methods(name, identifier, 'h2_for', &block)
650
+ define_method(name) do
651
+ return h2_text_for identifier.clone unless block_given?
652
+ self.send("#{name}_element").text
653
+ end
654
+ end
655
+
656
+ #
657
+ # adds three methods - one to retrieve the text of a h3 element,
658
+ # another to return a h3 element, and another to check for it's existence.
659
+ #
660
+ # @example
661
+ # h3(:title, :id => 'title')
662
+ # # will generate 'title', 'title_element', and 'title?' methods
663
+ #
664
+ # @param [Symbol] the name used for the generated methods
665
+ # @param [Hash] identifier how we find a H3. You can use a multiple paramaters
666
+ # @param optional block to be invoked when element method is called
667
+ #
668
+ def h3(name, identifier={:index => 0}, &block)
669
+ standard_methods(name, identifier, 'h3_for', &block)
670
+ define_method(name) do
671
+ return h3_text_for identifier.clone unless block_given?
672
+ self.send("#{name}_element").text
673
+ end
674
+ end
675
+
676
+ #
677
+ # adds three methods - one to retrieve the text of a h4 element,
678
+ # another to return a h4 element, and another to check for it's existence.
679
+ #
680
+ # @example
681
+ # h4(:title, :id => 'title')
682
+ # # will generate 'title', 'title_element', and 'title?' methods
683
+ #
684
+ # @param [Symbol] the name used for the generated methods
685
+ # @param [Hash] identifier how we find a H4. You can use a multiple paramaters
686
+ # @param optional block to be invoked when element method is called
687
+ #
688
+ def h4(name, identifier={:index => 0}, &block)
689
+ standard_methods(name, identifier, 'h4_for', &block)
690
+ define_method(name) do
691
+ return h4_text_for identifier.clone unless block_given?
692
+ self.send("#{name}_element").text
693
+ end
694
+ end
695
+
696
+ #
697
+ # adds three methods - one to retrieve the text of a h5 element,
698
+ # another to return a h5 element, and another to check for it's existence.
699
+ #
700
+ # @example
701
+ # h5(:title, :id => 'title')
702
+ # # will generate 'title', 'title_element', and 'title?' methods
703
+ #
704
+ # @param [Symbol] the name used for the generated methods
705
+ # @param [Hash] identifier how we find a H5. You can use a multiple paramaters
706
+ # @param optional block to be invoked when element method is called
707
+ #
708
+ def h5(name, identifier={:index => 0}, &block)
709
+ standard_methods(name, identifier, 'h5_for', &block)
710
+ define_method(name) do
711
+ return h5_text_for identifier.clone unless block_given?
712
+ self.send("#{name}_element").text
713
+ end
714
+ end
715
+
716
+ #
717
+ # adds three methods - one to retrieve the text of a h6 element,
718
+ # another to return a h6 element, and another to check for it's existence.
719
+ #
720
+ # @example
721
+ # h6(:title, :id => 'title')
722
+ # # will generate 'title', 'title_element', and 'title?' methods
723
+ #
724
+ # @param [Symbol] the name used for the generated methods
725
+ # @param [Hash] identifier how we find a H6. You can use a multiple paramaters
726
+ # @param optional block to be invoked when element method is called
727
+ #
728
+ def h6(name, identifier={:index => 0}, &block)
729
+ standard_methods(name, identifier, 'h6_for', &block)
730
+ define_method(name) do
731
+ return h6_text_for identifier.clone unless block_given?
732
+ self.send("#{name}_element").text
733
+ end
734
+ end
735
+
736
+ #
737
+ # adds three methods - one to retrieve the text of a paragraph, another
738
+ # to retrieve a paragraph element, and another to check the paragraph's existence.
739
+ #
740
+ # @example
741
+ # paragraph(:title, :id => 'title')
742
+ # # will generate 'title', 'title_element', and 'title?' methods
743
+ #
744
+ # @param [Symbol] the name used for the generated methods
745
+ # @param [Hash] identifier how we find a paragraph. You can use a multiple paramaters
746
+ # @param optional block to be invoked when element method is called
747
+ #
748
+ def paragraph(name, identifier={:index => 0}, &block)
749
+ standard_methods(name, identifier, 'paragraph_for', &block)
750
+ define_method(name) do
751
+ return paragraph_text_for identifier.clone unless block_given?
752
+ self.send("#{name}_element").text
753
+ end
754
+ end
755
+ alias_method :p, :paragraph
756
+
757
+ #
758
+ # adds three methods - one to set the file for a file field, another to retrieve
759
+ # the file field element, and another to check it's existence.
760
+ #
761
+ # @example
762
+ # file_field(:the_file, :id => 'file_to_upload')
763
+ # # will generate 'the_file=', 'the_file_element', and 'the_file?' methods
764
+ #
765
+ # @param [Symbol] the name used for the generated methods
766
+ # @param [Hash] identifier how we find a file_field. You can use a multiple paramaters
767
+ # @param optional block to be invoked when element method is called
768
+ #
769
+ def file_field(name, identifier={:index => 0}, &block)
770
+ standard_methods(name, identifier, 'file_field_for', &block)
771
+ define_method("#{name}=") do |value|
772
+ return file_field_value_set(identifier.clone, value) unless block_given?
773
+ self.send("#{name}_element").value = value
774
+ end
775
+ end
776
+
777
+ #
778
+ # adds three methods - one to retrieve the text from a label,
779
+ # another to return the label element, and another to check the label's existence.
780
+ #
781
+ # @example
782
+ # label(:message, :id => 'message')
783
+ # # will generate 'message', 'message_element', and 'message?' methods
784
+ #
785
+ # @param [Symbol] the name used for the generated methods
786
+ # @param [Hash] identifier how we find a label. You can use a multiple parameters
787
+ # @param optional block to be invoked when element method is called
788
+ #
789
+ def label(name, identifier={:index => 0}, &block)
790
+ standard_methods(name, identifier, 'label_for', &block)
791
+ define_method(name) do
792
+ return label_text_for identifier.clone unless block_given?
793
+ self.send("#{name}_element").text
794
+ end
795
+ end
796
+
797
+ #
798
+ # adds three methods - one to click the area,
799
+ # another to return the area element, and another to check the area's existence.
800
+ #
801
+ # @example
802
+ # area(:message, :id => 'message')
803
+ # # will generate 'message', 'message_element', and 'message?' methods
804
+ #
805
+ # @param [Symbol] the name used for the generated methods
806
+ # @param [Hash] identifier how we find an area. You can use a multiple parameters
807
+ # @param optional block to be invoked when element method is called
808
+ #
809
+ def area(name, identifier={:index => 0}, &block)
810
+ standard_methods(name, identifier, 'area_for', &block)
811
+ define_method(name) do
812
+ return click_area_for identifier.clone unless block_given?
813
+ self.send("#{name}_element").click
814
+ end
815
+ end
816
+
817
+ #
818
+ # adds two method - one to return the canvas element and another to check
819
+ # the canvas's existence.
820
+ #
821
+ # @example
822
+ # canvas(:my_canvas, :id => 'canvas_id')
823
+ # # will generate 'my_canvas_element' and 'my_canvas?' methods
824
+ #
825
+ # @param [Symbol] the name used for the generated methods
826
+ # @param [Hash] identifier how we find a canvas. You can use a multiple parameters
827
+ # @param optional block to be invoked when element method is called
828
+ #
829
+ def canvas(name, identifier={:index => 0}, &block)
830
+ standard_methods(name, identifier, 'canvas_for', &block)
831
+ end
832
+
833
+ #
834
+ # adds two methods - one to return the audio element and another to check
835
+ # the audio's existence
836
+ #
837
+ # @example
838
+ # audio(:acdc, :id => 'audio_id')
839
+ # # will generate 'acdc_element' and 'acdc?' methods
840
+ #
841
+ # @param [Symbol] the name used for the generated methods
842
+ # @param [Hash] identifier how we find an audio element. You can use a multiple parameters
843
+ # @param optional block to be invoked when element method is called
844
+ #
845
+ def audio(name, identifier={:index => 0}, &block)
846
+ standard_methods(name, identifier, 'audio_for', &block)
847
+ end
848
+
849
+ #
850
+ # adds two methods - one to return the video element and another to check
851
+ # the video's existence
852
+ #
853
+ # @example
854
+ # video(:movie, :id => 'video_id')
855
+ # # will generate 'movie_element' and 'movie?' methods
856
+ #
857
+ # @param [Symbol] the name used for the generated methods
858
+ # @param [Hash] identifier how we find a video element. You can use a multiple parameters
859
+ # @param optional block to be invoked when element method is called
860
+ #
861
+ def video(name, identifier={:index => 0}, &block)
862
+ standard_methods(name, identifier, 'video_for', &block)
863
+ end
864
+
865
+ #
866
+ # adds three methods - one to retrieve the text of a b element, another to
867
+ # retrieve a b element, and another to check for it's existence.
868
+ #
869
+ # @example
870
+ # b(:blod, :id => 'title')
871
+ # # will generate 'bold', 'bold_element', 'bold?' methods
872
+ #
873
+ # @param [Symbol] the name used for the generated methods
874
+ # @param [Hash] identifier how we find a b, You can use a multiple parameters
875
+ # @param optional block to be invoked when element method is called
876
+ #
877
+ def b(name, identifier={:index => 0}, &block)
878
+ standard_methods(name, identifier, 'b_for', &block)
879
+ define_method(name) do
880
+ return b_text_for identifier.clone unless block_given?
881
+ self.send("#{name}_element").text
882
+ end
883
+ end
884
+
885
+ #
886
+ # adds three methods - one to retrieve the text of a i element, another to
887
+ # retrieve a b element, and another to check for it's existence.
888
+ #
889
+ # @example
890
+ # i(:italic, :id => 'title')
891
+ # # will generate 'italic', 'italic_element', 'italic?' methods
892
+ #
893
+ # @param [Symbol] the name used for the generated methods
894
+ # @param [Hash] identifier how we find a i, You can use a multiple parameters
895
+ # @param optional block to be invoked when element method is called
896
+ #
897
+ def i(name, identifier={:index => 0}, &block)
898
+ standard_methods(name, identifier, 'i_for', &block)
899
+ define_method(name) do
900
+ return i_text_for identifier.clone unless block_given?
901
+ self.send("#{name}_element").text
902
+ end
903
+ end
904
+ alias_method :icon, :i
905
+
906
+ #
907
+ # adds two methods - one to retrieve a svg, and another to check
908
+ # svg's existence.
909
+ #
910
+ # @example
911
+ # svg(:circle, :id => 'circle')
912
+ # # will generate 'circle_element', and 'circle?' methods
913
+ #
914
+ # @param [Symbol] the name used for the generated methods
915
+ # @param [Hash] identifier how we find a svg. You can use a multiple parameters
916
+ # @param optional block to be invoked when element method is called
917
+ #
918
+ def svg(name, identifier={:index => 0}, &block)
919
+ standard_methods(name, identifier, 'svg_for', &block)
920
+ end
921
+
922
+ #
923
+ # adds three methods - one to retrieve the text an element, another
924
+ # to retrieve an element, and another to check the element's existence.
925
+ #
926
+ # @example
927
+ # element(:titile, :id => 'title')
928
+ # # will generate 'title'm 'title_element', and 'title?' methods
929
+ #
930
+ # @param [Symbol] the name used for the generated methods
931
+ # @param [Hash] identifier how we find an element. You can use a multiple parameters
932
+ # @param optional block to be invoked when element method is called
933
+ #
934
+ def element(name, tag=:element, identifier={:index => 0}, &block)
935
+ #
936
+ # sets tag as element if not defined
937
+ #
938
+ if tag.is_a? Hash
939
+ identifier = tag
940
+ tag = :element
941
+ end
942
+
943
+ define_method("#{name}") do
944
+ self.send("#{name}_element").text
945
+ end
946
+ define_method("#{name}_element") do
947
+ return call_block(&block) if block_given?
948
+ element_for(tag, identifier.clone)
949
+ end
950
+ define_method("#{name}?") do
951
+ self.send("#{name}_element").exist?
952
+ end
953
+ end
954
+
955
+ #
956
+ # adds a method to return a collection of generic Element objects
957
+ # for a specific tag
958
+ #
959
+ # @example
960
+ # elements(:title, :header, :id => 'title')
961
+ # # will generate 'title_elements'
962
+ #
963
+ # @param [Symbol] the name used for the generated methods
964
+ # @param [Symbol] the name of the tag for the element
965
+ # @param [Hash] identifier how we find an element. You can use a multiple parameters
966
+ # @param optional block to be invoked when element method is called
967
+ #
968
+ def elements(name, tag=:element, identifier={:index => 0}, &block)
969
+ #
970
+ # sets tag as element if not defined
971
+ #
972
+ if tag.is_a? Hash
973
+ identifier = tag
974
+ tag = :element
975
+ end
976
+
977
+ define_method("#{name}_elements") do
978
+ return call_block(&block) if block_given?
979
+ elements_for(tag, identifier.clone)
980
+ end
981
+ end
982
+
983
+ def standard_methods(name, identifier, method, &block)
984
+ define_method("#{name}_element") do
985
+ return call_block(&block) if block_given?
986
+ self.send(method, identifier.clone)
987
+ end
988
+ define_method("#{name}?") do
989
+ return call_block(&block).exist? if block_given?
990
+ self.send(method, identifier.clone).exist?
991
+ end
992
+ end
993
+
994
+ #
995
+ # adds a method to return a page object rooted at the element
996
+ #
997
+ # @example
998
+ # page_section(:navigation_bar, NavigationBar, :id => 'nav-bar')
999
+ # # will generate 'navigation_bar'
1000
+ #
1001
+ # @param [Symbol] the name used for the generated methods
1002
+ # @param [Class] the class to instantiate for the element
1003
+ # @param [Hash] identifier how we find an element. You can use multiple parameters
1004
+
1005
+ def page_section(name, section_class, identifier)
1006
+ define_method(name) do
1007
+ page_for(identifier, section_class)
1008
+ end
1009
+ end
1010
+
1011
+ #
1012
+ # adds a method to return a collection of page objects rooted at elements
1013
+ #
1014
+ # @example
1015
+ # page_sections(:articles, Article, :class => 'article')
1016
+ # # will generate 'articles'
1017
+ #
1018
+ # @param [Symbol] the name used for the generated method
1019
+ # @param [Class] the class to instantiate for each element
1020
+ # @param [Hash] identifier how we find an element. You can use a multiple parameters
1021
+
1022
+ def page_sections(name, section_class, identifier)
1023
+ define_method(name) do
1024
+ pages_for(identifier, section_class)
1025
+ end
1026
+ end
1027
+
1028
+ #
1029
+ # methods to generate accessors for types that follow the same
1030
+ # pattern as element
1031
+ #
1032
+ # @example
1033
+ # address(:my_article, :id => "article_id")
1034
+ # will generate 'my_article', 'my_article_element' and 'my_article?'
1035
+ #
1036
+ # @param [Symbol] the name used for the generated methods
1037
+ # @param [Symbol] the name of the tag for the element
1038
+ # @param [Hash] identifier how we find an element. You can use a multiple paramaters
1039
+ # @param optional block to be invoked when element method is called
1040
+ #
1041
+ LocatorGenerator::BASIC_ELEMENTS.each do |tag|
1042
+ define_method(tag) do |name, *identifier, &block|
1043
+ identifier = identifier[0] ? identifier[0] : {:index => 0}
1044
+ element(name, tag, identifier, &block)
1045
+ end
1046
+
1047
+ define_method("#{tag}s") do |name, *identifier, &block|
1048
+ identifier = identifier[0] ? identifier[0] : {:index => 0}
1049
+ elements(name, tag, identifier, &block)
1050
+ end unless tag == :param
1051
+ end
1052
+
1053
+ #
1054
+ # methods to fetch multiple elements of the same type
1055
+ #
1056
+ # adds a method to the page objec to retrun all of the matching elements
1057
+ #
1058
+ # @example
1059
+ # text_fields(:first_name, :id => "first_name")
1060
+ # # will generate 'first_name_elements'
1061
+ #
1062
+ # @param [String] the name used for the generated methods
1063
+ # @param [Hash] identifier how we find a text field. You can use a multiple paramaters
1064
+ # by combining of any of the following except xpath. The valid
1065
+ # keys are the same ones supported by the standard methods.
1066
+ # @param optional block to be invoked when element method is called
1067
+ #
1068
+ idx = LocatorGenerator::ADVANCED_ELEMENTS.find_index { |type| type == :checkbox}
1069
+ elements = LocatorGenerator::ADVANCED_ELEMENTS.clone
1070
+ elements[idx] = :checkboxe
1071
+ elements.each do |method_name|
1072
+ define_method("#{method_name}s") do |name, *identifier, &block|
1073
+ define_method("#{name}_elements") do
1074
+ return call_block(&block) unless block.nil?
1075
+ platform_method = (method_name == :checkboxe) ? 'checkboxs_for' : "#{method_name.to_s}s_for"
1076
+ self.send platform_method, (identifier.first ? identifier.first.clone : {})
1077
+ end
1078
+ end
1079
+ end
1080
+
1081
+ end
1082
+ end