testcentricity_web 4.1.4 → 4.1.7
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 +43 -1
- data/Gemfile.lock +60 -2
- data/README.md +166 -21
- data/Rakefile +60 -1
- data/config/cucumber.yml +163 -0
- data/config/test_data/data.json +12 -0
- data/config/test_data/data.xls +0 -0
- data/config/test_data/data.yml +12 -0
- data/docker-compose-v3.yml +48 -0
- data/features/basic_test_page_css.feature +35 -0
- data/features/basic_test_page_xpath.feature +27 -0
- data/features/media_players.feature +87 -0
- data/features/step_definitions/generic_steps.rb.rb +44 -0
- data/features/step_definitions/media_steps.rb +30 -0
- data/features/support/env.rb +50 -0
- data/features/support/hooks.rb +245 -0
- data/features/support/pages/base_test_page.rb +11 -0
- data/features/support/pages/basic_css_test_page.rb +52 -0
- data/features/support/pages/basic_test_page.rb +297 -0
- data/features/support/pages/basic_xpath_test_page.rb +53 -0
- data/features/support/pages/custom_controls_page.rb +16 -0
- data/features/support/pages/indexed_sections_page.rb +16 -0
- data/features/support/pages/media_test_page.rb +195 -0
- data/features/support/sections/header_nav.rb +28 -0
- data/features/support/world_data.rb +12 -0
- data/features/support/world_pages.rb +18 -0
- data/lib/testcentricity_web/data_objects/environment.rb +16 -0
- data/lib/testcentricity_web/version.rb +1 -1
- data/lib/testcentricity_web/web_core/page_object.rb +8 -8
- 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_core/webdriver_helper.rb +77 -120
- data/lib/testcentricity_web/web_elements/checkbox.rb +3 -4
- data/lib/testcentricity_web/web_elements/media.rb +50 -4
- data/lib/testcentricity_web/web_elements/radio.rb +5 -1
- data/lib/testcentricity_web/web_elements/select_list.rb +18 -7
- data/lib/testcentricity_web/web_elements/ui_elements_helper.rb +13 -0
- data/reports/.keep +1 -0
- data/test_site/basic_test_page.html +290 -0
- data/test_site/custom_controls_page.html +58 -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/indexed_sections_page.html +58 -0
- data/test_site/media/MIB2-subtitles-pt-BR.vtt +49 -0
- data/test_site/media/MIB2.mp4 +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 +86 -0
- data/testcentricity_web.gemspec +5 -0
- metadata +125 -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,52 @@
|
|
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
|
+
ranges slider: 'input#slider'
|
16
|
+
filefields 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
|
+
links link_1: 'a#link1',
|
28
|
+
link_2: 'a#link2',
|
29
|
+
link_3: 'a#link3'
|
30
|
+
tables static_table: 'table#table'
|
31
|
+
images image_1: 'img#image1',
|
32
|
+
image_2: 'img#image2',
|
33
|
+
image_3: 'img#image3'
|
34
|
+
buttons cancel_button: 'input#cancel',
|
35
|
+
submit_button: 'input#submit'
|
36
|
+
labels username_label: "label[for='username']",
|
37
|
+
password_label: "label[for='password']",
|
38
|
+
max_length_label: "label[for='maxlength']",
|
39
|
+
read_only_label: "label[for='readonly']",
|
40
|
+
number_label: "label[for='number-field']",
|
41
|
+
color_label: "label[for='color-picker']",
|
42
|
+
slider_label: "label[for='slider']",
|
43
|
+
comments_label: "label[for='comments']",
|
44
|
+
filename_label: "label[for='filename']",
|
45
|
+
checkboxes_label: 'label#checkboxes',
|
46
|
+
radios_label: 'label#radios',
|
47
|
+
multiselect_label: "label[for='multipleselect']",
|
48
|
+
dropdown_label: "label[for='dropdown']",
|
49
|
+
link_label: 'label#links',
|
50
|
+
table_label: "label[for='table']",
|
51
|
+
images_label: 'label#images'
|
52
|
+
end
|
@@ -0,0 +1,297 @@
|
|
1
|
+
# Page Object class definition for Basic HTML Test page
|
2
|
+
|
3
|
+
class BasicTestPage < BaseTestPage
|
4
|
+
trait(:page_url) { '/basic_test_page.html' }
|
5
|
+
trait(:navigator) { header_nav.open_form_page }
|
6
|
+
trait(:tab_order) {
|
7
|
+
[
|
8
|
+
header_nav.form_link,
|
9
|
+
header_nav.media_link,
|
10
|
+
header_nav.indexed_sections_link,
|
11
|
+
header_nav.custom_controls_link,
|
12
|
+
username_field,
|
13
|
+
password_field,
|
14
|
+
max_length_field,
|
15
|
+
read_only_field,
|
16
|
+
number_field,
|
17
|
+
color_picker,
|
18
|
+
slider,
|
19
|
+
comments_field,
|
20
|
+
upload_file,
|
21
|
+
check_1,
|
22
|
+
check_2,
|
23
|
+
check_3,
|
24
|
+
radio_1,
|
25
|
+
[
|
26
|
+
radio_2,
|
27
|
+
radio_3
|
28
|
+
],
|
29
|
+
multi_select,
|
30
|
+
drop_down_select,
|
31
|
+
link_1,
|
32
|
+
link_2,
|
33
|
+
cancel_button,
|
34
|
+
submit_button
|
35
|
+
]
|
36
|
+
}
|
37
|
+
trait(:firefox_order) {
|
38
|
+
[
|
39
|
+
username_field,
|
40
|
+
password_field,
|
41
|
+
max_length_field,
|
42
|
+
read_only_field,
|
43
|
+
number_field,
|
44
|
+
color_picker,
|
45
|
+
slider,
|
46
|
+
comments_field,
|
47
|
+
upload_file,
|
48
|
+
check_1,
|
49
|
+
check_2,
|
50
|
+
check_3,
|
51
|
+
radio_1,
|
52
|
+
[
|
53
|
+
radio_2,
|
54
|
+
radio_3
|
55
|
+
],
|
56
|
+
multi_select,
|
57
|
+
drop_down_select,
|
58
|
+
cancel_button,
|
59
|
+
submit_button
|
60
|
+
]
|
61
|
+
}
|
62
|
+
trait(:safari_tab_order) {
|
63
|
+
[
|
64
|
+
username_field,
|
65
|
+
password_field,
|
66
|
+
max_length_field,
|
67
|
+
read_only_field,
|
68
|
+
number_field,
|
69
|
+
comments_field,
|
70
|
+
multi_select,
|
71
|
+
drop_down_select
|
72
|
+
]
|
73
|
+
}
|
74
|
+
|
75
|
+
def verify_page_ui
|
76
|
+
ui = {
|
77
|
+
self => { exists: true, secure: false, title: 'Basic HTML Form' },
|
78
|
+
header_label => { visible: true, caption: 'Basic HTML Form Example' },
|
79
|
+
username_label => { visible: true, caption: 'Username:' },
|
80
|
+
username_field => { visible: true, enabled: true, required: true, value: '', placeholder: 'User name' },
|
81
|
+
password_label => { visible: true, caption: 'Password:' },
|
82
|
+
password_field => { visible: true, enabled: true, required: true, value: '', placeholder: 'Password' },
|
83
|
+
max_length_label => { visible: true, caption: 'Max Length:' },
|
84
|
+
max_length_field => {
|
85
|
+
visible: true,
|
86
|
+
enabled: true,
|
87
|
+
placeholder: 'up to 64 characters',
|
88
|
+
value: '',
|
89
|
+
maxlength: 64
|
90
|
+
},
|
91
|
+
read_only_label => { visible: true, caption: 'Read Only:' },
|
92
|
+
read_only_field => {
|
93
|
+
visible: true,
|
94
|
+
enabled: true,
|
95
|
+
readonly: true,
|
96
|
+
value: 'I am a read only text field'
|
97
|
+
},
|
98
|
+
number_label => { visible: true, caption: 'Number:' },
|
99
|
+
number_field => {
|
100
|
+
visible: true,
|
101
|
+
enabled: true,
|
102
|
+
value: '41',
|
103
|
+
min: 10,
|
104
|
+
max: 1024,
|
105
|
+
step: 1
|
106
|
+
},
|
107
|
+
color_label => { visible: true, caption: 'Color:' },
|
108
|
+
color_picker => { visible: true, enabled: true, value: '#000000' },
|
109
|
+
slider_label => { visible: true, caption: 'Range:' },
|
110
|
+
slider => {
|
111
|
+
visible: true,
|
112
|
+
enabled: true,
|
113
|
+
value: 25,
|
114
|
+
min: 0,
|
115
|
+
max: 50,
|
116
|
+
},
|
117
|
+
comments_label => { visible: true, caption: 'TextArea:' },
|
118
|
+
comments_field => { visible: true, enabled: true, value: '' },
|
119
|
+
filename_label => { visible: true, caption: 'Filename:' },
|
120
|
+
upload_file => { visible: true, enabled: true, value: '' },
|
121
|
+
checkboxes_label => { visible: true, caption: 'Checkbox Items:' },
|
122
|
+
check_1 => { visible: true, enabled: true, checked: false },
|
123
|
+
check_2 => { visible: true, enabled: true, checked: false },
|
124
|
+
check_3 => { visible: true, enabled: true, checked: false },
|
125
|
+
check_4 => { visible: true, enabled: false, checked: false },
|
126
|
+
radios_label => { visible: true, caption: 'Radio Items:' },
|
127
|
+
radio_1 => { visible: true, enabled: true, selected: false },
|
128
|
+
radio_2 => { visible: true, enabled: true, selected: false },
|
129
|
+
radio_3 => { visible: true, enabled: true, selected: false },
|
130
|
+
radio_4 => { visible: true, enabled: false, selected: false },
|
131
|
+
multiselect_label => { visible: true, caption: 'Multiple Select Values:' },
|
132
|
+
multi_select => {
|
133
|
+
visible: true,
|
134
|
+
enabled: true,
|
135
|
+
optioncount: 4,
|
136
|
+
options: ['Selection Item 1', 'Selection Item 2', 'Selection Item 3', 'Selection Item 4'],
|
137
|
+
selected: ''
|
138
|
+
},
|
139
|
+
dropdown_label => { visible: true, caption: 'Dropdown:' },
|
140
|
+
drop_down_select => {
|
141
|
+
visible: true,
|
142
|
+
enabled: true,
|
143
|
+
optioncount: 6,
|
144
|
+
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'],
|
145
|
+
selected: 'Drop Down Item 1'
|
146
|
+
},
|
147
|
+
link_label => { visible: true, caption: 'Links:' },
|
148
|
+
link_1 => {
|
149
|
+
visible: true,
|
150
|
+
href: { ends_with: 'media_page.html' },
|
151
|
+
caption: 'Open Media Page in same window/tab'
|
152
|
+
},
|
153
|
+
link_2 => {
|
154
|
+
visible: true,
|
155
|
+
href: { ends_with: 'media_page.html' },
|
156
|
+
caption: 'Open Media Page in a new window/tab'
|
157
|
+
},
|
158
|
+
link_3 => {
|
159
|
+
visible: true,
|
160
|
+
aria_disabled: true,
|
161
|
+
caption: 'Disabled Link'
|
162
|
+
},
|
163
|
+
table_label => { visible: true, caption: 'Table:' },
|
164
|
+
static_table => {
|
165
|
+
visible: true,
|
166
|
+
columncount: 3,
|
167
|
+
rowcount: 4,
|
168
|
+
column_headers: %w[Company Contact Country],
|
169
|
+
{ row: 1 } => [['Alfreds Futterkiste', 'Maria Anders', 'Germany']],
|
170
|
+
{ row: 2 } => [['Centro comercial Moctezuma', 'Francisco Chang', 'Mexico']],
|
171
|
+
{ row: 3 } => [['Ernst Handel', 'Roland Mendel', 'Austria']],
|
172
|
+
{ row: 4 } => [['Island Trading', 'Helen Bennett', 'UK']]
|
173
|
+
},
|
174
|
+
images_label => { visible: true, caption: 'Images:' },
|
175
|
+
image_1 => {
|
176
|
+
visible: true,
|
177
|
+
broken: false,
|
178
|
+
src: { ends_with: 'images/Wilder.jpg' },
|
179
|
+
alt: "It's alive"
|
180
|
+
},
|
181
|
+
image_2 => {
|
182
|
+
visible: true,
|
183
|
+
broken: false,
|
184
|
+
src: { ends_with: 'images/You_Betcha.jpg' },
|
185
|
+
alt: 'You Betcha'
|
186
|
+
},
|
187
|
+
image_3 => {
|
188
|
+
visible: true,
|
189
|
+
broken: true,
|
190
|
+
src: { ends_with: 'wrongname.gif' },
|
191
|
+
alt: 'A broken image'
|
192
|
+
},
|
193
|
+
cancel_button => { visible: true, enabled: true, caption: 'Cancel' },
|
194
|
+
submit_button => { visible: true, enabled: true, caption: 'Submit' }
|
195
|
+
}
|
196
|
+
verify_ui_states(ui)
|
197
|
+
end
|
198
|
+
|
199
|
+
def form_data
|
200
|
+
if Environ.platform == :mobile
|
201
|
+
file_path = nil
|
202
|
+
file_name = ''
|
203
|
+
color_value = '#000000'
|
204
|
+
else
|
205
|
+
file_path = "#{Dir.pwd}/test_site/images/Wilder.jpg"
|
206
|
+
file_name = 'Wilder.jpg'
|
207
|
+
color_value = Faker::Color.hex_color
|
208
|
+
end
|
209
|
+
{
|
210
|
+
username: Faker::Name.name,
|
211
|
+
password: 'T0p_Sekrit',
|
212
|
+
maxlength: Faker::Marketing.buzzwords,
|
213
|
+
number: Faker::Number.between(from: 10, to: 1024),
|
214
|
+
color: color_value,
|
215
|
+
slider: 50,
|
216
|
+
comments: Faker::Hipster.paragraph,
|
217
|
+
filepath: file_path,
|
218
|
+
filename: file_name,
|
219
|
+
check1: true,
|
220
|
+
check2: true,
|
221
|
+
check3: false,
|
222
|
+
radio1: false,
|
223
|
+
radio2: true,
|
224
|
+
radio3: false,
|
225
|
+
multi_select: 'Selection Item 2',
|
226
|
+
drop_select: 'Drop Down Item 5'
|
227
|
+
}
|
228
|
+
end
|
229
|
+
|
230
|
+
def populate_form
|
231
|
+
@data = form_data
|
232
|
+
fields = {
|
233
|
+
username_field => @data[:username],
|
234
|
+
password_field => @data[:password],
|
235
|
+
max_length_field => @data[:maxlength],
|
236
|
+
number_field => @data[:number],
|
237
|
+
color_picker => @data[:color],
|
238
|
+
slider => @data[:slider],
|
239
|
+
comments_field => @data[:comments],
|
240
|
+
upload_file => @data[:filepath],
|
241
|
+
check_1 => @data[:check1],
|
242
|
+
check_2 => @data[:check2],
|
243
|
+
check_3 => @data[:check3],
|
244
|
+
radio_1 => @data[:radio1],
|
245
|
+
radio_2 => @data[:radio2],
|
246
|
+
radio_3 => @data[:radio3],
|
247
|
+
multi_select => @data[:multi_select],
|
248
|
+
drop_down_select => @data[:drop_select]
|
249
|
+
}
|
250
|
+
populate_data_fields(fields)
|
251
|
+
end
|
252
|
+
|
253
|
+
def verify_form_data
|
254
|
+
ui = {
|
255
|
+
username_field => { value: @data[:username] },
|
256
|
+
password_field => { value: @data[:password] },
|
257
|
+
max_length_field => { value: @data[:maxlength] },
|
258
|
+
number_field => { value: @data[:number].to_s },
|
259
|
+
color_picker => { value: @data[:color] },
|
260
|
+
slider => { value: @data[:slider] },
|
261
|
+
comments_field => { value: @data[:comments] },
|
262
|
+
upload_file => { value: { ends_with: @data[:filename] } },
|
263
|
+
check_1 => { checked: @data[:check1] },
|
264
|
+
check_2 => { checked: @data[:check2] },
|
265
|
+
check_3 => { checked: @data[:check3] },
|
266
|
+
radio_1 => { selected: @data[:radio1] },
|
267
|
+
radio_2 => { selected: @data[:radio2] },
|
268
|
+
radio_3 => { selected: @data[:radio3] },
|
269
|
+
multi_select => { selected: @data[:multi_select] },
|
270
|
+
drop_down_select => { selected: @data[:drop_select] }
|
271
|
+
}
|
272
|
+
verify_ui_states(ui)
|
273
|
+
end
|
274
|
+
|
275
|
+
def perform_action(action)
|
276
|
+
case action
|
277
|
+
when :submit
|
278
|
+
submit_button.click
|
279
|
+
when :cancel
|
280
|
+
cancel_button.click
|
281
|
+
else
|
282
|
+
raise "#{action} is not a valid selector"
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
def verify_tab_order
|
287
|
+
order = case Environ.browser
|
288
|
+
when :safari
|
289
|
+
safari_tab_order
|
290
|
+
when :firefox
|
291
|
+
firefox_order
|
292
|
+
else
|
293
|
+
tab_order
|
294
|
+
end
|
295
|
+
verify_focus_order(order)
|
296
|
+
end
|
297
|
+
end
|
@@ -0,0 +1,53 @@
|
|
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
|
+
ranges slider: "//input[@id='slider']"
|
16
|
+
filefields 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
|
+
links link_1: "//a[@id='link1']",
|
28
|
+
link_2: "//a[@id='link2']",
|
29
|
+
link_3: "//a[@id='link3']"
|
30
|
+
tables static_table: "//table[@id='table']"
|
31
|
+
images image_1: "//img[@id='image1']",
|
32
|
+
image_2: "//img[@id='image2']",
|
33
|
+
image_3: "//img[@id='image3']"
|
34
|
+
buttons cancel_button: "//input[@id='cancel']",
|
35
|
+
submit_button: "//input[@id='submit']"
|
36
|
+
labels header_label: '//h2',
|
37
|
+
username_label: "//label[@for='username']",
|
38
|
+
password_label: "//label[@for='password']",
|
39
|
+
max_length_label: "//label[@for='maxlength']",
|
40
|
+
read_only_label: "//label[@for='readonly']",
|
41
|
+
number_label: "//label[@for='number-field']",
|
42
|
+
color_label: "//label[@for='color-picker']",
|
43
|
+
slider_label: "//label[@for='slider']",
|
44
|
+
comments_label: "//label[@for='comments']",
|
45
|
+
filename_label: "//label[@for='filename']",
|
46
|
+
checkboxes_label: "//label[@id='checkboxes']",
|
47
|
+
radios_label: "//label[@id='radios']",
|
48
|
+
multiselect_label: "//label[@for='multipleselect']",
|
49
|
+
dropdown_label: "//label[@for='dropdown']",
|
50
|
+
link_label: "//label[@id='links']",
|
51
|
+
table_label: "//label[@for='table']",
|
52
|
+
images_label: "//label[@id='images']"
|
53
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# Page Object class definition for Custom Controls page with CSS locators
|
2
|
+
|
3
|
+
class CustomControlsPage < BaseTestPage
|
4
|
+
trait(:page_name) { 'Custom Controls' }
|
5
|
+
trait(:page_locator) { 'div.custom-controls-page-body' }
|
6
|
+
trait(:page_url) { '/custom_controls_page.html' }
|
7
|
+
trait(:navigator) { header_nav.open_custom_controls_page }
|
8
|
+
|
9
|
+
def verify_page_ui
|
10
|
+
ui = {
|
11
|
+
self => { exists: true, secure: false, title: 'Custom Controls Page' },
|
12
|
+
header_label => { visible: true, caption: 'Custom Controls Page' }
|
13
|
+
}
|
14
|
+
verify_ui_states(ui)
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# Page Object class definition for Indexed Sections page with CSS locators
|
2
|
+
|
3
|
+
class IndexedSectionsPage < BaseTestPage
|
4
|
+
trait(:page_name) { 'Indexed Sections' }
|
5
|
+
trait(:page_locator) { 'div.indexed-sections-page-body' }
|
6
|
+
trait(:page_url) { '/indexed_sections_page.html' }
|
7
|
+
trait(:navigator) { header_nav.open_indexed_sections_page }
|
8
|
+
|
9
|
+
def verify_page_ui
|
10
|
+
ui = {
|
11
|
+
self => { exists: true, secure: false, title: 'Indexed Sections Page' },
|
12
|
+
header_label => { visible: true, caption: 'Indexed Sections Page' }
|
13
|
+
}
|
14
|
+
verify_ui_states(ui)
|
15
|
+
end
|
16
|
+
end
|