meeane-page-object 0.1.10 → 0.1.11

Sign up to get free protection for your applications and to get access to all the features.
Files changed (253) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +7 -7
  3. data/.rspec +2 -2
  4. data/.ruby-gemset +1 -1
  5. data/.ruby-version +1 -1
  6. data/.travis.yml +10 -10
  7. data/ChangeLog +790 -790
  8. data/Gemfile +13 -13
  9. data/Guardfile +20 -20
  10. data/LICENSE +20 -20
  11. data/README.md +1 -1
  12. data/Rakefile +35 -35
  13. data/cucumber.yml +10 -10
  14. data/features/area.feature +35 -35
  15. data/features/async.feature +30 -30
  16. data/features/audio.feature +68 -68
  17. data/features/button.feature +88 -87
  18. data/features/canvas.feature +37 -37
  19. data/features/check_box.feature +55 -55
  20. data/features/div.feature +45 -45
  21. data/features/element.feature +322 -322
  22. data/features/file_field.feature +40 -40
  23. data/features/form.feature +43 -43
  24. data/features/frames.feature +75 -75
  25. data/features/generic_elements.feature +29 -29
  26. data/features/gxt_table_extension.feature +24 -24
  27. data/features/headings.feature +97 -97
  28. data/features/hidden_field.feature +45 -45
  29. data/features/html/async.html +36 -36
  30. data/features/html/double_click.html +12 -12
  31. data/features/html/failure.html +7 -7
  32. data/features/html/frame_1.html +17 -17
  33. data/features/html/frame_2.html +15 -15
  34. data/features/html/frame_3.html +14 -14
  35. data/features/html/frames.html +12 -12
  36. data/features/html/hover.html +11 -11
  37. data/features/html/iframes.html +12 -12
  38. data/features/html/indexed_property.html +51 -51
  39. data/features/html/modal.html +17 -17
  40. data/features/html/modal_1.html +37 -37
  41. data/features/html/modal_2.html +26 -26
  42. data/features/html/multi_elements.html +144 -144
  43. data/features/html/nested_elements.html +77 -77
  44. data/features/html/nested_frame_2.html +11 -11
  45. data/features/html/nested_frame_3.html +14 -14
  46. data/features/html/nested_frames.html +10 -10
  47. data/features/html/static_elements.html +233 -226
  48. data/features/html/success.html +7 -7
  49. data/features/html/sun.html +7 -7
  50. data/features/image.feature +50 -50
  51. data/features/indexed_property.feature +97 -97
  52. data/features/javascript.feature +27 -27
  53. data/features/label.feature +46 -46
  54. data/features/link.feature +52 -52
  55. data/features/list_item.feature +36 -36
  56. data/features/modal_dialog.feature +15 -15
  57. data/features/multi_elements.feature +486 -486
  58. data/features/nested_elements.feature +117 -117
  59. data/features/ordered_list.feature +56 -56
  60. data/features/page_level_actions.feature +90 -90
  61. data/features/paragraph.feature +35 -35
  62. data/features/radio_button.feature +58 -58
  63. data/features/radio_button_collinson.feature +12 -58
  64. data/features/radio_button_group.feature +29 -29
  65. data/features/sample-app/public/jquery-1.3.2.js +4376 -4376
  66. data/features/sample-app/public/jquery.html +30 -30
  67. data/features/sample-app/public/prototype-1.6.0.3.js +4319 -4319
  68. data/features/sample-app/public/prototype.html +35 -35
  69. data/features/sample-app/sample_app.rb +35 -35
  70. data/features/select_list.feature +86 -86
  71. data/features/span.feature +37 -37
  72. data/features/step_definitions/accessor_steps.rb +60 -60
  73. data/features/step_definitions/area_steps.rb +19 -19
  74. data/features/step_definitions/async_steps.rb +83 -83
  75. data/features/step_definitions/audio_steps.rb +27 -27
  76. data/features/step_definitions/button_steps.rb +43 -43
  77. data/features/step_definitions/canvas_steps.rb +15 -15
  78. data/features/step_definitions/check_box_steps.rb +35 -35
  79. data/features/step_definitions/div_steps.rb +19 -19
  80. data/features/step_definitions/element_steps.rb +266 -266
  81. data/features/step_definitions/file_field_steps.rb +19 -19
  82. data/features/step_definitions/form_steps.rb +18 -18
  83. data/features/step_definitions/frames_steps.rb +159 -159
  84. data/features/step_definitions/generic_element_steps.rb +31 -31
  85. data/features/step_definitions/gxt_table_steps.rb +58 -58
  86. data/features/step_definitions/headings_steps.rb +12 -12
  87. data/features/step_definitions/hidden_field_steps.rb +26 -26
  88. data/features/step_definitions/image_steps.rb +27 -27
  89. data/features/step_definitions/indexed_property_steps.rb +128 -128
  90. data/features/step_definitions/javascript_steps.rb +52 -52
  91. data/features/step_definitions/label_steps.rb +19 -19
  92. data/features/step_definitions/link_steps.rb +40 -40
  93. data/features/step_definitions/list_item_steps.rb +19 -19
  94. data/features/step_definitions/modal_dialog_steps.rb +62 -62
  95. data/features/step_definitions/multi_elements_steps.rb +528 -528
  96. data/features/step_definitions/nested_elements_steps.rb +212 -212
  97. data/features/step_definitions/ordered_list_steps.rb +23 -23
  98. data/features/step_definitions/page_level_actions_steps.rb +135 -135
  99. data/features/step_definitions/page_traversal_steps.rb +4 -4
  100. data/features/step_definitions/paragraph_steps.rb +28 -28
  101. data/features/step_definitions/radio_button_collinson_steps.rb +2 -46
  102. data/features/step_definitions/radio_button_group_steps.rb +35 -35
  103. data/features/step_definitions/radio_button_steps.rb +26 -46
  104. data/features/step_definitions/select_list_steps.rb +65 -65
  105. data/features/step_definitions/span_steps.rb +19 -19
  106. data/features/step_definitions/table_cell_steps.rb +14 -14
  107. data/features/step_definitions/table_steps.rb +66 -66
  108. data/features/step_definitions/text_area_steps.rb +34 -34
  109. data/features/step_definitions/text_field_steps.rb +35 -35
  110. data/features/step_definitions/unordered_list_steps.rb +23 -23
  111. data/features/step_definitions/video_steps.rb +45 -45
  112. data/features/support/ajax_text_environment.rb +26 -26
  113. data/features/support/env.rb +8 -8
  114. data/features/support/hooks.rb +8 -8
  115. data/features/support/page.rb +370 -364
  116. data/features/support/persistent_browser.rb +70 -70
  117. data/features/support/targets/firefox14_osx.rb +6 -6
  118. data/features/support/targets/firefox14_windows7.rb +6 -6
  119. data/features/support/url_helper.rb +57 -57
  120. data/features/table.feature +114 -114
  121. data/features/table_cell.feature +45 -45
  122. data/features/text_area.feature +51 -51
  123. data/features/text_field.feature +70 -70
  124. data/features/unordered_list.feature +56 -56
  125. data/features/video.feature +73 -73
  126. data/lib/page-object.rb +408 -408
  127. data/lib/page-object/accessors.rb +1313 -1313
  128. data/lib/page-object/core_ext/string.rb +4 -4
  129. data/lib/page-object/element_locators.rb +21 -21
  130. data/lib/page-object/elements.rb +59 -59
  131. data/lib/page-object/elements/area.rb +31 -31
  132. data/lib/page-object/elements/audio.rb +9 -9
  133. data/lib/page-object/elements/button.rb +35 -35
  134. data/lib/page-object/elements/canvas.rb +23 -23
  135. data/lib/page-object/elements/check_box.rb +37 -37
  136. data/lib/page-object/elements/div.rb +19 -19
  137. data/lib/page-object/elements/element.rb +226 -226
  138. data/lib/page-object/elements/file_field.rb +38 -38
  139. data/lib/page-object/elements/form.rb +36 -36
  140. data/lib/page-object/elements/heading.rb +15 -15
  141. data/lib/page-object/elements/hidden_field.rb +22 -22
  142. data/lib/page-object/elements/image.rb +36 -36
  143. data/lib/page-object/elements/label.rb +36 -36
  144. data/lib/page-object/elements/link.rb +46 -46
  145. data/lib/page-object/elements/list_item.rb +19 -19
  146. data/lib/page-object/elements/media.rb +45 -45
  147. data/lib/page-object/elements/option.rb +10 -10
  148. data/lib/page-object/elements/ordered_list.rb +50 -50
  149. data/lib/page-object/elements/paragraph.rb +9 -9
  150. data/lib/page-object/elements/radio_button.rb +37 -37
  151. data/lib/page-object/elements/select_list.rb +42 -42
  152. data/lib/page-object/elements/span.rb +19 -19
  153. data/lib/page-object/elements/table.rb +68 -68
  154. data/lib/page-object/elements/table_cell.rb +28 -28
  155. data/lib/page-object/elements/table_row.rb +50 -50
  156. data/lib/page-object/elements/text_area.rb +38 -38
  157. data/lib/page-object/elements/text_field.rb +42 -42
  158. data/lib/page-object/elements/unordered_list.rb +51 -51
  159. data/lib/page-object/elements/video.rb +18 -18
  160. data/lib/page-object/indexed_properties.rb +36 -36
  161. data/lib/page-object/javascript/jquery.rb +14 -14
  162. data/lib/page-object/javascript/prototype.rb +14 -14
  163. data/lib/page-object/javascript/yui.rb +18 -18
  164. data/lib/page-object/javascript_framework_facade.rb +78 -78
  165. data/lib/page-object/loads_platform.rb +26 -26
  166. data/lib/page-object/locator_generator.rb +129 -129
  167. data/lib/page-object/nested_elements.rb +17 -17
  168. data/lib/page-object/page_factory.rb +108 -108
  169. data/lib/page-object/page_populator.rb +92 -92
  170. data/lib/page-object/platforms.rb +18 -18
  171. data/lib/page-object/platforms/selenium_webdriver.rb +17 -17
  172. data/lib/page-object/platforms/selenium_webdriver/button.rb +14 -14
  173. data/lib/page-object/platforms/selenium_webdriver/check_box.rb +29 -29
  174. data/lib/page-object/platforms/selenium_webdriver/element.rb +291 -291
  175. data/lib/page-object/platforms/selenium_webdriver/file_field.rb +16 -16
  176. data/lib/page-object/platforms/selenium_webdriver/form.rb +16 -16
  177. data/lib/page-object/platforms/selenium_webdriver/image.rb +28 -28
  178. data/lib/page-object/platforms/selenium_webdriver/label.rb +17 -18
  179. data/lib/page-object/platforms/selenium_webdriver/link.rb +23 -23
  180. data/lib/page-object/platforms/selenium_webdriver/ordered_list.rb +39 -39
  181. data/lib/page-object/platforms/selenium_webdriver/page_object.rb +1136 -1136
  182. data/lib/page-object/platforms/selenium_webdriver/radio_button.rb +22 -22
  183. data/lib/page-object/platforms/selenium_webdriver/select_list.rb +93 -93
  184. data/lib/page-object/platforms/selenium_webdriver/surrogate_selenium_element.rb +42 -42
  185. data/lib/page-object/platforms/selenium_webdriver/table.rb +42 -42
  186. data/lib/page-object/platforms/selenium_webdriver/table_row.rb +43 -43
  187. data/lib/page-object/platforms/selenium_webdriver/text_area.rb +17 -17
  188. data/lib/page-object/platforms/selenium_webdriver/text_field.rb +17 -17
  189. data/lib/page-object/platforms/selenium_webdriver/unordered_list.rb +39 -39
  190. data/lib/page-object/platforms/watir_webdriver.rb +18 -18
  191. data/lib/page-object/platforms/watir_webdriver/check_box.rb +29 -29
  192. data/lib/page-object/platforms/watir_webdriver/element.rb +249 -249
  193. data/lib/page-object/platforms/watir_webdriver/file_field.rb +16 -16
  194. data/lib/page-object/platforms/watir_webdriver/form.rb +16 -16
  195. data/lib/page-object/platforms/watir_webdriver/image.rb +22 -22
  196. data/lib/page-object/platforms/watir_webdriver/label.rb +17 -18
  197. data/lib/page-object/platforms/watir_webdriver/link.rb +15 -15
  198. data/lib/page-object/platforms/watir_webdriver/ordered_list.rb +35 -35
  199. data/lib/page-object/platforms/watir_webdriver/page_object.rb +1029 -1029
  200. data/lib/page-object/platforms/watir_webdriver/radio_button.rb +22 -22
  201. data/lib/page-object/platforms/watir_webdriver/select_list.rb +74 -74
  202. data/lib/page-object/platforms/watir_webdriver/table.rb +38 -38
  203. data/lib/page-object/platforms/watir_webdriver/table_row.rb +37 -37
  204. data/lib/page-object/platforms/watir_webdriver/text_area.rb +23 -23
  205. data/lib/page-object/platforms/watir_webdriver/text_field.rb +16 -16
  206. data/lib/page-object/platforms/watir_webdriver/unordered_list.rb +36 -36
  207. data/lib/page-object/version.rb +4 -4
  208. data/lib/page-object/widgets.rb +133 -133
  209. data/meeane-page-object.gemspec +32 -32
  210. data/spec/page-object/element_locators_spec.rb +1065 -1065
  211. data/spec/page-object/elements/area_spec.rb +45 -45
  212. data/spec/page-object/elements/button_spec.rb +50 -50
  213. data/spec/page-object/elements/canvas_spec.rb +40 -40
  214. data/spec/page-object/elements/check_box_spec.rb +49 -49
  215. data/spec/page-object/elements/div_spec.rb +28 -28
  216. data/spec/page-object/elements/element_spec.rb +114 -114
  217. data/spec/page-object/elements/file_field_spec.rb +39 -39
  218. data/spec/page-object/elements/form_spec.rb +28 -28
  219. data/spec/page-object/elements/heading_spec.rb +48 -48
  220. data/spec/page-object/elements/hidden_field_spec.rb +28 -28
  221. data/spec/page-object/elements/image_spec.rb +66 -66
  222. data/spec/page-object/elements/label_spec.rb +29 -29
  223. data/spec/page-object/elements/link_spec.rb +49 -49
  224. data/spec/page-object/elements/list_item_spec.rb +28 -28
  225. data/spec/page-object/elements/nested_element_spec.rb +254 -254
  226. data/spec/page-object/elements/option_spec.rb +11 -11
  227. data/spec/page-object/elements/ordered_list_spec.rb +94 -94
  228. data/spec/page-object/elements/paragraph_spec.rb +28 -28
  229. data/spec/page-object/elements/select_list_spec.rb +142 -142
  230. data/spec/page-object/elements/selenium/radio_button_spec.rb +44 -44
  231. data/spec/page-object/elements/selenium/text_field_spec.rb +49 -49
  232. data/spec/page-object/elements/selenium_element_spec.rb +172 -172
  233. data/spec/page-object/elements/span_spec.rb +26 -26
  234. data/spec/page-object/elements/table_cell_spec.rb +21 -21
  235. data/spec/page-object/elements/table_row_spec.rb +70 -70
  236. data/spec/page-object/elements/table_spec.rb +98 -98
  237. data/spec/page-object/elements/text_area_spec.rb +39 -39
  238. data/spec/page-object/elements/unordered_list_spec.rb +95 -95
  239. data/spec/page-object/elements/watir_element_spec.rb +142 -142
  240. data/spec/page-object/javascript_framework_facade_spec.rb +61 -61
  241. data/spec/page-object/loads_platform_spec.rb +53 -53
  242. data/spec/page-object/page-object_spec.rb +405 -405
  243. data/spec/page-object/page_factory_spec.rb +256 -256
  244. data/spec/page-object/page_populator_spec.rb +122 -122
  245. data/spec/page-object/platforms/selenium_webdriver/selenium_page_object_spec.rb +68 -68
  246. data/spec/page-object/platforms/selenium_webdriver_spec.rb +28 -28
  247. data/spec/page-object/platforms/watir_webdriver/watir_page_object_spec.rb +29 -29
  248. data/spec/page-object/platforms/watir_webdriver_spec.rb +9 -9
  249. data/spec/page-object/selenium_accessors_spec.rb +589 -589
  250. data/spec/page-object/watir_accessors_spec.rb +1107 -1107
  251. data/spec/page-object/widget_spec.rb +226 -226
  252. data/spec/spec_helper.rb +44 -44
  253. metadata +193 -43
