emites-client 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +31 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +11 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +366 -0
  8. data/Rakefile +9 -0
  9. data/emites-client.gemspec +37 -0
  10. data/lib/emites.rb +44 -0
  11. data/lib/emites/client.rb +30 -0
  12. data/lib/emites/configuration.rb +12 -0
  13. data/lib/emites/entities/account.rb +8 -0
  14. data/lib/emites/entities/base.rb +9 -0
  15. data/lib/emites/entities/emitter.rb +31 -0
  16. data/lib/emites/entities/nfse.rb +29 -0
  17. data/lib/emites/entities/nfse_status.rb +15 -0
  18. data/lib/emites/entities/nfse_status_transition.rb +14 -0
  19. data/lib/emites/entities/nfse_values.rb +28 -0
  20. data/lib/emites/entities/rps.rb +9 -0
  21. data/lib/emites/entities/taker.rb +20 -0
  22. data/lib/emites/entities/taker_address.rb +21 -0
  23. data/lib/emites/entities/taker_contact.rb +9 -0
  24. data/lib/emites/entities/webhook.rb +9 -0
  25. data/lib/emites/exception.rb +11 -0
  26. data/lib/emites/http.rb +34 -0
  27. data/lib/emites/request.rb +53 -0
  28. data/lib/emites/resources/base.rb +45 -0
  29. data/lib/emites/resources/emitter.rb +98 -0
  30. data/lib/emites/resources/hooks.rb +25 -0
  31. data/lib/emites/resources/nfse.rb +173 -0
  32. data/lib/emites/resources/webhook.rb +84 -0
  33. data/lib/emites/response.rb +38 -0
  34. data/lib/emites/version.rb +3 -0
  35. data/spec/emites/client_spec.rb +45 -0
  36. data/spec/emites/configuration_spec.rb +13 -0
  37. data/spec/emites/entities/account_spec.rb +14 -0
  38. data/spec/emites/entities/base_spec.rb +28 -0
  39. data/spec/emites/entities/emitter_spec.rb +20 -0
  40. data/spec/emites/entities/nfse_spec.rb +148 -0
  41. data/spec/emites/entities/nfse_status_spec.rb +16 -0
  42. data/spec/emites/entities/nfse_status_transition_spec.rb +23 -0
  43. data/spec/emites/entities/nfse_values_spec.rb +19 -0
  44. data/spec/emites/entities/rps_spec.rb +15 -0
  45. data/spec/emites/entities/taker_address_spec.rb +18 -0
  46. data/spec/emites/entities/taker_contact_spec.rb +13 -0
  47. data/spec/emites/entities/taker_spec.rb +18 -0
  48. data/spec/emites/entities/webhook_spec.rb +14 -0
  49. data/spec/emites/exception_spec.rb +21 -0
  50. data/spec/emites/http_spec.rb +62 -0
  51. data/spec/emites/resources/base_spec.rb +96 -0
  52. data/spec/emites/resources/emitter_spec.rb +119 -0
  53. data/spec/emites/resources/nfse_spec.rb +214 -0
  54. data/spec/emites/resources/webhook_spec.rb +62 -0
  55. data/spec/emites_spec.rb +63 -0
  56. data/spec/fixtures/certificate.pfx +0 -0
  57. data/spec/shared_examples/bound_notifiers.rb +8 -0
  58. data/spec/shared_examples/entity_attributes.rb +9 -0
  59. data/spec/spec_helper.rb +38 -0
  60. data/spec/support/matchers/have_attr_accessor.rb +18 -0
  61. data/spec/vcr_cassettes/client/authenticated/false.yml +48 -0
  62. data/spec/vcr_cassettes/client/authenticated/true.yml +259 -0
  63. data/spec/vcr_cassettes/emitters/create/error.yml +57 -0
  64. data/spec/vcr_cassettes/emitters/create/success.yml +80 -0
  65. data/spec/vcr_cassettes/emitters/destroy/error.yml +47 -0
  66. data/spec/vcr_cassettes/emitters/destroy/success.yml +44 -0
  67. data/spec/vcr_cassettes/emitters/info/error.yml +47 -0
  68. data/spec/vcr_cassettes/emitters/info/success.yml +77 -0
  69. data/spec/vcr_cassettes/emitters/list/success.yml +135 -0
  70. data/spec/vcr_cassettes/emitters/partial_update/success.yml +90 -0
  71. data/spec/vcr_cassettes/emitters/search/returns_empty.yml +47 -0
  72. data/spec/vcr_cassettes/emitters/search/success.yml +76 -0
  73. data/spec/vcr_cassettes/nfse/cancel/success.yml +49 -0
  74. data/spec/vcr_cassettes/nfse/create/given_taker.yml +109 -0
  75. data/spec/vcr_cassettes/nfse/create/incomplete.yml +73 -0
  76. data/spec/vcr_cassettes/nfse/create/success.yml +112 -0
  77. data/spec/vcr_cassettes/nfse/create/without_taker.yml +73 -0
  78. data/spec/vcr_cassettes/nfse/destroy/success.yml +46 -0
  79. data/spec/vcr_cassettes/nfse/history/success.yml +83 -0
  80. data/spec/vcr_cassettes/nfse/info/success.yml +113 -0
  81. data/spec/vcr_cassettes/nfse/list/success.yml +1353 -0
  82. data/spec/vcr_cassettes/nfse/pdf/success.yml +48 -0
  83. data/spec/vcr_cassettes/nfse/status/success.yml +51 -0
  84. data/spec/vcr_cassettes/nfse/update/success.yml +113 -0
  85. data/spec/vcr_cassettes/nfse/xml/success.yml +48 -0
  86. data/spec/vcr_cassettes/webhooks/create/success.yml +53 -0
  87. data/spec/vcr_cassettes/webhooks/destroy/success.yml +46 -0
  88. data/spec/vcr_cassettes/webhooks/list/success.yml +53 -0
  89. data/spec/vcr_cassettes/webhooks/update/success.yml +52 -0
  90. metadata +390 -0
