testcentricity_web 4.1.5 → 4.1.8

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 (67) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +18 -0
  3. data/.simplecov +9 -0
  4. data/CHANGELOG.md +44 -0
  5. data/Gemfile.lock +60 -2
  6. data/README.md +17 -7
  7. data/Rakefile +86 -1
  8. data/config/cucumber.yml +170 -0
  9. data/config/test_data/LOCAL_data.json +15 -0
  10. data/config/test_data/LOCAL_data.xls +0 -0
  11. data/config/test_data/LOCAL_data.yml +11 -0
  12. data/config/test_data/data.json +25 -0
  13. data/config/test_data/data.xls +0 -0
  14. data/config/test_data/data.yml +20 -0
  15. data/docker-compose-v3.yml +48 -0
  16. data/features/basic_form_page_css.feature +39 -0
  17. data/features/basic_form_page_xpath.feature +26 -0
  18. data/features/media_players.feature +84 -0
  19. data/features/step_definitions/generic_steps.rb.rb +109 -0
  20. data/features/step_definitions/media_steps.rb +30 -0
  21. data/features/support/data/form_data.rb +43 -0
  22. data/features/support/env.rb +50 -0
  23. data/features/support/hooks.rb +265 -0
  24. data/features/support/pages/base_test_page.rb +22 -0
  25. data/features/support/pages/basic_css_form_page.rb +52 -0
  26. data/features/support/pages/basic_form_page.rb +393 -0
  27. data/features/support/pages/basic_xpath_form_page.rb +53 -0
  28. data/features/support/pages/custom_controls_page.rb +13 -0
  29. data/features/support/pages/indexed_sections_page.rb +13 -0
  30. data/features/support/pages/media_test_page.rb +208 -0
  31. data/features/support/sections/header_nav.rb +39 -0
  32. data/features/support/world_data.rb +12 -0
  33. data/features/support/world_pages.rb +18 -0
  34. data/lib/testcentricity_web/appium_server.rb +5 -0
  35. data/lib/testcentricity_web/data_objects/data_objects_helper.rb +7 -0
  36. data/lib/testcentricity_web/data_objects/environment.rb +18 -0
  37. data/lib/testcentricity_web/data_objects/excel_helper.rb +60 -59
  38. data/lib/testcentricity_web/version.rb +1 -1
  39. data/lib/testcentricity_web/web_core/drag_drop_helper.rb +4 -0
  40. data/lib/testcentricity_web/web_core/page_object.rb +8 -8
  41. data/lib/testcentricity_web/web_core/page_objects_helper.rb +43 -8
  42. data/lib/testcentricity_web/web_core/page_section.rb +1 -16
  43. data/lib/testcentricity_web/web_core/webdriver_helper.rb +16 -0
  44. data/lib/testcentricity_web/web_elements/checkbox.rb +3 -4
  45. data/lib/testcentricity_web/web_elements/file_field.rb +9 -5
  46. data/lib/testcentricity_web/web_elements/image.rb +2 -1
  47. data/lib/testcentricity_web/web_elements/media.rb +45 -11
  48. data/lib/testcentricity_web/web_elements/radio.rb +5 -1
  49. data/lib/testcentricity_web/web_elements/select_list.rb +11 -3
  50. data/lib/testcentricity_web/web_elements/ui_elements_helper.rb +33 -7
  51. data/lib/testcentricity_web/web_elements/video.rb +2 -2
  52. data/reports/.keep +1 -0
  53. data/test_site/basic_test_page.html +290 -0
  54. data/test_site/custom_controls_page.html +58 -0
  55. data/test_site/images/Granny.jpg +0 -0
  56. data/test_site/images/Wilder.jpg +0 -0
  57. data/test_site/images/You_Betcha.jpg +0 -0
  58. data/test_site/indexed_sections_page.html +58 -0
  59. data/test_site/media/MIB2-subtitles-pt-BR.vtt +49 -0
  60. data/test_site/media/MIB2.mp4 +0 -0
  61. data/test_site/media/MP4_small.mp4 +0 -0
  62. data/test_site/media/MPS_sample.mp3 +0 -0
  63. data/test_site/media/count_and_bars.mp4 +0 -0
  64. data/test_site/media_page.html +86 -0
  65. data/testcentricity_web.gemspec +5 -0
  66. metadata +131 -4
  67. data/test_site/test_page.html +0 -11
