automation_helpers 4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE.txt +13 -0
- data/README.md +49 -0
- data/lib/automation_helpers/drivers/browserstack.rb +9 -0
- data/lib/automation_helpers/drivers/local.rb +9 -0
- data/lib/automation_helpers/drivers/remote.rb +9 -0
- data/lib/automation_helpers/drivers/v4/browserstack.rb +135 -0
- data/lib/automation_helpers/drivers/v4/capabilities.rb +106 -0
- data/lib/automation_helpers/drivers/v4/local.rb +92 -0
- data/lib/automation_helpers/drivers/v4/options.rb +52 -0
- data/lib/automation_helpers/drivers/v4/remote.rb +64 -0
- data/lib/automation_helpers/drivers/v4.rb +7 -0
- data/lib/automation_helpers/drivers.rb +6 -0
- data/lib/automation_helpers/extensions/array.rb +18 -0
- data/lib/automation_helpers/extensions/capybara/node/element.rb +31 -0
- data/lib/automation_helpers/extensions/cucumber/core/test/case.rb +26 -0
- data/lib/automation_helpers/extensions/selenium/webdriver/logs.rb +47 -0
- data/lib/automation_helpers/extensions/string.rb +34 -0
- data/lib/automation_helpers/extensions.rb +7 -0
- data/lib/automation_helpers/logger.rb +21 -0
- data/lib/automation_helpers/patches/base.rb +52 -0
- data/lib/automation_helpers/patches/capybara.rb +27 -0
- data/lib/automation_helpers/patches/parallel_cucumber.rb +86 -0
- data/lib/automation_helpers/patches/selenium_logger.rb +24 -0
- data/lib/automation_helpers/patches/selenium_manager.rb +43 -0
- data/lib/automation_helpers/patches/selenium_options.rb +72 -0
- data/lib/automation_helpers/patches.rb +8 -0
- data/lib/automation_helpers/version.rb +5 -0
- data/lib/automation_helpers.rb +68 -0
- metadata +201 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: e31fd999ded8a53243daee17b49c7d85c65c54c0c75ab657669b4e8753f0efc4
|
4
|
+
data.tar.gz: e0abb956e546004f43b9367f0c5e5bf6dbb51770f575642d6e00bfd1b5b0bcbf
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8f981fb29c66cd31b7a08459f4804cdf0917550547aeafddc1397b861b9f0935d03270db452e7cccbabd954425ab5d19e96b8c307a727b1123c842688cb5d558
|
7
|
+
data.tar.gz: 61a8a6dcbb015412438984f39983ea02073f15c9097428ba8cde64cfb4716b50c6dc73e68d0da9efea64b4cd86a197dfdea5e1030642c8c365191c734445a5ee
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
Copyright (c) 2020-2021, The SitePrism team & Marcelo Nicolosi Santos
|
2
|
+
|
3
|
+
All rights reserved.
|
4
|
+
|
5
|
+
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
6
|
+
|
7
|
+
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
8
|
+
|
9
|
+
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
10
|
+
|
11
|
+
Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
12
|
+
|
13
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/README.md
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
# Automation Helpers
|
2
|
+
|
3
|
+
#### The new OSS name for the gem formerly known as ca_testing
|
4
|
+
|
5
|
+
This package will allow you to extend your automated testing frameworks with the following
|
6
|
+
- Driver creation: Allowing you to simply reference your drivers with a simple method
|
7
|
+
(**No more confusing capability classes / methods**)
|
8
|
+
- Simple extensions to regular classes (A bit like ActiveSupport where it's needed / common)
|
9
|
+
- Extensions to the commonly used Automation Packages (Selenium / Capybara e.t.c.), DSL's
|
10
|
+
(Think of things like enhancing `Capybara::Node::Element` e.t.c.)
|
11
|
+
- Patches required to allow instant fixing of bugs in upstream repos whilst fixes are
|
12
|
+
in PR and being reviewed / merged
|
13
|
+
|
14
|
+
## Installation
|
15
|
+
|
16
|
+
Add this line to your application's Gemfile:
|
17
|
+
|
18
|
+
```ruby
|
19
|
+
gem 'automation_helpers'
|
20
|
+
```
|
21
|
+
|
22
|
+
And then execute:
|
23
|
+
|
24
|
+
```shell
|
25
|
+
$ bundle
|
26
|
+
```
|
27
|
+
|
28
|
+
## Usage
|
29
|
+
|
30
|
+
Either require all of the extensions required, or require individual bits and pieces
|
31
|
+
|
32
|
+
## Development
|
33
|
+
|
34
|
+
```
|
35
|
+
$ bundle
|
36
|
+
# Code anything relevant - Add tests for each public method!
|
37
|
+
$ bundle exec rake
|
38
|
+
# Ensure it's all green! Then commit and push
|
39
|
+
```
|
40
|
+
|
41
|
+
## Contributing
|
42
|
+
|
43
|
+
Bug reports and pull requests are welcome on GitHub at
|
44
|
+
https://github.com/site-prism/automation_helpers
|
45
|
+
|
46
|
+
## Verbose Documentation
|
47
|
+
|
48
|
+
This will come in time. Meanwhile if you check the gem code some of the methods are now
|
49
|
+
beginning to get documented. Also check the specs
|
@@ -0,0 +1,135 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'faraday'
|
4
|
+
require 'selenium/webdriver'
|
5
|
+
|
6
|
+
require 'automation_helpers/drivers/v4/capabilities'
|
7
|
+
require 'automation_helpers/drivers/v4/options'
|
8
|
+
|
9
|
+
module AutomationHelpers
|
10
|
+
module Drivers
|
11
|
+
module V4
|
12
|
+
#
|
13
|
+
# {AutomationHelpers::Drivers::V4::Browserstack}
|
14
|
+
#
|
15
|
+
# The Browserstack Driver that will connect to a hosted grid
|
16
|
+
# Requires a series of pre-set values to be passed in
|
17
|
+
#
|
18
|
+
class Browserstack
|
19
|
+
attr_reader :browser, :browserstack_options, :device_options
|
20
|
+
private :browser, :browserstack_options, :device_options
|
21
|
+
|
22
|
+
# #### Initial setup options
|
23
|
+
#
|
24
|
+
# - **browser** (required) - When instantiating, the first argument must be the symbol that represents what browser to use
|
25
|
+
# - **browserstack_options** (required) - A Hash of all required options that will be parsed and used to setup the driver
|
26
|
+
# - :build_name (String) -> The build name to be stored on browserstack servers
|
27
|
+
# - :project_name (String) -> The project name to be stored on browserstack servers
|
28
|
+
# - :session_name (String) -> The session name to be stored on browserstack servers
|
29
|
+
# - :browserstack_debug_mode (Boolean) -> Set this to true to run in browserstack debug mode (Note this runs slower!)
|
30
|
+
# - :config (String) -> This is an underscore separated key that distils the granular running information
|
31
|
+
# i.e. Windows_7_86 means run on Windows Operating System, OS Version 7, Browser Version 86
|
32
|
+
# i.e. OSX_Mojave_12 means run on Mac Operating System, OS Version Mojave, Browser Version 12
|
33
|
+
# i.e. Windows_10_92 means run on Windows Operating System, OS Version 10, Browser Version 92
|
34
|
+
# - :username (String) -> The username for Browserstack
|
35
|
+
# - :api_key (String) -> The api key for Browserstack
|
36
|
+
#
|
37
|
+
def initialize(browser, browserstack_options, device_options = {})
|
38
|
+
@browser = browser
|
39
|
+
@browserstack_options = browserstack_options
|
40
|
+
@device_options = device_options
|
41
|
+
end
|
42
|
+
|
43
|
+
# @return [Nil]
|
44
|
+
#
|
45
|
+
# Register a new driver with the default selenium name for use in a remote browserstack setup
|
46
|
+
def register
|
47
|
+
Capybara.register_driver :selenium do |app|
|
48
|
+
Capybara::Selenium::Driver.new(
|
49
|
+
app,
|
50
|
+
browser: :remote,
|
51
|
+
capabilities: [desired_capabilities, options],
|
52
|
+
url: browserstack_hub_url
|
53
|
+
)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def desired_capabilities
|
60
|
+
Selenium::WebDriver::Remote::Capabilities.new(
|
61
|
+
::Faraday::Utils.deep_merge(
|
62
|
+
# Browserstack Capabilities and General Capabilities are at different levels, so we merge first
|
63
|
+
browserstack_capabilities.merge(browser_version_capability),
|
64
|
+
# Then we deep merge with anything specifically passed into the driver registration (as these can be nested)
|
65
|
+
browser_specific_capabilities.as_json
|
66
|
+
)
|
67
|
+
)
|
68
|
+
end
|
69
|
+
|
70
|
+
def browserstack_capabilities
|
71
|
+
::Faraday::Utils.deep_merge(configurable_capabilities, static_capabilities)
|
72
|
+
end
|
73
|
+
|
74
|
+
def configurable_capabilities
|
75
|
+
{
|
76
|
+
'bstack:options' => {
|
77
|
+
'buildName' => browserstack_options[:build_name],
|
78
|
+
'projectName' => browserstack_options[:project_name],
|
79
|
+
'sessionName' => browserstack_options[:session_name],
|
80
|
+
'debug' => browserstack_options[:browserstack_debug_mode],
|
81
|
+
'os' => os,
|
82
|
+
'osVersion' => os_version
|
83
|
+
}
|
84
|
+
}
|
85
|
+
end
|
86
|
+
|
87
|
+
def static_capabilities
|
88
|
+
{
|
89
|
+
'bstack:options' => {
|
90
|
+
'local' => 'false',
|
91
|
+
'seleniumVersion' => '4.0.0-alpha-6',
|
92
|
+
'consoleLogs' => 'verbose',
|
93
|
+
'networkLogs' => 'true',
|
94
|
+
'resolution' => '1920x1080'
|
95
|
+
}
|
96
|
+
}
|
97
|
+
end
|
98
|
+
|
99
|
+
def browser_specific_capabilities
|
100
|
+
Capabilities.for(browser, device_options)
|
101
|
+
end
|
102
|
+
|
103
|
+
def browser_version_capability
|
104
|
+
return {} if device?
|
105
|
+
|
106
|
+
{ 'browserVersion' => browser_version }
|
107
|
+
end
|
108
|
+
|
109
|
+
def options
|
110
|
+
Options.for(browser)
|
111
|
+
end
|
112
|
+
|
113
|
+
def browserstack_hub_url
|
114
|
+
"https://#{browserstack_options[:username]}:#{browserstack_options[:api_key]}@hub-cloud.browserstack.com/wd/hub"
|
115
|
+
end
|
116
|
+
|
117
|
+
def os
|
118
|
+
browserstack_options[:config].split('_')[0]
|
119
|
+
end
|
120
|
+
|
121
|
+
def os_version
|
122
|
+
browserstack_options[:config].split('_')[1]
|
123
|
+
end
|
124
|
+
|
125
|
+
def browser_version
|
126
|
+
browserstack_options[:config].split('_')[2]
|
127
|
+
end
|
128
|
+
|
129
|
+
def device?
|
130
|
+
%i[android ios].include?(browser)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'selenium/webdriver'
|
4
|
+
|
5
|
+
module AutomationHelpers
|
6
|
+
module Drivers
|
7
|
+
module V4
|
8
|
+
#
|
9
|
+
# {AutomationHelpers::Drivers::V4::Capabilities}
|
10
|
+
#
|
11
|
+
# The Capabilities object that will be used to instantiate whatever driver you
|
12
|
+
# are configuring
|
13
|
+
#
|
14
|
+
class Capabilities
|
15
|
+
class << self
|
16
|
+
# @return [Selenium::WebDriver::Remote::Capabilities]
|
17
|
+
#
|
18
|
+
# Returns the Capabilities hash relevant to the browser specified to be passed to the driver instantiation
|
19
|
+
def for(browser, device_options = {})
|
20
|
+
::Selenium::WebDriver::Remote::Capabilities.new(capabilities_hash(browser, device_options))
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def capabilities_hash(browser, device_options)
|
26
|
+
case browser
|
27
|
+
when :android; then android_capabilities(device_options)
|
28
|
+
when :chrome; then chrome_capabilities
|
29
|
+
when :firefox; then firefox_capabilities
|
30
|
+
when :internet_explorer; then internet_explorer_capabilities
|
31
|
+
when :ios; then ios_capabilities(device_options)
|
32
|
+
else {}
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def android_capabilities(device_options)
|
37
|
+
{
|
38
|
+
'bstack:options' => {
|
39
|
+
'deviceName' => device_options[:device_name],
|
40
|
+
'realMobile' => 'true',
|
41
|
+
'appiumVersion' => android_appium_version(device_options[:os_version])
|
42
|
+
}
|
43
|
+
}
|
44
|
+
end
|
45
|
+
|
46
|
+
def chrome_capabilities
|
47
|
+
{
|
48
|
+
'browserName' => 'chrome',
|
49
|
+
'goog:loggingPrefs' => {
|
50
|
+
'browser' => 'ALL',
|
51
|
+
'driver' => 'ALL'
|
52
|
+
}
|
53
|
+
}
|
54
|
+
end
|
55
|
+
|
56
|
+
def firefox_capabilities
|
57
|
+
{
|
58
|
+
'browserName' => 'firefox'
|
59
|
+
}
|
60
|
+
end
|
61
|
+
|
62
|
+
def internet_explorer_capabilities
|
63
|
+
{
|
64
|
+
'browserName' => 'internet explorer',
|
65
|
+
'bstack:options' => {
|
66
|
+
'ie' => {
|
67
|
+
# This is a minor hack until the IEDriver catches up and releases a V4 compliant copy
|
68
|
+
# It is confirmed to be compliant with V4 selenium jars e.t.c.
|
69
|
+
'driver' => '3.141.59',
|
70
|
+
'arch' => 'x32'
|
71
|
+
}
|
72
|
+
}
|
73
|
+
}
|
74
|
+
end
|
75
|
+
|
76
|
+
def ios_capabilities(device_options)
|
77
|
+
{
|
78
|
+
'bstack:options' => {
|
79
|
+
'deviceName' => device_options[:device_name],
|
80
|
+
'realMobile' => 'true',
|
81
|
+
'appiumVersion' => ios_appium_version(device_options[:os_version])
|
82
|
+
}
|
83
|
+
}
|
84
|
+
end
|
85
|
+
|
86
|
+
def android_appium_version(android_version)
|
87
|
+
case android_version.to_f
|
88
|
+
when 10..; then '1.21.0'
|
89
|
+
when 9..; then '1.20.2'
|
90
|
+
else raise ArgumentError, "Your Android Version is too low. Please don't use lower than Android Pie (9)."
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def ios_appium_version(ios_version)
|
95
|
+
case ios_version.to_f
|
96
|
+
when 13..; then '1.21.0'
|
97
|
+
when 12..; then '1.20.2'
|
98
|
+
when 11..; then '1.16.0'
|
99
|
+
else raise ArgumentError, "Your iOS Version is too low. Please don't use lower than iOS 11."
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'selenium/webdriver'
|
4
|
+
|
5
|
+
require 'automation_helpers/drivers/v4/options'
|
6
|
+
|
7
|
+
module AutomationHelpers
|
8
|
+
module Drivers
|
9
|
+
module V4
|
10
|
+
#
|
11
|
+
# {AutomationHelpers::Drivers::V4::Local}
|
12
|
+
#
|
13
|
+
# The Local Driver that will spin up and run on your machine (Without connecting to any grid)
|
14
|
+
#
|
15
|
+
class Local
|
16
|
+
attr_reader :browser
|
17
|
+
private :browser
|
18
|
+
|
19
|
+
# #### Initial setup options
|
20
|
+
#
|
21
|
+
# - **browser** (required) - When instantiating, the first argument must be the symbol that represents what browser to use
|
22
|
+
#
|
23
|
+
def initialize(browser)
|
24
|
+
@browser = browser
|
25
|
+
end
|
26
|
+
|
27
|
+
# @return [Nil]
|
28
|
+
#
|
29
|
+
# Register a new driver with the default selenium name for use locally
|
30
|
+
def register
|
31
|
+
Capybara.register_driver :selenium do |app|
|
32
|
+
Capybara::Selenium::Driver.new(
|
33
|
+
app,
|
34
|
+
browser: browser,
|
35
|
+
service: service,
|
36
|
+
capabilities: capabilities
|
37
|
+
)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# @return [Array]
|
42
|
+
#
|
43
|
+
# The order of these capabilities is important because in the internal configuration
|
44
|
+
# for the driver; these 2 objects are merged (And both will contain a browserName)
|
45
|
+
# as such we need to ensure the browserName we manually set in `desired_capabilities`
|
46
|
+
# is retained as this is the one required by safari
|
47
|
+
def capabilities
|
48
|
+
if safari?
|
49
|
+
[options, desired_capabilities]
|
50
|
+
else
|
51
|
+
[desired_capabilities, options]
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
# This is required to make local drivers work exclusively with Safari TP
|
58
|
+
# This is required in V13 of Safari as the driver there is notoriously flaky
|
59
|
+
# In V12 it doesn't hinder it
|
60
|
+
# Safari V11 is unsupported.
|
61
|
+
def service
|
62
|
+
return unless safari?
|
63
|
+
|
64
|
+
::Selenium::WebDriver::Safari.technology_preview!
|
65
|
+
::Selenium::WebDriver::Service.safari(args: ['--diagnose'])
|
66
|
+
end
|
67
|
+
|
68
|
+
# This is required because Capybara and Safari aren't quite sure what the difference
|
69
|
+
# is between the two browsers. So to compensate an illegal browserName value is
|
70
|
+
# set that allows easy distinction between the two browsers
|
71
|
+
#
|
72
|
+
# NB: Whilst using Safari TP this is required.
|
73
|
+
def desired_capabilities
|
74
|
+
::Selenium::WebDriver::Remote::Capabilities.new.tap do |capabilities|
|
75
|
+
if safari?
|
76
|
+
capabilities['browserName'] = 'Safari Technology Preview'
|
77
|
+
AutomationHelpers.logger.warn('Altering Browser Name request to alleviate Capybara failure with STP.')
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def options
|
83
|
+
Options.for(browser)
|
84
|
+
end
|
85
|
+
|
86
|
+
def safari?
|
87
|
+
browser == :safari
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'selenium/webdriver'
|
4
|
+
|
5
|
+
module AutomationHelpers
|
6
|
+
module Drivers
|
7
|
+
module V4
|
8
|
+
#
|
9
|
+
# {AutomationHelpers::Drivers::V4::Options}
|
10
|
+
#
|
11
|
+
# The Options object that will be used to instantiate whatever driver you
|
12
|
+
# are configuring
|
13
|
+
#
|
14
|
+
class Options
|
15
|
+
class << self
|
16
|
+
# @return [Selenium::Webdriver::Options]
|
17
|
+
#
|
18
|
+
# Returns the Options payload relevant to the browser specified to be passed to the driver instantiation
|
19
|
+
def for(browser)
|
20
|
+
initial_options(browser).tap { |opts| opts.headless! if headless? }
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def initial_options(browser)
|
26
|
+
case browser
|
27
|
+
when :chrome; then ::Selenium::WebDriver::Chrome::Options.new
|
28
|
+
when :firefox; then ::Selenium::WebDriver::Firefox::Options.new(log_level: 'trace')
|
29
|
+
when :edge; then ::Selenium::WebDriver::Edge::Options.new
|
30
|
+
when :safari; then ::Selenium::WebDriver::Safari::Options.new(automatic_inspection: true)
|
31
|
+
when :internet_explorer; then internet_explorer_options
|
32
|
+
else {}
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Constantly fire mouseOver events on click actions (Should help mitigate flaky clicks)
|
37
|
+
def internet_explorer_options
|
38
|
+
::Selenium::WebDriver::IE::Options.new(persistent_hover: true).tap do |opts|
|
39
|
+
# This can be removed once we migrate past Se4 proper (As the space version name is present there)
|
40
|
+
AutomationHelpers.logger.info('Removing `browser_name` key from options payload.')
|
41
|
+
opts.options.delete(:browser_name)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def headless?
|
46
|
+
ENV['HEADLESS'] == 'true'
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'automation_helpers/drivers/v4/capabilities'
|
4
|
+
require 'automation_helpers/drivers/v4/options'
|
5
|
+
|
6
|
+
module AutomationHelpers
|
7
|
+
module Drivers
|
8
|
+
module V4
|
9
|
+
#
|
10
|
+
# {AutomationHelpers::Drivers::V4::Remote}
|
11
|
+
#
|
12
|
+
# The Remote Driver that will connect to a dockerised self-hosted grid
|
13
|
+
# Expects the grid to be live and accepting node requests
|
14
|
+
#
|
15
|
+
class Remote
|
16
|
+
attr_reader :browser
|
17
|
+
private :browser
|
18
|
+
|
19
|
+
# #### Initial setup options
|
20
|
+
#
|
21
|
+
# - **browser** (required) - When instantiating, the first argument must be the symbol that represents what browser to use
|
22
|
+
# - **ENV["HUB_URL"]** (required) - The environment variable HUB_URL must be set to the actively running dockerised grid
|
23
|
+
# (By default this should be +http://hub:4444/wd/hub+)
|
24
|
+
def initialize(browser)
|
25
|
+
@browser = browser
|
26
|
+
end
|
27
|
+
|
28
|
+
# @return [Nil]
|
29
|
+
#
|
30
|
+
# Register a new driver with the default selenium name for use in a (localised), remote grid setup
|
31
|
+
def register
|
32
|
+
Capybara.register_driver :selenium do |app|
|
33
|
+
Capybara::Selenium::Driver.new(
|
34
|
+
app,
|
35
|
+
browser: :remote,
|
36
|
+
capabilities: [browser_capabilities, options],
|
37
|
+
url: hub_url
|
38
|
+
)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def browser_capabilities
|
45
|
+
raise ArgumentError, 'You must use a supported browser' unless supported_browser?
|
46
|
+
|
47
|
+
Capabilities.for(browser)
|
48
|
+
end
|
49
|
+
|
50
|
+
def options
|
51
|
+
Options.for(browser)
|
52
|
+
end
|
53
|
+
|
54
|
+
def hub_url
|
55
|
+
ENV['HUB_URL']
|
56
|
+
end
|
57
|
+
|
58
|
+
def supported_browser?
|
59
|
+
%i[chrome firefox].include?(browser)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'automation_helpers/drivers/v4/browserstack'
|
4
|
+
require 'automation_helpers/drivers/v4/capabilities'
|
5
|
+
require 'automation_helpers/drivers/v4/local'
|
6
|
+
require 'automation_helpers/drivers/v4/options'
|
7
|
+
require 'automation_helpers/drivers/v4/remote'
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Additional useful methods to extend the Array class with
|
4
|
+
class Array
|
5
|
+
# @return [Boolean]
|
6
|
+
#
|
7
|
+
# Test whether an array is wholly unique
|
8
|
+
def uniq?
|
9
|
+
uniq == self
|
10
|
+
end
|
11
|
+
|
12
|
+
# @return [Array]
|
13
|
+
#
|
14
|
+
# Return the non-unique items of an array
|
15
|
+
def non_uniq
|
16
|
+
tally.select { |_key, count| count > 1 }.map(&:first)
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Capybara
|
4
|
+
module Node
|
5
|
+
#
|
6
|
+
# Additional useful methods to extend the Capybara::Node::Element class with
|
7
|
+
#
|
8
|
+
class Element
|
9
|
+
# @return [Integer]
|
10
|
+
#
|
11
|
+
# The Left-Most pixel's horizontal position in the DOM (From element.rect)
|
12
|
+
def horizontal_position
|
13
|
+
native.rect.x.to_i
|
14
|
+
end
|
15
|
+
|
16
|
+
# @return [Integer]
|
17
|
+
#
|
18
|
+
# The Left-Most pixel's vertical position in the DOM (From element.rect)
|
19
|
+
def vertical_position
|
20
|
+
native.rect.y.to_i
|
21
|
+
end
|
22
|
+
|
23
|
+
# @return [Boolean]
|
24
|
+
#
|
25
|
+
# Whether the element is in a stale state or not
|
26
|
+
def stale?
|
27
|
+
inspect == 'Obsolete #<Capybara::Node::Element>'
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Cucumber
|
4
|
+
module Core
|
5
|
+
module Test
|
6
|
+
#
|
7
|
+
# Additional useful methods to extend the Cucumber::Core::Test::Case class with
|
8
|
+
#
|
9
|
+
class Case
|
10
|
+
# @return [String]
|
11
|
+
#
|
12
|
+
# The file name of the feature being ran (Without the .feature extension)
|
13
|
+
def feature_file_name
|
14
|
+
feature_file_path.split('/').last&.split('.')&.first.to_s
|
15
|
+
end
|
16
|
+
|
17
|
+
# @return [String]
|
18
|
+
#
|
19
|
+
# The fully qualified location of the feature being ran
|
20
|
+
def feature_file_path
|
21
|
+
location.to_s
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|