public
Description: Shipping API extension for Active Merchant.
Clone URL: git://github.com/Shopify/active_shipping.git
Search Repo:
* Better residential/commercial behaviour + UPS test case
* fixtures now in YAML
* TestCase#xml_logs method for convenient exploration
N.B.: UPS requests will now include the ResidentialAddressIndicator 
element by default, unless the destination specifically has the new 
Location#address_type == 'commercial'
jamesmacaulay (author)
Fri Jun 20 14:04:54 -0700 2008
commit  c5e8b1f78d76e667c83ef100757c1dafa75e08f4
tree    73ab081eaf6b06dc045049d2f9a72e06605a7a48
parent  c9d609983956292c8ea58289857ae714471b54c7
...
27
28
29
 
30
31
32
...
27
28
29
30
31
32
33
0
@@ -27,6 +27,7 @@ $:.unshift File.dirname(__FILE__)
0
 
0
 require 'rubygems'
0
 require 'active_support'
0
+require 'ftools'
0
 
0
 require 'vendor/xml_node/lib/xml_node'
0
 
...
199
200
201
202
 
203
204
205
...
199
200
201
 
202
203
204
205
0
@@ -199,7 +199,7 @@ module ActiveMerchant
0
               # StateProvinceCode required for negotiated rates but not otherwise, for some reason
0
             address << XmlNode.new("PostalCode", location.postal_code) unless location.postal_code.blank?
0
             address << XmlNode.new("CountryCode", location.country_code(:alpha2)) unless location.country_code(:alpha2).blank?
0
- address << XmlNode.new("ResidentialAddressIndicator", true) if location.residential?
0
+ address << XmlNode.new("ResidentialAddressIndicator", true) unless location.commercial? # the default should be that UPS returns residential rates for destinations that it doesn't know about
0
             # not implemented: Shipment/(Shipper|ShipTo|ShipFrom)/Address/ResidentialAddressIndicator element
0
           end
0
         end
...
32
33
34
35
 
 
36
37
38
...
64
65
66
67
 
68
69
70
...
72
73
74
75
76
77
78
79
80
81
 
 
82
83
84
...
32
33
34
 
35
36
37
38
39
...
65
66
67
 
68
69
70
71
...
73
74
75
 
 
 
 
 
 
 
76
77
78
79
80
0
@@ -32,7 +32,8 @@ module ActiveMerchant #:nodoc:
0
         @address3 = options[:address3]
0
         @phone = options[:phone]
0
         @fax = options[:fax]
0
- @address_type = %{residential commercial}.include?(options[:address_type].to_s) ? options[:address_type] : raise ArgumentError.new('address_type must be either "residential" or "commercial"')
0
+ raise ArgumentError.new('address_type must be either "residential" or "commercial"') if options[:address_type] and not (["residential", "commercial", ""]).include?(options[:address_type].to_s)
0
+ @address_type = options[:address_type].nil? ? nil : options[:address_type].to_s
0
       end
0
       
0
       def self.from(object, options={})
0
@@ -64,7 +65,7 @@ module ActiveMerchant #:nodoc:
0
             end
0
           end
0
         end
0
- attributes.delete(:address_type) unless %{residential commercial}.include?(attributes[:address_type].to_s)
0
+ attributes.delete(:address_type) unless %w{residential commercial}.include?(attributes[:address_type].to_s)
0
         self.new(attributes.update(options))
0
       end
0
       
0
@@ -72,13 +73,8 @@ module ActiveMerchant #:nodoc:
0
         @country.nil? ? nil : @country.code(format).first.value
0
       end
0
       
0
- def residential?
0
- @address_type == 'residential'
0
- end
0
-
0
- def commercial?
0
- @address_type == 'commercial'
0
- end
0
+ def residential?; (@address_type == 'residential') end
0
+ def commercial?; (@address_type == 'commercial') end
0
       
0
       def to_s
0
         prettyprint.gsub(/\n/, ' ')
