druid-ts 1.1.8 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/ChangeLog +27 -0
  3. data/features/bold.feature +21 -0
  4. data/features/element.feature +7 -0
  5. data/features/frames.feature +15 -0
  6. data/features/html/frames.html +3 -3
  7. data/features/html/iframes.html +2 -2
  8. data/features/html/multi_elements.html +1 -0
  9. data/features/html/static_elements.html +25 -8
  10. data/features/javascript.feature +10 -1
  11. data/features/link.feature +4 -0
  12. data/features/multi_elements.feature +6 -0
  13. data/features/radio_button_group.feature +28 -0
  14. data/features/section.feature +128 -0
  15. data/features/select_list.feature +4 -0
  16. data/features/step_definations/bold_steps.rb +11 -0
  17. data/features/step_definations/element_steps.rb +8 -0
  18. data/features/step_definations/frame_steps.rb +53 -11
  19. data/features/step_definations/javasript_steps.rb +9 -0
  20. data/features/step_definations/link_steps.rb +8 -0
  21. data/features/step_definations/multi_elements_steps.rb +13 -0
  22. data/features/step_definations/radio_button_group_steps.rb +32 -0
  23. data/features/step_definations/section_steps.rb +262 -0
  24. data/features/step_definations/table_steps.rb +9 -0
  25. data/features/support/env.rb +1 -0
  26. data/features/support/page.rb +16 -5
  27. data/features/table.feature +18 -14
  28. data/lib/druid.rb +42 -30
  29. data/lib/druid/accessors.rb +188 -55
  30. data/lib/druid/assist.rb +46 -4
  31. data/lib/druid/elements.rb +1 -0
  32. data/lib/druid/elements/bold.rb +8 -0
  33. data/lib/druid/elements/element.rb +16 -3
  34. data/lib/druid/elements/link.rb +7 -0
  35. data/lib/druid/elements/radio_button.rb +0 -7
  36. data/lib/druid/elements/select_list.rb +2 -2
  37. data/lib/druid/elements/table.rb +7 -0
  38. data/lib/druid/javascript/angularjs.rb +12 -0
  39. data/lib/druid/javascript_framework_facade.rb +5 -3
  40. data/lib/druid/locator_generator.rb +1 -0
  41. data/lib/druid/page_factory.rb +1 -0
  42. data/lib/druid/page_populator.rb +10 -1
  43. data/lib/druid/sections.rb +29 -0
  44. data/lib/druid/version.rb +1 -1
  45. data/spec/druid/accessors_spec.rb +79 -13
  46. data/spec/druid/druid_spec.rb +2 -1
  47. data/spec/druid/element_locators_spec.rb +26 -4
  48. data/spec/druid/elements/bold_spec.rb +21 -0
  49. data/spec/druid/elements/link_spec.rb +1 -1
  50. data/spec/druid/elements/page_factory_spec.rb +2 -2
  51. data/spec/druid/elements/radio_button_spec.rb +0 -5
  52. data/spec/druid/elements/select_list_spec.rb +3 -3
  53. data/spec/druid/page_factory_spec.rb +15 -15
  54. data/spec/druid/page_populator_spec.rb +4 -4
  55. data/spec/druid/page_section_spec.rb +61 -0
  56. data/spec/spec_helper.rb +1 -0
  57. metadata +20 -1
data/lib/druid.rb CHANGED
@@ -4,6 +4,7 @@ require 'druid/page_factory'
4
4
  require 'druid/core_ext/string'
5
5
  require 'druid/element_locators'
6
6
  require 'druid/page_populator'
7
+ require 'druid/sections'
7
8
  require 'druid/javascript_framework_facade'
8
9
 
9
10
  # require 'watir-webdriver/extensions/alerts'
@@ -39,26 +40,29 @@ module Druid
39
40
  include Assist
40
41
  include ElementLocators
41
42
  include PagePopulator
42
- # include Watir::AlertHelper
43
+
43
44
  # @return [Watir::Browser] the drvier passed to the constructor
44
45
  attr_reader :driver
46
+
45
47
  #
46
48
  # Construct a new druid. Prior to browser initialization it will call
47
49
  # a method named initialize_accessors if it exists. Upon initialization of
48
50
  # the page it will call a method named initialize_page if it exists
49
51
  #
50
- # @param [Watir::Browser] the driver to use
52
+ # @param [Watir::Browser, Watir:HTMLElement] the driver/element to use
51
53
  # @param [bool] open the page if page_url is set
