sfdc 3.0.0 → 3.0.1

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 (97) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +96 -0
  3. data/Gemfile +11 -0
  4. data/Guardfile +11 -0
  5. data/LICENSE +22 -0
  6. data/README.md +88 -98
  7. data/Rakefile +10 -0
  8. data/lib/sfdc.rb +1 -0
  9. data/lib/sfdc/abstract_client.rb +1 -1
  10. data/lib/sfdc/attachment.rb +0 -2
  11. data/lib/sfdc/concerns/api.rb +1 -2
  12. data/lib/sfdc/concerns/authentication.rb +1 -2
  13. data/lib/sfdc/concerns/base.rb +5 -7
  14. data/lib/sfdc/concerns/caching.rb +1 -3
  15. data/lib/sfdc/concerns/canvas.rb +0 -2
  16. data/lib/sfdc/concerns/connection.rb +2 -3
  17. data/lib/sfdc/concerns/picklists.rb +1 -4
  18. data/lib/sfdc/concerns/streaming.rb +2 -2
  19. data/lib/sfdc/concerns/verbs.rb +0 -2
  20. data/lib/sfdc/config.rb +1 -0
  21. data/lib/sfdc/middleware/authentication.rb +4 -2
  22. data/lib/sfdc/middleware/authentication/password.rb +2 -5
  23. data/lib/sfdc/middleware/authorization.rb +1 -5
  24. data/lib/sfdc/middleware/caching.rb +0 -2
  25. data/lib/sfdc/middleware/instance_url.rb +0 -4
  26. data/lib/sfdc/middleware/mashify.rb +1 -3
  27. data/lib/sfdc/middleware/multipart.rb +6 -4
  28. data/lib/sfdc/signed_request.rb +1 -1
  29. data/lib/sfdc/tooling/client.rb +4 -6
  30. data/lib/sfdc/version.rb +2 -2
  31. data/sfdc.gemspec +27 -0
  32. data/spec/fixtures/auth_error_response.json +4 -0
  33. data/spec/fixtures/auth_success_response.json +7 -0
  34. data/spec/fixtures/blob.jpg +0 -0
  35. data/spec/fixtures/expired_session_response.json +6 -0
  36. data/spec/fixtures/reauth_success_response.json +7 -0
  37. data/spec/fixtures/refresh_error_response.json +4 -0
  38. data/spec/fixtures/refresh_success_response.json +7 -0
  39. data/spec/fixtures/services_data_success_response.json +12 -0
  40. data/spec/fixtures/sobject/create_success_response.json +5 -0
  41. data/spec/fixtures/sobject/delete_error_response.json +1 -0
  42. data/spec/fixtures/sobject/describe_sobjects_success_response.json +31 -0
  43. data/spec/fixtures/sobject/list_sobjects_success_response.json +31 -0
  44. data/spec/fixtures/sobject/org_query_response.json +11 -0
  45. data/spec/fixtures/sobject/query_aggregate_success_response.json +23 -0
  46. data/spec/fixtures/sobject/query_empty_response.json +5 -0
  47. data/spec/fixtures/sobject/query_error_response.json +6 -0
  48. data/spec/fixtures/sobject/query_paginated_first_page_response.json +14 -0
  49. data/spec/fixtures/sobject/query_paginated_last_page_response.json +13 -0
  50. data/spec/fixtures/sobject/query_success_response.json +38 -0
  51. data/spec/fixtures/sobject/recent_success_response.json +18 -0
  52. data/spec/fixtures/sobject/search_error_response.json +6 -0
  53. data/spec/fixtures/sobject/search_success_response.json +16 -0
  54. data/spec/fixtures/sobject/sobject_describe_error_response.json +6 -0
  55. data/spec/fixtures/sobject/sobject_describe_success_response.json +1429 -0
  56. data/spec/fixtures/sobject/sobject_find_error_response.json +6 -0
  57. data/spec/fixtures/sobject/sobject_find_success_response.json +29 -0
  58. data/spec/fixtures/sobject/upsert_created_success_response.json +5 -0
  59. data/spec/fixtures/sobject/upsert_error_response.json +6 -0
  60. data/spec/fixtures/sobject/upsert_multiple_error_response.json +4 -0
  61. data/spec/fixtures/sobject/upsert_updated_success_response.json +0 -0
  62. data/spec/fixtures/sobject/write_error_response.json +6 -0
  63. data/spec/integration/abstract_client_spec.rb +306 -0
  64. data/spec/integration/data/client_spec.rb +90 -0
  65. data/spec/spec_helper.rb +20 -0
  66. data/spec/support/client_integration.rb +45 -0
  67. data/spec/support/concerns.rb +18 -0
  68. data/spec/support/event_machine.rb +14 -0
  69. data/spec/support/fixture_helpers.rb +45 -0
  70. data/spec/support/matchers.rb +11 -0
  71. data/spec/support/middleware.rb +76 -0
  72. data/spec/support/mock_cache.rb +13 -0
  73. data/spec/unit/abstract_client_spec.rb +11 -0
  74. data/spec/unit/attachment_spec.rb +15 -0
  75. data/spec/unit/collection_spec.rb +52 -0
  76. data/spec/unit/concerns/api_spec.rb +244 -0
  77. data/spec/unit/concerns/authentication_spec.rb +98 -0
  78. data/spec/unit/concerns/base_spec.rb +42 -0
  79. data/spec/unit/concerns/caching_spec.rb +29 -0
  80. data/spec/unit/concerns/canvas_spec.rb +30 -0
  81. data/spec/unit/concerns/connection_spec.rb +22 -0
  82. data/spec/unit/config_spec.rb +99 -0
  83. data/spec/unit/data/client_spec.rb +10 -0
  84. data/spec/unit/mash_spec.rb +36 -0
  85. data/spec/unit/middleware/authentication/password_spec.rb +31 -0
  86. data/spec/unit/middleware/authentication/token_spec.rb +24 -0
  87. data/spec/unit/middleware/authentication_spec.rb +67 -0
  88. data/spec/unit/middleware/authorization_spec.rb +11 -0
  89. data/spec/unit/middleware/gzip_spec.rb +66 -0
  90. data/spec/unit/middleware/instance_url_spec.rb +24 -0
  91. data/spec/unit/middleware/logger_spec.rb +19 -0
  92. data/spec/unit/middleware/mashify_spec.rb +11 -0
  93. data/spec/unit/middleware/raise_error_spec.rb +32 -0
  94. data/spec/unit/signed_request_spec.rb +24 -0
  95. data/spec/unit/sobject_spec.rb +86 -0
  96. data/spec/unit/tooling/client_spec.rb +7 -0
  97. metadata +225 -65
