restforce 2.5.4 → 3.0.0
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.
- 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
|