percy-client 1.12.0 → 1.13.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8556dfa5a032fd21caa62af7e38c2b93ce945a40
4
- data.tar.gz: 0d176888922bc1309e4bdd217b34e6c6835356a0
3
+ metadata.gz: b94954861b98e83a57b9320d28682b66a66e49ee
4
+ data.tar.gz: b6b9a044bab771d3f3fa37ab4922a865c3cc465a
5
5
  SHA512:
6
- metadata.gz: 22b2d8ef3a9d9c79f106687ef66c4fb893354512598448c3c36cc193205f8d1746d1902b998a8a8ea90d73f6cfdc1b2edb09ac6a4ce9bab7e11ec288eacaefa1
7
- data.tar.gz: 0ce75d192a413664ff2c032c326f688b17748b8cd30cac51746620b5081aedf5271d89ad73da6c02ef66f611602b7faab090e80e51d2426edf1032e8d7816b03
6
+ metadata.gz: 9c70290afed751c1612eb3dec8024511c4bc5cb127f3919f84eb1ccec87e30ad2df515153d7c1d0ed4be78423f026ca021847d43bc8a21b20b62f9fa9278573a
7
+ data.tar.gz: 0637dcf07a4c97a5f8904bb4653ce9d6bfac3aa8f576c39a550a35a1cc0fd5716a84d074f62bef4980d67aa13b4b4fe9492dd9ee7fbf7349edd4228ede60c8da
data/Gemfile CHANGED
@@ -5,6 +5,10 @@ gemspec
5
5
 
6
6
  gem 'guard-rspec', require: false
7
7
 
8
+ group :test, :development do
9
+ gem 'pry'
10
+ end
11
+
8
12
  group :test do
9
13
  gem 'rubocop'
10
14
  gem 'rubocop-rspec'
@@ -15,8 +15,15 @@ module Percy
15
15
  # API client based on configured options.
16
16
  #
17
17
  # @return [Percy::Client] API client.
18
- def self.client
19
- @client = Percy::Client.new(config: config) if !defined?(@client) || !@client
18
+ def self.client(options = {})
19
+ if !defined?(@client) || !@client
20
+ @client = Percy::Client.new(
21
+ config: config,
22
+ client_info: options[:client_info],
23
+ environment_info: options[:environment_info],
24
+ )
25
+ end
26
+
20
27
  @client
21
28
  end
22
29
 
@@ -45,10 +45,12 @@ module Percy
45
45
  class BadGatewayError < ServerError; end # 502.
46
46
  class ServiceUnavailableError < ServerError; end # 503.
47
47
 
48
- attr_reader :config
48
+ attr_reader :config, :client_info, :environment_info
49
49
 
50
50
  def initialize(options = {})
51
51
  @config = options[:config] || Percy::Config.new
52
+ @client_info = options[:client_info]
53
+ @environment_info = options[:environment_info]
52
54
  end
53
55
  end
54
56
  end
@@ -14,6 +14,7 @@ module Percy
14
14
  # Only pass parallelism data if it all exists and there is more than 1 shard.
15
15
  in_parallel_environment = parallel_nonce && \
16
16
  parallel_total_shards && parallel_total_shards > 1
17
+
17
18
  unless in_parallel_environment
18
19
  parallel_nonce = nil
19
20
  parallel_total_shards = nil
@@ -44,6 +45,7 @@ module Percy
44
45
  raise ArgumentError,
45
46
  'resources argument must be an iterable of Percy::Client::Resource objects'
46
47
  end
48
+
47
49
  relationships_data = {
48
50
  'relationships' => {
49
51
  'resources' => {
@@ -51,16 +53,19 @@ module Percy
51
53
  },
52
54
  },
53
55
  }
56
+
54
57
  data['data'].merge!(relationships_data)
55
58
  end
56
59
 
57
60
  build_data = post("#{config.api_url}/repos/#{repo}/builds/", data)
58
61
  Percy.logger.debug { "Build #{build_data['data']['id']} created" }
62
+
59
63
  parallelism_msg = if parallel_total_shards
60
64
  "#{parallel_total_shards} shards detected (nonce: #{parallel_nonce.inspect})"
61
65
  else