52
54
  #
53
- def initialize(driver, visit=false)
55
+ def initialize(root, visit=false)
54
56
  initialize_accessors if respond_to?(:initialize_accessors)
55
- if driver.is_a? Watir::Browser
56
- @driver ||= driver
57
- goto if visit && respond_to?(:goto)
58
- initialize_page if respond_to?(:initialize_page)
59
- else
60
- raise ArgumentError, "expect Watir::Browser"
61
- end
57
+ initialize_driver root
58
+ goto if visit && respond_to?(:goto)
59
+ initialize_page if respond_to?(:initialize_page)
60
+ end
61
+
62
+ def initialize_driver root
63
+ @driver = root if root.is_a? Watir::HTMLElement or root.is_a? Watir::Browser
64
+ @root_element = Elements::Element.new root if root.is_a? Watir::HTMLElement
65
+ raise "expect Watir::Browser or Watir::HTMLElement" if not root.is_a? Watir::HTMLElement and not root.is_a? Watir::Browser
62
66
  end
63
67
 
64
68
  # @private
@@ -105,7 +109,8 @@ module Druid
105
109
 
106
110
  #
107
111
  # Set the javascript framework to use when determining number of
108
- # ajax requests. Valid frameworks are :jquery, :prototype, and :Dojo
112
+ # ajax requests. Valid frameworks are :jquery, :prototype, and :yui,
113
+ # and :angularjs
109
114
  #
110
115
  def self.javascript_framework=(framework)
111
116
  Druid::JavascriptFrameworkFacade.framework = framework
@@ -135,7 +140,7 @@ module Druid
135
140
  # Returns the text of the current page
136
141
  #
137
142
  def text
138
- driver.text
143
+ root.text
139
144
  end
140
145
 
141
146
  #
@@ -205,7 +210,7 @@ module Druid
205
210
  end
206
211
 
207
212
  #
208
- # Override the normal alert popup so it does not occurr.
213
+ # Override the normal alert popup so it does not occur.
209
214
  #
210
215
  # @example
211
216
  # message = @page.alert do
@@ -228,7 +233,7 @@ module Druid
228
233
  end
229
234
 
230
235
  #
231
- # Override the normal confirm popup so it does not occurr
236
+ # Override the normal confirm popup so it does not occur
232
237
  #
233
238
  # @example
234
239
  # message = @popup.confirm(true) do
@@ -250,7 +255,7 @@ module Druid
250
255
  end
251
256
 
252
257
  #
253
- # Override the normal prompt popup so it does not occurr
258
+ # Override the normal prompt popup so it does not occur
254
259
  #
255
260
  # @example
256
261
  # message = @popup.prompt("Some Value") do
@@ -275,13 +280,14 @@ module Druid
275
280
  #
276
281
  # Execute javascript on the browser
277
282
  #
278
- def execute_script(script)
279
- driver.execute_script(script)
283
+ def execute_script(script, *args)
284
+ args.map! { |e| e.kind_of?(Druid::Elements::Element) ? e.element : e }
285
+ driver.execute_script(script, *args)
280
286
  end
281
287
 
282
288
  #
283
289
  # Attach to a running window. You can locate the window using either
284
- # the window's title or url or index, If it failes to connect to a window it will
290
+ # the window's title or url or index, If it fails to connect to a window it will
285
291
  # pause for 1 second and try again.
286
292
  #
287
293
  # @example
@@ -353,7 +359,7 @@ module Druid
353
359
  end
354
360
 
355
361
  #
356
- # Identify an element as existing within a frame or iframe. A frame parameter is
362
+ # Identify an element as existing within a frame. A frame parameter is
357
363
  # passed to the block and must be passed to the other calls to Druid.
358
364
  # You can nest calls to in_frame by passing the frame to the next level.
359
365
  #
@@ -375,9 +381,9 @@ module Druid
375
381
  end
376
382
 
377
383
  #
378
- # Identify an element as existing within a frame or iframe. A frame parameter is
384
+ # Identify an element as existing within an iframe. Aframe parameter is
379
385
  # passed to the block and must be passed to the other calls to Druid.
380
- # You can nest calls to in_frame by passing the frame to the next level.
386
+ # You can nest calls to in_iframe by passing the frame to the next level.
381
387
  #
382
388
  # @example
383
389
  # @page.in_iframe(:id => 'frame_id') do |frame|
@@ -396,18 +402,24 @@ module Druid
396
402
  block.call(frame)
397
403
  end
398
404
 
