saucer 0.6.5 → 1.0.0.alpha

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Saucer
4
+ class Options
5
+ W3C = %i[browser_name browser_version platform_name accept_insecure_certs page_load_strategy proxy set_window_rect
6
+ timeouts strict_file_interactability unhandled_prompt_behavior].freeze
7
+
8
+ SAUCE = %i[access_key appium_version avoid_proxy build capture_html chromedriver_version command_timeout
9
+ crmuxdriver_version custom_data disable_popup_handler extended_debugging firefox_adapter_version
10
+ firefox_profile_url idle_timeout iedriver_version max_duration name parent_tunnel passed prerun
11
+ prevent_Requeue priority proxy_host public record_logs record_screenshots record_video
12
+ restricted_public_info screen_resolution selenium_version source tags time_zone tunnel_identifier
13
+ username video_upload_on_pass].freeze
14
+
15
+ VALID = W3C + SAUCE
16
+
17
+ attr_accessor :url, :scenario
18
+ attr_reader :data_center
19
+
20
+ def initialize(**opts)
21
+ VALID.each do |option|
22
+ self.class.__send__(:attr_accessor, option)
23
+ next unless opts.key?(option)
24
+
25
+ instance_variable_set("@#{option}", opts.delete(option))
26
+ end
27
+
28
+ validate_credentials
29
+ @browser_name ||= 'firefox'
30
+ @platform_name ||= 'Windows 10'
31
+ @browser_version ||= 'latest'
32
+ @selenium_version ||= '3.141.59'
33
+
34
+ opts.key?(:url) ? @url = opts[:url] : self.data_center = :US_WEST
35
+ @scenario = opts[:scenario] if opts.key?(:scenario)
36
+ end
37
+
38
+ def capabilities
39
+ w3c = W3C.each_with_object({}) do |option, hash|
40
+ value = instance_variable_get("@#{option}")
41
+ next if value.nil?
42
+
43
+ hash[option] = value
44
+ end
45
+
46
+ sauce = SAUCE.each_with_object({}) do |option, hash|
47
+ value = instance_variable_get("@#{option}")
48
+ next if value.nil?
49
+
50
+ hash[option] = value
51
+ end
52
+
53
+ w3c.merge('sauce:options' => sauce)
54
+ end
55
+ alias to_h capabilities
56
+
57
+ def data_center=(data_center)
58
+ @url = case data_center
59
+ when :US_WEST
60
+ 'https://ondemand.saucelabs.com:443/wd/hub'
61
+ when :US_EAST
62
+ 'https://us-east-1.saucelabs.com:443/wd/hub'
63
+ when :EU_VDC
64
+ 'https://ondemand.eu-central-1.saucelabs.com:443/wd/hub'
65
+ else
66
+ raise ::ArgumentError, "#{data_center} is an invalid data center; specify :US_WEST, :US_EAST or :EU_VDC"
67
+ end
68
+ @data_center = data_center
69
+ end
70
+
71
+ private
72
+
73
+ def validate_credentials
74
+ @username ||= ENV['SAUCE_USERNAME']
75
+ msg = "No valid username found; either pass the value into `Options#new` or set with ENV['SAUCE_USERNAME']"
76
+ raise AuthenticationError, msg if @username.nil?
77
+
78
+ @access_key ||= ENV['SAUCE_ACCESS_KEY']
79
+ return unless @access_key.nil?
80
+
81
+ msg = "No valid access key found; either pass the value into `Options#new` or set with ENV['SAUCE_ACCESS_KEY']"
82
+ raise AuthenticationError, msg
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'saucer/runners/cucumber'
4
+ require 'saucer/runners/rspec'
5
+ require 'saucer/runners/unknown'
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Saucer
4
+ class Cucumber
5
+ class << self
6
+ def test_name
7
+ scenario.source.map(&:name).join(' ')
8
+ end
9
+
10
+ def name
11
+ :cucumber
12
+ end
13
+
14
+ def result
15
+ scenario.passed?
16
+ end
17
+
18
+ def exception
19
+ scenario.exception
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Saucer
4
+ class Rspec
5
+ class << self
6
+ def test_name
7
+ RSpec.current_example.full_description
8
+ end
9
+
10
+ def name
11
+ :rspec
12
+ end
13
+
14
+ def result
15
+ RSpec.current_example.exception.nil?
16
+ end
17
+
18
+ def exception
19
+ RSpec.current_example.exception
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Saucer
4
+ class Unknown
5
+ class << self
6
+ def test_name
7
+ nil
8
+ end
9
+
10
+ def name
11
+ :unknown
12
+ end
13
+
14
+ def result
15
+ nil
16
+ end
17
+
18
+ def exception
19
+ nil
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,134 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'sauce_whisk'
4
+
5
+ module Saucer
6
+ class Session
7
+ class << self
8
+ def runner
9
+ if RSpec.respond_to?(:current_example) && !RSpec.current_example.nil?
10
+ Rspec
11
+ elsif @scenario
12
+ Cucumber
13
+ else
14
+ Unknown
15
+ end
16
+ end
17
+
18
+ def begin(options = nil, scenario: nil)
19
+ options ||= Options.new(scenario: scenario)
20
+ options.name ||= test_name if test_name
21
+ options.build ||= build_name
22
+
23
+ driver = Selenium::WebDriver.for :remote, url: options.url, desired_capabilities: options.capabilities
24
+ new(driver, options)
25
+ end
26
+
27
+ def test_name
28
+ runner.test_name
29
+ end
30
+
31
+ def build_name
32
+ if ENV['BUILD_NAME']
33
+ ENV['BUILD_NAME']
34
+ elsif ENV['BUILD_TAG']
35
+ ENV['BUILD_TAG']
36
+ elsif ENV['TRAVIS_JOB_NUMBER']
37
+ "#{ENV['TRAVIS_REPO_SLUG'][%r{[^/]+$}]}: #{ENV['TRAVIS_JOB_NUMBER']}"
38
+ elsif ENV['SAUCE_BAMBOO_BUILDNUMBER']
39
+ ENV['SAUCE_BAMBOO_BUILDNUMBER']
40
+ elsif ENV['CIRCLE_BUILD_NUM']
41
+ "#{ENV['CIRCLE_JOB']}: #{ENV['CIRCLE_BUILD_NUM']}"
42
+ else
43
+ "Local Execution - #{Time.now.to_i}"
44
+ end
45
+ end
46
+ end
47
+
48
+ attr_accessor :tags, :data
49
+ attr_reader :driver, :options, :job_id, :scenario, :runner
50
+
51
+ include CustomCommands
52
+ include JobUpdate
53
+ include AssetManagement
54
+
55
+ def initialize(driver, options)
56
+ @driver = driver
57
+ @options = options
58
+ @job_id = driver.session_id
59
+ @tags = []
60
+ @scenario = options.scenario
61
+ @runner = self.class.runner
62
+ @data = generate_data
63
+
64
+ SauceWhisk.data_center = options.data_center
65
+ end
66
+
67
+ def generate_data
68
+ data_collection = DataCollection.new
69
+
70
+ opt = {selenium_version: data_collection.selenium_version,
71
+ test_library: data_collection.test_library,
72
+ page_objects: data_collection.page_objects,
73
+ test_runner: data_collection.test_runner(runner),
74
+ language: "Ruby v#{Selenium::WebDriver::Platform.ruby_version}",
75
+ operating_system: Selenium::WebDriver::Platform.os}
76
+ opt[:ci_tool] = Selenium::WebDriver::Platform.ci if Selenium::WebDriver::Platform.ci
77
+ opt
78
+ end
79
+
80
+ def end
81
+ self.result = runner.result unless runner.result.nil?
82
+
83
+ if runner.exception
84
+ data[:error] = runner.exception.inspect
85
+ data[:stacktrace] = runner.exception.backtrace
86
+ end
87
+
88
+ save
89
+ driver.quit
90
+
91
+ wait_until_finished
92
+ end
93
+
94
+ def wait_until_finished
95
+ start_time = Time.now
96
+ loop do
97
+ break if finished? || Time.now - start_time > 10
98
+ end
99
+ end
100
+
101
+ def finished?
102
+ details.end_time
103
+ end
104
+
105
+ def result=(res)
106
+ SauceWhisk::Jobs.change_status(@job_id, res)
107
+ end
108
+
109
+ def stop
110
+ SauceWhisk::Jobs.stop(@job_id)
111
+ end
112
+
113
+ def delete
114
+ start_time = Time.now
115
+ begin
116
+ response = JSON.parse SauceWhisk::Jobs.delete_job(@job_id).body
117
+ raise APIError, "Can not delete job: #{response['error']}" if response.key?('error')
118
+ rescue APIError
119
+ retry if Time.now - start_time < 5
120
+ raise
121
+ end
122
+ end
123
+
124
+ def details
125
+ SauceWhisk::Jobs.fetch(@job_id)
126
+ end
127
+
128
+ private
129
+
130
+ def job
131
+ @job ||= SauceWhisk::Jobs.fetch(@job_id)
132
+ end
133
+ end
134
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Saucer
2
- VERSION = "0.6.5"
4
+ VERSION = '1.0.0.alpha'
3
5
  end