62
66
  'not detected'
63
67
  end
68
+
64
69
  Percy.logger.debug { "Parallel test environment: #{parallelism_msg}" }
65
70
  build_data
66
71
  end
@@ -20,6 +20,7 @@ module Percy
20
20
 
21
21
  def on_complete(env)
22
22
  error_class = nil
23
+
23
24
  case env[:status]
24
25
  when 400
25
26
  error_class = Percy::Client::BadRequestError
@@ -42,7 +43,9 @@ module Percy
42
43
  when CLIENT_ERROR_STATUS_RANGE # Catchall.
43
44
  error_class = Percy::Client::HttpError
44
45
  end
46
+
45
47
  return unless error_class
48
+
46
49
  raise error_class.new(
47
50
  env.status, env.method.upcase, env.url, env.body,
48
51
  "Got #{env.status} (#{env.method.upcase} #{env.url}):\n#{env.body}",
@@ -52,23 +55,27 @@ module Percy
52
55
 
53
56
  def connection
54
57
  return @connection if defined?(@connection)
58
+
55
59
  parsed_uri = URI.parse(config.api_url)
56
60
  base_url = "#{parsed_uri.scheme}://#{parsed_uri.host}:#{parsed_uri.port}"
61
+
57
62
  @connection = Faraday.new(url: base_url) do |faraday|
58
63
  faraday.request :token_auth, config.access_token if config.access_token
59
64
 
60
65
  faraday.use Percy::Client::Connection::NoCookiesHTTPClientAdapter
61
66
  faraday.use Percy::Client::Connection::NiceErrorMiddleware
62
67
  end
68
+
63
69
  @connection
64
70
  end
65
71
 
66
72
  def get(path, options = {})
67
73
  retries = options[:retries] || 3
74
+
68
75
  begin
69
76
  response = connection.get do |request|
70
77
  request.url(path)
71
- request.headers['Content-Type'] = 'application/vnd.api+json'
78
+ request.headers.merge! _headers
72
79
  end
73
80
  rescue Faraday::TimeoutError
74
81
  raise Percy::Client::TimeoutError
@@ -87,10 +94,11 @@ module Percy
87
94
 
88
95
  def post(path, data, options = {})
89
96
  retries = options[:retries] || 3
97
+
90
98
  begin
91
99
  response = connection.post do |request|
92
100
  request.url(path)
93
- request.headers['Content-Type'] = 'application/vnd.api+json'
101
+ request.headers.merge! _headers
94
102
  request.body = data.to_json
95
103
  end
96
104
  rescue Faraday::TimeoutError
@@ -102,10 +110,49 @@ module Percy
102
110
  sleep(rand(1..3))
103
111
  retry
104
112
  end
113
+
105
114
  raise e
106
115
  end
116
+
107
117
  JSON.parse(response.body)
108
118
  end
119
+
120
+ def _headers
121
+ {
122
+ 'Content-Type' => 'application/vnd.api+json',
123
+ 'User-Agent' => _user_agent,
124
+ }
125
+ end
126
+
127
+ def _user_agent
128
+ @_user_agent ||= begin
129
+ client = [
130
+ "Percy/#{_api_version}",
131
+ client_info,
132
+ "percy-client/#{VERSION}",
133
+ ].compact.join(' ')
134
+
135
+ environment = [
136
+ environment_info,
137
+ "ruby/#{_ruby_version}",
138
+ Percy::Client::Environment.current_ci,
139
+ ].compact.join('; ')
140
+
141
+ "#{client} (#{environment})"
142
+ end
143
+ end
144
+
145
+ def _reset_user_agent
146
+ @_user_agent = nil
147
+ end
148
+
149
+ def _api_version
150
+ config.api_url.match(/\w+$/).to_s
151
+ end
152
+
153
+ def _ruby_version
154
+ "#{RUBY_VERSION}p#{RUBY_PATCHLEVEL}"
155
+ end
109
156
  end
110
157
  end
111
158
  end
@@ -1,5 +1,5 @@
1
1
  module Percy
2
2
  class Client
3
- VERSION = '1.12.0'.freeze
3
+ VERSION = '1.13.0'.freeze
4
4
  end
5
5
  end
@@ -55,6 +55,7 @@ RSpec.describe Percy::Client::Builds, :vcr do
55
55
  expect(build['data']['relationships']['missing-resources']['data']).to be
56
56
  expect(build['data']['relationships']['missing-resources']['data'].length).to eq(1)
57
57
  end
58
+
58
59
  context 'with env vars configured' do
59
60
  before(:each) do
60
61
  ENV['PERCY_BRANCH'] = 'foo-branch'
@@ -1,114 +1,143 @@
1
1
  RSpec.describe Percy::Client::Connection do
2
+ let(:user_agent) do
3
+ "Percy/#{api_version} #{client_info} percy-client/#{Percy::Client::VERSION} "\
4
+ "(#{environment_info}; ruby/#{ruby_version}; #{ci_name})"
5
+ end
6
+ let(:content_type) { 'application/vnd.api+json' }
7
+ let(:api_version) { 'v1' }
8
+ let(:ruby_version) { '2.2.6p396' }
9
+ let(:client_info) { 'percy-capybara/3.1.0' }
10
+ let(:environment_info) { 'Rails/4.2.1' }
11
+ let(:ci_name) { 'buildkite' }
12
+ let(:uri) { "#{Percy.config.api_url}/test" }
13
+
2
14
  describe '#connection' do
3
15
  it 'disables cookies on faraday httpclient adapter' do
4
16
  expect(Percy.client.connection.builder.app.client.cookie_manager).to be_nil
5
17
  end
6
18
  end
19
+
20
+ shared_examples_for 'a connection that sets headers with HTTP method' do |http_method|
21
+ it 'sets headers' do
22
+ stub_request(http_method, uri)
23
+ .with(headers: {'User-Agent' => user_agent, 'Content-Type' => content_type})
24
+ .to_return(body: {foo: true}.to_json)
25
+
26
+ expect(Percy.client).to receive(:_api_version).and_return(api_version)
27
+ expect(Percy.client).to receive(:_ruby_version).and_return(ruby_version)
28
+
29
+ expect(Percy.client).to receive(:client_info).and_return(client_info)
30
+ expect(Percy.client).to receive(:environment_info).and_return(environment_info)
31
+
32
+ expect(Percy::Client::Environment).to receive(:current_ci).and_return(ci_name)
33
+
34
+ expect(response).to eq('foo' => true)
35
+ end
36
+ end
37
+
7
38
  describe '#get' do
39
+ subject(:response) { Percy.client.get(uri) }
40
+
41
+ it_behaves_like 'a connection that sets headers with HTTP method', :get
42
+
8
43
  it 'performs a GET request to the api_url and parses response' do
9
- stub_request(:get, "#{Percy.config.api_url}/test").to_return(body: {foo: true}.to_json)
10
- data = Percy.client.get("#{Percy.config.api_url}/test")
11
- expect(data).to eq('foo' => true)
44
+ stub_request(:get, uri).to_return(body: {foo: true}.to_json)
45
+ expect(response).to eq('foo' => true)
12
46
  end
47
+
13
48
  it 'raises customized timeout errors' do
14
- stub_request(:get, "#{Percy.config.api_url}/test").to_raise(Faraday::TimeoutError)
15
- expect do
16
- Percy.client.get("#{Percy.config.api_url}/test")
17
- end.to raise_error(Percy::Client::TimeoutError)
49
+ stub_request(:get, uri).to_raise(Faraday::TimeoutError)
50
+ expect { response }.to raise_error(Percy::Client::TimeoutError)
18
51
  end
52
+
19
53
  it 'raises customized connection failed errors' do
20
- stub_request(:get, "#{Percy.config.api_url}/test").to_raise(Faraday::ConnectionFailed)
21
- expect do
22
- Percy.client.get("#{Percy.config.api_url}/test")
23
- end.to raise_error(Percy::Client::ConnectionFailed)
54
+ stub_request(:get, uri).to_raise(Faraday::ConnectionFailed)
55
+ expect { response }.to raise_error(Percy::Client::ConnectionFailed)
24
56
  end
57
+
25
58
  it 'retries on 502 errors' do
26
- stub_request(:get, "#{Percy.config.api_url}/test")
59
+ stub_request(:get, uri)
27
60
  .to_return(body: {foo: true}.to_json, status: 502)
28
61
  .then.to_return(body: {foo: true}.to_json, status: 200)
29
62
 
30
- data = Percy.client.get("#{Percy.config.api_url}/test")
31
- expect(data).to eq('foo' => true)
63
+ expect(response).to eq('foo' => true)
32
64
  end
65
+
33
66
  it 'raises error after 3 retries' do
34
- stub_request(:get, "#{Percy.config.api_url}/test")
67
+ stub_request(:get, uri)
35
68
  .to_return(body: {foo: true}.to_json, status: 502).times(3)
36
- expect do
37
- Percy.client.get("#{Percy.config.api_url}/test")
38
- end.to raise_error(Percy::Client::BadGatewayError)
69
+
70
+ expect { response }.to raise_error(Percy::Client::BadGatewayError)
39
71
  end
40
72
  end
73
+
41
74
  describe '#post' do
75
+ subject(:response) { Percy.client.post(uri, {}) }
76
+
77
+ it_behaves_like 'a connection that sets headers with HTTP method', :post
78
+
42
79
  it 'performs a POST request to the api_url and parses response' do
43
- stub_request(:post, "#{Percy.config.api_url}/test").to_return(body: {foo: true}.to_json)
44
- data = Percy.client.post("#{Percy.config.api_url}/test", {})
45
- expect(data).to eq('foo' => true)
80
+ stub_request(:post, uri).to_return(body: {foo: true}.to_json)
81
+ expect(response).to eq('foo' => true)
82
+ end
83
+
84
+ it 'passes through arguments' do
85
+ stub_request(:post, uri)
86
+ .with(headers: {'User-Agent' => user_agent, 'Content-Type' => content_type})
87
+ .to_return(body: {foo: true}.to_json)
88
+
89
+ expect(Percy.client).to receive(:_user_agent).and_return(user_agent)
90
+ expect(response).to eq('foo' => true)
46
91
  end
92
+
47
93
  it 'raises customized timeout errors' do
48
- stub_request(:post, "#{Percy.config.api_url}/test").to_raise(Faraday::TimeoutError)
49
- expect do
50
- Percy.client.post("#{Percy.config.api_url}/test", {})
51
- end.to raise_error(Percy::Client::TimeoutError)
94
+ stub_request(:post, uri).to_raise(Faraday::TimeoutError)
95
+ expect { response }.to raise_error(Percy::Client::TimeoutError)
52
96
  end
97
+
53
98
  it 'raises customized connection failed errors' do
54
- stub_request(:post, "#{Percy.config.api_url}/test").to_raise(Faraday::ConnectionFailed)
55
- expect do
56
- Percy.client.post("#{Percy.config.api_url}/test", {})
57
- end.to raise_error(Percy::Client::ConnectionFailed)
99
+ stub_request(:post, uri).to_raise(Faraday::ConnectionFailed)
100
+ expect { response }.to raise_error(Percy::Client::ConnectionFailed)
58
101
  end
59
- it 'raises custom error classes for some HTTP errors' do
60
- stub_request(:post, "#{Percy.config.api_url}/test")
61
- .to_return(body: {foo: true}.to_json, status: 400)
62
- .then.to_return(body: {foo: true}.to_json, status: 401)
63
- .then.to_return(body: {foo: true}.to_json, status: 402)
64
- .then.to_return(body: {foo: true}.to_json, status: 403)
65
- .then.to_return(body: {foo: true}.to_json, status: 404)
66
- .then.to_return(body: {foo: true}.to_json, status: 409)
67
- .then.to_return(body: {foo: true}.to_json, status: 500)
68
- .then.to_return(body: {foo: true}.to_json, status: 502)
69
- .then.to_return(body: {foo: true}.to_json, status: 503)
70
- expect do
71
- Percy.client.post("#{Percy.config.api_url}/test", {}, retries: 0)
72
- end.to raise_error(Percy::Client::BadRequestError)
73
- expect do
74
- Percy.client.post("#{Percy.config.api_url}/test", {}, retries: 0)
75
- end.to raise_error(Percy::Client::UnauthorizedError)
76
- expect do
77
- Percy.client.post("#{Percy.config.api_url}/test", {}, retries: 0)
78
- end.to raise_error(Percy::Client::PaymentRequiredError)
79
- expect do
80
- Percy.client.post("#{Percy.config.api_url}/test", {}, retries: 0)
81
- end.to raise_error(Percy::Client::ForbiddenError)
82
- expect do
83
- Percy.client.post("#{Percy.config.api_url}/test", {}, retries: 0)
84
- end.to raise_error(Percy::Client::NotFoundError)
85
- expect do
86
- Percy.client.post("#{Percy.config.api_url}/test", {}, retries: 0)
87
- end.to raise_error(Percy::Client::ConflictError)
88
- expect do
89
- Percy.client.post("#{Percy.config.api_url}/test", {}, retries: 0)
90
- end.to raise_error(Percy::Client::InternalServerError)
91
- expect do
92
- Percy.client.post("#{Percy.config.api_url}/test", {}, retries: 0)
93
- end.to raise_error(Percy::Client::BadGatewayError)
94
- expect do
95
- Percy.client.post("#{Percy.config.api_url}/test", {}, retries: 0)
96
- end.to raise_error(Percy::Client::ServiceUnavailableError)
102
+
103
+ shared_examples_for 'HTTP status raises custom error class' do |http_status, error_class|
104
+ subject(:request) { Percy.client.post(uri, {}, retries: 0) }
105
+
106
+ it 'raises custom error classes for some HTTP errors' do
107
+ stub_request(:post, uri).to_return(body: {foo: true}.to_json, status: http_status.to_i)
108
+ expect { request }.to raise_error(error_class)
109
+ end
110
+ end
111
+
112
+ http_errors = {
113
+ '400' => Percy::Client::BadRequestError,
114
+ '401' => Percy::Client::UnauthorizedError,
115
+ '402' => Percy::Client::PaymentRequiredError,
116
+ '403' => Percy::Client::ForbiddenError,
117
+ '404' => Percy::Client::NotFoundError,
118
+ '409' => Percy::Client::ConflictError,
119
+ '500' => Percy::Client::InternalServerError,
120
+ '502' => Percy::Client::BadGatewayError,
121
+ '503' => Percy::Client::ServiceUnavailableError,
122
+ }
123
+
124
+ http_errors.each do |http_status, error_class|
125
+ include_examples 'HTTP status raises custom error class', http_status, error_class
97
126
  end
127
+
98
128
  it 'retries on server errors' do
99
- stub_request(:post, "#{Percy.config.api_url}/test")
129
+ stub_request(:post, uri)
100
130
  .to_return(body: {foo: true}.to_json, status: 500)
101
131
  .then.to_return(body: {foo: true}.to_json, status: 200)
102
132
 
103
- data = Percy.client.post("#{Percy.config.api_url}/test", {})
104
- expect(data).to eq('foo' => true)
133
+ expect(response).to eq('foo' => true)
105
134
  end
135
+
106
136
  it 'raises error after 3 retries' do
107
- stub_request(:post, "#{Percy.config.api_url}/test")
137
+ stub_request(:post, uri)
108
138
  .to_return(body: {foo: true}.to_json, status: 502).times(3)
109
- expect do
110
- Percy.client.post("#{Percy.config.api_url}/test", {})
111
- end.to raise_error(Percy::Client::BadGatewayError)
139
+
140
+ expect { response }.to raise_error(Percy::Client::BadGatewayError)
112
141
  end
113
142
  end
114
143
  end
@@ -88,6 +88,7 @@ RSpec.describe Percy::Client::Environment do
88
88
  }
