restforce 5.0.6 → 6.2.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.
- checksums.yaml +4 -4
- data/.github/dependabot.yml +4 -13
- data/.github/funding.yml +1 -0
- data/.github/workflows/build.yml +23 -0
- data/.github/workflows/faraday.yml +27 -0
- data/.rubocop.yml +2 -2
- data/CHANGELOG.md +68 -0
- data/Gemfile +15 -6
- data/README.md +61 -7
- data/UPGRADING.md +29 -0
- data/lib/restforce/abstract_client.rb +1 -0
- data/lib/restforce/collection.rb +20 -2
- data/lib/restforce/concerns/api.rb +2 -1
- data/lib/restforce/concerns/base.rb +2 -2
- data/lib/restforce/concerns/composite_api.rb +104 -0
- data/lib/restforce/concerns/connection.rb +1 -1
- data/lib/restforce/concerns/picklists.rb +1 -1
- data/lib/restforce/config.rb +12 -10
- data/lib/restforce/error_code.rb +30 -9
- data/lib/restforce/file_part.rb +12 -4
- data/lib/restforce/middleware/authentication.rb +1 -0
- data/lib/restforce/middleware/caching.rb +140 -15
- data/lib/restforce/middleware/gzip.rb +4 -0
- data/lib/restforce/middleware/json_request.rb +90 -0
- data/lib/restforce/middleware/json_response.rb +85 -0
- data/lib/restforce/middleware/logger.rb +6 -2
- data/lib/restforce/middleware/raise_error.rb +10 -1
- data/lib/restforce/version.rb +1 -1
- data/lib/restforce.rb +11 -7
- data/restforce.gemspec +8 -16
- data/spec/fixtures/sobject/list_view_results_success_response.json +151 -0
- data/spec/integration/abstract_client_spec.rb +42 -30
- data/spec/integration/data/client_spec.rb +6 -2
- data/spec/spec_helper.rb +10 -0
- data/spec/support/client_integration.rb +7 -7
- data/spec/support/concerns.rb +1 -1
- data/spec/support/middleware.rb +1 -2
- data/spec/unit/collection_spec.rb +22 -4
- data/spec/unit/concerns/api_spec.rb +22 -15
- data/spec/unit/concerns/authentication_spec.rb +6 -6
- data/spec/unit/concerns/base_spec.rb +1 -1
- data/spec/unit/concerns/composite_api_spec.rb +169 -0
- data/spec/unit/concerns/connection_spec.rb +1 -1
- data/spec/unit/concerns/streaming_spec.rb +4 -4
- data/spec/unit/config_spec.rb +2 -2
- data/spec/unit/middleware/authentication/jwt_bearer_spec.rb +24 -8
- data/spec/unit/middleware/authentication/password_spec.rb +12 -4
- data/spec/unit/middleware/authentication/token_spec.rb +12 -4
- data/spec/unit/middleware/authentication_spec.rb +8 -8
- data/spec/unit/middleware/authorization_spec.rb +5 -1
- data/spec/unit/middleware/custom_headers_spec.rb +6 -2
- data/spec/unit/middleware/gzip_spec.rb +60 -16
- data/spec/unit/middleware/instance_url_spec.rb +2 -2
- data/spec/unit/middleware/logger_spec.rb +1 -1
- data/spec/unit/middleware/raise_error_spec.rb +20 -10
- data/spec/unit/sobject_spec.rb +9 -5
- metadata +55 -172
- data/.circleci/config.yml +0 -56
@@ -0,0 +1,169 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Restforce::Concerns::CompositeAPI do
|
6
|
+
let(:endpoint) { 'composite' }
|
7
|
+
|
8
|
+
before do
|
9
|
+
client.should_receive(:options).and_return(api_version: 38.0)
|
10
|
+
end
|
11
|
+
|
12
|
+
shared_examples_for 'composite requests' do
|
13
|
+
it '#create' do
|
14
|
+
client.
|
15
|
+
should_receive(:api_post).
|
16
|
+
with(endpoint, { compositeRequest: [
|
17
|
+
{
|
18
|
+
method: 'POST',
|
19
|
+
url: '/services/data/v38.0/sobjects/Object',
|
20
|
+
body: { name: 'test' },
|
21
|
+
referenceId: 'create_ref'
|
22
|
+
}
|
23
|
+
], allOrNone: all_or_none, collateSubrequests: false }.to_json).
|
24
|
+
and_return(response)
|
25
|
+
|
26
|
+
client.send(method) do |subrequests|
|
27
|
+
subrequests.create('Object', 'create_ref', name: 'test')
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
it '#update' do
|
32
|
+
client.
|
33
|
+
should_receive(:api_post).
|
34
|
+
with(endpoint, { compositeRequest: [
|
35
|
+
{
|
36
|
+
method: 'PATCH',
|
37
|
+
url: '/services/data/v38.0/sobjects/Object/123',
|
38
|
+
body: { name: 'test' },
|
39
|
+
referenceId: 'update_ref'
|
40
|
+
}
|
41
|
+
], allOrNone: all_or_none, collateSubrequests: false }.to_json).
|
42
|
+
and_return(response)
|
43
|
+
|
44
|
+
client.send(method) do |subrequests|
|
45
|
+
subrequests.update('Object', 'update_ref', id: '123', name: 'test')
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
it '#destroy' do
|
50
|
+
client.
|
51
|
+
should_receive(:api_post).
|
52
|
+
with(endpoint, { compositeRequest: [
|
53
|
+
{
|
54
|
+
method: 'DELETE',
|
55
|
+
url: '/services/data/v38.0/sobjects/Object/123',
|
56
|
+
referenceId: 'destroy_ref'
|
57
|
+
}
|
58
|
+
], allOrNone: all_or_none, collateSubrequests: false }.to_json).
|
59
|
+
and_return(response)
|
60
|
+
|
61
|
+
client.send(method) do |subrequests|
|
62
|
+
subrequests.destroy('Object', 'destroy_ref', '123')
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
it '#upsert' do
|
67
|
+
client.
|
68
|
+
should_receive(:api_post).
|
69
|
+
with(endpoint, { compositeRequest: [
|
70
|
+
{
|
71
|
+
method: 'PATCH',
|
72
|
+
url: '/services/data/v38.0/sobjects/Object/extIdField__c/456',
|
73
|
+
body: { name: 'test' },
|
74
|
+
referenceId: 'upsert_ref'
|
75
|
+
}
|
76
|
+
], allOrNone: all_or_none, collateSubrequests: false }.to_json).
|
77
|
+
and_return(response)
|
78
|
+
|
79
|
+
client.send(method) do |subrequests|
|
80
|
+
subrequests.upsert('Object', 'upsert_ref', 'extIdField__c',
|
81
|
+
extIdField__c: '456', name: 'test')
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'multiple subrequests' do
|
86
|
+
client.
|
87
|
+
should_receive(:api_post).
|
88
|
+
with(endpoint, { compositeRequest: [
|
89
|
+
{
|
90
|
+
method: 'POST',
|
91
|
+
url: '/services/data/v38.0/sobjects/Object',
|
92
|
+
body: { name: 'test' },
|
93
|
+
referenceId: 'create_ref'
|
94
|
+
},
|
95
|
+
{
|
96
|
+
method: 'PATCH',
|
97
|
+
url: '/services/data/v38.0/sobjects/Object/123',
|
98
|
+
body: { name: 'test' },
|
99
|
+
referenceId: 'update_ref'
|
100
|
+
},
|
101
|
+
{
|
102
|
+
method: 'DELETE',
|
103
|
+
url: '/services/data/v38.0/sobjects/Object/123',
|
104
|
+
referenceId: 'destroy_ref'
|
105
|
+
}
|
106
|
+
], allOrNone: all_or_none, collateSubrequests: false }.to_json).
|
107
|
+
and_return(response)
|
108
|
+
|
109
|
+
client.send(method) do |subrequests|
|
110
|
+
subrequests.create('Object', 'create_ref', name: 'test')
|
111
|
+
subrequests.update('Object', 'update_ref', id: '123', name: 'test')
|
112
|
+
subrequests.destroy('Object', 'destroy_ref', '123')
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
it 'fails if more than 25 requests' do
|
117
|
+
expect do
|
118
|
+
client.send(method) do |subrequests|
|
119
|
+
26.times do |i|
|
120
|
+
subrequests.upsert('Object', "upsert_ref_#{i}", 'extIdField__c',
|
121
|
+
extIdField__c: '456', name: 'test')
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end.to raise_error(ArgumentError)
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'has response in CompositeAPIError' do
|
128
|
+
response = double('Faraday::Response',
|
129
|
+
body: { 'compositeResponse' =>
|
130
|
+
[{ 'httpStatusCode' => 400,
|
131
|
+
'body' => [{ 'errorCode' =>
|
132
|
+
'DUPLICATE_VALUE' }] }] })
|
133
|
+
client.
|
134
|
+
should_receive(:api_post).
|
135
|
+
with(endpoint, { compositeRequest: [
|
136
|
+
{
|
137
|
+
method: 'POST',
|
138
|
+
url: '/services/data/v38.0/sobjects/Object',
|
139
|
+
body: { name: 'test' },
|
140
|
+
referenceId: 'create_ref'
|
141
|
+
}
|
142
|
+
], allOrNone: true, collateSubrequests: false }.to_json).
|
143
|
+
and_return(response)
|
144
|
+
arg = method == :composite ? { all_or_none: true } : {}
|
145
|
+
expect do
|
146
|
+
client.send(method, **arg) do |subrequests|
|
147
|
+
subrequests.create('Object', 'create_ref', name: 'test')
|
148
|
+
end
|
149
|
+
end.to raise_error(an_instance_of(Restforce::CompositeAPIError).
|
150
|
+
and(having_attributes(response: response)))
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
describe '#composite' do
|
155
|
+
let(:method) { :composite }
|
156
|
+
let(:all_or_none) { false }
|
157
|
+
let(:response) { double('Faraday::Response', body: { 'compositeResponse' => [] }) }
|
158
|
+
it_behaves_like 'composite requests'
|
159
|
+
end
|
160
|
+
|
161
|
+
describe '#composite!' do
|
162
|
+
let(:method) { :composite! }
|
163
|
+
let(:all_or_none) { true }
|
164
|
+
let(:response) do
|
165
|
+
double('Faraday::Response', body: { 'compositeResponse' => [] })
|
166
|
+
end
|
167
|
+
it_behaves_like 'composite requests'
|
168
|
+
end
|
169
|
+
end
|
@@ -73,7 +73,7 @@ describe Restforce::Concerns::Connection do
|
|
73
73
|
Restforce.stub(log?: true)
|
74
74
|
end
|
75
75
|
|
76
|
-
it "must always be used as the last handler" do
|
76
|
+
it "must always be used as the last handler before the adapter" do
|
77
77
|
client.middleware.handlers.reverse.index(Restforce::Middleware::Logger).
|
78
78
|
should eq 0
|
79
79
|
end
|
@@ -13,10 +13,10 @@ describe Restforce::Concerns::Streaming, event_machine: true do
|
|
13
13
|
it 'subscribes to the topics with faye' do
|
14
14
|
faye_double.
|
15
15
|
should_receive(:subscribe).
|
16
|
-
with(channels
|
16
|
+
with(channels)
|
17
17
|
client.stub faye: faye_double
|
18
18
|
|
19
|
-
client.subscription(channels
|
19
|
+
client.subscription(channels)
|
20
20
|
end
|
21
21
|
|
22
22
|
context "replay_handlers" do
|
@@ -87,7 +87,7 @@ describe Restforce::Concerns::Streaming, event_machine: true do
|
|
87
87
|
end
|
88
88
|
|
89
89
|
it 'connects to the streaming api' do
|
90
|
-
client.stub authenticate!:
|
90
|
+
client.stub authenticate!: double(access_token: 'secret2')
|
91
91
|
faye_double = double('Faye::Client')
|
92
92
|
Faye::Client.
|
93
93
|
should_receive(:new).
|
@@ -110,7 +110,7 @@ describe Restforce::Concerns::Streaming, event_machine: true do
|
|
110
110
|
end
|
111
111
|
end
|
112
112
|
|
113
|
-
describe
|
113
|
+
describe "ReplayExtension" do
|
114
114
|
let(:handlers) { {} }
|
115
115
|
let(:extension) { Restforce::Concerns::Streaming::ReplayExtension.new(handlers) }
|
116
116
|
|
data/spec/unit/config_spec.rb
CHANGED
@@ -44,7 +44,7 @@ describe Restforce do
|
|
44
44
|
'SALESFORCE_PROXY_URI' => 'proxy',
|
45
45
|
'SALESFORCE_HOST' => 'test.host.com',
|
46
46
|
'SALESFORCE_API_VERSION' => '37.0' }.
|
47
|
-
each { |var, value| ENV.stub(:
|
47
|
+
each { |var, value| ENV.stub(:fetch).with(var, anything).and_return(value) }
|
48
48
|
end
|
49
49
|
|
50
50
|
its(:username) { should eq 'foo' }
|
@@ -76,7 +76,7 @@ describe Restforce do
|
|
76
76
|
subject { Restforce.log? }
|
77
77
|
|
78
78
|
context 'by default' do
|
79
|
-
it { should
|
79
|
+
it { should be false }
|
80
80
|
end
|
81
81
|
end
|
82
82
|
|
@@ -17,15 +17,23 @@ describe Restforce::Middleware::Authentication::JWTBearer do
|
|
17
17
|
let(:success_request) do
|
18
18
|
stub_login_request(
|
19
19
|
body: "grant_type=grant_type—urn:ietf:params:oauth:grant-type:jwt-bearer&" \
|
20
|
-
|
21
|
-
).to_return(
|
20
|
+
"assertion=abc1234567890"
|
21
|
+
).to_return(
|
22
|
+
status: 200,
|
23
|
+
body: fixture(:auth_success_response),
|
24
|
+
headers: { "Content-Type" => "application/json" }
|
25
|
+
)
|
22
26
|
end
|
23
27
|
|
24
28
|
let(:fail_request) do
|
25
29
|
stub_login_request(
|
26
30
|
body: "grant_type=grant_type—urn:ietf:params:oauth:grant-type:jwt-bearer&" \
|
27
|
-
|
28
|
-
).to_return(
|
31
|
+
"assertion=abc1234567890"
|
32
|
+
).to_return(
|
33
|
+
status: 400,
|
34
|
+
body: fixture(:refresh_error_response),
|
35
|
+
headers: { "Content-Type" => "application/json" }
|
36
|
+
)
|
29
37
|
end
|
30
38
|
end
|
31
39
|
|
@@ -47,15 +55,23 @@ describe Restforce::Middleware::Authentication::JWTBearer do
|
|
47
55
|
let(:success_request) do
|
48
56
|
stub_login_request(
|
49
57
|
body: "grant_type=grant_type—urn:ietf:params:oauth:grant-type:jwt-bearer&" \
|
50
|
-
|
51
|
-
).to_return(
|
58
|
+
"assertion=abc1234567890"
|
59
|
+
).to_return(
|
60
|
+
status: 200,
|
61
|
+
body: fixture(:auth_success_response),
|
62
|
+
headers: { "Content-Type" => "application/json" }
|
63
|
+
)
|
52
64
|
end
|
53
65
|
|
54
66
|
let(:fail_request) do
|
55
67
|
stub_login_request(
|
56
68
|
body: "grant_type=grant_type—urn:ietf:params:oauth:grant-type:jwt-bearer&" \
|
57
|
-
|
58
|
-
).to_return(
|
69
|
+
"assertion=abc1234567890"
|
70
|
+
).to_return(
|
71
|
+
status: 400,
|
72
|
+
body: fixture(:refresh_error_response),
|
73
|
+
headers: { "Content-Type" => "application/json" }
|
74
|
+
)
|
59
75
|
end
|
60
76
|
end
|
61
77
|
end
|
@@ -17,15 +17,23 @@ describe Restforce::Middleware::Authentication::Password do
|
|
17
17
|
let(:success_request) do
|
18
18
|
stub_login_request(
|
19
19
|
body: "grant_type=password&client_id=client_id&client_secret=client_secret" \
|
20
|
-
|
21
|
-
).to_return(
|
20
|
+
"&username=foo&password=barsecurity_token"
|
21
|
+
).to_return(
|
22
|
+
status: 200,
|
23
|
+
body: fixture(:auth_success_response),
|
24
|
+
headers: { "Content-Type" => "application/json" }
|
25
|
+
)
|
22
26
|
end
|
23
27
|
|
24
28
|
let(:fail_request) do
|
25
29
|
stub_login_request(
|
26
30
|
body: "grant_type=password&client_id=client_id&client_secret=client_secret" \
|
27
|
-
|
28
|
-
).to_return(
|
31
|
+
"&username=foo&password=barsecurity_token"
|
32
|
+
).to_return(
|
33
|
+
status: 400,
|
34
|
+
body: fixture(:auth_error_response),
|
35
|
+
headers: { "Content-Type" => "application/json" }
|
36
|
+
)
|
29
37
|
end
|
30
38
|
end
|
31
39
|
|
@@ -15,15 +15,23 @@ describe Restforce::Middleware::Authentication::Token do
|
|
15
15
|
let(:success_request) do
|
16
16
|
stub_login_request(
|
17
17
|
body: "grant_type=refresh_token&refresh_token=refresh_token&" \
|
18
|
-
|
19
|
-
).to_return(
|
18
|
+
"client_id=client_id&client_secret=client_secret"
|
19
|
+
).to_return(
|
20
|
+
status: 200,
|
21
|
+
body: fixture(:auth_success_response),
|
22
|
+
headers: { "Content-Type" => "application/json" }
|
23
|
+
)
|
20
24
|
end
|
21
25
|
|
22
26
|
let(:fail_request) do
|
23
27
|
stub_login_request(
|
24
28
|
body: "grant_type=refresh_token&refresh_token=refresh_token&" \
|
25
|
-
|
26
|
-
).to_return(
|
29
|
+
"client_id=client_id&client_secret=client_secret"
|
30
|
+
).to_return(
|
31
|
+
status: 400,
|
32
|
+
body: fixture(:refresh_error_response),
|
33
|
+
headers: { "Content-Type" => "application/json" }
|
34
|
+
)
|
27
35
|
end
|
28
36
|
end
|
29
37
|
end
|
@@ -15,7 +15,7 @@ describe Restforce::Middleware::Authentication do
|
|
15
15
|
|
16
16
|
describe '.authenticate!' do
|
17
17
|
subject { lambda { middleware.authenticate! } }
|
18
|
-
it {
|
18
|
+
it { expect { subject.call }.to raise_error NotImplementedError }
|
19
19
|
end
|
20
20
|
|
21
21
|
describe '.call' do
|
@@ -26,7 +26,7 @@ describe Restforce::Middleware::Authentication do
|
|
26
26
|
app.should_receive(:call).once
|
27
27
|
end
|
28
28
|
|
29
|
-
it {
|
29
|
+
it { expect { subject.call }.not_to raise_error }
|
30
30
|
end
|
31
31
|
|
32
32
|
context 'when an exception is thrown' do
|
@@ -37,7 +37,7 @@ describe Restforce::Middleware::Authentication do
|
|
37
37
|
and_raise(Restforce::UnauthorizedError.new('something bad'))
|
38
38
|
end
|
39
39
|
|
40
|
-
it {
|
40
|
+
it { expect { subject.call }.to raise_error Restforce::UnauthorizedError }
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
@@ -59,7 +59,7 @@ describe Restforce::Middleware::Authentication do
|
|
59
59
|
end
|
60
60
|
|
61
61
|
its(:handlers) {
|
62
|
-
should include
|
62
|
+
should include Restforce::Middleware::JsonResponse
|
63
63
|
}
|
64
64
|
its(:handlers) { should_not include Restforce::Middleware::Logger }
|
65
65
|
its(:adapter) { should eq Faraday::Adapter::NetHttp }
|
@@ -71,7 +71,7 @@ describe Restforce::Middleware::Authentication do
|
|
71
71
|
end
|
72
72
|
|
73
73
|
its(:handlers) {
|
74
|
-
should include
|
74
|
+
should include Restforce::Middleware::JsonResponse,
|
75
75
|
Restforce::Middleware::Logger
|
76
76
|
}
|
77
77
|
its(:adapter) { should eq Faraday::Adapter::NetHttp }
|
@@ -83,7 +83,7 @@ describe Restforce::Middleware::Authentication do
|
|
83
83
|
end
|
84
84
|
|
85
85
|
its(:handlers) {
|
86
|
-
should include
|
86
|
+
should include Restforce::Middleware::JsonResponse
|
87
87
|
}
|
88
88
|
its(:adapter) { should eq Faraday::Adapter::Typhoeus }
|
89
89
|
end
|
@@ -97,7 +97,7 @@ describe Restforce::Middleware::Authentication do
|
|
97
97
|
end
|
98
98
|
|
99
99
|
describe '.error_message' do
|
100
|
-
context 'when
|
100
|
+
context 'when response_body is present' do
|
101
101
|
let(:response) {
|
102
102
|
Faraday::Response.new(
|
103
103
|
response_body: { 'error' => 'error', 'error_description' => 'description' },
|
@@ -109,7 +109,7 @@ describe Restforce::Middleware::Authentication do
|
|
109
109
|
it { should eq "error: description (401)" }
|
110
110
|
end
|
111
111
|
|
112
|
-
context 'when
|
112
|
+
context 'when response_body is nil' do
|
113
113
|
let(:response) { Faraday::Response.new(status: 401) }
|
114
114
|
|
115
115
|
subject { middleware.error_message(response) }
|
@@ -8,6 +8,10 @@ describe Restforce::Middleware::Authorization do
|
|
8
8
|
describe '.call' do
|
9
9
|
subject { lambda { middleware.call(env) } }
|
10
10
|
|
11
|
-
it {
|
11
|
+
it {
|
12
|
+
expect { subject.call }.to change {
|
13
|
+
env[:request_headers]['Authorization']
|
14
|
+
}.to eq 'OAuth token'
|
15
|
+
}
|
12
16
|
end
|
13
17
|
end
|
@@ -9,13 +9,17 @@ describe Restforce::Middleware::CustomHeaders do
|
|
9
9
|
context 'when :request_headers are a Hash' do
|
10
10
|
let(:options) { { request_headers: { 'x-test-header' => 'Test Value' } } }
|
11
11
|
|
12
|
-
it {
|
12
|
+
it {
|
13
|
+
expect { subject.call }.to change {
|
14
|
+
env[:request_headers]['x-test-header']
|
15
|
+
}.to eq 'Test Value'
|
16
|
+
}
|
13
17
|
end
|
14
18
|
|
15
19
|
context 'when :request_headers are not a Hash' do
|
16
20
|
let(:options) { { request_headers: 'bad header' } }
|
17
21
|
|
18
|
-
it {
|
22
|
+
it { expect { subject.call }.not_to(change { env[:request_headers] }) }
|
19
23
|
end
|
20
24
|
end
|
21
25
|
end
|
@@ -17,29 +17,73 @@ describe Restforce::Middleware::Gzip do
|
|
17
17
|
describe '.call' do
|
18
18
|
subject { lambda { middleware.call(env) } }
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
20
|
+
context 'when the response is gzipped' do
|
21
|
+
before do
|
22
|
+
app.should_receive(:on_complete) { middleware.on_complete(env) }
|
23
|
+
app.should_receive(:call) do
|
24
|
+
env[:body] = gzip fixture('sobject/query_success_response')
|
25
|
+
env[:response_headers]['Content-Encoding'] = 'gzip'
|
26
|
+
app
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'decompresses the body' do
|
31
|
+
expect { subject.call }.to change {
|
32
|
+
env[:body]
|
33
|
+
}.to(fixture('sobject/query_success_response'))
|
34
|
+
end
|
35
|
+
|
36
|
+
context 'when :compress is false' do
|
37
|
+
it 'does not set request headers to ask the response to be compressed' do
|
38
|
+
expect { subject.call }.
|
39
|
+
not_to(change { env[:request_headers]['Accept-Encoding'] })
|
40
|
+
end
|
26
41
|
end
|
27
|
-
end
|
28
42
|
|
29
|
-
|
30
|
-
|
43
|
+
context 'when :compress is true' do
|
44
|
+
before do
|
45
|
+
options[:compress] = true
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'sets request headers to ask the response to be compressed' do
|
49
|
+
expect { subject.call }.to change {
|
50
|
+
env[:request_headers]['Accept-Encoding']
|
51
|
+
}.to('gzip')
|
52
|
+
end
|
53
|
+
end
|
31
54
|
end
|
32
55
|
|
33
|
-
context 'when
|
34
|
-
|
56
|
+
context 'when the response claims to be gzipped, but is not' do
|
57
|
+
before do
|
58
|
+
app.should_receive(:on_complete) { middleware.on_complete(env) }
|
59
|
+
app.should_receive(:call) do
|
60
|
+
env[:body] = fixture('sobject/query_success_response')
|
61
|
+
env[:response_headers]['Content-Encoding'] = 'gzip'
|
62
|
+
app
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'does not decompress the body' do
|
67
|
+
expect { subject.call }.to change {
|
68
|
+
env[:body]
|
69
|
+
}.to(fixture('sobject/query_success_response'))
|
70
|
+
end
|
35
71
|
end
|
36
72
|
|
37
|
-
context 'when
|
73
|
+
context 'when the response does not even claim to be gzipped' do
|
38
74
|
before do
|
39
|
-
|
75
|
+
app.should_receive(:on_complete) { middleware.on_complete(env) }
|
76
|
+
app.should_receive(:call) do
|
77
|
+
env[:body] = fixture('sobject/query_success_response')
|
78
|
+
app
|
79
|
+
end
|
40
80
|
end
|
41
81
|
|
42
|
-
it
|
82
|
+
it 'does not decompress the body' do
|
83
|
+
expect { subject.call }.to change {
|
84
|
+
env[:body]
|
85
|
+
}.to(fixture('sobject/query_success_response'))
|
86
|
+
end
|
43
87
|
end
|
44
88
|
end
|
45
89
|
|
@@ -58,11 +102,11 @@ describe Restforce::Middleware::Gzip do
|
|
58
102
|
env[:response_headers]['Content-Encoding'] = 'gzip'
|
59
103
|
end
|
60
104
|
|
61
|
-
it { should
|
105
|
+
it { should be true }
|
62
106
|
end
|
63
107
|
|
64
108
|
context 'when not gzipped' do
|
65
|
-
it { should
|
109
|
+
it { should be false }
|
66
110
|
end
|
67
111
|
end
|
68
112
|
end
|
@@ -11,7 +11,7 @@ describe Restforce::Middleware::InstanceURL do
|
|
11
11
|
client.stub_chain :connection, url_prefix: URI.parse('http:/')
|
12
12
|
end
|
13
13
|
|
14
|
-
it {
|
14
|
+
it { expect { subject.call }.to raise_error Restforce::UnauthorizedError }
|
15
15
|
end
|
16
16
|
|
17
17
|
context 'when the instance url is set' do
|
@@ -20,7 +20,7 @@ describe Restforce::Middleware::InstanceURL do
|
|
20
20
|
app.should_receive(:call).once
|
21
21
|
end
|
22
22
|
|
23
|
-
it {
|
23
|
+
it { expect { subject.call }.not_to raise_error }
|
24
24
|
end
|
25
25
|
end
|
26
26
|
end
|
@@ -14,8 +14,10 @@ describe Restforce::Middleware::RaiseError do
|
|
14
14
|
let(:status) { 404 }
|
15
15
|
|
16
16
|
it 'raises Restforce::NotFoundError' do
|
17
|
-
expect { on_complete }.to raise_error
|
18
|
-
|
17
|
+
expect { on_complete }.to raise_error do |error|
|
18
|
+
expect(error).to be_a Restforce::NotFoundError
|
19
|
+
expect(error.message).to start_with("INVALID_FIELD: error_message")
|
20
|
+
end
|
19
21
|
end
|
20
22
|
|
21
23
|
it 'raises an error that inherits from Faraday::ResourceNotFound' do
|
@@ -40,8 +42,10 @@ describe Restforce::Middleware::RaiseError do
|
|
40
42
|
let(:status) { 400 }
|
41
43
|
|
42
44
|
it "raises an error derived from the response's errorCode" do
|
43
|
-
expect { on_complete }.to raise_error
|
44
|
-
|
45
|
+
expect { on_complete }.to raise_error do |error|
|
46
|
+
expect(error).to be_a Restforce::ErrorCode::InvalidField
|
47
|
+
expect(error.message).to start_with("INVALID_FIELD: error_message")
|
48
|
+
end
|
45
49
|
end
|
46
50
|
|
47
51
|
it 'raises an error that inherits from Faraday::ClientError' do
|
@@ -53,8 +57,10 @@ describe Restforce::Middleware::RaiseError do
|
|
53
57
|
let(:status) { 401 }
|
54
58
|
|
55
59
|
it 'raises Restforce::UnauthorizedError' do
|
56
|
-
expect { on_complete }.to raise_error
|
57
|
-
|
60
|
+
expect { on_complete }.to raise_error do |error|
|
61
|
+
expect(error).to be_a Restforce::UnauthorizedError
|
62
|
+
expect(error.message).to start_with("INVALID_FIELD: error_message")
|
63
|
+
end
|
58
64
|
end
|
59
65
|
end
|
60
66
|
|
@@ -76,13 +82,17 @@ describe Restforce::Middleware::RaiseError do
|
|
76
82
|
let(:status) { 400 }
|
77
83
|
|
78
84
|
it 'raises a generic Restforce::ResponseError' do
|
79
|
-
expect { on_complete }.to raise_error
|
80
|
-
|
85
|
+
expect { on_complete }.to raise_error do |error|
|
86
|
+
expect(error).to be_a Restforce::ResponseError
|
87
|
+
expect(error.message).to start_with("(error code missing): An error occured")
|
88
|
+
end
|
81
89
|
end
|
82
90
|
|
83
91
|
it 'raises an error that inherits from Faraday::ClientError' do
|
84
|
-
expect { on_complete }.to raise_error
|
85
|
-
|
92
|
+
expect { on_complete }.to raise_error do |error|
|
93
|
+
expect(error).to be_a Faraday::ClientError
|
94
|
+
expect(error.message).to start_with("(error code missing): An error occured")
|
95
|
+
end
|
86
96
|
end
|
87
97
|
end
|
88
98
|
|