restforce 2.5.4 → 4.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.
Files changed (92) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +56 -0
  3. data/.rubocop.yml +27 -14
  4. data/.rubocop_todo.yml +128 -81
  5. data/CHANGELOG.md +37 -3
  6. data/CONTRIBUTING.md +3 -3
  7. data/Gemfile +4 -2
  8. data/Guardfile +3 -1
  9. data/LICENSE +1 -1
  10. data/README.md +120 -19
  11. data/Rakefile +2 -1
  12. data/lib/restforce.rb +23 -1
  13. data/lib/restforce/abstract_client.rb +3 -0
  14. data/lib/restforce/attachment.rb +3 -0
  15. data/lib/restforce/client.rb +2 -0
  16. data/lib/restforce/collection.rb +3 -1
  17. data/lib/restforce/concerns/api.rb +20 -14
  18. data/lib/restforce/concerns/authentication.rb +2 -0
  19. data/lib/restforce/concerns/base.rb +2 -0
  20. data/lib/restforce/concerns/batch_api.rb +87 -0
  21. data/lib/restforce/concerns/caching.rb +4 -2
  22. data/lib/restforce/concerns/canvas.rb +3 -0
  23. data/lib/restforce/concerns/connection.rb +26 -20
  24. data/lib/restforce/concerns/picklists.rb +9 -6
  25. data/lib/restforce/concerns/streaming.rb +60 -1
  26. data/lib/restforce/concerns/verbs.rb +3 -1
  27. data/lib/restforce/config.rb +4 -1
  28. data/lib/restforce/data/client.rb +2 -0
  29. data/lib/restforce/document.rb +3 -0
  30. data/lib/restforce/mash.rb +2 -0
  31. data/lib/restforce/middleware.rb +2 -0
  32. data/lib/restforce/middleware/authentication.rb +8 -6
  33. data/lib/restforce/middleware/authentication/password.rb +2 -0
  34. data/lib/restforce/middleware/authentication/token.rb +2 -0
  35. data/lib/restforce/middleware/authorization.rb +3 -1
  36. data/lib/restforce/middleware/caching.rb +3 -1
  37. data/lib/restforce/middleware/custom_headers.rb +2 -0
  38. data/lib/restforce/middleware/gzip.rb +5 -3
  39. data/lib/restforce/middleware/instance_url.rb +7 -3
  40. data/lib/restforce/middleware/logger.rb +2 -0
  41. data/lib/restforce/middleware/mashify.rb +2 -0
  42. data/lib/restforce/middleware/multipart.rb +8 -4
  43. data/lib/restforce/middleware/raise_error.rb +26 -8
  44. data/lib/restforce/patches/parts.rb +2 -0
  45. data/lib/restforce/signed_request.rb +3 -0
  46. data/lib/restforce/sobject.rb +3 -0
  47. data/lib/restforce/tooling/client.rb +5 -3
  48. data/lib/restforce/upload_io.rb +2 -0
  49. data/lib/restforce/version.rb +3 -1
  50. data/restforce.gemspec +19 -12
  51. data/spec/fixtures/sobject/sobject_describe_success_response.json +48 -1
  52. data/spec/integration/abstract_client_spec.rb +51 -7
  53. data/spec/integration/data/client_spec.rb +24 -5
  54. data/spec/spec_helper.rb +2 -0
  55. data/spec/support/client_integration.rb +2 -0
  56. data/spec/support/concerns.rb +2 -0
  57. data/spec/support/event_machine.rb +2 -0
  58. data/spec/support/fixture_helpers.rb +4 -2
  59. data/spec/support/matchers.rb +2 -0
  60. data/spec/support/middleware.rb +3 -1
  61. data/spec/support/mock_cache.rb +4 -2
  62. data/spec/unit/abstract_client_spec.rb +2 -0
  63. data/spec/unit/attachment_spec.rb +2 -0
  64. data/spec/unit/collection_spec.rb +5 -3
  65. data/spec/unit/concerns/api_spec.rb +40 -11
  66. data/spec/unit/concerns/authentication_spec.rb +4 -2
  67. data/spec/unit/concerns/base_spec.rb +2 -0
  68. data/spec/unit/concerns/batch_api_spec.rb +107 -0
  69. data/spec/unit/concerns/caching_spec.rb +2 -0
  70. data/spec/unit/concerns/canvas_spec.rb +3 -1
  71. data/spec/unit/concerns/connection_spec.rb +5 -3
  72. data/spec/unit/concerns/streaming_spec.rb +115 -1
  73. data/spec/unit/config_spec.rb +10 -8
  74. data/spec/unit/data/client_spec.rb +2 -0
  75. data/spec/unit/document_spec.rb +2 -0
  76. data/spec/unit/mash_spec.rb +3 -1
  77. data/spec/unit/middleware/authentication/password_spec.rb +2 -0
  78. data/spec/unit/middleware/authentication/token_spec.rb +2 -0
  79. data/spec/unit/middleware/authentication_spec.rb +3 -1
  80. data/spec/unit/middleware/authorization_spec.rb +2 -0
  81. data/spec/unit/middleware/custom_headers_spec.rb +3 -1
  82. data/spec/unit/middleware/gzip_spec.rb +4 -2
  83. data/spec/unit/middleware/instance_url_spec.rb +2 -0
  84. data/spec/unit/middleware/logger_spec.rb +2 -0
  85. data/spec/unit/middleware/mashify_spec.rb +3 -1
  86. data/spec/unit/middleware/raise_error_spec.rb +34 -11
  87. data/spec/unit/signed_request_spec.rb +2 -0
  88. data/spec/unit/sobject_spec.rb +5 -3
  89. data/spec/unit/tooling/client_spec.rb +2 -0
  90. metadata +38 -20
  91. data/.travis.yml +0 -16
  92. data/Gemfile.travis +0 -8
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Restforce
2
4
  # Authentication middleware used if username and password flow is used
