restforce 4.3.0 → 5.0.0

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.
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ begin
4
+ require 'faraday/file_part'
5
+ rescue LoadError
6
+ require 'faraday/upload_io'
7
+ end
8
+
9
+ module Restforce
10
+ if defined?(::Faraday::FilePart)
11
+ FilePart = Faraday::FilePart
12
+
13
+ # Deprecated
14
+ UploadIO = Faraday::FilePart
15
+ else
16
+ # Handle pre-1.0 versions of faraday
17
+ FilePart = Faraday::UploadIO
18
+ UploadIO = Faraday::UploadIO
19
+ end
20
+ end
21
+
22
+ # This patch is only needed with multipart-post < 2.0.0
23
+ # 2.0.0 was released in 2013.
24
+ require 'restforce/patches/parts' unless Parts::Part.method(:new).arity.abs == 4
@@ -18,7 +18,7 @@ module Restforce
18
18
  end
19
19
 
20
20
  def use_cache?
21
- @options.fetch(:use_cache, true)
21
+ @options[:use_cache]
22
22
  end
23
23
 
24
24
  def hashed_auth_header(env)
@@ -11,9 +11,9 @@ module Restforce
11
11
  response_values
12
12
  )
13
13
  when 401
14
- raise Restforce::UnauthorizedError, message
14
+ raise Restforce::UnauthorizedError.new(message, response_values)
15
15
  when 404
16
- raise Restforce::NotFoundError, message
16
+ raise Restforce::NotFoundError.new(message, response_values)
17
17
  when 413
18
18
  raise Restforce::EntityTooLargeError.new(
19
19
  "413: Request Entity Too Large",
@@ -56,8 +56,7 @@ module Restforce
56
56
  def exception_class_for_error_code(error_code)
57
57
  return Restforce::ResponseError unless ERROR_CODE_MATCHER.match?(error_code)
58
58
 
59
- constant_name = error_code.split('_').map(&:capitalize).join.to_sym
60
- Restforce::ErrorCode.const_get(constant_name)
59
+ Restforce::ErrorCode.get_exception_class(error_code)
61
60
  end
62
61
  end
63
62
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Restforce
4
- VERSION = '4.3.0'
4
+ VERSION = '5.0.0'
5
5
  end
data/restforce.gemspec CHANGED
@@ -3,11 +3,11 @@
3
3
  require File.expand_path('lib/restforce/version', __dir__)
4
4
 
5
5
  Gem::Specification.new do |gem|
6
- gem.authors = ["Eric J. Holmes", "Tim Rogers"]
7
- gem.email = ["eric@ejholmes.net", "tim@gocardless.com"]
8
- gem.description = 'A lightweight ruby client for the Salesforce REST API.'
9
- gem.summary = 'A lightweight ruby client for the Salesforce REST API.'
10
- gem.homepage = "http://restforce.org/"
6
+ gem.authors = ["Tim Rogers", "Eric J. Holmes"]
7
+ gem.email = ["me@timrogers.co.uk", "eric@ejholmes.net"]
8
+ gem.description = 'A lightweight Ruby client for the Salesforce REST API'
9
+ gem.summary = 'A lightweight Ruby client for the Salesforce REST API'
10
+ gem.homepage = "https://restforce.github.io/"
11
11
  gem.license = "MIT"
12
12
 
13
13
  gem.files = `git ls-files`.split($OUTPUT_RECORD_SEPARATOR)
@@ -22,12 +22,11 @@ Gem::Specification.new do |gem|
22
22
  'changelog_uri' => 'https://github.com/restforce/restforce/blob/master/CHANGELOG.md'
23
23
  }
24
24
 
25
- gem.required_ruby_version = '>= 2.4'
25
+ gem.required_ruby_version = '>= 2.5'
26
26
 
27
- gem.add_dependency 'faraday', '<= 1.0', '>= 0.9.0'
28
- gem.add_dependency 'faraday_middleware', ['>= 0.8.8', '<= 1.0']
27
+ gem.add_dependency 'faraday', '<= 2.0', '>= 0.9.0'
28
+ gem.add_dependency 'faraday_middleware', ['>= 0.8.8', '<= 2.0']
29
29
 
