charging-client 0.0.2
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 +7 -0
- data/.coveralls.yml +1 -0
- data/.gitignore +21 -0
- data/.rspec +2 -0
- data/.travis.yml +7 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +81 -0
- data/LICENSE +191 -0
- data/README.rdoc +228 -0
- data/Rakefile +16 -0
- data/charging-client.gemspec +40 -0
- data/lib/charging.rb +36 -0
- data/lib/charging/base.rb +109 -0
- data/lib/charging/charge_account.rb +169 -0
- data/lib/charging/collection.rb +29 -0
- data/lib/charging/configuration.rb +28 -0
- data/lib/charging/domain.rb +164 -0
- data/lib/charging/helpers.rb +37 -0
- data/lib/charging/http.rb +96 -0
- data/lib/charging/invoice.rb +191 -0
- data/lib/charging/service_account.rb +50 -0
- data/lib/charging/version.rb +4 -0
- data/spec/charging/charge_account_collection_spec.rb +95 -0
- data/spec/charging/charge_account_spec.rb +289 -0
- data/spec/charging/configuration_spec.rb +61 -0
- data/spec/charging/domain_collection_spec.rb +101 -0
- data/spec/charging/domain_spec.rb +386 -0
- data/spec/charging/helpers_spec.rb +59 -0
- data/spec/charging/http_last_response_error_spec.rb +18 -0
- data/spec/charging/http_spec.rb +184 -0
- data/spec/charging/invoice_spec.rb +442 -0
- data/spec/charging/service_account_spec.rb +71 -0
- data/spec/charging_spec.rb +42 -0
- data/spec/fixtures/new_user.json +8 -0
- data/spec/fixtures/recreate_user.json +9 -0
- data/spec/spec_helper.rb +69 -0
- data/spec/support/factory.rb +32 -0
- data/spec/support/faker.rb +56 -0
- metadata +283 -0
@@ -0,0 +1,184 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe Charging::Http do
|
5
|
+
let(:mock_response) { double('restclient http response') }
|
6
|
+
let(:configuration) { Charging.configuration }
|
7
|
+
|
8
|
+
describe '.basic_credential_for' do
|
9
|
+
it 'should accept only user' do
|
10
|
+
expect(described_class.basic_credential_for('user')).to eql 'Basic dXNlcg=='
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should accept user and password' do
|
14
|
+
expect(described_class.basic_credential_for('user', 'pass')).to eql 'Basic dXNlcjpwYXNz'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '.request_to_api' do
|
19
|
+
%w[post put patch].each do |method|
|
20
|
+
context 'with body as json' do
|
21
|
+
it "should use RestClient.#{method} with the supplied params and common options" do
|
22
|
+
expect(RestClient).to receive(method).with(
|
23
|
+
"#{configuration.url}/foo",
|
24
|
+
'{"hello":"world"}',
|
25
|
+
params: {},
|
26
|
+
authorization: 'Basic OnNvbWUtYXBwLXRva2Vu',
|
27
|
+
content_type: :json,
|
28
|
+
accept: :json,
|
29
|
+
user_agent: configuration.user_agent
|
30
|
+
).and_return(mock_response)
|
31
|
+
|
32
|
+
described_class.request_to_api(method, '/foo', {}, 'some-app-token', {hello: 'world'})
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context 'with body as string' do
|
37
|
+
it 'should use RestClient.post with the supplied params and common options' do
|
38
|
+
expect(RestClient).to receive(method).with(
|
39
|
+
"#{configuration.url}/foo",
|
40
|
+
'{"hello":"world"}',
|
41
|
+
params: {},
|
42
|
+
authorization: 'Basic OnNvbWUtYXBwLXRva2Vu',
|
43
|
+
content_type: :json,
|
44
|
+
accept: :json,
|
45
|
+
user_agent: configuration.user_agent
|
46
|
+
).and_return(mock_response)
|
47
|
+
|
48
|
+
described_class.request_to_api(method, '/foo', {}, 'some-app-token', '{"hello":"world"}')
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe ".delete" do
|
55
|
+
it 'should delegate to request_to_api' do
|
56
|
+
expect(Charging::Http).to receive(:request_to_api).with(
|
57
|
+
:delete,
|
58
|
+
'/foo',
|
59
|
+
{etag: 'etag'},
|
60
|
+
'some-app-token'
|
61
|
+
)
|
62
|
+
|
63
|
+
described_class.delete('/foo', 'some-app-token', 'etag')
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe ".get" do
|
68
|
+
it 'should delegate to request_to_api' do
|
69
|
+
expect(Charging::Http).to receive(:request_to_api).with(
|
70
|
+
:get,
|
71
|
+
'/foo',
|
72
|
+
{},
|
73
|
+
'some-app-token'
|
74
|
+
)
|
75
|
+
|
76
|
+
described_class.get('/foo', 'some-app-token')
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
%w[post].each do |method|
|
81
|
+
describe ".#{method}" do
|
82
|
+
it 'should delegate to request_to_api' do
|
83
|
+
expect(Charging::Http).to receive(:request_to_api).with(
|
84
|
+
method.to_sym,
|
85
|
+
'/foo',
|
86
|
+
{spam: 'eggs'},
|
87
|
+
'some-app-token',
|
88
|
+
'body'
|
89
|
+
)
|
90
|
+
|
91
|
+
described_class.send(method, '/foo', 'some-app-token', 'body', spam: 'eggs')
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
%w[put patch].each do |method|
|
97
|
+
describe ".#{method}" do
|
98
|
+
it 'should delegate to request_to_api' do
|
99
|
+
expect(Charging::Http).to receive(:request_to_api).with(
|
100
|
+
method.to_sym,
|
101
|
+
'/foo',
|
102
|
+
{etag: 'etag'},
|
103
|
+
'some-app-token',
|
104
|
+
'body'
|
105
|
+
)
|
106
|
+
|
107
|
+
described_class.send(method, '/foo', 'some-app-token', 'etag', 'body')
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
specify('.charging_path') do
|
113
|
+
expect(described_class.charging_path('/path')).to eql "#{configuration.url}/path"
|
114
|
+
end
|
115
|
+
|
116
|
+
describe '.common_params' do
|
117
|
+
context 'without etag' do
|
118
|
+
it 'should to return a hash with request headers' do
|
119
|
+
expect(described_class.common_params('token', nil)).to eql({
|
120
|
+
accept: :json,
|
121
|
+
authorization: 'Basic OnRva2Vu',
|
122
|
+
content_type: :json,
|
123
|
+
user_agent: configuration.user_agent
|
124
|
+
})
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
context 'with etag' do
|
129
|
+
it 'should to return a hash with request headers' do
|
130
|
+
expect(described_class.common_params('token', 'etag')).to eql({
|
131
|
+
accept: :json,
|
132
|
+
authorization: 'Basic OnRva2Vu',
|
133
|
+
content_type: :json,
|
134
|
+
user_agent: configuration.user_agent,
|
135
|
+
'If-Match' => 'etag'
|
136
|
+
})
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
describe '.encoded_body' do
|
142
|
+
context 'with hash body' do
|
143
|
+
it 'should convert to string in json format' do
|
144
|
+
expect(described_class.encoded_body({some: 'value'})).to eql('{"some":"value"}')
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
context 'with string body' do
|
149
|
+
it 'should repass the original body' do
|
150
|
+
expect(described_class.encoded_body('some text')).to eql('some text')
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
describe '.should_follow_redirect' do
|
156
|
+
context 'on success response code (200)' do
|
157
|
+
it 'should call return on response' do
|
158
|
+
response = double(code: 200).tap do |mock|
|
159
|
+
expect(mock).not_to receive(:follow_redirection)
|
160
|
+
expect(mock).to receive(:return!)
|
161
|
+
end
|
162
|
+
|
163
|
+
described_class.should_follow_redirect.call(response, nil, nil)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
{
|
168
|
+
301 => 'moved permanently',
|
169
|
+
302 => 'found',
|
170
|
+
307 => 'temporary redirect'
|
171
|
+
}.each do |status_code, status_message|
|
172
|
+
context "on #{status_message} response code (#{status_code})" do
|
173
|
+
it 'should call follow redirection on response' do
|
174
|
+
response = double(code: status_code).tap do |mock|
|
175
|
+
expect(mock).to receive(:follow_redirection)
|
176
|
+
expect(mock).not_to receive(:return!)
|
177
|
+
end
|
178
|
+
|
179
|
+
described_class.should_follow_redirect.call(response, nil, nil)
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
@@ -0,0 +1,442 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Charging::Invoice, :vcr do
|
6
|
+
let(:national_identifier) { Faker.cnpj_generator }
|
7
|
+
let(:domain) { create_domain(current_account, national_identifier) }
|
8
|
+
let(:charge_account) { create_charge_account(domain) }
|
9
|
+
let(:attributes) do
|
10
|
+
{
|
11
|
+
kind: 2,
|
12
|
+
amount: 123.45,
|
13
|
+
document_number: '000000000000001',
|
14
|
+
drawee: {
|
15
|
+
name: 'Nome do Sacado',
|
16
|
+
address: 'Rua do Carmo, 43',
|
17
|
+
city_state: 'Rio de Janeiro/RJ',
|
18
|
+
zipcode: '21345-999',
|
19
|
+
national_identifier: '37.818.380/0001-86'
|
20
|
+
},
|
21
|
+
due_date: '2020-12-31'
|
22
|
+
}
|
23
|
+
end
|
24
|
+
let(:invoice) { described_class.new(attributes, domain, charge_account).create! }
|
25
|
+
|
26
|
+
context 'for new instance' do
|
27
|
+
INVOICE_ATTRIBUTES = [
|
28
|
+
:kind, :amount, :document_number, :drawee, :due_date, :portfolio_code,
|
29
|
+
:charging_features, :supplier_name, :discount, :interest, :rebate,
|
30
|
+
:ticket, :protest_code, :protest_days, :instructions, :demonstrative,
|
31
|
+
:our_number
|
32
|
+
]
|
33
|
+
|
34
|
+
let(:response) { double(:response, code: 500) }
|
35
|
+
|
36
|
+
before do
|
37
|
+
VCR.use_cassette('Invoice/for new instance') do
|
38
|
+
attributes = Hash[*INVOICE_ATTRIBUTES.map {|attr| [attr, "#{attr} value"] }.flatten]
|
39
|
+
@domain = domain
|
40
|
+
@charge_account = charge_account
|
41
|
+
|
42
|
+
@new_invoice = described_class.new(attributes, @domain, @charge_account, response)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
subject { @new_invoice }
|
47
|
+
|
48
|
+
INVOICE_ATTRIBUTES.each do |attribute|
|
49
|
+
describe attribute do
|
50
|
+
subject { super().send(attribute) }
|
51
|
+
it { is_expected.to eq "#{attribute} value"}
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
[:uuid, :uri, :etag, :document_date, :paid].each do |attribute|
|
56
|
+
describe attribute do
|
57
|
+
subject { super().send(attribute) }
|
58
|
+
it { is_expected.to be_nil }
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe '#domain' do
|
63
|
+
subject { super().domain }
|
64
|
+
it { is_expected.to eq @domain }
|
65
|
+
end
|
66
|
+
|
67
|
+
describe '#charge_account' do
|
68
|
+
subject { super().charge_account }
|
69
|
+
it { is_expected.to eq @charge_account }
|
70
|
+
end
|
71
|
+
|
72
|
+
describe '#last_response' do
|
73
|
+
subject { super().last_response }
|
74
|
+
it { is_expected.to eq response }
|
75
|
+
end
|
76
|
+
|
77
|
+
describe '#errors' do
|
78
|
+
subject { super().errors }
|
79
|
+
it { is_expected.to eq [] }
|
80
|
+
end
|
81
|
+
|
82
|
+
specify('#persisted?') { expect(subject).to_not be_persisted }
|
83
|
+
specify('#deleted?') { expect(subject).to_not be_deleted }
|
84
|
+
|
85
|
+
describe '#attributes' do
|
86
|
+
subject { super().attributes }
|
87
|
+
it do
|
88
|
+
is_expected.to eq({
|
89
|
+
amount: 'amount value',
|
90
|
+
kind: 'kind value',
|
91
|
+
document_number: 'document_number value',
|
92
|
+
drawee: 'drawee value',
|
93
|
+
due_date: 'due_date value',
|
94
|
+
charging_features: 'charging_features value',
|
95
|
+
supplier_name: 'supplier_name value',
|
96
|
+
discount: 'discount value',
|
97
|
+
interest: 'interest value',
|
98
|
+
rebate: 'rebate value',
|
99
|
+
ticket: 'ticket value',
|
100
|
+
protest_code: 'protest_code value',
|
101
|
+
protest_days: 'protest_days value',
|
102
|
+
instructions: 'instructions value',
|
103
|
+
demonstrative: 'demonstrative value',
|
104
|
+
our_number: 'our_number value',
|
105
|
+
portfolio_code: 'portfolio_code value'
|
106
|
+
})
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
describe '#create!' do
|
112
|
+
it 'should require a domain and load errors' do
|
113
|
+
VCR.use_cassette('Invoice/try create an invoice with invalid domain') do
|
114
|
+
invoice = described_class.new(attributes, nil, charge_account)
|
115
|
+
|
116
|
+
expect(invoice.errors).to be_empty
|
117
|
+
|
118
|
+
expected_error = [StandardError, 'can not create without a domain']
|
119
|
+
expect { invoice.create! }.to raise_error(*expected_error)
|
120
|
+
|
121
|
+
expect(invoice.errors).to eq ['can not create without a domain']
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
it 'should require a charge account and load errors' do
|
126
|
+
VCR.use_cassette('Invoice/try create an invoice with invalid charge account') do
|
127
|
+
invoice = described_class.new(attributes, domain, nil)
|
128
|
+
|
129
|
+
expect(invoice.errors).to be_empty
|
130
|
+
|
131
|
+
expected_error = [StandardError, 'can not create wihtout a charge account']
|
132
|
+
expect { invoice.create! }.to raise_error(*expected_error)
|
133
|
+
|
134
|
+
expect(invoice.errors).to eq ['can not create wihtout a charge account']
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
context 'when everything is OK' do
|
139
|
+
before do
|
140
|
+
VCR.use_cassette('Invoice/creating an invoice') do
|
141
|
+
@charge_account = charge_account
|
142
|
+
@domain = @charge_account.domain
|
143
|
+
|
144
|
+
@invoice = described_class.new(attributes, domain, charge_account).create!
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
subject { @invoice }
|
149
|
+
|
150
|
+
[:uuid, :uri, :etag].each do |attribute|
|
151
|
+
describe attribute do
|
152
|
+
subject { super().send(attribute) }
|
153
|
+
it { is_expected.not_to be_nil }
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
it 'should be persisted' do
|
158
|
+
expect(subject).to be_persisted
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
describe '#billet_url' do
|
164
|
+
context 'for not persisted invoice' do
|
165
|
+
subject {
|
166
|
+
VCR.use_cassette('Invoice/check billet url for new invoice instance') do
|
167
|
+
described_class.new({}, domain, charge_account, nil)
|
168
|
+
end
|
169
|
+
}
|
170
|
+
|
171
|
+
describe '#billet_url' do
|
172
|
+
subject { super().billet_url }
|
173
|
+
it { is_expected.to be_nil }
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
context 'for a persisted invoice' do
|
178
|
+
it 'should be nil if something wrong' do
|
179
|
+
VCR.use_cassette('Invoice/try get billet url when something is wrong') do
|
180
|
+
@invoice = invoice
|
181
|
+
|
182
|
+
expect(Charging::Http)
|
183
|
+
.to receive(:get).with("/invoices/#{@invoice.uuid}/billet/", domain.token)
|
184
|
+
.and_return(double(:server_error, code: 500, body: 'generic error message'))
|
185
|
+
|
186
|
+
expect(@invoice.billet_url).to be_nil
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
it 'should get current billet url' do
|
191
|
+
VCR.use_cassette('Invoice/finding current billet url for invoice') do
|
192
|
+
@invoice = invoice
|
193
|
+
expected_url = %r{http://sandbox.charging.financeconnect.com.br/billets/#{@invoice.uuid}/\w+/}
|
194
|
+
expect(@invoice.billet_url).to match expected_url
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
describe '#pay!' do
|
201
|
+
context 'when something went wrong' do
|
202
|
+
it 'should load raise error' do
|
203
|
+
VCR.use_cassette('Invoice/paying an invoice and something is wrong') do
|
204
|
+
body = MultiJson.encode({
|
205
|
+
amount: invoice.amount,
|
206
|
+
date: Time.now.strftime('%Y-%m-%d')
|
207
|
+
})
|
208
|
+
|
209
|
+
expect(Charging::Http)
|
210
|
+
.to receive(:post).with("/invoices/#{invoice.uuid}/pay/", domain.token, body, etag: invoice.etag)
|
211
|
+
.and_return(double(:response, code: 500))
|
212
|
+
|
213
|
+
expected_error = [Charging::Http::LastResponseError]
|
214
|
+
|
215
|
+
expect { invoice.pay! }.to raise_error(*expected_error)
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
context 'when success payment' do
|
221
|
+
it 'should update paid value' do
|
222
|
+
VCR.use_cassette('Invoice/paying an invoice') do
|
223
|
+
invoice.pay!
|
224
|
+
|
225
|
+
expect(invoice.paid).to eq("123.45")
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
it 'should pass a new amount' do
|
231
|
+
VCR.use_cassette('Invoice/paying an invoice with another amount') do
|
232
|
+
body = MultiJson.encode({
|
233
|
+
amount: 100,
|
234
|
+
date: Time.now.strftime('%Y-%m-%d')
|
235
|
+
})
|
236
|
+
|
237
|
+
@invoice = invoice
|
238
|
+
@domain = domain
|
239
|
+
|
240
|
+
expect(Charging::Http)
|
241
|
+
.to receive(:post)
|
242
|
+
.with("/invoices/#{@invoice.uuid}/pay/", @domain.token, body, etag: @invoice.etag)
|
243
|
+
.and_return(double(:response, code: 201))
|
244
|
+
|
245
|
+
expect(invoice).to receive(:reload_attributes!)
|
246
|
+
|
247
|
+
invoice.pay!(amount: 100)
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
it 'should pass a payment date' do
|
252
|
+
VCR.use_cassette('Invoice/paying an invoice with another date') do
|
253
|
+
today = Time.now.strftime('%Y-%m-%d')
|
254
|
+
|
255
|
+
@invoice = invoice
|
256
|
+
@domain = domain
|
257
|
+
|
258
|
+
body = MultiJson.encode({
|
259
|
+
amount: @invoice.amount,
|
260
|
+
date: today
|
261
|
+
})
|
262
|
+
|
263
|
+
expect(Charging::Http)
|
264
|
+
.to receive(:post).with("/invoices/#{@invoice.uuid}/pay/", @domain.token, body, etag: @invoice.etag)
|
265
|
+
.and_return(double(:response, code: 201))
|
266
|
+
|
267
|
+
expect(invoice).to receive(:reload_attributes!)
|
268
|
+
|
269
|
+
invoice.pay!(date: today)
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
it 'should pass a note' do
|
274
|
+
VCR.use_cassette('Invoice/paying an invoice and adding a note') do
|
275
|
+
@invoice = invoice
|
276
|
+
|
277
|
+
body = MultiJson.encode({
|
278
|
+
amount: @invoice.amount,
|
279
|
+
date: Time.now.strftime('%Y-%m-%d'),
|
280
|
+
note: 'some note for payment'
|
281
|
+
})
|
282
|
+
|
283
|
+
expect(Charging::Http)
|
284
|
+
.to receive(:post).with("/invoices/#{@invoice.uuid}/pay/", domain.token, body, etag: @invoice.etag)
|
285
|
+
.and_return(double(:response, code: 201))
|
286
|
+
|
287
|
+
expect(invoice).to receive(:reload_attributes!)
|
288
|
+
|
289
|
+
invoice.pay!(note: "some note for payment")
|
290
|
+
end
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
describe '#payments' do
|
295
|
+
context 'invoice without payments' do
|
296
|
+
it 'should return an empty array' do
|
297
|
+
VCR.use_cassette('Invoice/invoice without payments') do
|
298
|
+
expect(invoice.payments).to eq []
|
299
|
+
end
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
context 'invoice with payments' do
|
304
|
+
it 'should return an empty array' do
|
305
|
+
VCR.use_cassette('Invoice/invoice with payments') do
|
306
|
+
invoice.pay!
|
307
|
+
|
308
|
+
expect(invoice.payments).to_not be_empty
|
309
|
+
end
|
310
|
+
end
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
314
|
+
describe '#destroy!' do
|
315
|
+
it 'should raise delete an invoice at API' do
|
316
|
+
VCR.use_cassette('Invoice/try delete an invoice with payments') do
|
317
|
+
invoice.pay!
|
318
|
+
|
319
|
+
expect(invoice.payments).to_not be_empty
|
320
|
+
|
321
|
+
expect { invoice.destroy! }.to raise_error Charging::Http::LastResponseError
|
322
|
+
|
323
|
+
expect(invoice).to_not be_deleted
|
324
|
+
expect(invoice).to be_persisted
|
325
|
+
end
|
326
|
+
end
|
327
|
+
|
328
|
+
it 'should delete an invoice without payments' do
|
329
|
+
VCR.use_cassette('Invoice/deleting an invoice without payments') do
|
330
|
+
expect(invoice).to be_persisted
|
331
|
+
|
332
|
+
expect { invoice.destroy! }.to_not raise_error
|
333
|
+
|
334
|
+
expect(invoice).to be_deleted
|
335
|
+
expect(invoice).to_not be_persisted
|
336
|
+
end
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
340
|
+
describe '.find_by_uuid' do
|
341
|
+
it 'should require an account' do
|
342
|
+
expected_error = [ArgumentError, 'domain required']
|
343
|
+
|
344
|
+
expect { described_class.find_by_uuid(nil, '') }.to raise_error(*expected_error)
|
345
|
+
end
|
346
|
+
|
347
|
+
it 'should require an uuid' do
|
348
|
+
VCR.use_cassette('Invoice/try find by uuid an invoice with nil value') do
|
349
|
+
expected_error = [ArgumentError, 'uuid required']
|
350
|
+
|
351
|
+
expect { described_class.find_by_uuid(domain, nil) }.to raise_error(*expected_error)
|
352
|
+
end
|
353
|
+
end
|
354
|
+
|
355
|
+
it 'should raise for invalid uuid' do
|
356
|
+
VCR.use_cassette('Invoice/try find by uuid an invoice with invalid uuid') do
|
357
|
+
expect { described_class.find_by_uuid(domain, 'invalid-uuid') }.to raise_error Charging::Http::LastResponseError
|
358
|
+
end
|
359
|
+
end
|
360
|
+
|
361
|
+
it 'should raise if not response to success (200)' do
|
362
|
+
VCR.use_cassette('Invoice/try find by uuid an invoice when response not success') do
|
363
|
+
response_mock = double('AcceptedResponse', code: 202, to_s: 'AcceptedResponse')
|
364
|
+
|
365
|
+
expect(described_class)
|
366
|
+
.to receive(:get_invoice)
|
367
|
+
.with(domain, 'uuid')
|
368
|
+
.and_return(response_mock)
|
369
|
+
|
370
|
+
expect {
|
371
|
+
described_class.find_by_uuid(domain, 'uuid')
|
372
|
+
}.to raise_error Charging::Http::LastResponseError, 'AcceptedResponse'
|
373
|
+
end
|
374
|
+
end
|
375
|
+
|
376
|
+
context 'for a valid uuid' do
|
377
|
+
before do
|
378
|
+
VCR.use_cassette('Invoice/find by uuid an invoice') do
|
379
|
+
@invoice = invoice
|
380
|
+
@find_result = described_class.find_by_uuid(domain, @invoice.uuid)
|
381
|
+
end
|
382
|
+
end
|
383
|
+
|
384
|
+
subject { @find_result }
|
385
|
+
|
386
|
+
it 'should instantiate a charge account' do
|
387
|
+
expect(subject).to be_an_instance_of(Charging::Invoice)
|
388
|
+
end
|
389
|
+
|
390
|
+
describe '#uri' do
|
391
|
+
subject { super().uri }
|
392
|
+
it { is_expected.to eq "http://sandbox.charging.financeconnect.com.br/invoices/#{@invoice.uuid}/" }
|
393
|
+
end
|
394
|
+
end
|
395
|
+
end
|
396
|
+
|
397
|
+
describe '.kinds' do
|
398
|
+
it 'should require a domain' do
|
399
|
+
expected_error = [ArgumentError, 'domain required']
|
400
|
+
|
401
|
+
expect { described_class.kinds(nil) }.to raise_error(*expected_error)
|
402
|
+
end
|
403
|
+
|
404
|
+
it 'should raise for invalid domain' do
|
405
|
+
VCR.use_cassette('Invoice/try get invoice kinds with invalid domain token') do
|
406
|
+
expected_error = [Charging::Http::LastResponseError]
|
407
|
+
|
408
|
+
expect { described_class.kinds(double(token: 'invalid')) }.to raise_error(*expected_error)
|
409
|
+
end
|
410
|
+
end
|
411
|
+
|
412
|
+
it 'should return an array with first page' do
|
413
|
+
VCR.use_cassette('Invoice/get first page of invoice kinds') do
|
414
|
+
default_result = described_class.kinds(domain)
|
415
|
+
first_page_result = described_class.kinds(domain, 1)
|
416
|
+
|
417
|
+
expect(default_result).to eq first_page_result
|
418
|
+
|
419
|
+
expect(default_result).to include({"acronym"=>"DM", "itau_code"=>1, "code"=>2, "name"=>"Duplicata Mercantil"})
|
420
|
+
expect(default_result.size).to eq 10
|
421
|
+
end
|
422
|
+
end
|
423
|
+
|
424
|
+
it 'should return an array with second page' do
|
425
|
+
VCR.use_cassette('Invoice/get second page of invoice kinds') do
|
426
|
+
result = described_class.kinds(domain, 2)
|
427
|
+
|
428
|
+
expect(result).to_not include({"acronym"=>"DM", "itau_code"=>1, "code"=>2, "name"=>"Duplicata Mercantil"})
|
429
|
+
expect(result.size).to eq 10
|
430
|
+
end
|
431
|
+
end
|
432
|
+
|
433
|
+
it 'should return an array of kinds passing new limit per page' do
|
434
|
+
VCR.use_cassette('Invoice/get first page of invoice kinds with 12 items per page') do
|
435
|
+
result = described_class.kinds(domain, 1, 12)
|
436
|
+
|
437
|
+
expect(result).to include({"acronym"=>"DM", "itau_code"=>1, "code"=>2, "name"=>"Duplicata Mercantil"})
|
438
|
+
expect(result.size).to eq 12
|
439
|
+
end
|
440
|
+
end
|
441
|
+
end
|
442
|
+
end
|