page-object 1.0.3 → 1.1.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/ChangeLog +10 -0
- data/features/button.feature +13 -3
- data/features/html/indexed_property.html +3 -0
- data/features/html/static_elements.html +2 -0
- data/features/indexed_property.feature +20 -1
- data/features/section.feature +132 -0
- data/features/step_definitions/accessor_steps.rb +4 -0
- data/features/step_definitions/button_steps.rb +5 -0
- data/features/step_definitions/indexed_property_steps.rb +36 -2
- data/features/step_definitions/section_steps.rb +268 -0
- data/lib/page-object.rb +19 -7
- data/lib/page-object/accessors.rb +48 -0
- data/lib/page-object/elements/element.rb +4 -4
- data/lib/page-object/indexed_properties.rb +7 -3
- data/lib/page-object/loads_platform.rb +24 -5
- data/lib/page-object/platforms/selenium_webdriver.rb +14 -2
- data/lib/page-object/platforms/selenium_webdriver/button.rb +3 -3
- data/lib/page-object/platforms/selenium_webdriver/element.rb +1 -1
- data/lib/page-object/platforms/selenium_webdriver/page_object.rb +50 -0
- data/lib/page-object/platforms/watir_webdriver.rb +15 -3
- data/lib/page-object/platforms/watir_webdriver/element.rb +1 -1
- data/lib/page-object/platforms/watir_webdriver/page_object.rb +30 -0
- data/lib/page-object/sections.rb +29 -0
- data/lib/page-object/version.rb +1 -1
- data/page-object.gemspec +3 -3
- data/spec/page-object/elements/button_spec.rb +14 -0
- data/spec/page-object/elements/selenium_element_spec.rb +5 -0
- data/spec/page-object/elements/watir_element_spec.rb +4 -0
- data/spec/page-object/loads_platform_spec.rb +3 -3
- data/spec/page-object/page-object_spec.rb +1 -0
- data/spec/page-object/page_section_spec.rb +73 -0
- data/spec/spec_helper.rb +3 -1
- metadata +15 -6
data/lib/page-object.rb
CHANGED
@@ -7,8 +7,15 @@ 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/sections'
|
10
11
|
require 'page-object/widgets'
|
11
12
|
|
13
|
+
require 'watir-webdriver'
|
14
|
+
require 'page-object/platforms/watir_webdriver/element'
|
15
|
+
require 'page-object/platforms/watir_webdriver/page_object'
|
16
|
+
require 'page-object/platforms/selenium_webdriver/element'
|
17
|
+
require 'page-object/platforms/selenium_webdriver/page_object'
|
18
|
+
|
12
19
|
require 'selenium/webdriver/common/error'
|
13
20
|
#
|
14
21
|
# Module that when included adds functionality to a page object. This module
|
@@ -53,19 +60,20 @@ module PageObject
|
|
53
60
|
# a method named initialize_accessors if it exists. Upon initialization of
|
54
61
|
# the page it will call a method named initialize_page if it exists.
|
55
62
|
#
|
56
|
-
# @param [Watir::Browser or Selenium::WebDriver::Driver] the platform browser to use
|
63
|
+
# @param [Watir::Browser, Watir::HTMLElement or Selenium::WebDriver::Driver, Selenium::WebDriver::Element] the platform browser/element to use
|
57
64
|
# @param [bool] open the page if page_url is set
|
58
65
|
#
|
59
|
-
def initialize(
|
66
|
+
def initialize(root, visit=false)
|
60
67
|
initialize_accessors if respond_to?(:initialize_accessors)
|
61
|
-
initialize_browser(
|
68
|
+
initialize_browser(root)
|
62
69
|
goto if visit && respond_to?(:goto)
|
63
70
|
initialize_page if respond_to?(:initialize_page)
|
64
71
|
end
|
65
72
|
|
66
|
-
def initialize_browser(
|
67
|
-
@
|
68
|
-
|
73
|
+
def initialize_browser(root)
|
74
|
+
@root_element = root_element_for root, PageObject::Platforms.get
|
75
|
+
@browser = browser_for root, PageObject::Platforms.get
|
76
|
+
include_platform_driver(root)
|
69
77
|
end
|
70
78
|
|
71
79
|
# @private
|
@@ -144,7 +152,7 @@ module PageObject
|
|
144
152
|
# Returns the text of the current page
|
145
153
|
#
|
146
154
|
def text
|
147
|
-
|
155
|
+
root.text
|
148
156
|
end
|
149
157
|
|
150
158
|
#
|
@@ -399,6 +407,10 @@ module PageObject
|
|
399
407
|
|
400
408
|
private
|
401
409
|
|
410
|
+
def root
|
411
|
+
@root_element || browser_root_for(browser, PageObject::Platforms.get)
|
412
|
+
end
|
413
|
+
|
402
414
|
def include_platform_driver(browser)
|
403
415
|
@platform = load_platform(browser, PageObject::Platforms.get)
|
404
416
|
end
|
@@ -1229,6 +1229,54 @@ module PageObject
|
|
1229
1229
|
end
|
1230
1230
|
end
|
1231
1231
|
|
1232
|
+
#
|
1233
|
+
# adds a method to return a page object rooted at an element
|
1234
|
+
#
|
1235
|
+
# @example
|
1236
|
+
# page_section(:navigation_bar, NavigationBar, :id => 'nav-bar')
|
1237
|
+
# # will generate 'navigation_bar' and 'navigation_bar?'
|
1238
|
+
#
|
1239
|
+
# @param [Symbol] the name used for the generated methods
|
1240
|
+
# @param [Class] the class to instantiate for the element
|
1241
|
+
# @param [Hash] identifier how we find an element. You can use multiple parameters
|
1242
|
+
# by combining of any of the following except xpath. The valid keys are:
|
1243
|
+
# * :class => Watir and Selenium
|
1244
|
+
# * :css => Selenium only
|
1245
|
+
# * :id => Watir and Selenium
|
1246
|
+
# * :index => Watir and Selenium
|
1247
|
+
# * :name => Watir and Selenium
|
1248
|
+
# * :xpath => Watir and Selenium
|
1249
|
+
#
|
1250
|
+
def page_section(name, section_class, identifier)
|
1251
|
+
define_method(name) do
|
1252
|
+
platform.page_for(identifier, section_class)
|
1253
|
+
end
|
1254
|
+
end
|
1255
|
+
|
1256
|
+
#
|
1257
|
+
# adds a method to return a collection of page objects rooted at elements
|
1258
|
+
#
|
1259
|
+
# @example
|
1260
|
+
# page_sections(:articles, Article, :class => 'article')
|
1261
|
+
# # will generate 'articles'
|
1262
|
+
#
|
1263
|
+
# @param [Symbol] the name used for the generated method
|
1264
|
+
# @param [Class] the class to instantiate for each element
|
1265
|
+
# @param [Hash] identifier how we find an element. You can use a multiple parameters
|
1266
|
+
# by combining of any of the following except xpath. The valid keys are:
|
1267
|
+
# * :class => Watir and Selenium
|
1268
|
+
# * :css => Selenium only
|
1269
|
+
# * :id => Watir and Selenium
|
1270
|
+
# * :index => Watir and Selenium
|
1271
|
+
# * :name => Watir and Selenium
|
1272
|
+
# * :xpath => Watir and Selenium
|
1273
|
+
#
|
1274
|
+
def page_sections(name, section_class, identifier)
|
1275
|
+
define_method(name) do
|
1276
|
+
platform.pages_for(identifier, section_class)
|
1277
|
+
end
|
1278
|
+
end
|
1279
|
+
|
1232
1280
|
#
|
1233
1281
|
# methods to generate accessors for types that follow the same
|
1234
1282
|
# pattern as element
|
@@ -208,19 +208,19 @@ module PageObject
|
|
208
208
|
|
209
209
|
def include_platform_for platform
|
210
210
|
if platform[:platform] == :watir_webdriver
|
211
|
-
require 'page-object/platforms/watir_webdriver/element'
|
212
|
-
require 'page-object/platforms/watir_webdriver/page_object'
|
213
211
|
self.class.send :include, ::PageObject::Platforms::WatirWebDriver::Element
|
214
212
|
@platform = ::PageObject::Platforms::WatirWebDriver::PageObject.new(@element)
|
215
213
|
elsif platform[:platform] == :selenium_webdriver
|
216
|
-
require 'page-object/platforms/selenium_webdriver/element'
|
217
|
-
require 'page-object/platforms/selenium_webdriver/page_object'
|
218
214
|
self.class.send :include, ::PageObject::Platforms::SeleniumWebDriver::Element
|
219
215
|
@platform = ::PageObject::Platforms::SeleniumWebDriver::PageObject.new(@element)
|
220
216
|
else
|
221
217
|
raise ArgumentError, "expect platform to be :watir_webdriver or :selenium_webdriver"
|
222
218
|
end
|
223
219
|
end
|
220
|
+
|
221
|
+
def to_ary
|
222
|
+
nil
|
223
|
+
end
|
224
224
|
end
|
225
225
|
end
|
226
226
|
end
|
@@ -20,16 +20,20 @@ module PageObject
|
|
20
20
|
name = identifier[1]
|
21
21
|
how_and_what = identifier[2].clone # Cannot modify the original...
|
22
22
|
how_and_what.each do |key, value|
|
23
|
-
|
23
|
+
if key == :index
|
24
|
+
how_and_what[key] = (value % index).to_i
|
25
|
+
else
|
26
|
+
how_and_what[key] = value % index
|
27
|
+
end
|
24
28
|
end
|
25
|
-
self.class.send type, name, how_and_what unless
|
29
|
+
self.class.send type, name, how_and_what unless Class.instance_methods.include? name
|
26
30
|
end
|
27
31
|
end
|
28
32
|
}
|
29
33
|
end
|
30
34
|
|
31
35
|
def [] (index)
|
32
|
-
@indexed_property_class.new(@browser,index
|
36
|
+
@indexed_property_class.new(@browser, index, @identifier_list)
|
33
37
|
end
|
34
38
|
end
|
35
39
|
end
|
@@ -15,12 +15,31 @@ module PageObject
|
|
15
15
|
# @returns [PageObject]
|
16
16
|
#
|
17
17
|
def load_platform(browser, adapters)
|
18
|
-
adapters.
|
19
|
-
|
18
|
+
adapter_for(browser,adapters).create_page_object(browser)
|
19
|
+
end
|
20
|
+
|
21
|
+
def browser_for root,adapters
|
22
|
+
adapter_for(root,adapters).browser_for(root)
|
23
|
+
end
|
24
|
+
|
25
|
+
def adapter_for element_or_browser, adapters
|
26
|
+
adapter = adapters.values.find { |adapter|
|
27
|
+
adapter.is_for?(element_or_browser)
|
20
28
|
}
|
21
|
-
|
22
|
-
|
23
|
-
|
29
|
+
unless adapter
|
30
|
+
message = "Unable to pick a platform for the provided browser or element: #{element_or_browser.inspect}."
|
31
|
+
message += "\nnil was passed to the PageObject constructor instead of a valid browser or element object." if element_or_browser.nil?
|
32
|
+
raise message
|
33
|
+
end
|
34
|
+
adapter
|
35
|
+
end
|
36
|
+
|
37
|
+
def root_element_for root, adapters
|
38
|
+
adapter_for(root,adapters).root_element_for(root)
|
39
|
+
end
|
40
|
+
|
41
|
+
def browser_root_for browser, adapters
|
42
|
+
adapter_for(browser,adapters).browser_root_for(browser)
|
24
43
|
end
|
25
44
|
end
|
26
45
|
end
|
@@ -3,13 +3,25 @@ module PageObject
|
|
3
3
|
module SeleniumWebDriver
|
4
4
|
|
5
5
|
def self.create_page_object(browser)
|
6
|
-
require 'page-object/platforms/selenium_webdriver/page_object'
|
7
6
|
SeleniumWebDriver::PageObject.new(browser)
|
8
7
|
end
|
9
8
|
|
10
9
|
def self.is_for?(browser)
|
11
10
|
require 'selenium-webdriver'
|
12
|
-
browser.is_a? ::Selenium::WebDriver::
|
11
|
+
browser.is_a?(::Selenium::WebDriver::Driver) || browser.is_a?(::Selenium::WebDriver::Element)
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.browser_for root
|
15
|
+
return root if root.is_a?(::Selenium::WebDriver::Driver)
|
16
|
+
Selenium::WebDriver::Driver.new(root.send(:bridge))
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.root_element_for root
|
20
|
+
Elements::Element.new root, platform: :selenium_webdriver if root.is_a?(::Selenium::WebDriver::Element)
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.browser_root_for browser
|
24
|
+
browser.find_element(tag_name: 'html')
|
13
25
|
end
|
14
26
|
end
|
15
27
|
end
|
@@ -3,11 +3,11 @@ module PageObject
|
|
3
3
|
module SeleniumWebDriver
|
4
4
|
module Button
|
5
5
|
#
|
6
|
-
# Override PageObject::PLatforms::SeleniumElement#text
|
7
|
-
# #text
|
6
|
+
# Override PageObject::PLatforms::SeleniumElement#text
|
7
|
+
# to get #text from buttons and #attribute('value') from inputs
|
8
8
|
#
|
9
9
|
def text
|
10
|
-
|
10
|
+
element.tag_name == 'button' ? element.text : element.attribute('value')
|
11
11
|
end
|
12
12
|
end
|
13
13
|
end
|
@@ -988,6 +988,22 @@ module PageObject
|
|
988
988
|
find_selenium_elements(identifier, Elements::Element, tag.to_s)
|
989
989
|
end
|
990
990
|
|
991
|
+
#
|
992
|
+
# platform method to return a PageObject rooted at an element
|
993
|
+
# See PageObject::Accessors#page_section
|
994
|
+
#
|
995
|
+
def page_for(identifier, page_class)
|
996
|
+
find_selenium_page(identifier, page_class)
|
997
|
+
end
|
998
|
+
|
999
|
+
#
|
1000
|
+
# platform method to return a collection of PageObjects rooted at elements
|
1001
|
+
# See PageObject::Accessors#page_sections
|
1002
|
+
#
|
1003
|
+
def pages_for(identifier, page_class)
|
1004
|
+
SectionCollection.new(find_selenium_pages(identifier, page_class))
|
1005
|
+
end
|
1006
|
+
|
991
1007
|
#
|
992
1008
|
# platform method to return a svg element
|
993
1009
|
#
|
@@ -1071,6 +1087,40 @@ module PageObject
|
|
1071
1087
|
elements.map { |element| type.new(element, :platform => :selenium_webdriver) }
|
1072
1088
|
end
|
1073
1089
|
|
1090
|
+
def find_selenium_pages(identifier, page_class)
|
1091
|
+
regexp = delete_regexp(identifier)
|
1092
|
+
how, what, frame_identifiers = parse_identifiers(identifier, Elements::Element, 'element')
|
1093
|
+
switch_to_frame(frame_identifiers)
|
1094
|
+
unless regexp
|
1095
|
+
elements = @browser.find_elements(how, what)
|
1096
|
+
else
|
1097
|
+
eles = @browser.find_elements(how, what)
|
1098
|
+
elements = eles.find_all {|ele| matches_selector?(ele, regexp[0], regexp[1])}
|
1099
|
+
end
|
1100
|
+
@browser.switch_to.default_content unless frame_identifiers.nil?
|
1101
|
+
elements.map { |element| page_class.new(element) }
|
1102
|
+
end
|
1103
|
+
|
1104
|
+
def find_selenium_page(identifier, page_class)
|
1105
|
+
type, tag = Elements::Element, 'element'
|
1106
|
+
regexp = delete_regexp(identifier)
|
1107
|
+
how, what, frame_identifiers = parse_identifiers(identifier, type, tag)
|
1108
|
+
switch_to_frame(frame_identifiers)
|
1109
|
+
begin
|
1110
|
+
unless regexp
|
1111
|
+
element = @browser.find_element(how, what)
|
1112
|
+
else
|
1113
|
+
elements = @browser.find_elements(how, what)
|
1114
|
+
element = elements.find {|ele| matches_selector?(ele, regexp[0], regexp[1])}
|
1115
|
+
end
|
1116
|
+
rescue Selenium::WebDriver::Error::NoSuchElementError
|
1117
|
+
@browser.switch_to.default_content unless frame_identifiers.nil?
|
1118
|
+
return build_null_object(identifier, type, tag, nil)
|
1119
|
+
end
|
1120
|
+
@browser.switch_to.default_content unless frame_identifiers.nil?
|
1121
|
+
page_class.new(element)
|
1122
|
+
end
|
1123
|
+
|
1074
1124
|
def build_null_object(identifier, type, tag, other)
|
1075
1125
|
null_element = SurrogateSeleniumElement.new
|
1076
1126
|
null_element.identifier = identifier
|
@@ -1,15 +1,27 @@
|
|
1
1
|
module PageObject
|
2
2
|
module Platforms
|
3
3
|
module WatirWebDriver
|
4
|
-
|
4
|
+
|
5
5
|
def self.create_page_object(browser)
|
6
|
-
require 'page-object/platforms/watir_webdriver/page_object'
|
7
6
|
return WatirWebDriver::PageObject.new(browser)
|
8
7
|
end
|
9
8
|
|
10
9
|
def self.is_for?(browser)
|
11
10
|
require 'watir-webdriver'
|
12
|
-
browser.is_a?(::Watir::Browser)
|
11
|
+
browser.is_a?(::Watir::Browser) || browser.is_a?(::Watir::HTMLElement)
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.browser_for root
|
15
|
+
return root if root.is_a?(::Watir::Browser)
|
16
|
+
root.browser
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.root_element_for root
|
20
|
+
Elements::Element.new root, :platform => :watir_webdriver if root.is_a? ::Watir::HTMLElement
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.browser_root_for browser
|
24
|
+
browser.element
|
13
25
|
end
|
14
26
|
end
|
15
27
|
end
|
@@ -917,6 +917,22 @@ module PageObject
|
|
917
917
|
find_watir_elements("#{tag.to_s}s(identifier)", Elements::Element, identifier, tag.to_s)
|
918
918
|
end
|
919
919
|
|
920
|
+
#
|
921
|
+
# platform method to return a PageObject rooted at an element
|
922
|
+
# See PageObject::Accessors#page_section
|
923
|
+
#
|
924
|
+
def page_for(identifier, page_class)
|
925
|
+
find_watir_page(identifier, page_class)
|
926
|
+
end
|
927
|
+
|
928
|
+
#
|
929
|
+
# platform method to return a collection of PageObjects rooted at elements
|
930
|
+
# See PageObject::Accessors#page_sections
|
931
|
+
#
|
932
|
+
def pages_for(identifier, page_class)
|
933
|
+
SectionCollection.new(find_watir_pages(identifier, page_class))
|
934
|
+
end
|
935
|
+
|
920
936
|
#
|
921
937
|
# platform method to return a svg element
|
922
938
|
#
|
@@ -970,6 +986,20 @@ module PageObject
|
|
970
986
|
type.new(element, :platform => :watir_webdriver)
|
971
987
|
end
|
972
988
|
|
989
|
+
def find_watir_pages(identifier, page_class)
|
990
|
+
identifier, frame_identifiers = parse_identifiers(identifier, Elements::Element, 'element')
|
991
|
+
elements = @browser.instance_eval "#{nested_frames(frame_identifiers)}elements(identifier)"
|
992
|
+
switch_to_default_content(frame_identifiers)
|
993
|
+
elements.map { |element| page_class.new(element) }
|
994
|
+
end
|
995
|
+
|
996
|
+
def find_watir_page(identifier, page_class)
|
997
|
+
identifier, frame_identifiers = parse_identifiers(identifier, Elements::Element, 'element')
|
998
|
+
element = @browser.instance_eval "#{nested_frames(frame_identifiers)}element(identifier)"
|
999
|
+
switch_to_default_content(frame_identifiers)
|
1000
|
+
page_class.new(element)
|
1001
|
+
end
|
1002
|
+
|
973
1003
|
def process_watir_call(the_call, type, identifier, value=nil, tag_name=nil)
|
974
1004
|
identifier, frame_identifiers = parse_identifiers(identifier, type, tag_name)
|
975
1005
|
value = @browser.instance_eval "#{nested_frames(frame_identifiers)}#{the_call}"
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module PageObject
|
2
|
+
class SectionCollection
|
3
|
+
include Enumerable
|
4
|
+
|
5
|
+
def initialize sections
|
6
|
+
@sections = sections
|
7
|
+
end
|
8
|
+
|
9
|
+
def each &block
|
10
|
+
@sections.each &block
|
11
|
+
end
|
12
|
+
|
13
|
+
def [] index
|
14
|
+
@sections[index]
|
15
|
+
end
|
16
|
+
|
17
|
+
def find_by values_hash
|
18
|
+
@sections.find {|section|
|
19
|
+
values_hash.all? {|method,value| value === section.public_send(method)}
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
def select_by values_hash
|
24
|
+
SectionCollection.new @sections.select {|section|
|
25
|
+
values_hash.all? {|method,value| value === section.public_send(method)}
|
26
|
+
}
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/page-object/version.rb
CHANGED