data/saucer.gemspec CHANGED
@@ -1,43 +1,43 @@
1
- # coding: utf-8
2
- lib = File.expand_path("../lib", __FILE__)
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path('lib', __dir__)
3
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require "saucer/version"
5
+ require 'saucer/version'
5
6
 
6
7
  Gem::Specification.new do |spec|
7
- spec.name = "saucer"
8
+ spec.name = 'saucer'
8
9
  spec.version = Saucer::VERSION
9
- spec.authors = ["Titus Fortner"]
10
- spec.email = ["titusfortner@gmail.com"]
10
+ spec.authors = ['Titus Fortner']
11
+ spec.email = ['titusfortner@gmail.com']
11
12
 
12
- spec.summary = %q{A Ruby helper for running tests in Sauce Labs}
13
- spec.description = %q{A Ruby helper for running tests in Sauce Labs}
14
- spec.homepage = "http://github.com/titusfortner/saucer"
15
- spec.license = "MIT"
13
+ spec.summary = 'A Ruby helper for running tests in Sauce Labs'
14
+ spec.description = 'A Ruby helper for running tests in Sauce Labs'
15
+ spec.homepage = 'http://github.com/titusfortner/saucer'
16
+ spec.license = 'MIT'
16
17
 
17
18
  # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
18
19
  # to allow pushing to a single host or delete this section to allow pushing to any host.
