digital_femsa 1.1.0 → 1.1.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/Gemfile +2 -0
- data/Gemfile.lock +104 -0
- data/README.md +4 -4
- data/VERSION +1 -1
- data/config-ruby.json +1 -1
- data/digital_femsa.gemspec +1 -1
- data/lib/digital_femsa/models/webhook_request.rb +247 -8
- data/lib/digital_femsa/version.rb +1 -1
- data/spec/api/balances_api_spec.rb +24 -22
- data/spec/api/charges_api_spec.rb +92 -49
- data/spec/api/companies_api_spec.rb +57 -35
- data/spec/api/customers_api_spec.rb +115 -99
- data/spec/api/events_api_spec.rb +72 -48
- data/spec/api/generated_apis_coverage_spec.rb +94 -0
- data/spec/api/logs_api_spec.rb +57 -38
- data/spec/api/orders_api_spec.rb +134 -108
- data/spec/api/payment_link_api_spec.rb +91 -81
- data/spec/api/payment_methods_api_spec.rb +102 -65
- data/spec/api/transactions_api_spec.rb +63 -41
- data/spec/api/transfers_api_spec.rb +57 -38
- data/spec/api/webhook_keys_api_spec.rb +87 -68
- data/spec/api/webhooks_api_spec.rb +110 -79
- data/spec/api_client_spec.rb +259 -0
- data/spec/models/generated_models_coverage_spec.rb +152 -0
- data/spec/models/webhook_request_ssrf_protection_spec.rb +275 -0
- data/spec/spec_helper.rb +37 -0
- metadata +28 -25
|
@@ -13,92 +13,111 @@ Generator version: 7.5.0
|
|
|
13
13
|
require 'spec_helper'
|
|
14
14
|
require 'json'
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
before do
|
|
21
|
-
# run before each test
|
|
22
|
-
@api_instance = DigitalFemsa::WebhookKeysApi.new
|
|
23
|
-
end
|
|
16
|
+
RSpec.describe DigitalFemsa::WebhookKeysApi do
|
|
17
|
+
let(:config) { DigitalFemsa::Configuration.new }
|
|
18
|
+
let(:api_client) { instance_double(DigitalFemsa::ApiClient) }
|
|
19
|
+
let(:api_instance) { described_class.new(api_client) }
|
|
24
20
|
|
|
25
|
-
|
|
26
|
-
|
|
21
|
+
before do
|
|
22
|
+
allow(api_client).to receive(:config).and_return(config)
|
|
23
|
+
allow(api_client).to receive(:select_header_accept).and_return('application/vnd.app-v2.1.0+json')
|
|
24
|
+
allow(api_client).to receive(:select_header_content_type).and_return('application/json')
|
|
25
|
+
allow(api_client).to receive(:object_to_http_body) { |value| value.to_json }
|
|
27
26
|
end
|
|
28
27
|
|
|
29
28
|
describe 'test an instance of WebhookKeysApi' do
|
|
30
|
-
it '
|
|
31
|
-
expect(
|
|
29
|
+
it 'creates an instance of WebhookKeysApi' do
|
|
30
|
+
expect(api_instance).to be_instance_of(DigitalFemsa::WebhookKeysApi)
|
|
32
31
|
end
|
|
33
32
|
end
|
|
34
33
|
|
|
35
|
-
#
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
34
|
+
describe '#create_webhook_key_with_http_info' do
|
|
35
|
+
it 'sends POST request with serialized payload' do
|
|
36
|
+
payload = { enabled: true }
|
|
37
|
+
|
|
38
|
+
expect(api_client).to receive(:call_api).with(:POST, '/webhook_keys', hash_including(
|
|
39
|
+
operation: :'WebhookKeysApi.create_webhook_key',
|
|
40
|
+
body: payload.to_json,
|
|
41
|
+
return_type: 'WebhookKeyCreateResponse'
|
|
42
|
+
)).and_return([:created, 201, {}])
|
|
43
|
+
|
|
44
|
+
data = api_instance.create_webhook_key(webhook_key_request: payload)
|
|
45
|
+
expect(data).to eq(:created)
|
|
45
46
|
end
|
|
46
47
|
end
|
|
47
48
|
|
|
48
|
-
#
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
# @return [WebhookKeyDeleteResponse]
|
|
54
|
-
describe 'delete_webhook_key test' do
|
|
55
|
-
it 'should work' do
|
|
56
|
-
# assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
|
|
49
|
+
describe '#delete_webhook_key_with_http_info' do
|
|
50
|
+
it 'raises when id is missing' do
|
|
51
|
+
expect do
|
|
52
|
+
api_instance.delete_webhook_key_with_http_info(nil)
|
|
53
|
+
end.to raise_error(ArgumentError, /Missing the required parameter 'id'/)
|
|
57
54
|
end
|
|
58
|
-
end
|
|
59
55
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
it 'should work' do
|
|
69
|
-
# assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
|
|
56
|
+
it 'sends DELETE request with escaped id path' do
|
|
57
|
+
expect(api_client).to receive(:call_api).with(:DELETE, '/webhook_keys/key%2F123', hash_including(
|
|
58
|
+
operation: :'WebhookKeysApi.delete_webhook_key',
|
|
59
|
+
return_type: 'WebhookKeyDeleteResponse'
|
|
60
|
+
)).and_return([:deleted, 200, {}])
|
|
61
|
+
|
|
62
|
+
data = api_instance.delete_webhook_key('key/123')
|
|
63
|
+
expect(data).to eq(:deleted)
|
|
70
64
|
end
|
|
71
65
|
end
|
|
72
66
|
|
|
73
|
-
#
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
# @option opts [String] :x_child_company_id In the case of a holding company, the company id of the child company to which will process the request.
|
|
79
|
-
# @option opts [Integer] :limit The numbers of items to return, the maximum value is 250
|
|
80
|
-
# @option opts [String] :search General order search, e.g. by mail, reference etc.
|
|
81
|
-
# @option opts [String] :_next next page
|
|
82
|
-
# @option opts [String] :previous previous page
|
|
83
|
-
# @return [GetWebhookKeysResponse]
|
|
84
|
-
describe 'get_webhook_keys test' do
|
|
85
|
-
it 'should work' do
|
|
86
|
-
# assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
|
|
67
|
+
describe '#get_webhook_keys_with_http_info' do
|
|
68
|
+
it 'raises for limit higher than 250' do
|
|
69
|
+
expect do
|
|
70
|
+
api_instance.get_webhook_keys_with_http_info(limit: 251)
|
|
71
|
+
end.to raise_error(ArgumentError, /must be smaller than or equal to 250/)
|
|
87
72
|
end
|
|
88
|
-
end
|
|
89
73
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
74
|
+
it 'raises for limit lower than 1' do
|
|
75
|
+
expect do
|
|
76
|
+
api_instance.get_webhook_keys_with_http_info(limit: 0)
|
|
77
|
+
end.to raise_error(ArgumentError, /must be greater than or equal to 1/)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
it 'maps pagination and search query params' do
|
|
81
|
+
expect(api_client).to receive(:call_api).with(:GET, '/webhook_keys', hash_including(
|
|
82
|
+
operation: :'WebhookKeysApi.get_webhook_keys',
|
|
83
|
+
query_params: {
|
|
84
|
+
limit: 50,
|
|
85
|
+
search: 'active',
|
|
86
|
+
next: 'next_token',
|
|
87
|
+
previous: 'prev_token'
|
|
88
|
+
},
|
|
89
|
+
return_type: 'GetWebhookKeysResponse'
|
|
90
|
+
)).and_return([:list, 200, {}])
|
|
91
|
+
|
|
92
|
+
data = api_instance.get_webhook_keys(
|
|
93
|
+
limit: 50,
|
|
94
|
+
search: 'active',
|
|
95
|
+
_next: 'next_token',
|
|
96
|
+
previous: 'prev_token'
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
expect(data).to eq(:list)
|
|
101
100
|
end
|
|
102
101
|
end
|
|
103
102
|
|
|
103
|
+
describe '#update_webhook_key_with_http_info' do
|
|
104
|
+
it 'raises when id is missing' do
|
|
105
|
+
expect do
|
|
106
|
+
api_instance.update_webhook_key_with_http_info(nil)
|
|
107
|
+
end.to raise_error(ArgumentError, /Missing the required parameter 'id'/)
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
it 'sends PUT request with serialized payload' do
|
|
111
|
+
payload = { disabled: true }
|
|
112
|
+
|
|
113
|
+
expect(api_client).to receive(:call_api).with(:PUT, '/webhook_keys/key_123', hash_including(
|
|
114
|
+
operation: :'WebhookKeysApi.update_webhook_key',
|
|
115
|
+
body: payload.to_json,
|
|
116
|
+
return_type: 'WebhookKeyResponse'
|
|
117
|
+
)).and_return([:updated, 200, {}])
|
|
118
|
+
|
|
119
|
+
data = api_instance.update_webhook_key('key_123', webhook_key_update_request: payload)
|
|
120
|
+
expect(data).to eq(:updated)
|
|
121
|
+
end
|
|
122
|
+
end
|
|
104
123
|
end
|
|
@@ -13,106 +13,137 @@ Generator version: 7.5.0
|
|
|
13
13
|
require 'spec_helper'
|
|
14
14
|
require 'json'
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
before do
|
|
21
|
-
# run before each test
|
|
22
|
-
@api_instance = DigitalFemsa::WebhooksApi.new
|
|
23
|
-
end
|
|
16
|
+
RSpec.describe DigitalFemsa::WebhooksApi do
|
|
17
|
+
let(:config) { DigitalFemsa::Configuration.new }
|
|
18
|
+
let(:api_client) { instance_double(DigitalFemsa::ApiClient) }
|
|
19
|
+
let(:api_instance) { described_class.new(api_client) }
|
|
24
20
|
|
|
25
|
-
|
|
26
|
-
|
|
21
|
+
before do
|
|
22
|
+
allow(api_client).to receive(:config).and_return(config)
|
|
23
|
+
allow(api_client).to receive(:select_header_accept).and_return('application/vnd.app-v2.1.0+json')
|
|
24
|
+
allow(api_client).to receive(:select_header_content_type).and_return('application/json')
|
|
25
|
+
allow(api_client).to receive(:object_to_http_body) { |value| value.to_json }
|
|
27
26
|
end
|
|
28
27
|
|
|
29
28
|
describe 'test an instance of WebhooksApi' do
|
|
30
|
-
it '
|
|
31
|
-
expect(
|
|
29
|
+
it 'creates an instance of WebhooksApi' do
|
|
30
|
+
expect(api_instance).to be_instance_of(DigitalFemsa::WebhooksApi)
|
|
32
31
|
end
|
|
33
32
|
end
|
|
34
33
|
|
|
35
|
-
#
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
# @option opts [String] :accept_language Use for knowing which language to use
|
|
41
|
-
# @return [WebhookResponse]
|
|
42
|
-
describe 'create_webhook test' do
|
|
43
|
-
it 'should work' do
|
|
44
|
-
# assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
|
|
34
|
+
describe '#create_webhook_with_http_info' do
|
|
35
|
+
it 'raises when webhook_request is missing' do
|
|
36
|
+
expect do
|
|
37
|
+
api_instance.create_webhook_with_http_info(nil)
|
|
38
|
+
end.to raise_error(ArgumentError, /Missing the required parameter 'webhook_request'/)
|
|
45
39
|
end
|
|
46
|
-
end
|
|
47
40
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
41
|
+
it 'sends POST request with serialized payload' do
|
|
42
|
+
payload = { url: 'https://example.com/hook', synchronous: false }
|
|
43
|
+
|
|
44
|
+
expect(api_client).to receive(:call_api).with(:POST, '/webhooks', hash_including(
|
|
45
|
+
operation: :'WebhooksApi.create_webhook',
|
|
46
|
+
body: payload.to_json,
|
|
47
|
+
return_type: 'WebhookResponse'
|
|
48
|
+
)).and_return([:created, 201, {}])
|
|
49
|
+
|
|
50
|
+
data = api_instance.create_webhook(payload)
|
|
51
|
+
expect(data).to eq(:created)
|
|
57
52
|
end
|
|
58
53
|
end
|
|
59
54
|
|
|
60
|
-
#
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
# @option opts [String] :x_child_company_id In the case of a holding company, the company id of the child company to which will process the request.
|
|
66
|
-
# @return [WebhookResponse]
|
|
67
|
-
describe 'get_webhook test' do
|
|
68
|
-
it 'should work' do
|
|
69
|
-
# assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
|
|
55
|
+
describe '#delete_webhook_with_http_info' do
|
|
56
|
+
it 'raises when id is missing' do
|
|
57
|
+
expect do
|
|
58
|
+
api_instance.delete_webhook_with_http_info(nil)
|
|
59
|
+
end.to raise_error(ArgumentError, /Missing the required parameter 'id'/)
|
|
70
60
|
end
|
|
71
|
-
end
|
|
72
61
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
# @option opts [String] :_next next page
|
|
82
|
-
# @option opts [String] :previous previous page
|
|
83
|
-
# @return [GetWebhooksResponse]
|
|
84
|
-
describe 'get_webhooks test' do
|
|
85
|
-
it 'should work' do
|
|
86
|
-
# assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
|
|
62
|
+
it 'sends DELETE request with escaped id path' do
|
|
63
|
+
expect(api_client).to receive(:call_api).with(:DELETE, '/webhooks/whk%2F123', hash_including(
|
|
64
|
+
operation: :'WebhooksApi.delete_webhook',
|
|
65
|
+
return_type: 'WebhookResponse'
|
|
66
|
+
)).and_return([:deleted, 200, {}])
|
|
67
|
+
|
|
68
|
+
data = api_instance.delete_webhook('whk/123')
|
|
69
|
+
expect(data).to eq(:deleted)
|
|
87
70
|
end
|
|
88
71
|
end
|
|
89
72
|
|
|
90
|
-
#
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
73
|
+
describe '#get_webhooks_with_http_info' do
|
|
74
|
+
it 'raises for limit higher than 250' do
|
|
75
|
+
expect do
|
|
76
|
+
api_instance.get_webhooks_with_http_info(limit: 251)
|
|
77
|
+
end.to raise_error(ArgumentError, /must be smaller than or equal to 250/)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
it 'raises for limit lower than 1' do
|
|
81
|
+
expect do
|
|
82
|
+
api_instance.get_webhooks_with_http_info(limit: 0)
|
|
83
|
+
end.to raise_error(ArgumentError, /must be greater than or equal to 1/)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
it 'maps filters into query params' do
|
|
87
|
+
expect(api_client).to receive(:call_api).with(:GET, '/webhooks', hash_including(
|
|
88
|
+
operation: :'WebhooksApi.get_webhooks',
|
|
89
|
+
query_params: {
|
|
90
|
+
limit: 25,
|
|
91
|
+
search: 'order',
|
|
92
|
+
url: 'https://example.com/hook',
|
|
93
|
+
next: 'next_token',
|
|
94
|
+
previous: 'prev_token'
|
|
95
|
+
},
|
|
96
|
+
return_type: 'GetWebhooksResponse'
|
|
97
|
+
)).and_return([:list, 200, {}])
|
|
98
|
+
|
|
99
|
+
data = api_instance.get_webhooks(
|
|
100
|
+
limit: 25,
|
|
101
|
+
search: 'order',
|
|
102
|
+
url: 'https://example.com/hook',
|
|
103
|
+
_next: 'next_token',
|
|
104
|
+
previous: 'prev_token'
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
expect(data).to eq(:list)
|
|
100
108
|
end
|
|
101
109
|
end
|
|
102
110
|
|
|
103
|
-
#
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
111
|
+
describe '#test_webhook_with_http_info' do
|
|
112
|
+
it 'raises when id is missing' do
|
|
113
|
+
expect do
|
|
114
|
+
api_instance.test_webhook_with_http_info(nil)
|
|
115
|
+
end.to raise_error(ArgumentError, /Missing the required parameter 'id'/)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
it 'sends POST request to test endpoint' do
|
|
119
|
+
expect(api_client).to receive(:call_api).with(:POST, '/webhooks/whk_123/test', hash_including(
|
|
120
|
+
operation: :'WebhooksApi.test_webhook',
|
|
121
|
+
return_type: 'WebhookResponse'
|
|
122
|
+
)).and_return([:tested, 200, {}])
|
|
123
|
+
|
|
124
|
+
data = api_instance.test_webhook('whk_123')
|
|
125
|
+
expect(data).to eq(:tested)
|
|
115
126
|
end
|
|
116
127
|
end
|
|
117
128
|
|
|
129
|
+
describe '#update_webhook_with_http_info' do
|
|
130
|
+
it 'raises when webhook_update_request is missing' do
|
|
131
|
+
expect do
|
|
132
|
+
api_instance.update_webhook_with_http_info('whk_123', nil)
|
|
133
|
+
end.to raise_error(ArgumentError, /Missing the required parameter 'webhook_update_request'/)
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
it 'sends PUT request with serialized payload' do
|
|
137
|
+
payload = { url: 'https://example.com/new-hook', disabled: false }
|
|
138
|
+
|
|
139
|
+
expect(api_client).to receive(:call_api).with(:PUT, '/webhooks/whk_123', hash_including(
|
|
140
|
+
operation: :'WebhooksApi.update_webhook',
|
|
141
|
+
body: payload.to_json,
|
|
142
|
+
return_type: 'WebhookResponse'
|
|
143
|
+
)).and_return([:updated, 200, {}])
|
|
144
|
+
|
|
145
|
+
data = api_instance.update_webhook('whk_123', payload)
|
|
146
|
+
expect(data).to eq(:updated)
|
|
147
|
+
end
|
|
148
|
+
end
|
|
118
149
|
end
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'tempfile'
|
|
3
|
+
|
|
4
|
+
RSpec.describe DigitalFemsa::ApiClient do
|
|
5
|
+
RequestOptionsStub = Struct.new(:params_encoder, :timeout)
|
|
6
|
+
RequestStub = Struct.new(:headers, :body, :params, :options, :requested_url) do
|
|
7
|
+
def url(value)
|
|
8
|
+
self.requested_url = value
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
let(:config) { DigitalFemsa::Configuration.new }
|
|
13
|
+
let(:api_client) { described_class.new(config) }
|
|
14
|
+
|
|
15
|
+
describe '#initialize' do
|
|
16
|
+
it 'sets default headers' do
|
|
17
|
+
expect(api_client.default_headers['Content-Type']).to eq('application/json')
|
|
18
|
+
expect(api_client.default_headers['User-Agent']).to include('RubyBindings')
|
|
19
|
+
expect(api_client.default_headers['Spin-Client-User-Agent']).to include('sdk_version=')
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
describe '#json_mime?' do
|
|
24
|
+
it 'returns true for json mime types and wildcard' do
|
|
25
|
+
expect(api_client.json_mime?('application/json')).to be(true)
|
|
26
|
+
expect(api_client.json_mime?('application/json; charset=UTF-8')).to be(true)
|
|
27
|
+
expect(api_client.json_mime?('*/*')).to be(true)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it 'returns false for non-json mime types' do
|
|
31
|
+
expect(api_client.json_mime?('text/plain')).to be(false)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
describe '#select_header_accept' do
|
|
36
|
+
it 'returns nil when accepts are empty' do
|
|
37
|
+
expect(api_client.select_header_accept([])).to be_nil
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it 'prefers json accept when present' do
|
|
41
|
+
expect(api_client.select_header_accept(%w[text/plain application/json])).to eq('application/json')
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it 'joins values when json is not present' do
|
|
45
|
+
expect(api_client.select_header_accept(%w[text/plain text/html])).to eq('text/plain,text/html')
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
describe '#select_header_content_type' do
|
|
50
|
+
it 'returns nil when content types are empty' do
|
|
51
|
+
expect(api_client.select_header_content_type([])).to be_nil
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it 'prefers json content type when present' do
|
|
55
|
+
expect(api_client.select_header_content_type(%w[text/plain application/json])).to eq('application/json')
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it 'returns the first content type when json is not present' do
|
|
59
|
+
expect(api_client.select_header_content_type(%w[text/plain text/html])).to eq('text/plain')
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
describe '#build_request_body' do
|
|
64
|
+
it 'encodes urlencoded form body' do
|
|
65
|
+
result = api_client.build_request_body(
|
|
66
|
+
{ 'Content-Type' => 'application/x-www-form-urlencoded' },
|
|
67
|
+
{ 'a' => '1', 'b' => '2' },
|
|
68
|
+
nil
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
expect(result).to eq('a=1&b=2')
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
it 'builds multipart form body preserving arrays and nil values' do
|
|
75
|
+
Tempfile.create('upload') do |file|
|
|
76
|
+
file.write('content')
|
|
77
|
+
file.flush
|
|
78
|
+
|
|
79
|
+
result = api_client.build_request_body(
|
|
80
|
+
{ 'Content-Type' => 'multipart/form-data' },
|
|
81
|
+
{ file: file, amount: 100, tags: %w[a b], optional: nil },
|
|
82
|
+
nil
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
expect(result[:file]).to be_a(Faraday::FilePart)
|
|
86
|
+
expect(result[:amount]).to eq('100')
|
|
87
|
+
expect(result[:tags]).to eq(%w[a b])
|
|
88
|
+
expect(result[:optional]).to be_nil
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
it 'serializes hash body as json' do
|
|
93
|
+
result = api_client.build_request_body(
|
|
94
|
+
{ 'Content-Type' => 'application/json' },
|
|
95
|
+
{},
|
|
96
|
+
{ order: 'ord_123' }
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
expect(result).to eq('{"order":"ord_123"}')
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
it 'returns body as-is when already string' do
|
|
103
|
+
result = api_client.build_request_body(
|
|
104
|
+
{ 'Content-Type' => 'application/json' },
|
|
105
|
+
{},
|
|
106
|
+
'{"raw":true}'
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
expect(result).to eq('{"raw":true}')
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
describe '#build_request' do
|
|
114
|
+
it 'builds request with auth, query params, body and url' do
|
|
115
|
+
config.access_token = 'token-123'
|
|
116
|
+
config.timeout = 45
|
|
117
|
+
|
|
118
|
+
request = RequestStub.new(nil, nil, nil, RequestOptionsStub.new(nil, nil), nil)
|
|
119
|
+
|
|
120
|
+
api_client.build_request(
|
|
121
|
+
:post,
|
|
122
|
+
'charges',
|
|
123
|
+
request,
|
|
124
|
+
header_params: { 'Content-Type' => 'application/json' },
|
|
125
|
+
query_params: { limit: 10 },
|
|
126
|
+
form_params: {},
|
|
127
|
+
body: { amount: 1000 },
|
|
128
|
+
auth_names: ['bearerAuth']
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
expect(request.headers['Authorization']).to eq('Bearer token-123')
|
|
132
|
+
expect(request.params).to eq(limit: 10)
|
|
133
|
+
expect(request.body).to eq('{"amount":1000}')
|
|
134
|
+
expect(request.requested_url).to eq('https://api.digitalfemsa.io/charges')
|
|
135
|
+
expect(request.options.timeout).to eq(45)
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
describe '#update_params_for_auth!' do
|
|
140
|
+
it 'supports query auth settings' do
|
|
141
|
+
allow(config).to receive(:auth_settings).and_return(
|
|
142
|
+
'queryAuth' => {
|
|
143
|
+
in: 'query',
|
|
144
|
+
key: 'api_key',
|
|
145
|
+
value: 'secret'
|
|
146
|
+
}
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
headers = {}
|
|
150
|
+
query = {}
|
|
151
|
+
|
|
152
|
+
api_client.update_params_for_auth!(headers, query, ['queryAuth'])
|
|
153
|
+
|
|
154
|
+
expect(query['api_key']).to eq('secret')
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
it 'raises error for unsupported auth location' do
|
|
158
|
+
allow(config).to receive(:auth_settings).and_return(
|
|
159
|
+
'badAuth' => {
|
|
160
|
+
in: 'cookie',
|
|
161
|
+
key: 'session',
|
|
162
|
+
value: 'abc'
|
|
163
|
+
}
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
expect do
|
|
167
|
+
api_client.update_params_for_auth!({}, {}, ['badAuth'])
|
|
168
|
+
end.to raise_error(ArgumentError, /Authentication token must be in `query` or `header`/)
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
describe '#sanitize_filename' do
|
|
173
|
+
it 'removes directory traversal from filename' do
|
|
174
|
+
expect(api_client.sanitize_filename('../../tmp/file.txt')).to eq('file.txt')
|
|
175
|
+
expect(api_client.sanitize_filename('C:\\tmp\\file.txt')).to eq('file.txt')
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
describe '#build_collection_param' do
|
|
180
|
+
it 'supports csv and multi formats' do
|
|
181
|
+
expect(api_client.build_collection_param(%w[a b], :csv)).to eq('a,b')
|
|
182
|
+
expect(api_client.build_collection_param(%w[a b], :multi)).to eq(%w[a b])
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
it 'raises for unknown collection format' do
|
|
186
|
+
expect do
|
|
187
|
+
api_client.build_collection_param(%w[a b], :unknown)
|
|
188
|
+
end.to raise_error(RuntimeError, /unknown collection format/)
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
describe '#call_api' do
|
|
193
|
+
let(:opts) do
|
|
194
|
+
{
|
|
195
|
+
header_params: { 'Content-Type' => 'application/json' },
|
|
196
|
+
query_params: {},
|
|
197
|
+
form_params: {},
|
|
198
|
+
auth_names: []
|
|
199
|
+
}
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
it 'raises ApiError on timeout' do
|
|
203
|
+
allow(api_client).to receive(:connection).and_raise(Faraday::TimeoutError)
|
|
204
|
+
|
|
205
|
+
expect do
|
|
206
|
+
api_client.call_api(:get, '/charges', opts)
|
|
207
|
+
end.to raise_error(DigitalFemsa::ApiError, /Connection timed out/)
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
it 'raises ApiError on connection failed' do
|
|
211
|
+
allow(api_client).to receive(:connection).and_raise(Faraday::ConnectionFailed)
|
|
212
|
+
|
|
213
|
+
expect do
|
|
214
|
+
api_client.call_api(:get, '/charges', opts)
|
|
215
|
+
end.to raise_error(DigitalFemsa::ApiError, /Connection failed/)
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
it 'raises ApiError for non-successful responses' do
|
|
219
|
+
response = instance_double(
|
|
220
|
+
'FaradayResponse',
|
|
221
|
+
success?: false,
|
|
222
|
+
status: 401,
|
|
223
|
+
headers: { 'Content-Type' => 'application/json' },
|
|
224
|
+
body: '{"error":"unauthorized"}',
|
|
225
|
+
reason_phrase: 'Unauthorized'
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
connection = instance_double('FaradayConnection')
|
|
229
|
+
allow(connection).to receive(:get).and_yield(double('request')).and_return(response)
|
|
230
|
+
allow(api_client).to receive(:connection).and_return(connection)
|
|
231
|
+
allow(api_client).to receive(:build_request)
|
|
232
|
+
|
|
233
|
+
expect do
|
|
234
|
+
api_client.call_api(:get, '/charges', opts)
|
|
235
|
+
end.to raise_error(DigitalFemsa::ApiError) { |error| expect(error.code).to eq(401) }
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
it 'returns status and headers on successful responses' do
|
|
239
|
+
response = instance_double(
|
|
240
|
+
'FaradayResponse',
|
|
241
|
+
success?: true,
|
|
242
|
+
status: 200,
|
|
243
|
+
headers: { 'X-Request-Id' => 'req_123' },
|
|
244
|
+
body: '{"ok":true}'
|
|
245
|
+
)
|
|
246
|
+
|
|
247
|
+
connection = instance_double('FaradayConnection')
|
|
248
|
+
allow(connection).to receive(:get).and_yield(double('request')).and_return(response)
|
|
249
|
+
allow(api_client).to receive(:connection).and_return(connection)
|
|
250
|
+
allow(api_client).to receive(:build_request)
|
|
251
|
+
|
|
252
|
+
data, status, headers = api_client.call_api(:get, '/charges', opts)
|
|
253
|
+
|
|
254
|
+
expect(data).to be_nil
|
|
255
|
+
expect(status).to eq(200)
|
|
256
|
+
expect(headers).to eq('X-Request-Id' => 'req_123')
|
|
257
|
+
end
|
|
258
|
+
end
|
|
259
|
+
end
|