cloud_test 1.0.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.ruby-version +1 -0
- data/.travis.yml +7 -0
- data/CHANGELOG.md +38 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +83 -0
- data/LICENSE.txt +21 -0
- data/README.md +184 -0
- data/Rakefile +10 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/cloud_test.gemspec +48 -0
- data/config/cloudtest.config.bak.yml +19 -0
- data/exe/cloud_test +5 -0
- data/lib/cloud_test.rb +34 -0
- data/lib/cloud_test/browserstack.rb +77 -0
- data/lib/cloud_test/cli.rb +150 -0
- data/lib/cloud_test/core.rb +180 -0
- data/lib/cloud_test/cross_browser_testing.rb +71 -0
- data/lib/cloud_test/generators/cloud_test_env.rb +21 -0
- data/lib/cloud_test/generators/config.rb +21 -0
- data/lib/cloud_test/generators/configs/sample.cloud_test.browserstack.yml +20 -0
- data/lib/cloud_test/generators/configs/sample.cloud_test.crossbrowsertesting.yml +31 -0
- data/lib/cloud_test/generators/configs/sample.cloud_test.lambdatest.yml +22 -0
- data/lib/cloud_test/generators/configs/sample.cloud_test.rb +16 -0
- data/lib/cloud_test/generators/configs/sample.cloud_test.saucelabs.yml +14 -0
- data/lib/cloud_test/lambdatest.rb +62 -0
- data/lib/cloud_test/saucelabs.rb +58 -0
- data/lib/cloud_test/version.rb +3 -0
- metadata +191 -0
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "cloud_test"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/cloud_test.gemspec
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
lib = File.expand_path("../lib", __FILE__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
require "cloud_test/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "cloud_test"
|
7
|
+
spec.version = CloudTest::VERSION
|
8
|
+
spec.authors = ["Philipp Häusele"]
|
9
|
+
spec.email = ["philipp.haeusele@makandra.de"]
|
10
|
+
|
11
|
+
spec.summary = %q{Enables automated Cloud-Testing with various providers. }
|
12
|
+
spec.description = %q{Enables cross-browser-testing with by the integration of the following providers Browserstack, Crossbrowsertesting, Saucelabs and lambdatest. Based on cucumber and capybara}
|
13
|
+
spec.homepage = "https://github.com/makandra/cloud_test"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
|
17
|
+
# to allow pushing to a single host or delete this section to allow pushing to any host.
|
18
|
+
if spec.respond_to?(:metadata)
|
19
|
+
# spec.metadata["allowed_push_host"] = "RubyGems.org"
|
20
|
+
|
21
|
+
spec.metadata["homepage_uri"] = "https://github.com/makandra/cloud_test"
|
22
|
+
spec.metadata["source_code_uri"] = "https://github.com/makandra/cloud_test"
|
23
|
+
spec.metadata["changelog_uri"] = "https://github.com/makandra/cloud_test/CHANGELOG.md"
|
24
|
+
else
|
25
|
+
raise "RubyGems 2.0 or newer is required to protect against " \
|
26
|
+
"public gem pushes."
|
27
|
+
end
|
28
|
+
|
29
|
+
# Specify which files should be added to the gem when it is released.
|
30
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
31
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
32
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
33
|
+
end
|
34
|
+
spec.bindir = "exe"
|
35
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
36
|
+
spec.require_paths = ["lib"]
|
37
|
+
|
38
|
+
spec.add_development_dependency "bundler", "~> 2.0"
|
39
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
40
|
+
spec.add_development_dependency "minitest", "~> 5.0"
|
41
|
+
|
42
|
+
spec.add_development_dependency "aruba"
|
43
|
+
|
44
|
+
spec.add_dependency "thor"
|
45
|
+
spec.add_dependency 'capybara'
|
46
|
+
spec.add_dependency "cucumber"
|
47
|
+
spec.add_development_dependency "selenium-webdriver"
|
48
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
server: "hub-cloud.browserstack.com"
|
2
|
+
user: "philipp127"
|
3
|
+
key: "vJwJsjXGMKeQw6vDus5x"
|
4
|
+
|
5
|
+
common_caps:
|
6
|
+
"browserstack.local": true
|
7
|
+
"browserstack.debug": true # Visual log
|
8
|
+
"acceptSslCerts": true # allow self signed certificates
|
9
|
+
"name": "Bstack-[Capybara] Local Test"
|
10
|
+
|
11
|
+
browser_caps:
|
12
|
+
IE:
|
13
|
+
"browser": "IE"
|
14
|
+
"browser_version": "11.0"
|
15
|
+
"os": "Windows"
|
16
|
+
"os_version": "7"
|
17
|
+
|
18
|
+
#
|
19
|
+
#curl -u "philipp127:vJwJsjXGMKeQw6vDus5x" -X PUT -H "Content-Type: application/json" -d "{\"status\":\"<new-status>\", \"reason\":\"<reason text>\"}" https://api.browserstack.com/automate/sessions/<session-id>.json
|
data/exe/cloud_test
ADDED
data/lib/cloud_test.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require "cloud_test/version"
|
2
|
+
require "cloud_test/core"
|
3
|
+
|
4
|
+
|
5
|
+
module CloudTest
|
6
|
+
class Error < StandardError; end
|
7
|
+
def self.enabled?
|
8
|
+
ENV.has_key?('CLOUD_TEST')
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.upload_status_to_provider(success:, session_id:, reason: "Unknown")
|
12
|
+
begin
|
13
|
+
Core.upload_status success: success, session_id: session_id, reason: reason
|
14
|
+
rescue StandardError => e
|
15
|
+
puts e.message
|
16
|
+
end
|
17
|
+
end
|
18
|
+
if enabled?
|
19
|
+
config = Core.load_config
|
20
|
+
CloudTest::Core.get_provider_class(config).init config
|
21
|
+
end
|
22
|
+
|
23
|
+
at_exit do # is this better in here or in the cloud_test.rb file with the Before tag?
|
24
|
+
if enabled?
|
25
|
+
if $!.nil? || $!.is_a?(SystemExit) && $!.success? # if test was successful
|
26
|
+
Core.list_dashboard_link
|
27
|
+
else
|
28
|
+
code = $!.is_a?(SystemExit) ? $!.status : 1 #if test was not successful, keep exit code
|
29
|
+
Core.list_dashboard_link
|
30
|
+
exit code
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require_relative 'core'
|
2
|
+
|
3
|
+
module CloudTest
|
4
|
+
class Browserstack < Core
|
5
|
+
# do anything browserstack specific
|
6
|
+
SERVER = "hub-cloud.browserstack.com/wd/hub"
|
7
|
+
ENV_USER ='BROWSERSTACK_USERNAME'
|
8
|
+
ENV_PWD = 'BROWSERSTACK_ACCESS_KEY'
|
9
|
+
DASHBOARD_LINK = "https://automate.browserstack.com/dashboard"
|
10
|
+
REST_STATUS_SERVER = "https://api.browserstack.com/automate/sessions/"
|
11
|
+
|
12
|
+
def self.init(config=nil)
|
13
|
+
@config = config || Core.load_config(ENV_USER, ENV_PWD)
|
14
|
+
@caps = Core.get_default_caps
|
15
|
+
|
16
|
+
@caps["browserstack.local"] = true
|
17
|
+
@caps["browserstack.debug"] = true # Visual log
|
18
|
+
@caps['os_version'] = '10'
|
19
|
+
@caps['os'] = 'WINDOWS'
|
20
|
+
@caps['browser'] = 'CHROME'
|
21
|
+
|
22
|
+
@caps = Core.merge_caps(@caps, @config, 'browserstack')
|
23
|
+
Capybara.app_host = "http://127.0.0.1:38946"
|
24
|
+
Capybara.server_port = 38946
|
25
|
+
if !config.nil?
|
26
|
+
start()
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.start
|
31
|
+
puts '> Running features on browserstack.com'
|
32
|
+
begin
|
33
|
+
require 'browserstack/local'
|
34
|
+
rescue LoadError
|
35
|
+
puts 'Please add gem "browserstack-local" to your gemfile!'
|
36
|
+
raise LoadError
|
37
|
+
end
|
38
|
+
# Code to start browserstack local (tunnel) before start of test
|
39
|
+
@bs_local = BrowserStack::Local.new
|
40
|
+
bs_local_args = {"key" => "#{@config['key']}", "logfile" => "log/browserstack-local-logs.log"}
|
41
|
+
@bs_local.start(bs_local_args)
|
42
|
+
register_driver(@caps, @config['user'], @config['key'], SERVER)
|
43
|
+
# Code to stop browserstack local after end of test
|
44
|
+
at_exit do
|
45
|
+
@bs_local.stop unless @bs_local.nil?
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.list_caps # defaults
|
50
|
+
Core.list_caps
|
51
|
+
puts "Browserstack specific defaults:"
|
52
|
+
puts "\tbrowserstack.local: true"
|
53
|
+
puts "\tbrowserstack.debug: true "
|
54
|
+
puts 'you can generate capabilities here https://www.browserstack.com/automate/capabilities?tag=selenium-2-3'
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.get_all_caps # dry run
|
58
|
+
@caps.kind_of?(Hash) || init()
|
59
|
+
puts "Capabilities: "
|
60
|
+
Core.list_these_caps(@caps)
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.get_status_msg(failed, reason)
|
64
|
+
{
|
65
|
+
"status" => failed ? "passed" : "failed",
|
66
|
+
"reason" => reason
|
67
|
+
}
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.check_session_id(session_id)
|
71
|
+
unless session_id =~ Regexp.new('^[0-9a-z]{40}$')
|
72
|
+
puts session_id << "length: " << session_id.length
|
73
|
+
raise "session_id is invalid!"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,150 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'cloud_test/generators/config'
|
3
|
+
require 'cloud_test/generators/cloud_test_env'
|
4
|
+
require_relative 'browserstack'
|
5
|
+
require_relative 'lambdatest'
|
6
|
+
require_relative 'cross_browser_testing'
|
7
|
+
require_relative 'saucelabs'
|
8
|
+
|
9
|
+
|
10
|
+
module CloudTest
|
11
|
+
class CLI < Thor
|
12
|
+
desc "list-caps PROVIDER", "Shows the currently applied capabilities of that provider"
|
13
|
+
def list_caps(provider)
|
14
|
+
hash = {"provider" => provider}
|
15
|
+
Core.get_provider_class(hash).get_all_caps
|
16
|
+
end
|
17
|
+
|
18
|
+
desc "list-default-caps PROVIDER", "Shows the default capabilities for that provider"
|
19
|
+
def list_default_caps(provider)
|
20
|
+
hash = {"provider" => provider}
|
21
|
+
Core.get_provider_class(hash).list_caps
|
22
|
+
end
|
23
|
+
|
24
|
+
desc "generate config", "Puts a sample config yml file into /config directory"
|
25
|
+
def generate_config(config)
|
26
|
+
CloudTest::Generators::Config.start([config])
|
27
|
+
end
|
28
|
+
|
29
|
+
desc "generate", "Puts a sample config yml file into /config directory, and additionally put a cloud_test.rb in features/support"
|
30
|
+
option :provider, :aliases => '-p', :default => 'browserstack'
|
31
|
+
def generate()
|
32
|
+
case options[:provider].to_s.downcase
|
33
|
+
when 'lambdatest', 'lt', 'l'
|
34
|
+
provider = 'lambdatest'
|
35
|
+
when 'crossbrowsertesting', 'cbs', 'ct', 'cbt', 'c'
|
36
|
+
provider = 'crossbrowsertesting'
|
37
|
+
when 'saucelabs', 'sauce', 'sc', 'sl', 's'
|
38
|
+
provider = 'saucelabs'
|
39
|
+
else
|
40
|
+
provider = 'browserstack'
|
41
|
+
end
|
42
|
+
CloudTest::Generators::Config.start([provider])
|
43
|
+
CloudTest::Generators::Support.start()
|
44
|
+
end
|
45
|
+
|
46
|
+
desc "cucumber", "Runs bundle exec cucumber sequentially for all defined browsers. Uses the cucumber tag. With -q hide output."
|
47
|
+
option :q
|
48
|
+
def start()
|
49
|
+
require 'open3'
|
50
|
+
config = Core.load_config
|
51
|
+
config['browsers'].keys.each { |browser_config_name|
|
52
|
+
Open3.popen2e({'CLOUD_TEST' =>browser_config_name.to_s}, "bundle" ,"exec", "cucumber", "-t","#{config['cucumber_tag'].to_s}") do |stdin, stdout_err, wait_thr|
|
53
|
+
unless options[:q]
|
54
|
+
while line = stdout_err.gets
|
55
|
+
puts line
|
56
|
+
end
|
57
|
+
end
|
58
|
+
exit_status = wait_thr.value
|
59
|
+
if exit_status == 0
|
60
|
+
puts "Test on browser: #{browser_config_name} was successful!"
|
61
|
+
else
|
62
|
+
puts "Test on browser: #{browser_config_name} was not successful!"
|
63
|
+
puts stdout_err
|
64
|
+
raise "did not work"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
}
|
68
|
+
end
|
69
|
+
|
70
|
+
desc "each COMMANDS", "Runs the COMMAND sequentially for all defined browsers. With -q hide output."
|
71
|
+
option :q
|
72
|
+
def each(*commands)
|
73
|
+
require 'open3'
|
74
|
+
config = Core.load_config
|
75
|
+
config['browsers'].keys.each { |browser_config_name|
|
76
|
+
Open3.popen2e({'CLOUD_TEST' =>browser_config_name.to_s}, commands.join(" ")) do |stdin, stdout_err, wait_thr|
|
77
|
+
unless options[:q]
|
78
|
+
while line = stdout_err.gets
|
79
|
+
puts line
|
80
|
+
end
|
81
|
+
end
|
82
|
+
exit_status = wait_thr.value
|
83
|
+
if exit_status == 0
|
84
|
+
puts "Test on browser: #{browser_config_name} was successful!"
|
85
|
+
else
|
86
|
+
puts "Error on browser: #{browser_config_name}!"
|
87
|
+
puts stdout_err.read
|
88
|
+
puts "Error on browser: #{browser_config_name}!"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
}
|
92
|
+
end
|
93
|
+
|
94
|
+
desc "test-connection", "Test whether the provider and credentials work, by connectiong to the api"
|
95
|
+
def test_connection()
|
96
|
+
require 'net/http'
|
97
|
+
require 'uri'
|
98
|
+
config = CloudTest::Core.load_config
|
99
|
+
request, uri, request, server = Hash.new
|
100
|
+
if config.has_key?('provider') && config.has_key?('user') && config.has_key?('key')
|
101
|
+
case config.delete 'provider'.to_s.downcase
|
102
|
+
when 'browserstack', 'bs', 'b'
|
103
|
+
server = "https://www.browserstack.com/local/v1/list?auth_token=#{config['key']}&last=1"
|
104
|
+
when 'lambdatest', 'lt', 'l'
|
105
|
+
server = "https://api.lambdatest.com/automation/api/v1/tunnels"
|
106
|
+
uri = URI.parse(server)
|
107
|
+
request = Net::HTTP::Get.new(uri)
|
108
|
+
request.basic_auth(config['user'], config['key'])
|
109
|
+
when 'crossbrowsertesting', 'cbs', 'ct', 'cbt', 'c'
|
110
|
+
server = "https://crossbrowsertesting.com/api/v3/tunnels"
|
111
|
+
uri = URI.parse(server)
|
112
|
+
request = Net::HTTP::Get.new(uri)
|
113
|
+
request.basic_auth(config['user'].sub("@", "%40"), config['key'])
|
114
|
+
when 'saucelabs', 'sauce', 'sc', 'sl', 's'
|
115
|
+
server = "https://saucelabs.com/rest/v1/#{config['user']}/tunnels"
|
116
|
+
uri = URI.parse(server)
|
117
|
+
request = Net::HTTP::Get.new(uri)
|
118
|
+
request.basic_auth(config['user'], config['key'])
|
119
|
+
else
|
120
|
+
puts "Unknown provider!"
|
121
|
+
return
|
122
|
+
end
|
123
|
+
uri ||= URI.parse(server)
|
124
|
+
request ||= Net::HTTP::Get.new(uri)
|
125
|
+
request["Accept"] = "application/json"
|
126
|
+
req_options = {
|
127
|
+
use_ssl: uri.scheme == "https",
|
128
|
+
}
|
129
|
+
response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
|
130
|
+
http.request(request)
|
131
|
+
end
|
132
|
+
if response.code == '200'
|
133
|
+
puts "Connection successful!"
|
134
|
+
else
|
135
|
+
puts "Connection was not successful! :("
|
136
|
+
puts response.code
|
137
|
+
end
|
138
|
+
else
|
139
|
+
puts "You have not all necessary keys in your config file. `provider`, `user`, `key` are necessary"
|
140
|
+
end
|
141
|
+
end
|
142
|
+
desc 'version', 'Display version'
|
143
|
+
map %w[-v --version] => :version
|
144
|
+
|
145
|
+
def version
|
146
|
+
say "cloud_test version: #{CloudTest::VERSION}"
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
@@ -0,0 +1,180 @@
|
|
1
|
+
require 'selenium/webdriver'
|
2
|
+
require 'capybara'
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
module CloudTest
|
6
|
+
class Core
|
7
|
+
CONFIG_NAME = 'cloud_test'
|
8
|
+
|
9
|
+
def self.get_default_caps
|
10
|
+
@caps = Hash.new
|
11
|
+
@caps['project'] = File.split(Dir.getwd)[-1] # folder name
|
12
|
+
@caps['build'] = `git rev-parse HEAD || echo buildname` # HEAD commit hash
|
13
|
+
@caps['name'] = `git log -1 --pretty=%B || echo testname` # HEAD commit message
|
14
|
+
return @caps
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.check_if_input_is_valid?(str)
|
18
|
+
#for all relevant config user input only allow an optional '@' for the cucumber_tag, then some letters, followed by
|
19
|
+
# optional digits
|
20
|
+
# this should enhance security
|
21
|
+
Regexp.new('^@?[A-z]+\d*$') =~ str
|
22
|
+
end
|
23
|
+
|
24
|
+
# the optional parameter could be deleted, or used if someone does not want to put there credentials in the config
|
25
|
+
def self.load_config(env_user='CLOUD_TEST_USER', env_pw='CLOUD_TEST_PW')
|
26
|
+
config = Hash.new
|
27
|
+
|
28
|
+
@caps = self.get_default_caps
|
29
|
+
path = `pwd`.to_s.gsub(/\s+/, "") + "/config/#{CONFIG_NAME}.yml" # complete path to the config file
|
30
|
+
begin
|
31
|
+
config = YAML.load_file(File.absolute_path path)
|
32
|
+
if ENV.has_key?(env_user) && ENV.has_key?(env_pw)
|
33
|
+
config['key'] = ENV[env_pw]
|
34
|
+
config['user'] = ENV[env_user]
|
35
|
+
end
|
36
|
+
rescue SystemCallError
|
37
|
+
puts 'Error: no config file found at: ' + path
|
38
|
+
puts 'Tip: You should run your tests from your main project directory'
|
39
|
+
puts 'Error: I need a config yml file, named ENV["CONFIG_NAME"] or "cloud_test.yml" which has at least a "user" and and "key" pair, thank you!'
|
40
|
+
else
|
41
|
+
if config.has_key?('user') && config.has_key?('key') && config.has_key?('provider') # check wether all the necessary keys exist
|
42
|
+
list_to_check_input = [config['browsers'].keys, (config['cucumber_tag'] if config.has_key?('cucumber_tag')), config['provider']].flatten
|
43
|
+
list_to_check_input.each do |str|
|
44
|
+
if !check_if_input_is_valid?(str)
|
45
|
+
raise "Invalid value: #{str}. Only characters followed by digits are allowed!"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
return config
|
49
|
+
else
|
50
|
+
puts 'Error: I have a config yml file, but no user, key or provider value :('
|
51
|
+
puts "Keys: " + config.keys.to_s
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.register_driver(capsArray, user, key, server)
|
57
|
+
# some debugging options
|
58
|
+
url = "https://#{user.sub("@", "%40")}:#{key}@#{server}"
|
59
|
+
if capsArray.has_key?('cloud_test_debug') and capsArray['cloud_test_debug']
|
60
|
+
puts "Capybara.app_host = #{Capybara.app_host}"
|
61
|
+
puts "Hub url: #{url}"
|
62
|
+
list_these_caps capsArray
|
63
|
+
end
|
64
|
+
Capybara.register_driver :cloud_test do |app|
|
65
|
+
Capybara::Selenium::Driver.new(app,
|
66
|
+
:browser => :remote,
|
67
|
+
:url => url,
|
68
|
+
:desired_capabilities => capsArray
|
69
|
+
)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.list_caps # print defaults
|
74
|
+
# this output could be reformatted
|
75
|
+
puts 'These are the defaults:' + """
|
76
|
+
PROJECT : # name of the folder
|
77
|
+
BUILD : # HEAD commit hash
|
78
|
+
NAME : # HEAD commit message
|
79
|
+
OS : '10'
|
80
|
+
PLATFORM : 'WINDOWS'
|
81
|
+
BROWSER : 'CHROME'"""
|
82
|
+
puts 'Please add additional capabilities in the cloud_test.yml file'
|
83
|
+
end
|
84
|
+
|
85
|
+
def self.list_these_caps(caps)
|
86
|
+
if caps.kind_of?(Enumerable)
|
87
|
+
caps.each do |key, value|
|
88
|
+
puts "|#{key.to_s.ljust(25)}|#{value.to_s.ljust(44)}|\n" # make a nice table like layout
|
89
|
+
end
|
90
|
+
else
|
91
|
+
puts "Error: No caps"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def self.copy_keys(caps, config, keys=config.keys) # a small helper method, to copy keys
|
96
|
+
keys.each do |key|
|
97
|
+
caps[key] = config[key]
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def self.merge_caps(caps, config, provider=nil, browser=ENV['CLOUD_TEST']) # config overwrites in case of conflict
|
102
|
+
if !config.kind_of?(Hash)
|
103
|
+
return caps
|
104
|
+
end
|
105
|
+
keys = config.keys - ['common_caps', 'browsers'] # handle those seperatly
|
106
|
+
copy_keys caps, config, keys
|
107
|
+
if provider && config.has_key?(provider) && config[provider].class.included_modules.include?(Enumerable)
|
108
|
+
copy_keys caps, config[provider]
|
109
|
+
end
|
110
|
+
if config.has_key?('common_caps')
|
111
|
+
caps = caps.merge(config['common_caps'])
|
112
|
+
end
|
113
|
+
if config.has_key?('browsers')
|
114
|
+
if config['browsers'].kind_of?(Hash)
|
115
|
+
if !browser.nil? && config['browsers'][browser].nil?
|
116
|
+
puts "There is no browser with the key:#{browser} in your config file!"
|
117
|
+
raise "No matching browser key found!"
|
118
|
+
end
|
119
|
+
caps = caps.merge(config['browsers'][browser || config['browsers'].keys[0]])
|
120
|
+
else
|
121
|
+
caps = caps.merge(config['browsers'])
|
122
|
+
end
|
123
|
+
end
|
124
|
+
return caps
|
125
|
+
end
|
126
|
+
|
127
|
+
def self.get_provider_class(config=load_config)
|
128
|
+
case config.delete('provider').to_s.downcase
|
129
|
+
when 'browserstack', 'bs', 'b'
|
130
|
+
require 'cloud_test/browserstack'
|
131
|
+
return Browserstack
|
132
|
+
when 'lambdatest', 'lt', 'l'
|
133
|
+
require 'cloud_test/lambdatest'
|
134
|
+
return Lambdatest
|
135
|
+
when 'crossbrowsertesting', 'cbs', 'ct', 'cbt', 'c'
|
136
|
+
require 'cloud_test/cross_browser_testing'
|
137
|
+
return CrossBrowserTesting
|
138
|
+
when 'saucelabs', 'sauce', 'sc', 'sl', 's'
|
139
|
+
require 'cloud_test/saucelabs'
|
140
|
+
return Saucelabs
|
141
|
+
else
|
142
|
+
puts "Error: Please add a valid provider to your config file!"
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def self.list_dashboard_link
|
147
|
+
puts "link to the dashboard: #{get_provider_class::DASHBOARD_LINK}"
|
148
|
+
end
|
149
|
+
|
150
|
+
def self.upload_status(success:, session_id:, reason: "Unknown")
|
151
|
+
config = load_config
|
152
|
+
provider = get_provider_class config
|
153
|
+
provider.check_session_id session_id
|
154
|
+
puts session_id
|
155
|
+
unless provider::REST_STATUS_SERVER.present?
|
156
|
+
puts "skipping upload, not implementet for your provider yet."
|
157
|
+
return
|
158
|
+
end
|
159
|
+
require 'net/http'
|
160
|
+
require 'uri'
|
161
|
+
require 'json'
|
162
|
+
uri = URI.parse(provider::REST_STATUS_SERVER + session_id )
|
163
|
+
request = Net::HTTP::Put.new(uri)
|
164
|
+
request.basic_auth(config['user'], config['key'])
|
165
|
+
request.content_type = "application/json"
|
166
|
+
request.body = JSON.dump(provider.get_status_msg(success, reason))
|
167
|
+
req_options = {
|
168
|
+
use_ssl: uri.scheme == "https",
|
169
|
+
}
|
170
|
+
response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
|
171
|
+
http.request(request)
|
172
|
+
end
|
173
|
+
if response.code != '200'
|
174
|
+
puts "Response Code: #{response.code}"
|
175
|
+
puts "Status upload error!"
|
176
|
+
end
|
177
|
+
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|