testcentricity_web 4.1.3 → 4.1.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +18 -0
  3. data/.simplecov +5 -0
  4. data/CHANGELOG.md +30 -1
  5. data/Gemfile.lock +170 -0
  6. data/README.md +287 -102
  7. data/Rakefile +37 -1
  8. data/config/cucumber.yml +150 -0
  9. data/docker-compose-v3.yml +48 -0
  10. data/features/basic_test_page_css.feature +24 -0
  11. data/features/basic_test_page_xpath.feature +24 -0
  12. data/features/step_definitions/generic_steps.rb.rb +37 -0
  13. data/features/support/env.rb +43 -0
  14. data/features/support/hooks.rb +245 -0
  15. data/features/support/pages/basic_css_test_page.rb +49 -0
  16. data/features/support/pages/basic_test_page.rb +238 -0
  17. data/features/support/pages/basic_xpath_test_page.rb +49 -0
  18. data/features/support/pages/media_page.rb +11 -0
  19. data/features/support/world_pages.rb +15 -0
  20. data/lib/testcentricity_web/data_objects/environment.rb +4 -0
  21. data/lib/testcentricity_web/version.rb +1 -1
  22. data/lib/testcentricity_web/web_core/page_object.rb +13 -6
  23. data/lib/testcentricity_web/web_core/page_objects_helper.rb +41 -8
  24. data/lib/testcentricity_web/web_core/page_section.rb +1 -16
  25. data/lib/testcentricity_web/web_core/webdriver_helper.rb +78 -120
  26. data/lib/testcentricity_web/web_elements/select_list.rb +18 -7
  27. data/lib/testcentricity_web/web_elements/ui_elements_helper.rb +13 -0
  28. data/reports/.keep +1 -0
  29. data/test_site/basic_test_page.html +240 -0
  30. data/test_site/images/Granny.jpg +0 -0
  31. data/test_site/images/Wilder.jpg +0 -0
  32. data/test_site/images/You_Betcha.jpg +0 -0
  33. data/test_site/media/MP4_small.mp4 +0 -0
  34. data/test_site/media/MPS_sample.mp3 +0 -0
  35. data/test_site/media_page.html +33 -0
  36. data/testcentricity_web.gemspec +5 -0
  37. metadata +105 -4
  38. data/test_site/test_page.html +0 -11
