restforce 1.3.0 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of restforce might be problematic. Click here for more details.
- data/.travis.yml +1 -0
- data/CHANGELOG.md +7 -1
- data/Gemfile +4 -0
- data/Guardfile +11 -0
- data/README.md +19 -8
- data/lib/restforce.rb +44 -14
- data/lib/restforce/abstract_client.rb +9 -0
- data/lib/restforce/client.rb +1 -95
- data/lib/restforce/{client → concerns}/api.rb +9 -9
- data/lib/restforce/{client → concerns}/authentication.rb +9 -9
- data/lib/restforce/concerns/base.rb +58 -0
- data/lib/restforce/{client → concerns}/caching.rb +4 -4
- data/lib/restforce/concerns/canvas.rb +12 -0
- data/lib/restforce/{client → concerns}/connection.rb +13 -12
- data/lib/restforce/{client → concerns}/picklists.rb +1 -1
- data/lib/restforce/{client → concerns}/streaming.rb +3 -3
- data/lib/restforce/{client → concerns}/verbs.rb +4 -4
- data/lib/restforce/config.rb +40 -10
- data/lib/restforce/data/client.rb +18 -0
- data/lib/restforce/middleware/authentication.rb +9 -2
- data/lib/restforce/sobject.rb +1 -1
- data/lib/restforce/tooling/client.rb +13 -0
- data/lib/restforce/version.rb +1 -1
- data/spec/{lib/client_spec.rb → integration/abstract_client_spec.rb} +21 -214
- data/spec/integration/data/client_spec.rb +90 -0
- data/spec/spec_helper.rb +0 -14
- data/spec/support/client_integration.rb +45 -0
- data/spec/support/concerns.rb +18 -0
- data/spec/support/event_machine.rb +14 -0
- data/spec/support/middleware.rb +18 -1
- data/spec/unit/abstract_client_spec.rb +11 -0
- data/spec/{lib → unit}/attachment_spec.rb +3 -6
- data/spec/unit/collection_spec.rb +50 -0
- data/spec/unit/concerns/api_spec.rb +222 -0
- data/spec/unit/concerns/authentication_spec.rb +98 -0
- data/spec/unit/concerns/base_spec.rb +50 -0
- data/spec/unit/concerns/caching_spec.rb +29 -0
- data/spec/unit/concerns/canvas_spec.rb +30 -0
- data/spec/unit/concerns/connection_spec.rb +14 -0
- data/spec/{lib → unit}/config_spec.rb +13 -23
- data/spec/unit/data/client_spec.rb +10 -0
- data/spec/{lib → unit}/mash_spec.rb +0 -0
- data/spec/{lib → unit}/middleware/authentication/password_spec.rb +0 -4
- data/spec/{lib → unit}/middleware/authentication/token_spec.rb +0 -4
- data/spec/unit/middleware/authentication_spec.rb +67 -0
- data/spec/unit/middleware/authorization_spec.rb +11 -0
- data/spec/{lib → unit}/middleware/gzip_spec.rb +15 -30
- data/spec/unit/middleware/instance_url_spec.rb +24 -0
- data/spec/{lib → unit}/middleware/logger_spec.rb +4 -7
- data/spec/unit/middleware/mashify_spec.rb +11 -0
- data/spec/{lib → unit}/middleware/raise_error_spec.rb +4 -5
- data/spec/{lib → unit}/signed_request_spec.rb +0 -0
- data/spec/unit/sobject_spec.rb +68 -0
- data/spec/unit/tooling/client_spec.rb +7 -0
- metadata +75 -46
- data/lib/restforce/client/canvas.rb +0 -12
- data/spec/lib/collection_spec.rb +0 -52
- data/spec/lib/middleware/authentication_spec.rb +0 -69
- data/spec/lib/middleware/authorization_spec.rb +0 -17
- data/spec/lib/middleware/instance_url_spec.rb +0 -31
- data/spec/lib/middleware/mashify_spec.rb +0 -28
- data/spec/lib/sobject_spec.rb +0 -122
- data/spec/support/basic_client.rb +0 -37
@@ -1,5 +1,5 @@
|
|
1
1
|
module Restforce
|
2
|
-
|
2
|
+
module Concerns
|
3
3
|
module Caching
|
4
4
|
|
5
5
|
# Public: Runs the block with caching disabled.
|
@@ -8,17 +8,17 @@ module Restforce
|
|
8
8
|
#
|
9
9
|
# Returns the result of the block
|
10
10
|
def without_caching(&block)
|
11
|
-
|
11
|
+
options[:use_cache] = false
|
12
12
|
block.call
|
13
13
|
ensure
|
14
|
-
|
14
|
+
options.delete(:use_cache)
|
15
15
|
end
|
16
16
|
|
17
17
|
private
|
18
18
|
|
19
19
|
# Internal: Cache to use for the caching middleware
|
20
20
|
def cache
|
21
|
-
|
21
|
+
options[:cache]
|
22
22
|
end
|
23
23
|
|
24
24
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Restforce
|
2
|
-
|
2
|
+
module Concerns
|
3
3
|
module Connection
|
4
4
|
|
5
5
|
# Public: The Faraday::Builder instance used for the middleware stack. This
|
@@ -14,36 +14,37 @@ module Restforce
|
|
14
14
|
def middleware
|
15
15
|
connection.builder
|
16
16
|
end
|
17
|
+
alias_method :builder, :middleware
|
17
18
|
|
18
19
|
private
|
19
20
|
|
20
21
|
# Internal: Internal faraday connection where all requests go through
|
21
22
|
def connection
|
22
|
-
@connection ||= Faraday.new(
|
23
|
+
@connection ||= Faraday.new(options[:instance_url], connection_options) do |builder|
|
23
24
|
# Parses JSON into Hashie::Mash structures.
|
24
|
-
builder.use Restforce::Middleware::Mashify, self,
|
25
|
+
builder.use Restforce::Middleware::Mashify, self, options
|
25
26
|
# Handles multipart file uploads for blobs.
|
26
27
|
builder.use Restforce::Middleware::Multipart
|
27
28
|
# Converts the request into JSON.
|
28
29
|
builder.request :json
|
29
30
|
# Handles reauthentication for 403 responses.
|
30
|
-
builder.use authentication_middleware, self,
|
31
|
+
builder.use authentication_middleware, self, options if authentication_middleware
|
31
32
|
# Sets the oauth token in the headers.
|
32
|
-
builder.use Restforce::Middleware::Authorization, self,
|
33
|
+
builder.use Restforce::Middleware::Authorization, self, options
|
33
34
|
# Ensures the instance url is set.
|
34
|
-
builder.use Restforce::Middleware::InstanceURL, self,
|
35
|
+
builder.use Restforce::Middleware::InstanceURL, self, options
|
35
36
|
# Parses returned JSON response into a hash.
|
36
37
|
builder.response :json, :content_type => /\bjson$/
|
37
38
|
# Caches GET requests.
|
38
|
-
builder.use Restforce::Middleware::Caching, cache,
|
39
|
+
builder.use Restforce::Middleware::Caching, cache, options if cache
|
39
40
|
# Follows 30x redirects.
|
40
41
|
builder.use FaradayMiddleware::FollowRedirects
|
41
42
|
# Raises errors for 40x responses.
|
42
43
|
builder.use Restforce::Middleware::RaiseError
|
43
44
|
# Log request/responses
|
44
|
-
builder.use Restforce::Middleware::Logger, Restforce.configuration.logger,
|
45
|
+
builder.use Restforce::Middleware::Logger, Restforce.configuration.logger, options if Restforce.log?
|
45
46
|
# Compress/Decompress the request/response
|
46
|
-
builder.use Restforce::Middleware::Gzip, self,
|
47
|
+
builder.use Restforce::Middleware::Gzip, self, options
|
47
48
|
|
48
49
|
builder.adapter adapter
|
49
50
|
end
|
@@ -56,9 +57,9 @@ module Restforce
|
|
56
57
|
# Internal: Faraday Connection options
|
57
58
|
def connection_options
|
58
59
|
{ :request => {
|
59
|
-
:timeout =>
|
60
|
-
:open_timeout =>
|
61
|
-
:proxy =>
|
60
|
+
:timeout => options[:timeout],
|
61
|
+
:open_timeout => options[:timeout] },
|
62
|
+
:proxy => options[:proxy_uri]
|
62
63
|
}
|
63
64
|
end
|
64
65
|
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Restforce
|
2
|
-
|
2
|
+
module Concerns
|
3
3
|
module Streaming
|
4
4
|
|
5
5
|
# Public: Subscribe to a PushTopic
|
@@ -14,8 +14,8 @@ module Restforce
|
|
14
14
|
|
15
15
|
# Public: Faye client to use for subscribing to PushTopics
|
16
16
|
def faye
|
17
|
-
raise 'Instance URL missing. Call .authenticate! first.' unless
|
18
|
-
@faye ||= Faye::Client.new("#{
|
17
|
+
raise 'Instance URL missing. Call .authenticate! first.' unless options[:instance_url]
|
18
|
+
@faye ||= Faye::Client.new("#{options[:instance_url]}/cometd/#{options[:api_version]}").tap do |client|
|
19
19
|
client.bind 'transport:down' do
|
20
20
|
Restforce.log "[COMETD DOWN]"
|
21
21
|
client.set_header 'Authorization', "OAuth #{authenticate!.access_token}"
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Restforce
|
2
|
-
|
2
|
+
module Concerns
|
3
3
|
module Verbs
|
4
4
|
|
5
5
|
# Internal: Define methods to handle a verb.
|
@@ -31,13 +31,13 @@ module Restforce
|
|
31
31
|
# Returns nil.
|
32
32
|
def define_verb(verb)
|
33
33
|
define_method verb do |*args, &block|
|
34
|
-
retries =
|
34
|
+
retries = options[:authentication_retries]
|
35
35
|
begin
|
36
36
|
connection.send(verb, *args, &block)
|
37
37
|
rescue Restforce::UnauthorizedError
|
38
38
|
if retries > 0
|
39
39
|
retries -= 1
|
40
|
-
connection.url_prefix =
|
40
|
+
connection.url_prefix = options[:instance_url]
|
41
41
|
retry
|
42
42
|
end
|
43
43
|
raise
|
@@ -51,7 +51,7 @@ module Restforce
|
|
51
51
|
# verb - Symbol name of the verb (e.g. :get).
|
52
52
|
#
|
53
53
|
# Examples
|
54
|
-
#
|
54
|
+
#
|
55
55
|
# define_api_verb :get
|
56
56
|
# # => api_get 'sobjects'
|
57
57
|
#
|
data/lib/restforce/config.rb
CHANGED
@@ -37,18 +37,48 @@ module Restforce
|
|
37
37
|
end
|
38
38
|
|
39
39
|
class Configuration
|
40
|
+
class Option
|
41
|
+
attr_reader :configuration, :name, :options
|
42
|
+
|
43
|
+
def self.define(*args)
|
44
|
+
new(*args).define
|
45
|
+
end
|
46
|
+
|
47
|
+
def initialize(configuration, name, options = {})
|
48
|
+
@configuration, @name, @options = configuration, name, options
|
49
|
+
@default = options.fetch(:default, nil)
|
50
|
+
end
|
51
|
+
|
52
|
+
def define
|
53
|
+
write_attribute
|
54
|
+
define_method if default_provided?
|
55
|
+
self
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
attr_reader :default
|
60
|
+
alias_method :default_provided?, :default
|
61
|
+
|
62
|
+
def write_attribute
|
63
|
+
configuration.send :attr_accessor, name
|
64
|
+
end
|
65
|
+
|
66
|
+
def define_method
|
67
|
+
our_default = default
|
68
|
+
our_name = name
|
69
|
+
configuration.send :define_method, our_name do
|
70
|
+
instance_variable_get(:"@#{our_name}") ||
|
71
|
+
instance_variable_set(:"@#{our_name}", our_default.respond_to?(:call) ? our_default.call : our_default)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
40
76
|
class << self
|
41
77
|
attr_accessor :options
|
42
78
|
|
43
|
-
def option(
|
44
|
-
|
45
|
-
|
46
|
-
define_method name do
|
47
|
-
instance_variable_get(:"@#{name}") ||
|
48
|
-
instance_variable_set(:"@#{name}", default.respond_to?(:call) ? default.call : default)
|
49
|
-
end if default
|
50
|
-
self.options ||= []
|
51
|
-
self.options << name
|
79
|
+
def option(*args)
|
80
|
+
option = Option.define(self, *args)
|
81
|
+
(self.options ||= []) << option.name
|
52
82
|
end
|
53
83
|
end
|
54
84
|
|
@@ -71,7 +101,7 @@ module Restforce
|
|
71
101
|
|
72
102
|
# Set this to true if you're authenticating with a Sandbox instance.
|
73
103
|
# Defaults to false.
|
74
|
-
option :host, :default => 'login.salesforce.com'
|
104
|
+
option :host, :default => lambda { ENV['SALESFORCE_HOST'] || 'login.salesforce.com' }
|
75
105
|
|
76
106
|
option :oauth_token
|
77
107
|
option :refresh_token
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Restforce
|
2
|
+
module Data
|
3
|
+
class Client < AbstractClient
|
4
|
+
include Restforce::Concerns::Streaming
|
5
|
+
include Restforce::Concerns::Picklists
|
6
|
+
include Restforce::Concerns::Canvas
|
7
|
+
|
8
|
+
# Public: Returns a url to the resource.
|
9
|
+
#
|
10
|
+
# resource - A record that responds to to_sparam or a String/Fixnum.
|
11
|
+
#
|
12
|
+
# Returns the url to the resource.
|
13
|
+
def url(resource)
|
14
|
+
"#{instance_url}/#{(resource.respond_to?(:to_sparam) ? resource.to_sparam : resource)}"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -29,12 +29,13 @@ module Restforce
|
|
29
29
|
|
30
30
|
# Internal: The params to post to the OAuth service.
|
31
31
|
def params
|
32
|
-
raise
|
32
|
+
raise NotImplementedError
|
33
33
|
end
|
34
34
|
|
35
35
|
# Internal: Faraday connection to use when sending an authentication request.
|
36
36
|
def connection
|
37
|
-
@connection ||= Faraday.new(
|
37
|
+
@connection ||= Faraday.new(faraday_options) do |builder|
|
38
|
+
builder.use Faraday::Request::UrlEncoded
|
38
39
|
builder.use Restforce::Middleware::Mashify, nil, @options
|
39
40
|
builder.response :json
|
40
41
|
builder.use Restforce::Middleware::Logger, Restforce.configuration.logger, @options if Restforce.log?
|
@@ -59,5 +60,11 @@ module Restforce
|
|
59
60
|
end.join('&')
|
60
61
|
end
|
61
62
|
end
|
63
|
+
|
64
|
+
private
|
65
|
+
def faraday_options
|
66
|
+
{ :url => "https://#{@options[:host]}",
|
67
|
+
:proxy => @options[:proxy_uri] }.reject { |k, v| v.nil? }
|
68
|
+
end
|
62
69
|
end
|
63
70
|
end
|
data/lib/restforce/sobject.rb
CHANGED
data/lib/restforce/version.rb
CHANGED
@@ -1,74 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
shared_examples_for
|
4
|
-
describe '#new' do
|
5
|
-
context 'without options passed in' do
|
6
|
-
it 'does not raise an exception' do
|
7
|
-
expect {
|
8
|
-
described_class.new
|
9
|
-
}.to_not raise_error
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
context 'with a non-hash value' do
|
14
|
-
it 'raises an exception' do
|
15
|
-
expect {
|
16
|
-
described_class.new 'foo'
|
17
|
-
}.to raise_error, 'Please specify a hash of options'
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
describe '@options' do
|
23
|
-
subject { client.instance_variable_get :@options }
|
24
|
-
|
25
|
-
its([:oauth_token]) { should eq oauth_token }
|
26
|
-
its([:refresh_token]) { should eq refresh_token }
|
27
|
-
its([:client_id]) { should eq client_id }
|
28
|
-
its([:client_secret]) { should eq client_secret }
|
29
|
-
its([:username]) { should eq username }
|
30
|
-
its([:password]) { should eq password }
|
31
|
-
its([:security_token]) { should eq security_token }
|
32
|
-
end
|
33
|
-
|
34
|
-
describe '.instance_url' do
|
35
|
-
subject { client.instance_url }
|
36
|
-
it { should eq 'https://na1.salesforce.com' }
|
37
|
-
end
|
38
|
-
|
39
|
-
describe '.url' do
|
40
|
-
subject { client.url(resource) }
|
41
|
-
|
42
|
-
context 'when given something that responds to to_sparam' do
|
43
|
-
let(:resource) { Struct.new(:to_sparam).new('1234') }
|
44
|
-
it { should eq 'https://na1.salesforce.com/1234' }
|
45
|
-
end
|
46
|
-
|
47
|
-
context 'when given a string' do
|
48
|
-
let(:resource) { '4321' }
|
49
|
-
it { should eq 'https://na1.salesforce.com/4321' }
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
describe '.authentication_middleware' do
|
54
|
-
subject { client.send :authentication_middleware }
|
55
|
-
|
56
|
-
context 'without required options for authentication middleware to be provided' do
|
57
|
-
let(:client_options) { {} }
|
58
|
-
it { should be_nil }
|
59
|
-
end
|
60
|
-
|
61
|
-
context 'with username, password, security token, client id and client secret provided' do
|
62
|
-
let(:client_options) { password_options }
|
63
|
-
it { should eq Restforce::Middleware::Authentication::Password }
|
64
|
-
end
|
65
|
-
|
66
|
-
context 'with refresh token, client id and client secret provided' do
|
67
|
-
let(:client_options) { oauth_options }
|
68
|
-
it { should eq Restforce::Middleware::Authentication::Token }
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
3
|
+
shared_examples_for Restforce::AbstractClient do
|
72
4
|
describe '.list_sobjects' do
|
73
5
|
requests :sobjects, :fixture => 'sobject/describe_sobjects_success_response'
|
74
6
|
|
@@ -145,15 +77,15 @@ shared_examples_for 'methods' do
|
|
145
77
|
:status => 404,
|
146
78
|
:fixture => 'sobject/delete_error_response'
|
147
79
|
|
148
|
-
subject { client.update!('Account', :Id => '001D000000INjVe', :Name => 'Foobar') }
|
149
|
-
|
80
|
+
subject { lambda { client.update!('Account', :Id => '001D000000INjVe', :Name => 'Foobar') } }
|
81
|
+
it { should raise_error Faraday::Error::ResourceNotFound }
|
150
82
|
end
|
151
83
|
end
|
152
84
|
|
153
85
|
describe '.update' do
|
154
86
|
context 'with missing Id' do
|
155
|
-
subject { client.update('Account', :Name => 'Foobar') }
|
156
|
-
|
87
|
+
subject { lambda { client.update('Account', :Name => 'Foobar') } }
|
88
|
+
it { should raise_error ArgumentError, 'Id field missing from attrs.' }
|
157
89
|
end
|
158
90
|
|
159
91
|
context 'with invalid Id' do
|
@@ -214,7 +146,7 @@ shared_examples_for 'methods' do
|
|
214
146
|
end
|
215
147
|
|
216
148
|
describe '.destroy!' do
|
217
|
-
subject { client.destroy!('Account', '001D000000INjVe') }
|
149
|
+
subject(:destroy!) { client.destroy!('Account', '001D000000INjVe') }
|
218
150
|
|
219
151
|
context 'with invalid Id' do
|
220
152
|
requests 'sobjects/Account/001D000000INjVe',
|
@@ -222,7 +154,8 @@ shared_examples_for 'methods' do
|
|
222
154
|
:method => :delete,
|
223
155
|
:status => 404
|
224
156
|
|
225
|
-
|
157
|
+
subject { lambda { destroy! } }
|
158
|
+
it { should raise_error Faraday::Error::ResourceNotFound }
|
226
159
|
end
|
227
160
|
|
228
161
|
context 'with success' do
|
@@ -269,44 +202,8 @@ shared_examples_for 'methods' do
|
|
269
202
|
end
|
270
203
|
end
|
271
204
|
|
272
|
-
describe '.picklist_values' do
|
273
|
-
requests 'sobjects/Account/describe',
|
274
|
-
:fixture => 'sobject/sobject_describe_success_response'
|
275
|
-
|
276
|
-
context 'when given a picklist field' do
|
277
|
-
subject { client.picklist_values('Account', 'Picklist_Field') }
|
278
|
-
it { should be_an Array }
|
279
|
-
its(:length) { should eq 3 }
|
280
|
-
it { should include_picklist_values ['one', 'two', 'three'] }
|
281
|
-
end
|
282
|
-
|
283
|
-
context 'when given a multipicklist field' do
|
284
|
-
subject { client.picklist_values('Account', 'Picklist_Multiselect_Field') }
|
285
|
-
it { should be_an Array }
|
286
|
-
its(:length) { should eq 3 }
|
287
|
-
it { should include_picklist_values ['four', 'five', 'six'] }
|
288
|
-
end
|
289
|
-
|
290
|
-
describe 'dependent picklists' do
|
291
|
-
context 'when given a picklist field that has a dependency' do
|
292
|
-
subject { client.picklist_values('Account', 'Dependent_Picklist_Field', :valid_for => 'one') }
|
293
|
-
it { should be_an Array }
|
294
|
-
its(:length) { should eq 2 }
|
295
|
-
it { should include_picklist_values ['seven', 'eight'] }
|
296
|
-
it { should_not include_picklist_values ['nine'] }
|
297
|
-
end
|
298
|
-
|
299
|
-
context 'when given a picklist field that does not have a dependency' do
|
300
|
-
subject { client.picklist_values('Account', 'Picklist_Field', :valid_for => 'one') }
|
301
|
-
it 'raises an exception' do
|
302
|
-
expect { subject }.to raise_error(/Picklist_Field is not a dependent picklist/)
|
303
|
-
end
|
304
|
-
end
|
305
|
-
end
|
306
|
-
end
|
307
|
-
|
308
205
|
describe '.authenticate!' do
|
309
|
-
subject { client.authenticate! }
|
206
|
+
subject(:authenticate!) { client.authenticate! }
|
310
207
|
|
311
208
|
context 'when successful' do
|
312
209
|
before do
|
@@ -327,29 +224,8 @@ shared_examples_for 'methods' do
|
|
327
224
|
client.stub(:authentication_middleware).and_return(nil)
|
328
225
|
end
|
329
226
|
|
330
|
-
|
331
|
-
|
332
|
-
end
|
333
|
-
end
|
334
|
-
end
|
335
|
-
|
336
|
-
describe '.cache' do
|
337
|
-
let(:cache) { double('cache') }
|
338
|
-
|
339
|
-
subject { client.send :cache }
|
340
|
-
it { should eq cache }
|
341
|
-
end
|
342
|
-
|
343
|
-
describe '.middleware' do
|
344
|
-
subject { client.middleware }
|
345
|
-
it { should eq client.send(:connection).builder }
|
346
|
-
|
347
|
-
context 'adding middleware' do
|
348
|
-
before do
|
349
|
-
client.middleware.use FaradayMiddleware::Instrumentation
|
350
|
-
end
|
351
|
-
|
352
|
-
its(:handlers) { should include FaradayMiddleware::Instrumentation }
|
227
|
+
subject { lambda { authenticate! } }
|
228
|
+
it { should raise_error Restforce::AuthenticationError, 'No authentication middleware present'}
|
353
229
|
end
|
354
230
|
end
|
355
231
|
|
@@ -367,56 +243,6 @@ shared_examples_for 'methods' do
|
|
367
243
|
it { should be_an Enumerable }
|
368
244
|
end
|
369
245
|
|
370
|
-
unless RUBY_PLATFORM == 'java'
|
371
|
-
describe '.faye', :eventmachine => true do
|
372
|
-
subject { client.faye }
|
373
|
-
|
374
|
-
context 'with missing instance url' do
|
375
|
-
let(:instance_url) { nil }
|
376
|
-
specify { expect { subject }.to raise_error RuntimeError, 'Instance URL missing. Call .authenticate! first.' }
|
377
|
-
end
|
378
|
-
|
379
|
-
context 'with oauth token and instance url' do
|
380
|
-
let(:instance_url) { 'http://google.com' }
|
381
|
-
let(:oauth_token) { 'bar' }
|
382
|
-
specify { expect { subject }.to_not raise_error }
|
383
|
-
end
|
384
|
-
|
385
|
-
context 'when the connection goes down' do
|
386
|
-
it 'should reauthenticate' do
|
387
|
-
access_token = double('access token')
|
388
|
-
access_token.stub(:access_token).and_return('token')
|
389
|
-
client.should_receive(:authenticate!).and_return(access_token)
|
390
|
-
client.faye.should_receive(:set_header).with('Authorization', "OAuth token")
|
391
|
-
client.faye.trigger('transport:down')
|
392
|
-
end
|
393
|
-
end
|
394
|
-
end
|
395
|
-
|
396
|
-
describe '.subcribe', :eventmachine => true do
|
397
|
-
context 'when given a single pushtopic' do
|
398
|
-
it 'subscribes to the pushtopic' do
|
399
|
-
client.faye.should_receive(:subscribe).with(['/topic/PushTopic'])
|
400
|
-
client.subscribe('PushTopic')
|
401
|
-
end
|
402
|
-
end
|
403
|
-
|
404
|
-
context 'when given an array of pushtopics' do
|
405
|
-
it 'subscribes to each pushtopic' do
|
406
|
-
client.faye.should_receive(:subscribe).with(['/topic/PushTopic1', '/topic/PushTopic2'])
|
407
|
-
client.subscribe(['PushTopic1', 'PushTopic2'])
|
408
|
-
end
|
409
|
-
end
|
410
|
-
end
|
411
|
-
end
|
412
|
-
|
413
|
-
describe '.decode_signed_request' do
|
414
|
-
it 'proxies to Restforce::SignedRequest' do
|
415
|
-
Restforce::SignedRequest.should_receive(:decode).with('foo', client_secret)
|
416
|
-
client.decode_signed_request('foo')
|
417
|
-
end
|
418
|
-
end
|
419
|
-
|
420
246
|
describe 'authentication retries' do
|
421
247
|
context 'when retries reaches 0' do
|
422
248
|
before do
|
@@ -428,8 +254,8 @@ shared_examples_for 'methods' do
|
|
428
254
|
to_return(:status => 200, :body => fixture(:auth_success_response))
|
429
255
|
end
|
430
256
|
|
431
|
-
subject { client.query('SELECT some, fields FROM object') }
|
432
|
-
|
257
|
+
subject { lambda { client.query('SELECT some, fields FROM object') } }
|
258
|
+
it { should raise_error Restforce::UnauthorizedError }
|
433
259
|
end
|
434
260
|
end
|
435
261
|
|
@@ -457,43 +283,24 @@ shared_examples_for 'methods' do
|
|
457
283
|
end
|
458
284
|
end
|
459
285
|
|
460
|
-
describe
|
461
|
-
describe
|
462
|
-
|
463
|
-
include_examples 'methods'
|
464
|
-
|
465
|
-
describe '.mashify?' do
|
466
|
-
subject { client.send :mashify? }
|
467
|
-
|
468
|
-
it { should be_true }
|
469
|
-
end
|
286
|
+
describe Restforce::AbstractClient do
|
287
|
+
describe 'with mashify' do
|
288
|
+
it_behaves_like Restforce::AbstractClient
|
470
289
|
|
471
290
|
describe '.query' do
|
472
291
|
context 'with pagination' do
|
292
|
+
subject { client.query('SELECT some, fields FROM object').next_page }
|
293
|
+
|
473
294
|
requests 'query\?q', :fixture => 'sobject/query_paginated_first_page_response'
|
474
295
|
requests 'query/01gD', :fixture => 'sobject/query_paginated_last_page_response'
|
475
296
|
|
476
|
-
subject { client.query('SELECT some, fields FROM object').next_page }
|
477
297
|
it { should be_a Restforce::Collection }
|
478
|
-
|
298
|
+
its('first.Text_Label') { should eq 'Last Page'}
|
479
299
|
end
|
480
300
|
end
|
481
301
|
end
|
482
|
-
end
|
483
|
-
|
484
|
-
describe 'without mashify middleware' do
|
485
|
-
before do
|
486
|
-
client.middleware.delete(Restforce::Middleware::Mashify)
|
487
|
-
end
|
488
|
-
|
489
|
-
describe Restforce::Client do
|
490
|
-
include_context 'basic client'
|
491
|
-
include_examples 'methods'
|
492
|
-
|
493
|
-
describe '.mashify?' do
|
494
|
-
subject { client.send :mashify? }
|
495
302
|
|
496
|
-
|
497
|
-
|
303
|
+
describe 'without mashify', :mashify => false do
|
304
|
+
it_behaves_like Restforce::AbstractClient
|
498
305
|
end
|
499
306
|
end
|