3
5
  class Middleware::Authentication::Password < Restforce::Middleware::Authentication
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Restforce
2
4
  # Authentication middleware used if oauth_token and refresh_token are set
3
5
  class Middleware::Authentication::Token < Restforce::Middleware::Authentication
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Restforce
2
4
  # Piece of middleware that simply injects the OAuth token into the request
3
5
  # headers.
4
6
  class Middleware::Authorization < Restforce::Middleware
5
- AUTH_HEADER = 'Authorization'.freeze
7
+ AUTH_HEADER = 'Authorization'
6
8
 
7
9
  def call(env)
8
10
  env[:request_headers][AUTH_HEADER] = %(OAuth #{token})
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Restforce
2
4
  class Middleware::Caching < FaradayMiddleware::Caching
3
5
  def call(env)
@@ -6,7 +8,7 @@ module Restforce
6
8
  end
7
9
 
8
10
  def expire(key)
9
- cache.delete(key) if cache
11
+ cache&.delete(key)
10
12
  end
11
13
 
12
14
  # We don't want to cache requests for different clients, so append the
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Restforce
2
4
  # Middleware that allows you to specify custom request headers
3
5
  # when initializing Restforce client
@@ -1,11 +1,13 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'zlib'
2
4
 
3
5
  module Restforce
4
6
  # Middleware to uncompress GZIP compressed responses from Salesforce.
5
7
  class Middleware::Gzip < Restforce::Middleware
6
- ACCEPT_ENCODING_HEADER = 'Accept-Encoding'.freeze
7
- CONTENT_ENCODING_HEADER = 'Content-Encoding'.freeze
8
- ENCODING = 'gzip'.freeze
8
+ ACCEPT_ENCODING_HEADER = 'Accept-Encoding'
9
+ CONTENT_ENCODING_HEADER = 'Content-Encoding'
10
+ ENCODING = 'gzip'
9
11
 
10
12
  def call(env)
11
13
  env[:request_headers][ACCEPT_ENCODING_HEADER] = ENCODING if @options[:compress]
@@ -1,16 +1,20 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Restforce
2
4
  # Middleware which asserts that the instance_url is always set
3
5
  class Middleware::InstanceURL < Restforce::Middleware
4
6
  def call(env)
5
7
  # If the connection url_prefix isn't set, we must not be authenticated.
6
- raise Restforce::UnauthorizedError,
7
- 'Connection prefix not set' unless url_prefix_set?
8
+ unless url_prefix_set?
9
+ raise Restforce::UnauthorizedError,
10
+ 'Connection prefix not set'
11
+ end
8
12
 
9
13
  @app.call(env)
10
14
  end
11
15
 
12
16
  def url_prefix_set?
13
- !!(connection.url_prefix && connection.url_prefix.host)
17
+ !!(connection.url_prefix&.host)
14
18
  end
15
19
  end
16
20
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'forwardable'
2
4
 
3
5
  module Restforce
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Restforce
2
4
  # Middleware the converts sobject records from JSON into Restforce::SObject objects
3
5
  # and collections of records into Restforce::Collection objects.
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Restforce
2
4
  class Middleware::Multipart < Faraday::Request::UrlEncoded
3
- self.mime_type = 'multipart/form-data'.freeze
4
- DEFAULT_BOUNDARY = "--boundary_string".freeze
5
- JSON_CONTENT_TYPE = { "Content-Type" => "application/json" }
5
+ self.mime_type = 'multipart/form-data'
6
+ DEFAULT_BOUNDARY = "--boundary_string"
7
+ JSON_CONTENT_TYPE = { "Content-Type" => "application/json" }.freeze
6
8
 
7
9
  def call(env)
8
10
  match_content_type(env) do |params|
@@ -46,9 +48,11 @@ module Restforce
46
48
 
47
49
  # Files
48
50
  params.each do |k, v|
51
+ next unless v.respond_to? :content_type
52
+
49
53
  parts << Faraday::Parts::Part.new(boundary,
50
54
  k.to_s,
51
- v) if v.respond_to? :content_type
55
+ v)
52
56
  end