data/Rakefile CHANGED
@@ -1 +1,37 @@
1
- require 'bundler/gem_tasks'
1
+ require 'rubygems'
2
+ require 'cucumber'
3
+ require 'cucumber/rake/task'
4
+ require 'rake'
5
+
6
+
7
+ namespace :features do
8
+ Cucumber::Rake::Task.new(:edge) do |t|
9
+ t.profile = 'edge'
10
+ end
11
+
12
+ Cucumber::Rake::Task.new(:chrome) do |t|
13
+ t.profile = 'chrome'
14
+ end
15
+
16
+ Cucumber::Rake::Task.new(:edge_headless) do |t|
17
+ t.profile = 'edge_headless'
18
+ end
19
+
20
+ Cucumber::Rake::Task.new(:chrome_headless) do |t|
21
+ t.profile = 'chrome_headless'
22
+ end
23
+
24
+ Cucumber::Rake::Task.new(:safari) do |t|
25
+ t.profile = 'safari'
26
+ end
27
+
28
+ Cucumber::Rake::Task.new(:firefox) do |t|
29
+ t.profile = 'firefox'
30
+ end
31
+
32
+ Cucumber::Rake::Task.new(:firefox_headless) do |t|
33
+ t.profile = 'firefox_headless'
34
+ end
35
+
36
+ task :all => [:edge, :edge_headless, :chrome, :chrome_headless, :safari]
37
+ end
@@ -0,0 +1,150 @@
1
+ <% desktop = "--require features BROWSER_TILE=true BROWSER_SIZE=1300,1000 --publish-quiet" %>
2
+ <% tablet = "--tags @desktop --require features BROWSER_TILE=true --publish-quiet" %>
3
+ <% mobile = "--tags @mobile --require features BROWSER_TILE=true --publish-quiet" %>
4
+ <% reports = "--require features --format pretty --format html --out reports/test_results.html --format junit --out reports --format json --out reports/test_results.json" %>
5
+
6
+
7
+ #==============
8
+ # generic test context profiles
9
+ #==============
10
+
11
+ failing: --tags '@failing and not @wip'
12
+ wip: --tags '@wip and not @failing'
13
+ dev: --tags '@dev and (not @wip and not @failing)'
14
+
15
+
16
+ #==============
17
+ # test reporting profiles
18
+ #==============
19
+
20
+ report: <%= reports %> REPORTING=true
21
+ parallel: PARALLEL=true REPORTING=true --require features --format pretty --format html --out reports/test_results<%= ENV['TEST_ENV_NUMBER'] %>.html --format junit --out reports --format json --out reports/test_results<%= ENV['TEST_ENV_NUMBER'] %>.json
22
+
23
+
24
+ #==============
25
+ # profiles for locally hosted desktop web browsers
26
+ #==============
27
+
28
+ chrome: WEB_BROWSER=chrome <%= desktop %>
29
+ firefox: WEB_BROWSER=firefox <%= desktop %>
30
+ edge: WEB_BROWSER=edge <%= desktop %>
31
+ safari: WEB_BROWSER=safari <%= desktop %>
32
+
33
+ firefox_headless: WEB_BROWSER=firefox_headless <%= desktop %>
34
+ chrome_headless: WEB_BROWSER=chrome_headless <%= desktop %>
35
+ edge_headless: WEB_BROWSER=edge_headless <%= desktop %>
36
+
37
+
38
+ #==============
39
+ # profile for Selenium Grid and Dockerized Selenium Grid hosted desktop web browsers
40
+ #==============
41
+ grid: SELENIUM=remote REMOTE_ENDPOINT="http://localhost:4444/wd/hub"
42
+
43
+
44
+ #==============
45
+ # profiles for mobile device screen orientation
46
+ #==============
47
+
48
+ landscape: ORIENTATION=landscape
49
+ portrait: ORIENTATION=portrait
50
+
51
+
52
+ #==============
53
+ # profile to start Appium Server prior to running mobile browser tests on iOS or Android simulators or physical devices
54
+ #==============
55
+ run_appium: APPIUM_SERVER=run
56
+
57
+
58
+ #==============
59
+ # profiles for mobile Safari web browsers hosted within XCode iOS simulators
60
+ # NOTE: Requires installation of XCode, iOS version specific target simulators, Appium, and the appium_capybara gem
61
+ #==============
62
+
63
+ appium_ios: WEB_BROWSER=appium AUTOMATION_ENGINE=XCUITest APP_PLATFORM_NAME="ios" APP_BROWSER="Safari" NEW_COMMAND_TIMEOUT=30 SHOW_SIM_KEYBOARD=false <%= desktop %>
64
+ app_ios_15: --profile appium_ios APP_VERSION="15.4"
65
+
66
+ ipad_pro_12_15_sim: --profile app_ios_15 DEVICE_TYPE=tablet APP_DEVICE="iPad Pro (12.9-inch) (5th generation)"
67
+ ipad_air_15_sim: --profile app_ios_15 DEVICE_TYPE=tablet APP_DEVICE="iPad Air (5th generation)" <%= desktop %>
68
+
69
+
70
+ #==============
71
+ # profiles for Android mobile web browsers hosted within Android Studio Android Virtual Device emulators
72
+ # NOTE: Requires installation of Android Studio, Android version specific virtual device simulators, Appium, and the appium_capybara gem
73
+ #==============
74
+
75
+ appium_android: WEB_BROWSER=appium APP_PLATFORM_NAME="Android" <%= desktop %>
76
+ app_android_12: --profile appium_android APP_BROWSER="Chrome" APP_VERSION="12.0"
77
+ pixel_c_api31_sim: --profile app_android_12 DEVICE_TYPE=tablet APP_DEVICE="Pixel_C_API_31"
78
+
79
+
80
+ #==============
81
+ # profiles for remotely hosted web browsers on the BrowserStack service
82
+ #==============
83
+
84
+ browserstack: WEB_BROWSER=browserstack BS_USERNAME="<INSERT USER NAME HERE>" BS_AUTHKEY="<INSERT PASSWORD HERE>" AUTOMATE_PROJECT="TC_Web_Sample - BrowserStack"
85
+ bs_desktop: --profile browserstack <%= desktop %> RESOLUTION="1920x1080"
86
+ bs_mobile: --profile browserstack <%= mobile %>
87
+
88
+ # BrowserStack macOS desktop browser profiles
89
+ bs_macos_monterey: --profile bs_desktop BS_OS="OS X" BS_OS_VERSION="Monterey"
90
+ bs_chrome_monterey: --profile bs_macos_monterey BS_BROWSER="Chrome" BS_VERSION="latest"
91
+ bs_edge_monterey: --profile bs_macos_monterey BS_BROWSER="Edge" BS_VERSION="latest"
92
+ bs_safari_monterey: --profile bs_macos_monterey BS_BROWSER="Safari" BS_VERSION="latest"
93
+
94
+ # BrowserStack iOS mobile browser profiles
95
+ bs_ipad: --profile bs_mobile BS_OS=ios BS_BROWSER=Safari DEVICE_TYPE=tablet BS_REAL_MOBILE="true"
96
+ bs_ipad_pro_12: --profile bs_ipad BS_DEVICE="iPad Pro 12.9 2018" BS_OS_VERSION="15"
97
+
98
+ # BrowserStack Android mobile browser profiles
99
+ bs_android: --profile bs_mobile BS_OS=android BS_BROWSER=Chrome DEVICE_TYPE=tablet BS_REAL_MOBILE="true"
100
+ bs_android_tablet: --profile bs_android BS_DEVICE="Samsung Galaxy Tab S7" BS_OS_VERSION="10.0"
101
+
102
+
103
+ #==============
104
+ # profiles for remotely hosted web browsers on the LambdaTest service
105
+ #==============
106
+
107
+ lambdatest: WEB_BROWSER=lambdatest LT_USERNAME="<INSERT USER NAME HERE>" LT_AUTHKEY="<INSERT PASSWORD HERE>" AUTOMATE_PROJECT="TC_Web_Sample - LambdaTest"
108
+ lt_desktop: --profile lambdatest <%= desktop %> RESOLUTION="2560x1440"
109
+
110
+ # LambdaTest macOS desktop browser profiles
111
+ lt_macos_monterey: --profile lt_desktop LT_OS="MacOS Monterey"
112
+ lt_chrome_monterey: --profile lt_macos_monterey LT_BROWSER="Chrome" LT_VERSION="98.0"
113
+ lt_edge_monterey: --profile lt_macos_monterey LT_BROWSER="MicrosoftEdge" LT_VERSION="97.0"
114
+
115
+
116
+ #==============
117
+ # profiles for remotely hosted web browsers on the TestingBot service
118
+ #==============
119
+
120
+ testingbot: WEB_BROWSER=testingbot TB_USERNAME="<INSERT USER NAME HERE>" TB_AUTHKEY="<INSERT PASSWORD HERE>" AUTOMATE_PROJECT="TC_Web_Sample - TestingBot"
121
+ tb_desktop: --profile testingbot <%= desktop %> RESOLUTION="1920x1200"
122
+
123
+ # TestingBot macOS desktop browser profiles
124
+ tb_macos_monterey: --profile tb_desktop TB_OS="MONTEREY"
125
+ tb_chrome_monterey: --profile tb_macos_monterey TB_BROWSER="chrome" TB_VERSION="latest"
126
+ tb_edge_monterey: --profile tb_macos_monterey TB_BROWSER="microsoftedge" TB_VERSION="latest"
127
+
128
+
129
+ #==============
130
+ # profiles for remotely hosted web browsers on the SauceLabs service
131
+ #==============
132
+
133
+ saucelabs: WEB_BROWSER=saucelabs SL_USERNAME="<INSERT USER NAME HERE>" SL_AUTHKEY="<INSERT PASSWORD HERE>" DATA_CENTER="us-west-1" AUTOMATE_PROJECT="TC_Web_Sample - SauceLabs"
134
+ sl_desktop: --profile saucelabs <%= desktop %>
135
+ sl_mobile: --profile saucelabs <%= mobile %>
136
+
137
+ # SauceLabs macOS desktop browser profiles
138
+ sl_macos_monterey: --profile sl_desktop SL_OS="macOS 12" RESOLUTION="1920x1440"
139
+ sl_chrome_monterey: --profile sl_macos_monterey SL_BROWSER="chrome" SL_VERSION="latest"
140
+ sl_edge_monterey: --profile sl_macos_monterey SL_BROWSER="MicrosoftEdge" SL_VERSION="latest"
141
+ sl_firefox_monterey: --profile sl_macos_monterey SL_BROWSER="Firefox" SL_VERSION="latest"
142
+
143
+ # SauceLabs Windows desktop browser profiles
144
+ sl_windows: --profile sl_desktop RESOLUTION="1920x1200"
145
+ sl_edge_win11: --profile sl_windows SL_OS="Windows 11" SL_BROWSER="MicrosoftEdge" SL_VERSION="latest"
146
+ sl_ie_win10: --profile sl_windows SL_OS="Windows 10" SL_BROWSER="internet explorer" SL_VERSION="11"
147
+
148
+ # SauceLabs iOS mobile browser profiles
149
+ sl_ipad: --profile sl_mobile DEVICE_TYPE=tablet SL_PLATFORM=iOS SL_BROWSER=Safari
150
+ sl_ipad_pro_12: --profile sl_ipad SL_DEVICE="iPad Pro (12.9 inch) (5th generation) Simulator" SL_VERSION="15.0"
@@ -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,24 @@
1
+ Feature: Basic HTML Test Page using CSS locators
2
+ In order to xxx
3
+ As a xxxx
4
+ I expect to xxxx
5
+
6
+
7
+ Background:
8
+ Given I am on the Basic CSS Test page
9
+
10
+
11
+ Scenario: xxxxx
12
+ Then I expect the Basic CSS Test page to be correctly displayed
13
+
14
+
15
+ @!mobile
16
+ Scenario: xxxxx
17
+ Then I expect the tab order to be correct
18
+
19
+
20
+ Scenario: xxxxx
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 Test page to be correctly displayed
@@ -0,0 +1,24 @@
1
+ Feature: Basic HTML Test Page using Xpath locators
2
+ In order to xxx
3
+ As a xxxx
4
+ I expect to xxxx
5
+
6
+
7
+ Background:
8
+ Given I am on the Basic Xpath Test page
9
+
10
+
11
+ Scenario: xxxxx
12
+ Then I expect the Basic Xpath Test page to be correctly displayed
13
+
14
+
15
+ @!mobile
16
+ Scenario: xxxxx
17
+ Then I expect the tab order to be correct
18
+
19
+
20
+ Scenario: xxxxx
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 Xpath Test page to be correctly displayed
@@ -0,0 +1,37 @@
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
@@ -0,0 +1,43 @@
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
+ SimpleCov.command_name "features #{ENV['WEB_BROWSER']}" + (ENV['TEST_ENV_NUMBER'] || '')
9
+
10
+ # require_relative 'world_data'
11
+ require_relative 'world_pages'
12
+
13
+ # require_rel 'data'
14
+ # require_rel 'sections'
15
+ require_rel 'pages'
16
+
17
+ $LOAD_PATH << './lib'
18
+
19
+ # set Capybara's default max wait time to 20 seconds
20
+ Capybara.default_max_wait_time = 20
21
+
22
+ # set the default locale and auto load all translations from config/locales/*.rb,yml.
23
+ ENV['LOCALE'] = 'en-US' unless ENV['LOCALE']
24
+ I18n.load_path += Dir['config/locales/*.{rb,yml}']
25
+ I18n.default_locale = ENV['LOCALE']
26
+ I18n.locale = ENV['LOCALE']
27
+ Faker::Config.locale = ENV['LOCALE']
28
+
29
+ # instantiate all data objects and target test environment
30
+ # include WorldData
31
+ # environs.find_environ(ENV['TEST_ENVIRONMENT'], :yaml)
32
+ # WorldData.instantiate_data_objects
33
+
34
+ # instantiate all page objects
35
+ include WorldPages
36
+ WorldPages.instantiate_page_objects
37
+
38
+ # establish connection to WebDriver and target web browser
39
+ Webdrivers.cache_time = 86_400
40
+
41
+ options = { app_host: "file://#{File.dirname(__FILE__)}/../../test_site" }
42
+ options = { app_host: "http://192.168.1.129"}
43
+ TestCentricity::WebDriverConnect.initialize_web_driver(options)
@@ -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,49 @@
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
+ range :slider, 'input#slider'
16
+ filefield :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
+ table :static_table, 'table#table'
28
+ images image_1: 'img#image1',
29
+ image_2: 'img#image2',
30
+ image_3: 'img#image3'
31
+ buttons cancel_button: 'input#cancel',
32
+ submit_button: 'input#submit'
33
+ labels header_label: 'h1',
34
+ username_label: "label[for='username']",
35
+ password_label: "label[for='password']",
36
+ max_length_label: "label[for='maxlength']",
37
+ read_only_label: "label[for='readonly']",
38
+ number_label: "label[for='number-field']",
39
+ color_label: "label[for='color-picker']",
40
+ slider_label: "label[for='slider']",
41
+ comments_label: "label[for='comments']",
42
+ filename_label: "label[for='filename']",
43
+ checkboxes_label: 'label#checkboxes',
44
+ radios_label: 'label#radios',
45
+ multiselect_label: "label[for='multipleselect']",
46
+ dropdown_label: "label[for='dropdown']",
47
+ table_label: "label[for='table']",
48
+ images_label: 'label#images'
49
+ end