@@ -0,0 +1,98 @@
1
+ require 'spec_helper'
2
+
3
+ describe Sfdc::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 Sfdc::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(double(: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 Sfdc::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 Sfdc::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,42 @@
1
+ require 'spec_helper'
2
+
3
+ describe Sfdc::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
+ it 'yields the builder to the block' do
14
+ klass.any_instance.stub :builder
15
+ expect { |b| klass.new(&b) }.to yield_control
16
+ end
17
+ end
18
+
19
+ describe '.options' do
20
+ subject { lambda { client.options } }
21
+ it { should_not raise_error }
22
+ end
23
+
24
+ describe '.instance_url' do
25
+ subject { client.instance_url }
26
+
27
+ context 'when options[:instance_url] is unset' do
28
+ it 'triggers an authentication' do
29
+ client.should_receive :authenticate!
30
+ subject
31
+ end
32
+ end
33
+
34
+ context 'when options[:instance_url] is set' do
35
+ before do
36
+ client.stub :options => { :instance_url => 'foo' }
37
+ end
38
+
39
+ it { should eq 'foo' }
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+
3
+ describe Sfdc::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 Sfdc::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 Sfdc::SignedRequest' do
18
+ Sfdc::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,22 @@
1
+ require 'spec_helper'
2
+
3
+ describe Sfdc::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
+
15
+ describe '#adapter' do
16
+ before do
17
+ client.stub :options => {:adapter => :typhoeus}
18
+ end
19
+
20
+ its(:adapter) { should eq(:typhoeus) }
21
+ end
22
+ end
@@ -0,0 +1,99 @@
1
+ require 'spec_helper'
2
+
3
+ describe Sfdc do
4
+ before do
5
+ ENV['SALESFORCE_USERNAME'] = nil
6
+ ENV['SALESFORCE_PASSWORD'] = nil
7
+ ENV['SALESFORCE_SECURITY_TOKEN'] = nil
8
+ ENV['SALESFORCE_CLIENT_ID'] = nil
9
+ ENV['SALESFORCE_CLIENT_SECRET'] = nil
10
+ end
11
+
12
+ after do
13
+ Sfdc.instance_variable_set :@configuration, nil
14
+ end
15
+
16
+ describe '#configuration' do
17
+ subject { Sfdc.configuration }
18
+
19
+ it { should be_a Sfdc::Configuration }
20
+
21
+ context 'by default' do
22
+ its(:api_version) { should eq '26.0' }
23
+ its(:host) { should eq 'login.salesforce.com' }
24
+ its(:authentication_retries) { should eq 3 }
25
+ its(:adapter) { should eq Faraday.default_adapter }
26
+ [:username, :password, :security_token, :client_id, :client_secret,
27
+ :oauth_token, :refresh_token, :instance_url, :compress, :timeout,
28
+ :proxy_uri, :authentication_callback].each do |attr|
29
+ its(attr) { should be_nil }
30
+ end
31
+ end
32
+
33
+ context 'when environment variables are defined' do
34
+ before do
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) }
43
+ end
44
+
45
+ its(:username) { should eq 'foo' }
46
+ its(:password) { should eq 'bar'}
47
+ its(:security_token) { should eq 'foobar' }
48
+ its(:client_id) { should eq 'client id' }
49
+ its(:client_secret) { should eq 'client secret' }
50
+ its(:proxy_uri) { should eq 'proxy' }
51
+ its(:host) { should eq 'test.host.com' }
52
+ end
53
+ end
54
+
55
+ describe '#configure' do
56
+ [:username, :password, :security_token, :client_id, :client_secret, :compress, :timeout,
57
+ :oauth_token, :refresh_token, :instance_url, :api_version, :host, :authentication_retries,
58
+ :proxy_uri, :authentication_callback].each do |attr|
59
+ it "allows #{attr} to be set" do
60
+ Sfdc.configure do |config|
61
+ config.send("#{attr}=", 'foobar')
62
+ end
63
+ expect(Sfdc.configuration.send(attr)).to eq 'foobar'
64
+ end
65
+ end
66
+ end
67
+
68
+ describe '#log?' do
69
+ subject { Sfdc.log? }
70
+
71
+ context 'by default' do
72
+ it { should be_false }
73
+ end
74
+ end
75
+
76
+ describe '#log' do
77
+ context 'with logging disabled' do
78
+ before do
79
+ Sfdc.stub :log? => false
80
+ end
81
+
82
+ it 'doesnt log anytning' do
83
+ Sfdc.configuration.logger.should_not_receive(:debug)
84
+ Sfdc.log 'foobar'
85
+ end
86
+ end
87
+
88
+ context 'with logging enabled' do
89
+ before do
90
+ Sfdc.stub :log? => true
91
+ Sfdc.configuration.logger.should_receive(:debug).with('foobar')
92
+ end
93
+
94
+ it 'logs something' do
95
+ Sfdc.log 'foobar'
96
+ end
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,10 @@
1
+ require 'spec_helper'
2
+
3
+ describe Sfdc::Client do
4
+ subject { described_class }
5
+
6
+ it { should < Sfdc::AbstractClient }
7
+ it { should < Sfdc::Concerns::Picklists }
8
+ it { should < Sfdc::Concerns::Streaming }
9
+ it { should < Sfdc::Concerns::Canvas }
10
+ end
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+
3
+ describe Sfdc::Mash do
4
+ describe '#build' do
5
+ subject { described_class.build(input, nil) }
6
+
7
+ context 'when array' do
8
+ let(:input) { [{ :foo => 'hello' }, { :bar => 'world' }] }
9
+ it { should be_all { |obj| expect(obj).to be_a Sfdc::Mash } }
10
+ end
11
+ end
12
+
13
+ describe '#klass' do
14
+ subject { described_class.klass(input) }
15
+
16
+ context 'when the hash has a "records" key' do
17
+ let(:input) { { 'records' => nil } }
18
+ it { should eq Sfdc::Collection }
19
+ end
20
+
21
+ context 'when the hash has an "attributes" key' do
22
+ let(:input) { { 'attributes' => { 'type' => 'Account' } } }
23
+ it { should eq Sfdc::SObject }
24
+
25
+ context 'when the sobject type is an Attachment' do
26
+ let(:input) { { 'attributes' => { 'type' => 'Attachment' } } }
27
+ it { should eq Sfdc::Attachment }
28
+ end
29
+ end
30
+
31
+ context 'else' do
32
+ let(:input) { {} }
33
+ it { should eq Sfdc::Mash }
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+
3
+ describe Sfdc::Middleware::Authentication::Password do
4
+ let(:options) do
5
+ { :host => 'login.salesforce.com',
6
+ :username => 'foo',
7
+ :password => 'bar',
8
+ :security_token => 'security_token',
9
+ :client_id => 'client_id',
10
+ :client_secret => 'client_secret' }
11
+ end
12
+
13
+ it_behaves_like 'authentication middleware' do
14
+ let(:success_request) do
15
+ stub_login_request(:body => "grant_type=password&client_id=client_id&client_secret=" \
16
+ "client_secret&username=foo&password=barsecurity_token").
17
+ to_return(:status => 200, :body => fixture(:auth_success_response))
18
+ end
19
+
20
+ let(:fail_request) do
21
+ stub_login_request(:body => "grant_type=password&client_id=client_id&client_secret=" \
22
+ "client_secret&username=foo&password=barsecurity_token").
23
+ to_return(:status => 400, :body => fixture(:auth_error_response))
24
+ end
25
+ end
26
+
27
+ describe '.password' do
28
+ subject { middleware.password }
29
+ it { should eq 'barsecurity_token' }
30
+ end
31
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+
3
+ describe Sfdc::Middleware::Authentication::Token do
4
+ let(:options) do
5
+ { :host => 'login.salesforce.com',
6
+ :refresh_token => 'refresh_token',
7
+ :client_id => 'client_id',
8
+ :client_secret => 'client_secret' }
9
+ end
10
+
11
+ it_behaves_like 'authentication middleware' do
12
+ let(:success_request) do
13
+ stub_login_request(:body => "grant_type=refresh_token&refresh_token=refresh_token&" \
14
+ "client_id=client_id&client_secret=client_secret").
15
+ to_return(:status => 200, :body => fixture(:auth_success_response))
16
+ end
17
+
18
+ let(:fail_request) do
19
+ stub_login_request(:body => "grant_type=refresh_token&refresh_token=refresh_token&" \
20
+ "client_id=client_id&client_secret=client_secret").
21
+ to_return(:status => 400, :body => fixture(:refresh_error_response))
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,67 @@
1
+ require 'spec_helper'
2
+
3
+ describe Sfdc::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(Sfdc::UnauthorizedError.new('something bad'))
32
+ end
33
+
34
+ it { should raise_error Sfdc::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
+ Sfdc.stub :log? => false
50
+ end
51
+
52
+ its(:handlers) { should include FaradayMiddleware::ParseJson,
53
+ Faraday::Adapter::NetHttp }
54
+ its(:handlers) { should_not include Sfdc::Middleware::Logger }
55
+ end
56
+
57
+ context 'with logging enabled' do
58
+ before do
59
+ Sfdc.stub :log? => true
60
+ end
61
+
62
+ its(:handlers) { should include FaradayMiddleware::ParseJson,
63
+ Sfdc::Middleware::Logger, Faraday::Adapter::NetHttp }
64
+ end
65
+ end
66
+ end
67
+ end