53
57
 
54
58
  parts << Faraday::Parts::EpiloguePart.new(boundary)
@@ -1,26 +1,35 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Restforce
2
4
  class Middleware::RaiseError < Faraday::Response::Middleware
3
5
  def on_complete(env)
4
6
  @env = env
5
7
  case env[:status]
6
8
  when 300
7
- raise Faraday::Error::ClientError.new("300: The external ID provided matches " \
8
- "more than one record",
9
- response_values)
9
+ raise Restforce::MatchesMultipleError.new(
10
+ "300: The external ID provided matches more than one record",
11
+ response_values
12
+ )
10
13
  when 401
11
14
  raise Restforce::UnauthorizedError, message
12
15
  when 404
13
- raise Faraday::Error::ResourceNotFound, message
16
+ raise Restforce::NotFoundError, message
14
17
  when 413
15
- raise Faraday::Error::ClientError.new("413: Request Entity Too Large",
16
- response_values)
18
+ raise Restforce::EntityTooLargeError.new(
19
+ "413: Request Entity Too Large",
20
+ response_values
21
+ )
17
22
  when 400...600
18
- raise Faraday::Error::ClientError.new(message, response_values)
23
+ klass = exception_class_for_error_code(body['errorCode'])
24
+ raise klass.new(message, response_values)
19
25
  end
20
26
  end
21
27
 
22
28
  def message
23
- "#{body['errorCode']}: #{body['message']}"
29
+ message = "#{body['errorCode']}: #{body['message']}"
30
+ message << "\nRESPONSE: #{JSON.dump(@env[:body])}"
31
+ rescue StandardError
32
+ message # if JSON.dump fails, return message without extra detail
24
33
  end
25
34
 
26
35
  def body
@@ -41,5 +50,14 @@ module Restforce
41
50
  body: @env[:body]
42
51
  }
43
52
  end
53
+
54
+ ERROR_CODE_MATCHER = /\A[A-Z_]+\z/.freeze
55
+
56
+ def exception_class_for_error_code(error_code)
57
+ return Restforce::ResponseError unless ERROR_CODE_MATCHER.match?(error_code)
58
+
59
+ constant_name = error_code.split('_').map(&:capitalize).join.to_sym
60
+ Restforce::ErrorCode.const_get(constant_name)
61
+ end
44
62
  end
