testcentricity_web 4.1.4 → 4.1.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +18 -0
  3. data/.simplecov +5 -0
  4. data/CHANGELOG.md +43 -1
  5. data/Gemfile.lock +60 -2
  6. data/README.md +166 -21
  7. data/Rakefile +60 -1
  8. data/config/cucumber.yml +163 -0
  9. data/config/test_data/data.json +12 -0
  10. data/config/test_data/data.xls +0 -0
  11. data/config/test_data/data.yml +12 -0
  12. data/docker-compose-v3.yml +48 -0
  13. data/features/basic_test_page_css.feature +35 -0
  14. data/features/basic_test_page_xpath.feature +27 -0
  15. data/features/media_players.feature +87 -0
  16. data/features/step_definitions/generic_steps.rb.rb +44 -0
  17. data/features/step_definitions/media_steps.rb +30 -0
  18. data/features/support/env.rb +50 -0
  19. data/features/support/hooks.rb +245 -0
  20. data/features/support/pages/base_test_page.rb +11 -0
  21. data/features/support/pages/basic_css_test_page.rb +52 -0
  22. data/features/support/pages/basic_test_page.rb +297 -0
  23. data/features/support/pages/basic_xpath_test_page.rb +53 -0
  24. data/features/support/pages/custom_controls_page.rb +16 -0
  25. data/features/support/pages/indexed_sections_page.rb +16 -0
  26. data/features/support/pages/media_test_page.rb +195 -0
  27. data/features/support/sections/header_nav.rb +28 -0
  28. data/features/support/world_data.rb +12 -0
  29. data/features/support/world_pages.rb +18 -0
  30. data/lib/testcentricity_web/data_objects/environment.rb +16 -0
  31. data/lib/testcentricity_web/version.rb +1 -1
  32. data/lib/testcentricity_web/web_core/page_object.rb +8 -8
  33. data/lib/testcentricity_web/web_core/page_objects_helper.rb +41 -8
  34. data/lib/testcentricity_web/web_core/page_section.rb +1 -16
  35. data/lib/testcentricity_web/web_core/webdriver_helper.rb +77 -120
  36. data/lib/testcentricity_web/web_elements/checkbox.rb +3 -4
  37. data/lib/testcentricity_web/web_elements/media.rb +50 -4
  38. data/lib/testcentricity_web/web_elements/radio.rb +5 -1
  39. data/lib/testcentricity_web/web_elements/select_list.rb +18 -7
  40. data/lib/testcentricity_web/web_elements/ui_elements_helper.rb +13 -0
  41. data/reports/.keep +1 -0
  42. data/test_site/basic_test_page.html +290 -0
  43. data/test_site/custom_controls_page.html +58 -0
  44. data/test_site/images/Granny.jpg +0 -0
  45. data/test_site/images/Wilder.jpg +0 -0
  46. data/test_site/images/You_Betcha.jpg +0 -0
  47. data/test_site/indexed_sections_page.html +58 -0
  48. data/test_site/media/MIB2-subtitles-pt-BR.vtt +49 -0
  49. data/test_site/media/MIB2.mp4 +0 -0
  50. data/test_site/media/MP4_small.mp4 +0 -0
  51. data/test_site/media/MPS_sample.mp3 +0 -0
  52. data/test_site/media_page.html +86 -0
  53. data/testcentricity_web.gemspec +5 -0
  54. metadata +125 -4
  55. 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,11 @@
1
+ # Page Object class definition for Base Test page
2
+
3
+ class BaseTestPage < TestCentricity::PageObject
4
+ # Base Test page UI elements
5
+ label :header_label, 'h2'
6
+ sections header_nav: NavHeader
7
+
8
+ def navigate_to
9
+ navigator
10
+ end
11
+ 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