89
89
  clear_env_vars
90
90
  end
91
+
91
92
  after(:each) do
92
93
  clear_env_vars
93
94
  ENV['TRAVIS_BUILD_ID'] = @original_env['TRAVIS_BUILD_ID']
@@ -106,41 +107,50 @@ RSpec.describe Percy::Client::Environment do
106
107
  expect(Percy::Client::Environment.current_ci).to be_nil
107
108
  end
108
109
  end
110
+
109
111
  describe '#branch' do
110
112
  it 'returns master if not in a git repo' do
111
113
  expect(Percy::Client::Environment).to receive(:_raw_branch_output).and_return('')
112
114
  expect(Percy::Client::Environment.branch).to eq('master')
113
115
  end
116
+
114
117
  it 'reads from the current local repo' do
115
118
  expect(Percy::Client::Environment.branch).to_not be_empty
116
119
  end
120
+
117
121
  it 'can be overridden with PERCY_BRANCH' do
118
122
  ENV['PERCY_BRANCH'] = 'test-branch'
119
123
  expect(Percy::Client::Environment.branch).to eq('test-branch')
120
124
  end
121
125
  end
126
+
122
127
  describe '#target_branch' do
123
128
  it 'returns nil if unset' do
124
129
  expect(Percy::Client::Environment.target_branch).to be_nil
