active_shipping 1.0.0.pre2 → 1.0.0.pre3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (187) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/.gitignore +12 -0
  5. data/.travis.yml +14 -0
  6. data/.yardopts +14 -0
  7. data/Gemfile +3 -0
  8. data/Gemfile.activesupport32 +4 -0
  9. data/Gemfile.activesupport40 +4 -0
  10. data/Gemfile.activesupport41 +4 -0
  11. data/Gemfile.activesupport42 +4 -0
  12. data/Rakefile +23 -0
  13. data/active_shipping.gemspec +32 -0
  14. data/lib/active_shipping.rb +1 -1
  15. data/lib/active_shipping/carrier.rb +1 -1
  16. data/lib/active_shipping/carriers/shipwire.rb +32 -35
  17. data/lib/active_shipping/carriers/ups.rb +2 -2
  18. data/lib/active_shipping/carriers/usps.rb +103 -101
  19. data/lib/active_shipping/label_response.rb +1 -1
  20. data/lib/active_shipping/rate_estimate.rb +76 -15
  21. data/lib/active_shipping/rate_response.rb +20 -0
  22. data/lib/active_shipping/response.rb +17 -0
  23. data/lib/active_shipping/shipment_packer.rb +2 -2
  24. data/lib/active_shipping/shipping_response.rb +24 -2
  25. data/lib/active_shipping/tracking_response.rb +65 -17
  26. data/lib/active_shipping/version.rb +1 -1
  27. data/shipit.rubygems.yml +1 -0
  28. data/test/credentials.yml +47 -0
  29. data/test/fixtures/files/label1.pdf +0 -0
  30. data/test/fixtures/files/ups-shipping-label.gif +0 -0
  31. data/test/fixtures/json/newzealandpost/domestic_book.json +1 -0
  32. data/test/fixtures/json/newzealandpost/domestic_default.json +1 -0
  33. data/test/fixtures/json/newzealandpost/domestic_error.json +1 -0
  34. data/test/fixtures/json/newzealandpost/domestic_poster.json +1 -0
  35. data/test/fixtures/json/newzealandpost/domestic_small_half_pound.json +1 -0
  36. data/test/fixtures/json/newzealandpost/international_book.json +1 -0
  37. data/test/fixtures/json/newzealandpost/international_new_zealand_wii.json +1 -0
  38. data/test/fixtures/json/newzealandpost/international_small_half_pound.json +1 -0
  39. data/test/fixtures/json/newzealandpost/international_wii.json +1 -0
  40. data/test/fixtures/xml/canadapost/example_request.xml +25 -0
  41. data/test/fixtures/xml/canadapost/example_response.xml +130 -0
  42. data/test/fixtures/xml/canadapost/example_response_error.xml +16 -0
  43. data/test/fixtures/xml/canadapost/example_response_french.xml +122 -0
  44. data/test/fixtures/xml/canadapost/example_response_with_nil_value.xml +164 -0
  45. data/test/fixtures/xml/canadapost/example_response_with_postal_outlet.xml +155 -0
  46. data/test/fixtures/xml/canadapost/example_response_with_postal_outlet_french.xml +274 -0
  47. data/test/fixtures/xml/canadapost/example_response_with_strange_delivery_date.xml +130 -0
  48. data/test/fixtures/xml/canadapost_pws/dnc_tracking_details_en.xml +112 -0
  49. data/test/fixtures/xml/canadapost_pws/merchant_details_error.xml +7 -0
  50. data/test/fixtures/xml/canadapost_pws/merchant_details_response.xml +7 -0
  51. data/test/fixtures/xml/canadapost_pws/option_response.xml +13 -0
  52. data/test/fixtures/xml/canadapost_pws/option_response_no_conflicts.xml +7 -0
  53. data/test/fixtures/xml/canadapost_pws/rates_info.xml +190 -0
  54. data/test/fixtures/xml/canadapost_pws/rates_info_error.xml +7 -0
  55. data/test/fixtures/xml/canadapost_pws/receipt_response.xml +42 -0
  56. data/test/fixtures/xml/canadapost_pws/receipt_response_no_priced_options.xml +36 -0
  57. data/test/fixtures/xml/canadapost_pws/register_token_error.xml +7 -0
  58. data/test/fixtures/xml/canadapost_pws/register_token_response.xml +3 -0
  59. data/test/fixtures/xml/canadapost_pws/service_options_response.xml +42 -0
  60. data/test/fixtures/xml/canadapost_pws/services_error.xml +6 -0
  61. data/test/fixtures/xml/canadapost_pws/services_response.xml +32 -0
  62. data/test/fixtures/xml/canadapost_pws/shipment_domestic.xml +69 -0
  63. data/test/fixtures/xml/canadapost_pws/shipment_response.xml +20 -0
  64. data/test/fixtures/xml/canadapost_pws/shipment_us.xml +69 -0
  65. data/test/fixtures/xml/canadapost_pws/tracking_details_en.xml +152 -0
  66. data/test/fixtures/xml/canadapost_pws/tracking_details_en_error.xml +7 -0
  67. data/test/fixtures/xml/canadapost_pws/tracking_details_en_undelivered.xml +116 -0
  68. data/test/fixtures/xml/canadapost_pws/tracking_details_fr.xml +156 -0
  69. data/test/fixtures/xml/canadapost_pws/tracking_details_no_expected_delivery_date.xml +40 -0
  70. data/test/fixtures/xml/fedex/freight_rate_request.xml +82 -0
  71. data/test/fixtures/xml/fedex/freight_rate_response.xml +506 -0
  72. data/test/fixtures/xml/fedex/invalid_fedex_reply.xml +27 -0
  73. data/test/fixtures/xml/fedex/ottawa_to_beverly_hills_commercial_rate_request.xml +79 -0
  74. data/test/fixtures/xml/fedex/ottawa_to_beverly_hills_rate_request.xml +80 -0
  75. data/test/fixtures/xml/fedex/ottawa_to_beverly_hills_rate_response.xml +214 -0
  76. data/test/fixtures/xml/fedex/raterequest_reply.xml +213 -0
  77. data/test/fixtures/xml/fedex/reply_without_notifications.xml +185 -0
  78. data/test/fixtures/xml/fedex/tracking_request.xml +27 -0
  79. data/test/fixtures/xml/fedex/tracking_response.xml +151 -0
  80. data/test/fixtures/xml/fedex/tracking_response_empty_destination.xml +76 -0
  81. data/test/fixtures/xml/fedex/tracking_response_no_destination.xml +139 -0
  82. data/test/fixtures/xml/fedex/tracking_response_no_ship_time.xml +150 -0
  83. data/test/fixtures/xml/fedex/tracking_response_with_estimated_delivery_date.xml +95 -0
  84. data/test/fixtures/xml/fedex/tracking_response_with_shipper_address.xml +71 -0
  85. data/test/fixtures/xml/fedex/unknown_fedex_document_reply.xml +3 -0
  86. data/test/fixtures/xml/kunaki/invalid_state_response.xml +3 -0
  87. data/test/fixtures/xml/kunaki/no_valid_items_response.xml +3 -0
  88. data/test/fixtures/xml/kunaki/successful_rates_response.xml +3 -0
  89. data/test/fixtures/xml/kunaki/unsuccessful_rates_response.xml +9 -0
  90. data/test/fixtures/xml/shipwire/international_rates_response.xml +17 -0
  91. data/test/fixtures/xml/shipwire/new_carrier_rate_response.xml +18 -0
  92. data/test/fixtures/xml/shipwire/no_rates_response.xml +7 -0
  93. data/test/fixtures/xml/shipwire/rates_response.xml +36 -0
  94. data/test/fixtures/xml/shipwire/rates_response_no_estimate.xml +14 -0
  95. data/test/fixtures/xml/stamps/authenticate_user_request.xml +15 -0
  96. data/test/fixtures/xml/stamps/authenticate_user_response.xml +10 -0
  97. data/test/fixtures/xml/stamps/cleanse_address_request.xml +19 -0
  98. data/test/fixtures/xml/stamps/cleanse_address_response.xml +27 -0
  99. data/test/fixtures/xml/stamps/create_indicium_request.xml +69 -0
  100. data/test/fixtures/xml/stamps/create_indicium_response.xml +40 -0
  101. data/test/fixtures/xml/stamps/expired_authenticator_response.xml +15 -0
  102. data/test/fixtures/xml/stamps/get_account_info_request.xml +11 -0
  103. data/test/fixtures/xml/stamps/get_account_info_response.xml +36 -0
  104. data/test/fixtures/xml/stamps/get_purchase_status_request.xml +12 -0
  105. data/test/fixtures/xml/stamps/get_purchase_status_response.xml +16 -0
  106. data/test/fixtures/xml/stamps/get_rates_request.xml +19 -0
  107. data/test/fixtures/xml/stamps/get_rates_response.xml +351 -0
  108. data/test/fixtures/xml/stamps/purchase_postage_request.xml +13 -0
  109. data/test/fixtures/xml/stamps/purchase_postage_response.xml +17 -0
  110. data/test/fixtures/xml/stamps/track_shipment_request.xml +12 -0
  111. data/test/fixtures/xml/stamps/track_shipment_response.xml +45 -0
  112. data/test/fixtures/xml/ups/delivered_shipment_with_refund.xml +290 -0
  113. data/test/fixtures/xml/ups/delivered_shipment_without_events_tracking_response.xml +62 -0
  114. data/test/fixtures/xml/ups/example_tracking_response.xml +53 -0
  115. data/test/fixtures/xml/ups/in_transit_shipment.xml +183 -0
  116. data/test/fixtures/xml/ups/out_for_delivery_shipment.xml +165 -0
  117. data/test/fixtures/xml/ups/shipment_accept_response.xml +42 -0
  118. data/test/fixtures/xml/ups/shipment_confirm_response.xml +33 -0
  119. data/test/fixtures/xml/ups/shipment_from_tiger_direct.xml +222 -0
  120. data/test/fixtures/xml/ups/test_real_home_as_residential_destination_response.xml +1 -0
  121. data/test/fixtures/xml/ups/test_real_home_as_residential_destination_response_with_insured.xml +289 -0
  122. data/test/fixtures/xml/ups/test_real_home_as_residential_destination_with_origin_account_response.xml +311 -0
  123. data/test/fixtures/xml/ups/triple_accept_response.xml +72 -0
  124. data/test/fixtures/xml/ups/triple_confirm_response.xml +32 -0
  125. data/test/fixtures/xml/usps/beverly_hills_to_new_york_book_commercial_base_rate_response.xml +2 -0
  126. data/test/fixtures/xml/usps/beverly_hills_to_new_york_book_commercial_plus_rate_response.xml +258 -0
  127. data/test/fixtures/xml/usps/beverly_hills_to_new_york_book_rate_response.xml +108 -0
  128. data/test/fixtures/xml/usps/beverly_hills_to_ottawa_american_wii_commercial_base_rate_response.xml +84 -0
  129. data/test/fixtures/xml/usps/beverly_hills_to_ottawa_american_wii_commercial_plus_rate_response.xml +212 -0
  130. data/test/fixtures/xml/usps/beverly_hills_to_ottawa_american_wii_rate_response.xml +230 -0
  131. data/test/fixtures/xml/usps/delivered_tracking_response.xml +11 -0
  132. data/test/fixtures/xml/usps/first_class_packages_with_invalid_mail_type_response.xml +12 -0
  133. data/test/fixtures/xml/usps/first_class_packages_with_mail_type_response.xml +16 -0
  134. data/test/fixtures/xml/usps/first_class_packages_without_mail_type_response.xml +12 -0
  135. data/test/fixtures/xml/usps/invalid_xml_tracking_response_error.xml +2 -0
  136. data/test/fixtures/xml/usps/tracking_request.xml +3 -0
  137. data/test/fixtures/xml/usps/tracking_response.xml +13 -0
  138. data/test/fixtures/xml/usps/tracking_response_failure.xml +3 -0
  139. data/test/fixtures/xml/usps/tracking_response_not_available.xml +12 -0
  140. data/test/fixtures/xml/usps/tracking_response_test_error.xml +8 -0
  141. data/test/fixtures/xml/usps/us_rate_request.xml +18 -0
  142. data/test/fixtures/xml/usps/world_rate_request_with_value.xml +20 -0
  143. data/test/fixtures/xml/usps/world_rate_request_without_value.xml +20 -0
  144. data/test/remote/canada_post_pws_platform_test.rb +246 -0
  145. data/test/remote/canada_post_pws_test.rb +171 -0
  146. data/test/remote/canada_post_test.rb +53 -0
  147. data/test/remote/fedex_test.rb +216 -0
  148. data/test/remote/kunaki_test.rb +36 -0
  149. data/test/remote/new_zealand_post_test.rb +147 -0
  150. data/test/remote/shipwire_test.rb +82 -0
  151. data/test/remote/stamps_test.rb +394 -0
  152. data/test/remote/ups_test.rb +257 -0
  153. data/test/remote/usps_test.rb +235 -0
  154. data/test/test_helper.rb +220 -0
  155. data/test/unit/carriers/benchmark_test.rb +18 -0
  156. data/test/unit/carriers/canada_post_pws_rating_test.rb +349 -0
  157. data/test/unit/carriers/canada_post_pws_register_test.rb +75 -0
  158. data/test/unit/carriers/canada_post_pws_shipping_test.rb +244 -0
  159. data/test/unit/carriers/canada_post_pws_tracking_test.rb +154 -0
  160. data/test/unit/carriers/canada_post_test.rb +145 -0
  161. data/test/unit/carriers/fedex_test.rb +408 -0
  162. data/test/unit/carriers/kunaki_test.rb +52 -0
  163. data/test/unit/carriers/new_zealand_post_test.rb +174 -0
  164. data/test/unit/carriers/shipwire_test.rb +187 -0
  165. data/test/unit/carriers/stamps_test.rb +241 -0
  166. data/test/unit/carriers/ups_test.rb +311 -0
  167. data/test/unit/carriers/usps_test.rb +484 -0
  168. data/test/unit/carriers_test.rb +17 -0
  169. data/test/unit/label_response_test.rb +15 -0
  170. data/test/unit/location_test.rb +138 -0
  171. data/test/unit/package_test.rb +68 -0
  172. data/test/unit/rate_estimate_test.rb +34 -0
  173. data/test/unit/response_test.rb +14 -0
  174. data/test/unit/shipment_packer_test.rb +174 -0
  175. metadata +331 -35
  176. metadata.gz.sig +0 -0
  177. data/lib/vendor/quantified/MIT-LICENSE +0 -22
  178. data/lib/vendor/quantified/README.markdown +0 -49
  179. data/lib/vendor/quantified/Rakefile +0 -13
  180. data/lib/vendor/quantified/init.rb +0 -0
  181. data/lib/vendor/quantified/lib/quantified.rb +0 -6
  182. data/lib/vendor/quantified/lib/quantified/attribute.rb +0 -211
  183. data/lib/vendor/quantified/lib/quantified/length.rb +0 -20
  184. data/lib/vendor/quantified/lib/quantified/mass.rb +0 -19
  185. data/lib/vendor/quantified/test/length_test.rb +0 -94
  186. data/lib/vendor/quantified/test/mass_test.rb +0 -96
  187. data/lib/vendor/quantified/test/test_helper.rb +0 -19
