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,90 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
shared_examples_for Restforce::Data::Client do
|
4
|
+
describe '.picklist_values' do
|
5
|
+
requests 'sobjects/Account/describe',
|
6
|
+
:fixture => 'sobject/sobject_describe_success_response'
|
7
|
+
|
8
|
+
context 'when given a picklist field' do
|
9
|
+
subject { client.picklist_values('Account', 'Picklist_Field') }
|
10
|
+
it { should be_an Array }
|
11
|
+
its(:length) { should eq 3 }
|
12
|
+
it { should include_picklist_values ['one', 'two', 'three'] }
|
13
|
+
end
|
14
|
+
|
15
|
+
context 'when given a multipicklist field' do
|
16
|
+
subject { client.picklist_values('Account', 'Picklist_Multiselect_Field') }
|
17
|
+
it { should be_an Array }
|
18
|
+
its(:length) { should eq 3 }
|
19
|
+
it { should include_picklist_values ['four', 'five', 'six'] }
|
20
|
+
end
|
21
|
+
|
22
|
+
describe 'dependent picklists' do
|
23
|
+
context 'when given a picklist field that has a dependency' do
|
24
|
+
subject { client.picklist_values('Account', 'Dependent_Picklist_Field', :valid_for => 'one') }
|
25
|
+
it { should be_an Array }
|
26
|
+
its(:length) { should eq 2 }
|
27
|
+
it { should include_picklist_values ['seven', 'eight'] }
|
28
|
+
it { should_not include_picklist_values ['nine'] }
|
29
|
+
end
|
30
|
+
|
31
|
+
context 'when given a picklist field that does not have a dependency' do
|
32
|
+
subject { client.picklist_values('Account', 'Picklist_Field', :valid_for => 'one') }
|
33
|
+
it 'raises an exception' do
|
34
|
+
expect { subject }.to raise_error(/Picklist_Field is not a dependent picklist/)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe '.faye', :event_machine => true do
|
41
|
+
subject { client.faye }
|
42
|
+
|
43
|
+
context 'with missing instance url' do
|
44
|
+
let(:instance_url) { nil }
|
45
|
+
specify { expect { subject }.to raise_error RuntimeError, 'Instance URL missing. Call .authenticate! first.' }
|
46
|
+
end
|
47
|
+
|
48
|
+
context 'with oauth token and instance url' do
|
49
|
+
let(:instance_url) { 'http://google.com' }
|
50
|
+
let(:oauth_token) { 'bar' }
|
51
|
+
specify { expect { subject }.to_not raise_error }
|
52
|
+
end
|
53
|
+
|
54
|
+
context 'when the connection goes down' do
|
55
|
+
it 'should reauthenticate' do
|
56
|
+
access_token = double('access token')
|
57
|
+
access_token.stub(:access_token).and_return('token')
|
58
|
+
client.should_receive(:authenticate!).and_return(access_token)
|
59
|
+
client.faye.should_receive(:set_header).with('Authorization', "OAuth token")
|
60
|
+
client.faye.trigger('transport:down')
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe '.subcribe', :event_machine => true do
|
66
|
+
context 'when given a single pushtopic' do
|
67
|
+
it 'subscribes to the pushtopic' do
|
68
|
+
client.faye.should_receive(:subscribe).with(['/topic/PushTopic'])
|
69
|
+
client.subscribe('PushTopic')
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
context 'when given an array of pushtopics' do
|
74
|
+
it 'subscribes to each pushtopic' do
|
75
|
+
client.faye.should_receive(:subscribe).with(['/topic/PushTopic1', '/topic/PushTopic2'])
|
76
|
+
client.subscribe(['PushTopic1', 'PushTopic2'])
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe Restforce::Data::Client do
|
83
|
+
describe 'with mashify' do
|
84
|
+
it_behaves_like Restforce::Client
|
85
|
+
end
|
86
|
+
|
87
|
+
describe 'without mashify', :mashify => false do
|
88
|
+
it_behaves_like Restforce::Client
|
89
|
+
end
|
90
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -12,17 +12,3 @@ WebMock.disable_net_connect!
|
|
12
12
|
# Requires supporting ruby files with custom matchers and macros, etc,
|
13
13
|
# in spec/support/ and its subdirectories.
|
14
14
|
Dir[File.join(File.dirname(__FILE__), "support/**/*.rb")].each {|f| require f}
|
15
|
-
|
16
|
-
RSpec.configure do |config|
|
17
|
-
config.before do
|
18
|
-
EventMachine.stub(:connect) if defined?(EventMachine)
|
19
|
-
end
|
20
|
-
|
21
|
-
config.around :eventmachine => true do |example|
|
22
|
-
EM.run {
|
23
|
-
example.run
|
24
|
-
EM.stop
|
25
|
-
}
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module ClientIntegrationExampleGroup
|
2
|
+
def self.included(base)
|
3
|
+
base.class_eval do
|
4
|
+
let(:oauth_token) { '00Dx0000000BV7z!AR8AQAxo9UfVkh8AlV0Gomt9Czx9LjHnSSpwBMmbRcgKFmxOtvxjTrKW19ye6PE3Ds1eQz3z8jr3W7_VbWmEu4Q8TVGSTHxs' }
|
5
|
+
let(:refresh_token) { 'refresh' }
|
6
|
+
let(:instance_url) { 'https://na1.salesforce.com' }
|
7
|
+
let(:username) { 'foo' }
|
8
|
+
let(:password) { 'bar' }
|
9
|
+
let(:security_token) { 'security_token' }
|
10
|
+
let(:client_id) { 'client_id' }
|
11
|
+
let(:client_secret) { 'client_secret' }
|
12
|
+
let(:cache) { nil }
|
13
|
+
|
14
|
+
let(:base_options) do
|
15
|
+
{
|
16
|
+
:oauth_token => oauth_token,
|
17
|
+
:refresh_token => refresh_token,
|
18
|
+
:instance_url => instance_url,
|
19
|
+
:username => username,
|
20
|
+
:password => password,
|
21
|
+
:security_token => security_token,
|
22
|
+
:client_id => client_id,
|
23
|
+
:client_secret => client_secret,
|
24
|
+
:cache => cache
|
25
|
+
}
|
26
|
+
end
|
27
|
+
|
28
|
+
let(:client_options) { base_options }
|
29
|
+
|
30
|
+
subject(:client) { described_class.new client_options }
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
RSpec.configure do |config|
|
35
|
+
config.include self,
|
36
|
+
:example_group => {
|
37
|
+
:describes => lambda { |described| described <= Restforce::AbstractClient },
|
38
|
+
:file_path => %r{spec/integration}
|
39
|
+
}
|
40
|
+
|
41
|
+
config.before :mashify => false do
|
42
|
+
client.middleware.delete(Restforce::Middleware::Mashify)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module ConcernsExampleGroup
|
2
|
+
def self.included(base)
|
3
|
+
base.class_eval do
|
4
|
+
let(:klass) do
|
5
|
+
context = self
|
6
|
+
Class.new { include context.described_class }
|
7
|
+
end
|
8
|
+
|
9
|
+
let(:client) { klass.new }
|
10
|
+
|
11
|
+
subject { client }
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
RSpec.configure do |config|
|
16
|
+
config.include self, :example_group => { :file_path => %r{spec/unit/concerns} }
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
RSpec.configure do |config|
|
2
|
+
config.before do
|
3
|
+
EventMachine.stub(:connect) if defined?(EventMachine)
|
4
|
+
end
|
5
|
+
|
6
|
+
config.filter_run_excluding :event_machine => true if RUBY_PLATFORM == 'java'
|
7
|
+
|
8
|
+
config.around :event_machine => true do |example|
|
9
|
+
EM.run {
|
10
|
+
example.run
|
11
|
+
EM.stop
|
12
|
+
}
|
13
|
+
end
|
14
|
+
end
|
data/spec/support/middleware.rb
CHANGED
@@ -1,3 +1,21 @@
|
|
1
|
+
module MiddlewareExampleGroup
|
2
|
+
def self.included(base)
|
3
|
+
base.class_eval do
|
4
|
+
let(:app) { double('@app', :call => nil) }
|
5
|
+
let(:env) { { :request_headers => {}, :response_headers => {} } }
|
6
|
+
let(:retries) { 3 }
|
7
|
+
let(:options) { { } }
|
8
|
+
let(:client) { double(Restforce::AbstractClient) }
|
9
|
+
subject(:middleware) { described_class.new app, client, options }
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
RSpec.configure do |config|
|
14
|
+
config.include self,
|
15
|
+
:example_group => { :file_path => %r{spec/unit/middleware} }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
1
19
|
shared_examples_for 'authentication middleware' do
|
2
20
|
describe '.authenticate!' do
|
3
21
|
after do
|
@@ -28,6 +46,5 @@ shared_examples_for 'authentication middleware' do
|
|
28
46
|
}.to raise_error Restforce::AuthenticationError, /^invalid_grant: .*/
|
29
47
|
end
|
30
48
|
end
|
31
|
-
|
32
49
|
end
|
33
50
|
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Restforce::AbstractClient do
|
4
|
+
subject { described_class }
|
5
|
+
|
6
|
+
it { should < Restforce::Concerns::Base }
|
7
|
+
it { should < Restforce::Concerns::Connection }
|
8
|
+
it { should < Restforce::Concerns::Authentication }
|
9
|
+
it { should < Restforce::Concerns::Caching }
|
10
|
+
it { should < Restforce::Concerns::API }
|
11
|
+
end
|
@@ -1,13 +1,10 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Restforce::Attachment do
|
4
|
-
|
5
|
-
|
4
|
+
let(:client) { double(Restforce::AbstractClient) }
|
6
5
|
let(:body_url) { '/services/data/v26.0/sobjects/Attachment/00PG0000006Hll5MAC/Body' }
|
7
|
-
let(:hash)
|
8
|
-
let(:sobject)
|
9
|
-
described_class.new(hash, client)
|
10
|
-
end
|
6
|
+
let(:hash) { { 'Id' => '1234', 'Body' => body_url } }
|
7
|
+
let(:sobject) { described_class.new(hash, client) }
|
11
8
|
|
12
9
|
describe '.Body' do
|
13
10
|
it 'requests the body' do
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Restforce::Collection do
|
4
|
+
let(:client) { double(Restforce::AbstractClient) }
|
5
|
+
|
6
|
+
describe '#new' do
|
7
|
+
context 'without pagination' do
|
8
|
+
subject(:collection) do
|
9
|
+
described_class.new(JSON.parse(fixture('sobject/query_success_response')), client)
|
10
|
+
end
|
11
|
+
|
12
|
+
it { should respond_to :each }
|
13
|
+
its(:size) { should eq 1 }
|
14
|
+
its(:has_next_page?) { should be_false }
|
15
|
+
it { should have_client client }
|
16
|
+
|
17
|
+
describe 'each record' do
|
18
|
+
it { should be_all { |record| expect(record).to be_a Restforce::SObject } }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context 'with pagination' do
|
23
|
+
let(:first_page) { JSON.parse(fixture('sobject/query_paginated_first_page_response')) }
|
24
|
+
let(:next_page) { JSON.parse(fixture('sobject/query_paginated_last_page_response')) }
|
25
|
+
subject(:collection) { described_class.new(first_page, client) }
|
26
|
+
|
27
|
+
it { should respond_to :each }
|
28
|
+
it { should have_client client }
|
29
|
+
|
30
|
+
context 'when only values from the first page are being requested' do
|
31
|
+
before { client.should_receive(:get).never }
|
32
|
+
|
33
|
+
its(:size) { should eq 2 }
|
34
|
+
its(:first) { should be_a Restforce::SObject }
|
35
|
+
end
|
36
|
+
|
37
|
+
context 'when all of the values are being requested' do
|
38
|
+
before do
|
39
|
+
client.stub(:get).
|
40
|
+
and_return(stub :body => Restforce::Collection.new(next_page, client))
|
41
|
+
end
|
42
|
+
|
43
|
+
its(:pages) { should be_all { |page| expect(page).to be_a Restforce::Collection } }
|
44
|
+
its(:has_next_page?) { should be_true }
|
45
|
+
it { should be_all { |record| expect(record).to be_a Restforce::SObject } }
|
46
|
+
its(:next_page) { should be_a Restforce::Collection }
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,222 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Restforce::Concerns::API do
|
4
|
+
let(:response) { double('Faraday::Response', :body => double('Body')) }
|
5
|
+
|
6
|
+
describe '.list_sobjects' do
|
7
|
+
subject { client.list_sobjects }
|
8
|
+
|
9
|
+
before do
|
10
|
+
client.stub :describe => [ { 'name' => 'foo' } ]
|
11
|
+
end
|
12
|
+
|
13
|
+
it { should eq ['foo'] }
|
14
|
+
end
|
15
|
+
|
16
|
+
describe '.describe' do
|
17
|
+
subject(:describe) { client.describe }
|
18
|
+
|
19
|
+
it 'returns the global describe' do
|
20
|
+
sobjects = double('sobjects')
|
21
|
+
response.body.stub(:[]).with('sobjects').and_return(sobjects)
|
22
|
+
client.should_receive(:api_get).
|
23
|
+
with('sobjects').
|
24
|
+
and_return(response)
|
25
|
+
expect(describe).to eq sobjects
|
26
|
+
end
|
27
|
+
|
28
|
+
context 'when given the name of an sobject' do
|
29
|
+
subject(:describe) { client.describe('Whizbang') }
|
30
|
+
|
31
|
+
it 'returns the full describe' do
|
32
|
+
client.should_receive(:api_get).
|
33
|
+
with('sobjects/Whizbang/describe').
|
34
|
+
and_return(response)
|
35
|
+
expect(describe).to eq response.body
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe '.org_id' do
|
41
|
+
subject(:org_id) { client.org_id }
|
42
|
+
|
43
|
+
it 'returns the organization id' do
|
44
|
+
organizations = [ { 'Id' => 'foo' } ]
|
45
|
+
client.should_receive(:query).
|
46
|
+
with('select id from Organization').
|
47
|
+
and_return(organizations)
|
48
|
+
expect(org_id).to eq 'foo'
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe '.query' do
|
53
|
+
let(:soql) { 'Select Id from Account' }
|
54
|
+
subject(:results) { client.query(soql) }
|
55
|
+
|
56
|
+
context 'with mashify middleware' do
|
57
|
+
before do
|
58
|
+
client.stub :mashify? => true
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'returns the body' do
|
62
|
+
client.should_receive(:api_get).
|
63
|
+
with('query', :q => soql).
|
64
|
+
and_return(response)
|
65
|
+
expect(results).to eq response.body
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context 'without mashify middleware' do
|
70
|
+
before do
|
71
|
+
client.stub :mashify? => false
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'returns the records attribute of the body' do
|
75
|
+
records = double('records')
|
76
|
+
response.body.stub(:[]).
|
77
|
+
with('records').
|
78
|
+
and_return(records)
|
79
|
+
client.should_receive(:api_get).
|
80
|
+
with('query', :q => soql).
|
81
|
+
and_return(response)
|
82
|
+
expect(results).to eq records
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe '.search' do
|
88
|
+
let(:sosl) { 'FIND {bar}' }
|
89
|
+
subject(:results) { client.search(sosl) }
|
90
|
+
|
91
|
+
it 'performs a sosl search' do
|
92
|
+
client.should_receive(:api_get).
|
93
|
+
with('search', :q => sosl).
|
94
|
+
and_return(response)
|
95
|
+
expect(results).to eq response.body
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
[:create, :update, :upsert, :destroy].each do |method|
|
100
|
+
describe ".#{method}" do
|
101
|
+
let(:args) { [] }
|
102
|
+
subject(:result) { client.send(method, *args) }
|
103
|
+
|
104
|
+
it "delegates to :#{method}!" do
|
105
|
+
client.should_receive(:"#{method}!").
|
106
|
+
with(*args).
|
107
|
+
and_return(response)
|
108
|
+
expect(result).to eq response
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'rescues exceptions' do
|
112
|
+
[Faraday::Error::ClientError].each do |exception_klass|
|
113
|
+
client.should_receive(:"#{method}!").
|
114
|
+
with(*args).
|
115
|
+
and_raise(exception_klass.new(nil))
|
116
|
+
expect(result).to eq false
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
describe '.create!' do
|
123
|
+
let(:sobject) { 'Whizbang' }
|
124
|
+
let(:attrs) { Hash.new }
|
125
|
+
subject(:result) { client.create!(sobject, attrs) }
|
126
|
+
|
127
|
+
it 'send an HTTP POST, and returns the id of the record' do
|
128
|
+
response.body.stub(:[]).with('id').and_return('1234')
|
129
|
+
client.should_receive(:api_post).
|
130
|
+
with('sobjects/Whizbang', attrs).
|
131
|
+
and_return(response)
|
132
|
+
expect(result).to eq '1234'
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
describe '.update!' do
|
137
|
+
let(:sobject) { 'Whizbang' }
|
138
|
+
let(:attrs) { Hash.new }
|
139
|
+
subject(:result) { client.update!(sobject, attrs) }
|
140
|
+
|
141
|
+
context 'when the id field is present' do
|
142
|
+
let(:attrs) { { :id => '1234' } }
|
143
|
+
|
144
|
+
it 'sends an HTTP PATCH, and returns true' do
|
145
|
+
client.should_receive(:api_patch).
|
146
|
+
with('sobjects/Whizbang/1234', attrs)
|
147
|
+
expect(result).to be_true
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
context 'when the id field is missing from the attrs' do
|
152
|
+
subject { lambda { result }}
|
153
|
+
it { should raise_error ArgumentError, 'Id field missing from attrs.' }
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
describe '.upsert!' do
|
158
|
+
let(:sobject) { 'Whizbang' }
|
159
|
+
let(:field) { :External_ID__c }
|
160
|
+
let(:attrs) { { 'External_ID__c' => '1234' } }
|
161
|
+
subject(:result) { client.upsert!(sobject, field, attrs) }
|
162
|
+
|
163
|
+
context 'when the record is found and updated' do
|
164
|
+
it 'returns true' do
|
165
|
+
response.body.stub :[]
|
166
|
+
client.should_receive(:api_patch).
|
167
|
+
with('sobjects/Whizbang/External_ID__c/1234', {}).
|
168
|
+
and_return(response)
|
169
|
+
expect(result).to be_true
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
context 'when the record is found and created' do
|
174
|
+
it 'returns the id of the record' do
|
175
|
+
response.body.stub(:[]).with('id').and_return('4321')
|
176
|
+
client.should_receive(:api_patch).
|
177
|
+
with('sobjects/Whizbang/External_ID__c/1234', {}).
|
178
|
+
and_return(response)
|
179
|
+
expect(result).to eq '4321'
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
describe '.destroy!' do
|
185
|
+
let(:id) { '1234' }
|
186
|
+
let(:sobject) { 'Whizbang' }
|
187
|
+
subject(:result) { client.destroy!(sobject, id) }
|
188
|
+
|
189
|
+
it 'sends and HTTP delete, and returns true' do
|
190
|
+
client.should_receive(:api_delete).
|
191
|
+
with('sobjects/Whizbang/1234')
|
192
|
+
expect(result).to be_true
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
describe '.find' do
|
197
|
+
let(:sobject) { 'Whizbang' }
|
198
|
+
let(:id) { '1234' }
|
199
|
+
let(:field) { nil }
|
200
|
+
subject(:result) { client.find(sobject, id, field) }
|
201
|
+
|
202
|
+
context 'when no external id is specified' do
|
203
|
+
it 'returns the full representation of the object' do
|
204
|
+
client.should_receive(:api_get).
|
205
|
+
with('sobjects/Whizbang/1234').
|
206
|
+
and_return(response)
|
207
|
+
expect(result).to eq response.body
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
context 'when an external id is specified' do
|
212
|
+
let(:field) { :External_ID__c }
|
213
|
+
|
214
|
+
it 'returns the full representation of the object' do
|
215
|
+
client.should_receive(:api_get).
|
216
|
+
with('sobjects/Whizbang/External_ID__c/1234').
|
217
|
+
and_return(response)
|
218
|
+
expect(result).to eq response.body
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|