399
- # def switch_to_frame(frame_identifiers)
400
- # unless frame_identifiers.nil?
401
- # frame_identifiers.each do |frame|
402
- # frame_id = frame.values.first
403
- # value = frame_id.values.first
404
- # driver.wd.switch_to.frame(value)
405
- # end
406
- # end
407
- # end
405
+ def switch_to_frame(frame_identifiers)
406
+ unless frame_identifiers.nil?
407
+ frame_identifiers.each do |frame|
408
+ frame_id = frame.values.first
409
+ value = frame_id.values.first
410
+ driver.wd.switch_to.frame(value)
411
+ end
412
+ end
413
+ end
408
414
 
409
415
  def call_block(&block)
410
416
  block.arity == 1 ? block.call(self) : self.instance_eval(&block)
411
417
  end
412
418
 
419
+ private
420
+
421
+ def root
422
+ @root_element || driver
423
+ end
424
+
413
425
  end
@@ -37,15 +37,43 @@ module Druid
37
37
  #
38
38
  def page_url(url)
39
39
  define_method("goto") do
40
+ driver.goto self.page_url_value
41
+ end
42
+
43
+ define_method("page_url_value") do
40
44
  lookup = url.kind_of?(Symbol) ? self.send(url) : url
41
45
  erb = ERB.new(%Q{#{lookup}})
42
46
  merged_params = self.class.instance_variable_get("@merged_params")
43
47
  params = merged_params ? merged_params : self.class.params
44
- driver.goto erb.result(binding)
48
+ erb.result(binding)
45
49
  end
46
50
  end
47
51
  alias_method :direct_url, :page_url
48
52
 
53
+ #
54
+ # Creates a method that waits the expected_title of a page to match the actual.
55
+ # @param [String] expected_title the literal expected title for the page
56
+ # @param [Regexp] expected_title the expected title pattern for the page
57
+ # @param [optional, Integer] timeout default value is nil - do not wait
58
+ # @return [boolean]
59
+ # @raise An exception if expected_title does not match actual title
60
+ #
61
+ # @example Specify 'Google' as the expected title of a page
62
+ # wait_for_expected_title "Google"
63
+ # page.wait_for_expected_title?
64
+ #
65
+ def wait_for_expected_title(expected_title, timeout=Druid.default_element_wait)
66
+ define_method("wait_for_expected_title?") do
67
+ error_message = lambda { "Expected title '#{expected_title}' instead of '#{title}'" }
68
+ has_expected_title = (expected_title === title)
69
+ wait_until(timeout, error_message.call) do
70
+ has_expected_title = (expected_title === title)
71
+ end unless has_expected_title
72
+ raise error_message.call unless has_expected_title
73
+ has_expected_title
74
+ end
75
+ end
76
+
49
77
  #
50
78
  # Creates a method that compares the expected_title of a page against the actual.
51
79
  # @param [String] expected_title the literal expected title for the page
@@ -83,6 +111,14 @@ module Druid
83
111
  end
84
112
  end
85
113
 
114
+ def expected_element_visible(element_name, timeout=Druid.default_element_wait)
115
+ define_method("has_expected_element_visible?") do
116
+ self.respond_to? "#{element_name}_element" and self.send("#{element_name}_element").when_present timeout
117
+ self.respond_to? "#{element_name}_element" and self.send("#{element_name}_element").when_visible timeout
118
+ end
119
+
120
+ end
121
+
86
122
  #
87
123
  # Identify an element as existing within a frame or iframe. A frame parameter
88
124
  # is passed to the block and must be passed to the other calls to Druid.
@@ -154,11 +190,11 @@ module Druid
154
190
  # @param optional block to be invoked when element method is called
155
191
  #
156
192
  def link(name, identifier={:index => 0}, &block)
193
+ standard_methods(name, identifier, 'link_for', &block)
157
194
  define_method(name) do
158
195
  return click_link_for identifier.clone unless block_given?
159
196
  self.send("#{name}_element").click
160
197
  end
161
- standard_methods(name, identifier, 'link_for', &block)
162
198
  end
163
199
 
164
200
  alias_method :a, :link
@@ -189,6 +225,7 @@ module Druid
189
225
  # @param optional block to be invoked when element method is called
190
226
  #
191
227
  def text_field(name, identifier={:index => 0}, &block)
228
+ standard_methods(name, identifier, 'text_field_for', &block)
192
229
  define_method(name) do
193
230
  return text_field_value_for identifier.clone unless block_given?
194
231
  self.send("#{name}_element").value
@@ -197,7 +234,6 @@ module Druid
197
234
  return text_field_value_set(identifier.clone, value) unless block_given?
198
235
  self.send("#{name}_element").value = value
199
236
  end
200
- standard_methods(name, identifier, 'text_field_for', &block)
201
237
  end
202
238
 
203
239
  #
@@ -225,6 +261,7 @@ module Druid
225
261
  # @param optional block to be invoked when element method is called
226
262
  #
227
263
  def checkbox(name, identifier={:index => 0}, &block)
264
+ standard_methods(name, identifier, 'checkbox_for', &block)
228
265
  define_method("check_#{name}") do
229
266
  return check_checkbox identifier.clone unless block_given?
230
267
  self.send("#{name}_element").check
@@ -237,7 +274,6 @@ module Druid
237
274
  return checkbox_checked? identifier.clone unless block_given?
238
275
  self.send("#{name}_element").checked?
239
276
  end
240
- standard_methods(name, identifier, 'checkbox_for', &block)
241
277
  end
242
278
 
243
279
  #
@@ -264,6 +300,7 @@ module Druid
264
300
  # @param optional block to be invoked when element method is called
265
301
  #
266
302
  def select_list(name, identifier={:index => 0}, &block)
303
+ standard_methods(name, identifier, 'select_list_for', &block)
267
304
  define_method(name) do
268
305
  return select_list_value_for identifier.clone unless block_given?
269
306
  self.send("#{name}_element").options.each {|o| return o.text if o.selected?}
@@ -276,20 +313,18 @@ module Druid
276
313
  element = self.send("#{name}_element")
277
314
  (element && element.options) ? element.options.collect(&:text) : []
278
315
  end
279
- standard_methods(name, identifier, 'select_list_for', &block)
280
316
  end
281
317
  alias_method :select, :select_list
282
318
 
283
319
  #
284
- # adds five methods - one to select, another to clear,
285
- # another to return if a radio button is selected,
286
- # another method to return a PageObject::Elements::RadioButton
320
+ # adds four methods - one to select, another to return if a radio button
321
+ # is selected, another method to return a PageObject::Elements::RadioButton
287
322
  # object representing the radio button element, and another to check
288
323
  # the radio button's existence.
289
324
  #
290
325
  # @example
291
326
  # radio_button(:north, :id => "north")
292
- # # will generate 'select_north', 'clear_north', 'north_selected?',
327
+ # # will generate 'select_north', 'north_selected?',
293
328
  # # 'north_element', and 'north?' methods
294
329
  #
295
330
  # @param [Symbol] the name used for the generated methods
@@ -306,22 +341,40 @@ module Druid
306
341
  # @param optional block to be invoked when element method is called
307
342
  #
308
343
  def radio_button(name, identifier={:index => 0}, &block)
344
+ standard_methods(name, identifier, 'radio_button_for', &block)
309
345
  define_method("select_#{name}") do
310
346
  return select_radio identifier.clone unless block_given?
311
347
  self.send("#{name}_element").select
312
348
  end
313
- define_method("clear_#{name}") do
314
- return clear_radio identifier.clone unless block_given?
315
- self.send("#{name}_element").clear
316
- end
317
349
  define_method("#{name}_selected?") do
318
350
  return radio_selected? identifier.clone unless block_given?
319
351
  self.send("#{name}_element").selected?
320
352
  end
321
- standard_methods(name, identifier, 'radio_button_for', &block)
322
353
  end
323
354
  alias_method :radio, :radio_button
324
355
 
356
+ def radio_button_group(name, identifier)
357
+ define_method("select_#{name}") do |value|
358
+ radio_buttons_for(identifier.clone).each do |radio_elem|
359
+ return radio_elem.select if radio_elem.value == value
360
+ end
361
+ end
362
+ define_method("#{name}_values") do
363
+ radio_buttons_for(identifier.clone).collect { |e| e.value}
364
+ end
365
+ define_method("#{name}_selected?") do
366
+ radio_buttons_for(identifier.clone).each do |radio_elem|
367
+ return radio_elem.value if radio_elem.selected?
368
+ end
369
+ return false
370
+ end
371
+ define_method("#{name}_elements") do
372
+ radio_buttons_for(identifier.clone)
373
+ end
374
+ define_method("#{name}?") do
375
+ radio_buttons_for(identifier.clone).any?
376
+ end
377
+ end
325
378
  #
326
379
  # adds three methods - one to click a button, another to
327
380
  # return the button element, and another to check the button's existence.
@@ -345,11 +398,11 @@ module Druid
345
398
  # @param optional block to be invoked when element method is called
346
399
  #
347
400
  def button(name, identifier={:index => 0}, &block)
401
+ standard_methods(name, identifier, 'button_for', &block)
348
402
  define_method(name) do
349
403
  return click_button_for identifier.clone unless block_given?
350
404
  self.send("#{name}_element").click
351
405
  end
352
- standard_methods(name, identifier, 'button_for', &block)
353
406
  end
354
407
 
355
408
  #
@@ -375,11 +428,11 @@ module Druid
375
428
  # @param optional block to be invoked when element method is called
376
429
  #
377
430
  def div(name, identifier={:index => 0}, &block)
431
+ standard_methods(name, identifier, 'div_for', &block)
378
432
  define_method(name) do
379
433
  return div_text_for identifier.clone unless block_given?
380
434
  self.send("#{name}_element").text
381
435
  end
382
- standard_methods(name, identifier, 'div_for', &block)
383
436
  end
384
437
 
385
438
  #
@@ -403,11 +456,11 @@ module Druid
403
456
  # @param optional block to be invoked when element method is called
404
457
  #
405
458
  def table(name, identifier={:index => 0}, &block)
459
+ standard_methods(name, identifier, 'table_for', &block)
406
460
  define_method(name) do
407
461
  return table_text_for identifier.clone unless block_given?
408
462
  self.send("#{name}_element").text
409
463
  end
410
- standard_methods(name, identifier, 'table_for', &block)
411
464
  end
412
465
 
413
466
  #
@@ -432,11 +485,11 @@ module Druid
432
485
  # @param optional block to be invoked when element method is called
433
486
  #
434
487
  def cell(name, identifier={:index => 0}, &block)
488
+ standard_methods(name, identifier, 'cell_for', &block)
435
489
  define_method(name) do
436
490
  return cell_text_for identifier.clone unless block_given?
437
491
  self.send("#{name}_element").text
438
492
  end
439
- standard_methods(name, identifier, 'cell_for', &block)
440
493
  end
441
494
  alias_method :td, :cell
442
495
 
@@ -462,11 +515,11 @@ module Druid
462
515
  # @param optional block to be invoked when element method is called
463
516
  #
464
517
  def span(name, identifier={:index => 0}, &block)
518
+ standard_methods(name, identifier, 'span_for', &block)
465
519
  define_method(name) do
466
520
  return span_text_for identifier.clone unless block_given?
467
521
  self.send("#{name}_element").text
468
522
  end
469
- standard_methods(name, identifier, 'span_for', &block)
470
523
  end
471
524
 
472
525
  #
@@ -542,11 +595,11 @@ module Druid
542
595
  # @param optional block to be invoked when element method is called
543
596
  #
544
597
  def hidden_field(name, identifier={:index => 0}, &block)
598
+ standard_methods(name, identifier, 'hidden_field_for', &block)
545
599
  define_method(name) do
546
600
  return hidden_field_value_for identifier.clone unless block_given?
547
601
  self.send("#{name}_element").value
548
602
  end
549
- standard_methods(name, identifier, 'hidden_field_for', &block)
550
603
  end
551
604
  alias_method :hidden, :hidden_field
552
605
 
@@ -572,11 +625,11 @@ module Druid
572
625
  # @param optional block to be invoked when element method is called
573
626
  #
574
627
  def list_item(name, identifier={:index => 0}, &block)
628
+ standard_methods(name, identifier, 'list_item_for', &block)
575
629
  define_method(name) do
576
630
  return list_item_text_for identifier.clone unless block_given?
577
631
  self.send("#{name}_element").text
578
632
  end
579
- standard_methods(name, identifier, 'list_item_for', &block)
580
633
  end
581
634
  alias_method :li, :list_item
582
635
 
@@ -601,11 +654,11 @@ module Druid
601
654
  # @param optional block to be invoked when element method is called
602
655
  #
603
656
  def ordered_list(name, identifier={:index => 0}, &block)
657
+ standard_methods(name, identifier, 'ordered_list_for', &block)
604
658
  define_method(name) do
605
659
  return ordered_list_text_for identifier.clone unless block_given?
606
660
  self.send("#{name}_element").text
607
661
  end
608
- standard_methods(name, identifier, 'ordered_list_for', &block)
609
662
  end
610
663
  alias_method :ol, :ordered_list
611
664
 
@@ -632,6 +685,7 @@ module Druid
632
685
  # @param optional block to be invoked when element method is called
633
686
  #
634
687
  def text_area(name, identifier={:index => 0}, &block)
688
+ standard_methods(name, identifier, 'text_area_for', &block)
635
689
  define_method("#{name}=") do |value|
636
690
  return text_area_value_set(identifier.clone, value) unless block_given?
637
691
  self.send("#{name}_element").value = value
@@ -640,7 +694,6 @@ module Druid
640
694
  return text_area_value_for identifier.clone unless block_given?
641
695
  self.send("#{name}_element").value
642
696
  end
643
- standard_methods(name, identifier, 'text_area_for', &block)
644
697
  end
645
698
  alias_method :textarea, :text_area
646
699
 
@@ -663,11 +716,11 @@ module Druid
663
716
  # * :css
664
717
  # @param optional block to be invoked when element method is called
665
718
  def unordered_list(name, identifier={:index => 0}, &block)
719
+ standard_methods(name, identifier, 'unordered_list_for', &block)
666
720
  define_method(name) do
667
721
  return unordered_list_text_for identifier.clone unless block_given?
668
722
  self.send("#{name}_element").text
669
723
  end
670
- standard_methods(name, identifier, 'unordered_list_for', &block)
671
724
  end
672
725
  alias_method :ul, :unordered_list
673
726
 
@@ -691,11 +744,11 @@ module Druid
691
744
  # @param optional block to be invoked when element method is called
692
745
  #
693
746
  def h1(name, identifier={:index => 0}, &block)
747
+ standard_methods(name, identifier, 'h1_for', &block)
694
748
  define_method(name) do
695
749
  return h1_text_for identifier.clone unless block_given?
696
750
  self.send("#{name}_element").text
697
751
  end
698
- standard_methods(name, identifier, 'h1_for', &block)
699
752
  end
700
753
 
701
754
  #
@@ -718,11 +771,11 @@ module Druid
718
771
  # @param optional block to be invoked when element method is called
719
772
  #
720
773
  def h2(name, identifier={:index => 0}, &block)
774
+ standard_methods(name, identifier, 'h2_for', &block)
721
775
  define_method(name) do
722
776
  return h2_text_for identifier.clone unless block_given?
723
777
  self.send("#{name}_element").text
724
778
  end
725
- standard_methods(name, identifier, 'h2_for', &block)
726
779
  end
727
780
 
728
781
  #
@@ -745,11 +798,11 @@ module Druid
745
798
  # @param optional block to be invoked when element method is called
746
799
  #
747
800
  def h3(name, identifier={:index => 0}, &block)
801
+ standard_methods(name, identifier, 'h3_for', &block)
748
802
  define_method(name) do
749
803
  return h3_text_for identifier.clone unless block_given?
750
804
  self.send("#{name}_element").text
751
805
  end
752
- standard_methods(name, identifier, 'h3_for', &block)
753
806
  end
754
807
 
755
808
  #
@@ -772,11 +825,11 @@ module Druid
772
825
  # @param optional block to be invoked when element method is called
773
826
  #
774
827
  def h4(name, identifier={:index => 0}, &block)
828
+ standard_methods(name, identifier, 'h4_for', &block)
775
829
  define_method(name) do
776
830
  return h4_text_for identifier.clone unless block_given?
777
831
  self.send("#{name}_element").text
778
832
  end
779
- standard_methods(name, identifier, 'h4_for', &block)
780
833
  end
781
834
 
782
835
  #
@@ -799,11 +852,11 @@ module Druid
799
852
  # @param optional block to be invoked when element method is called
800
853
  #
801
854
  def h5(name, identifier={:index => 0}, &block)
855
+ standard_methods(name, identifier, 'h5_for', &block)
802
856
  define_method(name) do
803
857
  return h5_text_for identifier.clone unless block_given?
804
858
  self.send("#{name}_element").text
805
859
  end
806
- standard_methods(name, identifier, 'h5_for', &block)
807
860
  end
808
861
 
809
862
  #
@@ -826,11 +879,11 @@ module Druid
826
879
  # @param optional block to be invoked when element method is called
827
880
  #
828
881
  def h6(name, identifier={:index => 0}, &block)
882
+ standard_methods(name, identifier, 'h6_for', &block)
829
883
  define_method(name) do
830
884
  return h6_text_for identifier.clone unless block_given?
831
885
  self.send("#{name}_element").text
832
886
  end
833
- standard_methods(name, identifier, 'h6_for', &block)
834
887
  end
835
888
 
836
889
  #
@@ -853,11 +906,11 @@ module Druid
853
906
  # @param optional block to be invoked when element method is called
854
907
  #
855
908
  def paragraph(name, identifier={:index => 0}, &block)
909
+ standard_methods(name, identifier, 'paragraph_for', &block)
856
910
  define_method(name) do
857
911
  return paragraph_text_for identifier.clone unless block_given?
858
912
  self.send("#{name}_element").text
859
913
  end
860
- standard_methods(name, identifier, 'paragraph_for', &block)
861
914
  end
862
915
  alias_method :p, :paragraph
863
916
 
@@ -883,11 +936,11 @@ module Druid
883
936
  # @param optional block to be invoked when element method is called
884
937
  #
885
938
  def file_field(name, identifier={:index => 0}, &block)
939
+ standard_methods(name, identifier, 'file_field_for', &block)
886
940
  define_method("#{name}=") do |value|
887
941
  return file_field_value_set(identifier.clone, value) unless block_given?
888
942
  self.send("#{name}_element").value = value
889
943
  end
890
- standard_methods(name, identifier, 'file_field_for', &block)
891
944
  end
892
945
 
893
946
  #
@@ -911,11 +964,11 @@ module Druid
911
964
  # @param optional block to be invoked when element method is called
912
965
  #
913
966
  def label(name, identifier={:index => 0}, &block)
967
+ standard_methods(name, identifier, 'label_for', &block)
914
968
  define_method(name) do
915
969
  return label_text_for identifier.clone unless block_given?
916
970
  self.send("#{name}_element").text
917
971
  end
918
- standard_methods(name, identifier, 'label_for', &block)
919
972
  end
920
973
 
921
974
  #
@@ -939,11 +992,11 @@ module Druid
939
992
  # @param optional block to be invoked when element method is called
940
993
  #
941
994
  def area(name, identifier={:index => 0}, &block)
995
+ standard_methods(name, identifier, 'area_for', &block)
942
996
  define_method(name) do
943
997
  return click_area_for identifier.clone unless block_given?
944
998
  self.send("#{name}_element").click
945
999
  end
946
- standard_methods(name, identifier, 'area_for', &block)
947
1000
  end
948
1001
 
949
1002
  #
@@ -1015,6 +1068,56 @@ module Druid
1015
1068
  standard_methods(name, identifier, 'video_for', &block)
1016
1069
  end
1017
1070
 
1071
+ #
1072
+ # adds three methods - one to retrieve the text of a b element, another to
1073
+ # retrieve a b element, and another to check for it's existence.
1074
+ #
1075
+ # @example
1076
+ # b(:blod, :id => 'title')
1077
+ # # will generate 'bold', 'bold_element', 'bold?' methods
1078
+ #
1079
+ # @param [Symbol] the name used for the generated methods
1080
+ # @param [Hash] identifier how we find a b, You can use a multiple parameters
1081
+ # by combining of any of the following except xpath. The valid keys are:
1082
+ # * :class
1083
+ # * :css
1084
+ # * :id
1085
+ # * :index
1086
+ # * :name
1087
+ # * :xpath
1088
+ # @param optional block to be invoked when element method is called
1089
+ #
1090
+ def b(name, identifier={:index => 0}, &block)
1091
+ standard_methods(name, identifier, 'b_for', &block)
1092
+ define_method(name) do
1093
+ return b_text_for identifier.clone unless block_given?
1094
+ self.send("#{name}_element").text
1095
+ end
1096
+ end
1097
+
1098
+ #
1099
+ # adds two methods - one to retrieve a svg, and another to check
1100
+ # svg's existence.
1101
+ #
1102
+ # @example
1103
+ # svg(:circle, :id => 'circle')
1104
+ # # will generate 'circle_element', and 'circle?' methods
1105
+ #
1106
+ # @param [Symbol] the name used for the generated methods
1107
+ # @param [Hash] identifier how we find a svg. You can use a multiple parameters
1108
+ # by combining of any of the following except xpath. The valid keys are:
1109
+ # * :class
1110
+ # * :css
1111
+ # * :id
1112
+ # * :index
1113
+ # * :name
1114
+ # * :xpath
1115
+ # @param optional block to be invoked when element method is called
1116
+ #
1117
+ def svg(name, identifier={:index => 0}, &block)
1118
+ standard_methods(name, identifier, 'svg_for', &block)
1119
+ end
1120
+
1018
1121
  #
1019
1122
  # adds three methods - one to retrieve the text an element, another
1020
1123
  # to retrieve an element, and another to check the element's existence.
@@ -1074,16 +1177,27 @@ module Druid
1074
1177
  end
1075
1178
  end
1076
1179
 
1180
+ def standard_methods(name, identifier, method, &block)
1181
+ define_method("#{name}_element") do
1182
+ return call_block(&block) if block_given?
1183
+ self.send(method, identifier.clone)
1184
+ end
1185
+ define_method("#{name}?") do
1186
+ return call_block(&block).exist? if block_given?
1187
+ self.send(method, identifier.clone).exist?
1188
+ end
1189
+ end
1190
+
1077
1191
  #
1078
- # adds two methods - one to retrieve a svg, and another to check
1079
- # svg's existence.
1192
+ # adds a method to return a page object rooted at the element
1080
1193
  #
1081
1194
  # @example
1082
- # svg(:circle, :id => 'circle')
1083
- # # will generate 'circle_element', and 'circle?' methods
1195
+ # page_section(:navigation_bar, NavigationBar, :id => 'nav-bar')
1196
+ # # will generate 'navigation_bar'
1084
1197
  #
1085
1198
  # @param [Symbol] the name used for the generated methods
1086
- # @param [Hash] identifier how we find a svg. You can use a multiple parameters
1199
+ # @param [Class] the class to instantiate for the element
1200
+ # @param [Hash] identifier how we find an element. You can use multiple parameters
1087
1201
  # by combining of any of the following except xpath. The valid keys are:
1088
1202
  # * :class
1089
1203
  # * :css
@@ -1091,10 +1205,35 @@ module Druid
1091
1205
  # * :index
1092
1206
  # * :name
1093
1207
  # * :xpath
1094
- # @param optional block to be invoked when element method is called
1095
1208
  #
1096
- def svg(name, identifier={:index => 0}, &block)
1097
- standard_methods(name, identifier, 'svg_for', &block)
1209
+ def page_section(name, section_class, identifier)
1210
+ define_method(name) do
1211
+ page_for(identifier, section_class)
1212
+ end
1213
+ end
1214
+
1215
+ #
1216
+ # adds a method to return a collection of page objects rooted at elements
1217
+ #
1218
+ # @example
1219
+ # page_sections(:articles, Article, :class => 'article')
1220
+ # # will generate 'articles'
1221
+ #
1222
+ # @param [Symbol] the name used for the generated method
1223
+ # @param [Class] the class to instantiate for each element
1224
+ # @param [Hash] identifier how we find an element. You can use a multiple parameters
1225
+ # by combining of any of the following except xpath. The valid keys are:
1226
+ # * :class
1227
+ # * :css
1228
+ # * :id
1229
+ # * :index
1230
+ # * :name
1231
+ # * :xpath
1232
+ #
1233
+ def page_sections(name, section_class, identifier)
1234
+ define_method(name) do
1235
+ pages_for(identifier, section_class)
1236
+ end
1098
1237
  end
1099
1238
 
1100
1239
  #
@@ -1117,22 +1256,16 @@ module Druid
1117
1256
  # * :xpath
1118
1257
  # @param optional block to be invoked when element method is called
1119
1258
  #
1120
- LocatorGenerator::BASIC_ELEMENTS.each do |type|
1121
- define_method(type) do |name, *identifier, &block|
1259
+ LocatorGenerator::BASIC_ELEMENTS.each do |tag|
1260
+ define_method(tag) do |name, *identifier, &block|
1122
1261
  identifier = identifier[0] ? identifier[0] : {:index => 0}
1123
- element(name, type, identifier, &block)
1262
+ element(name, tag, identifier, &block)
1124
1263
  end
1125
- end
1126
1264
 
1127
- def standard_methods(name, identifier, method, &block)
1128
- define_method("#{name}_element") do
1129
- return call_block(&block) if block_given?
1130
- self.send(method, identifier.clone)
1131
- end
1132
- define_method("#{name}?") do
1133
- return call_block(&block).exist? if block_given?
1134
- self.send(method, identifier.clone).exist?
1135
- end
1265
+ define_method("#{tag}s") do |name, *identifier, &block|
1266
+ identifier = identifier[0] ? identifier[0] : {:index => 0}
1267
+ elements(name, tag, identifier, &block)
1268
+ end unless tag == :param
1136
1269
  end
1137
1270
 
1138
1271
  #