...
4
5
6
7
8
 
 
9
10
11
...
73
74
75
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76
77
...
4
5
6
 
 
7
8
9
10
11
...
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
0
@@ -4,8 +4,8 @@ class UPSTest < Test::Unit::TestCase
0
   include ActiveMerchant::Shipping
0
   
0
   def setup
0
- @packages = ActiveMerchant::Shipping::TestFixtures.packages.dup
0
- @locations = ActiveMerchant::Shipping::TestFixtures.locations.dup
0
+ @packages = fixtures(:packages)
0
+ @locations = fixtures(:locations)
0
     @carrier = UPS.new(fixtures(:ups))
0
   end
0
   
0
@@ -73,4 +73,51 @@ class UPSTest < Test::Unit::TestCase
0
     end
0
     assert response.success?, response.message
0
   end
0
+
0
+ def test_different_rates_for_residential_and_commercial_destinations
0
+ responses = {}
0
+ locations = [
0
+ :real_home_as_residential, :real_home_as_commercial,
0
+ :fake_home_as_residential, :fake_home_as_commercial,
0
+ :real_google_as_residential, :real_google_as_commercial,
0
+ :fake_google_as_residential, :fake_google_as_commercial
0
+ ]
0
+
0
+ locations.each do |location|
0
+ responses[location] = @carrier.find_rates( @locations[:beverly_hills],
0
+ @locations[location],
0
+ @packages.values_at(:chocolate_stuff))
0
+ #xml_logs responses[location], :name => location.to_s
0
+ end
0
+
0
+ prices_of = lambda {|sym| responses[sym].rates.map(&:price)}
0
+
0
+ # this is how UPS does things...
0
+ # if it's a real residential address and UPS knows it, then they return
0
+ # residential rates whether or not we have the ResidentialAddressIndicator:
0
+ assert_equal prices_of.call(:real_home_as_residential), prices_of.call(:real_home_as_commercial)
0
+
0
+ # if UPS doesn't know about the address, and we HAVE the ResidentialAddressIndicator,
0
+ # then UPS will default to residential rates:
0
+ assert_equal prices_of.call(:real_home_as_residential), prices_of.call(:fake_home_as_residential)
0
+
0
+ # if UPS doesn't know about the address, and we DON'T have the ResidentialAddressIndicator,
0
+ # then UPS will default to commercial rates:
0
+ assert_not_equal prices_of.call(:fake_home_as_residential), prices_of.call(:fake_home_as_commercial)
0
+ assert prices_of.call(:fake_home_as_residential).first > prices_of.call(:fake_home_as_commercial).first
0
+
0
+
0
+ # if it's a real commercial address and UPS knows it, then they return
0
+ # commercial rates whether or not we have the ResidentialAddressIndicator:
0
+ assert_equal prices_of.call(:real_google_as_commercial), prices_of.call(:real_google_as_residential)
0
+
0
+ # if UPS doesn't know about the address, and we DON'T have the ResidentialAddressIndicator,
0
+ # then UPS will default to commercial rates:
0
+ assert_equal prices_of.call(:real_google_as_commercial), prices_of.call(:fake_google_as_commercial)
0
+
0
+ # if UPS doesn't know about the address, and we HAVE the ResidentialAddressIndicator,
0
+ # then UPS will default to residential rates:
0
+ assert_not_equal prices_of.call(:fake_google_as_commercial), prices_of.call(:fake_google_as_residential)
0
+ assert prices_of.call(:fake_home_as_residential).first > prices_of.call(:fake_home_as_commercial).first
0
+ end
0
 end
0
\ No newline at end of file
...
4
5
6
7
8
 
 
9
10
11
...
4
5
6
 
 
7
8
9
10
11
0
@@ -4,8 +4,8 @@ class USPSTest < Test::Unit::TestCase
0
   include ActiveMerchant::Shipping
0
   
0
   def setup
0
- @packages = ActiveMerchant::Shipping::TestFixtures.packages.dup
0
- @locations = ActiveMerchant::Shipping::TestFixtures.locations.dup
0
+ @packages = fixtures(:packages)
0
+ @locations = fixtures(:locations)
0
     @carrier = USPS.new(fixtures(:usps))
0
     
