saucer 0.6.5 → 1.0.0.alpha
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/CHANGELOG.md +6 -0
- data/Gemfile +3 -1
- data/LICENSE.txt +1 -1
- data/README.md +70 -59
- data/Rakefile +5 -3
- data/lib/saucer.rb +17 -4
- data/lib/saucer/asset_management.rb +113 -0
- data/lib/saucer/custom_commands.rb +21 -0
- data/lib/saucer/data_collection.rb +47 -0
- data/lib/saucer/job_update.rb +26 -0
- data/lib/saucer/options.rb +85 -0
- data/lib/saucer/runners.rb +5 -0
- data/lib/saucer/runners/cucumber.rb +23 -0
- data/lib/saucer/runners/rspec.rb +23 -0
- data/lib/saucer/runners/unknown.rb +23 -0
- data/lib/saucer/session.rb +134 -0
- data/lib/saucer/version.rb +3 -1
- data/saucer.gemspec +25 -25
- metadata +38 -57
- data/lib/saucer/annotations.rb +0 -44
- data/lib/saucer/api.rb +0 -57
- data/lib/saucer/config/common.rb +0 -23
- data/lib/saucer/config/sauce.rb +0 -67
- data/lib/saucer/config/selenium.rb +0 -39
- data/lib/saucer/driver.rb +0 -48
- data/lib/saucer/parallel.rb +0 -57
- data/lib/saucer/patches/sauce_whisk.rb +0 -7
- data/lib/saucer/platform_configuration.rb +0 -22
- data/lib/saucer/sauce.rb +0 -20
data/lib/saucer/annotations.rb
DELETED
@@ -1,44 +0,0 @@
|
|
1
|
-
module Saucer
|
2
|
-
module Annotations
|
3
|
-
|
4
|
-
def comment=(comment)
|
5
|
-
driver.execute_script("sauce:context=#{comment}")
|
6
|
-
end
|
7
|
-
|
8
|
-
def job_result=(result)
|
9
|
-
raise ArgumentError, "invalid value for result" unless ['passed', 'failed', true, false].include?(result)
|
10
|
-
driver.execute_script("sauce:job-result=#{result}")
|
11
|
-
end
|
12
|
-
|
13
|
-
def job_name=(name)
|
14
|
-
driver.execute_script("sauce:job-name=#{name}")
|
15
|
-
end
|
16
|
-
|
17
|
-
def job_tags=(tags)
|
18
|
-
tags = tags.join(',') if tags.is_a?(Array)
|
19
|
-
driver.execute_script("sauce:job-tags=#{tags}")
|
20
|
-
end
|
21
|
-
|
22
|
-
def job_info=(info)
|
23
|
-
raise ArgumentError, "job info must be JSON" unless info.is_a? JSON
|
24
|
-
driver.execute_script("sauce:job-info=#{info}")
|
25
|
-
end
|
26
|
-
|
27
|
-
def build_name=(name)
|
28
|
-
driver.execute_script("sauce:job-build=#{name}")
|
29
|
-
end
|
30
|
-
|
31
|
-
def stop_vm
|
32
|
-
driver.execute_script("sauce: stop network")
|
33
|
-
end
|
34
|
-
|
35
|
-
def start_vm
|
36
|
-
driver.execute_script("sauce: start network")
|
37
|
-
end
|
38
|
-
|
39
|
-
def breakpoint
|
40
|
-
driver.execute_script("sauce: break")
|
41
|
-
end
|
42
|
-
|
43
|
-
end
|
44
|
-
end
|
data/lib/saucer/api.rb
DELETED
@@ -1,57 +0,0 @@
|
|
1
|
-
module Saucer
|
2
|
-
class API
|
3
|
-
|
4
|
-
def initialize(driver, config)
|
5
|
-
@driver = driver
|
6
|
-
@config = config
|
7
|
-
end
|
8
|
-
|
9
|
-
def jobs
|
10
|
-
SauceWhisk::Jobs
|
11
|
-
end
|
12
|
-
|
13
|
-
def assets
|
14
|
-
SauceWhisk::Assets
|
15
|
-
end
|
16
|
-
|
17
|
-
def accounts
|
18
|
-
SauceWhisk::Accounts
|
19
|
-
end
|
20
|
-
|
21
|
-
def tunnels
|
22
|
-
SauceWhisk::Tunnels.all
|
23
|
-
end
|
24
|
-
|
25
|
-
def job
|
26
|
-
jobs.fetch(@driver.session_id)
|
27
|
-
end
|
28
|
-
|
29
|
-
def account
|
30
|
-
accounts.fetch(@config.username)
|
31
|
-
end
|
32
|
-
|
33
|
-
def concurrency
|
34
|
-
accounts.concurrency_for(@config.username)
|
35
|
-
end
|
36
|
-
|
37
|
-
def tunnel(id)
|
38
|
-
tunnels.fetch(id)
|
39
|
-
end
|
40
|
-
|
41
|
-
def platforms
|
42
|
-
SauceWhisk::Sauce.platforms
|
43
|
-
end
|
44
|
-
|
45
|
-
def storage
|
46
|
-
@storage ||= SauceWhisk::Storage.new
|
47
|
-
end
|
48
|
-
|
49
|
-
def service_status
|
50
|
-
SauceWhisk::Sauce.service_status
|
51
|
-
end
|
52
|
-
|
53
|
-
def total_job_count
|
54
|
-
SauceWhisk::Sauce.total_job_count
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
data/lib/saucer/config/common.rb
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
module Saucer
|
2
|
-
module Config
|
3
|
-
class Common
|
4
|
-
|
5
|
-
CONFIG_PARAMS = %i(auto_accept_alerts name build tags custom_data max_duration
|
6
|
-
command_timeout idle_timeout prerun executable args background
|
7
|
-
timeout tunnel_identifier parent_tunnel screen_resolution timezone
|
8
|
-
avoid_proxy public record_video video_upload_on_pass record_screenshots
|
9
|
-
record_logs capture_html priority webdriver_remote_quiet_exceptions).freeze
|
10
|
-
|
11
|
-
attr_reader :config_params, :username, :access_key, :url
|
12
|
-
|
13
|
-
def initialize(opts = {})
|
14
|
-
@username = opts.delete(:username) || ENV['SAUCE_USERNAME']
|
15
|
-
@access_key = opts.delete(:access_key) || ENV['SAUCE_ACCESS_KEY']
|
16
|
-
@url = opts.delete(:url) || "https://#{@username}:#{@access_key}@ondemand.saucelabs.com:443/wd/hub"
|
17
|
-
|
18
|
-
@opts = opts
|
19
|
-
@config_params = CONFIG_PARAMS
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
data/lib/saucer/config/sauce.rb
DELETED
@@ -1,67 +0,0 @@
|
|
1
|
-
require 'bundler'
|
2
|
-
|
3
|
-
module Saucer
|
4
|
-
module Config
|
5
|
-
class Sauce
|
6
|
-
|
7
|
-
def self.scenario=(scenario)
|
8
|
-
@@scenario = scenario
|
9
|
-
end
|
10
|
-
|
11
|
-
def self.scenario
|
12
|
-
@@scenario
|
13
|
-
end
|
14
|
-
|
15
|
-
DATA_PARAMS = %i(name build language host_os version ci ip gems framework page_object harness selenium).freeze
|
16
|
-
|
17
|
-
FRAMEWORKS = %w(capybara watir).freeze
|
18
|
-
PAGE_OBJECTS = %w(site_prism page-object watirsome watir_drops).freeze
|
19
|
-
|
20
|
-
def initialize(opt = {})
|
21
|
-
opt[:browser_name] ||= ENV['BROWSER']
|
22
|
-
opt[:platform] ||= ENV['PLATFORM']
|
23
|
-
opt[:version] ||= ENV['VERSION']
|
24
|
-
|
25
|
-
@gems = {}
|
26
|
-
Bundler.definition.specs.map(&:name).each do |gem_name|
|
27
|
-
next if Bundler.environment.specs.to_hash[gem_name].empty?
|
28
|
-
@gems[gem_name] = Bundler.environment.specs.to_hash[gem_name].first.version.version
|
29
|
-
end
|
30
|
-
|
31
|
-
@selenium = @gems['selenium-webdriver']
|
32
|
-
|
33
|
-
frameworks = @gems.select { |gem| FRAMEWORKS.include? gem }
|
34
|
-
@framework = frameworks.first if frameworks.size == 1
|
35
|
-
|
36
|
-
page_objects = @gems.select { |gem| PAGE_OBJECTS.include? gem }
|
37
|
-
@page_object = page_objects.first if page_objects.size == 1
|
38
|
-
|
39
|
-
@name = opt[:name] if opt.key? :name
|
40
|
-
@build = opt[:build] || ENV['BUILD_TAG'] || "Build - #{Time.now.to_i}"
|
41
|
-
|
42
|
-
if RSpec.respond_to?(:current_example) && !RSpec.current_example.nil?
|
43
|
-
@name ||= RSpec.current_example.full_description
|
44
|
-
@location = RSpec.current_example.location
|
45
|
-
@harness = ["rspec", @gems["rspec"]]
|
46
|
-
elsif @@scenario
|
47
|
-
@name ||= @@scenario.source.map(&:name).join(" ")
|
48
|
-
@location = @@scenario.location.to_s
|
49
|
-
@harness = ["cucumber", @gems["cucumber"]]
|
50
|
-
end
|
51
|
-
|
52
|
-
@language = 'Ruby'
|
53
|
-
@host_os = ::Selenium::WebDriver::Platform.os
|
54
|
-
@version = ::Selenium::WebDriver::Platform.ruby_version
|
55
|
-
@ci = ::Selenium::WebDriver::Platform.ci
|
56
|
-
@ip = ::Selenium::WebDriver::Platform.ip
|
57
|
-
end
|
58
|
-
|
59
|
-
def to_hash
|
60
|
-
DATA_PARAMS.each_with_object({}) do |name, hash|
|
61
|
-
var = eval("@#{name}")
|
62
|
-
hash[name] = var if var
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
@@ -1,39 +0,0 @@
|
|
1
|
-
module Saucer
|
2
|
-
module Config
|
3
|
-
class Selenium < Common
|
4
|
-
|
5
|
-
attr_reader :sauce
|
6
|
-
|
7
|
-
CONFIG_PARAMS = %i(browser_name version platform selenium_version
|
8
|
-
chromedriver_version iedriver_version).freeze
|
9
|
-
|
10
|
-
def initialize(opt = {})
|
11
|
-
super
|
12
|
-
@config_params += CONFIG_PARAMS
|
13
|
-
end
|
14
|
-
|
15
|
-
def url
|
16
|
-
"https://#{@username}:#{@access_key}@ondemand.saucelabs.com:443/wd/hub"
|
17
|
-
end
|
18
|
-
|
19
|
-
def capabilities
|
20
|
-
caps = @opts[:desired_capabilities]
|
21
|
-
caps ||= begin
|
22
|
-
caps = @config_params.each_with_object({}) do |param, hash|
|
23
|
-
hash[param] = @opts[param] if @opts.key?(param)
|
24
|
-
hash[param] ||= ENV[param.to_s] if ENV[param.to_s]
|
25
|
-
end
|
26
|
-
browser_name = @opts[:browser_name] || :chrome
|
27
|
-
::Selenium::WebDriver::Remote::Capabilities.send(browser_name, caps)
|
28
|
-
end
|
29
|
-
|
30
|
-
@sauce = Sauce.new.to_hash
|
31
|
-
caps[:"sauce:data"] = @sauce.to_hash
|
32
|
-
caps[:name] = @sauce[:name]
|
33
|
-
caps[:build] = @sauce[:build]
|
34
|
-
caps
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
end
|
39
|
-
end
|
data/lib/saucer/driver.rb
DELETED
@@ -1,48 +0,0 @@
|
|
1
|
-
module Saucer
|
2
|
-
class Driver < Selenium::WebDriver::Remote::Driver
|
3
|
-
|
4
|
-
attr_reader :driver, :config
|
5
|
-
|
6
|
-
def initialize(*args)
|
7
|
-
browser = args.shift if args.first.is_a? Symbol
|
8
|
-
browser = nil if browser == :remote
|
9
|
-
opt = args.first || {}
|
10
|
-
unless opt[:desired_capabilities].is_a? Selenium::WebDriver::Remote::Capabilities
|
11
|
-
opts = opt[:desired_capabilities] || {}
|
12
|
-
browser = opt.key?(:browser_name) ? opt[:browser_name].downcase.to_sym : browser || :chrome
|
13
|
-
opt[:desired_capabilities] = Selenium::WebDriver::Remote::Capabilities.send(browser, opts)
|
14
|
-
end
|
15
|
-
@config = Config::Selenium.new(opt)
|
16
|
-
|
17
|
-
opt[:url] = @config.url
|
18
|
-
opt[:desired_capabilities] = @config.capabilities
|
19
|
-
|
20
|
-
super(opt)
|
21
|
-
end
|
22
|
-
|
23
|
-
def sauce
|
24
|
-
@sauce ||= Sauce.new(self, @config)
|
25
|
-
end
|
26
|
-
|
27
|
-
def quit
|
28
|
-
if RSpec.current_example
|
29
|
-
exception = RSpec.current_example.exception
|
30
|
-
result = exception.nil?
|
31
|
-
elsif Saucer::Config::Sauce.scenario
|
32
|
-
exception = Saucer::Config::Sauce.scenario.exception
|
33
|
-
result = Saucer::Config::Sauce.scenario.passed?
|
34
|
-
end
|
35
|
-
|
36
|
-
if exception
|
37
|
-
sauce.comment = "Error: #{exception.inspect}"
|
38
|
-
sauce.comment = "Error Location: #{exception.backtrace.first}"
|
39
|
-
end
|
40
|
-
|
41
|
-
sauce.job_result = result unless result.nil?
|
42
|
-
results = sauce.api.job.log_url[/(.*)\/.*$/, 1]
|
43
|
-
Selenium::WebDriver.logger.warn("Sauce Labs results: #{results}")
|
44
|
-
|
45
|
-
super
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
data/lib/saucer/parallel.rb
DELETED
@@ -1,57 +0,0 @@
|
|
1
|
-
require 'sauce_platforms'
|
2
|
-
require 'yaml'
|
3
|
-
|
4
|
-
module Saucer
|
5
|
-
class Parallel
|
6
|
-
|
7
|
-
attr_accessor :number, :path, :output
|
8
|
-
|
9
|
-
def initialize(opt = {})
|
10
|
-
@number = opt[:number] || ENV['PARALLEL_PROCESSES']
|
11
|
-
@path = opt[:path] || ENV['TEST_PATH'] || "spec"
|
12
|
-
@output = opt[:output] || ENV['REPORT_OUTPUT'] || 'output'
|
13
|
-
@platforms = opt[:platforms] || []
|
14
|
-
if File.exist?('configs/platform_configs.yml')
|
15
|
-
yaml = YAML.load_file('configs/platform_configs.yml')
|
16
|
-
@platforms ||= yaml.map { |c| Saucer::PlatformConfiguration.new(c) }
|
17
|
-
end
|
18
|
-
@success = true
|
19
|
-
end
|
20
|
-
|
21
|
-
def run
|
22
|
-
if @platforms.empty?
|
23
|
-
raise StandardError, "Tests failed!" unless execute_test
|
24
|
-
return
|
25
|
-
end
|
26
|
-
|
27
|
-
@platforms.each do |platform|
|
28
|
-
Rake::Task.define_task(platform.name) {
|
29
|
-
ENV['platform'] = platform.to_hash[:platform]
|
30
|
-
ENV['browser_name'] = platform.to_hash[:browserName]
|
31
|
-
ENV['version'] = platform.to_hash[:version]
|
32
|
-
|
33
|
-
begin
|
34
|
-
@result = execute_test
|
35
|
-
ensure
|
36
|
-
@success &= @result
|
37
|
-
end
|
38
|
-
}
|
39
|
-
end
|
40
|
-
|
41
|
-
Rake::MultiTask.define_task(sauce_tests: @platforms.map(&:name)) {
|
42
|
-
raise StandardError, "Tests failed!" unless @success
|
43
|
-
}.invoke
|
44
|
-
end
|
45
|
-
|
46
|
-
def execute_test
|
47
|
-
if path.include?('spec')
|
48
|
-
ENV['PARALLEL_SPLIT_TEST_PROCESSES'] = number.to_s if number
|
49
|
-
system "parallel_split_test #{path} --out #{@output}.xml"
|
50
|
-
elsif path.include?('features')
|
51
|
-
system "parallel_cucumber #{path} -o \"--format junit --out #{@output} --format pretty\" -n #{number.to_s}"
|
52
|
-
else
|
53
|
-
raise ArgumentError, "Unable to determine if using rspec or cucumber"
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
require 'sauce_platforms'
|
2
|
-
|
3
|
-
module Saucer
|
4
|
-
class PlatformConfiguration
|
5
|
-
attr_accessor :browser, :os, :browser_version
|
6
|
-
|
7
|
-
def initialize(opt = {})
|
8
|
-
@browser = opt[:browser]
|
9
|
-
@os = opt[:os] || opt['os'].downcase.tr(' ', '_').tr(',', '_')
|
10
|
-
@browser_version = opt[:browser_version] || opt['short_version']
|
11
|
-
end
|
12
|
-
|
13
|
-
def to_hash
|
14
|
-
Platform.send(@os).send(@browser).send("v#{@browser_version}")
|
15
|
-
end
|
16
|
-
|
17
|
-
def name
|
18
|
-
"#{@os}_#{@browser}_#{@browser_version}".to_sym
|
19
|
-
end
|
20
|
-
|
21
|
-
end
|
22
|
-
end
|
data/lib/saucer/sauce.rb
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
module Saucer
|
2
|
-
class Sauce
|
3
|
-
|
4
|
-
include Annotations
|
5
|
-
|
6
|
-
def initialize(driver, config)
|
7
|
-
@driver = driver
|
8
|
-
@config = config
|
9
|
-
end
|
10
|
-
|
11
|
-
def api
|
12
|
-
@api ||= API.new(@driver, @config)
|
13
|
-
end
|
14
|
-
|
15
|
-
def driver
|
16
|
-
@driver
|
17
|
-
end
|
18
|
-
|
19
|
-
end
|
20
|
-
end
|