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.
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
@@ -49,7 +49,7 @@ module TestCentricity
49
49
  context = case browser.downcase.to_sym
50
50
  when :appium
51
51
  initialize_appium
52
- 'mobile device emulator'
52
+ 'Appium'
53
53
  when :browserstack
54
54
  initialize_browserstack
55
55
  'Browserstack cloud service'
@@ -138,7 +138,6 @@ module TestCentricity
138
138
  Environ.device_orientation = ENV['ORIENTATION'] if ENV['ORIENTATION']
139
139
  Capybara.default_driver = :appium
140
140
  Environ.driver = :appium
141
- @endpoint = 'http://localhost:4723/wd/hub' if @endpoint.nil?
142
141
  desired_capabilities = {
143
142
  platformName: Environ.device_os,
144
143
  platformVersion: Environ.device_os_version,
@@ -190,14 +189,13 @@ module TestCentricity
190
189
  desired_capabilities[:systemPort] = ENV['SYSTEM_PORT'] if ENV['SYSTEM_PORT']
191
190
  end
192
191
 
193
- unless @capabilities.nil?
194
- desired_capabilities = @capabilities
195
- end
192
+ desired_capabilities = @capabilities unless @capabilities.nil?
193
+ # specify endpoint url
194
+ @endpoint = 'http://localhost:4723/wd/hub' if @endpoint.nil?
196
195
 
197
- Capybara.register_driver :appium do |app|
198
- appium_lib_options = { server_url: @endpoint }
196
+ Capybara.register_driver(:appium) do |app|
199
197
  all_options = {
200
- appium_lib: appium_lib_options,
198
+ appium_lib: { server_url: @endpoint },
201
199
  caps: desired_capabilities
202
200
  }
203
201
  Appium::Capybara::Driver.new(app, all_options)
@@ -233,63 +231,18 @@ module TestCentricity
233
231
  when :safari, :ie
234
232
  Capybara::Selenium::Driver.new(app, browser: browser)
235
233
  when :firefox, :firefox_headless
236
- profile = Selenium::WebDriver::Firefox::Profile.new
237
- profile['browser.download.dir'] = @downloads_path
238
- profile['browser.download.folderList'] = 2
239
- profile['browser.download.manager.showWhenStarting'] = false
240
- profile['browser.download.manager.closeWhenDone'] = true
241
- profile['browser.download.manager.showAlertOnComplete'] = false
242
- profile['browser.download.manager.alertOnEXEOpen'] = false
243
- profile['browser.download.manager.useWindow'] = false
244
- profile['browser.helperApps.alwaysAsk.force'] = false
245
- profile['pdfjs.disabled'] = true
246
-
247
- mime_types = ENV['MIME_TYPES'] || 'images/jpeg, application/pdf, application/octet-stream'
248
- profile['browser.helperApps.neverAsk.saveToDisk'] = mime_types
249
-
250
- profile['intl.accept_languages'] = ENV['LOCALE'] if ENV['LOCALE']
251
- options = Selenium::WebDriver::Firefox::Options.new(profile: profile)
252
- options.args << '--headless' if browser == :firefox_headless
234
+ options = firefox_options(browser)
253
235
  Capybara::Selenium::Driver.new(app, browser: :firefox, capabilities: [options])
254
236
  when :chrome, :chrome_headless
255
- options = Selenium::WebDriver::Chrome::Options.new(options: {'excludeSwitches' => ['enable-automation']})
256
- prefs = {
257
- prompt_for_download: false,
258
- directory_upgrade: true,
259
- default_directory: @downloads_path
260
- }
261
- options.add_preference(:download, prefs)
262
- options.add_argument('--disable-dev-shm-usage')
263
- options.add_argument("--lang=#{ENV['LOCALE']}") if ENV['LOCALE']
264
- if browser == :chrome_headless
265
- options.add_argument('--headless')
266
- options.add_argument('--disable-gpu')
267
- options.add_argument('--no-sandbox')
268
- end
269
-
237
+ options = chrome_edge_options(browser)
270
238
  Capybara::Selenium::Driver.new(app, browser: :chrome, capabilities: [options])
271
239
  when :edge, :edge_headless
272
- options = Selenium::WebDriver::Edge::Options.new(options: {'excludeSwitches' => ['enable-automation']})
273
- prefs = {
274
- prompt_for_download: false,
275
- directory_upgrade: true,
276
- default_directory: @downloads_path
277
- }
278
- options.add_preference(:download, prefs)
279
- options.add_argument('--disable-dev-shm-usage')
280
- options.add_argument("--lang=#{ENV['LOCALE']}") if ENV['LOCALE']
281
- if browser == :edge_headless
282
- options.add_argument('--headless')
283
- options.add_argument('--disable-gpu')
284
- options.add_argument('--no-sandbox')
285
- end
286
-
240
+ options = chrome_edge_options(browser)
287
241
  Capybara::Selenium::Driver.new(app, browser: :edge, capabilities: [options])
288
242
  else
289
243
  if ENV['HOST_BROWSER'] && ENV['HOST_BROWSER'].downcase.to_sym == :chrome
290
244
  user_agent = Browsers.mobile_device_agent(ENV['WEB_BROWSER'])
291
245
  options = Selenium::WebDriver::Chrome::Options.new(options: {'excludeSwitches' => ['enable-automation']})
292
- options.add_argument('--disable-infobars')
293
246
  options.add_argument('--disable-dev-shm-usage')
294
247
  options.add_argument("--user-agent='#{user_agent}'")
295
248
  options.add_argument("--lang=#{ENV['LOCALE']}") if ENV['LOCALE']
@@ -452,74 +405,31 @@ module TestCentricity
452
405
  Environ.grid = :selenium_grid
453
406
  browser = ENV['WEB_BROWSER'].downcase.to_sym
454
407
  @endpoint = ENV['REMOTE_ENDPOINT'] || 'http://127.0.0.1:4444/wd/hub' if @endpoint.nil?
455
- Capybara.register_driver :remote_browser do |app|
456
- case browser
457
- when :safari
458
- options = Selenium::WebDriver::Safari::Options.new
459
- when :ie
460
- options = Selenium::WebDriver::IE::Options.new
461
- when :firefox, :firefox_headless
462
- profile = Selenium::WebDriver::Firefox::Profile.new
463
- profile['browser.download.dir'] = @downloads_path
464
- profile['browser.download.folderList'] = 2
465
- profile['browser.download.manager.showWhenStarting'] = false
466
- profile['browser.download.manager.closeWhenDone'] = true
467
- profile['browser.download.manager.showAlertOnComplete'] = false
468
- profile['browser.download.manager.alertOnEXEOpen'] = false
469
- profile['browser.download.manager.useWindow'] = false
470
- profile['browser.helperApps.alwaysAsk.force'] = false
471
- profile['pdfjs.disabled'] = true
472
-
473
- mime_types = ENV['MIME_TYPES'] || 'images/jpeg, application/pdf, application/octet-stream'
474
- profile['browser.helperApps.neverAsk.saveToDisk'] = mime_types
475
-
476
- profile['intl.accept_languages'] = ENV['LOCALE'] if ENV['LOCALE']
477
- options = Selenium::WebDriver::Firefox::Options.new(profile: profile)
478
- options.args << '--headless' if browser == :firefox_headless
479
- when :chrome, :chrome_headless
408
+
409
+ case browser
410
+ when :safari
411
+ options = Selenium::WebDriver::Safari::Options.new
412
+ when :ie
413
+ options = Selenium::WebDriver::IE::Options.new
414
+ when :firefox, :firefox_headless
415
+ options = firefox_options(browser)
416
+ when :chrome, :chrome_headless, :edge, :edge_headless
417
+ options = chrome_edge_options(browser)
418
+ else
419
+ if ENV['HOST_BROWSER'] && ENV['HOST_BROWSER'].downcase.to_sym == :chrome
420
+ Environ.platform = :mobile
421
+ Environ.device_name = Browsers.mobile_device_name(ENV['WEB_BROWSER'])
422
+ user_agent = Browsers.mobile_device_agent(ENV['WEB_BROWSER'])
480
423
  options = Selenium::WebDriver::Chrome::Options.new(options: {'excludeSwitches' => ['enable-automation']})
481
- prefs = {
482
- prompt_for_download: false,
483
- directory_upgrade: true,
484
- default_directory: @downloads_path
485
- }
486
- options.add_preference(:download, prefs)
487
- options.add_argument('--disable-dev-shm-usage')
488
- options.add_argument("--lang=#{ENV['LOCALE']}") if ENV['LOCALE']
489
- if browser == :chrome_headless
490
- options.add_argument('--headless')
491
- options.add_argument('--disable-gpu')
492
- options.add_argument('--no-sandbox')
493
- end
494
- when :edge, :edge_headless
495
- options = Selenium::WebDriver::Edge::Options.new(options: {'excludeSwitches' => ['enable-automation']})
496
- prefs = {
497
- prompt_for_download: false,
498
- directory_upgrade: true,
499
- default_directory: @downloads_path
500
- }
501
- options.add_preference(:download, prefs)
502
424
  options.add_argument('--disable-dev-shm-usage')
425
+ options.add_argument("--user-agent='#{user_agent}'")
503
426
  options.add_argument("--lang=#{ENV['LOCALE']}") if ENV['LOCALE']
504
- if browser == :edge_headless
505
- options.add_argument('--headless')
506
- options.add_argument('--disable-gpu')
507
- options.add_argument('--no-sandbox')
508
- end
509
427
  else
510
- if ENV['HOST_BROWSER'] && ENV['HOST_BROWSER'].downcase.to_sym == :chrome
511
- Environ.platform = :mobile
512
- Environ.device_name = Browsers.mobile_device_name(ENV['WEB_BROWSER'])
513
- user_agent = Browsers.mobile_device_agent(ENV['WEB_BROWSER'])
514
- options = Selenium::WebDriver::Chrome::Options.new(options: {'excludeSwitches' => ['enable-automation']})
515
- options.add_argument('--disable-infobars')
516
- options.add_argument('--disable-dev-shm-usage')
517
- options.add_argument("--user-agent='#{user_agent}'")
518
- options.add_argument("--lang=#{ENV['LOCALE']}") if ENV['LOCALE']
519
- else
520
- raise "Requested browser '#{browser}' is not supported on Selenium Grid"
521
- end
428
+ raise "Requested browser '#{browser}' is not supported on Selenium Grid"
522
429
  end
430
+ end
431
+
432
+ Capybara.register_driver :remote_browser do |app|
523
433
  Capybara::Selenium::Driver.new(app,
524
434
  browser: :remote,
525
435
  url: @endpoint,
@@ -645,6 +555,50 @@ module TestCentricity
645
555
  config_file_uploads unless ENV['TB_PLATFORM']
646
556
  end
647
557
 
558
+ def self.chrome_edge_options(browser)
559
+ options = case browser
560
+ when :chrome, :chrome_headless
561
+ Selenium::WebDriver::Chrome::Options.new(options: {'excludeSwitches' => ['enable-automation']})
562
+ when :edge, :edge_headless
563
+ Selenium::WebDriver::Edge::Options.new(options: {'excludeSwitches' => ['enable-automation']})
564
+ end
565
+ prefs = {
566
+ prompt_for_download: false,
567
+ directory_upgrade: true,
568
+ default_directory: @downloads_path
569
+ }
570
+ options.add_preference(:download, prefs)
571
+ options.add_argument('--disable-dev-shm-usage')
572
+ options.add_argument("--lang=#{ENV['LOCALE']}") if ENV['LOCALE']
573
+ if browser == :chrome_headless || browser == :edge_headless
574
+ options.add_argument('--headless')
575
+ options.add_argument('--disable-gpu')
576
+ options.add_argument('--no-sandbox')
577
+ end
578
+ options
579
+ end
580
+
581
+ def self.firefox_options(browser)
582
+ profile = Selenium::WebDriver::Firefox::Profile.new
583
+ profile['browser.download.dir'] = @downloads_path
584
+ profile['browser.download.folderList'] = 2
585
+ profile['browser.download.manager.showWhenStarting'] = false
586
+ profile['browser.download.manager.closeWhenDone'] = true
587
+ profile['browser.download.manager.showAlertOnComplete'] = false
588
+ profile['browser.download.manager.alertOnEXEOpen'] = false
589
+ profile['browser.download.manager.useWindow'] = false
590
+ profile['browser.helperApps.alwaysAsk.force'] = false
591
+ profile['pdfjs.disabled'] = true
592
+
593
+ mime_types = ENV['MIME_TYPES'] || 'images/jpeg, application/pdf, application/octet-stream'
594
+ profile['browser.helperApps.neverAsk.saveToDisk'] = mime_types
595
+
596
+ profile['intl.accept_languages'] = ENV['LOCALE'] if ENV['LOCALE']
597
+ options = Selenium::WebDriver::Firefox::Options.new(profile: profile)
598
+ options.args << '--headless' if browser == :firefox_headless
599
+ options
600
+ end
601
+
648
602
  def self.test_context_message
649
603
  context_message = if ENV['TEST_CONTEXT']
650
604
  "#{Environ.test_environment.to_s.upcase} - #{ENV['TEST_CONTEXT']}"
@@ -662,7 +616,10 @@ module TestCentricity
662
616
  def self.register_remote_driver(driver, browser, options)
663
617
  Capybara.register_driver driver do |app|
664
618
  capabilities = Selenium::WebDriver::Remote::Capabilities.send(browser.gsub(/\s+/, '_').downcase.to_sym, options)
665
- Capybara::Selenium::Driver.new(app, browser: :remote, url: @endpoint, capabilities: capabilities)
619
+ Capybara::Selenium::Driver.new(app,
620
+ browser: :remote,
621
+ url: @endpoint,
622
+ capabilities: capabilities)
666
623
  end
667
624
 
668
625
  Environ.browser = browser
@@ -112,11 +112,10 @@ module TestCentricity
112
112
  object_not_found_exception(obj, 'Checkbox')
113
113
  invalid_object_type_exception(obj, 'checkbox')
114
114
  if @proxy.nil?
115
- if obj.native.attribute('ot') == 'JCheckBox'
116
- expected = state.to_bool
117
- obj.click unless expected == obj.checked?
118
- else
115
+ begin
119
116
  obj.set(state)
117
+ rescue
118
+ obj.click unless state == obj.checked?
120
119
  end
121
120
  else
122
121
  page.find(:css, @proxy).click unless state == obj.checked?
@@ -125,7 +125,7 @@ module TestCentricity
125
125
  def current_time
126
126
  obj, = find_element(visible = :all)
127
127
  object_not_found_exception(obj, @type)
128
- obj.native.attribute('currentTime').to_f
128
+ obj.native.attribute('currentTime').to_f.round(2)
129
129
  end
130
130
 
131
131
  # Return media defaultPlaybackRate property
@@ -137,7 +137,7 @@ module TestCentricity
137
137
  def default_playback_rate
138
138
  obj, = find_element(visible = :all)
139
139
  object_not_found_exception(obj, @type)
140
- obj.native.attribute('defaultPlaybackRate')
140
+ obj.native.attribute('defaultPlaybackRate').to_f
141
141
  end
142
142
 
143
143
  # Return media duration property
@@ -149,7 +149,7 @@ module TestCentricity
149
149
  def duration
150
150
  obj, = find_element(visible = :all)
151
151
  object_not_found_exception(obj, @type)
152
- obj.native.attribute('duration').to_f
152
+ obj.native.attribute('duration').to_f.round(2)
153
153
  end
154
154
 
155
155
  # Return media playbackRate property
@@ -161,7 +161,7 @@ module TestCentricity
161
161
  def playback_rate
162
162
  obj, = find_element(visible = :all)
163
163
  object_not_found_exception(obj, @type)
164
- obj.native.attribute('playbackRate')
164
+ obj.native.attribute('playbackRate').to_f
165
165
  end
166
166
 
167
167
  # Return media readyState property
@@ -247,6 +247,52 @@ module TestCentricity
247
247
  page.execute_script('arguments[0].pause()', obj)
248
248
  end
249
249
 
250
+ # Mute the media's audio
251
+ #
252
+ # @example
253
+ # media_player.mute
254
+ #
255
+ def mute
256
+ obj, = find_element(visible = :all)
257
+ object_not_found_exception(obj, @type)
258
+ page.execute_script('arguments[0].muted = true;', obj)
259
+ end
260
+
261
+ # Unmute the media's audio
262
+ #
263
+ # @example
264
+ # media_player.unmute
265
+ #
266
+ def unmute
267
+ obj, = find_element(visible = :all)
268
+ object_not_found_exception(obj, @type)
269
+ page.execute_script('arguments[0].muted = false;', obj)
270
+ end
271
+
272
+ # Set the media playbackRate property
273
+ #
274
+ # @param value [Float]
275
+ # @example
276
+ # media_player.playback_rate = 1.5
277
+ #
278
+ def playback_rate=(value)
279
+ obj, = find_element(visible = :all)
280
+ object_not_found_exception(obj, @type)
281
+ page.execute_script('arguments[0].playbackRate = arguments[1]', obj, value)
282
+ end
283
+
284
+ # Set the media volume property
285
+ #
286
+ # @param value [Float] between 0 and 1
287
+ # @example
288
+ # media_player.volume = 0.5
289
+ #
290
+ def volume=(value)
291
+ obj, = find_element(visible = :all)
292
+ object_not_found_exception(obj, @type)
293
+ page.execute_script('arguments[0].volume = arguments[1]', obj, value)
294
+ end
295
+
250
296
  # Return media crossorigin property
251
297
  #
252
298
  # @return crossorigin value
@@ -101,7 +101,11 @@ module TestCentricity
101
101
  object_not_found_exception(obj, 'Radio')
102
102
  invalid_object_type_exception(obj, 'radio')
103
103
  if @proxy.nil?
104
- obj.set(state)
104
+ begin
105
+ obj.set(state)
106
+ rescue
107
+ obj.click unless state == obj.checked?
108
+ end
105
109
  else
106
110
  page.find(:css, @proxy).click unless state == obj.checked?
107
111
  end
@@ -246,13 +246,24 @@ module TestCentricity
246
246
  def get_selected_option
247
247
  @base_object, = find_element
248
248
  object_not_found_exception(@base_object, nil)
249
- if @base_object.first(:css, @list_item, minimum: 0)
250
- @base_object.first(:css, @selected_item).text
251
- elsif @base_object.first(:css, @selected_item, minimum: 0)
252
- @base_object.first(:css, @selected_item).text
253
- else
254
- @base_object.first('option[selected]', visible: :all).text
255
- end
249
+ trigger_list unless @options_list.nil?
250
+ selection = if @base_object.first(:css, @list_item, minimum: 0, wait: 1, visible: :all)
251
+ @base_object.first(:css, @selected_item, wait: 1, visible: :all).text
252
+ elsif @base_object.first(:css, @selected_item, minimum: 0, wait: 1, visible: :all)
253
+ @base_object.first(:css, @selected_item, visible: :all).text
254
+ elsif @base_object.first('option[selected]', minimum: 0, wait: 1, visible: :all)
255
+ @base_object.first('option[selected]', wait: 1, visible: :all).text
256
+ else
257
+ index = get_attribute(:selectedIndex).to_i
258
+ if index >= 0
259
+ options = get_options
260
+ options[index]
261
+ else
262
+ ''
263
+ end
264
+ end
265
+ trigger_list unless @options_list.nil?
266
+ selection
256
267
  end
257
268
 
258
269
  alias selected? get_selected_option
@@ -264,6 +264,19 @@ module TestCentricity
264
264
  obj.disabled?
265
265
  end
266
266
 
267
+ # Is UI object's required attribute set?
268
+ #
269
+ # @return [Boolean]
270
+ # @example
271
+ # first_name_field.required?
272
+ #
273
+ def required?
274
+ obj, type = find_element
275
+ object_not_found_exception(obj, type)
276
+ state = get_attribute(:required)
277
+ state.boolean? ? state : state == 'true'
278
+ end
279
+
267
280
  # Is UI object obscured (not currently in viewport and not clickable)?
268
281
  #
269
282
  # @return [Boolean]
data/reports/.keep ADDED
@@ -0,0 +1 @@
1
+ Placeholder file to allow the reports folder to be saved to repository. This folder is required for Jenkins test jobs using the Cucumber Reporting plug-in.