@@ -0,0 +1,311 @@
1
+ require 'test_helper'
2
+
3
+ class UPSTest < Minitest::Test
4
+ include ActiveShipping::Test::Fixtures
5
+
6
+ def setup
7
+ @carrier = UPS.new(
8
+ :key => 'key',
9
+ :login => 'login',
10
+ :password => 'password'
11
+ )
12
+ @tracking_response = xml_fixture('ups/shipment_from_tiger_direct')
13
+ end
14
+
15
+ def test_initialize_options_requirements
16
+ assert_raises(ArgumentError) { UPS.new }
17
+ assert_raises(ArgumentError) { UPS.new(:login => 'blah', :password => 'bloo') }
18
+ assert_raises(ArgumentError) { UPS.new(:login => 'blah', :key => 'kee') }
19
+ assert_raises(ArgumentError) { UPS.new(:password => 'bloo', :key => 'kee') }
20
+ assert UPS.new(:login => 'blah', :password => 'bloo', :key => 'kee')
21
+ end
22
+
23
+ def test_find_tracking_info_should_return_a_tracking_response
24
+ @carrier.expects(:commit).returns(@tracking_response)
25
+ assert_equal 'ActiveShipping::TrackingResponse', @carrier.find_tracking_info('1Z5FX0076803466397').class.name
26
+ end
27
+
28
+ def test_find_tracking_info_should_mark_shipment_as_delivered
29
+ @carrier.expects(:commit).returns(@tracking_response)
30
+ assert_equal true, @carrier.find_tracking_info('1Z5FX0076803466397').delivered?
31
+ end
32
+
33
+ def test_find_tracking_info_should_return_correct_carrier
34
+ @carrier.expects(:commit).returns(@tracking_response)
35
+ assert_equal :ups, @carrier.find_tracking_info('1Z5FX0076803466397').carrier
36
+ end
37
+
38
+ def test_find_tracking_info_should_return_correct_carrier_name
39
+ @carrier.expects(:commit).returns(@tracking_response)
40
+ assert_equal 'UPS', @carrier.find_tracking_info('1Z5FX0076803466397').carrier_name
41
+ end
42
+
43
+ def test_find_tracking_info_should_return_correct_status
44
+ @carrier.expects(:commit).returns(@tracking_response)
45
+ assert_equal :delivered, @carrier.find_tracking_info('1Z5FX0076803466397').status
46
+ end
47
+
48
+ def test_find_tracking_info_should_return_correct_status_code
49
+ @carrier.expects(:commit).returns(@tracking_response)
50
+ assert_equal 'd', @carrier.find_tracking_info('1Z5FX0076803466397').status_code.downcase
51
+ end
52
+
53
+ def test_find_tracking_info_should_return_correct_status_description
54
+ @carrier.expects(:commit).returns(@tracking_response)
55
+ assert_equal 'delivered', @carrier.find_tracking_info('1Z5FX0076803466397').status_description.downcase
56
+ end
57
+
58
+ def test_find_tracking_info_should_return_delivery_signature
59
+ @carrier.expects(:commit).returns(@tracking_response)
60
+ assert_equal 'MCAULEY', @carrier.find_tracking_info('1Z5FX0076803466397').delivery_signature
61
+ end
62
+
63
+ def test_find_tracking_info_should_have_an_out_for_delivery_status
64
+ out_for_delivery_tracking_response = xml_fixture('ups/out_for_delivery_shipment')
65
+ @carrier.expects(:commit).returns(out_for_delivery_tracking_response)
66
+ assert_equal :out_for_delivery, @carrier.find_tracking_info('1Z5FX0076803466397').status
67
+ end
68
+
69
+ def test_find_tracking_info_should_return_destination_address
70
+ @carrier.expects(:commit).returns(@tracking_response)
71
+ result = @carrier.find_tracking_info('1Z5FX0076803466397')
72
+ assert_equal 'ottawa', result.destination.city.downcase
73
+ assert_equal 'ON', result.destination.state
74
+ end
75
+
76
+ def test_find_tracking_info_should_return_destination_address_for_abbreviated_response
77
+ tracking_response = xml_fixture('ups/delivered_shipment_without_events_tracking_response')
78
+ @carrier.expects(:commit).returns(tracking_response)
79
+ result = @carrier.find_tracking_info('1Z5FX0076803466397')
80
+ assert_equal 'cypress', result.destination.city.downcase
81
+ assert_equal 'TX', result.destination.state
82
+ end
83
+
84
+ def test_find_tracking_info_should_return_delivered_if_event_is_not_latest
85
+ tracking_response = xml_fixture('ups/delivered_shipment_with_refund')
86
+ @carrier.expects(:commit).returns(tracking_response)
87
+ result = @carrier.find_tracking_info('1Z5FX0076803466397')
88
+ assert_equal :delivered, result.status
89
+ assert_equal true, result.delivered?
90
+ end
91
+
92
+ def test_find_tracking_info_should_return_origin_address
93
+ @carrier.expects(:commit).returns(@tracking_response)
94
+ result = @carrier.find_tracking_info('1Z5FX0076803466397')
95
+ assert_equal 'naperville', result.origin.city.downcase
96
+ assert_equal 'IL', result.origin.state
97
+ end
98
+
99
+ def test_find_tracking_info_should_parse_response_into_correct_number_of_shipment_events
100
+ @carrier.expects(:commit).returns(@tracking_response)
101
+ response = @carrier.find_tracking_info('1Z5FX0076803466397')
102
+ assert_equal 8, response.shipment_events.size
103
+ end
104
+
105
+ def test_find_tracking_info_should_return_shipment_events_in_ascending_chronological_order
106
+ @carrier.expects(:commit).returns(@tracking_response)
107
+ response = @carrier.find_tracking_info('1Z5FX0076803466397')
108
+ assert_equal response.shipment_events.map(&:time).sort, response.shipment_events.map(&:time)
109
+ end
110
+
111
+ def test_find_tracking_info_should_have_correct_names_for_shipment_events
112
+ @carrier.expects(:commit).returns(@tracking_response)
113
+ response = @carrier.find_tracking_info('1Z5FX0076803466397')
114
+ assert_equal ["BILLING INFORMATION RECEIVED",
115
+ "IMPORT SCAN",
116
+ "LOCATION SCAN",
117
+ "LOCATION SCAN",
118
+ "DEPARTURE SCAN",
119
+ "ARRIVAL SCAN",
120
+ "OUT FOR DELIVERY",
121
+ "DELIVERED"], response.shipment_events.map(&:name)
122
+ end
123
+
124
+ def test_add_origin_and_destination_data_to_shipment_events_where_appropriate
125
+ @carrier.expects(:commit).returns(@tracking_response)
126
+ response = @carrier.find_tracking_info('1Z5FX0076803466397')
127
+ assert_equal '175 AMBASSADOR', response.shipment_events.first.location.address1
128
+ assert_equal 'K1N5X8', response.shipment_events.last.location.postal_code
129
+ end
130
+
131
+ def test_find_tracking_info_should_return_correct_actual_delivery_date
132
+ @carrier.expects(:commit).returns(@tracking_response)
133
+ response = @carrier.find_tracking_info('1Z5FX0076803466397')
134
+ assert_equal Time.parse('2008-06-25 11:19:00 UTC'), response.actual_delivery_date
135
+ end
136
+
137
+ def test_response_parsing
138
+ mock_response = xml_fixture('ups/test_real_home_as_residential_destination_response')
139
+ @carrier.expects(:commit).returns(mock_response)
140
+ response = @carrier.find_rates( location_fixtures[:beverly_hills],
141
+ location_fixtures[:real_home_as_residential],
142
+ package_fixtures.values_at(:chocolate_stuff))
143
+ assert_equal ["UPS Ground",
144
+ "UPS Three-Day Select",
145
+ "UPS Second Day Air",
146
+ "UPS Next Day Air Saver",
147
+ "UPS Next Day Air Early A.M.",
148
+ "UPS Next Day Air"], response.rates.map(&:service_name)
149
+ assert_equal [992, 2191, 3007, 5509, 9401, 6124], response.rates.map(&:price)
150
+ assert_equal [0, 0, 0, 0, 0, 0], response.rates.map(&:negotiated_rate)
151
+ end
152
+
153
+ def test_response_with_insured_value
154
+ mock_response = xml_fixture('ups/test_real_home_as_residential_destination_response_with_insured')
155
+ @carrier.expects(:commit).returns(mock_response)
156
+ response = @carrier.find_rates( location_fixtures[:beverly_hills],
157
+ location_fixtures[:real_home_as_residential],
158
+ package_fixtures.values_at(:declared_value))
159
+ assert_equal ["UPS Ground",
160
+ "UPS Three-Day Select",
161
+ "UPS Second Day Air",
162
+ "UPS Next Day Air Saver",
163
+ "UPS Next Day Air Early A.M.",
164
+ "UPS Next Day Air"], response.rates.map(&:service_name)
165
+ assert_equal [2254, 4002, 5107, 8726, 12730, 9430], response.rates.map(&:price)
166
+ assert_equal [850, 850, 850, 850, 850, 850], response.rates.map(&:insurance_price)
167
+ assert_equal [0, 0, 0, 0, 0, 0], response.rates.map(&:negotiated_rate)
168
+ end
169
+
170
+ def test_response_with_origin_account_parsing
171
+ mock_response = xml_fixture('ups/test_real_home_as_residential_destination_with_origin_account_response')
172
+ @carrier.expects(:commit).returns(mock_response)
173
+ response = @carrier.find_rates( location_fixtures[:beverly_hills],
174
+ location_fixtures[:real_home_as_residential],
175
+ package_fixtures[:chocolate_stuff])
176
+ assert_equal ["UPS Express",
177
+ "UPS Worldwide Expedited",
178
+ "UPS Worldwide Express Plus",
179
+ "UPS Saver"], response.rates.map(&:service_name)
180
+ assert_equal [18893, 17856, 23473, 18286], response.rates.map(&:price)
181
+ assert_equal [18704, 17677, 23238, 18103], response.rates.map(&:negotiated_rate)
182
+ end
183
+
184
+ def test_delivery_range_takes_weekend_into_consideration
185
+ mock_response = xml_fixture('ups/test_real_home_as_residential_destination_response')
186
+ @carrier.expects(:commit).returns(mock_response)
187
+ Timecop.freeze(DateTime.new(2012, 6, 15))
188
+ response = @carrier.find_rates( location_fixtures[:beverly_hills],
189
+ location_fixtures[:real_home_as_residential],
190
+ package_fixtures.values_at(:chocolate_stuff))
191
+
192
+ date_test = [nil, 3, 2, 1, 1, 1].map do |days|
193
+ DateTime.now.utc + days + 2 if days
194
+ end
195
+ Timecop.return
196
+
197
+ assert_equal date_test, response.rates.map(&:delivery_date)
198
+ end
199
+
200
+ def test_maximum_weight
201
+ assert Package.new(150 * 16, [5, 5, 5], :units => :imperial).mass == @carrier.maximum_weight
202
+ assert Package.new((150 * 16) + 0.01, [5, 5, 5], :units => :imperial).mass > @carrier.maximum_weight
203
+ assert Package.new((150 * 16) - 0.01, [5, 5, 5], :units => :imperial).mass < @carrier.maximum_weight
204
+ end
205
+
206
+ def test_obtain_multiple_labels
207
+ confirm_response = xml_fixture('ups/triple_confirm_response')
208
+ accept_response = xml_fixture('ups/triple_accept_response')
209
+ @carrier.stubs(:commit).returns(confirm_response, accept_response)
210
+
211
+ response = @carrier.create_shipment(
212
+ location_fixtures[:beverly_hills],
213
+ location_fixtures[:new_york],
214
+ package_fixtures.values_at(:chocolate_stuff, :book, :american_wii),
215
+ :test => true,
216
+ :destination => {
217
+ :company_name => 'N.A.',
218
+ :phone_number => '123-123-1234',
219
+ :attention_name => 'Jane Doe'
220
+ }
221
+
222
+ )
223
+
224
+ # Sanity checks. Hmm. That looks a lot like a type check.
225
+ assert_instance_of LabelResponse, response
226
+ assert_equal 3, response.labels.count
227
+
228
+ # These tracking numbers are part of the fixture data. What we're trying
229
+ # to verify is that the data in the XML is extracted properly.
230
+ tracking = response.labels.map { |label| label[:tracking_number] }
231
+ assert_includes tracking, "1ZA03R691594829862"
232
+ assert_includes tracking, "1ZA03R691592132475"
233
+ assert_includes tracking, "1ZA03R691590470881"
234
+
235
+ pictures = response.labels.map { |label| label[:image] }
236
+ refute_includes pictures, nil
237
+ end
238
+
239
+ def test_obtain_single_label
240
+ confirm_response = xml_fixture('ups/shipment_confirm_response')
241
+ accept_response = xml_fixture('ups/shipment_accept_response')
242
+ @carrier.stubs(:commit).returns(confirm_response, accept_response)
243
+
244
+ response = @carrier.create_shipment(
245
+ location_fixtures[:beverly_hills],
246
+ location_fixtures[:new_york],
247
+ package_fixtures.values_at(:chocolate_stuff),
248
+ :test => true,
249
+ :destination => {
250
+ :company_name => 'N.A.',
251
+ :phone_number => '123-123-1234',
252
+ :attention_name => 'Jane Doe'
253
+ }
254
+
255
+ )
256
+
257
+ # Sanity checks. Hmm. That looks a lot like a type check.
258
+ assert_instance_of LabelResponse, response
259
+ assert_equal 1, response.labels.count
260
+
261
+ # These tracking numbers are part of the fixture data. What we're trying
262
+ # to verify is that the data in the XML is extracted properly.
263
+ tracking = response.labels.map { |label| label[:tracking_number] }
264
+ assert_includes tracking, "1ZA03R691591538440"
265
+
266
+ pictures = response.labels.map { |label| label[:image] }
267
+ refute_includes pictures, nil
268
+ end
269
+
270
+ def test_saturday_delivery
271
+ # It's ok to use Nokogiri for development, right?
272
+ response = Nokogiri::XML @carrier.send(:build_shipment_request,
273
+ location_fixtures[:beverly_hills],
274
+ location_fixtures[:annapolis],
275
+ package_fixtures.values_at(:chocolate_stuff),
276
+ :test => true,
277
+ :saturday_delivery => true
278
+ )
279
+
280
+ saturday = response.search '/ShipmentConfirmRequest/Shipment/ShipmentServiceOptions/SaturdayDelivery'
281
+ refute_empty saturday
282
+ end
283
+
284
+ def test_label_request_negotiated_rates_presence
285
+ response = Nokogiri::XML @carrier.send(:build_shipment_request,
286
+ location_fixtures[:beverly_hills],
287
+ location_fixtures[:annapolis],
288
+ package_fixtures.values_at(:chocolate_stuff),
289
+ :test => true,
290
+ :saturday_delivery => true,
291
+ :origin_account => 'A01B23' # without this option, a negotiated rate will not be requested
292
+ )
293
+
294
+ negotiated_rates = response.search '/ShipmentConfirmRequest/Shipment/RateInformation/NegotiatedRatesIndicator'
295
+ refute_empty negotiated_rates
296
+ end
297
+
298
+ def test_label_request_different_shipper
299
+ pickup = location_fixtures[:beverly_hills]
300
+ deliver = location_fixtures[:annapolis]
301
+ shipper = location_fixtures[:fake_google_as_commercial]
302
+ packages = package_fixtures.values_at(:chocolate_stuff)
303
+
304
+ result = Nokogiri::XML(@carrier.send(:build_shipment_request,
305
+ pickup, deliver, packages, :test => true, :shipper => shipper ))
306
+
307
+ address = result.search '/ShipmentConfirmRequest/Shipment/Shipper/Address/AddressLine1'
308
+ assert_equal address.text, shipper.address1
309
+ refute_equal address.text, pickup.address1
310
+ end
311
+ end
@@ -0,0 +1,484 @@
1
+ require 'test_helper'
2
+
3
+ class USPSTest < Minitest::Test
4
+ include ActiveShipping::Test::Fixtures
5
+ include ActiveShipping::Test::Credentials
6
+
7
+ def setup
8
+ @carrier = USPS.new(:login => 'login')
9
+ @tracking_response = xml_fixture('usps/tracking_response')
10
+ @tracking_response_failure = xml_fixture('usps/tracking_response_failure')
11
+ end
12
+
13
+ def test_tracking_failure_should_raise_exception
14
+ @carrier.expects(:commit).returns(@tracking_response_failure)
15
+ assert_raises ResponseError do
16
+ @carrier.find_tracking_info('abc123xyz', :test => true)
17
+ end
18
+ end
19
+
20
+ def test_find_tracking_info_should_handle_not_found_error
21
+ @carrier.expects(:commit).returns(xml_fixture('usps/tracking_response_test_error'))
22
+ assert_raises ResponseError do
23
+ @carrier.find_tracking_info('9102901000462189604217', :test => true)
24
+ end
25
+ end
26
+
27
+ def test_find_tracking_info_should_handle_invalid_xml_error
28
+ @carrier.expects(:commit).returns(xml_fixture('usps/invalid_xml_tracking_response_error'))
29
+ assert_raises ResponseError do
30
+ @carrier.find_tracking_info('9102901000462189604217,9102901000462189604214', :test => true)
31
+ end
32
+ end
33
+
34
+ def test_find_tracking_info_should_handle_not_available_error
35
+ @carrier.expects(:commit).returns(xml_fixture('usps/tracking_response_not_available'))
36
+ assert_raises ResponseError do
37
+ @carrier.find_tracking_info('9574211957289221353248', :test => true)
38
+ end
39
+ end
40
+
41
+ def test_find_tracking_info_should_return_a_tracking_response
42
+ @carrier.expects(:commit).returns(@tracking_response)
43
+ assert_instance_of ActiveShipping::TrackingResponse, @carrier.find_tracking_info('9102901000462189604217', :test => true)
44
+ @carrier.expects(:commit).returns(@tracking_response)
45
+ assert_equal 'ActiveShipping::TrackingResponse', @carrier.find_tracking_info('EJ958083578US').class.name
46
+ end
47
+
48
+ def test_find_tracking_info_should_parse_response_into_correct_number_of_shipment_events
49
+ @carrier.expects(:commit).returns(@tracking_response)
50
+ response = @carrier.find_tracking_info('9102901000462189604217', :test => true)
51
+ assert_equal 7, response.shipment_events.size
52
+ end
53
+
54
+ def test_find_tracking_info_should_return_shipment_events_in_ascending_chronological_order
55
+ @carrier.expects(:commit).returns(@tracking_response)
56
+ response = @carrier.find_tracking_info('9102901000462189604217', :test => true)
57
+ assert_equal response.shipment_events.map(&:time).sort, response.shipment_events.map(&:time)
58
+ end
59
+
60
+ def test_find_tracking_info_should_have_correct_timestamps_for_shipment_events
61
+ @carrier.expects(:commit).returns(@tracking_response)
62
+ response = @carrier.find_tracking_info('9102901000462189604217', :test => true)
63
+ assert_equal ['2012-01-22 16:30:00 UTC',
64
+ '2012-01-22 17:00:00 UTC',
65
+ '2012-01-23 02:49:00 UTC',
66
+ '2012-01-24 07:45:00 UTC',
67
+ '2012-01-26 11:21:00 UTC',
68
+ '2012-01-27 08:03:00 UTC',
69
+ '2012-01-27 08:13:00 UTC'], response.shipment_events.map { |e| e.time.strftime('%Y-%m-%d %H:%M:00 %Z') }
70
+ end
71
+
72
+ def test_find_tracking_info_should_have_correct_names_for_shipment_events
73
+ @carrier.expects(:commit).returns(@tracking_response)
74
+ response = @carrier.find_tracking_info('9102901000462189604217')
75
+ assert_equal ["PICKED UP BY SHIPPING PARTNER",
76
+ "ARRIVED SHIPPING PARTNER FACILITY",
77
+ "DEPARTED SHIPPING PARTNER FACILITY",
78
+ "DEPARTED SHIPPING PARTNER FACILITY",
79
+ "ARRIVAL AT POST OFFICE",
80
+ "SORTING COMPLETE",
81
+ "OUT FOR DELIVERY"], response.shipment_events.map(&:name)
82
+ end
83
+
84
+ def test_find_tracking_info_should_have_correct_locations_for_shipment_events
85
+ @carrier.expects(:commit).returns(@tracking_response)
86
+ response = @carrier.find_tracking_info('9102901000462189604217', :test => true)
87
+ assert_equal ["PHOENIX, AZ, 85043",
88
+ "PHOENIX, AZ, 85043",
89
+ "PHOENIX, AZ, 85043",
90
+ "GRAND PRAIRIE, TX, 75050",
91
+ "DES MOINES, IA, 50311",
92
+ "DES MOINES, IA, 50311",
93
+ "DES MOINES, IA, 50311"], response.shipment_events.map(&:location).map { |l| "#{l.city}, #{l.state}, #{l.postal_code}" }
94
+ end
95
+
96
+ def test_find_tracking_info_destination
97
+ # USPS API doesn't tell where it's going
98
+ @carrier.expects(:commit).returns(@tracking_response)
99
+ response = @carrier.find_tracking_info('9102901000462189604217', :test => true)
100
+ assert_equal response.destination, nil
101
+ end
102
+
103
+ def test_find_tracking_info_tracking_number
104
+ @carrier.expects(:commit).returns(@tracking_response)
105
+ response = @carrier.find_tracking_info('9102901000462189604217', :test => true)
106
+ assert_equal response.tracking_number, '9102901000462189604217'
107
+ end
108
+
109
+ def test_find_tracking_info_should_have_correct_status
110
+ @carrier.expects(:commit).returns(@tracking_response)
111
+ response = @carrier.find_tracking_info('9102901000462189604217')
112
+ assert_equal :out_for_delivery, response.status
113
+ end
114
+
115
+ def test_find_tracking_info_should_have_correct_delivered
116
+ @carrier.expects(:commit).returns(xml_fixture('usps/delivered_tracking_response'))
117
+ response = @carrier.find_tracking_info('9102901000462189604217')
118
+ assert_equal true, response.delivered?
119
+ end
120
+
121
+ def test_size_codes
122
+ assert_equal 'REGULAR', USPS.size_code_for(Package.new(2, [1, 12, 1], :units => :imperial))
123
+ assert_equal 'LARGE', USPS.size_code_for(Package.new(2, [12.1, 1, 1], :units => :imperial))
124
+ assert_equal 'LARGE', USPS.size_code_for(Package.new(2, [1000, 1000, 1000], :units => :imperial))
125
+ end
126
+
127
+ # TODO: test_parse_domestic_rate_response
128
+
129
+ def test_build_us_rate_request_uses_proper_container
130
+ expected_request = xml_fixture('usps/us_rate_request')
131
+ @carrier.expects(:commit).with(:us_rates, expected_request, false).returns(expected_request)
132
+ @carrier.expects(:parse_rate_response)
133
+ package = package_fixtures[:book]
134
+ package.options[:container] = :rectangular
135
+ @carrier.find_rates(location_fixtures[:beverly_hills], location_fixtures[:new_york], package, :test => true, :container => :rectangular)
136
+ end
137
+
138
+ def test_build_world_rate_request
139
+ expected_request = xml_fixture('usps/world_rate_request_without_value')
140
+ @carrier.expects(:commit).with(:world_rates, expected_request, false).returns(expected_request)
141
+ @carrier.expects(:parse_rate_response)
142
+ @carrier.find_rates(location_fixtures[:beverly_hills], location_fixtures[:ottawa], package_fixtures[:book], :test => true)
143
+ end
144
+
145
+ def test_build_world_rate_request_with_package_value
146
+ expected_request = xml_fixture('usps/world_rate_request_with_value')
147
+ @carrier.expects(:commit).with(:world_rates, expected_request, false).returns(expected_request)
148
+ @carrier.expects(:parse_rate_response)
149
+ @carrier.find_rates(location_fixtures[:beverly_hills], location_fixtures[:ottawa], package_fixtures[:american_wii], :test => true)
150
+ end
151
+
152
+ def test_initialize_options_requirements
153
+ assert_raises(ArgumentError) { USPS.new }
154
+ assert USPS.new(:login => 'blah')
155
+ end
156
+
157
+ def test_parse_international_rate_response
158
+ fixture_xml = xml_fixture('usps/beverly_hills_to_ottawa_american_wii_rate_response')
159
+ @carrier.expects(:commit).returns(fixture_xml)
160
+
161
+ response = begin
162
+ @carrier.find_rates(
163
+ location_fixtures[:beverly_hills], # imperial (U.S. origin)
164
+ location_fixtures[:ottawa],
165
+ package_fixtures[:american_wii],
166
+ :test => true
167
+ )
168
+ rescue ResponseError => e
169
+ e.response
170
+ end
171
+
172
+ expected_xml_hash = Hash.from_xml(fixture_xml)
173
+ actual_xml_hash = Hash.from_xml(response.xml)
174
+
175
+ assert_equal expected_xml_hash, actual_xml_hash
176
+
177
+ refute response.rates.empty?
178
+
179
+ assert_equal [1795, 3420, 5835, 8525, 8525], response.rates.map(&:price)
180
+ assert_equal [1, 2, 4, 12, 15], response.rates.map(&:service_code).map(&:to_i).sort
181
+
182
+ ordered_service_names = ["USPS Express Mail International",
183
+ "USPS First-Class Package International Service",
184
+ "USPS GXG Envelopes",
185
+ "USPS Global Express Guaranteed (GXG)",
186
+ "USPS Priority Mail International"]
187
+ assert_equal ordered_service_names, response.rates.map(&:service_name).sort
188
+ end
189
+
190
+ def test_parse_max_dimension_sentences
191
+ limits = {
192
+ "Max. length 46\", width 35\", height 46\" and max. length plus girth 108\"" =>
193
+ [{:length => 46.0, :width => 46.0, :height => 35.0, :length_plus_girth => 108.0}],
194
+ "Max.length 42\", max. length plus girth 79\"" =>
195
+ [{:length => 42.0, :length_plus_girth => 79.0}],
196
+ "9 1/2\" X 12 1/2\"" =>
197
+ [{:length => 12.5, :width => 9.5, :height => 0.75}, "Flat Rate Envelope"],
198
+ "Maximum length and girth combined 108\"" =>
199
+ [{:length_plus_girth => 108.0}],
200
+ "USPS-supplied Priority Mail flat-rate envelope 9 1/2\" x 12 1/2.\" Maximum weight 4 pounds." =>
201
+ [{:length => 12.5, :width => 9.5, :height => 0.75}, "Flat Rate Envelope"],
202
+ "Max. length 24\", Max. length, height, depth combined 36\"" =>
203
+ [{:length => 24.0, :length_plus_width_plus_height => 36.0}]
204
+ }
205
+ p = package_fixtures[:book]
206
+ limits.each do |sentence, hashes|
207
+ dimensions = hashes[0].update(:weight => 50.0)
208
+ service_node = build_service_node(
209
+ :name => hashes[1],
210
+ :max_weight => 50,
211
+ :max_dimensions => sentence )
212
+ @carrier.expects(:package_valid_for_max_dimensions).with(p, dimensions)
213
+ @carrier.send(:package_valid_for_service, p, service_node)
214
+ end
215
+
216
+ service_node = build_service_node(
217
+ :name => "flat-rate box",
218
+ :max_weight => 50,
219
+ :max_dimensions => "USPS-supplied Priority Mail flat-rate box. Maximum weight 20 pounds." )
220
+
221
+ # should test against either kind of flat rate box:
222
+ dimensions = [{:weight => 50.0, :length => 11.0, :width => 8.5, :height => 5.5}, # or...
223
+ {:weight => 50.0, :length => 13.625, :width => 11.875, :height => 3.375}]
224
+ @carrier.expects(:package_valid_for_max_dimensions).with(p, dimensions[0])
225
+ @carrier.expects(:package_valid_for_max_dimensions).with(p, dimensions[1])
226
+ @carrier.send(:package_valid_for_service, p, service_node)
227
+ end
228
+
229
+ def test_package_valid_for_max_dimensions
230
+ p = Package.new(70 * 16, [10, 10, 10], :units => :imperial)
231
+ limits = {:weight => 70.0, :length => 10.0, :width => 10.0, :height => 10.0, :length_plus_girth => 50.0, :length_plus_width_plus_height => 30.0}
232
+ assert_equal true, @carrier.send(:package_valid_for_max_dimensions, p, limits)
233
+
234
+ limits.keys.each do |key|
235
+ dimensions = {key => (limits[key] - 1)}
236
+ assert_equal false, @carrier.send(:package_valid_for_max_dimensions, p, dimensions)
237
+ end
238
+ end
239
+
240
+ def test_strip_9_digit_zip_codes
241
+ request = URI.decode(@carrier.send(:build_us_rate_request, package_fixtures[:book], "90210-1234", "123456789"))
242
+ assert !(request =~ /\>90210-1234\</)
243
+ assert request =~ /\>90210\</
244
+ assert !(request =~ /\>123456789\</)
245
+ assert request =~ /\>12345\</
246
+ end
247
+
248
+ def test_maximum_weight
249
+ assert Package.new(70 * 16, [5, 5, 5], :units => :imperial).mass == @carrier.maximum_weight
250
+ assert Package.new((70 * 16) + 0.01, [5, 5, 5], :units => :imperial).mass > @carrier.maximum_weight
251
+ assert Package.new((70 * 16) - 0.01, [5, 5, 5], :units => :imperial).mass < @carrier.maximum_weight
252
+ end
253
+
254
+ def test_updated_domestic_rate_name_format_with_unescaped_html
255
+ mock_response = xml_fixture('usps/beverly_hills_to_new_york_book_rate_response')
256
+ @carrier.expects(:commit).returns(mock_response)
257
+ rates_response = @carrier.find_rates(
258
+ location_fixtures[:beverly_hills],
259
+ location_fixtures[:new_york],
260
+ package_fixtures[:book],
261
+ :test => true
262
+ )
263
+ rate_names = [
264
+ 'USPS Express Mail',
265
+ 'USPS Express Mail Flat Rate Envelope',
266
+ 'USPS Express Mail Flat Rate Envelope Hold For Pickup',
267
+ 'USPS Express Mail Hold For Pickup',
268
+ 'USPS Express Mail Legal Flat Rate Envelope',
269
+ 'USPS Express Mail Legal Flat Rate Envelope Hold For Pickup',
270
+ 'USPS Express Mail Sunday/Holiday Delivery',
271
+ 'USPS Express Mail Sunday/Holiday Delivery Flat Rate Envelope',
272
+ 'USPS Express Mail Sunday/Holiday Delivery Legal Flat Rate Envelope',
273
+ 'USPS First-Class Mail Large Envelope',
274
+ 'USPS First-Class Mail Package',
275
+ 'USPS Library Mail',
276
+ 'USPS Media Mail',
277
+ 'USPS Parcel Post',
278
+ 'USPS Priority Mail',
279
+ 'USPS Priority Mail Flat Rate Envelope',
280
+ 'USPS Priority Mail Gift Card Flat Rate Envelope',
281
+ 'USPS Priority Mail Large Flat Rate Box',
282
+ 'USPS Priority Mail Legal Flat Rate Envelope',
283
+ 'USPS Priority Mail Medium Flat Rate Box',
284
+ 'USPS Priority Mail Padded Flat Rate Envelope',
285
+ 'USPS Priority Mail Small Flat Rate Box',
286
+ 'USPS Priority Mail Small Flat Rate Envelope',
287
+ 'USPS Priority Mail Window Flat Rate Envelope'
288
+ ]
289
+ assert_equal rate_names, rates_response.rates.collect(&:service_name).sort
290
+ end
291
+
292
+ def test_first_class_packages_with_mail_type
293
+ @carrier.expects(:commit).returns(xml_fixture('usps/first_class_packages_with_mail_type_response'))
294
+
295
+ response = begin
296
+ @carrier.find_rates(
297
+ location_fixtures[:beverly_hills], # imperial (U.S. origin)
298
+ location_fixtures[:new_york],
299
+ Package.new(0, 0),
300
+
301
+ :test => true,
302
+ :service => :first_class,
303
+ :first_class_mail_type => :parcel
304
+
305
+ )
306
+ rescue ResponseError => e
307
+ e.response
308
+ end
309
+ assert response.success?, response.message
310
+ end
311
+
312
+ def test_first_class_packages_without_mail_type
313
+ @carrier.expects(:commit).returns(xml_fixture('usps/first_class_packages_without_mail_type_response'))
314
+
315
+ begin
316
+ @carrier.find_rates(
317
+ location_fixtures[:beverly_hills], # imperial (U.S. origin)
318
+ location_fixtures[:new_york],
319
+ Package.new(0, 0),
320
+
321
+ :test => true,
322
+ :service => :first_class
323
+
324
+ )
325
+ rescue ResponseError => e
326
+ assert_equal "Invalid First Class Mail Type.", e.message
327
+ end
328
+ end
329
+
330
+ def test_first_class_packages_with_invalid_mail_type
331
+ @carrier.expects(:commit).returns(xml_fixture('usps/first_class_packages_with_invalid_mail_type_response'))
332
+
333
+ begin
334
+ @carrier.find_rates(
335
+ location_fixtures[:beverly_hills], # imperial (U.S. origin)
336
+ location_fixtures[:new_york],
337
+ Package.new(0, 0),
338
+
339
+ :test => true,
340
+ :service => :first_class,
341
+ :first_class_mail_tpe => :invalid
342
+
343
+ )
344
+ rescue ResponseError => e
345
+ assert_equal "Invalid First Class Mail Type.", e.message
346
+ end
347
+ end
348
+
349
+ def test_domestic_retail_rates
350
+ mock_response = xml_fixture('usps/beverly_hills_to_new_york_book_commercial_base_rate_response')
351
+ @carrier.expects(:commit).returns(mock_response)
352
+
353
+ response = @carrier.find_rates(
354
+ location_fixtures[:beverly_hills],
355
+ location_fixtures[:new_york],
356
+ package_fixtures.values_at(:book),
357
+ :test => true
358
+ )
359
+
360
+ rates = Hash[response.rates.map { |rate| [rate.service_name, rate.price] }]
361
+
362
+ assert_equal 0, rates["USPS First-Class Package Service"] # the "first class package service" is only available for commercial base shippers
363
+ assert_equal 309, rates["USPS First-Class Mail Parcel"] # 2013 retail 9oz first class parcel is $3.09
364
+ assert_equal 695, rates["USPS Priority Mail"] # 2013 1lb zone 8 priority retail is $6.95
365
+ end
366
+
367
+ def test_domestic_commercial_base_rates
368
+ @carrier = USPS.new(credentials(:usps).merge(:commercial_base => true))
369
+
370
+ mock_response = xml_fixture('usps/beverly_hills_to_new_york_book_commercial_base_rate_response')
371
+ @carrier.expects(:commit).returns(mock_response)
372
+
373
+ response = @carrier.find_rates(
374
+ location_fixtures[:beverly_hills],
375
+ location_fixtures[:new_york],
376
+ package_fixtures.values_at(:book),
377
+ :test => true
378
+ )
379
+
380
+ rates = Hash[response.rates.map { |rate| [rate.service_name, rate.price] }]
381
+
382
+ assert_equal 0, rates["USPS First-Class Mail Parcel"] # commercial base prices retail first class is unavailable. must ship as package service
383
+ assert_equal 273, rates["USPS First-Class Package Service"] # the "first class package service" should be present for commerical base (instead of USPS First-Class Mail Parcel for retail rates)
384
+ assert_equal 651, rates["USPS Priority Mail"] # 2013 zone 8 commercial base price is 6.51, retail is 6.95
385
+ end
386
+
387
+ def test_intl_commercial_base_rates
388
+ @carrier = USPS.new(credentials(:usps).merge(:commercial_base => true))
389
+
390
+ mock_response = xml_fixture('usps/beverly_hills_to_ottawa_american_wii_commercial_base_rate_response')
391
+ @carrier.expects(:commit).returns(mock_response)
392
+
393
+ response = @carrier.find_rates(
394
+ location_fixtures[:beverly_hills],
395
+ location_fixtures[:ottawa],
396
+ package_fixtures.values_at(:american_wii),
397
+ :test => true
398
+ )
399
+
400
+ assert_equal [4112, 6047, 7744, 7744], response.rates.map(&:price) # note these prices are higher than the normal/retail unit tests because the rates from that test is years older than from this test
401
+ end
402
+
403
+ def test_domestic_commercial_plus_rates
404
+ @carrier = USPS.new(credentials(:usps).merge(:commercial_plus => true))
405
+
406
+ mock_response = xml_fixture('usps/beverly_hills_to_new_york_book_commercial_plus_rate_response')
407
+ @carrier.expects(:commit).returns(mock_response)
408
+
409
+ response = @carrier.find_rates(
410
+ location_fixtures[:beverly_hills],
411
+ location_fixtures[:new_york],
412
+ package_fixtures.values_at(:book),
413
+ :test => true
414
+ )
415
+
416
+ rates = Hash[response.rates.map { |rate| [rate.service_name, rate.price] }]
417
+
418
+ assert_equal 0, rates["USPS First-Class Mail Parcel"]
419
+ assert_equal 405, rates["USPS First-Class Package Service"]
420
+ assert_equal 625, rates["USPS Priority Mail 2-Day"]
421
+ end
422
+
423
+ def test_intl_commercial_plus_rates
424
+ @carrier = USPS.new(credentials(:usps).merge(:commercial_plus => true))
425
+
426
+ mock_response = xml_fixture('usps/beverly_hills_to_ottawa_american_wii_commercial_plus_rate_response')
427
+ @carrier.expects(:commit).returns(mock_response)
428
+
429
+ response = @carrier.find_rates(
430
+ location_fixtures[:beverly_hills],
431
+ location_fixtures[:ottawa],
432
+ package_fixtures.values_at(:american_wii),
433
+ :test => true
434
+ )
435
+
436
+ assert_equal [3767, 5526, 7231, 7231], response.rates.map(&:price)
437
+ end
438
+
439
+ def test_extract_event_details_handles_single_digit_calendar_dates
440
+ assert details = @carrier.extract_event_details("Out for Delivery, October 9, 2013, 10:16 am, BROOKLYN, NY 11201")
441
+ assert_equal "OUT FOR DELIVERY", details.description
442
+ assert_equal 9, details.zoneless_time.mday
443
+ end
444
+
445
+ def test_extract_event_details_handles_double_digit_calendar_dates
446
+ assert details = @carrier.extract_event_details("Out for Delivery, October 12, 2013, 10:16 am, BROOKLYN, NY 11201")
447
+ assert_equal "OUT FOR DELIVERY", details.description
448
+ assert_equal 12, details.zoneless_time.mday
449
+ end
450
+
451
+ private
452
+
453
+ def build_service_node(options = {})
454
+ builder = Nokogiri::XML::Builder.new do |xml|
455
+ xml.Service do
456
+ xml.Pounds(options[:pounds] || "0")
457
+ xml.SvcCommitments(options[:svc_commitments] || "Varies")
458
+ xml.Country(options[:country] || "CANADA")
459
+ xml.ID(options[:id] || "3")
460
+ xml.MaxWeight(options[:max_weight] || "64")
461
+ xml.SvcDescription(options[:name] || "First-Class Mail International")
462
+ xml.MailType(options[:mail_type] || "Package")
463
+ xml.Postage(options[:postage] || "3.76")
464
+ xml.Ounces(options[:ounces] || "9")
465
+ xml.MaxDimensions(options[:max_dimensions].dup || "Max. length 24\", Max. length, height, depth combined 36\"")
466
+ end
467
+ end
468
+ builder.doc.root
469
+ end
470
+
471
+ def build_service_hash(options = {})
472
+ {"Pounds" => options[:pounds] || "0",
473
+ "SvcCommitments" => options[:svc_commitments] || "Varies",
474
+ "Country" => options[:country] || "CANADA",
475
+ "ID" => options[:id] || "3",
476
+ "MaxWeight" => options[:max_weight] || "64",
477
+ "SvcDescription" => options[:name] || "First-Class Mail International",
478
+ "MailType" => options[:mail_type] || "Package",
479
+ "Postage" => options[:postage] || "3.76",
480
+ "Ounces" => options[:ounces] || "9",
481
+ "MaxDimensions" => options[:max_dimensions] ||
482
+ "Max. length 24\", Max. length, height, depth combined 36\""}
483
+ end
484
+ end