45
63
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Faraday
2
4
  module Parts
3
5
  module Part
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'openssl'
2
4
  require 'base64'
3
5
  require 'json'
@@ -25,6 +27,7 @@ module Restforce
25
27
  # Returns nil if the signed request is invalid.
26
28
  def decode
27
29
  return nil if signature != hmac
30
+
28
31
  JSON.parse(Base64.decode64(payload))
29
32
  end
30
33
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Restforce
2
4
  class SObject < Restforce::Mash
3
5
  def sobject_type
@@ -61,6 +63,7 @@ module Restforce
61
63
 
62
64
  def ensure_id
63
65
  return true if self.Id?
66
+
64
67
  raise ArgumentError, 'You need to query the Id for the record first.'
65
68
  end
66
69
  end
@@ -1,11 +1,13 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Restforce
2
4
  module Tooling
3
5
  class Client < AbstractClient
4
6
  private
5
7
 
6
- def api_path(path)
7
- super("tooling/#{path}")
8
- end
8
+ def api_path(path)
9
+ super("tooling/#{path}")
10
+ end
9
11
  end
10
12
  end
11
13
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'faraday/upload_io'
2
4
 
3
5
  module Restforce
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Restforce
2
- VERSION = '2.5.4'.freeze
4
+ VERSION = '4.0.0'
3
5
  end
@@ -1,33 +1,40 @@
1
- # -*- encoding: utf-8 -*-
2
- require File.expand_path('../lib/restforce/version', __FILE__)
1
+ # frozen_string_literal: true
2
+
3
+ require File.expand_path('lib/restforce/version', __dir__)
3
4
 
4
5
  Gem::Specification.new do |gem|
5
6
  gem.authors = ["Eric J. Holmes", "Tim Rogers"]
6
7
  gem.email = ["eric@ejholmes.net", "tim@gocardless.com"]
7
- gem.description = %q{A lightweight ruby client for the Salesforce REST API.}
8
- gem.summary = %q{A lightweight ruby client for the Salesforce REST API.}
8
+ gem.description = 'A lightweight ruby client for the Salesforce REST API.'
9
+ gem.summary = 'A lightweight ruby client for the Salesforce REST API.'
9
10
  gem.homepage = "http://restforce.org/"
10
11
  gem.license = "MIT"
11
12
 
12
- gem.files = `git ls-files`.split($\)
13
- gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.files = `git ls-files`.split($OUTPUT_RECORD_SEPARATOR)
14
+ gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
14
15
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
15
16
  gem.name = "restforce"
16
17
  gem.require_paths = ["lib"]
17
18
  gem.version = Restforce::VERSION
18
19
 
19
- gem.required_ruby_version = '>= 2.0'
20
+ gem.metadata = {
21
+ 'source_code_uri' => 'https://github.com/restforce/restforce',
22
+ 'changelog_uri' => 'https://github.com/restforce/restforce/blob/master/CHANGELOG.md'
23
+ }
24
+
25
+ gem.required_ruby_version = '>= 2.4'
20
26
 
21
- gem.add_dependency 'faraday', ['>= 0.9.0', '<= 1.0']
27
+ gem.add_dependency 'faraday', '<= 1.0', '>= 0.9.0'
22
28
  gem.add_dependency 'faraday_middleware', ['>= 0.8.8', '<= 1.0']
23
29
 
24
30
  gem.add_dependency 'json', '>= 1.7.5'
25
31
 
26
32
  gem.add_dependency 'hashie', ['>= 1.2.0', '< 4.0']
27
33
 
28
- gem.add_development_dependency 'rspec', '~> 2.14.0'
29
- gem.add_development_dependency 'webmock', '~> 1.13.0'
30
- gem.add_development_dependency 'simplecov', '~> 0.7.1'
31
- gem.add_development_dependency 'rubocop', '~> 0.31.0'
32
34
  gem.add_development_dependency 'faye' unless RUBY_PLATFORM == 'java'
