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
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Restforce::Concerns::Authentication do
|
4
|
+
describe '.authenticate!' do
|
5
|
+
subject { lambda { client.authenticate! } }
|
6
|
+
|
7
|
+
context 'when there is no authentication middleware' do
|
8
|
+
before do
|
9
|
+
client.stub :authentication_middleware => nil
|
10
|
+
end
|
11
|
+
|
12
|
+
it { should raise_error Restforce::AuthenticationError, 'No authentication middleware present' }
|
13
|
+
end
|
14
|
+
|
15
|
+
context 'when there is authentication middleware' do
|
16
|
+
let(:authentication_middleware) { double('Authentication Middleware') }
|
17
|
+
subject(:result) { client.authenticate! }
|
18
|
+
|
19
|
+
it 'authenticates using the middleware' do
|
20
|
+
client.stub :authentication_middleware => authentication_middleware
|
21
|
+
client.stub :options
|
22
|
+
authentication_middleware.
|
23
|
+
should_receive(:new).
|
24
|
+
with(nil, client, client.options).
|
25
|
+
and_return(stub(:authenticate! => 'foo'))
|
26
|
+
expect(result).to eq 'foo'
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe '.authentication_middleware' do
|
32
|
+
subject { client.authentication_middleware }
|
33
|
+
|
34
|
+
context 'when username and password options are provided' do
|
35
|
+
before do
|
36
|
+
client.stub :username_password? => true
|
37
|
+
end
|
38
|
+
|
39
|
+
it { should eq Restforce::Middleware::Authentication::Password }
|
40
|
+
end
|
41
|
+
|
42
|
+
context 'when oauth options are provided' do
|
43
|
+
before do
|
44
|
+
client.stub :username_password? => false
|
45
|
+
client.stub :oauth_refresh? => true
|
46
|
+
end
|
47
|
+
|
48
|
+
it { should eq Restforce::Middleware::Authentication::Token }
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe '.username_password?' do
|
53
|
+
subject { client.username_password? }
|
54
|
+
let(:options) { Hash.new }
|
55
|
+
|
56
|
+
before do
|
57
|
+
client.stub :options => options
|
58
|
+
end
|
59
|
+
|
60
|
+
context 'when username and password options are provided' do
|
61
|
+
let(:options) do
|
62
|
+
{ :username => 'foo',
|
63
|
+
:password => 'bar',
|
64
|
+
:client_id => 'client',
|
65
|
+
:client_secret => 'secret' }
|
66
|
+
end
|
67
|
+
|
68
|
+
it { should be_true }
|
69
|
+
end
|
70
|
+
|
71
|
+
context 'when username and password options are not provided' do
|
72
|
+
it { should_not be_true }
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
describe '.oauth_refresh?' do
|
77
|
+
subject { client.oauth_refresh? }
|
78
|
+
let(:options) { Hash.new }
|
79
|
+
|
80
|
+
before do
|
81
|
+
client.stub :options => options
|
82
|
+
end
|
83
|
+
|
84
|
+
context 'when oauth options are provided' do
|
85
|
+
let(:options) do
|
86
|
+
{ :refresh_token => 'token',
|
87
|
+
:client_id => 'client',
|
88
|
+
:client_secret => 'secret' }
|
89
|
+
end
|
90
|
+
|
91
|
+
it { should be_true }
|
92
|
+
end
|
93
|
+
|
94
|
+
context 'when oauth options are not provided' do
|
95
|
+
it { should_not be_true }
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Restforce::Concerns::Base do
|
4
|
+
describe '#new' do
|
5
|
+
context 'without options passed in' do
|
6
|
+
it 'does not raise an exception' do
|
7
|
+
expect {
|
8
|
+
klass.new
|
9
|
+
}.to_not raise_error
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
context 'with a non-hash value' do
|
14
|
+
it 'raises an ArgumentError exception' do
|
15
|
+
expect {
|
16
|
+
klass.new 'foo'
|
17
|
+
}.to raise_error ArgumentError, 'Please specify a hash of options'
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'yields the builder to the block' do
|
22
|
+
klass.any_instance.stub :builder
|
23
|
+
expect { |b| klass.new(&b) }.to yield_control
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe '.options' do
|
28
|
+
subject { lambda { client.options } }
|
29
|
+
it { should_not raise_error }
|
30
|
+
end
|
31
|
+
|
32
|
+
describe '.instance_url' do
|
33
|
+
subject { client.instance_url }
|
34
|
+
|
35
|
+
context 'when options[:instance_url] is unset' do
|
36
|
+
it 'triggers an authentication' do
|
37
|
+
client.should_receive :authenticate!
|
38
|
+
subject
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context 'when options[:instance_url] is set' do
|
43
|
+
before do
|
44
|
+
client.stub :options => { :instance_url => 'foo' }
|
45
|
+
end
|
46
|
+
|
47
|
+
it { should eq 'foo' }
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Restforce::Concerns::Caching do
|
4
|
+
describe '.without_caching' do
|
5
|
+
let(:options) { double('Options') }
|
6
|
+
|
7
|
+
before do
|
8
|
+
client.stub :options => options
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'runs the block with caching disabled' do
|
12
|
+
options.should_receive(:[]=).with(:use_cache, false)
|
13
|
+
options.should_receive(:delete).with(:use_cache)
|
14
|
+
expect { |b| client.without_caching(&b) }.to yield_control
|
15
|
+
end
|
16
|
+
|
17
|
+
context 'when an exception is raised' do
|
18
|
+
it 'ensures the :use_cache is deleted' do
|
19
|
+
options.should_receive(:[]=).with(:use_cache, false)
|
20
|
+
options.should_receive(:delete).with(:use_cache)
|
21
|
+
expect {
|
22
|
+
client.without_caching do
|
23
|
+
raise 'Foo'
|
24
|
+
end
|
25
|
+
}.to raise_error 'Foo'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Restforce::Concerns::Canvas do
|
4
|
+
let(:options) { Hash.new }
|
5
|
+
|
6
|
+
before do
|
7
|
+
client.stub :options => options
|
8
|
+
end
|
9
|
+
|
10
|
+
describe '.decode_signed_request' do
|
11
|
+
subject { client.decode_signed_request(signed_request) }
|
12
|
+
let(:signed_request) { double('Signed Request') }
|
13
|
+
|
14
|
+
context 'when the client_secret is set' do
|
15
|
+
let(:options) { { :client_secret => 'secret' } }
|
16
|
+
|
17
|
+
it 'delegates to Restforce::SignedRequest' do
|
18
|
+
Restforce::SignedRequest.should_receive(:decode).
|
19
|
+
with(signed_request, options[:client_secret])
|
20
|
+
client.decode_signed_request(signed_request)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'when the client_secret is not set' do
|
25
|
+
it 'raises an exception' do
|
26
|
+
expect { subject }.to raise_error 'client_secret not set.'
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Restforce::Concerns::Connection do
|
4
|
+
describe '.middleware' do
|
5
|
+
subject { client.middleware }
|
6
|
+
let(:builder) { double('Faraday::Builder') }
|
7
|
+
|
8
|
+
before do
|
9
|
+
client.stub_chain :connection, :builder => builder
|
10
|
+
end
|
11
|
+
|
12
|
+
it { should eq builder }
|
13
|
+
end
|
14
|
+
end
|
@@ -32,21 +32,14 @@ describe Restforce do
|
|
32
32
|
|
33
33
|
context 'when environment variables are defined' do
|
34
34
|
before do
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
after do
|
44
|
-
ENV.delete('SALESFORCE_USERNAME')
|
45
|
-
ENV.delete('SALESFORCE_PASSWORD')
|
46
|
-
ENV.delete('SALESFORCE_SECURITY_TOKEN')
|
47
|
-
ENV.delete('SALESFORCE_CLIENT_ID')
|
48
|
-
ENV.delete('SALESFORCE_CLIENT_SECRET')
|
49
|
-
ENV.delete('PROXY_URI')
|
35
|
+
{ 'SALESFORCE_USERNAME' => 'foo',
|
36
|
+
'SALESFORCE_PASSWORD' => 'bar',
|
37
|
+
'SALESFORCE_SECURITY_TOKEN' => 'foobar',
|
38
|
+
'SALESFORCE_CLIENT_ID' => 'client id',
|
39
|
+
'SALESFORCE_CLIENT_SECRET' => 'client secret',
|
40
|
+
'PROXY_URI' => 'proxy',
|
41
|
+
'SALESFORCE_HOST' => 'test.host.com' }.
|
42
|
+
each { |var, value| ENV.stub(:[]).with(var).and_return(value) }
|
50
43
|
end
|
51
44
|
|
52
45
|
its(:username) { should eq 'foo' }
|
@@ -55,6 +48,7 @@ describe Restforce do
|
|
55
48
|
its(:client_id) { should eq 'client id' }
|
56
49
|
its(:client_secret) { should eq 'client secret' }
|
57
50
|
its(:proxy_uri) { should eq 'proxy' }
|
51
|
+
its(:host) { should eq 'test.host.com' }
|
58
52
|
end
|
59
53
|
end
|
60
54
|
|
@@ -80,24 +74,20 @@ describe Restforce do
|
|
80
74
|
end
|
81
75
|
|
82
76
|
describe '#log' do
|
83
|
-
after do
|
84
|
-
Restforce.log = false
|
85
|
-
end
|
86
|
-
|
87
77
|
context 'with logging disabled' do
|
88
78
|
before do
|
89
|
-
Restforce.log
|
90
|
-
Restforce.configuration.logger.should_not_receive(:debug)
|
79
|
+
Restforce.stub :log? => false
|
91
80
|
end
|
92
81
|
|
93
82
|
it 'doesnt log anytning' do
|
83
|
+
Restforce.configuration.logger.should_not_receive(:debug)
|
94
84
|
Restforce.log 'foobar'
|
95
85
|
end
|
96
86
|
end
|
97
|
-
|
87
|
+
|
98
88
|
context 'with logging enabled' do
|
99
89
|
before do
|
100
|
-
Restforce.log
|
90
|
+
Restforce.stub :log? => true
|
101
91
|
Restforce.configuration.logger.should_receive(:debug).with('foobar')
|
102
92
|
end
|
103
93
|
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Restforce::Client do
|
4
|
+
subject { described_class }
|
5
|
+
|
6
|
+
it { should < Restforce::AbstractClient }
|
7
|
+
it { should < Restforce::Concerns::Picklists }
|
8
|
+
it { should < Restforce::Concerns::Streaming }
|
9
|
+
it { should < Restforce::Concerns::Canvas }
|
10
|
+
end
|
File without changes
|
@@ -1,10 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Restforce::Middleware::Authentication::Password do
|
4
|
-
let(:app) { double('app') }
|
5
|
-
let(:env) { { } }
|
6
|
-
let(:middleware) { described_class.new app, nil, options }
|
7
|
-
|
8
4
|
let(:options) do
|
9
5
|
{ :host => 'login.salesforce.com',
|
10
6
|
:username => 'foo',
|
@@ -1,10 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Restforce::Middleware::Authentication::Token do
|
4
|
-
let(:app) { double('app') }
|
5
|
-
let(:env) { { } }
|
6
|
-
let(:middleware) { described_class.new app, nil, options }
|
7
|
-
|
8
4
|
let(:options) do
|
9
5
|
{ :host => 'login.salesforce.com',
|
10
6
|
:refresh_token => 'refresh_token',
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Restforce::Middleware::Authentication do
|
4
|
+
let(:options) do
|
5
|
+
{ :host => 'login.salesforce.com',
|
6
|
+
:proxy_uri => 'https://not-a-real-site.com',
|
7
|
+
:authentication_retries => retries }
|
8
|
+
end
|
9
|
+
|
10
|
+
describe '.authenticate!' do
|
11
|
+
subject { lambda { middleware.authenticate! }}
|
12
|
+
it { should raise_error NotImplementedError }
|
13
|
+
end
|
14
|
+
|
15
|
+
describe '.call' do
|
16
|
+
subject { lambda { middleware.call(env) } }
|
17
|
+
|
18
|
+
context 'when successfull' do
|
19
|
+
before do
|
20
|
+
app.should_receive(:call).once
|
21
|
+
end
|
22
|
+
|
23
|
+
it { should_not raise_error }
|
24
|
+
end
|
25
|
+
|
26
|
+
context 'when an exception is thrown' do
|
27
|
+
before do
|
28
|
+
env.stub :body => 'foo', :request => { :proxy => nil }
|
29
|
+
middleware.stub :authenticate!
|
30
|
+
app.should_receive(:call).once.
|
31
|
+
and_raise(Restforce::UnauthorizedError.new('something bad'))
|
32
|
+
end
|
33
|
+
|
34
|
+
it { should raise_error Restforce::UnauthorizedError }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe '.connection' do
|
39
|
+
subject(:connection) { middleware.connection }
|
40
|
+
|
41
|
+
its(:url_prefix) { should eq(URI.parse('https://login.salesforce.com')) }
|
42
|
+
its(:proxy) { should eq({ :uri => URI.parse('https://not-a-real-site.com') }) }
|
43
|
+
|
44
|
+
describe '.builder' do
|
45
|
+
subject(:builder) { connection.builder }
|
46
|
+
|
47
|
+
context 'with logging disabled' do
|
48
|
+
before do
|
49
|
+
Restforce.stub :log? => false
|
50
|
+
end
|
51
|
+
|
52
|
+
its(:handlers) { should include FaradayMiddleware::ParseJson,
|
53
|
+
Faraday::Adapter::NetHttp }
|
54
|
+
its(:handlers) { should_not include Restforce::Middleware::Logger }
|
55
|
+
end
|
56
|
+
|
57
|
+
context 'with logging enabled' do
|
58
|
+
before do
|
59
|
+
Restforce.stub :log? => true
|
60
|
+
end
|
61
|
+
|
62
|
+
its(:handlers) { should include FaradayMiddleware::ParseJson,
|
63
|
+
Restforce::Middleware::Logger, Faraday::Adapter::NetHttp }
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Restforce::Middleware::Authorization do
|
4
|
+
let(:options) { { :oauth_token => 'token' } }
|
5
|
+
|
6
|
+
describe '.call' do
|
7
|
+
subject { lambda { middleware.call(env) } }
|
8
|
+
|
9
|
+
it { should change { env[:request_headers]['Authorization'] }.to eq 'OAuth token' }
|
10
|
+
end
|
11
|
+
end
|
@@ -1,10 +1,7 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Restforce::Middleware::Gzip do
|
4
|
-
let(:
|
5
|
-
let(:env) { { :request_headers => {}, :response_headers => {} } }
|
6
|
-
let(:options) { { :oauth_token => 'token' } }
|
7
|
-
let(:middleware) { described_class.new app, nil, options }
|
4
|
+
let(:options) { { :oauth_token => 'token' } }
|
8
5
|
|
9
6
|
# Return a gzipped string.
|
10
7
|
def gzip(str)
|
@@ -15,17 +12,24 @@ describe Restforce::Middleware::Gzip do
|
|
15
12
|
end.string
|
16
13
|
end
|
17
14
|
|
18
|
-
describe '
|
15
|
+
describe '.call' do
|
16
|
+
subject { lambda { middleware.call(env) } }
|
17
|
+
|
19
18
|
before do
|
20
19
|
app.should_receive(:on_complete) { middleware.on_complete(env) }
|
21
|
-
app.should_receive(:call)
|
20
|
+
app.should_receive(:call) do
|
21
|
+
env[:body] = gzip fixture('sobject/query_success_response')
|
22
|
+
env[:response_headers]['Content-Encoding'] = 'gzip'
|
23
|
+
app
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'decompresses the body' do
|
28
|
+
should change { env[:body] }.to(fixture('sobject/query_success_response'))
|
22
29
|
end
|
23
30
|
|
24
31
|
context 'when :compress is false' do
|
25
|
-
it
|
26
|
-
middleware.call(env)
|
27
|
-
expect(env[:request_headers]['Accept-Encoding']).to be_nil
|
28
|
-
end
|
32
|
+
it { should_not change { env[:request_headers]['Accept-Encoding'] } }
|
29
33
|
end
|
30
34
|
|
31
35
|
context 'when :compress is true' do
|
@@ -33,26 +37,7 @@ describe Restforce::Middleware::Gzip do
|
|
33
37
|
options[:compress] = true
|
34
38
|
end
|
35
39
|
|
36
|
-
it
|
37
|
-
middleware.call(env)
|
38
|
-
expect(env[:request_headers]['Accept-Encoding']).to eq 'gzip'
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
describe 'response' do
|
44
|
-
before do
|
45
|
-
app.should_receive(:on_complete) { middleware.on_complete(env) }
|
46
|
-
app.should_receive(:call) do
|
47
|
-
env[:body] = gzip fixture('sobject/query_success_response')
|
48
|
-
env[:response_headers]['Content-Encoding'] = 'gzip'
|
49
|
-
app
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
it 'decompresses the response body' do
|
54
|
-
middleware.call(env)
|
55
|
-
expect(env[:body]).to eq fixture('sobject/query_success_response')
|
40
|
+
it { should change { env[:request_headers]['Accept-Encoding'] }.to('gzip') }
|
56
41
|
end
|
57
42
|
end
|
58
43
|
|