page-object 0.7.6 → 0.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -17,3 +17,7 @@ end
17
17
  Then /^I should see that the ordered list exists$/ do
18
18
  @page.ol_id?.should == true
19
19
  end
20
+
21
+ Then /^the text for the ordered list should contain "(.*)"$/ do |text|
22
+ @page.send("ol_id").should include text
23
+ end
@@ -55,3 +55,7 @@ end
55
55
  Then /^the data for row "([^\"]*)" and column "([^\"]*)" should be nil$/ do |row, column|
56
56
  @element[row][column].should be_nil
57
57
  end
58
+
59
+ Then /^I should see the text includes "([^"]*)" when I retrieve it by "([^"]*)"$/ do |text, how|
60
+ @page.send("table_#{how}").should include text
61
+ end
@@ -16,4 +16,8 @@ end
16
16
 
17
17
  Then /^I should see that the unordered list exists$/ do
18
18
  @page.ul_id?.should == true
19
- end
19
+ end
20
+
21
+ Then /^the text for the unordered list should contain "(.*)"$/ do |text|
22
+ @page.send("ul_id").should include text
23
+ end
@@ -111,3 +111,7 @@ Feature: Table
111
111
  @watir_only
112
112
  Scenario: Finding an existing table
113
113
  Then I should see that the table exists
114
+
115
+ Scenario: Getting the text from a table
116
+ Then I should see the text includes "Data1" when I retrieve it by "id"
117
+ And I should see the text includes "Data2" when I retrieve it by "id"
@@ -49,3 +49,8 @@ Feature: Unordered list
49
49
  Then I should see that the unordered list exists
50
50
  When I get the first item from the list
51
51
  Then the list items text should be "Item One"
52
+
53
+ Scenario: Getting the text from an unordered list
54
+ Then the text for the unordered list should contain "Item One"
55
+ And the text for the unordered list should contain "Item Two"
56
+ And the text for the unordered list should contain "Item Three"
data/lib/page-object.rb CHANGED
@@ -7,6 +7,7 @@ require 'page-object/page_factory'
7
7
  require 'page-object/page_populator'
8
8
  require 'page-object/javascript_framework_facade'
9
9
  require 'page-object/indexed_properties'
10
+ require 'page-object/widgets'
10
11
 
11
12
  require 'selenium/webdriver/common/error'
12
13
  #
@@ -41,7 +42,7 @@ module PageObject
41
42
  include LoadsPlatform
42
43
  include ElementLocators
43
44
  include PagePopulator
44
-
45
+
45
46
  # @return [Watir::Browser or Selenium::WebDriver::Driver] the platform browser passed to the constructor
46
47
  attr_reader :browser
47
48
  # @return [PageObject::WatirPageObject or PageObject::SeleniumPageObject] the platform page object
@@ -251,7 +252,7 @@ module PageObject
251
252
  def execute_script(script)
252
253
  platform.execute_script(script)
253
254
  end
254
-
255
+
255
256
  #
256
257
  # Identify an element as existing within a frame or iframe. A frame parameter
257
258
  # is passed to the block and must be passed to the other calls to PageObject.
@@ -287,7 +288,7 @@ module PageObject
287
288
  #
288
289
  def modal_dialog(&block)
289
290
  script =
290
- %Q{
291
+ %Q{
291
292
  window.showModalDialog = function(sURL, vArguments, sFeatures) {
292
293
  window.dialogArguments = vArguments;
293
294
  modalWin = window.open(sURL, 'modal', sFeatures);
@@ -297,7 +298,7 @@ module PageObject
297
298
  browser.execute_script script
298
299
  yield if block_given?
299
300
  end
300
-
301
+
301
302
  #
302
303
  # Attach to a running window. You can locate the window using either
303
304
  # the window's title or url. If it failes to connect to a window it will
@@ -326,35 +327,35 @@ module PageObject
326
327
  def element_with_focus
327
328
  platform.element_with_focus
328
329
  end
329
-
330
+
330
331
  #
331
332
  # Refresh to current page
332
333
  #
333
334
  def refresh
334
335
  platform.refresh
335
336
  end
336
-
337
+
337
338
  #
338
339
  # Go back to the previous page
339
340
  #
340
341
  def back
341
342
  platform.back
342
343
  end
343
-
344
+
344
345
  #
345
346
  # Go forward to the next page
346
347
  #
347
348
  def forward
348
349
  platform.forward
349
350
  end
350
-
351
+
351
352
  #
352
353
  # Clear the cookies from the browser
353
354
  #
354
355
  def clear_cookies
355
356
  platform.clear_cookies
356
357
  end
357
-
358
+
358
359
  #
359
360
  # Save the current screenshot to the provided url. File
360
361
  # is saved as a png file.
@@ -363,13 +364,17 @@ module PageObject
363
364
  platform.save_screenshot file_name
364
365
  end
365
366
 
367
+ def self.register_widget(widget_tag, widget_class, base_element_tag)
368
+ Widgets.register_widget(widget_tag, widget_class, base_element_tag)
369
+ end
370
+
366
371
  private
367
372
 
368
373
  def include_platform_driver(browser)
369
374
  @platform = load_platform(browser, PageObject::Platforms.get)
370
375
  end
371
-
376
+
372
377
  def call_block(&block)
373
- block.arity == 1 ? block.call(self) : self.instance_eval(&block)
378
+ block.arity == 1 ? block.call(self) : self.instance_eval(&block)
374
379
  end
375
380
  end
@@ -528,13 +528,14 @@ module PageObject
528
528
  end
529
529
 
530
530
  #
531
- # adds two methods - one to retrieve the table element, and another to
531
+ # adds three methods - one to return the text for the table, one
532
+ # to retrieve the table element, and another to
532
533
  # check the table's existence. The existence method does not work
533
534
  # on Selenium so it should not be called.
534
535
  #
535
536
  # @example
536
537
  # table(:cart, :id => 'shopping_cart')
537
- # # will generate a 'cart_element' and 'cart?' method
538
+ # # will generate a 'cart', 'cart_element' and 'cart?' method
538
539
  #
539
540
  # @param [Symbol] the name used for the generated methods
540
541
  # @param [Hash] identifier how we find a table. You can use a multiple paramaters
@@ -548,6 +549,10 @@ module PageObject
548
549
  # @param optional block to be invoked when element method is called
549
550
  #
550
551
  def table(name, identifier={:index => 0}, &block)
552
+ define_method(name) do
553
+ return platform.table_text_for identifier.clone unless block_given?
554
+ self.send("#{name}_element").text
555
+ end
551
556
  define_method("#{name}_element") do
552
557
  return call_block(&block) if block_given?
553
558
  platform.table_for(identifier.clone)
@@ -701,12 +706,13 @@ module PageObject
701
706
  alias_method :li, :list_item
702
707
 
703
708
  #
704
- # adds two methods - one to retrieve the unordered list element, and another to
709
+ # adds three methods - one to return the text within the unorderd
710
+ # list, one to retrieve the unordered list element, and another to
705
711
  # check it's existence.
706
712
  #
707
713
  # @example
708
714
  # unordered_list(:menu, :id => 'main_menu')
709
- # # will generate 'menu_element' and 'menu?' methods
715
+ # # will generate 'menu', 'menu_element' and 'menu?' methods
710
716
  #
711
717
  # @param [Symbol] the name used for the generated methods
712
718
  # @param [Hash] identifier how we find an unordered list. You can use a multiple paramaters
@@ -720,6 +726,10 @@ module PageObject
720
726
  # @param optional block to be invoked when element method is called
721
727
  #
722
728
  def unordered_list(name, identifier={:index => 0}, &block)
729
+ define_method(name) do
730
+ return platform.unordered_list_text_for identifier.clone unless block_given?
731
+ self.send("#{name}_element").text
732
+ end
723
733
  define_method("#{name}_element") do
724
734
  return call_block(&block) if block_given?
725
735
  platform.unordered_list_for(identifier.clone)
@@ -733,12 +743,13 @@ module PageObject
733
743
  alias_method :ul, :unordered_list
734
744
 
735
745
  #
736
- # adds two methods - one to retrieve the ordered list element, and another to
746
+ # adds three methods - one to return the text withing the ordered
747
+ # list, one to retrieve the ordered list element, and another to
737
748
  # test it's existence.
738
749
  #
739
750
  # @example
740
751
  # ordered_list(:top_five, :id => 'top')
741
- # # will generate 'top_five_element' and 'top_five?' methods
752
+ # # will generate 'top_five', 'top_five_element' and 'top_five?' methods
742
753
  #
743
754
  # @param [Symbol] the name used for the generated methods
744
755
  # @param [Hash] identifier how we find an ordered list. You can use a multiple paramaters
@@ -752,6 +763,10 @@ module PageObject
752
763
  # @param optional block to be invoked when element method is called
753
764
  #
754
765
  def ordered_list(name, identifier={:index => 0}, &block)
766
+ define_method(name) do
767
+ return platform.ordered_list_text_for identifier.clone unless block_given?
768
+ self.send("#{name}_element").text
769
+ end
755
770
  define_method("#{name}_element") do
756
771
  return call_block(&block) if block_given?
757
772
  platform.ordered_list_for(identifier.clone)
@@ -1981,5 +1996,55 @@ module PageObject
1981
1996
  IndexedProperties::TableOfElements.new(@browser, identifier_list)
1982
1997
  end
1983
1998
  end
1999
+
2000
+ #
2001
+ # methods to fetch multiple elements of the same type
2002
+ #
2003
+ # adds a method to the page object to retrun all of the matching elements
2004
+ #
2005
+ # @example
2006
+ # text_fields(:first_name, :id => "first_name")
2007
+ # # will generate 'first_name_elements'
2008
+ #
2009
+ # @param [String] the name used for the generated methods
2010
+ # @param [Hash] identifier how we find a text field. You can use a multiple paramaters
2011
+ # by combining of any of the following except xpath. The valid
2012
+ # keys are the same ones supported by the standard methods.
2013
+ # @param optional block to be invoked when element method is called
2014
+ #
2015
+ [:text_fields,
2016
+ :hidden_fields,
2017
+ :text_areas,
2018
+ :select_lists,
2019
+ :links,
2020
+ :checkboxes,
2021
+ :radio_buttons,
2022
+ :buttons,
2023
+ :divs,
2024
+ :spans,
2025
+ :tables,
2026
+ :cells,
2027
+ :images,
2028
+ :forms,
2029
+ :list_items,
2030
+ :unordered_lists,
2031
+ :ordered_lists,
2032
+ :h1s,
2033
+ :h2s,
2034
+ :h3s,
2035
+ :h4s,
2036
+ :h5s,
2037
+ :h6s,
2038
+ :paragraphs,
2039
+ :labels,
2040
+ :file_fields].each do |method_name|
2041
+ define_method(method_name) do |name, identifier, &block|
2042
+ define_method("#{name}_elements") do
2043
+ return call_block(&block) if block_given?
2044
+ platform.send "#{method_name.to_s}_for", identifier.clone
2045
+ end
2046
+ end
2047
+ end
2048
+
1984
2049
  end
1985
2050
  end
@@ -44,6 +44,16 @@ module PageObject
44
44
  element.text
45
45
  end
46
46
 
47
+ #
48
+ # Get the html for the element
49
+ #
50
+ # @return [String]
51
+ #
52
+ def html
53
+ script = "return (%s).apply(null, arguments)" % ATOMS.fetch(:getOuterHtml)
54
+ bridge.executeScript(script, element).strip
55
+ end
56
+
47
57
  #
48
58
  # Get the value of this element
49
59
  #
@@ -525,6 +525,16 @@ module PageObject
525
525
  find_selenium_elements(identifier, Elements::Button, 'input', :type => 'submit')
526
526
  end
527
527
 
528
+ #
529
+ # platform method to return the text for a table
530
+ # See PageObject::Accessors#table
531
+ #
532
+ def table_text_for(identifier)
533
+ process_selenium_call(identifier, Elements::Table, 'table') do |how, what|
534
+ @browser.find_element(how, what).text
535
+ end
536
+ end
537
+
528
538
  #
529
539
  # platform method to retrieve a table element
530
540
  # See PageObject::Accessors#table
@@ -620,6 +630,16 @@ module PageObject
620
630
  find_selenium_elements(identifier, Elements::ListItem, 'li')
621
631
  end
622
632
 
633
+ #
634
+ # platform method to retrieve the text from an unordered list
635
+ # See PageObject::Accessors#unordered_list
636
+ #
637
+ def unordered_list_text_for(identifier)
638
+ process_selenium_call(identifier, Elements::UnorderedList, 'ul') do |how, what|
639
+ @browser.find_element(how, what).text
640
+ end
641
+ end
642
+
623
643
  #
624
644
  # platform method to retrieve an unordered list element
625
645
  # See PageObject::Accessors#unordered_list
@@ -635,6 +655,16 @@ module PageObject
635
655
  find_selenium_elements(identifier, Elements::UnorderedList, 'ul')
636
656
  end
637
657
 
658
+ #
659
+ # platform method to retrieve the text from an ordered list
660
+ # See PageObject::Accessors#ordered_list
661
+ #
662
+ def ordered_list_text_for(identifier)
663
+ process_selenium_call(identifier, Elements::OrderedList, 'ol') do |how, what|
664
+ @browser.find_element(how, what).text
665
+ end
666
+ end
667
+
638
668
  #
639
669
  # platform method to retrieve an ordered list element
640
670
  # See PageObject::Accessors#ordered_list
@@ -36,6 +36,15 @@ module PageObject
36
36
  element.text
37
37
  end
38
38
 
39
+ #
40
+ # Get the html for the element
41
+ #
42
+ # @return [String]
43
+ #
44
+ def html
45
+ element.html
46
+ end
47
+
39
48
  #
40
49
  # Get the value of this element
41
50
  #
@@ -481,6 +481,14 @@ module PageObject
481
481
  find_watir_elements(call, Elements::Button, identifier)
482
482
  end
483
483
 
484
+ #
485
+ # platform method to return the text for a table
486
+ # See PageObject::Accessors#table
487
+ #
488
+ def table_text_for(identifier)
489
+ process_watir_call("table(identifier).text", Elements::Table, identifier, nil, 'table')
490
+ end
491
+
484
492
  #
485
493
  # platform method to retrieve a table element
486
494
  # See PageObject::Accessors#table
@@ -573,6 +581,14 @@ module PageObject
573
581
  find_watir_elements("lis(identifier)", Elements::ListItem, identifier, 'li')
574
582
  end
575
583
 
584
+ #
585
+ # platform method to retrieve the text from an unordered list
586
+ # See PageObject::Accessors#unordered_list
587
+ #
588
+ def unordered_list_text_for(identifier)
589
+ process_watir_call("ul(identifier).text", Elements::UnorderedList, identifier, nil, 'ul')
590
+ end
591
+
576
592
  #
577
593
  # platform method to retrieve an unordered list element
578
594
  # See PageObject::Accessors#unordered_list
@@ -588,6 +604,14 @@ module PageObject
588
604
  find_watir_elements("uls(identifier)", Elements::UnorderedList, identifier, 'ul')
589
605
  end
590
606
 
607
+ #
608
+ # platform method to retrieve the text from an ordered list
609
+ # See PageObject::Accessors#ordered_list
610
+ #
611
+ def ordered_list_text_for(identifier)
612
+ process_watir_call("ol(identifier).text", Elements::OrderedList, identifier, nil, 'ol')
613
+ end
614
+
591
615
  #
592
616
  # platform method to retrieve an ordered list element
593
617
  # See PageObject::Accessors#ordered_list
@@ -1,4 +1,4 @@
1
1
  module PageObject
2
2
  # @private
3
- VERSION = "0.7.6"
3
+ VERSION = "0.8"
4
4
  end
@@ -0,0 +1,120 @@
1
+ require 'page-object/elements'
2
+ require 'page-object/platforms/selenium_webdriver/page_object'
3
+ require 'page-object/platforms/watir_webdriver/page_object'
4
+
5
+ module PageObject
6
+ module Widgets
7
+
8
+ #
9
+ # Module that allows for the registration of widget classes which extend the functionality of PageObject
10
+ # Allows any classes which extend PageObject::Element to be used as PageObject elements.
11
+ # This allows such widgets to be created using the defined tags.
12
+ #
13
+ # @param [Symbol] defines the symbol which will be used as an accessor name.
14
+ # @param [Class] the widget class extending PageObject::Elements::Element
15
+ # @param [Symbol] the symbol of the html element used when searching for this widget.
16
+ #
17
+ #
18
+ def self.register_widget(widget_tag, widget_class, base_element_tag)
19
+ if widget_class.ancestors.include? Elements::Element
20
+ define_accessors(Accessors, widget_tag)
21
+ define_nested_elements(Elements::Element, widget_tag)
22
+ define_locators(PageObject, widget_tag)
23
+ define_selenium_accessors(Platforms::SeleniumWebDriver::PageObject, widget_tag, widget_class, base_element_tag)
24
+ define_watir_accessors(Platforms::WatirWebDriver::PageObject, widget_tag, widget_class, base_element_tag)
25
+ end
26
+ end
27
+
28
+ @private
29
+
30
+ def self.define_accessors(base, widget_tag)
31
+ accessors_module = Module.new do
32
+ class_eval "def #{widget_tag}(name, identifier={}, &block)
33
+ identifier={:index=>0} if identifier.empty?
34
+ define_method(\"\#{name}_element\") do
35
+ return call_block(&block) if block_given?
36
+ platform.#{widget_tag}_for(identifier.clone)
37
+ end
38
+ define_method(\"\#{name}?\") do
39
+ return call_block(&block).exists? if block_given?
40
+ platform.#{widget_tag}_for(identifier.clone).exists?
41
+ end
42
+ end"
43
+ end
44
+
45
+ base.send(:include, accessors_module)
46
+ end
47
+
48
+ def self.define_watir_accessors(base, widget_tag, widget_class, base_element_tag)
49
+ define_singular_watir_accessor(base, base_element_tag, widget_class, widget_tag)
50
+ define_multiple_watir_accessor(base, base_element_tag, widget_class, widget_tag)
51
+ end
52
+
53
+ def self.define_multiple_watir_accessor(base, base_element_tag, widget_class, widget_tag)
54
+ base.send(:define_method, "#{widget_tag}s_for") do |identifier|
55
+ find_watir_elements("#{base_element_tag}(identifier)", widget_class, identifier, base_element_tag)
56
+ end
57
+ end
58
+
59
+ def self.define_singular_watir_accessor(base, base_element_tag, widget_class, widget_tag)
60
+ base.send(:define_method, "#{widget_tag}_for") do |identifier|
61
+ find_watir_element("#{base_element_tag}(identifier)", widget_class, identifier, base_element_tag)
62
+ end
63
+ end
64
+
65
+ def self.define_selenium_accessors(base, widget_tag, widget_class, base_element_tag)
66
+ define_singular_selenium_accessor(base, base_element_tag, widget_class, widget_tag)
67
+ define_multiple_selenium_accessor(base, base_element_tag, widget_class, widget_tag)
68
+ end
69
+
70
+ def self.define_multiple_selenium_accessor(base, base_element_tag, widget_class, widget_tag)
71
+ base.send(:define_method, "#{widget_tag}s_for") do |identifier|
72
+ find_selenium_elements(identifier, widget_class, base_element_tag)
73
+ end
74
+ end
75
+
76
+ def self.define_singular_selenium_accessor(base, base_element_tag, widget_class, widget_tag)
77
+ base.send(:define_method, "#{widget_tag}_for") do |identifier|
78
+ find_selenium_element(identifier, widget_class, base_element_tag)
79
+ end
80
+ end
81
+
82
+ def self.define_nested_elements(base, widget_tag)
83
+ define_singular_nested_accessor(base, widget_tag)
84
+ define_multiple_nested_accessor(base, widget_tag)
85
+ end
86
+
87
+ def self.define_multiple_nested_accessor(base, widget_tag)
88
+ base.send(:define_method, "#{widget_tag}_elements") do |*args|
89
+ identifier = args[0] ? args[0] : {:index => 0}
90
+ @platform.send("#{widget_tag}s_for", identifier.clone)
91
+ end
92
+ end
93
+
94
+ def self.define_singular_nested_accessor(base, widget_tag)
95
+ base.send(:define_method, "#{widget_tag}_element") do |*args|
96
+ identifier = args[0] ? args[0] : {:index => 0}
97
+ @platform.send("#{widget_tag}_for", identifier.clone)
98
+ end
99
+ end
100
+
101
+ def self.define_locators(base, widget_tag)
102
+ define_singular_locator(base, widget_tag)
103
+ define_multiple_locator(base, widget_tag)
104
+ end
105
+
106
+ def self.define_multiple_locator(base, widget_tag)
107
+ base.send(:define_method, "#{widget_tag}_elements") do |*args|
108
+ identifier = args[0] ? args[0] : {}
109
+ platform.send("#{widget_tag}s_for", identifier.clone)
110
+ end
111
+ end
112
+
113
+ def self.define_singular_locator(base, widget_tag)
114
+ base.send(:define_method, "#{widget_tag}_element") do |*args|
115
+ identifier = args[0] ? args[0] : {:index => 0}
116
+ platform.send("#{widget_tag}_for", identifier.clone)
117
+ end
118
+ end
119
+ end
120
+ end