35
+ gem.add_development_dependency 'rspec', '~> 2.14.0'
36
+ gem.add_development_dependency 'rspec_junit_formatter', '~> 0.3.0'
37
+ gem.add_development_dependency 'rubocop', '~> 0.75.0'
38
+ gem.add_development_dependency 'simplecov', '~> 0.17.1'
39
+ gem.add_development_dependency 'webmock', '~> 3.7.6'
33
40
  end
@@ -767,7 +767,48 @@
767
767
  "label" : "three",
768
768
  "defaultValue" : false,
769
769
  "validFor" : null
770
- } ],
770
+ }, {
771
+ "value" : "control_four",
772
+ "active" : true,
773
+ "label" : "control_four",
774
+ "defaultValue" : false,
775
+ "validFor" : null
776
+ }, {
777
+ "value" : "control_five",
778
+ "active" : true,
779
+ "label" : "control_five",
780
+ "defaultValue" : false,
781
+ "validFor" : null
782
+ }, {
783
+ "value" : "control_six",
784
+ "active" : true,
785
+ "label" : "control_six",
786
+ "defaultValue" : false,
787
+ "validFor" : null
788
+ }, {
789
+ "value" : "control_seven",
790
+ "active" : true,
791
+ "label" : "control_seven",
792
+ "defaultValue" : false,
793
+ "validFor" : null
794
+ }, {
795
+ "value" : "control_eight",
796
+ "active" : true,
797
+ "label" : "control_eight",
798
+ "defaultValue" : false,
799
+ "validFor" : null
800
+ }, {
801
+ "value" : "control_nine",
802
+ "active" : true,
803
+ "label" : "control_nine",
804
+ "defaultValue" : false,
805
+ "validFor" : null
806
+ }, {
807
+ "value" : "control_ten",
808
+ "active" : true,
809
+ "label" : "control_ten",
810
+ "defaultValue" : false,
811
+ "validFor" : null}],
771
812
  "referenceTo" : [ ],
772
813
  "relationshipName" : null,
773
814
  "relationshipOrder" : null,
@@ -883,6 +924,12 @@
883
924
  "label" : "nine",
884
925
  "defaultValue" : false,
885
926
  "validFor" : "QAAA"
927
+ }, {
928
+ "value" : "ten",
929
+ "active" : true,
930
+ "label" : "nine",
931
+ "defaultValue" : false,
932
+ "validFor" : "AEAA"
886
933
  } ],
887
934
  "referenceTo" : [ ],
888
935
  "relationshipName" : null,
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  shared_examples_for Restforce::AbstractClient do
@@ -35,7 +37,7 @@ shared_examples_for Restforce::AbstractClient do
35
37
  end
36
38
 
37
39
  describe '.get_updated' do
38
- let(:start_date) { Time.new(2015, 8, 17, 0, 0, 0, "+02:00") }
40
+ let(:start_date) { Time.new(2015, 8, 17, 0, 0, 0, "+02:00") }
39
41
  let(:end_date) { Time.new(2016, 8, 19, 0, 0, 0, "+02:00") }
40
42
  end_string = '2016-08-18T22:00:00Z'
41
43
  start_string = '2015-08-16T22:00:00Z'
@@ -46,7 +48,7 @@ shared_examples_for Restforce::AbstractClient do
46
48
  end
47
49
 
48
50
  describe '.get_deleted' do
49
- let(:start_date) { Time.new(2015, 8, 17, 0, 0, 0, "+02:00") }
51
+ let(:start_date) { Time.new(2015, 8, 17, 0, 0, 0, "+02:00") }
50
52
  let(:end_date) { Time.new(2016, 8, 19, 0, 0, 0, "+02:00") }
51
53
  end_string = '2016-08-18T22:00:00Z'
52
54
  start_string = '2015-08-16T22:00:00Z'
@@ -94,7 +96,7 @@ shared_examples_for Restforce::AbstractClient do
94
96
  subject do
95
97
  client.create('Account', Name: 'Foobar',
96
98
  Blob: Restforce::UploadIO.new(
97
- File.expand_path('../../fixtures/blob.jpg', __FILE__),
99
+ File.expand_path('../fixtures/blob.jpg', __dir__),
98
100
  'image/jpeg'
99
101
  ))
