digital_femsa 1.0.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/Makefile +14 -0
- data/README.md +28 -33
- data/VERSION +1 -1
- data/config-ruby.json +1 -1
- data/digital_femsa.gemspec +1 -1
- data/docs/ApiKeyCreateResponse.md +1 -1
- data/docs/ApiKeyRequest.md +2 -2
- data/docs/ApiKeyResponseOnDelete.md +2 -2
- data/docs/ApiKeysApi.md +10 -10
- data/docs/BalanceResponse.md +8 -8
- data/docs/BalancesApi.md +1 -1
- data/docs/ChargeOrderResponse.md +1 -1
- data/docs/ChargeOrderResponseChannel.md +24 -0
- data/docs/ChargeRequest.md +1 -1
- data/docs/ChargeRequestPaymentMethod.md +3 -3
- data/docs/ChargeResponse.md +9 -7
- data/docs/ChargeResponseChannel.md +3 -3
- data/docs/ChargeResponseRefundsData.md +5 -1
- data/docs/ChargesApi.md +16 -12
- data/docs/ChargesDataResponse.md +9 -7
- data/docs/Checkout.md +17 -15
- data/docs/CheckoutOrderTemplate.md +3 -3
- data/docs/CheckoutResponse.md +1 -1
- data/docs/CreateCustomerFiscalEntitiesResponse.md +2 -2
- data/docs/Customer.md +13 -19
- data/docs/CustomerAddress.md +2 -2
- data/docs/CustomerFiscalEntitiesDataResponse.md +2 -2
- data/docs/CustomerFiscalEntitiesRequest.md +3 -3
- data/docs/CustomerInfo.md +4 -4
- data/docs/CustomerPaymentMethodRequest.md +1 -1
- data/docs/CustomerResponse.md +17 -21
- data/docs/CustomerShippingContactsResponse.md +5 -5
- data/docs/CustomersApi.md +15 -15
- data/docs/CustomersResponse.md +1 -1
- data/docs/DeleteApiKeysResponse.md +1 -1
- data/docs/DiscountsApi.md +9 -9
- data/docs/EventsApi.md +2 -2
- data/docs/EventsResendResponse.md +1 -1
- data/docs/GetChargesResponse.md +4 -4
- data/docs/GetTransactionsResponse.md +1 -1
- data/docs/LogsApi.md +1 -1
- data/docs/OrderFiscalEntityRequest.md +4 -4
- data/docs/OrderRefundRequest.md +7 -5
- data/docs/OrderRequest.md +17 -19
- data/docs/OrderResponse.md +37 -35
- data/docs/OrderResponseChannel.md +24 -0
- data/docs/OrderResponseShippingContact.md +4 -4
- data/docs/OrderUpdateFiscalEntityRequest.md +1 -1
- data/docs/OrderUpdateRequest.md +19 -15
- data/docs/OrdersApi.md +16 -16
- data/docs/PaymentLinkApi.md +12 -82
- data/docs/PaymentMethodCash.md +4 -4
- data/docs/PaymentMethodCashRequest.md +2 -2
- data/docs/PaymentMethodsApi.md +5 -5
- data/docs/Product.md +10 -12
- data/docs/ProductDataResponse.md +9 -11
- data/docs/ProductOrderResponse.md +9 -11
- data/docs/ProductsApi.md +7 -7
- data/docs/ShippingContactsApi.md +9 -9
- data/docs/ShippingOrderResponse.md +5 -3
- data/docs/ShippingRequest.md +2 -0
- data/docs/ShippingsApi.md +7 -7
- data/docs/TaxesApi.md +7 -7
- data/docs/TransactionResponse.md +20 -14
- data/docs/TransactionsApi.md +6 -6
- data/docs/TransfersApi.md +10 -10
- data/docs/UpdateCustomer.md +17 -21
- data/docs/UpdateCustomerFiscalEntitiesResponse.md +2 -2
- data/docs/UpdateOrderTaxRequest.md +2 -2
- data/docs/UpdateProduct.md +7 -9
- data/docs/WebhookKeysApi.md +18 -14
- data/docs/WebhooksApi.md +28 -22
- data/lib/digital_femsa/api/api_keys_api.rb +8 -8
- data/lib/digital_femsa/api/balances_api.rb +2 -2
- data/lib/digital_femsa/api/charges_api.rb +13 -9
- data/lib/digital_femsa/api/customers_api.rb +12 -12
- data/lib/digital_femsa/api/discounts_api.rb +12 -12
- data/lib/digital_femsa/api/events_api.rb +4 -4
- data/lib/digital_femsa/api/logs_api.rb +2 -2
- data/lib/digital_femsa/api/orders_api.rb +20 -20
- data/lib/digital_femsa/api/payment_link_api.rb +10 -86
- data/lib/digital_femsa/api/payment_methods_api.rb +8 -8
- data/lib/digital_femsa/api/products_api.rb +10 -10
- data/lib/digital_femsa/api/shipping_contacts_api.rb +8 -8
- data/lib/digital_femsa/api/shippings_api.rb +10 -10
- data/lib/digital_femsa/api/taxes_api.rb +10 -10
- data/lib/digital_femsa/api/transactions_api.rb +6 -6
- data/lib/digital_femsa/api/transfers_api.rb +8 -8
- data/lib/digital_femsa/api/webhook_keys_api.rb +14 -10
- data/lib/digital_femsa/api/webhooks_api.rb +23 -16
- data/lib/digital_femsa/api_client.rb +9 -5
- data/lib/digital_femsa/models/api_key_create_response.rb +1 -1
- data/lib/digital_femsa/models/api_key_request.rb +36 -1
- data/lib/digital_femsa/models/balance_response.rb +9 -9
- data/lib/digital_femsa/models/charge_order_response.rb +1 -1
- data/lib/digital_femsa/models/{order_next_action_response.rb → charge_order_response_channel.rb} +34 -18
- data/lib/digital_femsa/models/charge_request_payment_method.rb +3 -2
- data/lib/digital_femsa/models/charge_response.rb +15 -4
- data/lib/digital_femsa/models/charge_response_refunds_data.rb +23 -4
- data/lib/digital_femsa/models/charge_update_request.rb +1 -1
- data/lib/digital_femsa/models/charges_data_response.rb +15 -4
- data/lib/digital_femsa/models/checkout.rb +97 -81
- data/lib/digital_femsa/models/checkout_order_template.rb +4 -4
- data/lib/digital_femsa/models/checkout_order_template_customer_info.rb +1 -1
- data/lib/digital_femsa/models/checkout_request.rb +1 -1
- data/lib/digital_femsa/models/checkout_response.rb +1 -1
- data/lib/digital_femsa/models/create_customer_fiscal_entities_response.rb +10 -10
- data/lib/digital_femsa/models/customer.rb +57 -95
- data/lib/digital_femsa/models/customer_address.rb +7 -0
- data/lib/digital_femsa/models/customer_fiscal_entities_data_response.rb +10 -10
- data/lib/digital_femsa/models/customer_fiscal_entities_request.rb +13 -13
- data/lib/digital_femsa/models/customer_info.rb +13 -20
- data/lib/digital_femsa/models/customer_payment_method_request.rb +2 -2
- data/lib/digital_femsa/models/customer_payment_sources_inner.rb +104 -0
- data/lib/digital_femsa/models/customer_response.rb +122 -113
- data/lib/digital_femsa/models/customer_shipping_contacts_response.rb +2 -0
- data/lib/digital_femsa/models/customers_response.rb +1 -0
- data/lib/digital_femsa/models/events_resend_response.rb +1 -1
- data/lib/digital_femsa/models/get_charges_response.rb +21 -21
- data/lib/digital_femsa/models/get_transactions_response.rb +1 -1
- data/lib/digital_femsa/models/log_response.rb +1 -1
- data/lib/digital_femsa/models/logs_response.rb +1 -1
- data/lib/digital_femsa/models/order_fiscal_entity_response.rb +1 -1
- data/lib/digital_femsa/models/order_refund_request.rb +59 -11
- data/lib/digital_femsa/models/order_request.rb +69 -79
- data/lib/digital_femsa/models/order_response.rb +187 -119
- data/lib/digital_femsa/models/{order_next_action_response_redirect_to_url.rb → order_response_channel.rb} +35 -19
- data/lib/digital_femsa/models/order_response_charges.rb +1 -1
- data/lib/digital_femsa/models/order_response_checkout.rb +1 -0
- data/lib/digital_femsa/models/order_response_customer_info.rb +1 -0
- data/lib/digital_femsa/models/order_response_shipping_contact.rb +3 -0
- data/lib/digital_femsa/models/order_update_fiscal_entity_request.rb +1 -1
- data/lib/digital_femsa/models/order_update_request.rb +106 -65
- data/lib/digital_femsa/models/payment_method_cash.rb +1 -1
- data/lib/digital_femsa/models/payment_method_cash_request.rb +2 -1
- data/lib/digital_femsa/models/product.rb +103 -95
- data/lib/digital_femsa/models/product_data_response.rb +103 -95
- data/lib/digital_femsa/models/product_order_response.rb +103 -95
- data/lib/digital_femsa/models/shipping_order_response.rb +11 -1
- data/lib/digital_femsa/models/shipping_request.rb +12 -1
- data/lib/digital_femsa/models/transaction_response.rb +172 -99
- data/lib/digital_femsa/models/transfers_response.rb +1 -1
- data/lib/digital_femsa/models/transfers_response_destination.rb +312 -0
- data/lib/digital_femsa/models/update_customer.rb +42 -85
- data/lib/digital_femsa/models/update_customer_fiscal_entities_response.rb +10 -10
- data/lib/digital_femsa/models/update_order_discount_lines_request.rb +34 -0
- data/lib/digital_femsa/models/update_order_tax_request.rb +2 -2
- data/lib/digital_femsa/models/update_payment_methods_amount.rb +105 -0
- data/lib/digital_femsa/models/update_payment_methods_expires_at.rb +105 -0
- data/lib/digital_femsa/models/update_product.rb +85 -58
- data/lib/digital_femsa/models/webhook_key_delete_response.rb +1 -1
- data/lib/digital_femsa/models/webhook_key_request.rb +1 -0
- data/lib/digital_femsa/models/webhook_key_response.rb +1 -1
- data/lib/digital_femsa/models/webhook_request.rb +248 -9
- data/lib/digital_femsa/models/webhook_response.rb +1 -1
- data/lib/digital_femsa/models/webhook_update_request.rb +1 -1
- data/lib/digital_femsa/version.rb +1 -1
- data/lib/digital_femsa.rb +2 -6
- 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
- data/templates/ruby/api_client.mustache +8 -4
- metadata +40 -37
- data/docs/CustomerAntifraudInfo.md +0 -20
- data/docs/CustomerAntifraudInfoResponse.md +0 -20
- data/docs/OrderNextActionResponse.md +0 -20
- data/docs/OrderNextActionResponseRedirectToUrl.md +0 -20
- data/docs/SmsCheckoutRequest.md +0 -18
- data/docs/UpdateCustomerAntifraudInfo.md +0 -20
|
@@ -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
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
RSpec.describe 'Generated models coverage smoke tests' do
|
|
4
|
+
model_classes = DigitalFemsa.constants.filter_map do |const_name|
|
|
5
|
+
constant = DigitalFemsa.const_get(const_name)
|
|
6
|
+
next unless constant.is_a?(Class)
|
|
7
|
+
next unless constant.respond_to?(:attribute_map)
|
|
8
|
+
next unless constant.respond_to?(:openapi_types)
|
|
9
|
+
next unless constant.respond_to?(:build_from_hash)
|
|
10
|
+
next unless constant.respond_to?(:_deserialize)
|
|
11
|
+
|
|
12
|
+
constant
|
|
13
|
+
rescue NameError
|
|
14
|
+
nil
|
|
15
|
+
end.sort_by(&:name)
|
|
16
|
+
|
|
17
|
+
sample_value_for = lambda do |type, attr_name: nil, depth: 0|
|
|
18
|
+
return nil if depth > 2
|
|
19
|
+
|
|
20
|
+
type_name = type.to_s
|
|
21
|
+
|
|
22
|
+
return 'https://example.com/webhook' if attr_name.to_s.include?('url')
|
|
23
|
+
|
|
24
|
+
case type_name
|
|
25
|
+
when 'String'
|
|
26
|
+
attr_name.to_s.include?('email') ? 'test@example.com' : 'sample'
|
|
27
|
+
when 'Integer'
|
|
28
|
+
1
|
|
29
|
+
when 'Float'
|
|
30
|
+
1.5
|
|
31
|
+
when 'Boolean'
|
|
32
|
+
true
|
|
33
|
+
when 'Date'
|
|
34
|
+
'2024-01-01'
|
|
35
|
+
when 'Time'
|
|
36
|
+
'2024-01-01T00:00:00Z'
|
|
37
|
+
when 'Object'
|
|
38
|
+
{ 'key' => 'value' }
|
|
39
|
+
when /\AArray<(?<inner_type>.+)>\z/
|
|
40
|
+
[sample_value_for.call(Regexp.last_match[:inner_type], attr_name: attr_name, depth: depth + 1)]
|
|
41
|
+
when /\AHash<(?<k_type>.+?), (?<v_type>.+)>\z/
|
|
42
|
+
{
|
|
43
|
+
sample_value_for.call(Regexp.last_match[:k_type], depth: depth + 1) =>
|
|
44
|
+
sample_value_for.call(Regexp.last_match[:v_type], depth: depth + 1)
|
|
45
|
+
}
|
|
46
|
+
else
|
|
47
|
+
{}
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
candidate_values_for = lambda do |type, attr_name|
|
|
52
|
+
type_name = type.to_s
|
|
53
|
+
attr_name_str = attr_name.to_s
|
|
54
|
+
|
|
55
|
+
candidates = [sample_value_for.call(type, attr_name: attr_name)]
|
|
56
|
+
|
|
57
|
+
if type_name == 'String'
|
|
58
|
+
candidates.concat(
|
|
59
|
+
%w[private public MXN USD es en active inactive pending completed card cash transfer bank_transfer charge order customer webhook]
|
|
60
|
+
)
|
|
61
|
+
candidates << 'https://example.com/webhook' if attr_name_str.include?('url')
|
|
62
|
+
candidates << 'test@example.com' if attr_name_str.include?('email')
|
|
63
|
+
candidates << 'mx' if attr_name_str.include?('country')
|
|
64
|
+
elsif type_name == 'Integer'
|
|
65
|
+
candidates.concat([0, 20, 100, 1_700_000_000])
|
|
66
|
+
elsif type_name == 'Float'
|
|
67
|
+
candidates.concat([0.0, 2.5, 10.0])
|
|
68
|
+
elsif type_name == 'Boolean'
|
|
69
|
+
candidates << false
|
|
70
|
+
elsif type_name.match?(/\AArray<.+>\z/)
|
|
71
|
+
candidates << []
|
|
72
|
+
elsif type_name.match?(/\AHash<.+>\z/)
|
|
73
|
+
candidates << {}
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
candidates.compact.uniq
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
attributes_for = lambda do |klass|
|
|
80
|
+
klass.openapi_types.each_with_object({}) do |(attr, type), attrs|
|
|
81
|
+
assigned = false
|
|
82
|
+
|
|
83
|
+
candidate_values_for.call(type, attr).each do |value|
|
|
84
|
+
begin
|
|
85
|
+
klass.new(attrs.merge(attr => value))
|
|
86
|
+
attrs[attr] = value
|
|
87
|
+
assigned = true
|
|
88
|
+
break
|
|
89
|
+
rescue StandardError
|
|
90
|
+
next
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
next if assigned
|
|
95
|
+
|
|
96
|
+
begin
|
|
97
|
+
klass.new(attrs.merge(attr => nil))
|
|
98
|
+
attrs[attr] = nil
|
|
99
|
+
rescue StandardError
|
|
100
|
+
# Skip attributes that require highly specific values in custom setters.
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
model_classes.each do |klass|
|
|
106
|
+
it "smoke-tests #{klass.name}" do
|
|
107
|
+
attrs = attributes_for.call(klass)
|
|
108
|
+
|
|
109
|
+
begin
|
|
110
|
+
instance = klass.new(attrs)
|
|
111
|
+
another_instance = klass.new(attrs)
|
|
112
|
+
rescue StandardError => e
|
|
113
|
+
skip("Skipped strict model initialization: #{e.message}")
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
expect(klass.acceptable_attributes).to be_a(Array)
|
|
117
|
+
expect(klass.openapi_nullable).to be_a(Set)
|
|
118
|
+
|
|
119
|
+
expect { klass.new('invalid') }.to raise_error(ArgumentError)
|
|
120
|
+
expect { klass.new('__invalid_attribute__' => 'x') }.to raise_error(ArgumentError)
|
|
121
|
+
|
|
122
|
+
expect(instance.send(:==, another_instance)).to be(true)
|
|
123
|
+
expect(instance.send(:eql?, another_instance)).to be(true)
|
|
124
|
+
expect(instance.send(:hash)).to be_a(Integer)
|
|
125
|
+
expect { instance.send(:list_invalid_properties) }.not_to raise_error
|
|
126
|
+
expect { instance.send(:valid?) }.not_to raise_error
|
|
127
|
+
|
|
128
|
+
serialized_hash = instance.send(:to_hash)
|
|
129
|
+
expect(serialized_hash).to be_a(Hash)
|
|
130
|
+
expect(instance.send(:to_body)).to eq(serialized_hash)
|
|
131
|
+
expect(instance.send(:to_s)).to be_a(String)
|
|
132
|
+
expect(instance.send(:_to_hash, [1, nil, 2])).to eq([1, 2])
|
|
133
|
+
expect(instance.send(:_to_hash, { 'a' => 1 })).to eq('a' => 1)
|
|
134
|
+
|
|
135
|
+
rebuilt = klass.build_from_hash(serialized_hash) rescue nil
|
|
136
|
+
expect(rebuilt).to be_a(klass).or be_nil
|
|
137
|
+
|
|
138
|
+
expect(klass._deserialize('String', 1)).to eq('1')
|
|
139
|
+
expect(klass._deserialize('Integer', '1')).to eq(1)
|
|
140
|
+
expect(klass._deserialize('Float', '1.2')).to eq(1.2)
|
|
141
|
+
expect(klass._deserialize('Boolean', 'true')).to be(true)
|
|
142
|
+
expect(klass._deserialize('Boolean', 'false')).to be(false)
|
|
143
|
+
expect(klass._deserialize('Object', { 'a' => 1 })).to eq('a' => 1)
|
|
144
|
+
expect(klass._deserialize('Array<String>', [1, 2])).to eq(%w[1 2])
|
|
145
|
+
expect(klass._deserialize('Hash<String, Integer>', { 'a' => '1' })).to eq('a' => 1)
|
|
146
|
+
expect(klass._deserialize('Date', '2024-01-01')).to be_a(Date)
|
|
147
|
+
expect(klass._deserialize('Time', '2024-01-01T00:00:00Z')).to be_a(Time)
|
|
148
|
+
expect { klass._deserialize(klass.name.split('::').last, {}) rescue nil }.not_to raise_error
|
|
149
|
+
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
end
|