0
   end
...
20
21
22
 
 
23
24
25
...
34
35
36
 
 
 
 
 
 
 
37
38
39
...
49
50
51
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
53
54
...
90
91
92
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
93
94
95
...
20
21
22
23
24
25
26
27
...
36
37
38
39
40
41
42
43
44
45
46
47
48
...
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
...
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
0
@@ -20,6 +20,8 @@ module Test
0
       
0
       LOCAL_CREDENTIALS = ENV['HOME'] + '/.active_merchant/fixtures.yml' unless defined?(LOCAL_CREDENTIALS)
0
       DEFAULT_CREDENTIALS = File.dirname(__FILE__) + '/fixtures.yml' unless defined?(DEFAULT_CREDENTIALS)
0
+
0
+ MODEL_FIXTURES = File.dirname(__FILE__) + '/fixtures/' unless defined?(MODEL_FIXTURES)
0
 
0
       def all_fixtures
0
         @@fixtures ||= load_fixtures
0
@@ -34,6 +36,13 @@ module Test
0
       def load_fixtures
0
         file = File.exists?(LOCAL_CREDENTIALS) ? LOCAL_CREDENTIALS : DEFAULT_CREDENTIALS
0
         yaml_data = YAML.load(File.read(file))
0
+
0
+ model_fixtures = Dir.glob(File.join(MODEL_FIXTURES,'**','*.yml'))
0
+ model_fixtures.each do |file|
0
+ name = File.basename(file, '.yml')
0
+ yaml_data[name] = YAML.load(File.read(file))
0
+ end
0
+
0
         symbolize_keys(yaml_data)
0
       
0
         yaml_data
0
@@ -49,6 +58,24 @@ module Test
0
         hash.symbolize_keys!
0
         hash.each{|k,v| symbolize_keys(v)}
0
       end
0
+
0
+ def xml_logs(response_object, options={})
0
+ name = options[:name] || Time.new.strftime('%Y%m%d%H%M%S')
0
+ carrier_name = @carrier.name rescue ''
0
+ path = options[:path] || File.join(ENV['HOME'], '.active_merchant', 'shipping', 'logs', carrier_name)
0
+ File.makedirs(path)
0
+ methods = {'request' => 'request', 'response' => 'xml'}
0
+ methods.each do |suffix, method|
0
+ file = File.join(path, ([name,suffix].join('_') + '.xml'))
0
+ i = 0
0
+ while File.exist?(file) do
0
+ file = File.join(path, ([name + (i += 1).to_s,suffix].join('_') + '.xml'))
0
+ end
0
+ File.open(file, 'w+') do |file|
0
+ file.puts response_object.send(method)
0
+ end
0
+ end
0
+ end
0
     end
0
   end
0
 end
0
@@ -90,6 +117,60 @@ module ActiveMerchant
0
                                       :zip => '90210',
0
                                       :phone => '1-310-285-1013',
0
                                       :fax => '1-310-275-8159'),
