bcarpenter-active_shipping 0.0.2

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 (63) hide show
  1. data/CHANGELOG +23 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.markdown +173 -0
  4. data/Rakefile +52 -0
  5. data/VERSION +1 -0
  6. data/lib/active_shipping.rb +50 -0
  7. data/lib/active_shipping/lib/connection.rb +170 -0
  8. data/lib/active_shipping/lib/country.rb +319 -0
  9. data/lib/active_shipping/lib/error.rb +4 -0
  10. data/lib/active_shipping/lib/post_data.rb +22 -0
  11. data/lib/active_shipping/lib/posts_data.rb +47 -0
  12. data/lib/active_shipping/lib/requires_parameters.rb +16 -0
  13. data/lib/active_shipping/lib/utils.rb +18 -0
  14. data/lib/active_shipping/lib/validateable.rb +76 -0
  15. data/lib/active_shipping/shipping/base.rb +15 -0
  16. data/lib/active_shipping/shipping/carrier.rb +70 -0
  17. data/lib/active_shipping/shipping/carriers.rb +17 -0
  18. data/lib/active_shipping/shipping/carriers/bogus_carrier.rb +16 -0
  19. data/lib/active_shipping/shipping/carriers/fedex.rb +315 -0
  20. data/lib/active_shipping/shipping/carriers/shipwire.rb +167 -0
  21. data/lib/active_shipping/shipping/carriers/ups.rb +368 -0
  22. data/lib/active_shipping/shipping/carriers/usps.rb +420 -0
  23. data/lib/active_shipping/shipping/location.rb +100 -0
  24. data/lib/active_shipping/shipping/package.rb +144 -0
  25. data/lib/active_shipping/shipping/rate_estimate.rb +54 -0
  26. data/lib/active_shipping/shipping/rate_response.rb +19 -0
  27. data/lib/active_shipping/shipping/response.rb +49 -0
  28. data/lib/active_shipping/shipping/shipment_event.rb +14 -0
  29. data/lib/active_shipping/shipping/tracking_response.rb +22 -0
  30. data/lib/certs/cacert.pem +7815 -0
  31. data/lib/vendor/quantified/MIT-LICENSE +22 -0
  32. data/lib/vendor/quantified/README.markdown +49 -0
  33. data/lib/vendor/quantified/Rakefile +21 -0
  34. data/lib/vendor/quantified/init.rb +0 -0
  35. data/lib/vendor/quantified/lib/quantified.rb +6 -0
  36. data/lib/vendor/quantified/lib/quantified/attribute.rb +208 -0
  37. data/lib/vendor/quantified/lib/quantified/length.rb +20 -0
  38. data/lib/vendor/quantified/lib/quantified/mass.rb +19 -0
  39. data/lib/vendor/quantified/test/length_test.rb +92 -0
  40. data/lib/vendor/quantified/test/mass_test.rb +88 -0
  41. data/lib/vendor/quantified/test/test_helper.rb +2 -0
  42. data/lib/vendor/test_helper.rb +13 -0
  43. data/lib/vendor/xml_node/README +36 -0
  44. data/lib/vendor/xml_node/Rakefile +21 -0
  45. data/lib/vendor/xml_node/benchmark/bench_generation.rb +32 -0
  46. data/lib/vendor/xml_node/init.rb +1 -0
  47. data/lib/vendor/xml_node/lib/xml_node.rb +222 -0
  48. data/lib/vendor/xml_node/test/test_generating.rb +94 -0
  49. data/lib/vendor/xml_node/test/test_parsing.rb +43 -0
  50. data/test/remote/fedex_test.rb +140 -0
  51. data/test/remote/shipwire_test.rb +88 -0
  52. data/test/remote/ups_test.rb +187 -0
  53. data/test/remote/usps_test.rb +184 -0
  54. data/test/test_helper.rb +167 -0
  55. data/test/unit/base_test.rb +18 -0
  56. data/test/unit/carriers/fedex_test.rb +78 -0
  57. data/test/unit/carriers/shipwire_test.rb +130 -0
  58. data/test/unit/carriers/ups_test.rb +81 -0
  59. data/test/unit/carriers/usps_test.rb +170 -0
  60. data/test/unit/location_test.rb +46 -0
  61. data/test/unit/package_test.rb +65 -0
  62. data/test/unit/response_test.rb +10 -0
  63. metadata +123 -0