@@ -0,0 +1,62 @@
1
+ require "spec_helper"
2
+
3
+ describe Emites::Http do
4
+ let(:token) { "t0k3n" }
5
+ let!(:request) do
6
+ class_spy(Typhoeus::Request).
7
+ as_stubbed_const(transfer_nested_constants: true)
8
+ end
9
+
10
+ let!(:response) do
11
+ Typhoeus::Response.new(return_code: :ok, code: 200, body: "OK")
12
+ end
13
+
14
+ before :each do
15
+ Typhoeus.stub(/emites/).and_return(response)
16
+ allow(Typhoeus::Request).to receive(:new).
17
+ and_return(double :request, run: true, response: response)
18
+ end
19
+
20
+ subject { described_class.new(token) }
21
+
22
+ shared_examples "verbs" do |verb|
23
+ it "sends a #{verb.to_s.upcase} request to emites API" do
24
+ subject.send(verb, "/some_resource")
25
+ expect(request).to have_received(:new).
26
+ with("https://sandbox.emites.com.br/api/v1/some_resource",
27
+ method: verb,
28
+ userpwd: "#{token}:x",
29
+ accept_encoding: "gzip",
30
+ headers: {
31
+ "Accept" => "application/json",
32
+ "Content-Type" => "application/json",
33
+ "User-Agent" => Emites.configuration.user_agent
34
+ }
35
+ )
36
+ end
37
+
38
+ it "raises RequestTimeout when timed out" do
39
+ response = Typhoeus::Response.new(return_code: :operation_timedout)
40
+ Typhoeus.stub(/emites/).and_return(response)
41
+ allow(Typhoeus::Request).to receive(:new).
42
+ and_return(double :request, run: true, response: response)
43
+
44
+ expect { subject.send(verb, "/some_resource") }.to raise_error(Emites::RequestTimeout)
45
+ end
46
+
47
+ it "raises RequestError when an error occurred" do
48
+ response = Typhoeus::Response.new(return_code: :ok, code: 500, body: "")
49
+ Typhoeus.stub(/emites/).and_return(response)
50
+ allow(Typhoeus::Request).to receive(:new).
51
+ and_return(double :request, run: true, response: response)
52
+
53
+ expect { subject.send(verb, '/some_resource') }.to raise_error(Emites::RequestError)
54
+ end
55
+ end
56
+
57
+ [:get, :post, :put, :patch, :delete].each do |verb|
58
+ describe "##{verb.to_s}" do
59
+ it_behaves_like "verbs", verb
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,96 @@
1
+ require "spec_helper"
2
+
3
+ describe Emites::Resources::Base do
4
+
5
+ module Emites::Entities
6
+ class Dummy < Base
7
+ end
8
+ end
9
+
10
+ module Emites::Resources
11
+ class Dummy < Base
12
+ def parseable
13
+ response = http.get("/1mayrfq1")
14
+ parsed_body(response)
15
+ end
16
+
17
+ def fail
18
+ http.get("/fail")
19
+ end
20
+
21
+ def timeout
22
+ http.get("/timeout")
23
+ end
24
+
25
+ def notifiable(id)
26
+ "notifiable [#{id}]"
27
+ end
28
+
29
+ notify :notifiable
30
+ end
31
+ end
32
+
33
+ let(:http) { Emites::Http.new("7A75E575CFDEDB91FF7E2CE22089181A") }
34
+ let(:request) { double(body: nil, return_code: :ok) }
35
+
36
+ subject { Emites::Resources::Dummy.new(http) }
37
+
38
+ before do
39
+ allow(Emites.configuration).to receive(:url).and_return("http://requestb.in")
40
+ end
41
+
42
+ describe "#parsed_body" do
43
+ before do
44
+ allow(http).to receive(:send_request).and_return(request)
45
+ end
46
+
47
+ it "does not raise an error" do
48
+ expect{ subject.parseable }.not_to raise_error
49
+ end
50
+
51
+ it "response returns an empty hash" do
52
+ expect(subject.parseable).to eq({})
53
+ end
54
+ end
55
+
56
+ describe ".notify" do
57
+ before do
58
+ allow(http).to receive(:send_request).and_return(request)
59
+ end
60
+
61
+ class FakeListener
62
+ def call(result, args)
63
+ [result, args]
64
+ end
65
+ end
66
+
67
+ let(:listener) { FakeListener.new }
68
+
69
+ before do
70
+ Emites.subscribe("emites.dummy.notifiable", listener)
71
+ end
72
+
73
+ it "does not affect method return" do
74
+ expect(subject.notifiable(42)).to eq("notifiable [42]")
75
+ end
76
+
77
+ it "notifies listeners about event" do
78
+ expect(listener).to receive(:call).with("notifiable [42]", [42]).
79
+ and_return(["notifiable [42]", [42]])
80
+ subject.notifiable(42)
81
+ end
82
+ end
83
+
84
+ context "when request fails" do
85
+
86
+ it "raises an RequestError" do
87
+ Typhoeus.stub(/fail/).and_return(Typhoeus::Response.new(return_code: nil))
88
+ expect { subject.fail }.to raise_error(Emites::RequestError)
89
+ end
90
+
91
+ it "raises an RequestTimeout" do
92
+ Typhoeus.stub(/timeout/).and_return(Typhoeus::Response.new(return_code: :operation_timedout))
93
+ expect { subject.timeout }.to raise_error(Emites::RequestTimeout)
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,119 @@
1
+ require "spec_helper"
2
+
3
+ describe Emites::Resources::Emitter do
4
+ let(:http) { Emites::Http.new("7A75E575CFDEDB91FF7E2CE22089181A") }
5
+ let(:entity_klass) { Emites::Entities::Emitter }
6
+ let(:params) do
7
+ {
8
+ email: "wanderson.policarpo@myfreecomm.com.br",
9
+ social_reason: "My Fake, Inc",
10
+ cnpj: "01001001000113",
11
+ fancy_name: "My Fake",
12
+ city_inscription: "3304557",
13
+ state: "RJ",
14
+ city: "3",
15
+ neighborhood: "Icaraí",
16
+ street_type: "RUA",
17
+ street: "Avenida Roberto Silveira - de 472 ao fim - lado par",
18
+ number: 43,
19
+ zip_code: "24230-163",
20
+ phone: "2199999999",
21
+ certificate: Base64.encode64(File.read("spec/fixtures/certificate.pfx")),
22
+ password: "123456"
23
+ }
24
+ end
25
+
26
+ subject { described_class.new(http) }
27
+
28
+ it "has a instance of Emites::Http" do
29
+ expect(subject.http).to eq http
30
+ end
31
+
32
+ it_behaves_like "bound_notifiers", [:create, :destroy]
33
+
34
+ describe "#create" do
35
+ it "creates an emitter" do
36
+ VCR.use_cassette("emitters/create/success") do
37
+ emitter = subject.create(params)
38
+ expect(emitter).to be_a(entity_klass)
39
+ expect(emitter.cnpj).to eq(params[:cnpj])
40
+ end
41
+ end
42
+
43
+ it "returns RequestError" do
44
+ VCR.use_cassette("emitters/create/error") do
45
+ expect {
46
+ subject.create({ email: "email@example.com" })
47
+ }.to raise_error(Emites::RequestError)
48
+ end
49
+ end
50
+ end
51
+
52
+ describe "#info" do
53
+ it "returns an Emitter instance where id is 4" do
54
+ VCR.use_cassette("emitters/info/success") do
55
+ emitter = subject.info(4)
56
+ expect(emitter).to be_a(entity_klass)
57
+ expect(emitter.cnpj).to eq("17799377000155")
58
+ end
59
+ end
60
+
61
+ it "returns RequestError" do
62
+ VCR.use_cassette("emitters/info/error") do
63
+ expect {
64
+ subject.info(2)
65
+ }.to raise_error(Emites::RequestError)
66
+ end
67
+ end
68
+ end
69
+
70
+ describe "#list" do
71
+ it "returns an array of emitters" do
72
+ VCR.use_cassette("emitters/list/success") do
73
+ entities = subject.list
74
+ expect(entities).to be_a(Array)
75
+ entities.each do |e|
76
+ expect(e).to be_a(entity_klass)
77
+ end
78
+ end
79
+ end
80
+ end
81
+
82
+ describe "#search" do
83
+ it "returns an array of emitters where CNPJ is '17799377000155'" do
84
+ VCR.use_cassette("emitters/search/success") do
85
+ entities = subject.search({ cnpj: "17799377000155" })
86
+ expect(entities).to be_a(Array)
87
+ expect(entities.count).to eq(1)
88
+ entities.each do |e|
89
+ expect(e).to be_a(entity_klass)
90
+ end
91
+ end
92
+ end
93
+
94
+ it "returns empty" do
95
+ VCR.use_cassette("emitters/search/returns_empty") do
96
+ entities = subject.search({ cnpj: "1775" })
97
+ expect(entities).to be_a(Array)
98
+ expect(entities).to be_empty
99
+ end
100
+ end
101
+ end
102
+
103
+ describe "#destroy" do
104
+ it "deletes an emitter" do
105
+ VCR.use_cassette("emitters/destroy/success") do
106
+ result = subject.destroy(18)
107
+ expect(result).to be_truthy
108
+ end
109
+ end
110
+
111
+ it "returns RequestError" do
112
+ VCR.use_cassette("emitters/destroy/error") do
113
+ expect {
114
+ subject.destroy(2)
115
+ }.to raise_error(Emites::RequestError)
116
+ end
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,214 @@
1
+ require "spec_helper"
2
+ require "time"
3
+
4
+ describe Emites::Resources::Nfse do
5
+ let(:http) { Emites::Http.new("7A75E575CFDEDB91FF7E2CE22089181A") }
6
+ let(:entity_klass) { Emites::Entities::Nfse }
7
+ let(:params) do
8
+ {
9
+ emitter_id: 4,
10
+ rps_type: 1,
11
+ serie: "a",
12
+ emission_date: Time.now.utc.iso8601,
13
+ operation_nature: 1,
14
+ rps_situation: 1,
15
+ service_values: {
16
+ service_amount: 1000.0,
17
+ deduction_amount: 0,
18
+ retained_iss: false,
19
+ calculation_base: 1000.0,
20
+ iss_percentage: 5.00,
21
+ iss_amount: 50.0,
22
+ pis_amount: 0,
23
+ cofins_amount: 0,
24
+ inss_amount: 0,
25
+ ir_amount: 0,
26
+ csll_amount: 0,
27
+ service_item_code: "0105",
28
+ city_tax_code: "010501",
29
+ description: "RSPEC Servicos de informatica",
30
+ city_code: 3304557,
31
+ nfse_liquid_amount: 1000.0,
32
+ discount_conditioning_amount: 0
33
+ },
34
+ taker: {
35
+ cpf: "83051507121",
36
+ city_inscription: "92708711",
37
+ social_reason: "Tomador RSPEC",
38
+ address: {
39
+ street: "Feijó Júnior",
40
+ number: "535",
41
+ neighborhood: "São Pelegrino",
42
+ neighborhood_type: "COM",
43
+ city_code: 4305108,
44
+ state: "RS",
45
+ zip_code: 95110550,
46
+ city: "Caxias do Sul"
47
+ },
48
+ contact: {
49
+ phone: "32272144",
50
+ ddd: 54
51
+ }
52
+ }
53
+ }
54
+ end
55
+
56
+ subject { described_class.new(http) }
57
+
58
+ it "has a instance of Emites::Http" do
59
+ expect(subject.http).to eq http
60
+ end
61
+
62
+ it_behaves_like "bound_notifiers", [:create, :update, :cancel, :destroy]
63
+
64
+ describe "#list" do
65
+ it "returns an array of Nfse" do
66
+ VCR.use_cassette("nfse/list/success") do
67
+ nfses = subject.list
68
+ expect(nfses).to be_a(Array)
69
+ nfses.each do |e|
70
+ expect(e).to be_a(entity_klass)
71
+ end
72
+ end
73
+ end
74
+ end
75
+
76
+ describe "#info" do
77
+ it "returns a Nfse instance where id is 456" do
78
+ VCR.use_cassette("nfse/info/success") do
79
+ nfse = subject.info(456)
80
+ expect(nfse).to be_a(entity_klass)
81
+ expect(nfse.serie). to eq("MYFC")
82
+ expect(nfse.taker).to be_a(Emites::Entities::Taker)
83
+ end
84
+ end
85
+ end
86
+
87
+ describe "#status" do
88
+ it "returns a Nfse instance status representation" do
89
+ VCR.use_cassette("nfse/status/success") do
90
+ nfse_status = subject.status(456)
91
+ expect(nfse_status).to be_a(Emites::Entities::NfseStatus)
92
+ expect(nfse_status.status).to eq("accepted")
93
+ expect(nfse_status.description).to eq("Processado pela Sefaz")
94
+ end
95
+ end
96
+ end
97
+
98
+ describe "#history" do
99
+ it "returns a Nfse instance status history" do
100
+ VCR.use_cassette("nfse/history/success") do
101
+ nfse_status_history = subject.history(456)
102
+ expect(nfse_status_history).to be_a(Array)
103
+ nfse_status_history.each do |e|
104
+ expect(e).to be_a(Emites::Entities::NfseStatusTransition)
105
+ end
106
+ end
107
+ end
108
+ end
109
+
110
+ describe "#pdf" do
111
+ it "returns a Nfse pdf" do
112
+ VCR.use_cassette("nfse/pdf/success") do
113
+ pdf_url = subject.pdf(456)
114
+ expect(pdf_url).to be_a(String)
115
+ expect(pdf_url).to match(/https?/)
116
+ end
117
+ end
118
+ end
119
+
120
+ describe "#xml" do
121
+ it "returns a Nfse xml" do
122
+ VCR.use_cassette("nfse/xml/success") do
123
+ xml_url = subject.xml(456)
124
+ expect(xml_url).to be_a(String)
125
+ expect(xml_url).to match(/https?/)
126
+ end
127
+ end
128
+ end
129
+
130
+ describe "#cancel" do
131
+ it "cancels a Nfse" do
132
+ VCR.use_cassette("nfse/cancel/success") do
133
+ nfse = subject.cancel(456)
134
+ expect(nfse).to be_a(Emites::Entities::NfseStatus)
135
+ expect(nfse.status).to eq("cancelling")
136
+ end
137
+ end
138
+ end
139
+
140
+ describe "#destroy" do
141
+ it "deletes a Nfse" do
142
+ VCR.use_cassette("nfse/destroy/success") do
143
+ result = subject.destroy(455)
144
+ expect(result).to be_truthy
145
+ end
146
+ end
147
+ end
148
+
149
+ describe "#create" do
150
+ it "creates a completely new Nfse" do
151
+ VCR.use_cassette("nfse/create/success") do
152
+ nfse = subject.create(params)
153
+ taker = nfse.taker
154
+ values = nfse.service_values
155
+
156
+ expect(nfse).to be_a(entity_klass)
157
+
158
+ expect(taker).to be_a(Emites::Entities::Taker)
159
+ expect(taker.social_reason).to eq(params[:taker][:social_reason])
160
+
161
+ expect(values).to be_a(Emites::Entities::NfseValues)
162
+ expect(values.description).to eq(params[:service_values][:description])
163
+ end
164
+ end
165
+
166
+ it "creates a Nfse where taker already exists" do
167
+ VCR.use_cassette("nfse/create/given_taker") do
168
+ params.delete(:taker)
169
+ params[:taker_id] = 6
170
+
171
+ nfse = subject.create(params)
172
+
173
+ expect(nfse.taker).to be_a(Emites::Entities::Taker)
174
+ expect(nfse.taker.social_reason).to eq("Fulano de Tal")
175
+ end
176
+ end
177
+
178
+ it "creates a Nfse without a taker" do
179
+ VCR.use_cassette("nfse/create/without_taker") do
180
+ params.delete(:taker)
181
+
182
+ nfse = subject.create(params)
183
+
184
+ expect(nfse.taker).to be_nil
185
+ end
186
+ end
187
+
188
+ it "creates an incomplete Nfse" do
189
+ VCR.use_cassette("nfse/create/incomplete") do
190
+ params.delete(:taker)
191
+ params.delete(:service_values)
192
+ params[:allow_incomplete] = true
193
+
194
+ nfse = subject.create(params)
195
+
196
+ expect(nfse).to be_a(entity_klass)
197
+ expect(nfse.status).to eq("created")
198
+ end
199
+ end
200
+ end
201
+
202
+ describe "#update" do
203
+ it "updates a Nfse" do
204
+ VCR.use_cassette("nfse/update/success") do
205
+ nfse = subject.update(564, params)
206
+
207
+ expect(nfse).to be_a(entity_klass)
208
+ expect(nfse.status).to eq("scheduled")
209
+ expect(nfse.service_values.service_amount).to eq(1000.0)
210
+ end
211
+ end
212
+ end
213
+
214
+ end