avalara 0.1.1 → 0.2.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.
@@ -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
@@ -6,4 +6,6 @@ rvm:
6
6
  before_script:
7
7
  - cp spec/avalara.yml.example spec/avalara.yml
8
8
  notifications:
9
- email: false
9
+ email: false
10
+ before_install:
11
+ - gem install bundler
@@ -1,8 +1,13 @@
1
- # 0.1.1 - June 11, 2015 - Added license
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
- # 0.1.0 - June 11, 2015 - Ruby Support
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
- # 0.0.3 - October 4, 2013 - Updated multi_json gem
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
- # 0.0.2 - May 7, 2012 - Updated tests for test endpoint.
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
- # 0.0.1 - February 3, 2012 - Initial Release with get_tax call
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
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- avalara (0.1.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.1)
21
- httparty (0.13.5)
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.2)
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](http://github.com/adamfortuna)
103
+ * [James Cox](https://github.com/imajes)
104
104
  * [Dan Sosedoff](http://github.com/sosedoff)
105
+ * [Leo Correa](https://github.com/Tonkpils)
@@ -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@envylabs.com']
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}
@@ -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(uri,
68
- :headers => API.headers_for('0'),
69
- :query => {:saleamount => sales_amount},
70
- :basic_auth => authentication
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(uri,
83
- :body => invoice.to_json,
84
- :headers => API.headers_for(invoice.to_json.length),
85
- :basic_auth => authentication
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
- return case response.code
89
- when 200..299
90
- Response::Invoice.new(response)
91
- when 400..599
92
- raise ApiError.new(Response::Invoice.new(response))
93
- else
94
- raise ApiError.new(response)
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
  #
@@ -2,11 +2,13 @@
2
2
 
3
3
  module Avalara
4
4
  module Response
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'
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
@@ -1,5 +1,5 @@
1
1
  # encoding: UTF-8
2
2
 
3
3
  module Avalara
4
- VERSION = '0.1.1'
4
+ VERSION = '0.2.0'
5
5
  end
@@ -3,7 +3,7 @@
3
3
  request: !ruby/struct:VCR::Request
4
4
  method: :get
5
5
  uri: https://%{API_USERNAME}:%{API_PASSWORD}@development.avalara.net:443/1.0/tax/47.627935,-122.51702/get?saleamount=100
6
- body:
6
+ body:
7
7
  headers:
8
8
  accept:
9
9
  - application/json
@@ -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
@@ -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' }
@@ -14,4 +14,4 @@ RSpec.configure do |config|
14
14
  config.mock_with :rspec
15
15
  config.filter_run :focus => true
16
16
  config.run_all_when_everything_filtered = true
17
- end
17
+ end
@@ -35,4 +35,4 @@ end
35
35
 
36
36
  RSpec.configure do |config|
37
37
  config.extend ConfigurationSpecHelpers
38
- end
38
+ end
@@ -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.1.1
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: 2015-06-11 00:00:00.000000000 Z
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@envylabs.com
113
+ - adam@codeschool.com
129
114
  executables: []
130
115
  extensions: []
131
116
  extra_rdoc_files: []
132
117
  files:
133
- - .gitignore
134
- - .ruby-gemset
135
- - .ruby-version
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: 1.8.23.2
191
+ rubygems_version: 2.6.4
205
192
  signing_key:
206
- specification_version: 3
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:
@@ -1 +0,0 @@
1
- avalara