centric_page_object 2.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +7 -0
  2. data/.coveralls.yml +1 -0
  3. data/.gitignore +8 -0
  4. data/.rspec +2 -0
  5. data/.ruby-gemset +1 -0
  6. data/.ruby-version +1 -0
  7. data/.travis.yml +17 -0
  8. data/ChangeLog +931 -0
  9. data/Gemfile +12 -0
  10. data/Guardfile +20 -0
  11. data/LICENSE +20 -0
  12. data/README.md +114 -0
  13. data/Rakefile +29 -0
  14. data/centric_page_object.gemspec +31 -0
  15. data/cucumber.yml +8 -0
  16. data/lib/page-object/accessors.rb +1201 -0
  17. data/lib/page-object/element_locators.rb +21 -0
  18. data/lib/page-object/elements/area.rb +9 -0
  19. data/lib/page-object/elements/audio.rb +9 -0
  20. data/lib/page-object/elements/bold.rb +9 -0
  21. data/lib/page-object/elements/button.rb +12 -0
  22. data/lib/page-object/elements/canvas.rb +10 -0
  23. data/lib/page-object/elements/check_box.rb +9 -0
  24. data/lib/page-object/elements/date_field.rb +10 -0
  25. data/lib/page-object/elements/div.rb +9 -0
  26. data/lib/page-object/elements/element.rb +212 -0
  27. data/lib/page-object/elements/file_field.rb +9 -0
  28. data/lib/page-object/elements/form.rb +9 -0
  29. data/lib/page-object/elements/heading.rb +14 -0
  30. data/lib/page-object/elements/hidden_field.rb +9 -0
  31. data/lib/page-object/elements/image.rb +10 -0
  32. data/lib/page-object/elements/italic.rb +9 -0
  33. data/lib/page-object/elements/label.rb +9 -0
  34. data/lib/page-object/elements/link.rb +9 -0
  35. data/lib/page-object/elements/list_item.rb +9 -0
  36. data/lib/page-object/elements/media.rb +11 -0
  37. data/lib/page-object/elements/option.rb +9 -0
  38. data/lib/page-object/elements/ordered_list.rb +43 -0
  39. data/lib/page-object/elements/paragraph.rb +9 -0
  40. data/lib/page-object/elements/radio_button.rb +9 -0
  41. data/lib/page-object/elements/select_list.rb +42 -0
  42. data/lib/page-object/elements/span.rb +9 -0
  43. data/lib/page-object/elements/table.rb +85 -0
  44. data/lib/page-object/elements/table_cell.rb +10 -0
  45. data/lib/page-object/elements/table_row.rb +52 -0
  46. data/lib/page-object/elements/text_area.rb +9 -0
  47. data/lib/page-object/elements/text_field.rb +10 -0
  48. data/lib/page-object/elements/unordered_list.rb +42 -0
  49. data/lib/page-object/elements/video.rb +9 -0
  50. data/lib/page-object/elements.rb +62 -0
  51. data/lib/page-object/indexed_properties.rb +41 -0
  52. data/lib/page-object/javascript/angularjs.rb +14 -0
  53. data/lib/page-object/javascript/jquery.rb +14 -0
  54. data/lib/page-object/javascript/prototype.rb +14 -0
  55. data/lib/page-object/javascript/yui.rb +19 -0
  56. data/lib/page-object/javascript_framework_facade.rb +80 -0
  57. data/lib/page-object/locator_generator.rb +183 -0
  58. data/lib/page-object/nested_elements.rb +17 -0
  59. data/lib/page-object/page_factory.rb +108 -0
  60. data/lib/page-object/page_populator.rb +105 -0
  61. data/lib/page-object/platforms/watir/page_object.rb +1155 -0
  62. data/lib/page-object/platforms/watir.rb +50 -0
  63. data/lib/page-object/section_collection.rb +16 -0
  64. data/lib/page-object/version.rb +4 -0
  65. data/lib/page-object/widgets.rb +98 -0
  66. data/lib/page-object.rb +431 -0
  67. data/pageobject.gems +1 -0
  68. metadata +239 -0