125
130
  end
131
+
126
132
  it 'can be set with PERCY_TARGET_BRANCH' do
127
133
  ENV['PERCY_TARGET_BRANCH'] = 'test-target-branch'
128
134
  expect(Percy::Client::Environment.target_branch).to eq('test-target-branch')
129
135
  end
130
136
  end
137
+
131
138
  describe '#_commit_sha' do
132
139
  it 'returns nil if no environment info can be found' do
133
140
  expect(Percy::Client::Environment._commit_sha).to be_nil
134
141
  end
142
+
135
143
  it 'can be overridden with PERCY_COMMIT' do
136
144
  ENV['PERCY_COMMIT'] = 'test-commit'
137
145
  expect(Percy::Client::Environment._commit_sha).to eq('test-commit')
138
146
  end
139
147
  end
148
+
140
149
  describe '#pull_request_number' do
141
150
  it 'returns nil if no CI environment' do
142
151
  expect(Percy::Client::Environment.pull_request_number).to be_nil
143
152
  end
153
+
144
154
  it 'can be overridden with PERCY_PULL_REQUEST' do
145
155
  ENV['PERCY_PULL_REQUEST'] = '123'
146
156
  ENV['TRAVIS_BUILD_ID'] = '1234'
@@ -148,18 +158,22 @@ RSpec.describe Percy::Client::Environment do
148
158
  expect(Percy::Client::Environment.pull_request_number).to eq('123')