data/lib/page-object.rb CHANGED
@@ -1,408 +1,408 @@
1
- require 'page-object/version'
2
- require 'page-object/accessors'
3
- require 'page-object/platforms'
4
- require 'page-object/element_locators'
5
- require 'page-object/nested_elements'
6
- require 'page-object/page_factory'
7
- require 'page-object/page_populator'
8
- require 'page-object/javascript_framework_facade'
9
- require 'page-object/indexed_properties'
10
- require 'page-object/widgets'
11
-
12
- require 'selenium/webdriver/common/error'
13
- #
14
- # Module that when included adds functionality to a page object. This module
15
- # will add numerous class and instance methods that you use to define and
16
- # interact with web pages.
17
- #
18
- # If we have a login page with a username and password textfield and a login
19
- # button we might define our page like the one below. We can then interact with
20
- # the object using the generated methods.
21
- #
22
- # @example Login page example
23
- # class LoginPage
24
- # include PageObject
25
- #
26
- # text_field(:username, :id => 'user')
27
- # text_field(:password, :id => 'pass')
28
- # button(:login, :value => 'Login')
29
- # end
30
- #
31
- # ...
32
- #
33
- # browser = Watir::Browser.new :firefox
34
- # login_page = LoginPage.new(browser)
35
- # login_page.username = 'cheezy'
36
- # login_page.password = 'secret'
37
- # login_page.login
38
- #
39
- # @see PageObject::Accessors to see what class level methods are added to this module at runtime.
40
- #
41
- module PageObject
42
- include LoadsPlatform
43
- include ElementLocators
44
- include PagePopulator
45
-
46
- # @return [Watir::Browser or Selenium::WebDriver::Driver] the platform browser passed to the constructor
47
- attr_reader :browser
48
- # @return [PageObject::WatirPageObject or PageObject::SeleniumPageObject] the platform page object
49
- attr_reader :platform
50
-
51
- #
52
- # Construct a new page object. Prior to browser initialization it will call
53
- # a method named initialize_accessors if it exists. Upon initialization of
54
- # the page it will call a method named initialize_page if it exists.
55
- #
56
- # @param [Watir::Browser or Selenium::WebDriver::Driver] the platform browser to use
57
- # @param [bool] open the page if page_url is set
58
- #
59
- def initialize(browser, visit=false)
60
- initialize_accessors if respond_to?(:initialize_accessors)
61
- initialize_browser(browser)
62
- goto if visit && respond_to?(:goto)
63
- initialize_page if respond_to?(:initialize_page)
64
- end
65
-
66
- def initialize_browser(browser)
67
- @browser = browser
68
- include_platform_driver(browser)
69
- end
70
-
71
- # @private
72
- def self.included(cls)
73
- cls.extend PageObject::Accessors
74
- end
75
-
76
- #
77
- # Set the default timeout for page level waits
78
- #
79
- def self.default_page_wait=(timeout)
80
- @page_wait = timeout
81
- end
82
-
83
- #
84
- # Returns the default timeout for page lavel waits
85
- #
86
- def self.default_page_wait
87
- @page_wait ||= 30
88
- end
89
-
90
- #
91
- # Sets the default timeout for element level waits
92
- #
93
- def self.default_element_wait=(timeout)
94
- @element_wait = timeout
95
- end
96
-
97
- #
98
- # Returns the default timeout for element level waits
99
- #
100
- def self.default_element_wait
101
- @element_wait ||= 5
102
- end
103
-
104
- #
105
- # Set the javascript framework to use when determining number of
106
- # ajax requests. Valid frameworks are :jquery and :prototype
107
- #
108
- def self.javascript_framework=(framework)
109
- PageObject::JavascriptFrameworkFacade.framework = framework
110
- end
111
-
112
- #
113
- # Add a new javascript framework to page-object. The module passed
114
- # in must adhere to the same prototype as the JQuery and Prototype
115
- # modules.
116
- #
117
- # @param [Symbol] the name used to reference the framework in
118
- # subsequent calls
119
- # @param [Module] a module that has the necessary methods to perform
120
- # the required actions.
121
- #
122
- def self.add_framework(key, framework)
123
- PageObject::JavascriptFrameworkFacade.add_framework(key, framework)
124
- end
125
-
126
- #
127
- # get the current page url
128
- #
129
- def current_url
130
- platform.current_url
131
- end
132
-
133
- #
134
- # navigate to the provided url
135
- #
136
- # @param [String] the full url to navigate to
137
- #
138
- def navigate_to(url)
139
- platform.navigate_to(url)
140
- end
141
-
142
- #
143
- # Returns the text of the current page
144
- #
145
- def text
146
- platform.text
147
- end
148
-
149
- #
150
- # Returns the html of the current page
151
- #
152
- def html
153
- platform.html
154
- end
155
-
156
- #
157
- # Returns the title of the current page
158
- #
159
- def title
160
- platform.title
161
- end
162
-
163
- #
164
- # Wait until the block returns true or times out
165
- #
166
- # @example
167
- # @page.wait_until(5, 'Success not found on page') do
168
- # @page.text.include? 'Success'
169
- # end
170
- #
171
- # @param [Numeric] the amount of time to wait for the block to return true.
172
- # @param [String] the message to include with the error if we exceed the timeout duration.
173
- # @param block the block to execute. It should return true when successful.
174
- #
175
- def wait_until(timeout = PageObject.default_page_wait, message = nil, &block)
176
- platform.wait_until(timeout, message, &block)
177
- end
178
-
179
-
180
- #
181
- # Wait until there are no pending ajax requests. This requires you
182
- # to set the javascript framework in advance.
183
- #
184
- # @param [Numeric] the amount of time to wait for the block to return true.
185
- # @param [String] the message to include with the error if we exceed
186
- # the timeout duration.
187
- #
188
- def wait_for_ajax(timeout = 30, message = nil)
189
- end_time = ::Time.now + timeout
190
- until ::Time.now > end_time
191
- return if browser.execute_script(::PageObject::JavascriptFrameworkFacade.pending_requests) == 0
192
- sleep 0.5
193
- end
194
- message = "Timed out waiting for ajax requests to complete" unless message
195
- raise message
196
- end
197
-
198
- #
199
- # Override the normal alert popup so it does not occur.
200
- #
201
- # @example
202
- # message = @page.alert do
203
- # @page.button_that_causes_alert
204
- # end
205
- #
206
- # @param frame optional parameter used when alert is nested within a frame
207
- # @param block a block that has the call that will cause the alert to display
208
- # @return [String] the message that was contained in the alert
209
- #
210
- def alert(frame=nil, &block)
211
- platform.alert(frame, &block)
212
- end
213
-
214
- #
215
- # Override the normal confirm popup so it does not occur.
216
- #
217
- # @example
218
- # message = @popup.confirm(true) do
219
- # @page.button_that_causes_confirm
220
- # end
221
- #
222
- # @param [bool] what response you want to return back from the confirm popup
223
- # @param frame optional parameter used when the confirm is nested within a frame
224
- # @param block a block that has the call that will cause the confirm to display
225
- # @return [String] the message that was prompted in the confirm
226
- #
227
- def confirm(response, frame=nil, &block)
228
- platform.confirm(response, frame, &block)
229
- end
230
-
231
- #
232
- # Override the normal prompt popup so it does not occur.
233
- #
234
- # @example
235
- # message = @popup.prompt("Some Value") do
236
- # @page.button_that_causes_prompt
237
- # end
238
- #
239
- # @param [string] the value returned to the caller of the prompt
240
- # @param frame optional parameter used with the prompt is nested within a frame
241
- # @param block a block that has the call that will cause the prompt to display
242
- # @return [Hash] A has containing two keys - :message contains the prompt message and
243
- # :default_value contains the default value for the prompt if provided
244
- #
245
- def prompt(answer, frame=nil, &block)
246
- platform.prompt(answer, frame, &block)
247
- end
248
-
249
- #
250
- # Execute javascript on the browser
251
- #
252
- # @example Get inner HTML of element
253
- # span = @page.span_element
254
- # @page.execute_script "return arguments[0].innerHTML", span
255
- # #=> "Span innerHTML"
256
- #
257
- def execute_script(script, *args)
258
- args.map! { |e| e.kind_of?(PageObject::Elements::Element) ? e.element : e }
259
- platform.execute_script(script, *args)
260
- end
261
-
262
- #
263
- # Identify an element as existing within a frame. A frame parameter
264
- # is passed to the block and must be passed to the other calls to PageObject.
265
- # You can nest calls to in_frame by passing the frame to the next level.
266
- #
267
- # @example
268
- # in_frame(:id => 'frame_id') do |frame|
269
- # text_field_element(:id => 'fname', :frame => frame)
270
- # end
271
- #
272
- # @param [Hash] identifier how we find the frame. The valid keys are:
273
- # * :id => Watir and Selenium
274
- # * :index => Watir and Selenium
275
- # * :name => Watir and Selenium
276
- # * :class => Watir only
277
- # @param frame passed from a previous call to in_frame. Used to nest calls
278
- # @param block that contains the calls to elements that exist inside the frame.
279
- #
280
- def in_frame(identifier, frame=nil, &block)
281
- platform.in_frame(identifier, frame, &block)
282
- end
283
-
284
- # Identify an element as existing within an iframe. A frame parameter
285
- # is passed to the block and must be passed to the other calls to PageObject.
286
- # You can nest calls to in_iframe by passing the frame to the next level.
287
- #
288
- # @example
289
- # in_iframe(:id => 'iframe_id') do |iframe|
290
- # text_field_element(:id => 'ifname', :frame => iframe)
291
- # end
292
- #
293
- # @param [Hash] identifier how we find the iframe. The valid keys are:
294
- # * :id => Watir and Selenium
295
- # * :index => Watir and Selenium
296
- # * :name => Watir and Selenium
297
- # * :class => Watir only
298
- # @param frame passed from a previous call to in_iframe. Used to nest calls
299
- # @param block that contains the calls to elements that exist inside the iframe.
300
- #
301
- def in_iframe(identifier, frame=nil, &block)
302
- platform.in_iframe(identifier, frame, &block)
303
- end
304
-
305
- #
306
- # Override the normal showModalDialog call is it opens a window instead
307
- # of a dialog. You will need to attach to the new window in order to
308
- # continue.
309
- #
310
- # @example
311
- # @page.modal_dialog do
312
- # @page.action_that_spawns_the_modal
313
- # end
314
- #
315
- # @param block a block that contains the call that will cause the modal dialog.
316
- #
317
- def modal_dialog(&block)
318
- script =
319
- %Q{
320
- window.showModalDialog = function(sURL, vArguments, sFeatures) {
321
- window.dialogArguments = vArguments;
322
- modalWin = window.open(sURL, 'modal', sFeatures);
323
- return modalWin;
324
- }
325
- }
326
- browser.execute_script script
327
- yield if block_given?
328
- end
329
-
330
- #
331
- # Attach to a running window. You can locate the window using either
332
- # the window's title or url. If it fails to connect to a window it will
333
- # pause for 1 second and try again.
334
- #
335
- # @example
336
- # page.attach_to_window(:title => "other window's title")
337
- #
338
- # @param [Hash] either :title or :url of the other window. The url does not need to
339
- # be the entire url - it can just be the page name like index.html
340
- # @param block if present the block is executed and then execution is returned to the
341
- # calling window
342
- #
343
- def attach_to_window(identifier, &block)
344
- begin
345
- platform.attach_to_window(identifier, &block)
346
- rescue
347
- sleep 1
348
- platform.attach_to_window(identifier, &block)
349
- end
350
- end
351
-
352
- #
353
- # Find the element that has focus on the page
354
- #
355
- def element_with_focus
356
- platform.element_with_focus
357
- end
358
-
359
- #
360
- # Refresh to current page
361
- #
362
- def refresh
363
- platform.refresh
364
- end
365
-
366
- #
367
- # Go back to the previous page
368
- #
369
- def back
370
- platform.back
371
- end
372
-
373
- #
374
- # Go forward to the next page
375
- #
376
- def forward
377
- platform.forward
378
- end
379
-
380
- #
381
- # Clear the cookies from the browser
382
- #
383
- def clear_cookies
384
- platform.clear_cookies
385
- end
386
-
387
- #
388
- # Save the current screenshot to the provided url. File
389
- # is saved as a png file.
390
- #
391
- def save_screenshot(file_name)
392
- platform.save_screenshot file_name
393
- end
394
-
395
- def self.register_widget(widget_tag, widget_class, base_element_tag)
396
- Widgets.register_widget(widget_tag, widget_class, base_element_tag)
397
- end
398
-
399
- private
400
-
401
- def include_platform_driver(browser)
402
- @platform = load_platform(browser, PageObject::Platforms.get)
403
- end
404
-
405
- def call_block(&block)
406
- block.arity == 1 ? block.call(self) : self.instance_eval(&block)
407
- end
408
- end
1
+ require 'page-object/version'
2
+ require 'page-object/accessors'
3
+ require 'page-object/platforms'
4
+ require 'page-object/element_locators'
5
+ require 'page-object/nested_elements'
6
+ require 'page-object/page_factory'
7
+ require 'page-object/page_populator'
8
+ require 'page-object/javascript_framework_facade'
9
+ require 'page-object/indexed_properties'
10
+ require 'page-object/widgets'
11
+
12
+ require 'selenium/webdriver/common/error'
13
+ #
14
+ # Module that when included adds functionality to a page object. This module
15
+ # will add numerous class and instance methods that you use to define and
16
+ # interact with web pages.
17
+ #
18
+ # If we have a login page with a username and password textfield and a login
19
+ # button we might define our page like the one below. We can then interact with
20
+ # the object using the generated methods.
21
+ #
22
+ # @example Login page example
23
+ # class LoginPage
24
+ # include PageObject
25
+ #
26
+ # text_field(:username, :id => 'user')
27
+ # text_field(:password, :id => 'pass')
28
+ # button(:login, :value => 'Login')
29
+ # end
30
+ #
31
+ # ...
32
+ #
33
+ # browser = Watir::Browser.new :firefox
34
+ # login_page = LoginPage.new(browser)
35
+ # login_page.username = 'cheezy'
36
+ # login_page.password = 'secret'
37
+ # login_page.login
38
+ #
39
+ # @see PageObject::Accessors to see what class level methods are added to this module at runtime.
40
+ #
41
+ module PageObject
42
+ include LoadsPlatform
43
+ include ElementLocators
44
+ include PagePopulator
45
+
46
+ # @return [Watir::Browser or Selenium::WebDriver::Driver] the platform browser passed to the constructor
47
+ attr_reader :browser
48
+ # @return [PageObject::WatirPageObject or PageObject::SeleniumPageObject] the platform page object
49
+ attr_reader :platform
50
+
51
+ #
52
+ # Construct a new page object. Prior to browser initialization it will call
53
+ # a method named initialize_accessors if it exists. Upon initialization of
54
+ # the page it will call a method named initialize_page if it exists.
55
+ #
56
+ # @param [Watir::Browser or Selenium::WebDriver::Driver] the platform browser to use
57
+ # @param [bool] open the page if page_url is set
58
+ #
59
+ def initialize(browser, visit=false)
60
+ initialize_accessors if respond_to?(:initialize_accessors)
61
+ initialize_browser(browser)
62
+ goto if visit && respond_to?(:goto)
63
+ initialize_page if respond_to?(:initialize_page)
64
+ end
65
+
66
+ def initialize_browser(browser)
67
+ @browser = browser
68
+ include_platform_driver(browser)
69
+ end
70
+
71
+ # @private
72
+ def self.included(cls)
73
+ cls.extend PageObject::Accessors
74
+ end
75
+
76
+ #
77
+ # Set the default timeout for page level waits
78
+ #
79
+ def self.default_page_wait=(timeout)
80
+ @page_wait = timeout
81
+ end
82
+
83
+ #
84
+ # Returns the default timeout for page lavel waits
85
+ #
86
+ def self.default_page_wait
87
+ @page_wait ||= 30
88
+ end
89
+
90
+ #
91
+ # Sets the default timeout for element level waits
92
+ #
93
+ def self.default_element_wait=(timeout)
94
+ @element_wait = timeout
95
+ end
96
+
97
+ #
98
+ # Returns the default timeout for element level waits
99
+ #
100
+ def self.default_element_wait
101
+ @element_wait ||= 5
102
+ end
103
+
104
+ #
105
+ # Set the javascript framework to use when determining number of
106
+ # ajax requests. Valid frameworks are :jquery and :prototype
107
+ #
108
+ def self.javascript_framework=(framework)
109
+ PageObject::JavascriptFrameworkFacade.framework = framework
110
+ end
111
+
112
+ #
113
+ # Add a new javascript framework to page-object. The module passed
114
+ # in must adhere to the same prototype as the JQuery and Prototype
115
+ # modules.
116
+ #
117
+ # @param [Symbol] the name used to reference the framework in
118
+ # subsequent calls
119
+ # @param [Module] a module that has the necessary methods to perform
120
+ # the required actions.
121
+ #
122
+ def self.add_framework(key, framework)
123
+ PageObject::JavascriptFrameworkFacade.add_framework(key, framework)
124
+ end
125
+
126
+ #
127
+ # get the current page url
128
+ #
129
+ def current_url
130
+ platform.current_url
131
+ end
132
+
133
+ #
134
+ # navigate to the provided url
135
+ #
136
+ # @param [String] the full url to navigate to
137
+ #
138
+ def navigate_to(url)
139
+ platform.navigate_to(url)
140
+ end
141
+
142
+ #
143
+ # Returns the text of the current page
144
+ #
145
+ def text
146
+ platform.text
147
+ end
148
+
149
+ #
150
+ # Returns the html of the current page
151
+ #
152
+ def html
153
+ platform.html
154
+ end
155
+
156
+ #
157
+ # Returns the title of the current page
158
+ #
159
+ def title
160
+ platform.title
161
+ end
162
+
163
+ #
164
+ # Wait until the block returns true or times out
165
+ #
166
+ # @example
167
+ # @page.wait_until(5, 'Success not found on page') do
168
+ # @page.text.include? 'Success'
169
+ # end
170
+ #
171
+ # @param [Numeric] the amount of time to wait for the block to return true.
172
+ # @param [String] the message to include with the error if we exceed the timeout duration.
173
+ # @param block the block to execute. It should return true when successful.
174
+ #
175
+ def wait_until(timeout = PageObject.default_page_wait, message = nil, &block)
176
+ platform.wait_until(timeout, message, &block)
177
+ end
178
+
179
+
180
+ #
181
+ # Wait until there are no pending ajax requests. This requires you
182
+ # to set the javascript framework in advance.
183
+ #
184
+ # @param [Numeric] the amount of time to wait for the block to return true.
185
+ # @param [String] the message to include with the error if we exceed
186
+ # the timeout duration.
187
+ #
188
+ def wait_for_ajax(timeout = 30, message = nil)
189
+ end_time = ::Time.now + timeout
190
+ until ::Time.now > end_time
191
+ return if browser.execute_script(::PageObject::JavascriptFrameworkFacade.pending_requests) == 0
192
+ sleep 0.5
193
+ end
194
+ message = "Timed out waiting for ajax requests to complete" unless message
195
+ raise message
196
+ end
197
+
198
+ #
199
+ # Override the normal alert popup so it does not occur.
200
+ #
201
+ # @example
202
+ # message = @page.alert do
203
+ # @page.button_that_causes_alert
204
+ # end
205
+ #
206
+ # @param frame optional parameter used when alert is nested within a frame
207
+ # @param block a block that has the call that will cause the alert to display
208
+ # @return [String] the message that was contained in the alert
209
+ #
210
+ def alert(frame=nil, &block)
211
+ platform.alert(frame, &block)
212
+ end
213
+
214
+ #
215
+ # Override the normal confirm popup so it does not occur.
216
+ #
217
+ # @example
218
+ # message = @popup.confirm(true) do
219
+ # @page.button_that_causes_confirm
220
+ # end
221
+ #
222
+ # @param [bool] what response you want to return back from the confirm popup
223
+ # @param frame optional parameter used when the confirm is nested within a frame
224
+ # @param block a block that has the call that will cause the confirm to display
225
+ # @return [String] the message that was prompted in the confirm
226
+ #
227
+ def confirm(response, frame=nil, &block)
228
+ platform.confirm(response, frame, &block)
229
+ end
230
+
231
+ #
232
+ # Override the normal prompt popup so it does not occur.
233
+ #
234
+ # @example
235
+ # message = @popup.prompt("Some Value") do
236
+ # @page.button_that_causes_prompt
237
+ # end
238
+ #
239
+ # @param [string] the value returned to the caller of the prompt
240
+ # @param frame optional parameter used with the prompt is nested within a frame
241
+ # @param block a block that has the call that will cause the prompt to display
242
+ # @return [Hash] A has containing two keys - :message contains the prompt message and
243
+ # :default_value contains the default value for the prompt if provided
244
+ #
245
+ def prompt(answer, frame=nil, &block)
246
+ platform.prompt(answer, frame, &block)
247
+ end
248
+
249
+ #
250
+ # Execute javascript on the browser
251
+ #
252
+ # @example Get inner HTML of element
253
+ # span = @page.span_element
254
+ # @page.execute_script "return arguments[0].innerHTML", span
255
+ # #=> "Span innerHTML"
256
+ #
257
+ def execute_script(script, *args)
258
+ args.map! { |e| e.kind_of?(PageObject::Elements::Element) ? e.element : e }
259
+ platform.execute_script(script, *args)
260
+ end
261
+
262
+ #
263
+ # Identify an element as existing within a frame. A frame parameter
264
+ # is passed to the block and must be passed to the other calls to PageObject.
265
+ # You can nest calls to in_frame by passing the frame to the next level.
266
+ #
267
+ # @example
268
+ # in_frame(:id => 'frame_id') do |frame|
269
+ # text_field_element(:id => 'fname', :frame => frame)
270
+ # end
271
+ #
272
+ # @param [Hash] identifier how we find the frame. The valid keys are:
273
+ # * :id => Watir and Selenium
274
+ # * :index => Watir and Selenium
275
+ # * :name => Watir and Selenium
276
+ # * :class => Watir only
277
+ # @param frame passed from a previous call to in_frame. Used to nest calls
278
+ # @param block that contains the calls to elements that exist inside the frame.
279
+ #
280
+ def in_frame(identifier, frame=nil, &block)
281
+ platform.in_frame(identifier, frame, &block)
282
+ end
283
+
284
+ # Identify an element as existing within an iframe. A frame parameter
285
+ # is passed to the block and must be passed to the other calls to PageObject.
286
+ # You can nest calls to in_iframe by passing the frame to the next level.
287
+ #
288
+ # @example
289
+ # in_iframe(:id => 'iframe_id') do |iframe|
290
+ # text_field_element(:id => 'ifname', :frame => iframe)
291
+ # end
292
+ #
293
+ # @param [Hash] identifier how we find the iframe. The valid keys are:
294
+ # * :id => Watir and Selenium
295
+ # * :index => Watir and Selenium
296
+ # * :name => Watir and Selenium
297
+ # * :class => Watir only
298
+ # @param frame passed from a previous call to in_iframe. Used to nest calls
299
+ # @param block that contains the calls to elements that exist inside the iframe.
300
+ #
301
+ def in_iframe(identifier, frame=nil, &block)
302
+ platform.in_iframe(identifier, frame, &block)
303
+ end
304
+
305
+ #
306
+ # Override the normal showModalDialog call is it opens a window instead
307
+ # of a dialog. You will need to attach to the new window in order to
308
+ # continue.
309
+ #
310
+ # @example
311
+ # @page.modal_dialog do
312
+ # @page.action_that_spawns_the_modal
313
+ # end
314
+ #
315
+ # @param block a block that contains the call that will cause the modal dialog.
316
+ #
317
+ def modal_dialog(&block)
318
+ script =
319
+ %Q{
320
+ window.showModalDialog = function(sURL, vArguments, sFeatures) {
321
+ window.dialogArguments = vArguments;
322
+ modalWin = window.open(sURL, 'modal', sFeatures);
323
+ return modalWin;
324
+ }
325
+ }
326
+ browser.execute_script script
327
+ yield if block_given?
328
+ end
329
+
330
+ #
331
+ # Attach to a running window. You can locate the window using either
332
+ # the window's title or url. If it fails to connect to a window it will
333
+ # pause for 1 second and try again.
334
+ #
335
+ # @example
336
+ # page.attach_to_window(:title => "other window's title")
337
+ #
338
+ # @param [Hash] either :title or :url of the other window. The url does not need to
339
+ # be the entire url - it can just be the page name like index.html
340
+ # @param block if present the block is executed and then execution is returned to the
341
+ # calling window
342
+ #
343
+ def attach_to_window(identifier, &block)
344
+ begin
345
+ platform.attach_to_window(identifier, &block)
346
+ rescue
347
+ sleep 1
348
+ platform.attach_to_window(identifier, &block)
349
+ end
350
+ end
351
+
352
+ #
353
+ # Find the element that has focus on the page
354
+ #
355
+ def element_with_focus
356
+ platform.element_with_focus
357
+ end
358
+
359
+ #
360
+ # Refresh to current page
361
+ #
362
+ def refresh
363
+ platform.refresh
364
+ end
365
+
366
+ #
367
+ # Go back to the previous page
368
+ #
369
+ def back
370
+ platform.back
371
+ end
372
+
373
+ #
374
+ # Go forward to the next page
375
+ #
376
+ def forward
377
+ platform.forward
378
+ end
379
+
380
+ #
381
+ # Clear the cookies from the browser
382
+ #
383
+ def clear_cookies
384
+ platform.clear_cookies
385
+ end
386
+
387
+ #
388
+ # Save the current screenshot to the provided url. File
389
+ # is saved as a png file.
390
+ #
391
+ def save_screenshot(file_name)
392
+ platform.save_screenshot file_name
393
+ end
394
+
395
+ def self.register_widget(widget_tag, widget_class, base_element_tag)
396
+ Widgets.register_widget(widget_tag, widget_class, base_element_tag)
397
+ end
398
+
399
+ private
400
+
401
+ def include_platform_driver(browser)
402
+ @platform = load_platform(browser, PageObject::Platforms.get)
403
+ end
404
+
405
+ def call_block(&block)
406
+ block.arity == 1 ? block.call(self) : self.instance_eval(&block)
407
+ end
408
+ end