page-object 1.0.3 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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