avalara 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.travis.yml +3 -1
- data/{Changelog.md → CHANGELOG.md} +10 -5
- data/Gemfile.lock +7 -4
- data/README.md +10 -9
- data/avalara.gemspec +1 -1
- data/lib/avalara.rb +78 -15
- data/lib/avalara/configuration.rb +4 -1
- data/lib/avalara/response.rb +8 -6
- data/lib/avalara/response/address.rb +29 -0
- data/lib/avalara/response/address_line.rb +18 -0
- data/lib/avalara/version.rb +1 -1
- data/spec/fixtures/net/geographical_tax_no_sales.yml +1 -1
- data/spec/fixtures/net/validate_address/failure.yml +106 -0
- data/spec/fixtures/net/validate_address/success_ambiguous.yml +52 -0
- data/spec/models/avalara/configuration_spec.rb +39 -3
- data/spec/models/avalara_spec.rb +151 -0
- data/spec/spec_helper.rb +1 -1
- data/spec/support/avalara.rb +1 -1
- data/spec/support/timeout_server.rb +28 -0
- metadata +34 -43
- data/.ruby-gemset +0 -1
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 17daf1e3192f43bcbab3f7e4bf6d46b00ecbe831
|
4
|
+
data.tar.gz: 050df1c835d6ef337b2804f86fe6bd6444254852
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7e12aded617978eeaaf0dd4cda53d97a42e3cb48063d0a5f4bda351d4dfdf0c2262ca6f43fd0f6f3e96a968b4993e58e9a63c309c17489efae0d5df850be78ad
|
7
|
+
data.tar.gz: 75d9aac50cae897b0c14488fbb7211738126eab8e1a05918cebcc918dd936fab7d279ddbe3bdbc934a645fb508885274b4a700fb67a38a1abeffbf8039dac1b4
|
data/.travis.yml
CHANGED
@@ -1,8 +1,13 @@
|
|
1
|
-
|
1
|
+
## 0.2.0 - January 7, 2016 - Added Timeout
|
2
|
+
|
3
|
+
Added the ability to have set timeouts for open and read connections.
|
4
|
+
Add address validation API.
|
5
|
+
|
6
|
+
## 0.1.1 - June 11, 2015 - Added license
|
2
7
|
|
3
8
|
Added MIT license.
|
4
9
|
|
5
|
-
|
10
|
+
## 0.1.0 - June 11, 2015 - Ruby Support
|
6
11
|
|
7
12
|
Great work @orenf
|
8
13
|
Removes support for ruby 1.9.2 and 1.8.7
|
@@ -12,18 +17,18 @@ Fixes failing specs
|
|
12
17
|
APIError message now returns valid Invoice object
|
13
18
|
|
14
19
|
|
15
|
-
|
20
|
+
## 0.0.3 - October 4, 2013 - Updated multi_json gem
|
16
21
|
|
17
22
|
The multi_json gem was way out of date, but https://github.com/imajes
|
18
23
|
updated it. We also moved over to using Travis for builds.
|
19
24
|
|
20
|
-
|
25
|
+
## 0.0.2 - May 7, 2012 - Updated tests for test endpoint.
|
21
26
|
|
22
27
|
Looks like the tests were initally run against the production database
|
23
28
|
(whops). I re-ran them against test and they're still working.
|
24
29
|
No code changes for this, other than documenting the test endpoint.
|
25
30
|
|
26
|
-
|
31
|
+
## 0.0.1 - February 3, 2012 - Initial Release with get_tax call
|
27
32
|
|
28
33
|
Not much in the way of features so far, but the rough draft of the get_tax call is in,
|
29
34
|
as well as error and warning message handling. Still need to update the docs with it
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
avalara (0.
|
4
|
+
avalara (0.2.0)
|
5
5
|
hashie
|
6
6
|
httparty (~> 0.13.5)
|
7
7
|
multi_json
|
@@ -17,12 +17,12 @@ GEM
|
|
17
17
|
diff-lcs (1.1.3)
|
18
18
|
factory_girl (2.5.0)
|
19
19
|
activesupport
|
20
|
-
hashie (3.4.
|
21
|
-
httparty (0.13.
|
20
|
+
hashie (3.4.4)
|
21
|
+
httparty (0.13.7)
|
22
22
|
json (~> 1.8)
|
23
23
|
multi_xml (>= 0.5.2)
|
24
24
|
i18n (0.6.0)
|
25
|
-
json (1.8.
|
25
|
+
json (1.8.3)
|
26
26
|
multi_json (1.8.0)
|
27
27
|
multi_xml (0.5.5)
|
28
28
|
rake (0.9.2.2)
|
@@ -49,3 +49,6 @@ DEPENDENCIES
|
|
49
49
|
rspec
|
50
50
|
vcr
|
51
51
|
webmock
|
52
|
+
|
53
|
+
BUNDLED WITH
|
54
|
+
1.12.4
|
data/README.md
CHANGED
@@ -8,26 +8,26 @@ This API provides access to the [Avalara](http://www.avalara.com/) AvaTax API.
|
|
8
8
|
|
9
9
|
Add the gem to your `Gemfile`.
|
10
10
|
|
11
|
-
```
|
11
|
+
```ruby
|
12
12
|
gem 'avalara'
|
13
13
|
```
|
14
14
|
|
15
15
|
Setup your Avalara credentials, either in a yml file, or as environment variables. If you want to add a yml file, it'll just need `username` and `password`:
|
16
16
|
|
17
|
-
```
|
17
|
+
```yaml
|
18
18
|
username: 'testaccount'
|
19
19
|
password: 'testkey'
|
20
20
|
```
|
21
21
|
|
22
22
|
You can also specify a different endpoint for development mode:
|
23
23
|
|
24
|
-
```
|
25
|
-
https://development.avalara.net
|
24
|
+
```yaml
|
25
|
+
endpoint: https://development.avalara.net
|
26
26
|
```
|
27
27
|
|
28
28
|
Setup the gem in an initializer (if using Rails), or wherever if you're not. You can load in your username/password however you want, but here's a sample way to do this:
|
29
29
|
|
30
|
-
```
|
30
|
+
```ruby
|
31
31
|
file = File.new(File.join(Rails.root, 'config', 'avalara.yml'))
|
32
32
|
|
33
33
|
if file.exist?
|
@@ -51,7 +51,7 @@ After that you should be able to use a few endpoints to Avalaras tax service. If
|
|
51
51
|
|
52
52
|
### Geographical Tax
|
53
53
|
|
54
|
-
```
|
54
|
+
```ruby
|
55
55
|
result = Avalara.geographical_tax('47.627935', '-122.51702', 100)
|
56
56
|
|
57
57
|
# Access the details of the result, which is a Avalara::Response::Tax object
|
@@ -62,7 +62,7 @@ result.tax_details
|
|
62
62
|
|
63
63
|
### Get Tax
|
64
64
|
|
65
|
-
```
|
65
|
+
```ruby
|
66
66
|
line = Avalara::Request::Line.new({
|
67
67
|
line_no: "1",
|
68
68
|
destination_code: "1",
|
@@ -86,7 +86,7 @@ invoice = Avalara::Request::Invoice.new({
|
|
86
86
|
})
|
87
87
|
|
88
88
|
# You'll get back a Response::Invoice object
|
89
|
-
result = Avalara.get_tax(invoice)
|
89
|
+
result = Avalara.get_tax(invoice)
|
90
90
|
|
91
91
|
result.result_code
|
92
92
|
result.total_amount
|
@@ -100,5 +100,6 @@ result.total_tax_calculated
|
|
100
100
|
If you want to contribute, please fork this repo and make a pull request back. If you add some specs and everything still passes, we can get your contribution in! Thanks to everyone who has contributed:
|
101
101
|
|
102
102
|
* [Adam Fortuna](http://github.com/adamfortuna)
|
103
|
-
* [James Cox](
|
103
|
+
* [James Cox](https://github.com/imajes)
|
104
104
|
* [Dan Sosedoff](http://github.com/sosedoff)
|
105
|
+
* [Leo Correa](https://github.com/Tonkpils)
|
data/avalara.gemspec
CHANGED
@@ -6,7 +6,7 @@ Gem::Specification.new do |s|
|
|
6
6
|
s.name = 'avalara'
|
7
7
|
s.version = Avalara::VERSION
|
8
8
|
s.authors = ['Adam Fortuna']
|
9
|
-
s.email = ['adam@
|
9
|
+
s.email = ['adam@codeschool.com']
|
10
10
|
s.homepage = 'https://github.com/adamfortuna/avalara'
|
11
11
|
s.summary = %q{A Ruby interface to the Avalara Tax API}
|
12
12
|
s.description = %q{This library provides Ruby calls to interact with the Avalara Tax API}
|
data/lib/avalara.rb
CHANGED
@@ -27,6 +27,30 @@ module Avalara
|
|
27
27
|
configuration(&block)
|
28
28
|
end
|
29
29
|
|
30
|
+
def self.timeout
|
31
|
+
configuration.timeout
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.timeout=(timeout)
|
35
|
+
configuration.timeout = timeout
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.read_timeout
|
39
|
+
configuration.read_timeout
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.read_timeout=(read_timeout)
|
43
|
+
configuration.read_timeout = read_timeout
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.open_timeout
|
47
|
+
configuration.open_timeout
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.open_timeout=(open_timeout)
|
51
|
+
configuration.open_timeout = open_timeout
|
52
|
+
end
|
53
|
+
|
30
54
|
def self.endpoint
|
31
55
|
configuration.endpoint
|
32
56
|
end
|
@@ -64,10 +88,13 @@ module Avalara
|
|
64
88
|
"get"
|
65
89
|
].join("/")
|
66
90
|
|
67
|
-
response = API.get(
|
68
|
-
|
69
|
-
|
70
|
-
|
91
|
+
response = API.get(
|
92
|
+
uri,
|
93
|
+
{
|
94
|
+
:headers => API.headers_for('0'),
|
95
|
+
:query => {:saleamount => sales_amount},
|
96
|
+
:basic_auth => authentication
|
97
|
+
}.merge!(net_settings)
|
71
98
|
)
|
72
99
|
|
73
100
|
Avalara::Response::Tax.new(response)
|
@@ -79,19 +106,22 @@ module Avalara
|
|
79
106
|
def self.get_tax(invoice)
|
80
107
|
uri = [endpoint, version, 'tax', 'get'].join('/')
|
81
108
|
|
82
|
-
response = API.post(
|
83
|
-
|
84
|
-
|
85
|
-
|
109
|
+
response = API.post(
|
110
|
+
uri,
|
111
|
+
{
|
112
|
+
:body => invoice.to_json,
|
113
|
+
:headers => API.headers_for(invoice.to_json.length),
|
114
|
+
:basic_auth => authentication
|
115
|
+
}.merge!(net_settings)
|
86
116
|
)
|
87
117
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
118
|
+
case response.code
|
119
|
+
when 200..299
|
120
|
+
Response::Invoice.new(response)
|
121
|
+
when 400..599
|
122
|
+
raise ApiError.new(Response::Invoice.new(response))
|
123
|
+
else
|
124
|
+
raise ApiError.new(response)
|
95
125
|
end
|
96
126
|
rescue Timeout::Error => e
|
97
127
|
raise TimeoutError.new(e)
|
@@ -101,8 +131,41 @@ module Avalara
|
|
101
131
|
raise Error.new(e)
|
102
132
|
end
|
103
133
|
|
134
|
+
def self.validate_address(address_hash)
|
135
|
+
uri = [endpoint, version, "address", "validate"].join("/")
|
136
|
+
response = API.get(
|
137
|
+
uri,
|
138
|
+
{
|
139
|
+
query: address_hash,
|
140
|
+
headers: API.headers_for('0'),
|
141
|
+
basic_auth: authentication
|
142
|
+
}.merge!(net_settings)
|
143
|
+
)
|
144
|
+
case response.code
|
145
|
+
when 200..299
|
146
|
+
Response::Address.new(response)
|
147
|
+
when 400..599
|
148
|
+
fail ApiError.new(Response::Address.new(response))
|
149
|
+
else
|
150
|
+
fail ApiError.new(response)
|
151
|
+
end
|
152
|
+
rescue Timeout::Error => e
|
153
|
+
raise TimeoutError.new(e)
|
154
|
+
end
|
155
|
+
|
104
156
|
private
|
105
157
|
|
158
|
+
def self.net_settings
|
159
|
+
settings = {}
|
160
|
+
if timeout
|
161
|
+
settings[:read_timeout] = timeout
|
162
|
+
settings[:open_timeout] = timeout
|
163
|
+
end
|
164
|
+
settings[:read_timeout] = read_timeout if read_timeout
|
165
|
+
settings[:open_timeout] = open_timeout if open_timeout
|
166
|
+
settings
|
167
|
+
end
|
168
|
+
|
106
169
|
def self.authentication
|
107
170
|
{ :username => username, :password => password}
|
108
171
|
end
|
@@ -3,6 +3,9 @@
|
|
3
3
|
class Avalara::Configuration
|
4
4
|
|
5
5
|
attr_writer :endpoint
|
6
|
+
attr_accessor :timeout
|
7
|
+
attr_accessor :read_timeout
|
8
|
+
attr_accessor :open_timeout
|
6
9
|
attr_accessor :password
|
7
10
|
attr_accessor :username
|
8
11
|
attr_writer :version
|
@@ -12,7 +15,7 @@ class Avalara::Configuration
|
|
12
15
|
# set, the endpoint will default to the official production endpoint at
|
13
16
|
# 'https://rest.avalara.net'.
|
14
17
|
#
|
15
|
-
# If you want to set this to the test endpoint, use 'https://development.avalara.net'
|
18
|
+
# If you want to set this to the test endpoint, use 'https://development.avalara.net'
|
16
19
|
#
|
17
20
|
# Returns the String for the API endpoint.
|
18
21
|
#
|
data/lib/avalara/response.rb
CHANGED
@@ -2,11 +2,13 @@
|
|
2
2
|
|
3
3
|
module Avalara
|
4
4
|
module Response
|
5
|
-
autoload :Invoice,
|
6
|
-
autoload :Message,
|
7
|
-
autoload :TaxLine,
|
8
|
-
autoload :TaxDetail,
|
9
|
-
autoload :TaxAddress,
|
10
|
-
autoload :Tax,
|
5
|
+
autoload :Invoice, 'avalara/response/invoice'
|
6
|
+
autoload :Message, 'avalara/response/message'
|
7
|
+
autoload :TaxLine, 'avalara/response/tax_line'
|
8
|
+
autoload :TaxDetail, 'avalara/response/tax_detail'
|
9
|
+
autoload :TaxAddress, 'avalara/response/tax_address'
|
10
|
+
autoload :Tax, 'avalara/response/tax'
|
11
|
+
autoload :AddressLine, 'avalara/response/address_line'
|
12
|
+
autoload :Address, 'avalara/response/address'
|
11
13
|
end
|
12
14
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require "hashie/extensions/symbolize_keys"
|
2
|
+
|
3
|
+
module Avalara
|
4
|
+
module Response
|
5
|
+
class Address < Avalara::Types::Stash
|
6
|
+
property :result_code, from: :ResultCode
|
7
|
+
property :address, from: :Address
|
8
|
+
property :messages, from: :Messages
|
9
|
+
|
10
|
+
def initialize(response)
|
11
|
+
super(Hashie::Extensions::SymbolizeKeys.symbolize_keys(response))
|
12
|
+
end
|
13
|
+
|
14
|
+
def success?
|
15
|
+
result_code == "Success"
|
16
|
+
end
|
17
|
+
|
18
|
+
def Messages=(msgs)
|
19
|
+
self.messages = msgs.map do |message|
|
20
|
+
Message.new(message)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def Address=(addr)
|
25
|
+
self.address = AddressLine.new(addr)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Avalara
|
2
|
+
module Response
|
3
|
+
class AddressLine < Avalara::Types::Stash
|
4
|
+
property :line_1, from: :Line1
|
5
|
+
property :line_2, from: :Line2
|
6
|
+
property :line_3, from: :Line3
|
7
|
+
property :city, from: :City
|
8
|
+
property :region, from: :Region
|
9
|
+
property :postal_code, from: :PostalCode
|
10
|
+
property :country, from: :Country
|
11
|
+
property :county, from: :County
|
12
|
+
property :fips_code, from: :FipsCode
|
13
|
+
property :carrier_route, from: :CarrierRoute
|
14
|
+
property :post_net, from: :PostNet
|
15
|
+
property :address_type, from: :AddressType
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/avalara/version.rb
CHANGED
@@ -0,0 +1,106 @@
|
|
1
|
+
---
|
2
|
+
- !ruby/struct:VCR::HTTPInteraction
|
3
|
+
request: !ruby/struct:VCR::Request
|
4
|
+
method: :get
|
5
|
+
uri: https://%{API_USERNAME}:%{API_PASSWORD}@development.avalara.net:443/1.0/address/validate?City=New%20York&Country=US&Line1=122%20Hudson%20St&Region=NY
|
6
|
+
body:
|
7
|
+
headers:
|
8
|
+
accept:
|
9
|
+
- application/json
|
10
|
+
content-type:
|
11
|
+
- text/json
|
12
|
+
date:
|
13
|
+
- Mon, 16 May 2016 21:16:56 GMT
|
14
|
+
user-agent:
|
15
|
+
- avalara/0.2.0 (Rubygems; Ruby 2.3.0 x86_64-darwin15)
|
16
|
+
content-length:
|
17
|
+
- '0'
|
18
|
+
response: !ruby/struct:VCR::Response
|
19
|
+
status: !ruby/struct:VCR::ResponseStatus
|
20
|
+
code: 200
|
21
|
+
message: OK
|
22
|
+
headers:
|
23
|
+
cache-control:
|
24
|
+
- private
|
25
|
+
content-type:
|
26
|
+
- text/json; charset=utf-8
|
27
|
+
server:
|
28
|
+
- Microsoft-IIS/7.5
|
29
|
+
x-aspnet-version:
|
30
|
+
- 4.0.30319
|
31
|
+
x-powered-by:
|
32
|
+
- ASP.NET
|
33
|
+
date:
|
34
|
+
- Mon, 16 May 2016 21:19:32 GMT
|
35
|
+
content-length:
|
36
|
+
- '268'
|
37
|
+
body: |
|
38
|
+
{
|
39
|
+
"ResultCode": "Success",
|
40
|
+
"Address": {
|
41
|
+
"Line1": "122 Hudson St",
|
42
|
+
"City": "New York",
|
43
|
+
"Region": "NY",
|
44
|
+
"PostalCode": "10013-2355",
|
45
|
+
"Country": "US",
|
46
|
+
"County": "NEW YORK",
|
47
|
+
"FipsCode": "3606151000",
|
48
|
+
"CarrierRoute": "C006",
|
49
|
+
"PostNet": "100132355992",
|
50
|
+
"AddressType": "H"}
|
51
|
+
}
|
52
|
+
http_version: '1.1'
|
53
|
+
- !ruby/struct:VCR::HTTPInteraction
|
54
|
+
request: !ruby/struct:VCR::Request
|
55
|
+
method: :get
|
56
|
+
uri: https://%{API_USERNAME}:%{API_PASSWORD}@development.avalara.net:443/1.0/address/validate?City=Miami&Country=US&Line1=122%20Hudson%20St&Region=NY
|
57
|
+
body:
|
58
|
+
headers:
|
59
|
+
accept:
|
60
|
+
- application/json
|
61
|
+
content-type:
|
62
|
+
- text/json
|
63
|
+
date:
|
64
|
+
- Mon, 16 May 2016 21:21:26 GMT
|
65
|
+
user-agent:
|
66
|
+
- avalara/0.2.0 (Rubygems; Ruby 2.3.0 x86_64-darwin15)
|
67
|
+
content-length:
|
68
|
+
- '0'
|
69
|
+
response: !ruby/struct:VCR::Response
|
70
|
+
status: !ruby/struct:VCR::ResponseStatus
|
71
|
+
code: 500
|
72
|
+
message: Internal Server Error
|
73
|
+
headers:
|
74
|
+
cache-control:
|
75
|
+
- private
|
76
|
+
content-type:
|
77
|
+
- text/json; charset=utf-8
|
78
|
+
server:
|
79
|
+
- Microsoft-IIS/7.5
|
80
|
+
x-aspnet-version:
|
81
|
+
- 4.0.30319
|
82
|
+
x-powered-by:
|
83
|
+
- ASP.NET
|
84
|
+
date:
|
85
|
+
- Mon, 16 May 2016 21:24:01 GMT
|
86
|
+
content-length:
|
87
|
+
- '431'
|
88
|
+
body: |
|
89
|
+
{
|
90
|
+
"ResultCode": "Error",
|
91
|
+
"Messages": [
|
92
|
+
{
|
93
|
+
"Summary": "The city could not be determined.",
|
94
|
+
"Details": "The city could not be found or determined from postal code.",
|
95
|
+
"RefersTo": "Address.City",
|
96
|
+
"Severity": "Error",
|
97
|
+
"Source": "Avalara.AvaTax.Services.Address"}
|
98
|
+
,{
|
99
|
+
"Summary": "Address not geocoded.",
|
100
|
+
"Details": "Address cannot be geocoded.",
|
101
|
+
"RefersTo": "Address",
|
102
|
+
"Severity": "Error",
|
103
|
+
"Source": "Avalara.AvaTax.Services.Address"}
|
104
|
+
]
|
105
|
+
}
|
106
|
+
http_version: '1.1'
|
@@ -0,0 +1,52 @@
|
|
1
|
+
---
|
2
|
+
- !ruby/struct:VCR::HTTPInteraction
|
3
|
+
request: !ruby/struct:VCR::Request
|
4
|
+
method: :get
|
5
|
+
uri: https://%{API_USERNAME}:%{API_PASSWORD}@development.avalara.net:443/1.0/address/validate?City=NY&Country=US&Line1=122%20Hudson%20St&Region=NY
|
6
|
+
body:
|
7
|
+
headers:
|
8
|
+
accept:
|
9
|
+
- application/json
|
10
|
+
content-type:
|
11
|
+
- text/json
|
12
|
+
date:
|
13
|
+
- Mon, 16 May 2016 21:59:13 GMT
|
14
|
+
user-agent:
|
15
|
+
- avalara/0.2.0 (Rubygems; Ruby 2.3.0 x86_64-darwin15)
|
16
|
+
content-length:
|
17
|
+
- '0'
|
18
|
+
response: !ruby/struct:VCR::Response
|
19
|
+
status: !ruby/struct:VCR::ResponseStatus
|
20
|
+
code: 200
|
21
|
+
message: OK
|
22
|
+
headers:
|
23
|
+
cache-control:
|
24
|
+
- private
|
25
|
+
content-type:
|
26
|
+
- text/json; charset=utf-8
|
27
|
+
server:
|
28
|
+
- Microsoft-IIS/7.5
|
29
|
+
x-aspnet-version:
|
30
|
+
- 4.0.30319
|
31
|
+
x-powered-by:
|
32
|
+
- ASP.NET
|
33
|
+
date:
|
34
|
+
- Mon, 16 May 2016 22:01:47 GMT
|
35
|
+
content-length:
|
36
|
+
- '268'
|
37
|
+
body: |
|
38
|
+
{
|
39
|
+
"ResultCode": "Success",
|
40
|
+
"Address": {
|
41
|
+
"Line1": "122 Hudson St",
|
42
|
+
"City": "New York",
|
43
|
+
"Region": "NY",
|
44
|
+
"PostalCode": "10013-2355",
|
45
|
+
"Country": "US",
|
46
|
+
"County": "NEW YORK",
|
47
|
+
"FipsCode": "3606151000",
|
48
|
+
"CarrierRoute": "C006",
|
49
|
+
"PostNet": "100132355992",
|
50
|
+
"AddressType": "H"}
|
51
|
+
}
|
52
|
+
http_version: '1.1'
|
@@ -5,6 +5,42 @@ require 'spec_helper'
|
|
5
5
|
describe Avalara::Configuration do
|
6
6
|
let(:configuration) { Avalara::Configuration.new }
|
7
7
|
|
8
|
+
context '#timeout' do
|
9
|
+
it 'defaults to nil' do
|
10
|
+
configuration.timeout.should == nil
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'may be overridden' do
|
14
|
+
expect {
|
15
|
+
configuration.timeout = 10
|
16
|
+
}.to change(configuration, :timeout).to(10)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
context '#open_timeout' do
|
21
|
+
it 'defaults to nil' do
|
22
|
+
configuration.open_timeout.should == nil
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'may be overridden' do
|
26
|
+
expect {
|
27
|
+
configuration.open_timeout = 10
|
28
|
+
}.to change(configuration, :open_timeout).to(10)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context '#read_timeout' do
|
33
|
+
it 'defaults to nil' do
|
34
|
+
configuration.read_timeout.should == nil
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'may be overridden' do
|
38
|
+
expect {
|
39
|
+
configuration.read_timeout = 10
|
40
|
+
}.to change(configuration, :read_timeout).to(10)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
8
44
|
context '#endpoint' do
|
9
45
|
it 'defaults to https://rest.avalara.net' do
|
10
46
|
configuration.endpoint.should == 'https://rest.avalara.net'
|
@@ -16,7 +52,7 @@ describe Avalara::Configuration do
|
|
16
52
|
}.to change(configuration, :endpoint).to('https://example.local/')
|
17
53
|
end
|
18
54
|
end
|
19
|
-
|
55
|
+
|
20
56
|
context '#version' do
|
21
57
|
it 'defaults to 1.0' do
|
22
58
|
configuration.version.should == '1.0'
|
@@ -40,7 +76,7 @@ describe Avalara::Configuration do
|
|
40
76
|
}.to change(configuration, :username).to('abcdefg')
|
41
77
|
end
|
42
78
|
end
|
43
|
-
|
79
|
+
|
44
80
|
context '#password' do
|
45
81
|
it 'is unset by default' do
|
46
82
|
configuration.password.should be_nil
|
@@ -52,4 +88,4 @@ describe Avalara::Configuration do
|
|
52
88
|
}.to change(configuration, :password).to('abcdefg')
|
53
89
|
end
|
54
90
|
end
|
55
|
-
end
|
91
|
+
end
|
data/spec/models/avalara_spec.rb
CHANGED
@@ -54,6 +54,45 @@ describe Avalara do
|
|
54
54
|
end
|
55
55
|
end
|
56
56
|
|
57
|
+
describe '.timeout' do
|
58
|
+
it 'returns the configuration timeout' do
|
59
|
+
configuration.timeout = 10
|
60
|
+
Avalara.timeout.should == configuration.timeout
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'overrides the configuration timeout' do
|
64
|
+
expect {
|
65
|
+
Avalara.timeout = 10
|
66
|
+
}.to change(configuration, :timeout).to(10)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe '.open_timeout' do
|
71
|
+
it 'returns the configuration timeout' do
|
72
|
+
configuration.open_timeout = 10
|
73
|
+
Avalara.open_timeout.should == configuration.open_timeout
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'overrides the configuration open_timeout' do
|
77
|
+
expect {
|
78
|
+
Avalara.open_timeout = 10
|
79
|
+
}.to change(configuration, :open_timeout).to(10)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
describe '.read_timeout' do
|
84
|
+
it 'returns the configuration timeout' do
|
85
|
+
configuration.read_timeout = 10
|
86
|
+
Avalara.read_timeout.should == configuration.read_timeout
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'overrides the configuration timeout' do
|
90
|
+
expect {
|
91
|
+
Avalara.read_timeout = 10
|
92
|
+
}.to change(configuration, :read_timeout).to(10)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
57
96
|
describe '.username' do
|
58
97
|
it 'returns the configuration username' do
|
59
98
|
configuration.username = 'username'
|
@@ -124,6 +163,55 @@ describe Avalara do
|
|
124
163
|
end
|
125
164
|
end
|
126
165
|
|
166
|
+
context 'with a timeout' do
|
167
|
+
|
168
|
+
before do
|
169
|
+
WebMock.allow_net_connect!
|
170
|
+
Avalara.timeout = 1
|
171
|
+
Avalara.endpoint = "http://10.255.255.1"
|
172
|
+
end
|
173
|
+
|
174
|
+
it 'raises an avalara timeout error' do
|
175
|
+
expect { subject }.to raise_error(Avalara::TimeoutError)
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
context 'with an open timeout' do
|
180
|
+
|
181
|
+
before do
|
182
|
+
WebMock.allow_net_connect!
|
183
|
+
Avalara.open_timeout = 1
|
184
|
+
Avalara.endpoint = "http://10.255.255.1"
|
185
|
+
end
|
186
|
+
|
187
|
+
it 'raises an avalara timeout error' do
|
188
|
+
expect { subject }.to raise_error(Avalara::TimeoutError)
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
context 'with a read timeout' do
|
193
|
+
let(:dummy) { TimeoutServer.new }
|
194
|
+
|
195
|
+
before(:all) do
|
196
|
+
dummy.listen(TimeoutServer::CONFIG[:BindAddress], TimeoutServer::CONFIG[:Port])
|
197
|
+
Thread.new { dummy.start }
|
198
|
+
end
|
199
|
+
|
200
|
+
before do
|
201
|
+
WebMock.allow_net_connect!
|
202
|
+
Avalara.read_timeout = 1
|
203
|
+
Avalara.endpoint = dummy.endpoint
|
204
|
+
end
|
205
|
+
|
206
|
+
after(:all) do
|
207
|
+
dummy.shutdown
|
208
|
+
end
|
209
|
+
|
210
|
+
it 'raises an avalara timeout error' do
|
211
|
+
expect { subject }.to raise_error(Avalara::TimeoutError)
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
127
215
|
context 'on timeout' do
|
128
216
|
it 'raises an avalara timeout error' do
|
129
217
|
Avalara::API.should_receive(:post).and_raise(Timeout::Error)
|
@@ -189,6 +277,69 @@ describe Avalara do
|
|
189
277
|
end
|
190
278
|
end
|
191
279
|
|
280
|
+
describe ".validate_address" do
|
281
|
+
let(:address) { {
|
282
|
+
Line1: "122 Hudson St",
|
283
|
+
City: "New York",
|
284
|
+
Region: "NY",
|
285
|
+
Country: "US",
|
286
|
+
} }
|
287
|
+
|
288
|
+
def request(address)
|
289
|
+
Avalara.validate_address(address)
|
290
|
+
rescue Avalara::ApiError => e
|
291
|
+
e
|
292
|
+
end
|
293
|
+
|
294
|
+
context "on success" do
|
295
|
+
|
296
|
+
context "and an ambiguous city" do
|
297
|
+
use_vcr_cassette "validate_address/success_ambiguous"
|
298
|
+
|
299
|
+
before do
|
300
|
+
address[:City] = "NY"
|
301
|
+
end
|
302
|
+
|
303
|
+
it "resolves the ambiguity on the city" do
|
304
|
+
response = request(address)
|
305
|
+
response.address.city.should eq("New York")
|
306
|
+
end
|
307
|
+
|
308
|
+
it "is a successful request" do
|
309
|
+
response = request(address)
|
310
|
+
response.result_code.should eq("Success")
|
311
|
+
end
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
context "with an error returned from the api" do
|
316
|
+
use_vcr_cassette "validate_address/failure"
|
317
|
+
|
318
|
+
before do
|
319
|
+
address[:City] = "Miami"
|
320
|
+
end
|
321
|
+
|
322
|
+
it "raises an error" do
|
323
|
+
expect { Avalara.validate_address(address) }.to raise_error(Avalara::ApiError)
|
324
|
+
end
|
325
|
+
|
326
|
+
it "returns messages with details" do
|
327
|
+
response = request(address)
|
328
|
+
response.message.messages.length.should == 2
|
329
|
+
|
330
|
+
errors = response.message.messages
|
331
|
+
city_error = errors[0]
|
332
|
+
city_error.refers_to.should == "Address.City"
|
333
|
+
city_error.summary.should match(/city could not be determined/)
|
334
|
+
city_error.severity.should == "Error"
|
335
|
+
|
336
|
+
address_geocoded_error = errors[1]
|
337
|
+
address_geocoded_error.refers_to.should == "Address"
|
338
|
+
address_geocoded_error.severity.should == "Error"
|
339
|
+
end
|
340
|
+
end
|
341
|
+
end
|
342
|
+
|
192
343
|
## Missing VCR
|
193
344
|
describe '.geographical_tax' do
|
194
345
|
let(:latitude) { '47.627935' }
|
data/spec/spec_helper.rb
CHANGED
data/spec/support/avalara.rb
CHANGED
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'webrick'
|
2
|
+
|
3
|
+
class BlackHole
|
4
|
+
def self.method_missing(*args)
|
5
|
+
self
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
class TimeoutServer < WEBrick::HTTPServer
|
10
|
+
CONFIG = {
|
11
|
+
BindAddress: '127.0.0.1',
|
12
|
+
Port: 5000,
|
13
|
+
AccessLog: BlackHole,
|
14
|
+
Logger: BlackHole,
|
15
|
+
DoNotListen: true
|
16
|
+
}.freeze
|
17
|
+
|
18
|
+
def initialize(options = {})
|
19
|
+
super(CONFIG)
|
20
|
+
mount_proc('/', ->(req, res) {
|
21
|
+
sleep 2
|
22
|
+
})
|
23
|
+
end
|
24
|
+
|
25
|
+
def endpoint
|
26
|
+
"http://#{config[:BindAddress]}:#{config[:Port]}"
|
27
|
+
end
|
28
|
+
end
|
metadata
CHANGED
@@ -1,140 +1,123 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: avalara
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.2.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Adam Fortuna
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2016-06-12 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: hashie
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
|
-
- -
|
17
|
+
- - ">="
|
20
18
|
- !ruby/object:Gem::Version
|
21
19
|
version: '0'
|
22
20
|
type: :runtime
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
|
-
- -
|
24
|
+
- - ">="
|
28
25
|
- !ruby/object:Gem::Version
|
29
26
|
version: '0'
|
30
27
|
- !ruby/object:Gem::Dependency
|
31
28
|
name: httparty
|
32
29
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
30
|
requirements:
|
35
|
-
- - ~>
|
31
|
+
- - "~>"
|
36
32
|
- !ruby/object:Gem::Version
|
37
33
|
version: 0.13.5
|
38
34
|
type: :runtime
|
39
35
|
prerelease: false
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
37
|
requirements:
|
43
|
-
- - ~>
|
38
|
+
- - "~>"
|
44
39
|
- !ruby/object:Gem::Version
|
45
40
|
version: 0.13.5
|
46
41
|
- !ruby/object:Gem::Dependency
|
47
42
|
name: multi_json
|
48
43
|
requirement: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
44
|
requirements:
|
51
|
-
- -
|
45
|
+
- - ">="
|
52
46
|
- !ruby/object:Gem::Version
|
53
47
|
version: '0'
|
54
48
|
type: :runtime
|
55
49
|
prerelease: false
|
56
50
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
51
|
requirements:
|
59
|
-
- -
|
52
|
+
- - ">="
|
60
53
|
- !ruby/object:Gem::Version
|
61
54
|
version: '0'
|
62
55
|
- !ruby/object:Gem::Dependency
|
63
56
|
name: vcr
|
64
57
|
requirement: !ruby/object:Gem::Requirement
|
65
|
-
none: false
|
66
58
|
requirements:
|
67
|
-
- -
|
59
|
+
- - ">="
|
68
60
|
- !ruby/object:Gem::Version
|
69
61
|
version: '0'
|
70
62
|
type: :development
|
71
63
|
prerelease: false
|
72
64
|
version_requirements: !ruby/object:Gem::Requirement
|
73
|
-
none: false
|
74
65
|
requirements:
|
75
|
-
- -
|
66
|
+
- - ">="
|
76
67
|
- !ruby/object:Gem::Version
|
77
68
|
version: '0'
|
78
69
|
- !ruby/object:Gem::Dependency
|
79
70
|
name: webmock
|
80
71
|
requirement: !ruby/object:Gem::Requirement
|
81
|
-
none: false
|
82
72
|
requirements:
|
83
|
-
- -
|
73
|
+
- - ">="
|
84
74
|
- !ruby/object:Gem::Version
|
85
75
|
version: '0'
|
86
76
|
type: :development
|
87
77
|
prerelease: false
|
88
78
|
version_requirements: !ruby/object:Gem::Requirement
|
89
|
-
none: false
|
90
79
|
requirements:
|
91
|
-
- -
|
80
|
+
- - ">="
|
92
81
|
- !ruby/object:Gem::Version
|
93
82
|
version: '0'
|
94
83
|
- !ruby/object:Gem::Dependency
|
95
84
|
name: rspec
|
96
85
|
requirement: !ruby/object:Gem::Requirement
|
97
|
-
none: false
|
98
86
|
requirements:
|
99
|
-
- -
|
87
|
+
- - ">="
|
100
88
|
- !ruby/object:Gem::Version
|
101
89
|
version: '0'
|
102
90
|
type: :development
|
103
91
|
prerelease: false
|
104
92
|
version_requirements: !ruby/object:Gem::Requirement
|
105
|
-
none: false
|
106
93
|
requirements:
|
107
|
-
- -
|
94
|
+
- - ">="
|
108
95
|
- !ruby/object:Gem::Version
|
109
96
|
version: '0'
|
110
97
|
- !ruby/object:Gem::Dependency
|
111
98
|
name: factory_girl
|
112
99
|
requirement: !ruby/object:Gem::Requirement
|
113
|
-
none: false
|
114
100
|
requirements:
|
115
|
-
- -
|
101
|
+
- - ">="
|
116
102
|
- !ruby/object:Gem::Version
|
117
103
|
version: '0'
|
118
104
|
type: :development
|
119
105
|
prerelease: false
|
120
106
|
version_requirements: !ruby/object:Gem::Requirement
|
121
|
-
none: false
|
122
107
|
requirements:
|
123
|
-
- -
|
108
|
+
- - ">="
|
124
109
|
- !ruby/object:Gem::Version
|
125
110
|
version: '0'
|
126
111
|
description: This library provides Ruby calls to interact with the Avalara Tax API
|
127
112
|
email:
|
128
|
-
- adam@
|
113
|
+
- adam@codeschool.com
|
129
114
|
executables: []
|
130
115
|
extensions: []
|
131
116
|
extra_rdoc_files: []
|
132
117
|
files:
|
133
|
-
- .gitignore
|
134
|
-
- .
|
135
|
-
- .
|
136
|
-
- .travis.yml
|
137
|
-
- Changelog.md
|
118
|
+
- ".gitignore"
|
119
|
+
- ".travis.yml"
|
120
|
+
- CHANGELOG.md
|
138
121
|
- Gemfile
|
139
122
|
- Gemfile.lock
|
140
123
|
- LICENSE
|
@@ -152,6 +135,8 @@ files:
|
|
152
135
|
- lib/avalara/request/invoice.rb
|
153
136
|
- lib/avalara/request/line.rb
|
154
137
|
- lib/avalara/response.rb
|
138
|
+
- lib/avalara/response/address.rb
|
139
|
+
- lib/avalara/response/address_line.rb
|
155
140
|
- lib/avalara/response/invoice.rb
|
156
141
|
- lib/avalara/response/message.rb
|
157
142
|
- lib/avalara/response/tax.rb
|
@@ -170,6 +155,8 @@ files:
|
|
170
155
|
- spec/fixtures/net/geographical_tax_no_sales.yml
|
171
156
|
- spec/fixtures/net/get_tax/failure.yml
|
172
157
|
- spec/fixtures/net/get_tax/success.yml
|
158
|
+
- spec/fixtures/net/validate_address/failure.yml
|
159
|
+
- spec/fixtures/net/validate_address/success_ambiguous.yml
|
173
160
|
- spec/models/avalara/configuration_spec.rb
|
174
161
|
- spec/models/avalara/request/address_spec.rb
|
175
162
|
- spec/models/avalara/request/detail_level_spec.rb
|
@@ -179,31 +166,31 @@ files:
|
|
179
166
|
- spec/spec_helper.rb
|
180
167
|
- spec/support/avalara.rb
|
181
168
|
- spec/support/factory_girl.rb
|
169
|
+
- spec/support/timeout_server.rb
|
182
170
|
- spec/support/vcr.rb
|
183
171
|
homepage: https://github.com/adamfortuna/avalara
|
184
172
|
licenses:
|
185
173
|
- MIT
|
174
|
+
metadata: {}
|
186
175
|
post_install_message:
|
187
176
|
rdoc_options: []
|
188
177
|
require_paths:
|
189
178
|
- lib
|
190
179
|
required_ruby_version: !ruby/object:Gem::Requirement
|
191
|
-
none: false
|
192
180
|
requirements:
|
193
|
-
- -
|
181
|
+
- - ">="
|
194
182
|
- !ruby/object:Gem::Version
|
195
183
|
version: '0'
|
196
184
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
197
|
-
none: false
|
198
185
|
requirements:
|
199
|
-
- -
|
186
|
+
- - ">="
|
200
187
|
- !ruby/object:Gem::Version
|
201
188
|
version: '0'
|
202
189
|
requirements: []
|
203
190
|
rubyforge_project:
|
204
|
-
rubygems_version:
|
191
|
+
rubygems_version: 2.6.4
|
205
192
|
signing_key:
|
206
|
-
specification_version:
|
193
|
+
specification_version: 4
|
207
194
|
summary: A Ruby interface to the Avalara Tax API
|
208
195
|
test_files:
|
209
196
|
- spec/avalara.yml.example
|
@@ -214,6 +201,8 @@ test_files:
|
|
214
201
|
- spec/fixtures/net/geographical_tax_no_sales.yml
|
215
202
|
- spec/fixtures/net/get_tax/failure.yml
|
216
203
|
- spec/fixtures/net/get_tax/success.yml
|
204
|
+
- spec/fixtures/net/validate_address/failure.yml
|
205
|
+
- spec/fixtures/net/validate_address/success_ambiguous.yml
|
217
206
|
- spec/models/avalara/configuration_spec.rb
|
218
207
|
- spec/models/avalara/request/address_spec.rb
|
219
208
|
- spec/models/avalara/request/detail_level_spec.rb
|
@@ -223,4 +212,6 @@ test_files:
|
|
223
212
|
- spec/spec_helper.rb
|
224
213
|
- spec/support/avalara.rb
|
225
214
|
- spec/support/factory_girl.rb
|
215
|
+
- spec/support/timeout_server.rb
|
226
216
|
- spec/support/vcr.rb
|
217
|
+
has_rdoc:
|
data/.ruby-gemset
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
avalara
|