@@ -0,0 +1,48 @@
1
+ # To execute this docker-compose yml file use `docker-compose -f docker-compose-v3.yml up`
2
+ # Add the `-d` flag at the end for detached execution
3
+ # To stop the execution, hit Ctrl+C, and then `docker-compose -f docker-compose-v3.yml down`
4
+ version: "3"
5
+ services:
6
+ chrome:
7
+ image: selenium/node-chrome:4.1.2-20220217
8
+ shm_size: 2gb
9
+ depends_on:
10
+ - selenium-hub
11
+ environment:
12
+ - SE_EVENT_BUS_HOST=selenium-hub
13
+ - SE_EVENT_BUS_PUBLISH_PORT=4442
14
+ - SE_EVENT_BUS_SUBSCRIBE_PORT=4443
15
+ - SE_NODE_MAX_SESSIONS=4
16
+ - SE_NODE_OVERRIDE_MAX_SESSIONS=true
17
+
18
+ edge:
19
+ image: selenium/node-edge:4.1.2-20220217
20
+ shm_size: 2gb
21
+ depends_on:
22
+ - selenium-hub
23
+ environment:
24
+ - SE_EVENT_BUS_HOST=selenium-hub
25
+ - SE_EVENT_BUS_PUBLISH_PORT=4442
26
+ - SE_EVENT_BUS_SUBSCRIBE_PORT=4443
27
+ - SE_NODE_MAX_SESSIONS=4
28
+ - SE_NODE_OVERRIDE_MAX_SESSIONS=true
29
+
30
+ firefox:
31
+ image: selenium/node-firefox:4.1.2-20220217
32
+ shm_size: 2gb
33
+ depends_on:
34
+ - selenium-hub
35
+ environment:
36
+ - SE_EVENT_BUS_HOST=selenium-hub
37
+ - SE_EVENT_BUS_PUBLISH_PORT=4442
38
+ - SE_EVENT_BUS_SUBSCRIBE_PORT=4443
39
+ - SE_NODE_MAX_SESSIONS=4
40
+ - SE_NODE_OVERRIDE_MAX_SESSIONS=true
41
+
42
+ selenium-hub:
43
+ image: selenium/hub:4.1.2-20220217
44
+ container_name: selenium-hub
45
+ ports:
46
+ - "4442:4442"
47
+ - "4443:4443"
48
+ - "4444:4444"
@@ -0,0 +1,39 @@
1
+ Feature: Basic HTML Form Test Page using CSS locators
2
+ In order to ensure comprehensive support for HTML UI elements and forms
3
+ As a developer of the TestCentricity web gem
4
+ I expect to validate the interaction and verification capabilities of typical HTML form UI elements
5
+
6
+
7
+ Background:
8
+ Given I am on the Basic CSS Form page
9
+
10
+
11
+ Scenario: Validate verify_ui_states method and associated object state verification methods
12
+ Then I expect the Basic CSS Form page to be correctly displayed
13
+
14
+
15
+ @!mobile @!firefox_headless
16
+ Scenario: Validate verify_focus_order method
17
+ Then I expect the tab order to be correct
18
+
19
+
20
+ Scenario: Validate populate_data_fields method and associated object action methods
21
+ When I populate the form fields
22
+ Then I expect the form fields to be correctly populated
23
+ When I cancel my changes
24
+ Then I expect the Basic CSS Form page to be correctly displayed
25
+
26
+
27
+ Scenario Outline: Verify functionality of navigation tabs and browser back/forward
28
+ When I click the <target_page> navigation tab
29
+ Then I expect the <target_page> page to be correctly displayed
30
+ When I navigate back
31
+ Then I should be on the Basic CSS Form page
32
+ When I navigate forward
33
+ Then I should be on the <target_page> page
34
+
35
+ Examples:
36
+ |target_page |
37
+ |Media Test |
38
+ |Indexed Sections |
39
+ |Custom Controls |
@@ -0,0 +1,26 @@
1
+ @!grid @!mobile @!headless
2
+
3
+
4
+ Feature: Basic HTML Form Test Page using Xpath locators
5
+ In order to ensure comprehensive support for HTML UI elements and forms
6
+ As a developer of the TestCentricity web gem
7
+ I expect to validate the interaction and verification capabilities of typical HTML form UI elements
8
+
9
+
10
+ Background:
11
+ Given I am on the Basic Xpath Form page
12
+
13
+
14
+ Scenario: Validate verify_ui_states method and associated object state verification methods
15
+ Then I expect the Basic Xpath Form page to be correctly displayed
16
+
17
+
18
+ Scenario: Validate verify_focus_order method
19
+ Then I expect the tab order to be correct
20
+
21
+
22
+ Scenario: Validate populate_data_fields method and associated object action methods
23
+ When I populate the form fields
24
+ Then I expect the form fields to be correctly populated
25
+ When I cancel my changes
26
+ Then I expect the Basic Xpath Form page to be correctly displayed
@@ -0,0 +1,84 @@
1
+ Feature: HTML5 Audio/Video Test Page using CSS locators
2
+ In order to ensure comprehensive support for HTML5 Audio and Video media elements
3
+ As a developer of the TestCentricity web gem
4
+ I expect to validate the interaction and verification capabilities of media UI elements
5
+
6
+
7
+ Background:
8
+ Given I am on the Media Test page
9
+
10
+
11
+ Scenario: Verify video player play and pause controls
12
+ When I play the video media
13
+ Then the video should be playing
14
+ When I pause the video media
15
+ Then the video should be paused
16
+
17
+
18
+ Scenario: Verify audio player play and pause controls
19
+ When I play the audio media
20
+ Then the audio should be playing
21
+ When I pause the audio media
22
+ Then the audio should be paused
23
+
24
+
25
+ Scenario: Verify video player mute control
26
+ When I mute the video media
27
+ Then the video should be muted
28
+ When I unmute the video media
29
+ Then the video should be unmuted
30
+
31
+
32
+ Scenario: Verify audio player mute control
33
+ When I mute the audio media
34
+ Then the audio should be muted
35
+ When I unmute the audio media
36
+ Then the audio should be unmuted
37
+
38
+
39
+ Scenario: Verify video player volume control
40
+ When I set the volume of the video to .5
41
+ Then the video should have a volume of .5
42
+
43
+
44
+ Scenario: Verify audio player volume control
45
+ When I set the volume of the audio to .5
46
+ Then the audio should have a volume of .5
47
+
48
+
49
+ Scenario: Verify video playback speed settings
50
+ When I play the video with a playback speed of 2x
51
+ Then the video should play at 2x speed
52
+ When I play the video with a playback speed of 0.25x
53
+ Then the video should play at 0.25x speed
54
+ When I play the video with a playback speed of 1.75x
55
+ Then the video should play at 1.75x speed
56
+ When I play the video with a playback speed of 0.5x
57
+ Then the video should play at 0.5x speed
58
+ When I play the video with a playback speed of 1.5x
59
+ Then the video should play at 1.5x speed
60
+ When I play the video with a playback speed of 0.75x
61
+ Then the video should play at 0.75x speed
62
+ When I play the video with a playback speed of 1.25x
63
+ Then the video should play at 1.25x speed
64
+ When I play the video with a playback speed of 1x
65
+ Then the video should play at 1x speed
66
+
67
+
68
+ Scenario: Verify audio playback speed settings
69
+ When I play the audio with a playback speed of 2x
70
+ Then the audio should play at 2x speed
71
+ When I play the audio with a playback speed of 0.25x
72
+ Then the audio should play at 0.25x speed
73
+ When I play the audio with a playback speed of 1.75x
74
+ Then the audio should play at 1.75x speed
75
+ When I play the audio with a playback speed of 0.5x
76
+ Then the audio should play at 0.5x speed
77
+ When I play the audio with a playback speed of 1.5x
78
+ Then the audio should play at 1.5x speed
79
+ When I play the audio with a playback speed of 0.75x
80
+ Then the audio should play at 0.75x speed
81
+ When I play the audio with a playback speed of 1.25x
82
+ Then the audio should play at 1.25x speed
83
+ When I play the audio with a playback speed of 1x
84
+ Then the audio should play at 1x speed
@@ -0,0 +1,109 @@
1
+ include TestCentricity
2
+
3
+
4
+ Given(/^I am (?:on|viewing) the (.*) page$/) do |page_name|
5
+ # find and load the specified target page
6
+ target_page = PageManager.find_page(page_name)
7
+ target_page.load_page
8
+ end
9
+
10
+
11
+ Then(/^I expect the (.*) page to be correctly displayed$/) do |page_name|
12
+ # find and verify that the specified target page is loaded
13
+ target_page = PageManager.find_page(page_name)
14
+ target_page.verify_page_exists
15
+ # verify that target page is correctly displayed
16
+ target_page.verify_page_ui
17
+ end
18
+
19
+
20
+ When(/^I populate the form fields$/) do
21
+ PageManager.current_page.populate_form
22
+ end
23
+
24
+
25
+ Then(/^I expect the form fields to be correctly populated$/) do
26
+ PageManager.current_page.verify_form_data
27
+ end
28
+
29
+
30
+ When(/^I (.*) my changes$/) do | action|
31
+ PageManager.current_page.perform_action(action.downcase.to_sym)
32
+ end
33
+
34
+
35
+ Then(/^I expect the tab order to be correct$/) do
36
+ PageManager.current_page.verify_tab_order
37
+ end
38
+
39
+
40
+ When(/^I click the (.*) navigation (?:tab|link)$/) do |page_name|
41
+ # find and navigate to the specified target page
42
+ target_page = PageManager.find_page(page_name)
43
+ target_page.navigate_to
44
+ end
45
+
46
+
47
+ Then(/^I should (?:see|be on) the (.*) page$/) do |page_name|
48
+ # find and verify that the specified target page is loaded
49
+ target_page = PageManager.find_page(page_name)
50
+ target_page.verify_page_exists
51
+ end
52
+
53
+
54
+ Then(/^I expect the (.*) page to be correctly displayed in a new browser tab$/) do |page_name|
55
+ Browsers.switch_to_new_browser_instance
56
+ Environ.set_external_page(true)
57
+ TestCentricity::WebDriverConnect.initialize_browser_size if Environ.headless
58
+ # find and verify that the specified target page is loaded
59
+ target_page = PageManager.find_page(page_name)
60
+ target_page.verify_page_exists
61
+ # verify that target page is correctly displayed
62
+ target_page.verify_page_ui
63
+ end
64
+
65
+
66
+ When(/^I (?:access|switch to) the new browser tab$/) do
67
+ Browsers.switch_to_new_browser_instance
68
+ end
69
+
70
+
71
+ When(/^I close the current browser window$/) do
72
+ Browsers.close_current_browser_window
73
+ # intercept and accept any JavaScript system or browser modals that may appear
74
+ begin
75
+ page.driver.browser.switch_to.alert.accept
76
+ switch_to_new_browser_instance
77
+ rescue
78
+ end
79
+ end
80
+
81
+
82
+ When(/^I close the previous browser window$/) do
83
+ Browsers.close_old_browser_instance
84
+ end
85
+
86
+
87
+ When(/^I refresh the current page$/) do
88
+ Browsers.refresh_browser unless Environ.driver == :appium
89
+ end
90
+
91
+
92
+ When(/^I navigate back$/) do
93
+ Browsers.navigate_back
94
+ end
95
+
96
+
97
+ When(/^I navigate forward$/) do
98
+ Browsers.navigate_forward
99
+ end
100
+
101
+
102
+ When(/^I delete all cookies$/) do
103
+ Browsers.delete_all_cookies
104
+ end
105
+
106
+
107
+ When(/^I set device orientation to (.*)$/) do |orientation|
108
+ Browsers.set_device_orientation(orientation.downcase.to_sym)
109
+ end
@@ -0,0 +1,30 @@
1
+
2
+
3
+ When(/^I (.*) the (.*) media$/) do |action, media_type|
4
+ media_test_page.perform_action(media_type, action)
5
+ end
6
+
7
+
8
+ Then(/^the (.*) should be (.*)$/) do |media_type, state|
9
+ media_test_page.verify_media_state(media_type, state)
10
+ end
11
+
12
+
13
+ When(/^I play the (.*) with a playback speed of (.*)x$/) do |media_type, rate|
14
+ media_test_page.set_playback_rate(media_type, rate)
15
+ end
16
+
17
+
18
+ Then(/^the (.*) should play at (.*)x speed$/) do |media_type, rate|
19
+ media_test_page.verify_playback_rate(media_type, rate)
20
+ end
21
+
22
+
23
+ When(/^I set the volume of the (.*) to (.*)$/) do |media_type, volume|
24
+ media_test_page.set_volume(media_type, volume)
25
+ end
26
+
27
+
28
+ Then(/^the (.*) should have a volume of (.*)$/) do |media_type, volume|
29
+ media_test_page.verify_volume(media_type, volume)
30
+ end
@@ -0,0 +1,43 @@
1
+ class FormDataSource < TestCentricity::ExcelDataSource
2
+ def read_form_data
3
+ form_data = case ENV['DATA_SOURCE'].downcase.to_sym
4
+ when :excel
5
+ read_excel_row_data('Form_data', 'primary')
6
+ when :yaml, :json
7
+ environs.read('Form_data', 'primary')
8
+ else
9
+ raise "#{ENV['DATA_SOURCE']} is not a valid data source"
10
+ end
11
+ FormData.current = FormData.new(form_data)
12
+ end
13
+
14
+ def map_form_data(form_data)
15
+ FormData.current = FormData.new(form_data)
16
+ end
17
+ end
18
+
19
+
20
+ class FormData < TestCentricity::DataPresenter
21
+ attribute :username, String
22
+ attribute :password, String
23
+ attribute :image_filename, String
24
+ attribute :multi_select, String
25
+ attribute :drop_down_item, String
26
+ attribute :check1, Boolean, default: false
27
+ attribute :check2, Boolean, default: false
28
+ attribute :check3, Boolean, default: false
29
+ attribute :radio_select, Integer
30
+
31
+ def initialize(data)
32
+ @username = data[:username]
33
+ @password = data[:password]
34
+ @image_filename = data[:image_filename]
35
+ @multi_select = data[:multi_select]
36
+ @drop_down_item = data[:drop_down_item]
37
+ @check1 = data[:check1]
38
+ @check2 = data[:check2]
39
+ @check3 = data[:check3]
40
+ @radio_select = data[:radio_select]
41
+ super
42
+ end
43
+ end
@@ -0,0 +1,50 @@
1
+ require 'capybara/cucumber'
2
+ require 'parallel_tests'
3
+ require 'appium_capybara'
4
+ require 'require_all'
5
+ require 'simplecov'
6
+ require 'testcentricity_web'
7
+
8
+ include TestCentricity
9
+
10
+ SimpleCov.command_name("features-#{ENV['WEB_BROWSER']}-#{ENV['SELENIUM']}" + (ENV['TEST_ENV_NUMBER'] || ''))
11
+
12
+ require_relative 'world_data'
13
+ require_relative 'world_pages'
14
+
15
+ require_rel 'data'
16
+ require_rel 'sections'
17
+ require_rel 'pages'
18
+
19
+ $LOAD_PATH << './lib'
20
+
21
+ # set Capybara's default max wait time to 20 seconds
22
+ Capybara.default_max_wait_time = 20
23
+
24
+ # set the default locale and auto load all translations from config/locales/*.rb,yml.
25
+ ENV['LOCALE'] = 'en-US' unless ENV['LOCALE']
26
+ I18n.load_path += Dir['config/locales/*.{rb,yml}']
27
+ I18n.default_locale = ENV['LOCALE']
28
+ I18n.locale = ENV['LOCALE']
29
+ Faker::Config.locale = ENV['LOCALE']
30
+
31
+ # instantiate all data objects and target test environment
32
+ include WorldData
33
+ ENV['DATA_SOURCE'] = 'yaml' unless ENV['DATA_SOURCE']
34
+ environs.find_environ(ENV['TEST_ENVIRONMENT'], ENV['DATA_SOURCE'].downcase.to_sym)
35
+ WorldData.instantiate_data_objects
36
+
37
+ # instantiate all page objects
38
+ include WorldPages
39
+ WorldPages.instantiate_page_objects
40
+
41
+ # establish connection to WebDriver and target web browser
42
+ Webdrivers.cache_time = 86_400
43
+
44
+
45
+ url = if ENV['TEST_ENVIRONMENT'].downcase == 'local'
46
+ "file://#{File.dirname(__FILE__)}/../../test_site"
47
+ else
48
+ Environ.current.app_host
49
+ end
50
+ WebDriverConnect.initialize_web_driver(app_host: url)
@@ -0,0 +1,265 @@
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}' is not executed on mobile devices or simulators."
186
+ skip_this_scenario
187
+ else
188
+ block.call
189
+ end
190
+ end
191
+
192
+
193
+ Around('@!headless') do |scenario, block|
194
+ if Environ.headless
195
+ log "Scenario '#{scenario.name}' is not executed on headless browsers."
196
+ skip_this_scenario
197
+ else
198
+ block.call
199
+ end
200
+ end
201
+
202
+
203
+ Around('@!firefox_headless') do |scenario, block|
204
+ if Environ.browser == :firefox_headless
205
+ log "Scenario '#{scenario.name}' can not be executed on headless Firefox browsers."
206
+ skip_this_scenario
207
+ else
208
+ block.call
209
+ end
210
+ end
211
+
212
+
213
+ # supporting methods
214
+
215
+ def qualify_browser(browser_type, browser_name, scenario, block)
216
+ if Environ.browser != browser_type && ENV['HOST_BROWSER'] != browser_name.downcase
217
+ block.call
218
+ else
219
+ log "Scenario '#{scenario.name}' cannot be executed with the #{browser_name} browser."
220
+ skip_this_scenario
221
+ end
222
+ end
223
+
224
+ def qualify_device(device, scenario, block)
225
+ if Environ.is_device?
226
+ if Environ.device_type.include? device
227
+ log "Scenario '#{scenario.name}' cannot be executed on #{device} devices."
228
+ skip_this_scenario
229
+ else
230
+ block.call
231
+ end
232
+ else
233
+ block.call
234
+ end
235
+ end
236
+
237
+ def terminate_session
238
+ Capybara.page.driver.quit
239
+ Capybara.reset_sessions!
240
+ Environ.session_state = :quit
241
+ $driver_scenario_count = 0
242
+ end
243
+
244
+ def screen_shot_and_save_page(scenario)
245
+ timestamp = Time.now.strftime('%Y%m%d%H%M%S%L')
246
+ filename = scenario.nil? ? "Screenshot-#{timestamp}.png" : "Screenshot-#{scenario.__id__}-#{timestamp}.png"
247
+ path = File.join Dir.pwd, 'reports/screenshots/', filename
248
+ save_screenshot path
249
+ log "Screenshot saved at #{path}"
250
+ screen_shot = { path: path, filename: filename }
251
+ Environ.save_screen_shot(screen_shot)
252
+ attach(path, 'image/png') unless scenario.nil?
253
+ end
254
+
255
+ def process_embed_screenshots(scenario)
256
+ screen_shots = Environ.get_screen_shots
257
+ if screen_shots.count > 0
258
+ screen_shots.each do |row|
259
+ path = row[:path]
260
+ attach(path, 'image/png')
261
+ end
262
+ else
263
+ screen_shot_and_save_page(scenario) if scenario.failed?
264
+ end
265
+ end