testcentricity_web 4.1.5 → 4.1.6
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/.gitignore +18 -0
- data/.simplecov +5 -0
- data/CHANGELOG.md +14 -0
- data/Gemfile.lock +59 -1
- data/README.md +14 -6
- data/Rakefile +37 -1
- data/config/cucumber.yml +150 -0
- data/docker-compose-v3.yml +48 -0
- data/features/basic_test_page_css.feature +24 -0
- data/features/basic_test_page_xpath.feature +24 -0
- data/features/step_definitions/generic_steps.rb.rb +37 -0
- data/features/support/env.rb +43 -0
- data/features/support/hooks.rb +245 -0
- data/features/support/pages/basic_css_test_page.rb +49 -0
- data/features/support/pages/basic_test_page.rb +238 -0
- data/features/support/pages/basic_xpath_test_page.rb +49 -0
- data/features/support/pages/media_page.rb +11 -0
- data/features/support/world_pages.rb +15 -0
- data/lib/testcentricity_web/data_objects/environment.rb +4 -0
- data/lib/testcentricity_web/version.rb +1 -1
- data/lib/testcentricity_web/web_core/page_object.rb +13 -6
- data/lib/testcentricity_web/web_core/page_objects_helper.rb +41 -8
- data/lib/testcentricity_web/web_core/page_section.rb +1 -16
- data/lib/testcentricity_web/web_elements/select_list.rb +11 -3
- data/lib/testcentricity_web/web_elements/ui_elements_helper.rb +13 -0
- data/reports/.keep +1 -0
- data/test_site/basic_test_page.html +240 -0
- data/test_site/images/Granny.jpg +0 -0
- data/test_site/images/Wilder.jpg +0 -0
- data/test_site/images/You_Betcha.jpg +0 -0
- data/test_site/media/MP4_small.mp4 +0 -0
- data/test_site/media/MPS_sample.mp3 +0 -0
- data/test_site/media_page.html +33 -0
- data/testcentricity_web.gemspec +5 -0
- metadata +104 -4
- data/test_site/test_page.html +0 -11
@@ -0,0 +1,245 @@
|
|
1
|
+
|
2
|
+
BeforeAll do
|
3
|
+
# start Appium Server if command line option was specified and target browser is mobile simulator or device
|
4
|
+
if ENV['APPIUM_SERVER'] == 'run' && Environ.driver == :appium
|
5
|
+
$server = TestCentricity::AppiumServer.new
|
6
|
+
$server.start
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
|
11
|
+
AfterAll do
|
12
|
+
# terminate Appium Server if command line option was specified and target browser is mobile simulator or device
|
13
|
+
if ENV['APPIUM_SERVER'] == 'run' && Environ.driver == :appium && $server.running?
|
14
|
+
$server.stop
|
15
|
+
end
|
16
|
+
# close driver
|
17
|
+
terminate_session
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
Before do |scenario|
|
22
|
+
# if executing tests in parallel concurrent threads, print thread number with scenario name
|
23
|
+
message = Environ.parallel ? "Thread ##{Environ.process_num} | Scenario: #{scenario.name}" : "Scenario: #{scenario.name}"
|
24
|
+
log message
|
25
|
+
$initialized ||= false
|
26
|
+
unless $initialized
|
27
|
+
$initialized = true
|
28
|
+
$test_start_time = Time.now
|
29
|
+
# HTML report header information if reporting is enabled
|
30
|
+
log Environ.report_header if ENV['REPORTING']
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
After do |scenario|
|
36
|
+
# process and embed any screenshots recorded during execution of scenario
|
37
|
+
process_embed_screenshots(scenario)
|
38
|
+
# clear out any queued screenshots
|
39
|
+
Environ.reset_contexts
|
40
|
+
# close any external pages that may have been opened
|
41
|
+
if Environ.external_page
|
42
|
+
Browsers.close_current_browser_instance
|
43
|
+
begin
|
44
|
+
page.driver.browser.switch_to.alert.accept
|
45
|
+
Browsers.switch_to_new_browser_instance
|
46
|
+
rescue
|
47
|
+
end
|
48
|
+
Environ.set_external_page(false)
|
49
|
+
end
|
50
|
+
# block any JavaScript modals that may appear as a result of ending the session
|
51
|
+
Browsers.suppress_js_leave_page_modal
|
52
|
+
# close Capybara Appium driver if it was opened
|
53
|
+
Capybara.page.driver.quit if Capybara.default_driver == :appium
|
54
|
+
|
55
|
+
if ENV['QUIT_DRIVER']
|
56
|
+
terminate_session
|
57
|
+
elsif Environ.grid == :browserstack
|
58
|
+
# restart BrowserStack test sessions if test duration exceeds 110 minutes to avoid the 2 hour test limit
|
59
|
+
test_elapsed_time = Time.now - $test_start_time
|
60
|
+
if test_elapsed_time > 6600
|
61
|
+
terminate_session
|
62
|
+
log 'Restarting BrowserStack test session'
|
63
|
+
$test_start_time = Time.now
|
64
|
+
else
|
65
|
+
Capybara.reset_sessions!
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
|
71
|
+
# exclusionary Around hooks to prevent running feature/scenario on unsupported browsers, devices, or
|
72
|
+
# cloud remote browser hosting platforms. Use the following tags to block test execution:
|
73
|
+
# desktop web browsers: @!safari, @!ie, @!firefox, @!chrome, @!edge
|
74
|
+
# mobile devices: @!ipad, @!iphone
|
75
|
+
# remotely hosted browsers: @!browserstack, @!saucelabs
|
76
|
+
|
77
|
+
# block feature/scenario execution if running against Safari browser
|
78
|
+
Around('@!safari') do |scenario, block|
|
79
|
+
qualify_browser(:safari, 'Safari', scenario, block)
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
# block feature/scenario execution if running against Internet Explorer browser
|
84
|
+
Around('@!ie') do |scenario, block|
|
85
|
+
qualify_browser(:ie, 'Internet Explorer', scenario, block)
|
86
|
+
end
|
87
|
+
|
88
|
+
|
89
|
+
# block feature/scenario execution if running against Microsoft Edge browser
|
90
|
+
Around('@!edge') do |scenario, block|
|
91
|
+
qualify_browser(:edge, 'Edge', scenario, block)
|
92
|
+
end
|
93
|
+
|
94
|
+
|
95
|
+
# block feature/scenario execution if running against Chrome browser
|
96
|
+
Around('@!chrome') do |scenario, block|
|
97
|
+
qualify_browser(:chrome, 'Chrome', scenario, block)
|
98
|
+
end
|
99
|
+
|
100
|
+
|
101
|
+
# block feature/scenario execution if running against Firefox browser
|
102
|
+
Around('@!firefox') do |scenario, block|
|
103
|
+
qualify_browser(:firefox, 'Firefox', scenario, block)
|
104
|
+
end
|
105
|
+
|
106
|
+
|
107
|
+
# block feature/scenario execution if running against iPad mobile browser
|
108
|
+
Around('@!ipad') do |scenario, block|
|
109
|
+
qualify_device('ipad', scenario, block)
|
110
|
+
end
|
111
|
+
|
112
|
+
|
113
|
+
# block feature/scenario execution if running against iPhone mobile browser
|
114
|
+
Around('@!iphone') do |scenario, block|
|
115
|
+
qualify_device('iphone', scenario, block)
|
116
|
+
end
|
117
|
+
|
118
|
+
|
119
|
+
# block feature/scenario execution if running on Selenium Grid or cloud-hosted services
|
120
|
+
Around('@!grid') do |scenario, block|
|
121
|
+
if !Environ.grid
|
122
|
+
block.call
|
123
|
+
else
|
124
|
+
log "Scenario '#{scenario.name}' cannot be executed on Selenium Grid or cloud-hosted services."
|
125
|
+
skip_this_scenario
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
|
130
|
+
# block feature/scenario execution if running against Browserstack cloud-hosted service
|
131
|
+
Around('@!browserstack') do |scenario, block|
|
132
|
+
if Environ.grid != :browserstack
|
133
|
+
block.call
|
134
|
+
else
|
135
|
+
log "Scenario '#{scenario.name}' cannot be executed on the BrowserStack service."
|
136
|
+
skip_this_scenario
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
|
141
|
+
# block feature/scenario execution if running against Sauce Labs cloud-hosted service
|
142
|
+
Around('@!saucelabs') do |scenario, block|
|
143
|
+
if Environ.grid != :saucelabs
|
144
|
+
block.call
|
145
|
+
else
|
146
|
+
log "Scenario '#{scenario.name}' cannot be executed on the SauceLabs service."
|
147
|
+
skip_this_scenario
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
|
152
|
+
# block feature/scenario execution if running against a physical or emulated mobile device
|
153
|
+
Around('@!device') do |scenario, block|
|
154
|
+
if Environ.is_device?
|
155
|
+
log "Scenario '#{scenario.name}' cannot be executed on physical or emulated devices."
|
156
|
+
skip_this_scenario
|
157
|
+
else
|
158
|
+
block.call
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
|
163
|
+
Around('@!ios') do |scenario, block|
|
164
|
+
if Environ.device_os == :android
|
165
|
+
block.call
|
166
|
+
else
|
167
|
+
log "Scenario '#{scenario.name}' can not be executed on iOS devices."
|
168
|
+
skip_this_scenario
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
|
173
|
+
Around('@!android') do |scenario, block|
|
174
|
+
if Environ.device_os == :ios
|
175
|
+
block.call
|
176
|
+
else
|
177
|
+
log "Scenario '#{scenario.name}' can not be executed on Android devices."
|
178
|
+
skip_this_scenario
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
|
183
|
+
Around('@!mobile') do |scenario, block|
|
184
|
+
if Environ.platform == :mobile
|
185
|
+
log "Scenario '#{scenario.name}' can not be executed on mobile devices or simulators."
|
186
|
+
skip_this_scenario
|
187
|
+
else
|
188
|
+
block.call
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
|
193
|
+
# supporting methods
|
194
|
+
|
195
|
+
def qualify_browser(browser_type, browser_name, scenario, block)
|
196
|
+
if Environ.browser != browser_type && ENV['HOST_BROWSER'] != browser_name.downcase
|
197
|
+
block.call
|
198
|
+
else
|
199
|
+
log "Scenario '#{scenario.name}' cannot be executed with the #{browser_name} browser."
|
200
|
+
skip_this_scenario
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
def qualify_device(device, scenario, block)
|
205
|
+
if Environ.is_device?
|
206
|
+
if Environ.device_type.include? device
|
207
|
+
log "Scenario '#{scenario.name}' cannot be executed on #{device} devices."
|
208
|
+
skip_this_scenario
|
209
|
+
else
|
210
|
+
block.call
|
211
|
+
end
|
212
|
+
else
|
213
|
+
block.call
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
def terminate_session
|
218
|
+
Capybara.page.driver.quit
|
219
|
+
Capybara.reset_sessions!
|
220
|
+
Environ.session_state = :quit
|
221
|
+
$driver_scenario_count = 0
|
222
|
+
end
|
223
|
+
|
224
|
+
def screen_shot_and_save_page(scenario)
|
225
|
+
timestamp = Time.now.strftime('%Y%m%d%H%M%S%L')
|
226
|
+
filename = scenario.nil? ? "Screenshot-#{timestamp}.png" : "Screenshot-#{scenario.__id__}-#{timestamp}.png"
|
227
|
+
path = File.join Dir.pwd, 'reports/screenshots/', filename
|
228
|
+
save_screenshot path
|
229
|
+
log "Screenshot saved at #{path}"
|
230
|
+
screen_shot = { path: path, filename: filename }
|
231
|
+
Environ.save_screen_shot(screen_shot)
|
232
|
+
attach(path, 'image/png') unless scenario.nil?
|
233
|
+
end
|
234
|
+
|
235
|
+
def process_embed_screenshots(scenario)
|
236
|
+
screen_shots = Environ.get_screen_shots
|
237
|
+
if screen_shots.count > 0
|
238
|
+
screen_shots.each do |row|
|
239
|
+
path = row[:path]
|
240
|
+
attach(path, 'image/png')
|
241
|
+
end
|
242
|
+
else
|
243
|
+
screen_shot_and_save_page(scenario) if scenario.failed?
|
244
|
+
end
|
245
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# Page Object class definition for Basic HTML Test page with CSS locators
|
2
|
+
|
3
|
+
class BasicCSSTestPage < BasicTestPage
|
4
|
+
trait(:page_name) { 'Basic CSS Test' }
|
5
|
+
trait(:page_locator) { 'form#HTMLFormElements' }
|
6
|
+
|
7
|
+
# Basic HTML Test page UI elements
|
8
|
+
textfields username_field: 'input#username',
|
9
|
+
password_field: 'input#password',
|
10
|
+
max_length_field: 'input#maxlength',
|
11
|
+
read_only_field: 'input#readonly',
|
12
|
+
number_field: 'input#number-field',
|
13
|
+
color_picker: 'input#color-picker',
|
14
|
+
comments_field: 'textarea#comments'
|
15
|
+
range :slider, 'input#slider'
|
16
|
+
filefield :upload_file, 'input#filename'
|
17
|
+
checkboxes check_1: 'input#check1',
|
18
|
+
check_2: 'input#check2',
|
19
|
+
check_3: 'input#check3',
|
20
|
+
check_4: 'input#check4'
|
21
|
+
radios radio_1: 'input#radio1',
|
22
|
+
radio_2: 'input#radio2',
|
23
|
+
radio_3: 'input#radio3',
|
24
|
+
radio_4: 'input#radio4'
|
25
|
+
selectlists multi_select: 'select#multipleselect',
|
26
|
+
drop_down_select: 'select#dropdown'
|
27
|
+
table :static_table, 'table#table'
|
28
|
+
images image_1: 'img#image1',
|
29
|
+
image_2: 'img#image2',
|
30
|
+
image_3: 'img#image3'
|
31
|
+
buttons cancel_button: 'input#cancel',
|
32
|
+
submit_button: 'input#submit'
|
33
|
+
labels header_label: 'h1',
|
34
|
+
username_label: "label[for='username']",
|
35
|
+
password_label: "label[for='password']",
|
36
|
+
max_length_label: "label[for='maxlength']",
|
37
|
+
read_only_label: "label[for='readonly']",
|
38
|
+
number_label: "label[for='number-field']",
|
39
|
+
color_label: "label[for='color-picker']",
|
40
|
+
slider_label: "label[for='slider']",
|
41
|
+
comments_label: "label[for='comments']",
|
42
|
+
filename_label: "label[for='filename']",
|
43
|
+
checkboxes_label: 'label#checkboxes',
|
44
|
+
radios_label: 'label#radios',
|
45
|
+
multiselect_label: "label[for='multipleselect']",
|
46
|
+
dropdown_label: "label[for='dropdown']",
|
47
|
+
table_label: "label[for='table']",
|
48
|
+
images_label: 'label#images'
|
49
|
+
end
|
@@ -0,0 +1,238 @@
|
|
1
|
+
# Page Object class definition for Basic HTML Test page
|
2
|
+
|
3
|
+
class BasicTestPage < TestCentricity::PageObject
|
4
|
+
trait(:page_url) { '/basic_test_page.html' }
|
5
|
+
trait(:tab_order) {
|
6
|
+
[
|
7
|
+
username_field,
|
8
|
+
password_field,
|
9
|
+
max_length_field,
|
10
|
+
read_only_field,
|
11
|
+
number_field,
|
12
|
+
color_picker,
|
13
|
+
slider,
|
14
|
+
comments_field,
|
15
|
+
upload_file,
|
16
|
+
check_1,
|
17
|
+
check_2,
|
18
|
+
check_3,
|
19
|
+
radio_1,
|
20
|
+
[
|
21
|
+
radio_2,
|
22
|
+
radio_3
|
23
|
+
],
|
24
|
+
multi_select,
|
25
|
+
drop_down_select,
|
26
|
+
cancel_button,
|
27
|
+
submit_button
|
28
|
+
]
|
29
|
+
}
|
30
|
+
trait(:safari_tab_order) {
|
31
|
+
[
|
32
|
+
username_field,
|
33
|
+
password_field,
|
34
|
+
max_length_field,
|
35
|
+
read_only_field,
|
36
|
+
number_field,
|
37
|
+
comments_field,
|
38
|
+
multi_select,
|
39
|
+
drop_down_select
|
40
|
+
]
|
41
|
+
}
|
42
|
+
|
43
|
+
def verify_page_ui
|
44
|
+
ui = {
|
45
|
+
self => { exists: true, secure: false, title: 'Basic HTML Form' },
|
46
|
+
header_label => { visible: true, caption: 'Basic HTML Form Example' },
|
47
|
+
username_label => { visible: true, caption: 'Username:' },
|
48
|
+
username_field => { visible: true, enabled: true, required: true, value: '', placeholder: 'User name' },
|
49
|
+
password_label => { visible: true, caption: 'Password:' },
|
50
|
+
password_field => { visible: true, enabled: true, required: true, value: '', placeholder: 'Password' },
|
51
|
+
max_length_label => { visible: true, caption: 'Max Length:' },
|
52
|
+
max_length_field => {
|
53
|
+
visible: true,
|
54
|
+
enabled: true,
|
55
|
+
placeholder: 'up to 64 characters',
|
56
|
+
value: '',
|
57
|
+
maxlength: 64
|
58
|
+
},
|
59
|
+
read_only_label => { visible: true, caption: 'Read Only:' },
|
60
|
+
read_only_field => {
|
61
|
+
visible: true,
|
62
|
+
enabled: true,
|
63
|
+
readonly: true,
|
64
|
+
value: 'I am a read only text field'
|
65
|
+
},
|
66
|
+
number_label => { visible: true, caption: 'Number:' },
|
67
|
+
number_field => {
|
68
|
+
visible: true,
|
69
|
+
enabled: true,
|
70
|
+
value: '41',
|
71
|
+
min: 10,
|
72
|
+
max: 1024,
|
73
|
+
step: 1
|
74
|
+
},
|
75
|
+
color_label => { visible: true, caption: 'Color:' },
|
76
|
+
color_picker => { visible: true, enabled: true, value: '#000000' },
|
77
|
+
slider_label => { visible: true, caption: 'Range:' },
|
78
|
+
slider => {
|
79
|
+
visible: true,
|
80
|
+
enabled: true,
|
81
|
+
value: 25,
|
82
|
+
min: 0,
|
83
|
+
max: 50,
|
84
|
+
},
|
85
|
+
comments_label => { visible: true, caption: 'TextArea:' },
|
86
|
+
comments_field => { visible: true, enabled: true, value: '' },
|
87
|
+
filename_label => { visible: true, caption: 'Filename:' },
|
88
|
+
upload_file => { visible: true, enabled: true, value: '' },
|
89
|
+
checkboxes_label => { visible: true, caption: 'Checkbox Items:' },
|
90
|
+
check_1 => { visible: true, enabled: true, checked: false },
|
91
|
+
check_2 => { visible: true, enabled: true, checked: false },
|
92
|
+
check_3 => { visible: true, enabled: true, checked: false },
|
93
|
+
check_4 => { visible: true, enabled: false, checked: false },
|
94
|
+
radios_label => { visible: true, caption: 'Radio Items:' },
|
95
|
+
radio_1 => { visible: true, enabled: true, selected: false },
|
96
|
+
radio_2 => { visible: true, enabled: true, selected: false },
|
97
|
+
radio_3 => { visible: true, enabled: true, selected: false },
|
98
|
+
radio_4 => { visible: true, enabled: false, selected: false },
|
99
|
+
multiselect_label => { visible: true, caption: 'Multiple Select Values:' },
|
100
|
+
multi_select => {
|
101
|
+
visible: true,
|
102
|
+
enabled: true,
|
103
|
+
optioncount: 4,
|
104
|
+
options: ['Selection Item 1', 'Selection Item 2', 'Selection Item 3', 'Selection Item 4'],
|
105
|
+
selected: ''
|
106
|
+
},
|
107
|
+
dropdown_label => { visible: true, caption: 'Dropdown:' },
|
108
|
+
drop_down_select => {
|
109
|
+
visible: true,
|
110
|
+
enabled: true,
|
111
|
+
optioncount: 6,
|
112
|
+
options: ['Drop Down Item 1', 'Drop Down Item 2', 'Drop Down Item 3', 'Drop Down Item 4', 'Drop Down Item 5', 'Drop Down Item 6'],
|
113
|
+
selected: 'Drop Down Item 1'
|
114
|
+
},
|
115
|
+
table_label => { visible: true, caption: 'Table:' },
|
116
|
+
static_table => {
|
117
|
+
visible: true,
|
118
|
+
columncount: 3,
|
119
|
+
rowcount: 4,
|
120
|
+
column_headers: %w[Company Contact Country],
|
121
|
+
{ row: 1 } => [['Alfreds Futterkiste', 'Maria Anders', 'Germany']],
|
122
|
+
{ row: 2 } => [['Centro comercial Moctezuma', 'Francisco Chang', 'Mexico']],
|
123
|
+
{ row: 3 } => [['Ernst Handel', 'Roland Mendel', 'Austria']],
|
124
|
+
{ row: 4 } => [['Island Trading', 'Helen Bennett', 'UK']]
|
125
|
+
},
|
126
|
+
images_label => { visible: true, caption: 'Images:' },
|
127
|
+
image_1 => {
|
128
|
+
visible: true,
|
129
|
+
broken: false,
|
130
|
+
src: { ends_with: 'images/Wilder.jpg' },
|
131
|
+
alt: "It's alive"
|
132
|
+
},
|
133
|
+
image_2 => {
|
134
|
+
visible: true,
|
135
|
+
broken: false,
|
136
|
+
src: { ends_with: 'images/You_Betcha.jpg' },
|
137
|
+
alt: 'You Betcha'
|
138
|
+
},
|
139
|
+
image_3 => {
|
140
|
+
visible: true,
|
141
|
+
broken: true,
|
142
|
+
src: { ends_with: 'wrongname.gif' },
|
143
|
+
alt: 'A broken image'
|
144
|
+
},
|
145
|
+
cancel_button => { visible: true, enabled: true, caption: 'Cancel' },
|
146
|
+
submit_button => { visible: true, enabled: true, caption: 'Submit' }
|
147
|
+
}
|
148
|
+
verify_ui_states(ui)
|
149
|
+
end
|
150
|
+
|
151
|
+
def form_data
|
152
|
+
file_path = Environ.platform == :mobile ? nil : "#{Dir.pwd}/test_site/images/Wilder.jpg"
|
153
|
+
{
|
154
|
+
username: Faker::Name.name,
|
155
|
+
password: 'T0p_Sekrit',
|
156
|
+
maxlength: Faker::Marketing.buzzwords,
|
157
|
+
number: Faker::Number.between(from: 10, to: 1024),
|
158
|
+
color: Faker::Color.hex_color,
|
159
|
+
slider: 45,
|
160
|
+
comments: Faker::Hipster.paragraph,
|
161
|
+
filepath: file_path,
|
162
|
+
filename: "Wilder.jpg",
|
163
|
+
check1: true,
|
164
|
+
check2: true,
|
165
|
+
check3: false,
|
166
|
+
radio1: true,
|
167
|
+
radio2: false,
|
168
|
+
radio3: false,
|
169
|
+
multi_select: 'Selection Item 2',
|
170
|
+
drop_select: 'Drop Down Item 5'
|
171
|
+
}
|
172
|
+
end
|
173
|
+
|
174
|
+
def populate_form
|
175
|
+
@data = form_data
|
176
|
+
fields = {
|
177
|
+
username_field => @data[:username],
|
178
|
+
password_field => @data[:password],
|
179
|
+
max_length_field => @data[:maxlength],
|
180
|
+
number_field => @data[:number],
|
181
|
+
color_picker => @data[:color],
|
182
|
+
slider => @data[:slider],
|
183
|
+
comments_field => @data[:comments],
|
184
|
+
upload_file => @data[:filepath],
|
185
|
+
check_1 => @data[:check1],
|
186
|
+
check_2 => @data[:check2],
|
187
|
+
check_3 => @data[:check3],
|
188
|
+
radio_1 => @data[:radio1],
|
189
|
+
radio_2 => @data[:radio2],
|
190
|
+
radio_3 => @data[:radio3],
|
191
|
+
multi_select => @data[:multi_select],
|
192
|
+
drop_down_select => @data[:drop_select]
|
193
|
+
}
|
194
|
+
populate_data_fields(fields)
|
195
|
+
end
|
196
|
+
|
197
|
+
def verify_form_data
|
198
|
+
ui = {
|
199
|
+
username_field => { value: @data[:username] },
|
200
|
+
password_field => { value: @data[:password] },
|
201
|
+
max_length_field => { value: @data[:maxlength] },
|
202
|
+
number_field => { value: @data[:number].to_s },
|
203
|
+
color_picker => { value: @data[:color] },
|
204
|
+
slider => { value: @data[:slider] },
|
205
|
+
comments_field => { value: @data[:comments] },
|
206
|
+
upload_file => { value: { ends_with: @data[:filename] } },
|
207
|
+
check_1 => { checked: @data[:check1] },
|
208
|
+
check_2 => { checked: @data[:check2] },
|
209
|
+
check_3 => { checked: @data[:check3] },
|
210
|
+
radio_1 => { selected: @data[:radio1] },
|
211
|
+
radio_2 => { selected: @data[:radio2] },
|
212
|
+
radio_3 => { selected: @data[:radio3] },
|
213
|
+
multi_select => { selected: @data[:multi_select] },
|
214
|
+
drop_down_select => { selected: @data[:drop_select] }
|
215
|
+
}
|
216
|
+
verify_ui_states(ui)
|
217
|
+
end
|
218
|
+
|
219
|
+
def perform_action(action)
|
220
|
+
case action
|
221
|
+
when :submit
|
222
|
+
submit_button.click
|
223
|
+
when :cancel
|
224
|
+
cancel_button.click
|
225
|
+
else
|
226
|
+
raise "#{action} is not a valid selector"
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
def verify_tab_order
|
231
|
+
order = if Environ.browser == :safari
|
232
|
+
safari_tab_order
|
233
|
+
else
|
234
|
+
tab_order
|
235
|
+
end
|
236
|
+
verify_focus_order(order)
|
237
|
+
end
|
238
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# Page Object class definition for Basic HTML Test page with Xpath locators
|
2
|
+
|
3
|
+
class BasicXpathTestPage < BasicTestPage
|
4
|
+
trait(:page_name) { 'Basic Xpath Test' }
|
5
|
+
trait(:page_locator) { "//form[@id='HTMLFormElements']" }
|
6
|
+
|
7
|
+
# Basic HTML Test page UI elements
|
8
|
+
textfields username_field: "//input[@id='username']",
|
9
|
+
password_field: "//input[@id='password']",
|
10
|
+
max_length_field: "//input[@id='maxlength']",
|
11
|
+
read_only_field: "//input[@id='readonly']",
|
12
|
+
number_field: "//input[@id='number-field']",
|
13
|
+
comments_field: "//textarea[@id='comments']",
|
14
|
+
color_picker: "//input[@id='color-picker']"
|
15
|
+
range :slider, "//input[@id='slider']"
|
16
|
+
filefield :upload_file, "//input[@id='filename']"
|
17
|
+
checkboxes check_1: "//input[@id='check1']",
|
18
|
+
check_2: "//input[@id='check2']",
|
19
|
+
check_3: "//input[@id='check3']",
|
20
|
+
check_4: "//input[@id='check4']"
|
21
|
+
radios radio_1: "//input[@id='radio1']",
|
22
|
+
radio_2: "//input[@id='radio2']",
|
23
|
+
radio_3: "//input[@id='radio3']",
|
24
|
+
radio_4: "//input[@id='radio4']"
|
25
|
+
selectlists multi_select: "//select[@id='multipleselect']",
|
26
|
+
drop_down_select: "//select[@id='dropdown']"
|
27
|
+
table :static_table, "//table[@id='table']"
|
28
|
+
images image_1: "//img[@id='image1']",
|
29
|
+
image_2: "//img[@id='image2']",
|
30
|
+
image_3: "//img[@id='image3']"
|
31
|
+
buttons cancel_button: "//input[@id='cancel']",
|
32
|
+
submit_button: "//input[@id='submit']"
|
33
|
+
labels header_label: '//h1',
|
34
|
+
username_label: "//label[@for='username']",
|
35
|
+
password_label: "//label[@for='password']",
|
36
|
+
max_length_label: "//label[@for='maxlength']",
|
37
|
+
read_only_label: "//label[@for='readonly']",
|
38
|
+
number_label: "//label[@for='number-field']",
|
39
|
+
color_label: "//label[@for='color-picker']",
|
40
|
+
slider_label: "//label[@for='slider']",
|
41
|
+
comments_label: "//label[@for='comments']",
|
42
|
+
filename_label: "//label[@for='filename']",
|
43
|
+
checkboxes_label: "//label[@id='checkboxes']",
|
44
|
+
radios_label: "//label[@id='radios']",
|
45
|
+
multiselect_label: "//label[@for='multipleselect']",
|
46
|
+
dropdown_label: "//label[@for='dropdown']",
|
47
|
+
table_label: "//label[@for='table']",
|
48
|
+
images_label: "//label[@id='images']"
|
49
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# Page Object class definition for Media Test page with CSS locators
|
2
|
+
|
3
|
+
class MediaTestPage < TestCentricity::PageObject
|
4
|
+
trait(:page_name) { 'Media Test' }
|
5
|
+
trait(:page_locator) { 'div.media-page-body' }
|
6
|
+
trait(:page_url) { '/media_page.html' }
|
7
|
+
|
8
|
+
# Media Test page UI elements
|
9
|
+
video :video_player, 'video#video_player'
|
10
|
+
audio :audio_player, 'audio#audio_player'
|
11
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module WorldPages
|
2
|
+
#
|
3
|
+
# page_objects method returns a hash table of your web app's page objects and associated page classes to be instantiated
|
4
|
+
# by the TestCentricity™ PageManager. Page Object class definitions are contained in the features/support/pages folder.
|
5
|
+
#
|
6
|
+
def page_objects
|
7
|
+
{
|
8
|
+
basic_css_test_page: BasicCSSTestPage,
|
9
|
+
basic_xpath_test_page: BasicXpathTestPage,
|
10
|
+
}
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
World(WorldPages)
|
@@ -1,5 +1,9 @@
|
|
1
1
|
module TestCentricity
|
2
2
|
class PageObject < BasePageSectionObject
|
3
|
+
def initialize
|
4
|
+
set_locator_type(page_locator) if defined?(page_locator)
|
5
|
+
end
|
6
|
+
|
3
7
|
# Declare and instantiate a single generic UI Element for this page object.
|
4
8
|
#
|
5
9
|
# @param element_name [Symbol] name of UI object (as a symbol)
|
@@ -310,17 +314,20 @@ module TestCentricity
|
|
310
314
|
def open_portal
|
311
315
|
environment = Environ.current
|
312
316
|
url = environment.hostname.blank? ? "#{environment.base_url}#{environment.append}" : "#{environment.hostname}/#{environment.base_url}#{environment.append}"
|
313
|
-
if environment.user_id.blank? || environment.password.blank?
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
317
|
+
full_url = if environment.user_id.blank? || environment.password.blank?
|
318
|
+
"#{environment.protocol}://#{url}"
|
319
|
+
else
|
320
|
+
"#{environment.protocol}://#{environment.user_id}:#{environment.password}@#{url}"
|
321
|
+
end
|
322
|
+
visit full_url
|
318
323
|
Environ.portal_state = :open
|
319
324
|
end
|
320
325
|
|
321
326
|
def verify_page_exists
|
322
327
|
raise "Page object #{self.class.name} does not have a page_locator trait defined" unless defined?(page_locator)
|
323
|
-
|
328
|
+
|
329
|
+
set_locator_type(page_locator) if @locator_type.blank?
|
330
|
+
unless page.has_selector?(@locator_type, page_locator)
|
324
331
|
body_class = find(:xpath, '//body')[:class]
|
325
332
|
error_message = %(
|
326
333
|
Expected page to have selector '#{page_locator}' but found '#{body_class}' instead.
|