suretax 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +27 -0
  3. data/.travis.yml +14 -0
  4. data/Gemfile +4 -0
  5. data/Gemfile.lock +74 -0
  6. data/Gemfile.travis +12 -0
  7. data/LICENSE.txt +22 -0
  8. data/NOTES.md +3 -0
  9. data/README.md +58 -0
  10. data/Rakefile +1 -0
  11. data/circle.yml +7 -0
  12. data/lib/suretax.rb +24 -0
  13. data/lib/suretax/api.rb +7 -0
  14. data/lib/suretax/api/cancel_request.rb +64 -0
  15. data/lib/suretax/api/group.rb +16 -0
  16. data/lib/suretax/api/item_message.rb +13 -0
  17. data/lib/suretax/api/request.rb +133 -0
  18. data/lib/suretax/api/request_item.rb +84 -0
  19. data/lib/suretax/api/response.rb +53 -0
  20. data/lib/suretax/api/tax.rb +25 -0
  21. data/lib/suretax/api/tax_amount.rb +46 -0
  22. data/lib/suretax/concerns.rb +7 -0
  23. data/lib/suretax/concerns/validatable.rb +208 -0
  24. data/lib/suretax/configuration.rb +84 -0
  25. data/lib/suretax/connection.rb +48 -0
  26. data/lib/suretax/constants.rb +7 -0
  27. data/lib/suretax/constants/regulatory_codes.rb +11 -0
  28. data/lib/suretax/constants/response_groups.rb +8 -0
  29. data/lib/suretax/constants/sales_type_codes.rb +8 -0
  30. data/lib/suretax/constants/tax_situs_codes.rb +12 -0
  31. data/lib/suretax/constants/transaction_type_codes.rb +505 -0
  32. data/lib/suretax/response.rb +70 -0
  33. data/lib/suretax/version.rb +3 -0
  34. data/spec/lib/suretax/api/group_spec.rb +50 -0
  35. data/spec/lib/suretax/api/request_item_spec.rb +54 -0
  36. data/spec/lib/suretax/api/request_item_validations_spec.rb +237 -0
  37. data/spec/lib/suretax/api/request_spec.rb +197 -0
  38. data/spec/lib/suretax/api/request_validations_spec.rb +384 -0
  39. data/spec/lib/suretax/api/response_spec.rb +165 -0
  40. data/spec/lib/suretax/api/tax_amount_spec.rb +37 -0
  41. data/spec/lib/suretax/api/tax_spec.rb +59 -0
  42. data/spec/lib/suretax/configuration_spec.rb +97 -0
  43. data/spec/lib/suretax/connection_spec.rb +77 -0
  44. data/spec/lib/suretax/response_spec.rb +136 -0
  45. data/spec/spec_helper.rb +45 -0
  46. data/spec/support/cancellation_helper.rb +31 -0
  47. data/spec/support/connection_shared_examples.rb +37 -0
  48. data/spec/support/request_helper.rb +309 -0
  49. data/spec/support/suretax_helper.rb +27 -0
  50. data/spec/support/validations_shared_examples.rb +28 -0
  51. data/suretax.gemspec +33 -0
  52. 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
@@ -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