149
159
  end
150
160
  end
161
+
151
162
  describe '#repo' do
152
163
  it 'returns the current local repo name' do
153
164
  expect(Percy::Client::Environment.repo).to eq('percy/percy-client')
154
165
  end
166
+
155
167
  it 'can be overridden with PERCY_PROJECT' do
156
168
  ENV['PERCY_PROJECT'] = 'percy/slug'
157
169
  expect(Percy::Client::Environment.repo).to eq('percy/slug')
158
170
  end
171
+
159
172
  it 'can be overridden with PERCY_REPO_SLUG (deprecated)' do
160
173
  ENV['PERCY_REPO_SLUG'] = 'percy/slug'
161
174
  expect(Percy::Client::Environment.repo).to eq('percy/slug')
162
175
  end
176
+
163
177
  it 'handles git ssh urls' do
164
178
  expect(Percy::Client::Environment).to receive(:_get_origin_url)
165
179
  .once.and_return('git@github.com:org-name/repo-name.git')
@@ -173,6 +187,7 @@ RSpec.describe Percy::Client::Environment do
173
187
  .once.and_return('git@custom-local-hostname:org-name/repo-name.org')
174
188
  expect(Percy::Client::Environment.repo).to eq('org-name/repo-name.org')
175
189
  end
190
+
176
191
  it 'handles git https urls' do
