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.
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