testcentricity_web 3.2.0 → 3.2.1
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 +5 -5
- data/CHANGELOG.md +8 -0
- data/Gemfile.lock +4 -4
- data/README.md +8 -4
- data/lib/testcentricity_web.rb +2 -1
- data/lib/testcentricity_web/data_objects/environment.rb +8 -8
- data/lib/testcentricity_web/version.rb +1 -1
- data/lib/testcentricity_web/web_core/page_object.rb +537 -0
- data/lib/testcentricity_web/web_core/page_objects_helper.rb +269 -801
- data/lib/testcentricity_web/web_core/{page_sections_helper.rb → page_section.rb} +1 -261
- data/lib/testcentricity_web/web_elements/cell_element.rb +6 -6
- data/lib/testcentricity_web/web_elements/checkbox.rb +33 -0
- data/lib/testcentricity_web/web_elements/list_element.rb +6 -6
- data/lib/testcentricity_web/web_elements/radio.rb +33 -0
- data/lib/testcentricity_web/web_elements/ui_elements_helper.rb +4 -4
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c875303a27c1eaa23f786550d0b3c32738e84e9d
|
4
|
+
data.tar.gz: 1ddf7a0bc2f69efbd98c4331e09770bf74fe88b3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 557a3f34be2aff3383ac17ed402b72eb039e8d4b9ad8945c16be513db1179813b4c2f980d9b74e100f75228c8314412766c22ea9384e22744c8c03f3832c8b12
|
7
|
+
data.tar.gz: cb41453fd495fcd1b50ccf9a4da1d8a4b67afad02c2029f8952fa5e9eb6cda657603ffbcbe421f18b79f84a716d24bbd4f9edd1e85e8a209a13dd2566d7547ba
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,14 @@
|
|
2
2
|
All notable changes to this project will be documented in this file.
|
3
3
|
|
4
4
|
|
5
|
+
## [3.2.1] - 2019-10-03
|
6
|
+
|
7
|
+
### Changed
|
8
|
+
* `CheckBox.visible?`, `CheckBox.disabled?`, and `CheckBox.get_value` methods now work with React and Ember checkboxes with
|
9
|
+
proxy elements.
|
10
|
+
* `Radio.visible?`, `Radio.disabled?`, and `Radio.get_value` methods now work with React and Ember radio buttons with
|
11
|
+
proxy elements.
|
12
|
+
|
5
13
|
## [3.2.0] - 2019-07-28
|
6
14
|
|
7
15
|
### Added
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
testcentricity_web (3.2.
|
4
|
+
testcentricity_web (3.2.1)
|
5
5
|
appium_lib
|
6
6
|
browserstack-local
|
7
7
|
capybara (>= 3.1, < 4)
|
@@ -25,7 +25,7 @@ GEM
|
|
25
25
|
appium_lib_core (~> 3.2)
|
26
26
|
nokogiri (~> 1.8, >= 1.8.1)
|
27
27
|
tomlrb (~> 1.1)
|
28
|
-
appium_lib_core (3.2.
|
28
|
+
appium_lib_core (3.2.2)
|
29
29
|
faye-websocket (~> 0.10.0)
|
30
30
|
selenium-webdriver (~> 3.14, >= 3.14.1)
|
31
31
|
axiom-types (0.1.1)
|
@@ -33,7 +33,7 @@ GEM
|
|
33
33
|
ice_nine (~> 0.11.0)
|
34
34
|
thread_safe (~> 0.3, >= 0.3.1)
|
35
35
|
browserstack-local (1.3.0)
|
36
|
-
capybara (3.
|
36
|
+
capybara (3.28.0)
|
37
37
|
addressable
|
38
38
|
mini_mime (>= 0.1.3)
|
39
39
|
nokogiri (~> 1.8)
|
@@ -51,7 +51,7 @@ GEM
|
|
51
51
|
thread_safe (~> 0.3, >= 0.3.1)
|
52
52
|
equalizer (0.0.11)
|
53
53
|
eventmachine (1.2.7)
|
54
|
-
faker (2.0)
|
54
|
+
faker (2.1.0)
|
55
55
|
i18n (>= 0.7)
|
56
56
|
faye-websocket (0.10.9)
|
57
57
|
eventmachine (>= 0.12.0)
|
data/README.md
CHANGED
@@ -15,9 +15,13 @@ The TestCentricity™ Web gem supports running automated tests against the follo
|
|
15
15
|
* desktop and emulated mobile web browsers hosted on Selenium Grid and Dockerized Selenium Grid environments
|
16
16
|
* mobile Safari browsers on iOS device simulators or physical iOS devices (using Appium and XCode on OS X)
|
17
17
|
* mobile Chrome or Android browsers on Android Studio virtual device emulators (using Appium and Android Studio on OS X)
|
18
|
-
* cloud hosted desktop (Firefox, Chrome, Safari, IE, or Edge) or mobile (iOS Mobile Safari or Android) web browsers using the
|
19
|
-
[
|
20
|
-
|
18
|
+
* cloud hosted desktop (Firefox, Chrome, Safari, IE, or Edge) or mobile (iOS Mobile Safari or Android) web browsers using the following service:
|
19
|
+
* [Browserstack](https://www.browserstack.com/list-of-browsers-and-platforms?product=automate)
|
20
|
+
* [Sauce Labs](https://saucelabs.com/open-source#automated-testing-platform)
|
21
|
+
* [CrossBrowserTesting](https://crossbrowsertesting.com/selenium-testing)
|
22
|
+
* [TestingBot](https://testingbot.com/features)
|
23
|
+
* [Gridlastic](https://www.gridlastic.com/test-environments.html)
|
24
|
+
* [LambdaTest](https://www.lambdatest.com/selenium-automation)
|
21
25
|
* web portals utilizing JavaScript front end application frameworks like Ember, React, Angular, and GWT
|
22
26
|
* enterprise web portals built using Siebel Open UI
|
23
27
|
* web pages containing HTML5 Video and Audio objects
|
@@ -855,7 +859,7 @@ Once your test environment is properly configured, the following **Environment V
|
|
855
859
|
`WEB_BROWSER` | Must be set to `appium`
|
856
860
|
`APP_PLATFORM_NAME` | Must be set to `iOS`
|
857
861
|
`APP_BROWSER` | Must be set to `Safari`
|
858
|
-
`APP_VERSION` | Must be set to `
|
862
|
+
`APP_VERSION` | Must be set to `12.2`, `11.4`, `10.3.1`, or which ever iOS version you wish to run within the XCode Simulator
|
859
863
|
`APP_DEVICE` | Set to iOS device name supported by the iOS Simulator (`iPhone 6s Plus`, `iPad Pro (10.5-inch)`, `iPad Air 2`, etc.) or name of physically connected iOS device
|
860
864
|
`DEVICE_TYPE` | Must be set to `phone` or `tablet`
|
861
865
|
`APP_UDID` | UDID of physically connected iOS device (not used for simulators)
|
data/lib/testcentricity_web.rb
CHANGED
@@ -11,7 +11,8 @@ require 'testcentricity_web/appium_server'
|
|
11
11
|
|
12
12
|
require 'testcentricity_web/web_core/drag_drop_helper'
|
13
13
|
require 'testcentricity_web/web_core/page_objects_helper'
|
14
|
-
require 'testcentricity_web/web_core/
|
14
|
+
require 'testcentricity_web/web_core/page_object'
|
15
|
+
require 'testcentricity_web/web_core/page_section'
|
15
16
|
require 'testcentricity_web/web_core/webdriver_helper'
|
16
17
|
|
17
18
|
require 'testcentricity_web/data_objects/data_objects_helper'
|
@@ -5,14 +5,14 @@ module TestCentricity
|
|
5
5
|
WKS_ENVIRONS ||= 'Environments'
|
6
6
|
|
7
7
|
def find_environ(environ_name, source_type = :excel)
|
8
|
-
case source_type
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
8
|
+
data = case source_type
|
9
|
+
when :excel
|
10
|
+
ExcelData.read_row_data(XL_PRIMARY_DATA_FILE, WKS_ENVIRONS, environ_name)
|
11
|
+
when :yaml
|
12
|
+
read_yaml_node_data('environments.yml', environ_name)
|
13
|
+
when :json
|
14
|
+
read_json_node_data('environments.json', environ_name)
|
15
|
+
end
|
16
16
|
@current = Environ.new(data)
|
17
17
|
Environ.current = @current
|
18
18
|
end
|
@@ -0,0 +1,537 @@
|
|
1
|
+
module TestCentricity
|
2
|
+
class PageObject < BasePageSectionObject
|
3
|
+
# Declare and instantiate a single generic UI Element for this page object.
|
4
|
+
#
|
5
|
+
# @param element_name [Symbol] name of UI object (as a symbol)
|
6
|
+
# @param locator [String] CSS selector or XPath expression that uniquely identifies object
|
7
|
+
# @example
|
8
|
+
# element :siebel_view, 'div#_sweview'
|
9
|
+
# element :siebel_busy, "//html[contains(@class, 'siebui-busy')]"
|
10
|
+
#
|
11
|
+
def self.element(element_name, locator)
|
12
|
+
define_page_element(element_name, TestCentricity::UIElement, locator)
|
13
|
+
end
|
14
|
+
|
15
|
+
# Declare and instantiate a collection of generic UI Elements for this page object.
|
16
|
+
#
|
17
|
+
# @param element_hash [Hash] names of UI objects (as a symbol) and CSS selectors or XPath expressions that uniquely identifies objects
|
18
|
+
# @example
|
19
|
+
# elements profile_item: 'a#profile',
|
20
|
+
# settings_item: 'a#userPreferencesTrigger',
|
21
|
+
# log_out_item: 'a#logout'
|
22
|
+
#
|
23
|
+
def self.elements(element_hash)
|
24
|
+
element_hash.each(&method(:element))
|
25
|
+
end
|
26
|
+
|
27
|
+
# Declare and instantiate a single button UI Element for this page object.
|
28
|
+
#
|
29
|
+
# @param element_name [Symbol] name of button object (as a symbol)
|
30
|
+
# @param locator [String] CSS selector or XPath expression that uniquely identifies object
|
31
|
+
# @example
|
32
|
+
# button :checkout_button, 'button.checkout_button'
|
33
|
+
# button :login_button, "//input[@id='submit_button']"
|
34
|
+
#
|
35
|
+
def self.button(element_name, locator)
|
36
|
+
define_page_element(element_name, TestCentricity::Button, locator)
|
37
|
+
end
|
38
|
+
|
39
|
+
# Declare and instantiate a collection of buttons for this page object.
|
40
|
+
#
|
41
|
+
# @param element_hash [Hash] names of buttons (as a symbol) and CSS selectors or XPath expressions that uniquely identifies buttons
|
42
|
+
# @example
|
43
|
+
# buttons new_account_button: 'button#new-account',
|
44
|
+
# save_button: 'button#save',
|
45
|
+
# cancel_button: 'button#cancel'
|
46
|
+
#
|
47
|
+
def self.buttons(element_hash)
|
48
|
+
element_hash.each(&method(:button))
|
49
|
+
end
|
50
|
+
|
51
|
+
# Declare and instantiate a single text field UI Element for this page object.
|
52
|
+
#
|
53
|
+
# @param element_name [Symbol] name of text field object (as a symbol)
|
54
|
+
# @param locator [String] CSS selector or XPath expression that uniquely identifies object
|
55
|
+
# @example
|
56
|
+
# textfield :user_id_field, "//input[@id='UserName']"
|
57
|
+
# textfield :password_field, 'consumer_password'
|
58
|
+
#
|
59
|
+
def self.textfield(element_name, locator)
|
60
|
+
define_page_element(element_name, TestCentricity::TextField, locator)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Declare and instantiate a collection of text fields for this page object.
|
64
|
+
#
|
65
|
+
# @param element_hash [Hash] names of text fields (as a symbol) and CSS selectors or XPath expressions that uniquely identifies text fields
|
66
|
+
# @example
|
67
|
+
# textfields name_field: 'input#Name',
|
68
|
+
# title_field: 'input#Title',
|
69
|
+
# phone_field: 'input#PhoneNumber',
|
70
|
+
# fax_field: 'input#FaxNumber',
|
71
|
+
# email_field: 'input#Email'
|
72
|
+
#
|
73
|
+
def self.textfields(element_hash)
|
74
|
+
element_hash.each(&method(:textfield))
|
75
|
+
end
|
76
|
+
|
77
|
+
# Declare and instantiate a single checkbox UI Element for this page object.
|
78
|
+
#
|
79
|
+
# @param element_name [Symbol] name of checkbox object (as a symbol)
|
80
|
+
# @param locator [String] CSS selector or XPath expression that uniquely identifies object
|
81
|
+
# @param proxy [Symbol] Optional name (as a symbol) of proxy object to receive click actions
|
82
|
+
# @example
|
83
|
+
# checkbox :remember_checkbox, "//input[@id='RememberUser']"
|
84
|
+
# checkbox :accept_terms_checkbox, 'input#accept_terms_conditions', :accept_terms_label
|
85
|
+
#
|
86
|
+
def self.checkbox(element_name, locator, proxy = nil)
|
87
|
+
class_eval(%(def #{element_name};@#{element_name} ||= TestCentricity::CheckBox.new("#{element_name}", self, "#{locator}", :page, #{proxy});end))
|
88
|
+
end
|
89
|
+
|
90
|
+
# Declare and instantiate a collection of checkboxes for this page object.
|
91
|
+
#
|
92
|
+
# @param element_hash [Hash] names of checkboxes (as a symbol) and CSS selectors or XPath expressions that uniquely identifies checkboxes
|
93
|
+
# @example
|
94
|
+
# checkboxes hazmat_certified_check: 'input#hazmatCertified',
|
95
|
+
# epa_certified_check: 'input#epaCertified',
|
96
|
+
# dhs_certified_check: 'input#homelandSecurityCertified',
|
97
|
+
# carb_compliant_check: 'input#carbCompliant'
|
98
|
+
#
|
99
|
+
def self.checkboxes(element_hash)
|
100
|
+
element_hash.each(&method(:checkbox))
|
101
|
+
end
|
102
|
+
|
103
|
+
# Declare and instantiate a single radio button UI Element for this page object.
|
104
|
+
#
|
105
|
+
# @param element_name [Symbol] name of radio object (as a symbol)
|
106
|
+
# @param locator [String] CSS selector or XPath expression that uniquely identifies object
|
107
|
+
# @param proxy [Symbol] Optional name (as a symbol) of proxy object to receive click actions
|
108
|
+
# @example
|
109
|
+
# radio :accept_terms_radio, "//input[@id='Accept_Terms']"
|
110
|
+
# radio :decline_terms_radio, '#decline_terms_conditions', :decline_terms_label
|
111
|
+
#
|
112
|
+
def self.radio(element_name, locator, proxy = nil)
|
113
|
+
class_eval(%(def #{element_name};@#{element_name} ||= TestCentricity::Radio.new("#{element_name}", self, "#{locator}", :page, #{proxy});end))
|
114
|
+
end
|
115
|
+
|
116
|
+
# Declare and instantiate a collection of radio buttons for this page object.
|
117
|
+
#
|
118
|
+
# @param element_hash [Hash] names of radio buttons (as a symbol) and CSS selectors or XPath expressions that uniquely identifies radio buttons
|
119
|
+
# @example
|
120
|
+
# radios visa_radio: 'input#payWithVisa',
|
121
|
+
# mastercard_radio: 'input#payWithMastercard',
|
122
|
+
# discover_radio: 'input#payWithDiscover',
|
123
|
+
# amex_radio: 'input#payWithAmEx'
|
124
|
+
#
|
125
|
+
def self.radios(element_hash)
|
126
|
+
element_hash.each(&method(:radio))
|
127
|
+
end
|
128
|
+
|
129
|
+
# Declare and instantiate a single label UI Element for this page object.
|
130
|
+
#
|
131
|
+
# @param element_name [Symbol] name of label object (as a symbol)
|
132
|
+
# @param locator [String] CSS selector or XPath expression that uniquely identifies object
|
133
|
+
# @example
|
134
|
+
# label :welcome_label, 'div.Welcome'
|
135
|
+
# label :rollup_price_label, "//div[contains(@id, 'Rollup Item Price')]"
|
136
|
+
#
|
137
|
+
def self.label(element_name, locator)
|
138
|
+
define_page_element(element_name, TestCentricity::Label, locator)
|
139
|
+
end
|
140
|
+
|
141
|
+
def self.labels(element_hash)
|
142
|
+
element_hash.each(&method(:label))
|
143
|
+
end
|
144
|
+
|
145
|
+
# Declare and instantiate a single link UI Element for this page object.
|
146
|
+
#
|
147
|
+
# @param element_name [Symbol] name of link object (as a symbol)
|
148
|
+
# @param locator [String] CSS selector or XPath expression that uniquely identifies object
|
149
|
+
# @example
|
150
|
+
# link :registration_link, 'a.account-nav__link.register'
|
151
|
+
# link :shopping_basket_link, "//a[@href='shopping_basket']"
|
152
|
+
#
|
153
|
+
def self.link(element_name, locator)
|
154
|
+
define_page_element(element_name, TestCentricity::Link, locator)
|
155
|
+
end
|
156
|
+
|
157
|
+
def self.links(element_hash)
|
158
|
+
element_hash.each(&method(:link))
|
159
|
+
end
|
160
|
+
|
161
|
+
# Declare and instantiate a single table UI Element for this page object.
|
162
|
+
#
|
163
|
+
# @param element_name [Symbol] name of table object (as a symbol)
|
164
|
+
# @param locator [String] XPath expression that uniquely identifies object
|
165
|
+
# @example
|
166
|
+
# table :payments_table, "//table[@class='payments_table']"
|
167
|
+
#
|
168
|
+
def self.table(element_name, locator)
|
169
|
+
define_page_element(element_name, TestCentricity::Table, locator)
|
170
|
+
end
|
171
|
+
|
172
|
+
def self.tables(element_hash)
|
173
|
+
element_hash.each(&method(:table))
|
174
|
+
end
|
175
|
+
|
176
|
+
# Declare and instantiate a single select list UI Element for this page object.
|
177
|
+
#
|
178
|
+
# @param element_name [Symbol] name of select list object (as a symbol)
|
179
|
+
# @param locator [String] CSS selector or XPath expression that uniquely identifies object
|
180
|
+
# @example
|
181
|
+
# selectlist :category_selector, 'select#search_form_category_chosen'
|
182
|
+
# selectlist :gender_select, "//select[@id='customer_gender']"
|
183
|
+
#
|
184
|
+
def self.selectlist(element_name, locator)
|
185
|
+
define_page_element(element_name, TestCentricity::SelectList, locator)
|
186
|
+
end
|
187
|
+
|
188
|
+
def self.selectlists(element_hash)
|
189
|
+
element_hash.each(&method(:selectlist))
|
190
|
+
end
|
191
|
+
|
192
|
+
# Declare and instantiate a single list UI Element for this page object.
|
193
|
+
#
|
194
|
+
# @param element_name [Symbol] name of list object (as a symbol)
|
195
|
+
# @param locator [String] CSS selector or XPath expression that uniquely identifies object
|
196
|
+
# @example
|
197
|
+
# list :x_axis_list, 'g.x-axis'
|
198
|
+
#
|
199
|
+
def self.list(element_name, locator)
|
200
|
+
define_page_element(element_name, TestCentricity::List, locator)
|
201
|
+
end
|
202
|
+
|
203
|
+
def self.lists(element_hash)
|
204
|
+
element_hash.each(&method(:list))
|
205
|
+
end
|
206
|
+
|
207
|
+
# Declare and instantiate an single image UI Element for this page object.
|
208
|
+
#
|
209
|
+
# @param element_name [Symbol] name of image object (as a symbol)
|
210
|
+
# @param locator [String] CSS selector or XPath expression that uniquely identifies object
|
211
|
+
# @example
|
212
|
+
# image :basket_item_image, 'div.product_image'
|
213
|
+
# image :corporate_logo_image, "//img[@alt='MyCompany_logo']"
|
214
|
+
#
|
215
|
+
def self.image(element_name, locator)
|
216
|
+
define_page_element(element_name, TestCentricity::Image, locator)
|
217
|
+
end
|
218
|
+
|
219
|
+
def self.images(element_hash)
|
220
|
+
element_hash.each(&method(:image))
|
221
|
+
end
|
222
|
+
|
223
|
+
# Declare and instantiate a single HTML5 video UI Element for this page object.
|
224
|
+
#
|
225
|
+
# @param element_name [Symbol] name of an HTML5 video object (as a symbol)
|
226
|
+
# @param locator [String] CSS selector or XPath expression that uniquely identifies object
|
227
|
+
# @example
|
228
|
+
# video :video_player, 'video#my_video_player'
|
229
|
+
#
|
230
|
+
def self.video(element_name, locator)
|
231
|
+
define_page_element(element_name, TestCentricity::Video, locator)
|
232
|
+
end
|
233
|
+
|
234
|
+
def self.videos(element_hash)
|
235
|
+
element_hash.each(&method(:video))
|
236
|
+
end
|
237
|
+
|
238
|
+
# Declare and instantiate a single HTML5 audio UI Element for this page object.
|
239
|
+
#
|
240
|
+
# @param element_name [Symbol] name of an HTML5 audio object (as a symbol)
|
241
|
+
# @param locator [String] CSS selector or XPath expression that uniquely identifies object
|
242
|
+
# @example
|
243
|
+
# audio :audio_player, 'audio#my_audio_player'
|
244
|
+
#
|
245
|
+
def self.audio(element_name, locator)
|
246
|
+
define_page_element(element_name, TestCentricity::Audio, locator)
|
247
|
+
end
|
248
|
+
|
249
|
+
def self.audios(element_hash)
|
250
|
+
element_hash.each(&method(:audio))
|
251
|
+
end
|
252
|
+
|
253
|
+
# Declare and instantiate a single File Field UI Element for this page object.
|
254
|
+
#
|
255
|
+
# @param element_name [Symbol] name of file field object (as a symbol)
|
256
|
+
# @param locator [String] CSS selector or XPath expression that uniquely identifies object
|
257
|
+
# @example
|
258
|
+
# filefield :attach_file, 's_SweFileName'
|
259
|
+
#
|
260
|
+
def self.filefield(element_name, locator)
|
261
|
+
define_page_element(element_name, TestCentricity::FileField, locator)
|
262
|
+
end
|
263
|
+
|
264
|
+
def self.filefields(element_hash)
|
265
|
+
element_hash.each(&method(:filefield))
|
266
|
+
end
|
267
|
+
|
268
|
+
# Declare and instantiate a cell button in a table column on this page object.
|
269
|
+
#
|
270
|
+
# @param element_name [Symbol] name of cell button object (as a symbol)
|
271
|
+
# @param locator [String] XPath expression that uniquely identifies cell button within row and column of parent table object
|
272
|
+
# @param table [Symbol] Name (as a symbol) of parent table object
|
273
|
+
# @param column [Integer] 1-based index of table column that contains the cell button object
|
274
|
+
# @example
|
275
|
+
# cell_button :show_button, "a[@class='show']", :data_table, 5
|
276
|
+
# cell_button :edit_button, "a[@class='edit']", :data_table, 5
|
277
|
+
#
|
278
|
+
def self.cell_button(element_name, locator, table, column)
|
279
|
+
class_eval(%(def #{element_name};@#{element_name} ||= TestCentricity::CellButton.new("#{element_name}", self, "#{locator}", :page, #{table}, #{column});end))
|
280
|
+
end
|
281
|
+
|
282
|
+
# Declare and instantiate a cell checkbox in a table column on this page object.
|
283
|
+
#
|
284
|
+
# @param element_name [Symbol] name of cell checkbox object (as a symbol)
|
285
|
+
# @param locator [String] XPath expression that uniquely identifies cell checkbox within row and column of parent table object
|
286
|
+
# @param table [Symbol] Name (as a symbol) of parent table object
|
287
|
+
# @param column [Integer] 1-based index of table column that contains the cell checkbox object
|
288
|
+
# @example
|
289
|
+
# cell_checkbox :is_registered_check, "a[@class='registered']", :data_table, 4
|
290
|
+
#
|
291
|
+
def self.cell_checkbox(element_name, locator, table, column, proxy = nil)
|
292
|
+
class_eval(%(def #{element_name};@#{element_name} ||= TestCentricity::CellCheckBox.new("#{element_name}", self, "#{locator}", :page, #{table}, #{column}, #{proxy});end))
|
293
|
+
end
|
294
|
+
|
295
|
+
# Declare and instantiate a cell radio in a table column on this page object.
|
296
|
+
#
|
297
|
+
# @param element_name [Symbol] name of cell radio object (as a symbol)
|
298
|
+
# @param locator [String] XPath expression that uniquely identifies cell radio within row and column of parent table object
|
299
|
+
# @param table [Symbol] Name (as a symbol) of parent table object
|
300
|
+
# @param column [Integer] 1-based index of table column that contains the cell radio object
|
301
|
+
# @example
|
302
|
+
# cell_radio :track_a_radio, "a[@class='track_a']", :data_table, 8
|
303
|
+
#
|
304
|
+
def self.cell_radio(element_name, locator, table, column, proxy = nil)
|
305
|
+
class_eval(%(def #{element_name};@#{element_name} ||= TestCentricity::CellRadio.new("#{element_name}", self, "#{locator}", :page, #{table}, #{column}, #{proxy});end))
|
306
|
+
end
|
307
|
+
|
308
|
+
# Declare and instantiate a cell image in a table column on this page object.
|
309
|
+
#
|
310
|
+
# @param element_name [Symbol] name of cell image object (as a symbol)
|
311
|
+
# @param locator [String] XPath expression that uniquely identifies cell image within row and column of parent table object
|
312
|
+
# @param table [Symbol] Name (as a symbol) of parent table object
|
313
|
+
# @param column [Integer] 1-based index of table column that contains the cell image object
|
314
|
+
# @example
|
315
|
+
# cell_image :ready_icon, "img[@class='ready']", :data_table, 3
|
316
|
+
# cell_image :send_icon, "img[@class='send']", :data_table, 3
|
317
|
+
#
|
318
|
+
def self.cell_image(element_name, locator, table, column)
|
319
|
+
class_eval(%(def #{element_name};@#{element_name} ||= TestCentricity::CellImage.new("#{element_name}", self, "#{locator}", :page, #{table}, #{column});end))
|
320
|
+
end
|
321
|
+
|
322
|
+
# Declare and instantiate a list button in a row of a list object on this page object.
|
323
|
+
#
|
324
|
+
# @param element_name [Symbol] name of list button object (as a symbol)
|
325
|
+
# @param locator [String] XPath expression that uniquely identifies list button within row of parent list object
|
326
|
+
# @param list [Symbol] Name (as a symbol) of parent list object
|
327
|
+
# @example
|
328
|
+
# list_button :delete_button, "a[@class='delete']", :icon_list
|
329
|
+
# list_button :edit_button, "a[@class='edit']", :icon_list
|
330
|
+
#
|
331
|
+
def self.list_button(element_name, locator, list)
|
332
|
+
class_eval(%(def #{element_name};@#{element_name} ||= TestCentricity::ListButton.new("#{element_name}", self, "#{locator}", :page, #{list});end))
|
333
|
+
end
|
334
|
+
|
335
|
+
# Declare and instantiate a list checkbox in a row of a list object on this page object.
|
336
|
+
#
|
337
|
+
# @param element_name [Symbol] name of list checkbox object (as a symbol)
|
338
|
+
# @param locator [String] XPath expression that uniquely identifies list checkbox within row of parent list object
|
339
|
+
# @param list [Symbol] Name (as a symbol) of parent list object
|
340
|
+
# @example
|
341
|
+
# list_checkbox :is_registered_check, "a[@class='registered']", :data_list
|
342
|
+
#
|
343
|
+
def self.list_checkbox(element_name, locator, list, proxy = nil)
|
344
|
+
class_eval(%(def #{element_name};@#{element_name} ||= TestCentricity::ListCheckBox.new("#{element_name}", self, "#{locator}", :page, #{list}, #{proxy});end))
|
345
|
+
end
|
346
|
+
|
347
|
+
# Declare and instantiate a list radio in a row of a list object on this page object.
|
348
|
+
#
|
349
|
+
# @param element_name [Symbol] name of list radio object (as a symbol)
|
350
|
+
# @param locator [String] XPath expression that uniquely identifies list radio within row of parent list object
|
351
|
+
# @param list [Symbol] Name (as a symbol) of parent list object
|
352
|
+
# @example
|
353
|
+
# list_radio :sharing_radio, "a[@class='sharing']", :data_list
|
354
|
+
#
|
355
|
+
def self.list_radio(element_name, locator, list, proxy = nil)
|
356
|
+
class_eval(%(def #{element_name};@#{element_name} ||= TestCentricity::ListRadio.new("#{element_name}", self, "#{locator}", :page, #{list}, #{proxy});end))
|
357
|
+
end
|
358
|
+
|
359
|
+
# Instantiate a single PageSection object for this page object.
|
360
|
+
#
|
361
|
+
# @param section_name [Symbol] name of PageSection object (as a symbol)
|
362
|
+
# @param class_name [String] Class name of PageSection object
|
363
|
+
# @example
|
364
|
+
# section :search_form, SearchForm
|
365
|
+
#
|
366
|
+
def self.section(section_name, obj, locator = nil)
|
367
|
+
define_method(section_name) do
|
368
|
+
ivar_name = "@#{section_name}"
|
369
|
+
ivar = instance_variable_get(ivar_name)
|
370
|
+
return ivar if ivar
|
371
|
+
instance_variable_set(ivar_name, obj.new(section_name, self, "#{locator}", :page))
|
372
|
+
end
|
373
|
+
end
|
374
|
+
|
375
|
+
def self.sections(section_hash)
|
376
|
+
section_hash.each do |section_name, class_name|
|
377
|
+
section(section_name, class_name)
|
378
|
+
end
|
379
|
+
end
|
380
|
+
|
381
|
+
def open_portal
|
382
|
+
environment = Environ.current
|
383
|
+
url = environment.hostname.blank? ? "#{environment.base_url}#{environment.append}" : "#{environment.hostname}/#{environment.base_url}#{environment.append}"
|
384
|
+
if environment.user_id.blank? || environment.password.blank?
|
385
|
+
visit "#{environment.protocol}://#{url}"
|
386
|
+
else
|
387
|
+
visit "#{environment.protocol}://#{environment.user_id}:#{environment.password}@#{url}"
|
388
|
+
end
|
389
|
+
Environ.portal_state = :open
|
390
|
+
end
|
391
|
+
|
392
|
+
def verify_page_exists
|
393
|
+
raise "Page object #{self.class.name} does not have a page_locator trait defined" unless defined?(page_locator)
|
394
|
+
unless page.has_selector?(page_locator)
|
395
|
+
body_class = find(:xpath, '//body')[:class]
|
396
|
+
error_message = %(
|
397
|
+
Expected page to have selector '#{page_locator}' but found '#{body_class}' instead.
|
398
|
+
Actual URL of page loaded = #{URI.parse(current_url)}.
|
399
|
+
)
|
400
|
+
error_message = "#{error_message}\nExpected URL of page was #{page_url}." if defined?(page_url)
|
401
|
+
raise error_message
|
402
|
+
end
|
403
|
+
PageManager.current_page = self
|
404
|
+
end
|
405
|
+
|
406
|
+
def navigate_to; end
|
407
|
+
|
408
|
+
def verify_page_ui; end
|
409
|
+
|
410
|
+
def load_page
|
411
|
+
return if exists?
|
412
|
+
if defined?(page_url) && !page_url.nil?
|
413
|
+
visit page_url
|
414
|
+
begin
|
415
|
+
page.driver.browser.switch_to.alert.accept
|
416
|
+
rescue => e
|
417
|
+
end unless Environ.browser == :safari || Environ.browser == :ie || Environ.is_device?
|
418
|
+
else
|
419
|
+
navigate_to
|
420
|
+
end
|
421
|
+
verify_page_exists
|
422
|
+
end
|
423
|
+
|
424
|
+
def verify_page_contains(content)
|
425
|
+
raise "Expected page to have content '#{content}'" unless page.has_content?(:visible, content)
|
426
|
+
end
|
427
|
+
|
428
|
+
# Does Page object exists?
|
429
|
+
#
|
430
|
+
# @return [Boolean]
|
431
|
+
# @example
|
432
|
+
# home_page.exists?
|
433
|
+
#
|
434
|
+
def exists?
|
435
|
+
raise "Page object #{self.class.name} does not have a page_locator trait defined" unless defined?(page_locator)
|
436
|
+
saved_wait_time = Capybara.default_max_wait_time
|
437
|
+
Capybara.default_max_wait_time = 0.1
|
438
|
+
tries ||= 2
|
439
|
+
attributes = [:id, :css, :xpath]
|
440
|
+
type = attributes[tries]
|
441
|
+
obj = page.find(type, page_locator)
|
442
|
+
obj != nil
|
443
|
+
rescue
|
444
|
+
Capybara.default_max_wait_time = saved_wait_time
|
445
|
+
retry if (tries -= 1) > 0
|
446
|
+
false
|
447
|
+
ensure
|
448
|
+
Capybara.default_max_wait_time = saved_wait_time
|
449
|
+
end
|
450
|
+
|
451
|
+
# Return page title
|
452
|
+
#
|
453
|
+
# @return [String]
|
454
|
+
# @example
|
455
|
+
# home_page.title
|
456
|
+
#
|
457
|
+
def title
|
458
|
+
page.driver.browser.title
|
459
|
+
end
|
460
|
+
|
461
|
+
# Wait until the page object exists, or until the specified wait time has expired. If the wait time is nil, then the wait
|
462
|
+
# time will be Capybara.default_max_wait_time.
|
463
|
+
#
|
464
|
+
# @param seconds [Integer or Float] wait time in seconds
|
465
|
+
# @example
|
466
|
+
# home_page.wait_until_exists(15)
|
467
|
+
#
|
468
|
+
def wait_until_exists(seconds = nil, post_exception = true)
|
469
|
+
timeout = seconds.nil? ? Capybara.default_max_wait_time : seconds
|
470
|
+
wait = Selenium::WebDriver::Wait.new(timeout: timeout)
|
471
|
+
wait.until { exists? }
|
472
|
+
rescue
|
473
|
+
if post_exception
|
474
|
+
raise "Page object #{self.class.name} not found after #{timeout} seconds" unless exists?
|
475
|
+
else
|
476
|
+
exists?
|
477
|
+
end
|
478
|
+
end
|
479
|
+
|
480
|
+
# Wait until the page object no longer exists, or until the specified wait time has expired. If the wait time is nil, then
|
481
|
+
# the wait time will be Capybara.default_max_wait_time.
|
482
|
+
#
|
483
|
+
# @param seconds [Integer or Float] wait time in seconds
|
484
|
+
# @example
|
485
|
+
# payment_processing_page.wait_until_gone(15)
|
486
|
+
#
|
487
|
+
def wait_until_gone(seconds = nil, post_exception = true)
|
488
|
+
timeout = seconds.nil? ? Capybara.default_max_wait_time : seconds
|
489
|
+
wait = Selenium::WebDriver::Wait.new(timeout: timeout)
|
490
|
+
wait.until { !exists? }
|
491
|
+
rescue
|
492
|
+
if post_exception
|
493
|
+
raise "Page object #{self.class.name} remained visible after #{timeout} seconds" if exists?
|
494
|
+
else
|
495
|
+
exists?
|
496
|
+
end
|
497
|
+
end
|
498
|
+
|
499
|
+
# Wait until all AJAX requests have completed, or until the specified wait time has expired. If the wait time is nil, then
|
500
|
+
# the wait time will be Capybara.default_max_wait_time.
|
501
|
+
#
|
502
|
+
# @param seconds [Integer or Float] wait time in seconds
|
503
|
+
# @example
|
504
|
+
# shopping_basket_page.wait_for_ajax(15)
|
505
|
+
#
|
506
|
+
def wait_for_ajax(seconds = nil)
|
507
|
+
wait_time = seconds.nil? ? Capybara.default_max_wait_time : seconds
|
508
|
+
Timeout.timeout(wait_time) do
|
509
|
+
loop do
|
510
|
+
active = page.evaluate_script('jQuery.active')
|
511
|
+
break if active.zero?
|
512
|
+
end
|
513
|
+
end
|
514
|
+
end
|
515
|
+
|
516
|
+
# Is current Page object URL secure?
|
517
|
+
#
|
518
|
+
# @return [Boolean]
|
519
|
+
# @example
|
520
|
+
# home_page.secure?
|
521
|
+
#
|
522
|
+
def secure?
|
523
|
+
current_url.start_with?('https')
|
524
|
+
end
|
525
|
+
|
526
|
+
private
|
527
|
+
|
528
|
+
def self.define_page_element(element_name, obj, locator)
|
529
|
+
define_method(element_name) do
|
530
|
+
ivar_name = "@#{element_name}"
|
531
|
+
ivar = instance_variable_get(ivar_name)
|
532
|
+
return ivar if ivar
|
533
|
+
instance_variable_set(ivar_name, obj.new(element_name, self, locator, :page))
|
534
|
+
end
|
535
|
+
end
|
536
|
+
end
|
537
|
+
end
|