177
192
  expect(Percy::Client::Environment).to receive(:_get_origin_url)
178
193
  .once.and_return('https://github.com/org-name/repo-name.git')
@@ -186,6 +201,7 @@ RSpec.describe Percy::Client::Environment do
186
201
  .once.and_return("https://github.com/org-name/repo-name.org\n")
187
202
  expect(Percy::Client::Environment.repo).to eq('org-name/repo-name.org')
188
203
  end
204
+
189
205
  it 'errors if unable to parse local repo name' do
190
206
  expect(Percy::Client::Environment).to receive(:_get_origin_url).once.and_return('foo')
191
207
  expect { Percy::Client::Environment.repo }.to raise_error(
@@ -193,25 +209,38 @@ RSpec.describe Percy::Client::Environment do
193
209
  )
194
210
  end
195
211
  end
212
+
196
213
  describe '#parallel_nonce' do
197
214
  it 'returns nil' do
198
215
  expect(Percy::Client::Environment.parallel_nonce).to be_nil
199
216
  end
217
+
200
218
  it 'can be set with environment var' do
201
219
  ENV['PERCY_PARALLEL_NONCE'] = 'nonce'
202
220
  expect(Percy::Client::Environment.parallel_nonce).to eq('nonce')
203
221
  end
204
222
  end
