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