taxjar-ruby 1.0.0
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/.gitignore +19 -0
- data/.rspec +2 -0
- data/Gemfile +11 -0
- data/LICENSE.txt +22 -0
- data/README.md +173 -0
- data/Rakefile +2 -0
- data/lib/taxjar.rb +15 -0
- data/lib/taxjar/api/api.rb +37 -0
- data/lib/taxjar/api/request.rb +70 -0
- data/lib/taxjar/api/utils.rb +40 -0
- data/lib/taxjar/base.rb +88 -0
- data/lib/taxjar/breakdown.rb +16 -0
- data/lib/taxjar/breakdown_line_item.rb +10 -0
- data/lib/taxjar/category.rb +7 -0
- data/lib/taxjar/client.rb +25 -0
- data/lib/taxjar/error.rb +74 -0
- data/lib/taxjar/line_item.rb +9 -0
- data/lib/taxjar/order.rb +13 -0
- data/lib/taxjar/rate.rb +9 -0
- data/lib/taxjar/refund.rb +13 -0
- data/lib/taxjar/shipping.rb +9 -0
- data/lib/taxjar/tax.rb +11 -0
- data/lib/taxjar/version.rb +38 -0
- data/spec/fixtures/categories.json +39 -0
- data/spec/fixtures/order.json +26 -0
- data/spec/fixtures/rates.json +13 -0
- data/spec/fixtures/refund.json +27 -0
- data/spec/fixtures/taxes.json +42 -0
- data/spec/helper.rb +45 -0
- data/spec/taxjar/api/api_spec.rb +207 -0
- data/spec/taxjar/api/request_spec.rb +134 -0
- data/spec/taxjar/base_spec.rb +28 -0
- data/spec/taxjar/client_spec.rb +23 -0
- data/spec/taxjar/error_spec.rb +21 -0
- data/spec/taxjar/version_spec.rb +34 -0
- data/taxjar-ruby.gemspec +26 -0
- metadata +163 -0
@@ -0,0 +1,207 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
describe Taxjar::API do
|
4
|
+
|
5
|
+
before do
|
6
|
+
@client = Taxjar::Client.new(api_key: 'AK')
|
7
|
+
end
|
8
|
+
|
9
|
+
describe '#categories' do
|
10
|
+
before do
|
11
|
+
stub_get('/v2/categories').to_return(body: fixture('categories.json'),
|
12
|
+
headers: {content_type: 'application/json; charset=utf-8'})
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'requests the right resource' do
|
17
|
+
@client.categories
|
18
|
+
expect(a_get('/v2/categories')).to have_been_made
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'returns the requested categories' do
|
22
|
+
categories = @client.categories
|
23
|
+
expect(categories).to be_an Array
|
24
|
+
expect(categories.first).to be_a Taxjar::Category
|
25
|
+
expect(categories.first.name).to eq('Digital Goods')
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe '#rate_for_location' do
|
30
|
+
before do
|
31
|
+
@postal_code = "90210"
|
32
|
+
stub_get("/v2/rates/#{@postal_code}").to_return(body: fixture('rates.json'),
|
33
|
+
headers: {content_type: 'application/json; charset=utf-8'})
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'requests the right resource' do
|
38
|
+
@client.rates_for_location(@postal_code)
|
39
|
+
expect(a_get("/v2/rates/#{@postal_code}")).to have_been_made
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'returns the requested rates' do
|
43
|
+
rates = @client.rates_for_location(@postal_code)
|
44
|
+
expect(rates).to be_a Taxjar::Rate
|
45
|
+
expect(rates.county).to eq('LOS ANGELES')
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "#tax_for_order" do
|
50
|
+
before do
|
51
|
+
stub_post("/v2/taxes").to_return(body: fixture('taxes.json'),
|
52
|
+
headers: {content_type: 'application/json; charset=utf-8'})
|
53
|
+
|
54
|
+
@order = {:from_country => 'US',
|
55
|
+
:from_zip => '07001',
|
56
|
+
:from_state => 'NJ',
|
57
|
+
:to_zip => '07446',
|
58
|
+
:amount => 16.50,
|
59
|
+
:shipping => 1.5,
|
60
|
+
:line_items => [{:line_item => {:quantity => 1,
|
61
|
+
:unit_price => 15.0,
|
62
|
+
:product_tax_code => '20010'}}]
|
63
|
+
}
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'requests the right resource' do
|
67
|
+
@client.tax_for_order(@order)
|
68
|
+
expect(a_post("/v2/taxes")).to have_been_made
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'returns the requested taxes' do
|
72
|
+
tax = @client.tax_for_order(@order)
|
73
|
+
expect(tax).to be_a Taxjar::Tax
|
74
|
+
expect(tax.tax_source).to eq('destination')
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe "#create_order" do
|
79
|
+
before do
|
80
|
+
stub_post("/v2/transactions/orders").to_return(body: fixture('order.json'),
|
81
|
+
headers: {content_type: 'application/json; charset=utf-8'})
|
82
|
+
|
83
|
+
@order = {:transaction_id => '123',
|
84
|
+
:transaction_date => '2015/05/14',
|
85
|
+
:to_country => 'US',
|
86
|
+
:to_zip => '90002',
|
87
|
+
:to_city => 'Los Angeles',
|
88
|
+
:to_street => '123 Palm Grove Ln',
|
89
|
+
:amount => 17.45,
|
90
|
+
:shipping => 1.5,
|
91
|
+
:sales_tax => 0.95,
|
92
|
+
:line_items => [{:quantity => 1,
|
93
|
+
:product_identifier => '12-34243-9',
|
94
|
+
:descriptiion => 'Fuzzy Widget',
|
95
|
+
:unit_price => 15.0,
|
96
|
+
:sales_tax => 0.95}]
|
97
|
+
}
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'requests the right resource' do
|
101
|
+
@client.create_order(@order)
|
102
|
+
expect(a_post("/v2/transactions/orders")).to have_been_made
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'returns the created order' do
|
106
|
+
order = @client.create_order(@order)
|
107
|
+
expect(order).to be_a Taxjar::Order
|
108
|
+
expect(order.transaction_id).to eq(123)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
describe "#update_order" do
|
113
|
+
before do
|
114
|
+
@order_id = 123
|
115
|
+
stub_put("/v2/transactions/orders/#{@order_id}").to_return(body: fixture('order.json'),
|
116
|
+
headers: {content_type: 'application/json; charset=utf-8'})
|
117
|
+
|
118
|
+
@order = {:transaction_id => '123',
|
119
|
+
:amount => 17.95,
|
120
|
+
:shipping => 2.0,
|
121
|
+
:line_items => [{:quantity => 1,
|
122
|
+
:product_identifier => '12-34243-0',
|
123
|
+
:descriptiion => 'Heavy Widget',
|
124
|
+
:unit_price => 15.0,
|
125
|
+
:discount => 0.0,
|
126
|
+
:sales_tax => 0.95}]
|
127
|
+
}
|
128
|
+
end
|
129
|
+
|
130
|
+
it 'requests the right resource' do
|
131
|
+
@client.update_order(@order)
|
132
|
+
expect(a_put("/v2/transactions/orders/#{@order_id}")).to have_been_made
|
133
|
+
end
|
134
|
+
|
135
|
+
it 'returns the updated order' do
|
136
|
+
order = @client.update_order(@order)
|
137
|
+
expect(order).to be_a Taxjar::Order
|
138
|
+
expect(order.transaction_id).to eq(123)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
describe "#create_refund" do
|
143
|
+
before do
|
144
|
+
stub_post("/v2/transactions/refunds").to_return(body: fixture('refund.json'),
|
145
|
+
headers: {content_type: 'application/json; charset=utf-8'})
|
146
|
+
|
147
|
+
@refund = {:transaction_id => '321',
|
148
|
+
:transaction_date => '2015/05/14',
|
149
|
+
:transaction_reference_id => '123',
|
150
|
+
:to_country => 'US',
|
151
|
+
:to_zip => '90002',
|
152
|
+
:to_state => 'CA',
|
153
|
+
:to_city => 'Los Angeles',
|
154
|
+
:to_street => '123 Palm Grove Ln',
|
155
|
+
:amount => 17.45,
|
156
|
+
:shipping => 1.5,
|
157
|
+
:sales_tax => 0.95,
|
158
|
+
:line_items => [{:quantity => 1,
|
159
|
+
:product_identifier => '12-34243-9',
|
160
|
+
:descriptiion => 'Fuzzy Widget',
|
161
|
+
:unit_price => 15.0,
|
162
|
+
:sales_tax => 0.95}]
|
163
|
+
}
|
164
|
+
end
|
165
|
+
|
166
|
+
it 'requests the right resource' do
|
167
|
+
@client.create_refund(@refund)
|
168
|
+
expect(a_post("/v2/transactions/refunds")).to have_been_made
|
169
|
+
end
|
170
|
+
|
171
|
+
it 'returns the created order' do
|
172
|
+
refund = @client.create_refund(@refund)
|
173
|
+
expect(refund).to be_a Taxjar::Refund
|
174
|
+
expect(refund.transaction_id).to eq(321)
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
describe "#update_refund" do
|
179
|
+
before do
|
180
|
+
@refund_id = 321
|
181
|
+
stub_put("/v2/transactions/refunds/#{@refund_id}").to_return(body: fixture('refund.json'),
|
182
|
+
headers: {content_type: 'application/json; charset=utf-8'})
|
183
|
+
|
184
|
+
@refund = {:transaction_id => '321',
|
185
|
+
:amount => 17.95,
|
186
|
+
:shipping => 2.0,
|
187
|
+
:sales_tax => 0.95,
|
188
|
+
:line_items => [{:quantity => 1,
|
189
|
+
:product_identifier => '12-34243-9',
|
190
|
+
:descriptiion => 'Heavy Widget',
|
191
|
+
:unit_price => 15.0,
|
192
|
+
:sales_tax => 0.95}]
|
193
|
+
}
|
194
|
+
end
|
195
|
+
|
196
|
+
it 'requests the right resource' do
|
197
|
+
@client.update_refund(@refund)
|
198
|
+
expect(a_put("/v2/transactions/refunds/#{@refund_id}")).to have_been_made
|
199
|
+
end
|
200
|
+
|
201
|
+
it 'returns the updated refund' do
|
202
|
+
refund = @client.update_refund(@refund)
|
203
|
+
expect(refund).to be_a Taxjar::Refund
|
204
|
+
expect(refund.transaction_id).to eq(321)
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
describe Taxjar::API::Request do
|
4
|
+
|
5
|
+
describe "#BASE_URL" do
|
6
|
+
it 'should have taxjar api url' do
|
7
|
+
expect(Taxjar::API::Request::BASE_URL).to eq('https://api.taxjar.com')
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "attr_accessors" do
|
12
|
+
let(:client){ Taxjar::Client.new(api_key: 'AK')}
|
13
|
+
let(:subject) do
|
14
|
+
Taxjar::API::Request.new(client, :get, '/api_path', 'object')
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should return the client' do
|
18
|
+
expect(subject).to respond_to(:client)
|
19
|
+
expect(subject.client).to be(client)
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'should return a uri' do
|
23
|
+
expect(subject).to respond_to(:uri)
|
24
|
+
expect(subject.uri).to be_instance_of(Addressable::URI)
|
25
|
+
expect(subject.uri.to_s).to eq('https://api.taxjar.com/api_path')
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'should return headers' do
|
29
|
+
expect(subject).to respond_to(:headers)
|
30
|
+
expect(subject.headers).to be_instance_of(Hash)
|
31
|
+
expect(subject.headers[:user_agent]).to match('TaxjarRubyGem')
|
32
|
+
expect(subject.headers[:authorization]).to eq('Bearer AK')
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'should return request method' do
|
36
|
+
expect(subject).to respond_to(:request_method)
|
37
|
+
expect(subject.request_method).to be_instance_of(Symbol)
|
38
|
+
expect(subject.request_method).to eq(:get)
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'should return path' do
|
42
|
+
expect(subject).to respond_to(:path)
|
43
|
+
expect(subject.path).to be_instance_of(String)
|
44
|
+
expect(subject.path).to eq('/api_path')
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should return object_key' do
|
48
|
+
expect(subject).to respond_to(:object_key)
|
49
|
+
expect(subject.object_key).to be_instance_of(String)
|
50
|
+
expect(subject.object_key).to eq('object')
|
51
|
+
end
|
52
|
+
|
53
|
+
describe 'options' do
|
54
|
+
it 'should return options' do
|
55
|
+
expect(subject).to respond_to(:options)
|
56
|
+
expect(subject.options).to be_instance_of(Hash)
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'should have an empty hash if no options passed to constructor' do
|
60
|
+
expect(subject.options).to eq({})
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'should have options if passed to constructor' do
|
64
|
+
options = {city: "New York City", state: "NY"}
|
65
|
+
client = Taxjar::Client.new(api_key: 'AK')
|
66
|
+
subject = Taxjar::API::Request.new(client, :get, '/api_path', 'object', options)
|
67
|
+
expect(subject.options).to eq(options)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
describe "#perform" do
|
74
|
+
|
75
|
+
let(:client){ Taxjar::Client.new(api_key: 'AK')}
|
76
|
+
let(:subject) do
|
77
|
+
Taxjar::API::Request.new(client, :get, '/api_path', 'object')
|
78
|
+
end
|
79
|
+
|
80
|
+
context 'with get' do
|
81
|
+
it 'should return a body if no errors' do
|
82
|
+
stub_request(:get, "https://api.taxjar.com/api_path").
|
83
|
+
with(:headers => {'Authorization'=>'Bearer AK', 'Connection'=>'close',
|
84
|
+
'Host'=>'api.taxjar.com',
|
85
|
+
'User-Agent'=>'TaxjarRubyGem/1.0.0'}).
|
86
|
+
to_return(:status => 200, :body => '{"object": {"id": "3"}}',
|
87
|
+
:headers => {content_type: 'application/json; charset utf-8'})
|
88
|
+
|
89
|
+
|
90
|
+
expect(subject.perform).to eq({id: '3'})
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
context 'with POST' do
|
95
|
+
|
96
|
+
let(:client){ Taxjar::Client.new(api_key: 'AK')}
|
97
|
+
let(:subject) do
|
98
|
+
Taxjar::API::Request.new(client, :post, '/api_path', 'object', {:city => "New York"})
|
99
|
+
end
|
100
|
+
|
101
|
+
it 'should return a body if no errors' do
|
102
|
+
stub_request(:post, "https://api.taxjar.com/api_path").
|
103
|
+
with(:body => "{\"city\":\"New York\"}",
|
104
|
+
:headers => {'Authorization'=>'Bearer AK', 'Connection'=>'close',
|
105
|
+
'Content-Type'=>'application/json',
|
106
|
+
'Host'=>'api.taxjar.com',
|
107
|
+
'User-Agent'=>'TaxjarRubyGem/1.0.0'}).
|
108
|
+
to_return(:status => 200, :body => '{"object": {"id": "3"}}',
|
109
|
+
:headers => {content_type: 'application/json; charset utf-8'})
|
110
|
+
|
111
|
+
|
112
|
+
expect(subject.perform).to eq({id: '3'})
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
Taxjar::Error::ERRORS.each do |status, exception|
|
117
|
+
context "when HTTP status is #{status}" do
|
118
|
+
it "raises #{exception}" do
|
119
|
+
stub_request(:get, "https://api.taxjar.com/api_path").
|
120
|
+
with(:headers => {'Authorization'=>'Bearer AK', 'Connection'=>'close',
|
121
|
+
'Host'=>'api.taxjar.com',
|
122
|
+
'User-Agent'=>'TaxjarRubyGem/1.0.0'}).
|
123
|
+
to_return(:status => status, :body => '{}',
|
124
|
+
:body => '{"error": "Not Acceptable",
|
125
|
+
"detail": "error explanation",
|
126
|
+
"status": "'+ status.to_s + '"}',
|
127
|
+
:headers => {content_type: 'application/json; charset utf-8'})
|
128
|
+
expect{subject.perform}.to raise_error(exception, 'error explanation')
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
require 'helper'
|
4
|
+
|
5
|
+
describe Taxjar::Base do
|
6
|
+
|
7
|
+
describe "#initialize" do
|
8
|
+
before do
|
9
|
+
@klass = Class.new(Taxjar::Base)
|
10
|
+
@klass.attr_reader(:field)
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should convert string fields to floats if it can be done' do
|
14
|
+
b = @klass.new(:field => '3.0')
|
15
|
+
expect(b.field).to eq(3.0)
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should convert string fields to integers if it can be done' do
|
19
|
+
b = @klass.new(:field => '3')
|
20
|
+
expect(b.field).to eq(3)
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'it should leave string as strings' do
|
24
|
+
b = @klass.new(:field => 'a')
|
25
|
+
expect(b.field).to eq('a')
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
describe Taxjar::Client do
|
4
|
+
|
5
|
+
describe '#api_key?' do
|
6
|
+
it 'returns true if api_key is present' do
|
7
|
+
client = Taxjar::Client.new(api_key: 'AK')
|
8
|
+
expect(client.api_key?).to be true
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'returns false if api_key is not present' do
|
12
|
+
client = Taxjar::Client.new
|
13
|
+
expect(client.api_key?).to be false
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe '#user_agent' do
|
18
|
+
it 'returns string with version' do
|
19
|
+
client = Taxjar::Client.new(api_key: 'AK')
|
20
|
+
expect(client.user_agent).to eq("TaxjarRubyGem/#{Taxjar::Version}")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
describe Taxjar::Error do
|
4
|
+
|
5
|
+
describe 'attributes' do
|
6
|
+
let(:error) { Taxjar::Error.new('unprocessable entity', 422)}
|
7
|
+
|
8
|
+
describe "#code" do
|
9
|
+
it 'returns the error code' do
|
10
|
+
expect(error.code).to eq(422)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "#message" do
|
15
|
+
it 'returns the message' do
|
16
|
+
expect(error.message).to eq('unprocessable entity')
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
describe Taxjar::Version do
|
4
|
+
before do
|
5
|
+
allow(Taxjar::Version).to receive(:major).and_return(1)
|
6
|
+
allow(Taxjar::Version).to receive(:minor).and_return(2)
|
7
|
+
allow(Taxjar::Version).to receive(:patch).and_return(3)
|
8
|
+
allow(Taxjar::Version).to receive(:pre).and_return(nil)
|
9
|
+
end
|
10
|
+
|
11
|
+
describe '.to_h' do
|
12
|
+
it 'returns a hash with the right values' do
|
13
|
+
expect(Taxjar::Version.to_h).to be_a Hash
|
14
|
+
expect(Taxjar::Version.to_h[:major]).to eq(1)
|
15
|
+
expect(Taxjar::Version.to_h[:minor]).to eq(2)
|
16
|
+
expect(Taxjar::Version.to_h[:patch]).to eq(3)
|
17
|
+
expect(Taxjar::Version.to_h[:pre]).to eq(nil)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe '.to_a' do
|
22
|
+
it 'returns an array with the right values' do
|
23
|
+
expect(Taxjar::Version.to_a).to be_an Array
|
24
|
+
expect(Taxjar::Version.to_a).to eq([1, 2, 3])
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe '.to_s' do
|
29
|
+
it 'returns a string with the right value' do
|
30
|
+
expect(Taxjar::Version.to_s).to be_a String
|
31
|
+
expect(Taxjar::Version.to_s).to eq('1.2.3')
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|