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.
- 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
|