restforce 2.5.4 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.circleci/config.yml +56 -0
- data/.rubocop.yml +18 -3
- data/.rubocop_todo.yml +8 -8
- data/CHANGELOG.md +12 -3
- data/CONTRIBUTING.md +3 -3
- data/Gemfile +4 -2
- data/Guardfile +3 -1
- data/LICENSE +1 -1
- data/README.md +22 -16
- data/Rakefile +2 -1
- data/lib/restforce.rb +2 -0
- data/lib/restforce/abstract_client.rb +2 -0
- data/lib/restforce/attachment.rb +2 -0
- data/lib/restforce/client.rb +2 -0
- data/lib/restforce/collection.rb +3 -1
- data/lib/restforce/concerns/api.rb +11 -8
- data/lib/restforce/concerns/authentication.rb +2 -0
- data/lib/restforce/concerns/base.rb +2 -0
- data/lib/restforce/concerns/caching.rb +4 -2
- data/lib/restforce/concerns/canvas.rb +2 -0
- data/lib/restforce/concerns/connection.rb +26 -20
- data/lib/restforce/concerns/picklists.rb +7 -5
- data/lib/restforce/concerns/streaming.rb +2 -0
- data/lib/restforce/concerns/verbs.rb +3 -1
- data/lib/restforce/config.rb +3 -1
- data/lib/restforce/data/client.rb +2 -0
- data/lib/restforce/document.rb +2 -0
- data/lib/restforce/mash.rb +2 -0
- data/lib/restforce/middleware.rb +2 -0
- data/lib/restforce/middleware/authentication.rb +8 -6
- data/lib/restforce/middleware/authentication/password.rb +2 -0
- data/lib/restforce/middleware/authentication/token.rb +2 -0
- data/lib/restforce/middleware/authorization.rb +3 -1
- data/lib/restforce/middleware/caching.rb +3 -1
- data/lib/restforce/middleware/custom_headers.rb +2 -0
- data/lib/restforce/middleware/gzip.rb +5 -3
- data/lib/restforce/middleware/instance_url.rb +7 -3
- data/lib/restforce/middleware/logger.rb +2 -0
- data/lib/restforce/middleware/mashify.rb +2 -0
- data/lib/restforce/middleware/multipart.rb +7 -4
- data/lib/restforce/middleware/raise_error.rb +2 -0
- data/lib/restforce/patches/parts.rb +2 -0
- data/lib/restforce/signed_request.rb +2 -0
- data/lib/restforce/sobject.rb +2 -0
- data/lib/restforce/tooling/client.rb +2 -0
- data/lib/restforce/upload_io.rb +2 -0
- data/lib/restforce/version.rb +3 -1
- data/restforce.gemspec +17 -10
- data/spec/fixtures/sobject/sobject_describe_success_response.json +48 -1
- data/spec/integration/abstract_client_spec.rb +9 -6
- data/spec/integration/data/client_spec.rb +24 -5
- data/spec/spec_helper.rb +2 -0
- data/spec/support/client_integration.rb +2 -0
- data/spec/support/concerns.rb +2 -0
- data/spec/support/event_machine.rb +2 -0
- data/spec/support/fixture_helpers.rb +2 -0
- data/spec/support/matchers.rb +2 -0
- data/spec/support/middleware.rb +3 -1
- data/spec/support/mock_cache.rb +4 -2
- data/spec/unit/abstract_client_spec.rb +2 -0
- data/spec/unit/attachment_spec.rb +2 -0
- data/spec/unit/collection_spec.rb +5 -3
- data/spec/unit/concerns/api_spec.rb +30 -11
- data/spec/unit/concerns/authentication_spec.rb +4 -2
- data/spec/unit/concerns/base_spec.rb +2 -0
- data/spec/unit/concerns/caching_spec.rb +2 -0
- data/spec/unit/concerns/canvas_spec.rb +3 -1
- data/spec/unit/concerns/connection_spec.rb +5 -3
- data/spec/unit/concerns/streaming_spec.rb +3 -1
- data/spec/unit/config_spec.rb +10 -8
- data/spec/unit/data/client_spec.rb +2 -0
- data/spec/unit/document_spec.rb +2 -0
- data/spec/unit/mash_spec.rb +3 -1
- data/spec/unit/middleware/authentication/password_spec.rb +2 -0
- data/spec/unit/middleware/authentication/token_spec.rb +2 -0
- data/spec/unit/middleware/authentication_spec.rb +3 -1
- data/spec/unit/middleware/authorization_spec.rb +2 -0
- data/spec/unit/middleware/custom_headers_spec.rb +3 -1
- data/spec/unit/middleware/gzip_spec.rb +4 -2
- data/spec/unit/middleware/instance_url_spec.rb +2 -0
- data/spec/unit/middleware/logger_spec.rb +2 -0
- data/spec/unit/middleware/mashify_spec.rb +3 -1
- data/spec/unit/middleware/raise_error_spec.rb +2 -0
- data/spec/unit/signed_request_spec.rb +2 -0
- data/spec/unit/sobject_spec.rb +5 -3
- data/spec/unit/tooling/client_spec.rb +2 -0
- metadata +35 -19
- data/.travis.yml +0 -16
- data/Gemfile.travis +0 -8
@@ -767,7 +767,48 @@
|
|
767
767
|
"label" : "three",
|
768
768
|
"defaultValue" : false,
|
769
769
|
"validFor" : null
|
770
|
-
}
|
770
|
+
}, {
|
771
|
+
"value" : "control_four",
|
772
|
+
"active" : true,
|
773
|
+
"label" : "control_four",
|
774
|
+
"defaultValue" : false,
|
775
|
+
"validFor" : null
|
776
|
+
}, {
|
777
|
+
"value" : "control_five",
|
778
|
+
"active" : true,
|
779
|
+
"label" : "control_five",
|
780
|
+
"defaultValue" : false,
|
781
|
+
"validFor" : null
|
782
|
+
}, {
|
783
|
+
"value" : "control_six",
|
784
|
+
"active" : true,
|
785
|
+
"label" : "control_six",
|
786
|
+
"defaultValue" : false,
|
787
|
+
"validFor" : null
|
788
|
+
}, {
|
789
|
+
"value" : "control_seven",
|
790
|
+
"active" : true,
|
791
|
+
"label" : "control_seven",
|
792
|
+
"defaultValue" : false,
|
793
|
+
"validFor" : null
|
794
|
+
}, {
|
795
|
+
"value" : "control_eight",
|
796
|
+
"active" : true,
|
797
|
+
"label" : "control_eight",
|
798
|
+
"defaultValue" : false,
|
799
|
+
"validFor" : null
|
800
|
+
}, {
|
801
|
+
"value" : "control_nine",
|
802
|
+
"active" : true,
|
803
|
+
"label" : "control_nine",
|
804
|
+
"defaultValue" : false,
|
805
|
+
"validFor" : null
|
806
|
+
}, {
|
807
|
+
"value" : "control_ten",
|
808
|
+
"active" : true,
|
809
|
+
"label" : "control_ten",
|
810
|
+
"defaultValue" : false,
|
811
|
+
"validFor" : null}],
|
771
812
|
"referenceTo" : [ ],
|
772
813
|
"relationshipName" : null,
|
773
814
|
"relationshipOrder" : null,
|
@@ -883,6 +924,12 @@
|
|
883
924
|
"label" : "nine",
|
884
925
|
"defaultValue" : false,
|
885
926
|
"validFor" : "QAAA"
|
927
|
+
}, {
|
928
|
+
"value" : "ten",
|
929
|
+
"active" : true,
|
930
|
+
"label" : "nine",
|
931
|
+
"defaultValue" : false,
|
932
|
+
"validFor" : "AEAA"
|
886
933
|
} ],
|
887
934
|
"referenceTo" : [ ],
|
888
935
|
"relationshipName" : null,
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
|
3
5
|
shared_examples_for Restforce::AbstractClient do
|
@@ -35,7 +37,7 @@ shared_examples_for Restforce::AbstractClient do
|
|
35
37
|
end
|
36
38
|
|
37
39
|
describe '.get_updated' do
|
38
|
-
let(:start_date) { Time.new(2015, 8, 17, 0, 0, 0, "+02:00")
|
40
|
+
let(:start_date) { Time.new(2015, 8, 17, 0, 0, 0, "+02:00") }
|
39
41
|
let(:end_date) { Time.new(2016, 8, 19, 0, 0, 0, "+02:00") }
|
40
42
|
end_string = '2016-08-18T22:00:00Z'
|
41
43
|
start_string = '2015-08-16T22:00:00Z'
|
@@ -46,7 +48,7 @@ shared_examples_for Restforce::AbstractClient do
|
|
46
48
|
end
|
47
49
|
|
48
50
|
describe '.get_deleted' do
|
49
|
-
let(:start_date) { Time.new(2015, 8, 17, 0, 0, 0, "+02:00")
|
51
|
+
let(:start_date) { Time.new(2015, 8, 17, 0, 0, 0, "+02:00") }
|
50
52
|
let(:end_date) { Time.new(2016, 8, 19, 0, 0, 0, "+02:00") }
|
51
53
|
end_string = '2016-08-18T22:00:00Z'
|
52
54
|
start_string = '2015-08-16T22:00:00Z'
|
@@ -168,7 +170,8 @@ shared_examples_for Restforce::AbstractClient do
|
|
168
170
|
context 'when updated' do
|
169
171
|
requests 'sobjects/Account/External__c/foobar',
|
170
172
|
method: :patch,
|
171
|
-
with_body: "{\"Name\":\"Foobar\"}"
|
173
|
+
with_body: "{\"Name\":\"Foobar\"}",
|
174
|
+
fixture: "sobject/upsert_updated_success_response"
|
172
175
|
|
173
176
|
context 'with symbol external Id key' do
|
174
177
|
subject do
|
@@ -379,11 +382,11 @@ shared_examples_for Restforce::AbstractClient do
|
|
379
382
|
|
380
383
|
before do
|
381
384
|
@query = stub_api_request('query\?q=SELECT%20some,%20fields%20FROM%20object').
|
382
|
-
|
383
|
-
|
385
|
+
with(headers: { 'Authorization' => "OAuth #{oauth_token}" }).
|
386
|
+
to_return(status: 401,
|
384
387
|
body: fixture('expired_session_response'),
|
385
388
|
headers: { 'Content-Type' => 'application/json' }).then.
|
386
|
-
|
389
|
+
to_return(status: 200,
|
387
390
|
body: fixture('sobject/query_success_response'),
|
388
391
|
headers: { 'Content-Type' => 'application/json' })
|
389
392
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
|
3
5
|
shared_examples_for Restforce::Data::Client do
|
@@ -8,15 +10,20 @@ shared_examples_for Restforce::Data::Client do
|
|
8
10
|
context 'when given a picklist field' do
|
9
11
|
subject { client.picklist_values('Account', 'Picklist_Field') }
|
10
12
|
it { should be_an Array }
|
11
|
-
its(:length) { should eq
|
12
|
-
it {
|
13
|
+
its(:length) { should eq 10 }
|
14
|
+
it {
|
15
|
+
should include_picklist_values %w[
|
16
|
+
one two three control_four control_five
|
17
|
+
control_six control_seven control_eight control_nine control_ten
|
18
|
+
]
|
19
|
+
}
|
13
20
|
end
|
14
21
|
|
15
22
|
context 'when given a multipicklist field' do
|
16
23
|
subject { client.picklist_values('Account', 'Picklist_Multiselect_Field') }
|
17
24
|
it { should be_an Array }
|
18
25
|
its(:length) { should eq 3 }
|
19
|
-
it { should include_picklist_values %w
|
26
|
+
it { should include_picklist_values %w[four five six] }
|
20
27
|
end
|
21
28
|
|
22
29
|
describe 'dependent picklists' do
|
@@ -29,10 +36,22 @@ shared_examples_for Restforce::Data::Client do
|
|
29
36
|
|
30
37
|
it { should be_an Array }
|
31
38
|
its(:length) { should eq 2 }
|
32
|
-
it { should include_picklist_values %w
|
39
|
+
it { should include_picklist_values %w[seven eight] }
|
33
40
|
it { should_not include_picklist_values ['nine'] }
|
34
41
|
end
|
35
42
|
|
43
|
+
context 'when given a picklist field that has a dependency index greater than 8' do
|
44
|
+
subject do
|
45
|
+
client.picklist_values('Account',
|
46
|
+
'Dependent_Picklist_Field',
|
47
|
+
valid_for: 'control_ten')
|
48
|
+
end
|
49
|
+
|
50
|
+
it { should be_an Array }
|
51
|
+
its(:length) { should eq 1 }
|
52
|
+
it { should include_picklist_values %w[ten] }
|
53
|
+
end
|
54
|
+
|
36
55
|
context 'when given a picklist field that does not have a dependency' do
|
37
56
|
subject do
|
38
57
|
client.picklist_values('Account', 'Picklist_Field', valid_for: 'one')
|
@@ -90,7 +109,7 @@ shared_examples_for Restforce::Data::Client do
|
|
90
109
|
it 'subscribes to each pushtopic' do
|
91
110
|
client.faye.should_receive(:subscribe).with(['/topic/PushTopic1',
|
92
111
|
'/topic/PushTopic2'])
|
93
|
-
client.subscribe(%w
|
112
|
+
client.subscribe(%w[PushTopic1 PushTopic2])
|
94
113
|
end
|
95
114
|
end
|
96
115
|
end
|
data/spec/spec_helper.rb
CHANGED
data/spec/support/concerns.rb
CHANGED
data/spec/support/matchers.rb
CHANGED
data/spec/support/middleware.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module MiddlewareExampleGroup
|
2
4
|
def self.included(base)
|
3
5
|
base.class_eval do
|
4
|
-
let(:app) { double('@app', call: nil)
|
6
|
+
let(:app) { double('@app', call: nil) }
|
5
7
|
let(:env) { { request_headers: {}, response_headers: {} } }
|
6
8
|
let(:retries) { 3 }
|
7
9
|
let(:options) { {} }
|
data/spec/support/mock_cache.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class MockCache
|
2
4
|
def initialize
|
3
5
|
@storage = {}
|
@@ -11,8 +13,8 @@ class MockCache
|
|
11
13
|
@storage[key] = value
|
12
14
|
end
|
13
15
|
|
14
|
-
def fetch(key
|
15
|
-
@storage[key] ||=
|
16
|
+
def fetch(key)
|
17
|
+
@storage[key] ||= yield
|
16
18
|
end
|
17
19
|
|
18
20
|
def delete(key)
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
|
3
5
|
describe Restforce::Collection do
|
@@ -16,7 +18,7 @@ describe Restforce::Collection do
|
|
16
18
|
its(:page_size) { should eq 1 }
|
17
19
|
|
18
20
|
describe 'each record' do
|
19
|
-
it { should
|
21
|
+
it { should(be_all { |record| expect(record).to be_a Restforce::SObject }) }
|
20
22
|
end
|
21
23
|
end
|
22
24
|
|
@@ -51,11 +53,11 @@ describe Restforce::Collection do
|
|
51
53
|
end
|
52
54
|
|
53
55
|
its(:pages) do
|
54
|
-
should
|
56
|
+
should(be_all { |page| expect(page).to be_a Restforce::Collection })
|
55
57
|
end
|
56
58
|
|
57
59
|
its(:has_next_page?) { should be_true }
|
58
|
-
it { should
|
60
|
+
it { should(be_all { |record| expect(record).to be_a Restforce::SObject }) }
|
59
61
|
its(:next_page) { should be_a Restforce::Collection }
|
60
62
|
end
|
61
63
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
|
3
5
|
describe Restforce::Concerns::API do
|
@@ -27,7 +29,7 @@ describe Restforce::Concerns::API do
|
|
27
29
|
it 'returns the body' do
|
28
30
|
start_string = '2002-10-31T00:02:02Z'
|
29
31
|
end_string = '2003-10-31T00:02:02Z'
|
30
|
-
url = "
|
32
|
+
url = "sobjects/Whizbang/updated/?start=#{start_string}&end=#{end_string}"
|
31
33
|
client.should_receive(:api_get).
|
32
34
|
with(url).
|
33
35
|
and_return(response)
|
@@ -43,7 +45,7 @@ describe Restforce::Concerns::API do
|
|
43
45
|
it 'returns the body' do
|
44
46
|
start_string = '2002-10-31T00:02:02Z'
|
45
47
|
end_string = '2003-10-31T00:02:02Z'
|
46
|
-
url = "
|
48
|
+
url = "sobjects/Whizbang/deleted/?start=#{start_string}&end=#{end_string}"
|
47
49
|
client.should_receive(:api_get).
|
48
50
|
with(url).
|
49
51
|
and_return(response)
|
@@ -259,7 +261,7 @@ describe Restforce::Concerns::API do
|
|
259
261
|
end
|
260
262
|
end
|
261
263
|
|
262
|
-
[
|
264
|
+
%i[create update upsert destroy].each do |method|
|
263
265
|
describe ".#{method}" do
|
264
266
|
let(:args) { [] }
|
265
267
|
subject(:result) { client.send(method, *args) }
|
@@ -289,7 +291,7 @@ describe Restforce::Concerns::API do
|
|
289
291
|
|
290
292
|
describe '.create!' do
|
291
293
|
let(:sobject) { 'Whizbang' }
|
292
|
-
let(:attrs) {
|
294
|
+
let(:attrs) { {} }
|
293
295
|
subject(:result) { client.create!(sobject, attrs) }
|
294
296
|
|
295
297
|
it 'send an HTTP POST, and returns the id of the record' do
|
@@ -303,7 +305,7 @@ describe Restforce::Concerns::API do
|
|
303
305
|
|
304
306
|
describe '.update!' do
|
305
307
|
let(:sobject) { 'Whizbang' }
|
306
|
-
let(:attrs) {
|
308
|
+
let(:attrs) { {} }
|
307
309
|
subject(:result) { client.update!(sobject, attrs) }
|
308
310
|
|
309
311
|
context 'when the id field is present' do
|
@@ -342,7 +344,7 @@ describe Restforce::Concerns::API do
|
|
342
344
|
|
343
345
|
context 'when the record is found and updated' do
|
344
346
|
it 'returns true' do
|
345
|
-
response.body
|
347
|
+
response.stub(:body) { {} }
|
346
348
|
client.should_receive(:api_patch).
|
347
349
|
with('sobjects/Whizbang/External_ID__c/1234', {}).
|
348
350
|
and_return(response)
|
@@ -352,7 +354,7 @@ describe Restforce::Concerns::API do
|
|
352
354
|
|
353
355
|
context 'when the record is found and created' do
|
354
356
|
it 'returns the id of the record' do
|
355
|
-
response.
|
357
|
+
response.stub(:body) { { "id" => "4321" } }
|
356
358
|
client.should_receive(:api_patch).
|
357
359
|
with('sobjects/Whizbang/External_ID__c/1234', {}).
|
358
360
|
and_return(response)
|
@@ -361,7 +363,7 @@ describe Restforce::Concerns::API do
|
|
361
363
|
end
|
362
364
|
|
363
365
|
context 'when the external id field is missing from the attrs' do
|
364
|
-
let(:attrs) {
|
366
|
+
let(:attrs) { {} }
|
365
367
|
|
366
368
|
it 'raises an argument error' do
|
367
369
|
expect { client.upsert!(sobject, field, attrs) }.
|
@@ -376,7 +378,7 @@ describe Restforce::Concerns::API do
|
|
376
378
|
|
377
379
|
context 'and the value for Id is provided' do
|
378
380
|
it 'returns the id of the record, and original record still contains id' do
|
379
|
-
response.
|
381
|
+
response.stub(:body) { { "id" => "4321" } }
|
380
382
|
client.should_receive(:api_patch).
|
381
383
|
with('sobjects/Whizbang/Id/4321', {}).
|
382
384
|
and_return(response)
|
@@ -389,7 +391,7 @@ describe Restforce::Concerns::API do
|
|
389
391
|
let(:attrs) { { 'External_ID__c' => '1234' } }
|
390
392
|
|
391
393
|
it 'uses POST to create the record' do
|
392
|
-
response.
|
394
|
+
response.stub(:body) { { "id" => "4321" } }
|
393
395
|
client.should_receive(:options).and_return(api_version: 38.0)
|
394
396
|
client.should_receive(:api_post).
|
395
397
|
with('sobjects/Whizbang/Id', attrs).
|
@@ -415,7 +417,7 @@ describe Restforce::Concerns::API do
|
|
415
417
|
|
416
418
|
context 'when the record is found and updated' do
|
417
419
|
it 'returns true' do
|
418
|
-
response.body
|
420
|
+
response.stub(:body) { {} }
|
419
421
|
client.should_receive(:api_patch).
|
420
422
|
with('sobjects/Whizbang/External_ID__c/%E3%81%82', {}).
|
421
423
|
and_return(response)
|
@@ -423,6 +425,23 @@ describe Restforce::Concerns::API do
|
|
423
425
|
end
|
424
426
|
end
|
425
427
|
end
|
428
|
+
|
429
|
+
describe '.upsert! with Fixnum argument' do
|
430
|
+
let(:sobject) { 'Whizbang' }
|
431
|
+
let(:field) { :External_ID__c }
|
432
|
+
let(:attrs) { { 'External_ID__c' => 1234 } }
|
433
|
+
subject(:result) { client.upsert!(sobject, field, attrs) }
|
434
|
+
|
435
|
+
context 'when the record is found and updated' do
|
436
|
+
it 'returns true' do
|
437
|
+
response.stub(:body) { {} }
|
438
|
+
client.should_receive(:api_patch).
|
439
|
+
with('sobjects/Whizbang/External_ID__c/1234', {}).
|
440
|
+
and_return(response)
|
441
|
+
expect(result).to be_true
|
442
|
+
end
|
443
|
+
end
|
444
|
+
end
|
426
445
|
end
|
427
446
|
|
428
447
|
describe '.destroy!' do
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
|
3
5
|
describe Restforce::Concerns::Authentication do
|
@@ -54,7 +56,7 @@ describe Restforce::Concerns::Authentication do
|
|
54
56
|
|
55
57
|
describe '.username_password?' do
|
56
58
|
subject { client.username_password? }
|
57
|
-
let(:options) {
|
59
|
+
let(:options) { {} }
|
58
60
|
|
59
61
|
before do
|
60
62
|
client.stub options: options
|
@@ -78,7 +80,7 @@ describe Restforce::Concerns::Authentication do
|
|
78
80
|
|
79
81
|
describe '.oauth_refresh?' do
|
80
82
|
subject { client.oauth_refresh? }
|
81
|
-
let(:options) {
|
83
|
+
let(:options) { {} }
|
82
84
|
|
83
85
|
before do
|
84
86
|
client.stub options: options
|