testcentricity_web 4.1.5 → 4.1.8

Sign up to get free protection for your applications and to get access to all the features.
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