30
- gem.add_dependency 'json', '>= 1.7.5'
31
30
  gem.add_dependency 'jwt', ['>= 1.5.6']
32
31
 
33
32
  gem.add_dependency 'hashie', '>= 1.2.0', '< 5.0'
@@ -35,7 +34,7 @@ Gem::Specification.new do |gem|
35
34
  gem.add_development_dependency 'faye' unless RUBY_PLATFORM == 'java'
36
35
  gem.add_development_dependency 'rspec', '~> 2.14.0'
37
36
  gem.add_development_dependency 'rspec_junit_formatter', '~> 0.4.1'
38
- gem.add_development_dependency 'rubocop', '~> 0.77.0'
39
- gem.add_development_dependency 'simplecov', '~> 0.17.1'
40
- gem.add_development_dependency 'webmock', '~> 3.7.6'
37
+ gem.add_development_dependency 'rubocop', '~> 0.87.1'
38
+ gem.add_development_dependency 'simplecov', '~> 0.18.2'
39
+ gem.add_development_dependency 'webmock', '~> 3.8.3'
41
40
  end
@@ -86,22 +86,34 @@ shared_examples_for Restforce::AbstractClient do
86
86
  end
87
87
 
88
88
  context 'with multipart' do
89
- # rubocop:disable Metrics/LineLength
89
+ # rubocop:disable Layout/LineLength
90
90
  requests 'sobjects/Account',
91
91
  method: :post,