100
102
  end
@@ -168,7 +170,8 @@ shared_examples_for Restforce::AbstractClient do
168
170
  context 'when updated' do
169
171
  requests 'sobjects/Account/External__c/foobar',
170
172
  method: :patch,
171
- with_body: "{\"Name\":\"Foobar\"}"
173
+ with_body: "{\"Name\":\"Foobar\"}",
174
+ fixture: "sobject/upsert_updated_success_response"
172
175
 
173
176
  context 'with symbol external Id key' do
174
177
  subject do
@@ -206,6 +209,24 @@ shared_examples_for Restforce::AbstractClient do
206
209
  end
207
210
  end
208
211
  end
212
+
213
+ context 'when created with a space in the id' do
214
+ requests 'sobjects/Account/External__c/foo%20bar',
215
+ method: :patch,
216
+ with_body: "{\"Name\":\"Foobar\"}",
217
+ fixture: 'sobject/upsert_created_success_response'
218
+
219
+ [:External__c, 'External__c', :external__c, 'external__c'].each do |key|
220
+ context "with #{key.inspect} as the external id" do
221
+ subject do
222
+ client.upsert!('Account', 'External__c', key => 'foo bar',
223
+ :Name => 'Foobar')
224
+ end
225
+
226
+ it { should eq 'foo' }
227
+ end
228
+ end
229
+ end
209
230
  end
210
231
 
211
232
  describe '.destroy!' do
@@ -226,6 +247,13 @@ shared_examples_for Restforce::AbstractClient do
226
247
 
227
248
  it { should be_true }
228
249
  end
250
+
251
+ context 'with a space in the id' do
252
+ subject(:destroy!) { client.destroy!('Account', '001D000000 INjVe') }
253
+ requests 'sobjects/Account/001D000000%20INjVe', method: :delete
254
+
255
+ it { should be_true }
256
+ end
229
257
  end
230
258
 
231
259
  describe '.destroy' do
@@ -263,6 +291,14 @@ shared_examples_for Restforce::AbstractClient do
263
291
  subject { client.find('Account', '1234', 'External_Field__c') }
264
292
  it { should be_a Hash }
265
293
  end
294
+
295
+ context 'with a space in an external id' do
296
+ requests 'sobjects/Account/External_Field__c/12%2034',
297
+ fixture: 'sobject/sobject_find_success_response'
298
+
299
+ subject { client.find('Account', '12 34', 'External_Field__c') }
300
+ it { should be_a Hash }
301
+ end
266
302
  end
267
303
 
268
304
  describe '.select' do
@@ -281,6 +317,14 @@ shared_examples_for Restforce::AbstractClient do
281
317
  subject { client.select('Account', '1234', ['External_Field__c']) }
282
318
  it { should be_a Hash }
283
319
  end
320
+
321
+ context 'with a space in the id' do
322
+ requests 'sobjects/Account/12%2034',
323
+ fixture: 'sobject/sobject_select_success_response'
324
+
325
+ subject { client.select('Account', '12 34', nil, nil) }
326
+ it { should be_a Hash }
327
+ end
284
328
  end
285
329
 
286
330
  context 'when an external id is specified' do
@@ -379,11 +423,11 @@ shared_examples_for Restforce::AbstractClient do
379
423
 
380
424
  before do
381
425
  @query = stub_api_request('query\?q=SELECT%20some,%20fields%20FROM%20object').
382
- with(headers: { 'Authorization' => "OAuth #{oauth_token}" }).
383
- to_return(status: 401,
426
+ with(headers: { 'Authorization' => "OAuth #{oauth_token}" }).
427
+ to_return(status: 401,
384
428
  body: fixture('expired_session_response'),
385
429
  headers: { 'Content-Type' => 'application/json' }).then.
386
- to_return(status: 200,
430
+ to_return(status: 200,
387
431
  body: fixture('sobject/query_success_response'),
388
432
  headers: { 'Content-Type' => 'application/json' })
389
433