223
+
205
224
  describe '#parallel_total_shards' do
206
225
  it 'returns nil' do
207
226
  expect(Percy::Client::Environment.parallel_nonce).to be_nil
208
227
  end
228
+
209
229
  it 'can be set with environment var' do
210
230
  ENV['PERCY_PARALLEL_TOTAL'] = '3'
211
231
  expect(Percy::Client::Environment.parallel_total_shards).to eq(3)
212
232
  end
213
233
  end
214
234
  end
235
+
236
+ RSpec.shared_examples 'an environment user agent that includes CI' do |ci_name|
237
+ it 'returns a user_agent that includes CI name' do
238
+ user_agent = "Percy/v1 percy-client/#{Percy::Client::VERSION} "\
239
+ "(ruby/#{RUBY_VERSION}p#{RUBY_PATCHLEVEL}; #{ci_name})"
240
+ expect(Percy::Client::Environment.user_agent).to eq user_agent
241
+ end
242
+ end
243
+
215
244
  context 'in Jenkins CI' do
216
245
  before(:each) do
217
246
  ENV['JENKINS_URL'] = 'http://localhost:8080/'
@@ -228,6 +257,7 @@ RSpec.describe Percy::Client::Environment do
228
257
  expect(Percy::Client::Environment.repo).to eq('percy/percy-client')
229
258
  end
230
259
  end
260
+
231
261
  context 'in Travis CI' do
232
262
  before(:each) do
233
263
  ENV['TRAVIS_BUILD_ID'] = '1234'
@@ -250,28 +280,33 @@ RSpec.describe Percy::Client::Environment do
250
280
  expect(Percy::Client::Environment.parallel_nonce).to eq('build-number')
251
281
  expect(Percy::Client::Environment.parallel_total_shards).to be_nil
252
282
  end
283
+
253
284
  context 'Pull Request build' do
254
285
  before(:each) do
255
286
  ENV['TRAVIS_PULL_REQUEST'] = '256'
256
287
  ENV['TRAVIS_PULL_REQUEST_BRANCH'] = 'travis-pr-branch'
257
288
  ENV['TRAVIS_PULL_REQUEST_SHA'] = 'travis-pr-head-commit-sha'
258
289
  end
290
+
259
291
  it 'has the correct properties' do
260
292
  expect(Percy::Client::Environment.branch).to eq('travis-pr-branch')
261
293
  expect(Percy::Client::Environment._commit_sha).to eq('travis-pr-head-commit-sha')
262
294
  expect(Percy::Client::Environment.pull_request_number).to eq('256')
263
295
  end
264
296
  end
297
+
265
298
  context 'parallel build' do
266
299
  before(:each) do
267
300
  ENV['CI_NODE_TOTAL'] = '3'
268
301
  end
302
+
269
303
  it 'has the correct properties' do
270
304
  expect(Percy::Client::Environment.parallel_nonce).to eq('build-number')
271
305
  expect(Percy::Client::Environment.parallel_total_shards).to eq(3)
272
306
  end
273
307
  end
274
308
  end
309
+
275
310
  context 'in Circle CI' do
276
311
  before(:each) do
277
312
  ENV['CIRCLECI'] = 'true'
@@ -293,16 +328,19 @@ RSpec.describe Percy::Client::Environment do
293
328
  expect(Percy::Client::Environment.parallel_nonce).to eq('build-number')
294
329
  expect(Percy::Client::Environment.parallel_total_shards).to be_nil
295
330
  end
331
+
296
332
  context 'parallel build' do
297
333
  before(:each) do
