restforce 1.5.3 → 2.0.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.
- checksums.yaml +4 -4
- data/.rubocop.yml +60 -0
- data/.rubocop_todo.yml +117 -0
- data/.travis.yml +3 -5
- data/CHANGELOG.md +6 -0
- data/README.md +2 -0
- data/Rakefile +1 -1
- data/lib/restforce/abstract_client.rb +1 -1
- data/lib/restforce/attachment.rb +1 -3
- data/lib/restforce/concerns/api.rb +22 -17
- data/lib/restforce/concerns/authentication.rb +4 -3
- data/lib/restforce/concerns/base.rb +42 -31
- data/lib/restforce/concerns/caching.rb +1 -3
- data/lib/restforce/concerns/canvas.rb +0 -2
- data/lib/restforce/concerns/connection.rb +18 -12
- data/lib/restforce/concerns/picklists.rb +10 -10
- data/lib/restforce/concerns/streaming.rb +9 -4
- data/lib/restforce/concerns/verbs.rb +0 -2
- data/lib/restforce/config.rb +19 -13
- data/lib/restforce/data/client.rb +8 -1
- data/lib/restforce/mash.rb +6 -10
- data/lib/restforce/middleware.rb +3 -1
- data/lib/restforce/middleware/authentication.rb +21 -7
- data/lib/restforce/middleware/authentication/password.rb +5 -9
- data/lib/restforce/middleware/authentication/token.rb +4 -8
- data/lib/restforce/middleware/authorization.rb +0 -3
- data/lib/restforce/middleware/caching.rb +4 -4
- data/lib/restforce/middleware/instance_url.rb +3 -5
- data/lib/restforce/middleware/logger.rb +7 -7
- data/lib/restforce/middleware/mashify.rb +2 -3
- data/lib/restforce/middleware/multipart.rb +15 -8
- data/lib/restforce/middleware/raise_error.rb +2 -1
- data/lib/restforce/patches/parts.rb +2 -3
- data/lib/restforce/signed_request.rb +2 -2
- data/lib/restforce/sobject.rb +1 -3
- data/lib/restforce/tooling/client.rb +1 -3
- data/lib/restforce/upload_io.rb +1 -3
- data/lib/restforce/version.rb +1 -1
- data/restforce.gemspec +7 -4
- data/spec/integration/abstract_client_spec.rb +123 -75
- data/spec/integration/data/client_spec.rb +24 -12
- data/spec/spec_helper.rb +2 -2
- data/spec/support/client_integration.rb +23 -17
- data/spec/support/concerns.rb +2 -2
- data/spec/support/event_machine.rb +3 -3
- data/spec/support/fixture_helpers.rb +16 -12
- data/spec/support/middleware.rb +16 -8
- data/spec/unit/abstract_client_spec.rb +1 -1
- data/spec/unit/attachment_spec.rb +2 -1
- data/spec/unit/collection_spec.rb +13 -4
- data/spec/unit/concerns/api_spec.rb +15 -13
- data/spec/unit/concerns/authentication_spec.rb +20 -17
- data/spec/unit/concerns/base_spec.rb +2 -2
- data/spec/unit/concerns/caching_spec.rb +2 -2
- data/spec/unit/concerns/canvas_spec.rb +3 -3
- data/spec/unit/concerns/connection_spec.rb +6 -7
- data/spec/unit/concerns/streaming_spec.rb +8 -8
- data/spec/unit/config_spec.rb +6 -6
- data/spec/unit/data/client_spec.rb +1 -1
- data/spec/unit/mash_spec.rb +1 -1
- data/spec/unit/middleware/authentication/password_spec.rb +14 -12
- data/spec/unit/middleware/authentication/token_spec.rb +12 -10
- data/spec/unit/middleware/authentication_spec.rb +15 -11
- data/spec/unit/middleware/authorization_spec.rb +1 -1
- data/spec/unit/middleware/gzip_spec.rb +1 -1
- data/spec/unit/middleware/instance_url_spec.rb +2 -2
- data/spec/unit/middleware/mashify_spec.rb +2 -2
- data/spec/unit/middleware/raise_error_spec.rb +23 -7
- data/spec/unit/sobject_spec.rb +16 -9
- data/spec/unit/tooling/client_spec.rb +1 -1
- metadata +23 -5
@@ -3,33 +3,41 @@ require 'spec_helper'
|
|
3
3
|
shared_examples_for Restforce::Data::Client do
|
4
4
|
describe '.picklist_values' do
|
5
5
|
requests 'sobjects/Account/describe',
|
6
|
-
|
6
|
+
fixture: 'sobject/sobject_describe_success_response'
|
7
7
|
|
8
8
|
context 'when given a picklist field' do
|
9
9
|
subject { client.picklist_values('Account', 'Picklist_Field') }
|
10
10
|
it { should be_an Array }
|
11
11
|
its(:length) { should eq 3 }
|
12
|
-
it { should include_picklist_values
|
12
|
+
it { should include_picklist_values %w(one two three) }
|
13
13
|
end
|
14
14
|
|
15
15
|
context 'when given a multipicklist field' do
|
16
16
|
subject { client.picklist_values('Account', 'Picklist_Multiselect_Field') }
|
17
17
|
it { should be_an Array }
|
18
18
|
its(:length) { should eq 3 }
|
19
|
-
it { should include_picklist_values
|
19
|
+
it { should include_picklist_values %w(four five six) }
|
20
20
|
end
|
21
21
|
|
22
22
|
describe 'dependent picklists' do
|
23
23
|
context 'when given a picklist field that has a dependency' do
|
24
|
-
subject
|
24
|
+
subject do
|
25
|
+
client.picklist_values('Account',
|
26
|
+
'Dependent_Picklist_Field',
|
27
|
+
valid_for: 'one')
|
28
|
+
end
|
29
|
+
|
25
30
|
it { should be_an Array }
|
26
31
|
its(:length) { should eq 2 }
|
27
|
-
it { should include_picklist_values
|
32
|
+
it { should include_picklist_values %w(seven eight) }
|
28
33
|
it { should_not include_picklist_values ['nine'] }
|
29
34
|
end
|
30
35
|
|
31
36
|
context 'when given a picklist field that does not have a dependency' do
|
32
|
-
subject
|
37
|
+
subject do
|
38
|
+
client.picklist_values('Account', 'Picklist_Field', valid_for: 'one')
|
39
|
+
end
|
40
|
+
|
33
41
|
it 'raises an exception' do
|
34
42
|
expect { subject }.to raise_error(/Picklist_Field is not a dependent picklist/)
|
35
43
|
end
|
@@ -37,12 +45,15 @@ shared_examples_for Restforce::Data::Client do
|
|
37
45
|
end
|
38
46
|
end
|
39
47
|
|
40
|
-
describe '.faye', :
|
48
|
+
describe '.faye', event_machine: true do
|
41
49
|
subject { client.faye }
|
42
50
|
|
43
51
|
context 'with missing instance url' do
|
44
52
|
let(:instance_url) { nil }
|
45
|
-
|
53
|
+
|
54
|
+
it "raises an error" do
|
55
|
+
expect { subject }.to raise_error RuntimeError, /Instance URL missing/
|
56
|
+
end
|
46
57
|
end
|
47
58
|
|
48
59
|
context 'with oauth token and instance url' do
|
@@ -67,7 +78,7 @@ shared_examples_for Restforce::Data::Client do
|
|
67
78
|
end
|
68
79
|
end
|
69
80
|
|
70
|
-
describe '.subscribe', :
|
81
|
+
describe '.subscribe', event_machine: true do
|
71
82
|
context 'when given a single pushtopic' do
|
72
83
|
it 'subscribes to the pushtopic' do
|
73
84
|
client.faye.should_receive(:subscribe).with(['/topic/PushTopic'])
|
@@ -77,8 +88,9 @@ shared_examples_for Restforce::Data::Client do
|
|
77
88
|
|
78
89
|
context 'when given an array of pushtopics' do
|
79
90
|
it 'subscribes to each pushtopic' do
|
80
|
-
client.faye.should_receive(:subscribe).with(['/topic/PushTopic1',
|
81
|
-
|
91
|
+
client.faye.should_receive(:subscribe).with(['/topic/PushTopic1',
|
92
|
+
'/topic/PushTopic2'])
|
93
|
+
client.subscribe(%w(PushTopic1 PushTopic2))
|
82
94
|
end
|
83
95
|
end
|
84
96
|
end
|
@@ -89,7 +101,7 @@ describe Restforce::Data::Client do
|
|
89
101
|
it_behaves_like Restforce::Client
|
90
102
|
end
|
91
103
|
|
92
|
-
describe 'without mashify', :
|
104
|
+
describe 'without mashify', mashify: false do
|
93
105
|
it_behaves_like Restforce::Client
|
94
106
|
end
|
95
107
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -11,10 +11,10 @@ WebMock.disable_net_connect!
|
|
11
11
|
|
12
12
|
RSpec.configure do |config|
|
13
13
|
config.order = 'random'
|
14
|
-
config.filter_run :
|
14
|
+
config.filter_run focus: true
|
15
15
|
config.run_all_when_everything_filtered = true
|
16
16
|
end
|
17
17
|
|
18
18
|
# Requires supporting ruby files with custom matchers and macros, etc,
|
19
19
|
# in spec/support/ and its subdirectories.
|
20
|
-
Dir[File.join(File.dirname(__FILE__), "support/**/*.rb")].each {|f| require f}
|
20
|
+
Dir[File.join(File.dirname(__FILE__), "support/**/*.rb")].each { |f| require f }
|
@@ -1,7 +1,11 @@
|
|
1
1
|
module ClientIntegrationExampleGroup
|
2
2
|
def self.included(base)
|
3
3
|
base.class_eval do
|
4
|
-
let(:oauth_token)
|
4
|
+
let(:oauth_token) do
|
5
|
+
'00Dx0000000BV7z!AR8AQAxo9UfVkh8AlV0Gomt9Czx9LjHnSSpwBMmbRcgKFmxOtvxjTrKW19ye6P' \
|
6
|
+
'E3Ds1eQz3z8jr3W7_VbWmEu4Q8TVGSTHxs'
|
7
|
+
end
|
8
|
+
|
5
9
|
let(:refresh_token) { 'refresh' }
|
6
10
|
let(:instance_url) { 'https://na1.salesforce.com' }
|
7
11
|
let(:username) { 'foo' }
|
@@ -13,15 +17,15 @@ module ClientIntegrationExampleGroup
|
|
13
17
|
|
14
18
|
let(:base_options) do
|
15
19
|
{
|
16
|
-
:
|
17
|
-
:
|
18
|
-
:
|
19
|
-
:
|
20
|
-
:
|
21
|
-
:
|
22
|
-
:
|
23
|
-
:
|
24
|
-
:
|
20
|
+
oauth_token: oauth_token,
|
21
|
+
refresh_token: refresh_token,
|
22
|
+
instance_url: instance_url,
|
23
|
+
username: username,
|
24
|
+
password: password,
|
25
|
+
security_token: security_token,
|
26
|
+
client_id: client_id,
|
27
|
+
client_secret: client_secret,
|
28
|
+
cache: cache
|
25
29
|
}
|
26
30
|
end
|
27
31
|
|
@@ -33,13 +37,15 @@ module ClientIntegrationExampleGroup
|
|
33
37
|
|
34
38
|
RSpec.configure do |config|
|
35
39
|
config.include self,
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
+
example_group: {
|
41
|
+
describes: lambda do |described|
|
42
|
+
described <= Restforce::AbstractClient
|
43
|
+
end,
|
44
|
+
file_path: %r{spec/integration}
|
45
|
+
}
|
40
46
|
|
41
|
-
config.before :
|
42
|
-
base_options.merge!(:
|
47
|
+
config.before mashify: false do
|
48
|
+
base_options.merge!(mashify: false)
|
43
49
|
end
|
44
50
|
end
|
45
|
-
end
|
51
|
+
end
|
data/spec/support/concerns.rb
CHANGED
@@ -3,12 +3,12 @@ RSpec.configure do |config|
|
|
3
3
|
EventMachine.stub(:connect) if defined?(EventMachine)
|
4
4
|
end
|
5
5
|
|
6
|
-
config.filter_run_excluding :
|
6
|
+
config.filter_run_excluding event_machine: true if RUBY_PLATFORM == 'java'
|
7
7
|
|
8
|
-
config.around :
|
8
|
+
config.around event_machine: true do |example|
|
9
9
|
EM.run {
|
10
10
|
example.run
|
11
11
|
EM.stop
|
12
12
|
}
|
13
13
|
end
|
14
|
-
end
|
14
|
+
end
|
@@ -1,33 +1,37 @@
|
|
1
1
|
module FixtureHelpers
|
2
2
|
module InstanceMethods
|
3
|
-
|
4
|
-
def stub_api_request(endpoint, options={})
|
3
|
+
def stub_api_request(endpoint, options = {})
|
5
4
|
options = {
|
6
|
-
:
|
7
|
-
:
|
8
|
-
:
|
5
|
+
method: :get,
|
6
|
+
status: 200,
|
7
|
+
api_version: Restforce.configuration.api_version
|
9
8
|
}.merge(options)
|
10
9
|
|
11
|
-
stub = stub_request(options[:method],
|
12
|
-
|
13
|
-
|
10
|
+
stub = stub_request(options[:method],
|
11
|
+
%r{/services/data/v#{options[:api_version]}/#{endpoint}})
|
12
|
+
|
13
|
+
if options[:fixture]
|
14
|
+
stub = stub.to_return(status: options[:status],
|
15
|
+
body: fixture(options[:fixture]),
|
16
|
+
headers: { 'Content-Type' => 'application/json' })
|
17
|
+
end
|
18
|
+
|
14
19
|
stub
|
15
20
|
end
|
16
21
|
|
17
|
-
def stub_login_request(
|
22
|
+
def stub_login_request(*)
|
18
23
|
stub = stub_request(:post, "https://login.salesforce.com/services/oauth2/token")
|
19
|
-
|
24
|
+
|
20
25
|
stub
|
21
26
|
end
|
22
27
|
|
23
28
|
def fixture(f)
|
24
29
|
File.read(File.expand_path("../../fixtures/#{f}.json", __FILE__))
|
25
30
|
end
|
26
|
-
|
27
31
|
end
|
28
32
|
|
29
33
|
module ClassMethods
|
30
|
-
def requests(endpoint, options={})
|
34
|
+
def requests(endpoint, options = {})
|
31
35
|
before do
|
32
36
|
(@requests ||= []) << stub_api_request(endpoint, options)
|
33
37
|
end
|
data/spec/support/middleware.rb
CHANGED
@@ -1,20 +1,24 @@
|
|
1
1
|
module MiddlewareExampleGroup
|
2
2
|
def self.included(base)
|
3
3
|
base.class_eval do
|
4
|
-
let(:app) { double('@app', :
|
5
|
-
let(:env) { { :
|
4
|
+
let(:app) { double('@app', call: nil) }
|
5
|
+
let(:env) { { request_headers: {}, response_headers: {} } }
|
6
6
|
let(:retries) { 3 }
|
7
|
-
let(:options) { {
|
7
|
+
let(:options) { {} }
|
8
8
|
let(:client) { double(Restforce::AbstractClient) }
|
9
9
|
let(:auth_callback) { double(Proc) }
|
10
|
-
|
10
|
+
|
11
|
+
let(:success_response) do
|
12
|
+
Restforce::Mash.new(JSON.parse(fixture(:auth_success_response)))
|
13
|
+
end
|
14
|
+
|
11
15
|
subject(:middleware) { described_class.new app, client, options }
|
12
16
|
end
|
13
17
|
end
|
14
18
|
|
15
19
|
RSpec.configure do |config|
|
16
20
|
config.include self,
|
17
|
-
|
21
|
+
example_group: { file_path: %r{spec/unit/middleware} }
|
18
22
|
end
|
19
23
|
end
|
20
24
|
|
@@ -35,12 +39,16 @@ shared_examples_for 'authentication middleware' do
|
|
35
39
|
end
|
36
40
|
|
37
41
|
its([:instance_url]) { should eq 'https://na1.salesforce.com' }
|
38
|
-
|
42
|
+
|
43
|
+
its([:oauth_token]) do
|
44
|
+
should eq "00Dx0000000BV7z!AR8AQAxo9UfVkh8AlV0Gomt9Czx9LjHnSSpwBMmbRcgKFmxOtv" \
|
45
|
+
"xjTrKW19ye6PE3Ds1eQz3z8jr3W7_VbWmEu4Q8TVGSTHxs"
|
46
|
+
end
|
39
47
|
end
|
40
48
|
|
41
49
|
context 'when an authentication_callback is specified' do
|
42
50
|
before(:each) do
|
43
|
-
options.merge!(:
|
51
|
+
options.merge!(authentication_callback: auth_callback)
|
44
52
|
end
|
45
53
|
|
46
54
|
it 'calls the authentication callback with the response body' do
|
@@ -61,7 +69,7 @@ shared_examples_for 'authentication middleware' do
|
|
61
69
|
|
62
70
|
context 'when an authentication_callback is specified' do
|
63
71
|
before(:each) do
|
64
|
-
options.merge!(:
|
72
|
+
options.merge!(authentication_callback: auth_callback)
|
65
73
|
end
|
66
74
|
|
67
75
|
it 'does not call the authentication callback' do
|
@@ -8,7 +8,8 @@ describe Restforce::Attachment do
|
|
8
8
|
|
9
9
|
describe '.Body' do
|
10
10
|
it 'requests the body' do
|
11
|
-
client.should_receive(:get).with(body_url).
|
11
|
+
client.should_receive(:get).with(body_url).
|
12
|
+
and_return(double('response').as_null_object)
|
12
13
|
sobject.Body
|
13
14
|
end
|
14
15
|
end
|
@@ -21,8 +21,14 @@ describe Restforce::Collection do
|
|
21
21
|
end
|
22
22
|
|
23
23
|
context 'with pagination' do
|
24
|
-
let(:first_page)
|
25
|
-
|
24
|
+
let(:first_page) do
|
25
|
+
JSON.parse(fixture('sobject/query_paginated_first_page_response'))
|
26
|
+
end
|
27
|
+
|
28
|
+
let(:next_page) do
|
29
|
+
JSON.parse(fixture('sobject/query_paginated_last_page_response'))
|
30
|
+
end
|
31
|
+
|
26
32
|
subject(:collection) { described_class.new(first_page, client) }
|
27
33
|
|
28
34
|
it { should respond_to :each }
|
@@ -41,10 +47,13 @@ describe Restforce::Collection do
|
|
41
47
|
context 'when all of the values are being requested' do
|
42
48
|
before do
|
43
49
|
client.stub(:get).
|
44
|
-
and_return(double(:
|
50
|
+
and_return(double(body: Restforce::Collection.new(next_page, client)))
|
51
|
+
end
|
52
|
+
|
53
|
+
its(:pages) do
|
54
|
+
should be_all { |page| expect(page).to be_a Restforce::Collection }
|
45
55
|
end
|
46
56
|
|
47
|
-
its(:pages) { should be_all { |page| expect(page).to be_a Restforce::Collection } }
|
48
57
|
its(:has_next_page?) { should be_true }
|
49
58
|
it { should be_all { |record| expect(record).to be_a Restforce::SObject } }
|
50
59
|
its(:next_page) { should be_a Restforce::Collection }
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Restforce::Concerns::API do
|
4
|
-
let(:response) { double('Faraday::Response', :
|
4
|
+
let(:response) { double('Faraday::Response', body: double('Body')) }
|
5
5
|
|
6
6
|
describe '.user_info' do
|
7
7
|
subject(:user_info) { client.user_info }
|
@@ -9,7 +9,7 @@ describe Restforce::Concerns::API do
|
|
9
9
|
it 'returns the user info from identity url' do
|
10
10
|
identity_url = double('identity_url')
|
11
11
|
response.body.stub(:identity).and_return(identity_url)
|
12
|
-
client.should_receive(:api_get).with
|
12
|
+
client.should_receive(:api_get).with.and_return(response)
|
13
13
|
|
14
14
|
identity = double('identity')
|
15
15
|
identity.stub(:body).and_return(identity)
|
@@ -23,7 +23,7 @@ describe Restforce::Concerns::API do
|
|
23
23
|
subject { client.list_sobjects }
|
24
24
|
|
25
25
|
before do
|
26
|
-
client.stub :
|
26
|
+
client.stub describe: [{ 'name' => 'foo' }]
|
27
27
|
end
|
28
28
|
|
29
29
|
it { should eq ['foo'] }
|
@@ -64,7 +64,9 @@ describe Restforce::Concerns::API do
|
|
64
64
|
end
|
65
65
|
|
66
66
|
context 'when given the id of a layout' do
|
67
|
-
subject(:describe_layouts)
|
67
|
+
subject(:describe_layouts) do
|
68
|
+
client.describe_layouts('Whizbang', '012E0000000RHEp')
|
69
|
+
end
|
68
70
|
|
69
71
|
it 'returns the describe for the specified layout' do
|
70
72
|
client.should_receive(:api_get).
|
@@ -79,7 +81,7 @@ describe Restforce::Concerns::API do
|
|
79
81
|
subject(:org_id) { client.org_id }
|
80
82
|
|
81
83
|
it 'returns the organization id' do
|
82
|
-
organizations = [
|
84
|
+
organizations = [{ 'Id' => 'foo' }]
|
83
85
|
client.should_receive(:query).
|
84
86
|
with('select id from Organization').
|
85
87
|
and_return(organizations)
|
@@ -93,12 +95,12 @@ describe Restforce::Concerns::API do
|
|
93
95
|
|
94
96
|
context 'with mashify middleware' do
|
95
97
|
before do
|
96
|
-
client.stub
|
98
|
+
client.stub mashify?: true
|
97
99
|
end
|
98
100
|
|
99
101
|
it 'returns the body' do
|
100
102
|
client.should_receive(:api_get).
|
101
|
-
with('query', :
|
103
|
+
with('query', q: soql).
|
102
104
|
and_return(response)
|
103
105
|
expect(results).to eq response.body
|
104
106
|
end
|
@@ -106,7 +108,7 @@ describe Restforce::Concerns::API do
|
|
106
108
|
|
107
109
|
context 'without mashify middleware' do
|
108
110
|
before do
|
109
|
-
client.stub
|
111
|
+
client.stub mashify?: false
|
110
112
|
end
|
111
113
|
|
112
114
|
it 'returns the records attribute of the body' do
|
@@ -115,7 +117,7 @@ describe Restforce::Concerns::API do
|
|
115
117
|
with('records').
|
116
118
|
and_return(records)
|
117
119
|
client.should_receive(:api_get).
|
118
|
-
with('query', :
|
120
|
+
with('query', q: soql).
|
119
121
|
and_return(response)
|
120
122
|
expect(results).to eq records
|
121
123
|
end
|
@@ -128,7 +130,7 @@ describe Restforce::Concerns::API do
|
|
128
130
|
|
129
131
|
it 'performs a sosl search' do
|
130
132
|
client.should_receive(:api_get).
|
131
|
-
with('search', :
|
133
|
+
with('search', q: sosl).
|
132
134
|
and_return(response)
|
133
135
|
expect(results).to eq response.body
|
134
136
|
end
|
@@ -177,17 +179,17 @@ describe Restforce::Concerns::API do
|
|
177
179
|
subject(:result) { client.update!(sobject, attrs) }
|
178
180
|
|
179
181
|
context 'when the id field is present' do
|
180
|
-
let(:attrs) { { :
|
182
|
+
let(:attrs) { { id: '1234', StageName: "Call Scheduled" } }
|
181
183
|
|
182
184
|
it 'sends an HTTP PATCH, and returns true' do
|
183
185
|
client.should_receive(:api_patch).
|
184
|
-
with('sobjects/Whizbang/1234',
|
186
|
+
with('sobjects/Whizbang/1234', StageName: "Call Scheduled")
|
185
187
|
expect(result).to be_true
|
186
188
|
end
|
187
189
|
end
|
188
190
|
|
189
191
|
context 'when the id field is missing from the attrs' do
|
190
|
-
subject { lambda { result }}
|
192
|
+
subject { lambda { result } }
|
191
193
|
it { should raise_error ArgumentError, 'Id field missing from attrs.' }
|
192
194
|
end
|
193
195
|
end
|