suretax 0.1.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 +27 -0
- data/.travis.yml +14 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +74 -0
- data/Gemfile.travis +12 -0
- data/LICENSE.txt +22 -0
- data/NOTES.md +3 -0
- data/README.md +58 -0
- data/Rakefile +1 -0
- data/circle.yml +7 -0
- data/lib/suretax.rb +24 -0
- data/lib/suretax/api.rb +7 -0
- data/lib/suretax/api/cancel_request.rb +64 -0
- data/lib/suretax/api/group.rb +16 -0
- data/lib/suretax/api/item_message.rb +13 -0
- data/lib/suretax/api/request.rb +133 -0
- data/lib/suretax/api/request_item.rb +84 -0
- data/lib/suretax/api/response.rb +53 -0
- data/lib/suretax/api/tax.rb +25 -0
- data/lib/suretax/api/tax_amount.rb +46 -0
- data/lib/suretax/concerns.rb +7 -0
- data/lib/suretax/concerns/validatable.rb +208 -0
- data/lib/suretax/configuration.rb +84 -0
- data/lib/suretax/connection.rb +48 -0
- data/lib/suretax/constants.rb +7 -0
- data/lib/suretax/constants/regulatory_codes.rb +11 -0
- data/lib/suretax/constants/response_groups.rb +8 -0
- data/lib/suretax/constants/sales_type_codes.rb +8 -0
- data/lib/suretax/constants/tax_situs_codes.rb +12 -0
- data/lib/suretax/constants/transaction_type_codes.rb +505 -0
- data/lib/suretax/response.rb +70 -0
- data/lib/suretax/version.rb +3 -0
- data/spec/lib/suretax/api/group_spec.rb +50 -0
- data/spec/lib/suretax/api/request_item_spec.rb +54 -0
- data/spec/lib/suretax/api/request_item_validations_spec.rb +237 -0
- data/spec/lib/suretax/api/request_spec.rb +197 -0
- data/spec/lib/suretax/api/request_validations_spec.rb +384 -0
- data/spec/lib/suretax/api/response_spec.rb +165 -0
- data/spec/lib/suretax/api/tax_amount_spec.rb +37 -0
- data/spec/lib/suretax/api/tax_spec.rb +59 -0
- data/spec/lib/suretax/configuration_spec.rb +97 -0
- data/spec/lib/suretax/connection_spec.rb +77 -0
- data/spec/lib/suretax/response_spec.rb +136 -0
- data/spec/spec_helper.rb +45 -0
- data/spec/support/cancellation_helper.rb +31 -0
- data/spec/support/connection_shared_examples.rb +37 -0
- data/spec/support/request_helper.rb +309 -0
- data/spec/support/suretax_helper.rb +27 -0
- data/spec/support/validations_shared_examples.rb +28 -0
- data/suretax.gemspec +33 -0
- metadata +281 -0
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Suretax::Api::Amount do
|
4
|
+
let(:tax_amount) { Suretax::Api::Amount.new('1.394490') }
|
5
|
+
|
6
|
+
let(:params) {
|
7
|
+
{
|
8
|
+
amount: 1394490,
|
9
|
+
precision: 6,
|
10
|
+
divisor: 1000000
|
11
|
+
}
|
12
|
+
}
|
13
|
+
|
14
|
+
it 'should return a Float for #to_f' do
|
15
|
+
expect(tax_amount.to_f).to eql(1.394490)
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should return a String for #to_s' do
|
19
|
+
expect(tax_amount.to_s).to eql('1.394490')
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'should provide an integer version via #to_i' do
|
23
|
+
expect(tax_amount.to_i).to eql(1394490)
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'should provide a hard currency value via #cents' do
|
27
|
+
expect(tax_amount.cents).to eql(139)
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'should give the number of decimal places via #precision' do
|
31
|
+
expect(tax_amount.precision).to eql(6)
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'should give integer parameters for calculating the Float via #params' do
|
35
|
+
expect(tax_amount.params).to eql(params)
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Suretax::Api::Tax do
|
4
|
+
|
5
|
+
let(:tax) { Suretax::Api::Tax.new(tax_params) }
|
6
|
+
|
7
|
+
context 'with an API v01 response' do
|
8
|
+
let(:tax_params) { valid_test_response_body['GroupList'].first['TaxList'].first }
|
9
|
+
|
10
|
+
it 'should have a code' do
|
11
|
+
expect(tax.code).to eql('106')
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should have a description' do
|
15
|
+
expect(tax.description).to eql('CA EMERG TEL. USERS SURCHARGE')
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should have an amount' do
|
19
|
+
expect(tax.amount.to_f).to eql(0.200760)
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'with an API v03 response' do
|
25
|
+
let(:tax_params) { valid_v03_response_body['GroupList'].first['TaxList'].first }
|
26
|
+
|
27
|
+
it 'should have a code' do
|
28
|
+
expect(tax.code).to eql('106')
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should have a description' do
|
32
|
+
expect(tax.description).to eql('CA EMERG TEL. USERS SURCHARGE')
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'should have an amount' do
|
36
|
+
expect(tax.amount.to_f).to eql(0.200760)
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should have a revenue code' do
|
40
|
+
expect(tax.revenue).to eql('40')
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'should have a county name' do
|
44
|
+
expect(tax.county).to eql('SAN DIEGO')
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should have a city name' do
|
48
|
+
expect(tax.city).to eql('SAN DIEGO')
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'should have a tax rate' do
|
52
|
+
expect(tax.rate.to_f).to eql(0.005)
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'should have a percent taxable' do
|
56
|
+
expect(tax.taxable.to_f).to eql(1.0)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Suretax do
|
4
|
+
|
5
|
+
let(:config) { Suretax.configuration }
|
6
|
+
let(:url) { 'http://test.dev' }
|
7
|
+
let(:test_host) { 'https://testapi.taxrating.net' }
|
8
|
+
|
9
|
+
describe ".configure" do
|
10
|
+
|
11
|
+
let(:key) { 'xxxxxxxx' }
|
12
|
+
let(:client) { '9999999999' }
|
13
|
+
let(:post_path) { '/Services/V03/SureTax.asmx/PostRequest' }
|
14
|
+
let(:cancel_path) { '/Services/V01/SureTax.asmx/CancelPostRequest' }
|
15
|
+
|
16
|
+
before do
|
17
|
+
Suretax.configure do |c|
|
18
|
+
c.validation_key = key
|
19
|
+
c.client_number = client
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should allow me to set the validation key' do
|
24
|
+
expect(config.validation_key).to eql key
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'should allow me to set the API server base url' do
|
28
|
+
expect(config.base_url).to eql test_host
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should allow me to set the client number' do
|
32
|
+
expect(config.client_number).to eql client
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'should allow me to set the default post path' do
|
36
|
+
expect(config.request_path).to eql post_path
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should allow me to set the default cancel path' do
|
40
|
+
expect(config.cancel_path).to eql cancel_path
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'should default test mode' do
|
44
|
+
expect(config.test?).to eql true
|
45
|
+
end
|
46
|
+
|
47
|
+
context 'when setting the mode' do
|
48
|
+
around(:each) do |test|
|
49
|
+
original_url = Suretax.configuration.base_url
|
50
|
+
Suretax.configuration.base_url = url
|
51
|
+
test.run
|
52
|
+
Suretax.configuration.base_url = original_url
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'should allow me to select non-test mode' do
|
56
|
+
expect(config.test?).to eql false
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe 'production?' do
|
62
|
+
subject { Suretax.configuration.test? }
|
63
|
+
|
64
|
+
context 'when using the test host' do
|
65
|
+
around(:each) do |test|
|
66
|
+
original_url = Suretax.configuration.base_url
|
67
|
+
Suretax.configuration.base_url = test_host
|
68
|
+
test.run
|
69
|
+
Suretax.configuration.base_url = original_url
|
70
|
+
end
|
71
|
+
it { should eql true }
|
72
|
+
end
|
73
|
+
|
74
|
+
context 'when using another host' do
|
75
|
+
around(:each) do |test|
|
76
|
+
original_url = Suretax.configuration.base_url
|
77
|
+
Suretax.configuration.base_url = url
|
78
|
+
test.run
|
79
|
+
Suretax.configuration.base_url = original_url
|
80
|
+
end
|
81
|
+
it { should eql false }
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
describe 'loading from the app environment' do
|
86
|
+
it 'should allow me to set the validation key' do
|
87
|
+
expect(suretax_key).to_not match(/\A\s*\z/)
|
88
|
+
expect(config.validation_key).to include(suretax_key)
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'should allow me to set the API server base url' do
|
92
|
+
expect(suretax_url).to_not match(/\A\s*\z/)
|
93
|
+
expect(config.base_url).to include(suretax_url)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Suretax::Connection do
|
4
|
+
|
5
|
+
let(:connection) { Suretax::Connection.new }
|
6
|
+
|
7
|
+
context 'using v01 of the API' do
|
8
|
+
|
9
|
+
describe '#post' do
|
10
|
+
it_should_behave_like 'API connection' do
|
11
|
+
let(:api_path) { suretax_post_path }
|
12
|
+
let(:request_body) { valid_encoded_test_request_body }
|
13
|
+
let(:response) { connection.post(body: request_body) }
|
14
|
+
|
15
|
+
let(:response_body) do
|
16
|
+
suretax_wrap_response(valid_test_response_body.to_json)
|
17
|
+
end
|
18
|
+
|
19
|
+
let(:invalid_response_body) do
|
20
|
+
suretax_wrap_response(post_failed_response_body.to_json)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe '#cancel' do
|
26
|
+
it_should_behave_like 'API connection' do
|
27
|
+
let(:api_path) { suretax_cancel_path }
|
28
|
+
let(:request_body) { cancel_request_body }
|
29
|
+
let(:response) { connection.cancel(body: request_body) }
|
30
|
+
|
31
|
+
let(:response_body) do
|
32
|
+
suretax_wrap_response(cancel_response_body.to_json)
|
33
|
+
end
|
34
|
+
|
35
|
+
let(:invalid_response_body) do
|
36
|
+
suretax_wrap_response(cancel_failed_response_body.to_json)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
context 'using v03 of the API' do
|
44
|
+
|
45
|
+
describe '#post' do
|
46
|
+
it_should_behave_like 'API connection' do
|
47
|
+
let(:api_path) { suretax_post_path }
|
48
|
+
let(:request_body) { valid_encoded_test_request_body }
|
49
|
+
let(:response) { connection.post(body: request_body) }
|
50
|
+
|
51
|
+
let(:response_body) do
|
52
|
+
suretax_wrap_response(valid_v03_response_body.to_json)
|
53
|
+
end
|
54
|
+
|
55
|
+
let(:invalid_response_body) do
|
56
|
+
suretax_wrap_response(post_failed_response_body.to_json)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe '#cancel' do
|
62
|
+
it_should_behave_like 'API connection' do
|
63
|
+
let(:api_path) { suretax_cancel_path }
|
64
|
+
let(:request_body) { cancel_request_body }
|
65
|
+
let(:response) { connection.cancel(body: request_body) }
|
66
|
+
|
67
|
+
let(:response_body) do
|
68
|
+
suretax_wrap_response(cancel_response_body.to_json)
|
69
|
+
end
|
70
|
+
|
71
|
+
let(:invalid_response_body) do
|
72
|
+
suretax_wrap_response(cancel_failed_response_body.to_json)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,136 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Suretax::Response do
|
4
|
+
let(:api_response_class) {
|
5
|
+
Struct.new(:status,:body,:success) do
|
6
|
+
def success?
|
7
|
+
success
|
8
|
+
end
|
9
|
+
end
|
10
|
+
}
|
11
|
+
|
12
|
+
let(:status_code) { 200 }
|
13
|
+
|
14
|
+
let(:api_response_object) {
|
15
|
+
api_response_class.new(
|
16
|
+
status_code,
|
17
|
+
response_body,
|
18
|
+
true
|
19
|
+
)
|
20
|
+
}
|
21
|
+
|
22
|
+
let(:client_response) { Suretax::Response.new(api_response_object) }
|
23
|
+
|
24
|
+
context 'when posting is successful' do
|
25
|
+
|
26
|
+
let(:response_body) do
|
27
|
+
suretax_wrap_response(valid_test_response_body.to_json)
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'has a body' do
|
31
|
+
expect(client_response.body).to be_instance_of(Hash)
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'has a status' do
|
35
|
+
expect(client_response.status).to eql(200)
|
36
|
+
end
|
37
|
+
|
38
|
+
it "is successful" do
|
39
|
+
expect(client_response).to be_success
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'has a response object' do
|
43
|
+
client_response.response.should respond_to(:status, :body)
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'should return the correct response body' do
|
47
|
+
expect(client_response.body['ResponseCode']).to eql('9999')
|
48
|
+
expect(client_response.body['TotalTax']).to eql('1.394490')
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
context 'when posting is partially successful' do
|
54
|
+
let(:response_body) do
|
55
|
+
suretax_wrap_response(success_with_item_errors.to_json)
|
56
|
+
end
|
57
|
+
|
58
|
+
before do
|
59
|
+
api_response_object.success = false
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'has a body' do
|
63
|
+
expect(client_response.body).to be_instance_of(Hash)
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'responds with a 409' do
|
67
|
+
expect(client_response.status).to eql(409)
|
68
|
+
end
|
69
|
+
|
70
|
+
it "is unsuccessful" do
|
71
|
+
expect(client_response).to_not be_success
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'has a response object' do
|
75
|
+
client_response.response.should respond_to(:status, :body)
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'should return the correct response body' do
|
79
|
+
expect(client_response.body['ResponseCode']).to eql('9001')
|
80
|
+
expect(client_response.body['TotalTax']).to eql('26.53')
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
context 'when posting fails' do
|
85
|
+
|
86
|
+
let(:response_body) do
|
87
|
+
suretax_wrap_response(post_failed_response_body.to_json)
|
88
|
+
end
|
89
|
+
|
90
|
+
before do
|
91
|
+
api_response_object.success = false
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'has a body' do
|
95
|
+
expect(client_response.body).to be_instance_of(Hash)
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'responds with a 400' do
|
99
|
+
expect(client_response.status).to eql(400)
|
100
|
+
end
|
101
|
+
|
102
|
+
it "is unsuccessful" do
|
103
|
+
expect(client_response).to_not be_success
|
104
|
+
end
|
105
|
+
|
106
|
+
it 'has a response object' do
|
107
|
+
client_response.response.should respond_to(:status, :body)
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'should return the correct response body' do
|
111
|
+
expect(client_response.body['ResponseCode']).to eql('1101')
|
112
|
+
expect(client_response.body['TotalTax']).to be_nil
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
context 'when posting fails from a malformed request' do
|
117
|
+
|
118
|
+
let(:response_body) { suretax_wrap_response("invalid request") }
|
119
|
+
|
120
|
+
before do
|
121
|
+
api_response_object.success = true
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'has a body' do
|
125
|
+
expect(client_response.body).to eql('invalid request')
|
126
|
+
end
|
127
|
+
|
128
|
+
it 'responds with a 409' do
|
129
|
+
expect(client_response.status).to eql(400)
|
130
|
+
end
|
131
|
+
|
132
|
+
it "is unsuccessful" do
|
133
|
+
expect(client_response).to_not be_success
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'dotenv' # First line of spec_helper
|
2
|
+
Dotenv.load # Second line of spec_helper
|
3
|
+
|
4
|
+
require 'simplecov'
|
5
|
+
SimpleCov.start do
|
6
|
+
add_filter '/spec/'
|
7
|
+
add_filter '/.bundle/'
|
8
|
+
end
|
9
|
+
|
10
|
+
require 'pry'
|
11
|
+
require 'rspec'
|
12
|
+
require 'rspec/its'
|
13
|
+
require 'suretax'
|
14
|
+
require 'awesome_print'
|
15
|
+
require 'webmock/rspec'
|
16
|
+
|
17
|
+
# Load support files
|
18
|
+
Dir[File.expand_path(File.dirname(__FILE__) + '/support/**/*.rb')].each do
|
19
|
+
|support_file| require support_file
|
20
|
+
end
|
21
|
+
|
22
|
+
RSpec.configure do |config|
|
23
|
+
|
24
|
+
config.before(:each) do
|
25
|
+
Suretax.configure do |c|
|
26
|
+
c.validation_key = ENV['SURETAX_VALIDATION_KEY']
|
27
|
+
c.client_number = ENV['SURETAX_CLIENT_NUMBER']
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
config.expect_with :rspec do |c|
|
32
|
+
c.syntax = [:should, :expect]
|
33
|
+
end
|
34
|
+
|
35
|
+
config.mock_with :rspec do |c|
|
36
|
+
c.syntax = [:should, :expect]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# Silence deprecation warning from money/monetize libraries
|
41
|
+
I18n.enforce_available_locales = false
|
42
|
+
|
43
|
+
include RequestSpecHelper
|
44
|
+
include CancellationSpecHelper
|
45
|
+
include SuretaxSpecHelper
|