0
+ :real_home_as_commercial => Location.new(
0
+ :country => 'US',
0
+ :city => 'Tampa',
0
+ :state => 'FL',
0
+ :address1 => '7926 Woodvale Circle',
0
+ :zip => '33615',
0
+ :address_type => 'commercial'), # means that UPS will default to commercial if it doesn't know
0
+ :fake_home_as_commercial => Location.new(
0
+ :country => 'US',
0
+ :state => 'FL',
0
+ :address1 => '123 fake st.',
0
+ :zip => '33615',
0
+ :address_type => 'commercial'),
0
+ :real_google_as_commercial => Location.new(
0
+ :country => 'US',
0
+ :city => 'Mountain View',
0
+ :state => 'CA',
0
+ :address1 => '1600 Amphitheatre Parkway',
0
+ :zip => '94043',
0
+ :address_type => 'commercial'),
0
+ :real_google_as_residential => Location.new(
0
+ :country => 'US',
0
+ :city => 'Mountain View',
0
+ :state => 'CA',
0
+ :address1 => '1600 Amphitheatre Parkway',
0
+ :zip => '94043',
0
+ :address_type => 'residential'), # means that will default to residential if it doesn't know
0
+ :fake_google_as_commercial => Location.new(
0
+ :country => 'US',
0
+ :city => 'Mountain View',
0
+ :state => 'CA',
0
+ :address1 => '123 bogusland dr.',
0
+ :zip => '94043',
0
+ :address_type => 'commercial'),
0
+ :fake_google_as_residential => Location.new(
0
+ :country => 'US',
0
+ :city => 'Mountain View',
0
+ :state => 'CA',
0
+ :address1 => '123 bogusland dr.',
0
+ :zip => '94043',
0
+ :address_type => 'residential'), # means that will default to residential if it doesn't know
0
+ :fake_home_as_residential => Location.new(
0
+ :country => 'US',
0
+ :state => 'FL',
0
+ :address1 => '123 fake st.',
0
+ :zip => '33615',
0
+ :address_type => 'residential'),
0
+ :real_home_as_residential => Location.new(
0
+ :country => 'US',
0
+ :city => 'Tampa',
0
+ :state => 'FL',
0
+ :address1 => '7926 Woodvale Circle',
0
+ :zip => '33615',
0
+ :address_type => 'residential'),
0
         :london => Location.new(
0
                                       :country => 'GB',
0
                                       :city => 'London',
...
4
5
6
7
8
 
 
9
10
11
...
4
5
6
 
 
7
8
9
10
11
0
@@ -4,8 +4,8 @@ class UPSTest < Test::Unit::TestCase
0
   include ActiveMerchant::Shipping
0
   
0
   def setup
0
- @packages = ActiveMerchant::Shipping::TestFixtures.packages.dup
0
- @locations = ActiveMerchant::Shipping::TestFixtures.locations.dup
0
+ @packages = fixtures(:packages)
0
+ @locations = fixtures(:locations)
0
     @carrier = UPS.new(fixtures(:ups))
0
   end
0
   
...
4
5
6
7
8
 
 
9
10
11
...
4
5
6
 
 
7
8
9
10
11
0
@@ -4,8 +4,8 @@ class USPSTest < Test::Unit::TestCase
0
   include ActiveMerchant::Shipping
0
   
0
   def setup
0
- @packages = ActiveMerchant::Shipping::TestFixtures.packages.dup
0
- @locations = ActiveMerchant::Shipping::TestFixtures.locations.dup
0
+ @packages = fixtures(:packages)
0
+ @locations = fixtures(:locations)
0
     @carrier = USPS.new(fixtures(:usps))
0
     @international_rate_responses = {
0
       :vanilla => xml_fixture('usps/beverly_hills_to_ottawa_book_rate_response')
...
19
20
21
22
 
 
23
24
25
...
30
31
32
 
33
34
35
...
19
20
21
 
22
23
24
25
26
...
31
32
33
34
35
36
37
0
@@ -19,7 +19,8 @@ class LocationTest < Test::Unit::TestCase
0
               :town => 'Perth',
0
               :address => '66 Gregory Ave.',
0
               :phone => '515-555-1212',
0
- :fax_number => 'none to speak of'
0
+ :fax_number => 'none to speak of',
0
+ :address_type => :commercial
0
             }
0
     location = Location.from(hash)
0
     
0
@@ -30,6 +31,7 @@ class LocationTest < Test::Unit::TestCase
0
     assert_equal hash[:address], location.address1
0
     assert_equal hash[:phone], location.phone
0
     assert_equal hash[:fax_number], location.fax
0
+ assert_equal hash[:address_type].to_s, location.address_type
0
   end
0
   
0
   def to_s
...
22
23
24
25
 
26
27
28
...
22
23
24
 
25
26
27
28
0
@@ -22,7 +22,7 @@ class PackageTest < Test::Unit::TestCase
0
                                           
0
       @bare_info_package = Package.new(nil,nil)
0
       
0
- @packages = ActiveMerchant::Shipping::TestFixtures.packages.dup
0
+ @packages = fixtures(:packages)
0
   end
0
 
0
   def test_initialize

Comments

    No one has commented yet.