@@ -0,0 +1,184 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ class USPSTest < Test::Unit::TestCase
4
+
5
+ def setup
6
+ @packages = TestFixtures.packages
7
+ @locations = TestFixtures.locations
8
+ @carrier = USPS.new(fixtures(:usps))
9
+ end
10
+
11
+ def test_machinable_rate_discrepancy
12
+ assert_nothing_raised do
13
+ default_machinable_response = @carrier.find_rates(
14
+ Location.new(:zip => 83843),
15
+ Location.new(:zip => 70001),
16
+ Package.new(32, [12,6,2], :units => :imperial)
17
+ )
18
+ assert default_machinable_response.request =~ /<Machinable>TRUE<\/Machinable>/
19
+
20
+ explicit_non_machinable_response = @carrier.find_rates(
21
+ Location.new(:zip => 83843),
22
+ Location.new(:zip => 70001),
23
+ Package.new(32, [12,6,2], :units => :imperial, :machinable => false)
24
+ )
25
+ assert explicit_non_machinable_response.request =~ /<Machinable>FALSE<\/Machinable>/
26
+
27
+ assert_not_equal default_machinable_response.rates.map(&:price),
28
+ explicit_non_machinable_response.rates.map(&:price)
29
+ end
30
+ end
31
+
32
+ def test_zip_to_zip
33
+ assert_nothing_raised do
34
+ response = @carrier.find_rates(
35
+ Location.new(:zip => 40524),
36
+ Location.new(:zip => 40515),
37
+ Package.new(16, [12,6,2], :units => :imperial)
38
+ )
39
+ end
40
+ end
41
+
42
+ def test_just_country_given
43
+ assert_nothing_raised do
44
+ response = @carrier.find_rates(
45
+ @locations[:beverly_hills],
46
+ Location.new(:country => 'CZ'),
47
+ Package.new(100, [5,10,20])
48
+ )
49
+ end
50
+ end
51
+
52
+ def test_us_to_canada
53
+ response = nil
54
+ assert_nothing_raised do
55
+ response = @carrier.find_rates(
56
+ @locations[:beverly_hills],
57
+ @locations[:ottawa],
58
+ @packages.values_at(:wii),
59
+ :test => true
60
+ )
61
+ assert_not_equal [], response.rates.length
62
+ end
63
+ end
64
+
65
+ def test_domestic_rates_thoroughly
66
+ response = nil
67
+ assert_nothing_raised do
68
+ response = @carrier.find_rates(
69
+ @locations[:new_york],
70
+ @locations[:beverly_hills],
71
+ @packages.values_at(:book,:wii),
72
+ :test => true
73
+ )
74
+ end
75
+ assert response.success?, response.message
76
+ assert_instance_of Hash, response.params
77
+ assert_instance_of String, response.xml
78
+ assert_instance_of Array, response.rates
79
+ assert_not_equal [], response.rates
80
+
81
+ rate = response.rates.first
82
+ assert_equal 'USPS', rate.carrier
83
+ assert_equal 'USD', rate.currency
84
+ assert_instance_of Fixnum, rate.total_price
85
+ assert_instance_of Fixnum, rate.price
86
+ assert_instance_of String, rate.service_name
87
+ assert_instance_of String, rate.service_code
88
+ assert_instance_of Array, rate.package_rates
89
+ assert_equal @packages.values_at(:book, :wii), rate.packages
90
+
91
+ package_rate = rate.package_rates.first
92
+ assert_instance_of Hash, package_rate
93
+ assert_instance_of Package, package_rate[:package]
94
+ assert_not_nil package_rate[:rate]
95
+
96
+ other_than_two = response.rates.map(&:package_count).reject {|n| n == 2}
97
+ assert_equal [], other_than_two, "Some RateEstimates do not refer to the right number of packages (#{other_than_two.inspect})"
98
+
99
+
100
+ end
101
+
102
+ def test_international_thoroughly
103
+
104
+ response = nil
105
+ assert_nothing_raised do
106
+ response = @carrier.find_rates(
107
+ @locations[:beverly_hills],
108
+ @locations[:ottawa],
109
+ @packages.values_at(:book, :wii),
110
+ :test => true
111
+ )
112
+ end
113
+
114
+ assert response.success?, response.message
115
+ assert_instance_of Hash, response.params
116
+ assert_instance_of String, response.xml
117
+ assert_instance_of Array, response.rates
118
+ assert_not_equal [], response.rates
119
+
120
+ rate = response.rates.first
121
+ assert_equal 'USPS', rate.carrier
122
+ assert_equal 'USD', rate.currency
123
+ assert_instance_of Fixnum, rate.total_price
124
+ assert_instance_of Fixnum, rate.price
125
+ assert_instance_of String, rate.service_name
126
+ assert_instance_of String, rate.service_code
127
+ assert_instance_of Array, rate.package_rates
128
+ assert_equal @packages.values_at(:book, :wii), rate.packages
129
+
130
+ package_rate = rate.package_rates.first
131
+ assert_instance_of Hash, package_rate
132
+ assert_instance_of Package, package_rate[:package]
133
+ assert_not_nil package_rate[:rate]
134
+
135
+ other_than_two = response.rates.map(&:package_count).reject {|n| n == 2}
136
+ assert_equal [], other_than_two, "Some RateEstimates do not refer to the right number of packages (#{other_than_two.inspect})"
137
+
138
+ end
139
+
140
+ def test_bare_packages
141
+ response = nil
142
+ p = Package.new(0,0)
143
+ response = begin
144
+ @carrier.find_rates(
145
+ @locations[:beverly_hills], # imperial (U.S. origin)
146
+ @locations[:ottawa],
147
+ p,
148
+ :test => true
149
+ )
150
+ rescue ResponseError => e
151
+ e.response
152
+ end
153
+ assert response.success?, response.message
154
+ end
155
+
156
+ def test_valid_credentials
157
+ assert USPS.new(fixtures(:usps).merge(:test => true)).valid_credentials?
158
+ end
159
+
160
+ # Uncomment and switch out SPECIAL_COUNTRIES with some other batch to see which
161
+ # countries are currently working. Commented out here just because it's a lot of
162
+ # hits to their server at once:
163
+
164
+ # ALL_COUNTRIES = ActiveMerchant::Country.const_get('COUNTRIES').map {|c| c[:alpha2]}
165
+ # SPECIAL_COUNTRIES = USPS.const_get('COUNTRY_NAME_CONVERSIONS').keys.sort
166
+ # NORMAL_COUNTRIES = (ALL_COUNTRIES - SPECIAL_COUNTRIES)
167
+ #
168
+ # SPECIAL_COUNTRIES.each do |code|
169
+ # unless ActiveMerchant::Country.find(code).name == USPS.const_get('COUNTRY_NAME_CONVERSIONS')[code]
170
+ # define_method("test_country_#{code}") do
171
+ # response = nil
172
+ # begin
173
+ # response = @carrier.find_rates( @locations[:beverly_hills],
174
+ # Location.new(:country => code),
175
+ # @packages.values_at(:wii),
176
+ # :test => true)
177
+ # rescue Exception => e
178
+ # flunk(e.inspect + "\nrequest: " + @carrier.last_request)
179
+ # end
180
+ # assert_not_equal [], response.rates.length
181
+ # end
182
+ # end
183
+ # end
184
+ end
@@ -0,0 +1,167 @@
1
+ #!/usr/bin/env ruby
2
+ $:.unshift(File.dirname(__FILE__) + '/../lib')
3
+
4
+ require 'test/unit'
5
+ require 'active_shipping'
6
+ require 'mocha'
7
+
8
+ module Test
9
+ module Unit
10
+ class TestCase
11
+ include ActiveMerchant::Shipping
12
+
13
+ LOCAL_CREDENTIALS = ENV['HOME'] + '/.active_merchant/fixtures.yml' unless defined?(LOCAL_CREDENTIALS)
14
+ DEFAULT_CREDENTIALS = File.dirname(__FILE__) + '/fixtures.yml' unless defined?(DEFAULT_CREDENTIALS)
15
+
16
+ MODEL_FIXTURES = File.dirname(__FILE__) + '/fixtures/' unless defined?(MODEL_FIXTURES)
17
+
18
+ def all_fixtures
19
+ @@fixtures ||= load_fixtures
20
+ end
21
+
22
+ def fixtures(key)
23
+ data = all_fixtures[key] || raise(StandardError, "No fixture data was found for '#{key}'")
24
+
25
+ data.dup
26
+ end
27
+
28
+ def load_fixtures
29
+ file = File.exists?(LOCAL_CREDENTIALS) ? LOCAL_CREDENTIALS : DEFAULT_CREDENTIALS
30
+ yaml_data = YAML.load(File.read(file))
31
+
32
+ model_fixtures = Dir.glob(File.join(MODEL_FIXTURES,'**','*.yml'))
33
+ model_fixtures.each do |file|
34
+ name = File.basename(file, '.yml')
35
+ yaml_data[name] = YAML.load(File.read(file))
36
+ end
37
+
38
+ symbolize_keys(yaml_data)
39
+
40
+ yaml_data
41
+ end
42
+
43
+ def xml_fixture(path) # where path is like 'usps/beverly_hills_to_ottawa_response'
44
+ open(File.join(File.dirname(__FILE__),'fixtures','xml',"#{path}.xml")) {|f| f.read}
45
+ end
46
+
47
+ def symbolize_keys(hash)
48
+ return unless hash.is_a?(Hash)
49
+
50
+ hash.symbolize_keys!
51
+ hash.each{|k,v| symbolize_keys(v)}
52
+ end
53
+
54
+ end
55
+ end
56
+ end
57
+
58
+ module ActiveMerchant
59
+ module Shipping
60
+ module TestFixtures
61
+
62
+ mattr_reader :packages, :locations
63
+
64
+ @@packages = {
65
+ :just_ounces => Package.new(16, nil, :units => :imperial),
66
+ :just_grams => Package.new(1000, nil),
67
+ :all_imperial => Package.new(16, [1,8,12], :units => :imperial),
68
+ :all_metric => Package.new(1000, [2,20,40]),
69
+ :book => Package.new(250, [14, 19, 2]),
70
+ :wii => Package.new((7.5 * 16), [15, 10, 4.5], :units => :imperial, :value => 269.99, :currency => 'GBP'),
71
+ :poster => Package.new(100, [93,10], :cylinder => true),
72
+ :small_half_pound => Package.new(8, [1,1,1], :units => :imperial),
73
+ :big_half_pound => Package.new((16 * 50), [24,24,36], :units => :imperial),
74
+ :chocolate_stuff => Package.new(80, [2,6,12], :units => :imperial)
75
+ }
76
+
77
+ @@locations = {
78
+ :bare_ottawa => Location.new(:country => 'CA', :postal_code => 'K1P 1J1'),
79
+ :bare_beverly_hills => Location.new(:country => 'US', :zip => '90210'),
80
+ :ottawa => Location.new( :country => 'CA',
81
+ :province => 'ON',
82
+ :city => 'Ottawa',
83
+ :address1 => '110 Laurier Avenue West',
84
+ :postal_code => 'K1P 1J1',
85
+ :phone => '1-613-580-2400',
86
+ :fax => '1-613-580-2495'),
87
+ :beverly_hills => Location.new(
88
+ :country => 'US',
89
+ :state => 'CA',
90
+ :city => 'Beverly Hills',
91
+ :address1 => '455 N. Rexford Dr.',
92
+ :address2 => '3rd Floor',
93
+ :zip => '90210',
94
+ :phone => '1-310-285-1013',
95
+ :fax => '1-310-275-8159'),
96
+ :real_home_as_commercial => Location.new(
97
+ :country => 'US',
98
+ :city => 'Tampa',
99
+ :state => 'FL',
100
+ :address1 => '7926 Woodvale Circle',
101
+ :zip => '33615',
102
+ :address_type => 'commercial'), # means that UPS will default to commercial if it doesn't know
103
+ :fake_home_as_commercial => Location.new(
104
+ :country => 'US',
105
+ :state => 'FL',
106
+ :address1 => '123 fake st.',
107
+ :zip => '33615',
108
+ :address_type => 'commercial'),
109
+ :real_google_as_commercial => Location.new(
110
+ :country => 'US',
111
+ :city => 'Mountain View',
112
+ :state => 'CA',
113
+ :address1 => '1600 Amphitheatre Parkway',
114
+ :zip => '94043',
115
+ :address_type => 'commercial'),
116
+ :real_google_as_residential => Location.new(
117
+ :country => 'US',
118
+ :city => 'Mountain View',
119
+ :state => 'CA',
120
+ :address1 => '1600 Amphitheatre Parkway',
121
+ :zip => '94043',
122
+ :address_type => 'residential'), # means that will default to residential if it doesn't know
123
+ :fake_google_as_commercial => Location.new(
124
+ :country => 'US',
125
+ :city => 'Mountain View',
126
+ :state => 'CA',
127
+ :address1 => '123 bogusland dr.',
128
+ :zip => '94043',
129
+ :address_type => 'commercial'),
130
+ :fake_google_as_residential => Location.new(
131
+ :country => 'US',
132
+ :city => 'Mountain View',
133
+ :state => 'CA',
134
+ :address1 => '123 bogusland dr.',
135
+ :zip => '94043',
136
+ :address_type => 'residential'), # means that will default to residential if it doesn't know
137
+ :fake_home_as_residential => Location.new(
138
+ :country => 'US',
139
+ :state => 'FL',
140
+ :address1 => '123 fake st.',
141
+ :zip => '33615',
142
+ :address_type => 'residential'),
143
+ :real_home_as_residential => Location.new(
144
+ :country => 'US',
145
+ :city => 'Tampa',
146
+ :state => 'FL',
147
+ :address1 => '7926 Woodvale Circle',
148
+ :zip => '33615',
149
+ :address_type => 'residential'),
150
+ :london => Location.new(
151
+ :country => 'GB',
152
+ :city => 'London',
153
+ :address1 => '170 Westminster Bridge Rd.',
154
+ :zip => 'SE1 7RW'),
155
+ :new_york => Location.new(
156
+ :country => 'US',
157
+ :city => 'New York',
158
+ :state => 'NY',
159
+ :address1 => '780 3rd Avenue',
160
+ :address2 => 'Suite 2601',
161
+ :zip => '10017')
162
+
163
+ }
164
+
165
+ end
166
+ end
167
+ end
@@ -0,0 +1,18 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ class BaseTest < Test::Unit::TestCase
4
+ include ActiveMerchant::Shipping
5
+
6
+ def test_get_usps_by_string
7
+ assert_equal USPS, Base.carrier('usps')
8
+ assert_equal USPS, Base.carrier('USPS')
9
+ end
10
+
11
+ def test_get_usps_by_name
12
+ assert_equal USPS, Base.carrier(:usps)
13
+ end
14
+
15
+ def test_get_unknown_carrier
16
+ assert_raise(NameError){ Base.carrier(:polar_north) }
17
+ end
18
+ end
@@ -0,0 +1,78 @@
1
+ require File.dirname(__FILE__) + '/../../test_helper'
2
+
3
+ class FedExTest < Test::Unit::TestCase
4
+ def setup
5
+ @packages = TestFixtures.packages
6
+ @locations = TestFixtures.locations
7
+ @carrier = FedEx.new(:key => '1111', :password => '2222', :account => '3333', :login => '4444')
8
+ end
9
+
10
+ def test_initialize_options_requirements
11
+ assert_raises ArgumentError do FedEx.new end
12
+ assert_raises ArgumentError do FedEx.new(:login => '999999999') end
13
+ assert_raises ArgumentError do FedEx.new(:password => '7777777') end
14
+ assert_nothing_raised { FedEx.new(:key => '999999999', :password => '7777777', :account => '123', :login => '123')}
15
+ end
16
+
17
+ # def test_no_rates_response
18
+ # @carrier.expects(:commit).returns(xml_fixture('fedex/empty_response'))
19
+ #
20
+ # response = @carrier.find_rates(
21
+ # @locations[:ottawa],
22
+ # @locations[:beverly_hills],
23
+ # @packages.values_at(:book, :wii)
24
+ # )
25
+ # assert_equal "WARNING - 556: There are no valid services available. ", response.message
26
+ # end
27
+
28
+ def test_find_tracking_info_should_return_a_tracking_response
29
+ @carrier.expects(:commit).returns(xml_fixture('fedex/tracking_response'))
30
+ assert_instance_of ActiveMerchant::Shipping::TrackingResponse, @carrier.find_tracking_info('077973360403984', :test => true)
31
+ end
32
+
33
+ def test_find_tracking_info_should_parse_response_into_correct_number_of_shipment_events
34
+ @carrier.expects(:commit).returns(xml_fixture('fedex/tracking_response'))
35
+ response = @carrier.find_tracking_info('077973360403984', :test => true)
36
+ assert_equal 7, response.shipment_events.size
37
+ end
38
+
39
+ def test_find_tracking_info_should_return_shipment_events_in_ascending_chronological_order
40
+ @carrier.expects(:commit).returns(xml_fixture('fedex/tracking_response'))
41
+ response = @carrier.find_tracking_info('077973360403984', :test => true)
42
+ assert_equal response.shipment_events.map(&:time).sort, response.shipment_events.map(&:time)
43
+ end
44
+
45
+ def test_building_request_and_parsing_response
46
+ expected_request = xml_fixture('fedex/ottawa_to_beverly_hills_rate_request')
47
+ mock_response = xml_fixture('fedex/ottawa_to_beverly_hills_rate_response')
48
+ Time.any_instance.expects(:to_xml_value).returns("2009-07-20T12:01:55-04:00")
49
+
50
+ @carrier.expects(:commit).with {|request, test_mode| Hash.from_xml(request) == Hash.from_xml(expected_request) && test_mode}.returns(mock_response)
51
+ response = @carrier.find_rates( @locations[:ottawa],
52
+ @locations[:beverly_hills],
53
+ @packages.values_at(:book, :wii), :test => true)
54
+ assert_equal ["FedEx Ground"], response.rates.map(&:service_name)
55
+ assert_equal [3836], response.rates.map(&:price)
56
+
57
+ assert response.success?, response.message
58
+ assert_instance_of Hash, response.params
59
+ assert_instance_of String, response.xml
60
+ assert_instance_of Array, response.rates
61
+ assert_not_equal [], response.rates
62
+
63
+ rate = response.rates.first
64
+ assert_equal 'FedEx', rate.carrier
65
+ assert_equal 'CAD', rate.currency
66
+ assert_instance_of Fixnum, rate.total_price
67
+ assert_instance_of Fixnum, rate.price
68
+ assert_instance_of String, rate.service_name
69
+ assert_instance_of String, rate.service_code
70
+ assert_instance_of Array, rate.package_rates
71
+ assert_equal @packages.values_at(:book, :wii), rate.packages
72
+
73
+ package_rate = rate.package_rates.first
74
+ assert_instance_of Hash, package_rate
75
+ assert_instance_of Package, package_rate[:package]
76
+ assert_nil package_rate[:rate]
77
+ end
78
+ end