92
- with_body: %r(----boundary_string\r\nContent-Disposition: form-data; name=\"entity_content\"\r\nContent-Type: application/json\r\n\r\n{\"Name\":\"Foobar\"}\r\n----boundary_string\r\nContent-Disposition: form-data; name=\"Blob\"; filename=\"blob.jpg\"\r\nContent-Length: 42171\r\nContent-Type: image/jpeg\r\nContent-Transfer-Encoding: binary),
92
+ with_body: %r(----boundary_string\r\nContent-Disposition: form-data; name="entity_content"\r\nContent-Type: application/json\r\n\r\n{"Name":"Foobar"}\r\n----boundary_string\r\nContent-Disposition: form-data; name="Blob"; filename="blob.jpg"\r\nContent-Length: 42171\r\nContent-Type: image/jpeg\r\nContent-Transfer-Encoding: binary),
93
93
  fixture: 'sobject/create_success_response'
94
- # rubocop:enable Metrics/LineLength
94
+ # rubocop:enable Layout/LineLength
95
95
 
96
96
  subject do
97
97
  client.create('Account', Name: 'Foobar',
98
- Blob: Restforce::UploadIO.new(
98
+ Blob: Restforce::FilePart.new(
99
99
  File.expand_path('../fixtures/blob.jpg', __dir__),
100
100
  'image/jpeg'
101
101
  ))
102
102
  end
103
103
 
104
104
  it { should eq 'some_id' }
105
+
106
+ context 'with deprecated UploadIO' do
107
+ subject do
108
+ client.create('Account', Name: 'Foobar',
109
+ Blob: Restforce::UploadIO.new(
110
+ File.expand_path('../fixtures/blob.jpg', __dir__),
111
+ 'image/jpeg'
112
+ ))
113
+ end
114
+
115
+ it { should eq 'some_id' }
116
+ end
105
117
  end
106
118
  end
107
119
 
data/spec/spec_helper.rb CHANGED
@@ -15,8 +15,21 @@ RSpec.configure do |config|
15
15
  config.order = 'random'
16
16
  config.filter_run focus: true
17
17
  config.run_all_when_everything_filtered = true
18
+
19
+ original_stderr = $stderr
20
+ original_stdout = $stdout
21
+ config.before(:all) do
22
+ # Redirect stderr and stdout
23
+ $stderr = File.open(File::NULL, "w")
24
+ $stdout = File.open(File::NULL, "w")
25
+ end
26
+ config.after(:all) do
27
+ $stderr = original_stderr
28
+ $stdout = original_stdout
29
+ end
18
30
  end
19
31
 
20
32
  # Requires supporting ruby files with custom matchers and macros, etc,
21
33
  # in spec/support/ and its subdirectories.
22
- Dir[File.join(File.dirname(__FILE__), "support/**/*.rb")].each { |f| require f }
34
+ paths = Dir[File.join(File.dirname(__FILE__), "support/**/*.rb")]
35
+ paths.sort.each { |f| require f }
@@ -22,9 +22,7 @@ module FixtureHelpers
22
22
  end
23
23
 
24
24
  def stub_login_request(*)
25
- stub = stub_request(:post, "https://login.salesforce.com/services/oauth2/token")
26
-
27
- stub
25
+ stub_request(:post, "https://login.salesforce.com/services/oauth2/token")
28
26
  end
29
27
 
30
28
  def fixture(filename)
@@ -62,4 +62,22 @@ describe Restforce::Collection do
62
62
  end
63
63
  end
64
64
  end
65
+
66
+ describe '#empty?' do
67
+ subject(:empty?) do
68
+ described_class.new(JSON.parse(fixture(sobject_fixture)), client).empty?
69
+ end
70
+
71
+ context 'with size 1' do
72
+ let(:sobject_fixture) { 'sobject/query_success_response' }
73
+
74
+ it { should be_false }
75
+ end
76
+
77
+ context 'with size 0' do
78
+ let(:sobject_fixture) { 'sobject/query_empty_response' }
79
+
80
+ it { should be_true }
81
+ end
82
+ end
65
83
  end
@@ -28,4 +28,30 @@ describe Restforce::Concerns::Caching do
28
28
  end
29
29
  end
30
30
  end
31
+
32
+ describe '.with_caching' do
33
+ let(:options) { double('Options') }
34
+
35
+ before do
36
+ client.stub options: options
37
+ end
38
+
39
+ it 'runs the block with caching enabled' do
40
+ options.should_receive(:[]=).with(:use_cache, true)
41
+ options.should_receive(:[]=).with(:use_cache, false)
42
+ expect { |b| client.with_caching(&b) }.to yield_control
43
+ end
44
+
45
+ context 'when an exception is raised' do
46
+ it 'ensures the :use_cache is set to false' do
47
+ options.should_receive(:[]=).with(:use_cache, true)
48
+ options.should_receive(:[]=).with(:use_cache, false)
49
+ expect {
50
+ client.with_caching do
51
+ raise 'Foo'
52
+ end
53
+ }.to raise_error 'Foo'
54
+ end
55
+ end
56
+ end
31
57
  end
@@ -73,9 +73,9 @@ describe Restforce::Concerns::Connection do
73
73
  Restforce.stub(log?: true)
74
74
  end
75
75
 
76
- it "must always be used last before the Faraday Adapter" do
76
+ it "must always be used as the last handler" do
77
77
  client.middleware.handlers.reverse.index(Restforce::Middleware::Logger).
78
- should eq 1
78
+ should eq 0
79
79
  end
80
80
  end
81
81
  end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Restforce::ErrorCode do
6
+ describe "mapping of error codes to classes" do
7
+ subject(:error_exception_classes) { described_class::ERROR_EXCEPTION_CLASSES }
8
+
9
+ let(:exception_classes) do
10
+ described_class.constants.
11
+ map { |constant_name| described_class.const_get(constant_name) }.
12
+ select { |constant| constant.is_a?(Class) }
13
+ end
14
+
15
+ it "maps all defined exception classes to an error code" do
16
+ exception_classes.each do |exception_class|
17
+ expect(error_exception_classes.values).to include(exception_class)
18
+ end
19
+ end
20
+
21
+ it "maps all error codes to a defined exception class" do
22
+ error_exception_classes.each_value do |mapped_exception_class|
23
+ expect(exception_classes).to include(mapped_exception_class)
24
+ end
25
+ end
26
+ end
27
+
28
+ describe '.get_exception_class' do
29
+ context 'when a non-existent error code is looked up' do
30
+ let(:new_error_code) { 'ANOTHER_NEW_ERROR_CODE' }
31
+ subject { described_class.get_exception_class(new_error_code) }
32
+
33
+ it { should be Restforce::ResponseError }
34
+
35
+ it 'outputs a warning' do
36
+ expect(Warning).to receive(:warn)
37
+ subject
38
+ end
39
+ end
40
+
41
+ context 'when a known error code is looked up' do
42
+ let(:existing_error_code) { "ALL_OR_NONE_OPERATION_ROLLED_BACK" }
43
+ let(:existing_error) { described_class::AllOrNoneOperationRolledBack }
44
+
45
+ subject do
46
+ described_class.get_exception_class(existing_error_code)
47
+ end
48
+
49
+ it { should < Restforce::ResponseError }
50
+
51
+ it 'returns existing error' do
52
+ should be(existing_error)
53
+ end
54
+
55
+ it 'does not output a warning' do
56
+ expect(Warning).to_not receive(:warn)
57
+ subject
58
+ end
59
+ end
60
+ end
61
+ end
@@ -57,10 +57,10 @@ describe Restforce::Middleware::Authentication do
57
57
  end
58
58
 
59
59
  its(:handlers) {
60
- should include FaradayMiddleware::ParseJson,
61
- Faraday::Adapter::NetHttp
60
+ should include FaradayMiddleware::ParseJson
62
61
  }
63
62
  its(:handlers) { should_not include Restforce::Middleware::Logger }
63
+ its(:adapter) { should eq Faraday::Adapter::NetHttp }
64
64
  end
65
65
 
66
66
  context 'with logging enabled' do
@@ -70,8 +70,9 @@ describe Restforce::Middleware::Authentication do
70
70
 
71
71
  its(:handlers) {
72
72
  should include FaradayMiddleware::ParseJson,
73
- Restforce::Middleware::Logger, Faraday::Adapter::NetHttp
73
+ Restforce::Middleware::Logger
74
74
  }
75
+ its(:adapter) { should eq Faraday::Adapter::NetHttp }
75
76
  end
76
77
 
77
78
  context 'with specified adapter' do
@@ -80,8 +81,9 @@ describe Restforce::Middleware::Authentication do
80
81
  end
81
82
 
82
83
  its(:handlers) {
83
- should include FaradayMiddleware::ParseJson, Faraday::Adapter::Typhoeus
84
+ should include FaradayMiddleware::ParseJson
84
85
  }
86
+ its(:adapter) { should eq Faraday::Adapter::Typhoeus }
85
87
  end
86
88
  end
87
89
 
@@ -94,7 +96,7 @@ describe Restforce::Middleware::Authentication do
94
96
  context 'when response.body is present' do
95
97
  let(:response) {
96
98
  Faraday::Response.new(
97
- body: { 'error' => 'error', 'error_description' => 'description' },
99
+ response_body: { 'error' => 'error', 'error_description' => 'description' },
98
100
  status: 401
99
101
  )
100
102
  }
@@ -85,5 +85,14 @@ describe Restforce::Middleware::RaiseError do
85
85
  "(error code missing): #{body}"
86
86
  end
87
87
  end
88
+
89
+ context 'when error code is not already defined' do
90
+ let(:body) { { 'errorCode' => 'SOMETHING_UNDEFINED' } }
91
+ let(:status) { 400 }
92
+
93
+ it 'raises a generic Restforce::ResponseError' do
94
+ expect { on_complete }.to raise_error Restforce::ResponseError
95
+ end
96
+ end
88
97
  end
89
98
  end
@@ -6,7 +6,7 @@ describe Restforce::SignedRequest do
6
6
  let(:client_secret) { 'foo' }
7
7
  let(:digest) do
8
8
  if RUBY_VERSION < '2.1'
9
- OpenSSL::Digest::Digest.new('sha256')
9
+ OpenSSL::Digest.new('Digest', 'sha256')
10
10
  else
11
11
  OpenSSL::Digest.new('sha256')
12
12
  end
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: restforce
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.3.0
4
+ version: 5.0.0
5
5
  platform: ruby
6
6
  authors:
7
- - Eric J. Holmes
8
7
  - Tim Rogers
9
- autorequire:
8
+ - Eric J. Holmes
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2021-02-10 00:00:00.000000000 Z
12
+ date: 2020-07-10 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: faraday
@@ -17,7 +17,7 @@ dependencies:
17
17
  requirements:
18
18
  - - "<="
19
19
  - !ruby/object:Gem::Version
20
- version: '1.0'
20
+ version: '2.0'
21
21
  - - ">="
22
22
  - !ruby/object:Gem::Version
23
23
  version: 0.9.0
@@ -27,7 +27,7 @@ dependencies:
27
27
  requirements:
28
28
  - - "<="
29
29
  - !ruby/object:Gem::Version
30
- version: '1.0'
30
+ version: '2.0'
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
33
  version: 0.9.0
@@ -40,7 +40,7 @@ dependencies:
40
40
  version: 0.8.8
41
41
  - - "<="
42
42
  - !ruby/object:Gem::Version
43
- version: '1.0'
43
+ version: '2.0'
44
44
  type: :runtime
45
45
  prerelease: false
46
46
  version_requirements: !ruby/object:Gem::Requirement
@@ -50,21 +50,7 @@ dependencies:
50
50
  version: 0.8.8
51
51
  - - "<="
52
52
  - !ruby/object:Gem::Version
53
- version: '1.0'
54
- - !ruby/object:Gem::Dependency
55
- name: json
56
- requirement: !ruby/object:Gem::Requirement
57
- requirements:
58
- - - ">="
59
- - !ruby/object:Gem::Version
60
- version: 1.7.5
61
- type: :runtime
62
- prerelease: false
63
- version_requirements: !ruby/object:Gem::Requirement
64
- requirements:
65
- - - ">="
66
- - !ruby/object:Gem::Version
67
- version: 1.7.5
53
+ version: '2.0'
68
54
  - !ruby/object:Gem::Dependency
69
55
  name: jwt
70
56
  requirement: !ruby/object:Gem::Requirement
@@ -147,51 +133,52 @@ dependencies:
147
133
  requirements:
148
134
  - - "~>"
149
135
  - !ruby/object:Gem::Version
150
- version: 0.77.0
136
+ version: 0.87.1
151
137
  type: :development
152
138
  prerelease: false
153
139
  version_requirements: !ruby/object:Gem::Requirement
154
140
  requirements:
155
141
  - - "~>"
156
142
  - !ruby/object:Gem::Version
157
- version: 0.77.0
143
+ version: 0.87.1
158
144
  - !ruby/object:Gem::Dependency
159
145
  name: simplecov
160
146
  requirement: !ruby/object:Gem::Requirement
161
147
  requirements:
162
148
  - - "~>"
163
149
  - !ruby/object:Gem::Version
164
- version: 0.17.1
150
+ version: 0.18.2
165
151
  type: :development
166
152
  prerelease: false
167
153
  version_requirements: !ruby/object:Gem::Requirement
168
154
  requirements:
169
155
  - - "~>"
170
156
  - !ruby/object:Gem::Version
171
- version: 0.17.1
157
+ version: 0.18.2
172
158
  - !ruby/object:Gem::Dependency
173
159
  name: webmock
174
160
  requirement: !ruby/object:Gem::Requirement
175
161
  requirements:
176
162
  - - "~>"
177
163
  - !ruby/object:Gem::Version
178
- version: 3.7.6
164
+ version: 3.8.3
179
165
  type: :development
180
166
  prerelease: false
181
167
  version_requirements: !ruby/object:Gem::Requirement
182
168
  requirements:
183
169
  - - "~>"
184
170
  - !ruby/object:Gem::Version
185
- version: 3.7.6
186
- description: A lightweight ruby client for the Salesforce REST API.
171
+ version: 3.8.3
172
+ description: A lightweight Ruby client for the Salesforce REST API
187
173
  email:
174
+ - me@timrogers.co.uk
188
175
  - eric@ejholmes.net
189
- - tim@gocardless.com
190
176
  executables: []
191
177
  extensions: []
192
178
  extra_rdoc_files: []
193
179
  files:
194
180
  - ".circleci/config.yml"
181
+ - ".github/ISSUE_TEMPLATE/unhandled-salesforce-error.md"
195
182
  - ".gitignore"
196
183
  - ".rubocop.yml"
197
184
  - ".rubocop_todo.yml"
@@ -203,6 +190,7 @@ files:
203
190
  - LICENSE
204
191
  - README.md
205
192
  - Rakefile
193
+ - UPGRADING.md
206
194
  - lib/restforce.rb
207
195
  - lib/restforce/abstract_client.rb
208
196
  - lib/restforce/attachment.rb
@@ -221,6 +209,8 @@ files:
221
209
  - lib/restforce/config.rb
222
210
  - lib/restforce/data/client.rb
223
211
  - lib/restforce/document.rb
212
+ - lib/restforce/error_code.rb
213
+ - lib/restforce/file_part.rb
224
214
  - lib/restforce/mash.rb
225
215
  - lib/restforce/middleware.rb
226
216
  - lib/restforce/middleware/authentication.rb
@@ -240,7 +230,6 @@ files:
240
230
  - lib/restforce/signed_request.rb
241
231
  - lib/restforce/sobject.rb
242
232
  - lib/restforce/tooling/client.rb
243
- - lib/restforce/upload_io.rb
244
233
  - lib/restforce/version.rb
245
234
  - restforce.gemspec
246
235
  - script/bootstrap
@@ -306,6 +295,7 @@ files:
306
295
  - spec/unit/config_spec.rb
307
296
  - spec/unit/data/client_spec.rb
308
297
  - spec/unit/document_spec.rb
298
+ - spec/unit/error_code_spec.rb
309
299
  - spec/unit/mash_spec.rb
310
300
  - spec/unit/middleware/authentication/jwt_bearer_spec.rb
311
301
  - spec/unit/middleware/authentication/password_spec.rb
@@ -321,13 +311,13 @@ files:
321
311
  - spec/unit/signed_request_spec.rb
322
312
  - spec/unit/sobject_spec.rb
323
313
  - spec/unit/tooling/client_spec.rb
324
- homepage: http://restforce.org/
314
+ homepage: https://restforce.github.io/
325
315
  licenses:
326
316
  - MIT
327
317
  metadata:
328
318
  source_code_uri: https://github.com/restforce/restforce
329
319
  changelog_uri: https://github.com/restforce/restforce/blob/master/CHANGELOG.md
330
- post_install_message:
320
+ post_install_message:
331
321
  rdoc_options: []
332
322
  require_paths:
333
323
  - lib
@@ -335,17 +325,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
335
325
  requirements:
336
326
  - - ">="
337
327
  - !ruby/object:Gem::Version
338
- version: '2.4'
328
+ version: '2.5'
339
329
  required_rubygems_version: !ruby/object:Gem::Requirement
340
330
  requirements:
341
331
  - - ">="
342
332
  - !ruby/object:Gem::Version
343
333
  version: '0'
344
334
  requirements: []
345
- rubygems_version: 3.2.5
346
- signing_key:
335
+ rubygems_version: 3.1.2
336
+ signing_key:
347
337
  specification_version: 4
348
- summary: A lightweight ruby client for the Salesforce REST API.
338
+ summary: A lightweight Ruby client for the Salesforce REST API
349
339
  test_files:
350
340
  - spec/fixtures/auth_error_response.json
351
341
  - spec/fixtures/auth_success_response.json
@@ -406,6 +396,7 @@ test_files:
406
396
  - spec/unit/config_spec.rb
407
397
  - spec/unit/data/client_spec.rb
408
398
  - spec/unit/document_spec.rb
399
+ - spec/unit/error_code_spec.rb
409
400
  - spec/unit/mash_spec.rb
410
401
  - spec/unit/middleware/authentication/jwt_bearer_spec.rb
411
402
  - spec/unit/middleware/authentication/password_spec.rb