19
20
  if spec.respond_to?(:metadata)
20
- spec.metadata["allowed_push_host"] = "https://rubygems.org"
21
+ spec.metadata['allowed_push_host'] = 'https://rubygems.org'
21
22
  else
22
- raise "RubyGems 2.0 or newer is required to protect against " \
23
- "public gem pushes."
23
+ raise 'RubyGems 2.0 or newer is required to protect against ' \
24
+ 'public gem pushes.'
24
25
  end
25
26
 
26
- spec.files = `git ls-files -z`.split("\x0").reject do |f|
27
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
27
28
  f.match(%r{^(test|spec|features)/})
28
29
  end
29
- spec.bindir = "exe"
30
+ spec.bindir = 'exe'
30
31
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
31
- spec.require_paths = ["lib"]
32
+ spec.require_paths = ['lib']
32
33
 
33
- spec.add_development_dependency "bundler", "~> 1.15"
34
- spec.add_development_dependency "rake", "~> 10.0"
35
- spec.add_development_dependency "rspec", "~> 3.0"
34
+ spec.add_development_dependency 'rake'
35
+ spec.add_development_dependency 'rspec'
36
+ spec.add_development_dependency 'rubocop', '~>0.66'
37
+ spec.add_development_dependency 'rubocop-performance'
38
+ spec.add_development_dependency 'rubocop-rspec', '~>1.32'
36
39
 
37
- spec.add_dependency 'parallel_split_test'
38
- spec.add_dependency 'require_all'
39
- spec.add_dependency 'selenium-webdriver', "~> 3.0", ">= 3.4.4"
40
- spec.add_dependency 'sauce_whisk'
41
- spec.add_dependency 'sauce_platforms'
42
- spec.add_dependency 'json'
40
+ spec.add_runtime_dependency 'json'
41
+ spec.add_runtime_dependency 'sauce_whisk'
42
+ spec.add_runtime_dependency 'selenium-webdriver'
43
43
  end
metadata CHANGED
@@ -1,79 +1,65 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: saucer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.5
4
+ version: 1.0.0.alpha
5
5
  platform: ruby
6
6
  authors:
7
7
  - Titus Fortner
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-07-20 00:00:00.000000000 Z
11
+ date: 2019-05-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: bundler
14
+ name: rake
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '1.15'
19
+ version: '0'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '1.15'
26
+ version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: rake
28
+ name: rspec
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '10.0'
33
+ version: '0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '10.0'
40
+ version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: rspec
42
+ name: rubocop
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '3.0'
47
+ version: '0.66'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '3.0'
54
+ version: '0.66'
55
55
  - !ruby/object:Gem::Dependency
56
- name: parallel_split_test
56
+ name: rubocop-performance
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - ">="
60
60
  - !ruby/object:Gem::Version
