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.
- checksums.yaml +4 -4
- data/.gitignore +18 -0
- data/.simplecov +9 -0
- data/CHANGELOG.md +44 -0
- data/Gemfile.lock +60 -2
- data/README.md +17 -7
- data/Rakefile +86 -1
- data/config/cucumber.yml +170 -0
- data/config/test_data/LOCAL_data.json +15 -0
- data/config/test_data/LOCAL_data.xls +0 -0
- data/config/test_data/LOCAL_data.yml +11 -0
- data/config/test_data/data.json +25 -0
- data/config/test_data/data.xls +0 -0
- data/config/test_data/data.yml +20 -0
- data/docker-compose-v3.yml +48 -0
- data/features/basic_form_page_css.feature +39 -0
- data/features/basic_form_page_xpath.feature +26 -0
- data/features/media_players.feature +84 -0
- data/features/step_definitions/generic_steps.rb.rb +109 -0
- data/features/step_definitions/media_steps.rb +30 -0
- data/features/support/data/form_data.rb +43 -0
- data/features/support/env.rb +50 -0
- data/features/support/hooks.rb +265 -0
- data/features/support/pages/base_test_page.rb +22 -0
- data/features/support/pages/basic_css_form_page.rb +52 -0
- data/features/support/pages/basic_form_page.rb +393 -0
- data/features/support/pages/basic_xpath_form_page.rb +53 -0
- data/features/support/pages/custom_controls_page.rb +13 -0
- data/features/support/pages/indexed_sections_page.rb +13 -0
- data/features/support/pages/media_test_page.rb +208 -0
- data/features/support/sections/header_nav.rb +39 -0
- data/features/support/world_data.rb +12 -0
- data/features/support/world_pages.rb +18 -0
- data/lib/testcentricity_web/appium_server.rb +5 -0
- data/lib/testcentricity_web/data_objects/data_objects_helper.rb +7 -0
- data/lib/testcentricity_web/data_objects/environment.rb +18 -0
- data/lib/testcentricity_web/data_objects/excel_helper.rb +60 -59
- data/lib/testcentricity_web/version.rb +1 -1
- data/lib/testcentricity_web/web_core/drag_drop_helper.rb +4 -0
- data/lib/testcentricity_web/web_core/page_object.rb +8 -8
- data/lib/testcentricity_web/web_core/page_objects_helper.rb +43 -8
- data/lib/testcentricity_web/web_core/page_section.rb +1 -16
- data/lib/testcentricity_web/web_core/webdriver_helper.rb +16 -0
- data/lib/testcentricity_web/web_elements/checkbox.rb +3 -4
- data/lib/testcentricity_web/web_elements/file_field.rb +9 -5
- data/lib/testcentricity_web/web_elements/image.rb +2 -1
- data/lib/testcentricity_web/web_elements/media.rb +45 -11
- data/lib/testcentricity_web/web_elements/radio.rb +5 -1
- data/lib/testcentricity_web/web_elements/select_list.rb +11 -3
- data/lib/testcentricity_web/web_elements/ui_elements_helper.rb +33 -7
- data/lib/testcentricity_web/web_elements/video.rb +2 -2
- data/reports/.keep +1 -0
- data/test_site/basic_test_page.html +290 -0
- data/test_site/custom_controls_page.html +58 -0
- data/test_site/images/Granny.jpg +0 -0
- data/test_site/images/Wilder.jpg +0 -0
- data/test_site/images/You_Betcha.jpg +0 -0
- data/test_site/indexed_sections_page.html +58 -0
- data/test_site/media/MIB2-subtitles-pt-BR.vtt +49 -0
- data/test_site/media/MIB2.mp4 +0 -0
- data/test_site/media/MP4_small.mp4 +0 -0
- data/test_site/media/MPS_sample.mp3 +0 -0
- data/test_site/media/count_and_bars.mp4 +0 -0
- data/test_site/media_page.html +86 -0
- data/testcentricity_web.gemspec +5 -0
- metadata +131 -4
- 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
|