298
334
  ENV['CIRCLE_NODE_TOTAL'] = '3'
299
335
  end
336
+
300
337
  it 'has the correct properties' do
301
338
  expect(Percy::Client::Environment.parallel_nonce).to eq('build-number')
302
339
  expect(Percy::Client::Environment.parallel_total_shards).to eq(3)
303
340
  end
304
341
  end
305
342
  end
343
+
306
344
  context 'in Codeship' do
307
345
  before(:each) do
308
346
  ENV['CI_NAME'] = 'codeship'
@@ -322,16 +360,19 @@ RSpec.describe Percy::Client::Environment do
322
360
  expect(Percy::Client::Environment.parallel_nonce).to eq('codeship-build-number')
323
361
  expect(Percy::Client::Environment.parallel_total_shards).to be_nil
324
362
  end
363
+
325
364
  context 'parallel build' do
326
365
  before(:each) do
327
366
  ENV['CI_NODE_TOTAL'] = '3'
328
367
  end
368
+
329
369
  it 'has the correct properties' do
330
370
  expect(Percy::Client::Environment.parallel_nonce).to eq('codeship-build-number')
331
371
  expect(Percy::Client::Environment.parallel_total_shards).to eq(3)
332
372
  end
333
373
  end
334
374
  end
375
+
335
376
  context 'in Drone' do
336
377
  before(:each) do
337
378
  ENV['DRONE'] = 'true'
@@ -348,6 +389,7 @@ RSpec.describe Percy::Client::Environment do
348
389
  expect(Percy::Client::Environment.repo).to eq('percy/percy-client')
349
390
  end
350
391
  end
392
+
351
393
  context 'in Semaphore CI' do
352
394
  before(:each) do
353
395
  ENV['SEMAPHORE'] = 'true'
@@ -368,16 +410,19 @@ RSpec.describe Percy::Client::Environment do
368
410
  expect(Percy::Client::Environment.parallel_nonce).to eq('semaphore-build-number')
369
411
  expect(Percy::Client::Environment.parallel_total_shards).to be_nil
370
412
  end
413
+
371
414
  context 'parallel build' do
372
415
  before(:each) do
373
416
  ENV['SEMAPHORE_THREAD_COUNT'] = '3'
374
417
  end
418
+
375
419
  it 'has the correct properties' do
376
420
  expect(Percy::Client::Environment.parallel_nonce).to eq('semaphore-build-number')
377
421
  expect(Percy::Client::Environment.parallel_total_shards).to eq(3)
378
422
  end
379
423
  end
380
424
  end
425
+
381
426
  context 'in Buildkite' do
382
427
  before(:each) do
383
428
  ENV['BUILDKITE'] = 'true'
@@ -28,4 +28,10 @@ RSpec.configure do |config|
28
28
  # test failures related to randomization by passing the same `--seed` value
29
29
  # as the one that triggered the failure.
30
30
  Kernel.srand config.seed
31
+
32
+ config.after(:each) do |_example|
33
+ # After each run, clear the memoized `_user_agent` property to avoid polluting
34
+ # other tests with the incorrect values.
35
+ Percy.client._reset_user_agent
36
+ end
31
37
  end
@@ -5,6 +5,10 @@ VCR.configure do |c|
5
5
  c.cassette_library_dir = 'spec/cassettes'
6
6
  c.hook_into :webmock
7
7
 
8
+ # Uncomment this to get VCR logger debugging.
9
+ # Run: `rspec spec vcr.log` to get debugging output to vcr.log
10
+ # c.debug_logger = File.open(ARGV[1], 'w')
11
+
8
12
  c.default_cassette_options = {
9
13
  record: ENV['RECORD'] ? :new_episodes : :none,
10
14
  }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: percy-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.12.0
4
+ version: 1.13.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Perceptual Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-06-17 00:00:00.000000000 Z
11
+ date: 2017-06-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -189,7 +189,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
189
189
  version: '0'
190
190
  requirements: []
191
191
  rubyforge_project:
192
- rubygems_version: 2.6.12
192
+ rubygems_version: 2.4.5.2
193
193
  signing_key:
194
194
  specification_version: 4
195
195
  summary: Percy::Client