@@ -0,0 +1,52 @@
1
+ require 'watir/elements/html_elements'
2
+
3
+ module PageObject
4
+ module Elements
5
+ class TableRow < Element
6
+ include Enumerable
7
+
8
+ #
9
+ # iterator that yields with a PageObject::Elements::TableCell
10
+ #
11
+ def each(&block)
12
+ cell_items.each(&block)
13
+ end
14
+
15
+ #
16
+ # Return the PageObject::Elements::TableCell for the index provided. Index
17
+ # is zero based. If the index provided is a String then it
18
+ # will be matched with the text from the columns in the first row.
19
+ # The text can be a substring of the full column text.
20
+ #
21
+ def [](what)
22
+ idx = find_index(what)
23
+ idx && cell_items[idx]
24
+ end
25
+
26
+ #
27
+ # Returns the number of columns in the table.
28
+ #
29
+ def columns
30
+ cell_items.size
31
+ end
32
+
33
+ protected
34
+
35
+ def cell_items
36
+ @cell_items ||= element.cells.map do |obj|
37
+ ::PageObject::Elements::TableCell.new(obj)
38
+ end
39
+ end
40
+
41
+ def find_index(what)
42
+ return what if what.is_a? Integer
43
+
44
+ parent(tag_name: 'table').headers.find_index do |header|
45
+ header.text.include? what
46
+ end
47
+ end
48
+ end
49
+
50
+ ::PageObject::Elements.tag_to_class[:tr] = ::PageObject::Elements::TableRow
51
+ end
52
+ end
@@ -0,0 +1,9 @@
1
+ module PageObject
2
+ module Elements
3
+ class TextArea < Element
4
+
5
+ end
6
+
7
+ ::PageObject::Elements.tag_to_class[:textarea] = ::PageObject::Elements::TextArea
8
+ end
9
+ end
@@ -0,0 +1,10 @@
1
+ module PageObject
2
+ module Elements
3
+ class TextField < Element
4
+
5
+ end
6
+
7
+ ::PageObject::Elements.type_to_class[:text] = ::PageObject::Elements::TextField
8
+ ::PageObject::Elements.type_to_class[:password] = ::PageObject::Elements::TextField
9
+ end
10
+ end
@@ -0,0 +1,42 @@
1
+ module PageObject
2
+ module Elements
3
+ class UnorderedList < Element
4
+ include Enumerable
5
+
6
+ #
7
+ # iterator that yields with a PageObject::Elements::ListItem
8
+ #
9
+ # @return [PageObject::Elements::ListItem]
10
+ #
11
+ def each(&block)
12
+ list_items.each(&block)
13
+ end
14
+
15
+ #
16
+ # Return the PageObject::Elements::ListItem for the index provided. Index
17
+ # is zero based.
18
+ #
19
+ # @return [PageObject::Elements::ListItem]
20
+ #
21
+ def [](idx)
22
+ list_items[idx]
23
+ end
24
+
25
+ #
26
+ # Return the number of items contained in the unordered list
27
+ #
28
+ def items
29
+ list_items.size
30
+ end
31
+
32
+ #
33
+ # Return Array of ListItem objects that are children of the UnorderedList
34
+ #
35
+ def list_items
36
+ @list_items ||= children(tag_name: 'li')
37
+ end
38
+ end
39
+
40
+ ::PageObject::Elements.tag_to_class[:ul] = ::PageObject::Elements::UnorderedList
41
+ end
42
+ end
@@ -0,0 +1,9 @@
1
+ module PageObject
2
+ module Elements
3
+ class Video < Media
4
+
5
+ end
6
+
7
+ ::PageObject::Elements.type_to_class[:video] = ::PageObject::Elements::Video
8
+ end
9
+ end
@@ -0,0 +1,62 @@
1
+ module PageObject
2
+ module Elements
3
+ class << self
4
+
5
+ #
6
+ # method to return the collection of tag_name to class mappings
7
+ #
8
+ def tag_to_class
9
+ @tag_to_class ||= {}
10
+ end
11
+
12
+ def type_to_class
13
+ @type_to_class ||= {}
14
+ end
15
+
16
+ #
17
+ # method to return the element for a tag_name
18
+ #
19
+ def element_class_for(tag_name, type=nil)
20
+ return type_to_class[type.to_sym] if type
21
+ tag_to_class[tag_name.to_sym] || ::PageObject::Elements::Element
22
+ end
23
+
24
+ end
25
+ end
26
+ end
27
+
28
+
29
+ require 'page-object/elements/element'
30
+ require 'page-object/elements/link'
31
+ require 'page-object/elements/text_field'
32
+ require 'page-object/elements/date_field'
33
+ require 'page-object/elements/select_list'
34
+ require 'page-object/elements/check_box'
35
+ require 'page-object/elements/button'
36
+ require 'page-object/elements/radio_button'
37
+ require 'page-object/elements/div'
38
+ require 'page-object/elements/table'
39
+ require 'page-object/elements/table_cell'
40
+ require 'page-object/elements/table_row'
41
+ require 'page-object/elements/span'
42
+ require 'page-object/elements/image'
43
+ require 'page-object/elements/hidden_field'
44
+ require 'page-object/elements/form'
45
+ require 'page-object/elements/text_area'
46
+ require 'page-object/elements/list_item'
47
+ require 'page-object/elements/unordered_list'
48
+ require 'page-object/elements/ordered_list'
49
+ require 'page-object/elements/option'
50
+ require 'page-object/elements/heading'
51
+ require 'page-object/elements/paragraph'
52
+ require 'page-object/elements/label'
53
+ require 'page-object/elements/file_field'
54
+ require 'page-object/elements/area'
55
+ require 'page-object/elements/canvas'
56
+ require 'page-object/elements/media'
57
+ require 'page-object/elements/audio'
58
+ require 'page-object/elements/video'
59
+ require 'page-object/elements/bold'
60
+ require 'page-object/elements/italic'
61
+
62
+
@@ -0,0 +1,41 @@
1
+ module PageObject
2
+ module IndexedProperties
3
+ class TableOfElements
4
+ include PageObject
5
+
6
+ def initialize (browser, identifier_list)
7
+ initialize_browser(browser)
8
+ @identifier_list = identifier_list
9
+ @indexed_property_class = Class.new {
10
+ include PageObject
11
+ extend Accessors
12
+
13
+ def initialize (browser, index, identifier_list)
14
+ initialize_browser(browser)
15
+
16
+ identifier_list.each do |identifier|
17
+ type = identifier[0]
18
+ name = identifier[1]
19
+ how_and_what = identifier[2].clone # Cannot modify the original...
20
+ how_and_what.each do |key, value|
21
+ next if value.is_a? Regexp # Cannot format Regexp with %
22
+ if key == :index
23
+ how_and_what[key] = (value % index).to_i
24
+ elsif key == :frame
25
+ how_and_what[key] = value #passthrough frame without modification
26
+ else
27
+ how_and_what[key] = value % index
28
+ end
29
+ end
30
+ self.class.send type, name, how_and_what unless Class.instance_methods.include? name
31
+ end
32
+ end
33
+ }
34
+ end
35
+
36
+ def [] (index)
37
+ @indexed_property_class.new(@browser, index, @identifier_list)
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,14 @@
1
+ module PageObject
2
+ module Javascript
3
+
4
+ module AngularJS
5
+ #
6
+ # return the number of pending ajax requests
7
+ #
8
+ def self.pending_requests
9
+ 'return angular.element(document.body).injector().get(\'$http\').pendingRequests.length;'
10
+ end
11
+ end
12
+
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ module PageObject
2
+ module Javascript
3
+
4
+ module JQuery
5
+ #
6
+ # return the number of pending ajax requests
7
+ #
8
+ def self.pending_requests
9
+ 'return jQuery.active'
10
+ end
11
+ end
12
+
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ module PageObject
2
+ module Javascript
3
+
4
+ module Prototype
5
+ #
6
+ # return the number of pending ajax requests
7
+ #
8
+ def self.pending_requests
9
+ 'return Ajax.activeRequestCount'
10
+ end
11
+ end
12
+
13
+ end
14
+ end
@@ -0,0 +1,19 @@
1
+ module PageObject
2
+ module Javascript
3
+
4
+ module YUI
5
+ #
6
+ # return the number of pending ajax requests
7
+ #
8
+ def self.pending_requests
9
+ "var inProgress=0
10
+ for(var i=0; i < YAHOO.util.Connect._transaction_id; i++) {
11
+ if(YAHOO.util.Connect.isCallInProgress(i))
12
+ inProgress++;
13
+ }
14
+ return inProgress;"
15
+ end
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,80 @@
1
+ require 'page-object/javascript/jquery'
2
+ require 'page-object/javascript/prototype'
3
+ require 'page-object/javascript/yui'
4
+ require 'page-object/javascript/angularjs'
5
+
6
+
7
+ module PageObject
8
+ #
9
+ # Provide hooks into different common Javascript Frameworks.
10
+ # Currently this module only supports jQuery and Prototype but it
11
+ # has the ability for you to plug your own framework into it and
12
+ # therefore have it work with this gem. You do this by calling the
13
+ # #add_framework method. The module you provide must implement the
14
+ # necessary methods. Please look at the jQuery or Prototype
15
+ # implementations to determine the necessary methods
16
+ #
17
+ module JavascriptFrameworkFacade
18
+
19
+ class << self
20
+ #
21
+ # Set the framework to use.
22
+ #
23
+ # @param[Symbol] the framework to use. :jquery, :prototype, :yui,
24
+ # and :angularjs are supported
25
+ #
26
+ def framework=(framework)
27
+ initialize_script_builder unless @builder
28
+ raise unknown_framework(framework) unless @builder[framework]
29
+ @framework = framework
30
+ end
31
+
32
+ #
33
+ # Get the framework that will be used
34
+ #
35
+ def framework
36
+ @framework
37
+ end
38
+
39
+ #
40
+ # Add a framework and make it available to the system.
41
+ #
42
+ def add_framework(key, value)
43
+ raise invalid_framework unless value.respond_to? :pending_requests
44
+ initialize_script_builder unless @builder
45
+ @builder[key] = value
46
+ end
47
+
48
+ #
49
+ # get the javascript to determine number of pending requests
50
+ #
51
+ def pending_requests
52
+ script_builder.pending_requests
53
+ end
54
+
55
+ def script_builder
56
+ initialize_script_builder unless @builder
57
+ @builder[@framework]
58
+ end
59
+
60
+ private
61
+
62
+ def initialize_script_builder
63
+ @builder = {
64
+ :jquery => ::PageObject::Javascript::JQuery,
65
+ :prototype => ::PageObject::Javascript::Prototype,
66
+ :yui => ::PageObject::Javascript::YUI,
67
+ :angularjs => ::PageObject::Javascript::AngularJS
68
+ }
69
+ end
70
+
71
+ def unknown_framework(framework)
72
+ "You specified the Javascript framework #{framework} and it is unknown to the system"
73
+ end
74
+
75
+ def invalid_framework
76
+ "The Javascript framework you provided does not implement the necessary methods"
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,183 @@
1
+ module PageObject
2
+ module LocatorGenerator
3
+
4
+ BASIC_ELEMENTS = %i(
5
+ abbr
6
+ address
7
+ animate
8
+ animate_motion
9
+ animate_transform
10
+ article
11
+ as
12
+ aside
13
+ base
14
+ bdi
15
+ bdo
16
+ blockquote
17
+ body
18
+ br
19
+ caption
20
+ circle
21
+ cite
22
+ code
23
+ col
24
+ colgroup
25
+ command
26
+ cursor
27
+ data
28
+ datalist
29
+ dd
30
+ defs
31
+ del
32
+ desc
33
+ details
34
+ dfn
35
+ dialog
36
+ discard
37
+ dl
38
+ dt
39
+ ellipse
40
+ em
41
+ embed
42
+ fieldset
43
+ figcaption
44
+ figure
45
+ font
46
+ footer
47
+ foreign_object
48
+ g
49
+ head
50
+ header
51
+ hgroup
52
+ hr
53
+ html
54
+ ins
55
+ kbd
56
+ keygen
57
+ legend
58
+ line
59
+ linear_gradient
60
+ main
61
+ map
62
+ mark
63
+ marker
64
+ menu
65
+ menuitem
66
+ mesh_gradient
67
+ mesh_patch
68
+ mesh_row
69
+ meta
70
+ metadata
71
+ meter
72
+ mpath
73
+ nav
74
+ noscript
75
+ object
76
+ optgroup
77
+ output
78
+ p
79
+ param
80
+ path
81
+ pattern
82
+ polygon
83
+ polyline
84
+ pre
85
+ progress
86
+ q
87
+ radial_gradient
88
+ rect
89
+ rp
90
+ rt
91
+ ruby
92
+ s
93
+ samp
94
+ script
95
+ section
96
+ set
97
+ small
98
+ source
99
+ stop
100
+ strong
101
+ style
102
+ sub
103
+ summary
104
+ sup
105
+ switch
106
+ symbol
107
+ template
108
+ text_path
109
+ thread
110
+ time
111
+ title
112
+ track
113
+ tspan
114
+ u
115
+ use
116
+ var
117
+ view
118
+ wbr
119
+ )
120
+
121
+
122
+ ADVANCED_ELEMENTS = %i(
123
+ text_field
124
+ date_field
125
+ hidden_field
126
+ text_area
127
+ select_list
128
+ link
129
+ checkbox
130
+ radio_button
131
+ button
132
+ div
133
+ span
134
+ table
135
+ cell
136
+ row
137
+ image
138
+ form
139
+ list_item
140
+ ordered_list
141
+ unordered_list
142
+ h1
143
+ h2
144
+ h3
145
+ h4
146
+ h5
147
+ h6
148
+ paragraph
149
+ label
150
+ file_field
151
+ area
152
+ canvas
153
+ audio
154
+ video
155
+ b
156
+ i
157
+ svg
158
+ )
159
+
160
+ def self.generate_locators(target)
161
+ ADVANCED_ELEMENTS.each do |tag|
162
+ target.send(:define_method, "#{tag.to_s}_element") do |*identifier|
163
+ @platform.send "#{tag.to_s}_for", locator(identifier)
164
+ end
165
+
166
+ target.send(:define_method, "#{tag.to_s}_elements") do |*identifier|
167
+ @platform.send("#{tag.to_s}s_for", identifier[0] ? identifier[0] : {})
168
+ end
169
+ end
170
+
171
+ BASIC_ELEMENTS.each do |tag|
172
+ target.send(:define_method, "#{tag.to_s}_element") do |*identifier|
173
+ @platform.send :element_for, tag, locator(identifier)
174
+ end
175
+
176
+ target.send(:define_method, "#{tag.to_s}_elements") do |*identifier|
177
+ @platform.send(:elements_for, tag, identifier[0] ? identifier[0] : {})
178
+ end
179
+ end
180
+ end
181
+
182
+ end
183
+ end
@@ -0,0 +1,17 @@
1
+ require 'page-object/locator_generator'
2
+
3
+ module PageObject
4
+ module NestedElements
5
+
6
+ def self.included(cls)
7
+ ::PageObject::LocatorGenerator.generate_locators(cls)
8
+ end
9
+
10
+ private
11
+
12
+ def locator(identifier)
13
+ identifier[0] ? identifier[0] : {:index => 0}
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,108 @@
1
+ require 'page_navigation'
2
+
3
+ module PageObject
4
+ #
5
+ # Module to facilitate to creating of page objects in step definitions. You
6
+ # can make the methods below available to all of your step definitions by adding
7
+ # this module to World. This idea was first discussed in Alister Scott's blog
8
+ # entry http://watirmelon.com/2011/06/07/removing-local-page-references-from-cucumber-steps/.
9
+ #
10
+ # @example Making the PageFactory available to your step definitions
11
+ # World PageObject::PageFactory
12
+ #
13
+ # @example Visiting a page for the first time in a Scenario
14
+ # visit_page MyPageObject do |page|
15
+ # page.name = 'Cheezy'
16
+ # end
17
+ #
18
+ # @example using a page that has already been visited in a Scenario
19
+ # on_page MyPageObject do |page|
20
+ # page.name.should == 'Cheezy'
21
+ # end
22
+ #
23
+ # If you plan to use the navigate_to method you will need to ensure
24
+ # you setup the possible routes ahead of time. You must always have
25
+ # a default route in order for this to work. Here is an example of
26
+ # how you define routes:
27
+ #
28
+ # @example Example routes defined in env.rb
29
+ # PageObject::PageFactory.routes = {
30
+ # :default => [[PageOne,:method1], [PageTwoA,:method2], [PageThree,:method3]],
31
+ # :another_route => [[PageOne,:method1, "arg1"], [PageTwoB,:method2b], [PageThree,:method3]]
32
+ # }
33
+ #
34
+ # Notice the first entry of :another_route is passing an argument
35
+ # to the method.
36
+ #
37
+ module PageFactory
38
+ include PageNavigation
39
+
40
+
41
+ #
42
+ # Create and navigate to a page object. The navigation will only work if the
43
+ # 'page_url' method was call on the page object.
44
+ #
45
+ # @param [PageObject, String] a class that has included the
46
+ # PageObject module or a string containing the name of the class
47
+ # @param Hash values that is pass through to page class a
48
+ # available in the @params instance variable.
49
+ # @param an optional block to be called
50
+ # @return [PageObject] the newly created page object
51
+ #
52
+ def visit_page(page_class, params={:using_params => {}}, &block)
53
+ on_page page_class, params, true, &block
54
+ end
55
+
56
+ # Support 'visit' for readability of usage
57
+ alias_method :visit, :visit_page
58
+
59
+ #
60
+ # Create a page object.
61
+ #
62
+ # @param [PageObject, String] a class that has included the PageObject module or a string containing the name of the class
63
+ # @param Hash values that is pass through to page class a
64
+ # available in the @params instance variable.
65
+ # @param [Boolean] a boolean indicating if the page should be visited? default is false.
66
+ # @param [block] an optional block to be called
67
+ # @return [PageObject] the newly created page object
68
+ #
69
+ def on_page(page_class, params={:using_params => {}}, visit=false, &block)
70
+ page_class = class_from_string(page_class) if page_class.is_a? String
71
+ return super(page_class, params, visit, &block) unless page_class.ancestors.include? PageObject
72
+ merged = page_class.params.merge(params[:using_params])
73
+ page_class.instance_variable_set("@merged_params", merged) unless merged.empty?
74
+ @current_page = page_class.new(@browser, visit)
75
+ block.call @current_page if block
76
+ @current_page
77
+ end
78
+
79
+ # Support 'on' for readability of usage
80
+ alias_method :on, :on_page
81
+
82
+ #
83
+ # Create a page object if and only if the current page is the same page to be created
84
+ #
85
+ # @param [PageObject, String] a class that has included the PageObject module or a string containing the name of the class
86
+ # @param Hash values that is pass through to page class a
87
+ # available in the @params instance variable.
88
+ # @param [block] an optional block to be called
89
+ # @return [PageObject] the newly created page object
90
+ #
91
+ def if_page(page_class, params={:using_params => {}},&block)
92
+ page_class = class_from_string(page_class) if page_class.is_a? String
93
+ return @current_page unless @current_page.class == page_class
94
+ on_page(page_class, params, false, &block)
95
+ end
96
+
97
+ # Support 'if' for readability of usage
98
+ alias_method :if, :if_page
99
+
100
+ private
101
+
102
+ def class_from_string(str)
103
+ str.split('::').inject(Object) do |mod, class_name|
104
+ mod.const_get(class_name)
105
+ end
106
+ end
107
+ end
108
+ end