61
61
  version: '0'
62
- type: :runtime
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - ">="
67
- - !ruby/object:Gem::Version
68
- version: '0'
69
- - !ruby/object:Gem::Dependency
70
- name: require_all
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - ">="
74
- - !ruby/object:Gem::Version
75
- version: '0'
76
- type: :runtime
62
+ type: :development
77
63
  prerelease: false
78
64
  version_requirements: !ruby/object:Gem::Requirement
79
65
  requirements:
@@ -81,27 +67,21 @@ dependencies:
81
67
  - !ruby/object:Gem::Version
82
68
  version: '0'
83
69
  - !ruby/object:Gem::Dependency
84
- name: selenium-webdriver
70
+ name: rubocop-rspec
85
71
  requirement: !ruby/object:Gem::Requirement
86
72
  requirements:
87
73
  - - "~>"
88
74
  - !ruby/object:Gem::Version
89
- version: '3.0'
90
- - - ">="
91
- - !ruby/object:Gem::Version
92
- version: 3.4.4
93
- type: :runtime
75
+ version: '1.32'
76
+ type: :development
94
77
  prerelease: false
95
78
  version_requirements: !ruby/object:Gem::Requirement
96
79
  requirements:
97
80
  - - "~>"
98
81
  - !ruby/object:Gem::Version
99
- version: '3.0'
100
- - - ">="
101
- - !ruby/object:Gem::Version
102
- version: 3.4.4
82
+ version: '1.32'
103
83
  - !ruby/object:Gem::Dependency
104
- name: sauce_whisk
84
+ name: json
105
85
  requirement: !ruby/object:Gem::Requirement
106
86
  requirements:
107
87
  - - ">="
@@ -115,7 +95,7 @@ dependencies:
115
95
  - !ruby/object:Gem::Version
116
96
  version: '0'
117
97
  - !ruby/object:Gem::Dependency
118
- name: sauce_platforms
98
+ name: sauce_whisk
119
99
  requirement: !ruby/object:Gem::Requirement
120
100
  requirements:
121
101
  - - ">="
@@ -129,7 +109,7 @@ dependencies:
129
109
  - !ruby/object:Gem::Version
130
110
  version: '0'
131
111
  - !ruby/object:Gem::Dependency
132
- name: json
112
+ name: selenium-webdriver
133
113
  requirement: !ruby/object:Gem::Requirement
134
114
  requirements:
135
115
  - - ">="
@@ -152,21 +132,22 @@ files:
152
132
  - ".gitignore"
153
133
  - ".rspec"
154
134
  - ".travis.yml"
135
+ - CHANGELOG.md
155
136
  - Gemfile
156
137
  - LICENSE.txt
157
138
  - README.md
158
139
  - Rakefile
159
140
  - lib/saucer.rb
160
- - lib/saucer/annotations.rb
161
- - lib/saucer/api.rb
162
- - lib/saucer/config/common.rb
163
- - lib/saucer/config/sauce.rb
164
- - lib/saucer/config/selenium.rb
165
- - lib/saucer/driver.rb
166
- - lib/saucer/parallel.rb
167
- - lib/saucer/patches/sauce_whisk.rb
168
- - lib/saucer/platform_configuration.rb
169
- - lib/saucer/sauce.rb
141
+ - lib/saucer/asset_management.rb
142
+ - lib/saucer/custom_commands.rb
143
+ - lib/saucer/data_collection.rb
144
+ - lib/saucer/job_update.rb
145
+ - lib/saucer/options.rb
146
+ - lib/saucer/runners.rb
147
+ - lib/saucer/runners/cucumber.rb
148
+ - lib/saucer/runners/rspec.rb
149
+ - lib/saucer/runners/unknown.rb
150
+ - lib/saucer/session.rb
170
151
  - lib/saucer/version.rb
171
152
  - saucer.gemspec
172
153
  homepage: http://github.com/titusfortner/saucer
@@ -185,12 +166,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
185
166
  version: '0'
186
167
  required_rubygems_version: !ruby/object:Gem::Requirement
187
168
  requirements:
188
- - - ">="
169
+ - - ">"
189
170
  - !ruby/object:Gem::Version
190
- version: '0'
171
+ version: 1.3.1
191
172
  requirements: []
192
173
  rubyforge_project:
193
- rubygems_version: 2.5.2
174
+ rubygems_version: 2.5.2.3
194
175
  signing_key:
195
176
  specification_version: 4
196
177
  summary: A Ruby helper for running tests in Sauce Labs