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.

Files changed (63) hide show
  1. data/.travis.yml +1 -0
  2. data/CHANGELOG.md +7 -1
  3. data/Gemfile +4 -0
  4. data/Guardfile +11 -0
  5. data/README.md +19 -8
  6. data/lib/restforce.rb +44 -14
  7. data/lib/restforce/abstract_client.rb +9 -0
  8. data/lib/restforce/client.rb +1 -95
  9. data/lib/restforce/{client → concerns}/api.rb +9 -9
  10. data/lib/restforce/{client → concerns}/authentication.rb +9 -9
  11. data/lib/restforce/concerns/base.rb +58 -0
  12. data/lib/restforce/{client → concerns}/caching.rb +4 -4
  13. data/lib/restforce/concerns/canvas.rb +12 -0
  14. data/lib/restforce/{client → concerns}/connection.rb +13 -12
  15. data/lib/restforce/{client → concerns}/picklists.rb +1 -1
  16. data/lib/restforce/{client → concerns}/streaming.rb +3 -3
  17. data/lib/restforce/{client → concerns}/verbs.rb +4 -4
  18. data/lib/restforce/config.rb +40 -10
  19. data/lib/restforce/data/client.rb +18 -0
  20. data/lib/restforce/middleware/authentication.rb +9 -2
  21. data/lib/restforce/sobject.rb +1 -1
  22. data/lib/restforce/tooling/client.rb +13 -0
  23. data/lib/restforce/version.rb +1 -1
  24. data/spec/{lib/client_spec.rb → integration/abstract_client_spec.rb} +21 -214
  25. data/spec/integration/data/client_spec.rb +90 -0
  26. data/spec/spec_helper.rb +0 -14
  27. data/spec/support/client_integration.rb +45 -0
  28. data/spec/support/concerns.rb +18 -0
  29. data/spec/support/event_machine.rb +14 -0
  30. data/spec/support/middleware.rb +18 -1
  31. data/spec/unit/abstract_client_spec.rb +11 -0
  32. data/spec/{lib → unit}/attachment_spec.rb +3 -6
  33. data/spec/unit/collection_spec.rb +50 -0
  34. data/spec/unit/concerns/api_spec.rb +222 -0
  35. data/spec/unit/concerns/authentication_spec.rb +98 -0
  36. data/spec/unit/concerns/base_spec.rb +50 -0
  37. data/spec/unit/concerns/caching_spec.rb +29 -0
  38. data/spec/unit/concerns/canvas_spec.rb +30 -0
  39. data/spec/unit/concerns/connection_spec.rb +14 -0
  40. data/spec/{lib → unit}/config_spec.rb +13 -23
  41. data/spec/unit/data/client_spec.rb +10 -0
  42. data/spec/{lib → unit}/mash_spec.rb +0 -0
  43. data/spec/{lib → unit}/middleware/authentication/password_spec.rb +0 -4
  44. data/spec/{lib → unit}/middleware/authentication/token_spec.rb +0 -4
  45. data/spec/unit/middleware/authentication_spec.rb +67 -0
  46. data/spec/unit/middleware/authorization_spec.rb +11 -0
  47. data/spec/{lib → unit}/middleware/gzip_spec.rb +15 -30
  48. data/spec/unit/middleware/instance_url_spec.rb +24 -0
  49. data/spec/{lib → unit}/middleware/logger_spec.rb +4 -7
  50. data/spec/unit/middleware/mashify_spec.rb +11 -0
  51. data/spec/{lib → unit}/middleware/raise_error_spec.rb +4 -5
  52. data/spec/{lib → unit}/signed_request_spec.rb +0 -0
  53. data/spec/unit/sobject_spec.rb +68 -0
  54. data/spec/unit/tooling/client_spec.rb +7 -0
  55. metadata +75 -46
  56. data/lib/restforce/client/canvas.rb +0 -12
  57. data/spec/lib/collection_spec.rb +0 -52
  58. data/spec/lib/middleware/authentication_spec.rb +0 -69
  59. data/spec/lib/middleware/authorization_spec.rb +0 -17
  60. data/spec/lib/middleware/instance_url_spec.rb +0 -31
  61. data/spec/lib/middleware/mashify_spec.rb +0 -28
  62. data/spec/lib/sobject_spec.rb +0 -122
  63. 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
- ENV['SALESFORCE_USERNAME'] = 'foo'
36
- ENV['SALESFORCE_PASSWORD'] = 'bar'
37
- ENV['SALESFORCE_SECURITY_TOKEN'] = 'foobar'
38
- ENV['SALESFORCE_CLIENT_ID'] = 'client id'
39
- ENV['SALESFORCE_CLIENT_SECRET'] = 'client secret'
40
- ENV['PROXY_URI'] = 'proxy'
41
- end
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 = false
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 = true
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(:app) { double('app') }
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 'request' do
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).and_return(app)
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 'does not add the Accept-Encoding header' do
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 'adds the Accept-Encoding header' do
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