reactive_shipping 3.0.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.
Files changed (247) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -0
  3. data/.travis.yml +33 -0
  4. data/.yardopts +13 -0
  5. data/CHANGELOG.md +225 -0
  6. data/CONTRIBUTING.md +23 -0
  7. data/Gemfile +3 -0
  8. data/MIT-LICENSE +21 -0
  9. data/README.md +158 -0
  10. data/Rakefile +35 -0
  11. data/dev.yml +17 -0
  12. data/gemfiles/activesupport42.gemfile +5 -0
  13. data/gemfiles/activesupport50.gemfile +6 -0
  14. data/gemfiles/activesupport51.gemfile +5 -0
  15. data/gemfiles/activesupport52.gemfile +5 -0
  16. data/gemfiles/activesupport_master.gemfile +5 -0
  17. data/lib/certs/eParcel.dtd +111 -0
  18. data/lib/reactive_shipping.rb +26 -0
  19. data/lib/reactive_shipping/address_validation_response.rb +30 -0
  20. data/lib/reactive_shipping/carrier.rb +184 -0
  21. data/lib/reactive_shipping/carriers.rb +35 -0
  22. data/lib/reactive_shipping/carriers/australia_post.rb +248 -0
  23. data/lib/reactive_shipping/carriers/benchmark_carrier.rb +31 -0
  24. data/lib/reactive_shipping/carriers/bogus_carrier.rb +12 -0
  25. data/lib/reactive_shipping/carriers/canada_post.rb +263 -0
  26. data/lib/reactive_shipping/carriers/canada_post_pws.rb +908 -0
  27. data/lib/reactive_shipping/carriers/fedex.rb +797 -0
  28. data/lib/reactive_shipping/carriers/kunaki.rb +155 -0
  29. data/lib/reactive_shipping/carriers/new_zealand_post.rb +260 -0
  30. data/lib/reactive_shipping/carriers/shipwire.rb +178 -0
  31. data/lib/reactive_shipping/carriers/stamps.rb +860 -0
  32. data/lib/reactive_shipping/carriers/ups.rb +1060 -0
  33. data/lib/reactive_shipping/carriers/usps.rb +708 -0
  34. data/lib/reactive_shipping/carriers/usps_returns.rb +86 -0
  35. data/lib/reactive_shipping/delivery_date_estimate.rb +20 -0
  36. data/lib/reactive_shipping/delivery_date_estimates_response.rb +11 -0
  37. data/lib/reactive_shipping/errors.rb +35 -0
  38. data/lib/reactive_shipping/external_return_label_request.rb +417 -0
  39. data/lib/reactive_shipping/external_return_label_response.rb +26 -0
  40. data/lib/reactive_shipping/label.rb +10 -0
  41. data/lib/reactive_shipping/label_response.rb +10 -0
  42. data/lib/reactive_shipping/location.rb +166 -0
  43. data/lib/reactive_shipping/package.rb +165 -0
  44. data/lib/reactive_shipping/package_item.rb +60 -0
  45. data/lib/reactive_shipping/rate_estimate.rb +197 -0
  46. data/lib/reactive_shipping/rate_response.rb +33 -0
  47. data/lib/reactive_shipping/response.rb +44 -0
  48. data/lib/reactive_shipping/shipment_event.rb +22 -0
  49. data/lib/reactive_shipping/shipment_packer.rb +108 -0
  50. data/lib/reactive_shipping/shipping_response.rb +34 -0
  51. data/lib/reactive_shipping/tracking_response.rb +120 -0
  52. data/lib/reactive_shipping/version.rb +3 -0
  53. data/reactive_shipping.gemspec +38 -0
  54. data/shipit.rubygems.yml +1 -0
  55. data/test/console.rb +39 -0
  56. data/test/credentials.yml +76 -0
  57. data/test/fixtures/files/label1.pdf +0 -0
  58. data/test/fixtures/files/ups-shipping-label.gif +0 -0
  59. data/test/fixtures/json/australia_post/calculate_domestic.json +13 -0
  60. data/test/fixtures/json/australia_post/calculate_domestic_2.json +19 -0
  61. data/test/fixtures/json/australia_post/calculate_international.json +12 -0
  62. data/test/fixtures/json/australia_post/calculate_international_2.json +15 -0
  63. data/test/fixtures/json/australia_post/error_message.json +5 -0
  64. data/test/fixtures/json/australia_post/service_domestic.json +117 -0
  65. data/test/fixtures/json/australia_post/service_domestic_2.json +117 -0
  66. data/test/fixtures/json/australia_post/service_international.json +76 -0
  67. data/test/fixtures/json/australia_post/service_international_2.json +59 -0
  68. data/test/fixtures/json/newzealandpost/domestic_book.json +1 -0
  69. data/test/fixtures/json/newzealandpost/domestic_default.json +1 -0
  70. data/test/fixtures/json/newzealandpost/domestic_error.json +1 -0
  71. data/test/fixtures/json/newzealandpost/domestic_poster.json +1 -0
  72. data/test/fixtures/json/newzealandpost/domestic_small_half_pound.json +1 -0
  73. data/test/fixtures/json/newzealandpost/international_book.json +1 -0
  74. data/test/fixtures/json/newzealandpost/international_new_zealand_wii.json +1 -0
  75. data/test/fixtures/json/newzealandpost/international_small_half_pound.json +1 -0
  76. data/test/fixtures/json/newzealandpost/international_wii.json +1 -0
  77. data/test/fixtures/xml/canadapost/example_request.xml +25 -0
  78. data/test/fixtures/xml/canadapost/example_response.xml +130 -0
  79. data/test/fixtures/xml/canadapost/example_response_error.xml +16 -0
  80. data/test/fixtures/xml/canadapost/example_response_french.xml +122 -0
  81. data/test/fixtures/xml/canadapost/example_response_with_nil_value.xml +164 -0
  82. data/test/fixtures/xml/canadapost/example_response_with_postal_outlet.xml +155 -0
  83. data/test/fixtures/xml/canadapost/example_response_with_postal_outlet_french.xml +274 -0
  84. data/test/fixtures/xml/canadapost/example_response_with_strange_delivery_date.xml +130 -0
  85. data/test/fixtures/xml/canadapost_pws/dnc_tracking_details_en.xml +112 -0
  86. data/test/fixtures/xml/canadapost_pws/merchant_details_error.xml +7 -0
  87. data/test/fixtures/xml/canadapost_pws/merchant_details_response.xml +7 -0
  88. data/test/fixtures/xml/canadapost_pws/option_response.xml +13 -0
  89. data/test/fixtures/xml/canadapost_pws/option_response_no_conflicts.xml +7 -0
  90. data/test/fixtures/xml/canadapost_pws/rates_info.xml +190 -0
  91. data/test/fixtures/xml/canadapost_pws/rates_info_error.xml +7 -0
  92. data/test/fixtures/xml/canadapost_pws/receipt_response.xml +42 -0
  93. data/test/fixtures/xml/canadapost_pws/receipt_response_no_priced_options.xml +36 -0
  94. data/test/fixtures/xml/canadapost_pws/register_token_error.xml +7 -0
  95. data/test/fixtures/xml/canadapost_pws/register_token_response.xml +3 -0
  96. data/test/fixtures/xml/canadapost_pws/service_options_response.xml +42 -0
  97. data/test/fixtures/xml/canadapost_pws/services_error.xml +6 -0
  98. data/test/fixtures/xml/canadapost_pws/services_response.xml +32 -0
  99. data/test/fixtures/xml/canadapost_pws/shipment_domestic.xml +69 -0
  100. data/test/fixtures/xml/canadapost_pws/shipment_response.xml +20 -0
  101. data/test/fixtures/xml/canadapost_pws/shipment_us.xml +69 -0
  102. data/test/fixtures/xml/canadapost_pws/tracking_details_en.xml +152 -0
  103. data/test/fixtures/xml/canadapost_pws/tracking_details_en_error.xml +7 -0
  104. data/test/fixtures/xml/canadapost_pws/tracking_details_en_undelivered.xml +116 -0
  105. data/test/fixtures/xml/canadapost_pws/tracking_details_fr.xml +156 -0
  106. data/test/fixtures/xml/canadapost_pws/tracking_details_no_expected_delivery_date.xml +40 -0
  107. data/test/fixtures/xml/fedex/create_shipment_response.xml +2 -0
  108. data/test/fixtures/xml/fedex/freight_rate_request.xml +82 -0
  109. data/test/fixtures/xml/fedex/freight_rate_response.xml +506 -0
  110. data/test/fixtures/xml/fedex/invalid_fedex_reply.xml +27 -0
  111. data/test/fixtures/xml/fedex/ottawa_to_beverly_hills_commercial_rate_request.xml +79 -0
  112. data/test/fixtures/xml/fedex/ottawa_to_beverly_hills_no_saturday_rate_request.xml +79 -0
  113. data/test/fixtures/xml/fedex/ottawa_to_beverly_hills_rate_request.xml +80 -0
  114. data/test/fixtures/xml/fedex/ottawa_to_beverly_hills_rate_response.xml +214 -0
  115. data/test/fixtures/xml/fedex/raterequest_reply.xml +213 -0
  116. data/test/fixtures/xml/fedex/raterequest_response_with_ground_home_delivery.xml +206 -0
  117. data/test/fixtures/xml/fedex/reply_without_notifications.xml +185 -0
  118. data/test/fixtures/xml/fedex/tracking_request.xml +29 -0
  119. data/test/fixtures/xml/fedex/tracking_response_bad_tracking_number.xml +20 -0
  120. data/test/fixtures/xml/fedex/tracking_response_delivered_at_door.xml +254 -0
  121. data/test/fixtures/xml/fedex/tracking_response_delivered_at_facility.xml +403 -0
  122. data/test/fixtures/xml/fedex/tracking_response_delivered_with_signature.xml +269 -0
  123. data/test/fixtures/xml/fedex/tracking_response_empty_status_detail.xml +84 -0
  124. data/test/fixtures/xml/fedex/tracking_response_failure_code_9045.xml +52 -0
  125. data/test/fixtures/xml/fedex/tracking_response_failure_code_9080.xml +51 -0
  126. data/test/fixtures/xml/fedex/tracking_response_in_transit.xml +127 -0
  127. data/test/fixtures/xml/fedex/tracking_response_invalid_tracking_number.xml +52 -0
  128. data/test/fixtures/xml/fedex/tracking_response_missing_status_code.xml +89 -0
  129. data/test/fixtures/xml/fedex/tracking_response_multiple_results.xml +100 -0
  130. data/test/fixtures/xml/fedex/tracking_response_not_found.xml +52 -0
  131. data/test/fixtures/xml/fedex/tracking_response_shipment_exception.xml +209 -0
  132. data/test/fixtures/xml/fedex/tracking_response_unable_to_process.xml +32 -0
  133. data/test/fixtures/xml/fedex/tracking_response_with_blank_state.xml +107 -0
  134. data/test/fixtures/xml/fedex/unknown_fedex_document_reply.xml +3 -0
  135. data/test/fixtures/xml/kunaki/invalid_state_response.xml +3 -0
  136. data/test/fixtures/xml/kunaki/no_valid_items_response.xml +3 -0
  137. data/test/fixtures/xml/kunaki/successful_rates_response.xml +3 -0
  138. data/test/fixtures/xml/kunaki/unsuccessful_rates_response.xml +9 -0
  139. data/test/fixtures/xml/shipwire/international_rates_response.xml +17 -0
  140. data/test/fixtures/xml/shipwire/new_carrier_rate_response.xml +18 -0
  141. data/test/fixtures/xml/shipwire/no_rates_response.xml +7 -0
  142. data/test/fixtures/xml/shipwire/rates_response.xml +36 -0
  143. data/test/fixtures/xml/shipwire/rates_response_no_estimate.xml +14 -0
  144. data/test/fixtures/xml/stamps/authenticate_user_request.xml +15 -0
  145. data/test/fixtures/xml/stamps/authenticate_user_response.xml +10 -0
  146. data/test/fixtures/xml/stamps/cleanse_address_request.xml +19 -0
  147. data/test/fixtures/xml/stamps/cleanse_address_response.xml +27 -0
  148. data/test/fixtures/xml/stamps/create_indicium_request.xml +69 -0
  149. data/test/fixtures/xml/stamps/create_indicium_response.xml +40 -0
  150. data/test/fixtures/xml/stamps/expired_authenticator_response.xml +15 -0
  151. data/test/fixtures/xml/stamps/get_account_info_request.xml +11 -0
  152. data/test/fixtures/xml/stamps/get_account_info_response.xml +36 -0
  153. data/test/fixtures/xml/stamps/get_purchase_status_request.xml +12 -0
  154. data/test/fixtures/xml/stamps/get_purchase_status_response.xml +16 -0
  155. data/test/fixtures/xml/stamps/get_rates_request.xml +19 -0
  156. data/test/fixtures/xml/stamps/get_rates_response.xml +351 -0
  157. data/test/fixtures/xml/stamps/purchase_postage_request.xml +13 -0
  158. data/test/fixtures/xml/stamps/purchase_postage_response.xml +17 -0
  159. data/test/fixtures/xml/stamps/track_shipment_request.xml +12 -0
  160. data/test/fixtures/xml/stamps/track_shipment_response.xml +45 -0
  161. data/test/fixtures/xml/ups/access_request.xml +6 -0
  162. data/test/fixtures/xml/ups/delivered_shipment_with_refund.xml +290 -0
  163. data/test/fixtures/xml/ups/delivered_shipment_without_events_tracking_response.xml +62 -0
  164. data/test/fixtures/xml/ups/delivery_dates_response.xml +140 -0
  165. data/test/fixtures/xml/ups/example_tracking_response.xml +53 -0
  166. data/test/fixtures/xml/ups/in_transit_shipment.xml +183 -0
  167. data/test/fixtures/xml/ups/out_for_delivery_shipment.xml +165 -0
  168. data/test/fixtures/xml/ups/package_exceeds_maximum_length.xml +12 -0
  169. data/test/fixtures/xml/ups/rate_single_service.xml +54 -0
  170. data/test/fixtures/xml/ups/rescheduled_shipment.xml +204 -0
  171. data/test/fixtures/xml/ups/shipment_accept_response.xml +42 -0
  172. data/test/fixtures/xml/ups/shipment_confirm_response.xml +33 -0
  173. data/test/fixtures/xml/ups/shipment_from_tiger_direct.xml +222 -0
  174. data/test/fixtures/xml/ups/test_real_home_as_residential_destination_response.xml +290 -0
  175. data/test/fixtures/xml/ups/test_real_home_as_residential_destination_response_with_insured.xml +289 -0
  176. data/test/fixtures/xml/ups/test_real_home_as_residential_destination_with_origin_account_response.xml +311 -0
  177. data/test/fixtures/xml/ups/tracking_request.xml +9 -0
  178. data/test/fixtures/xml/ups/triple_accept_response.xml +72 -0
  179. data/test/fixtures/xml/ups/triple_confirm_response.xml +32 -0
  180. data/test/fixtures/xml/ups/void_shipment_response.xml +11 -0
  181. data/test/fixtures/xml/usps/api_error_rate_response.xml +53 -0
  182. data/test/fixtures/xml/usps/beverly_hills_to_new_york_book_commercial_base_rate_response.xml +2 -0
  183. data/test/fixtures/xml/usps/beverly_hills_to_new_york_book_commercial_plus_rate_response.xml +258 -0
  184. data/test/fixtures/xml/usps/beverly_hills_to_new_york_book_rate_response.xml +108 -0
  185. data/test/fixtures/xml/usps/beverly_hills_to_ottawa_american_wii_commercial_base_rate_response.xml +84 -0
  186. data/test/fixtures/xml/usps/beverly_hills_to_ottawa_american_wii_commercial_plus_rate_response.xml +212 -0
  187. data/test/fixtures/xml/usps/beverly_hills_to_ottawa_american_wii_rate_response.xml +230 -0
  188. data/test/fixtures/xml/usps/first_class_packages_with_invalid_mail_type_response.xml +12 -0
  189. data/test/fixtures/xml/usps/first_class_packages_with_mail_type_response.xml +16 -0
  190. data/test/fixtures/xml/usps/first_class_packages_without_mail_type_response.xml +12 -0
  191. data/test/fixtures/xml/usps/invalid_xml_response.xml +10 -0
  192. data/test/fixtures/xml/usps/invalid_xml_tracking_response_error.xml +2 -0
  193. data/test/fixtures/xml/usps/tracking_request.xml +10 -0
  194. data/test/fixtures/xml/usps/tracking_request_batch.xml +12 -0
  195. data/test/fixtures/xml/usps/tracking_response.xml +162 -0
  196. data/test/fixtures/xml/usps/tracking_response_alt.xml +53 -0
  197. data/test/fixtures/xml/usps/tracking_response_batch.xml +231 -0
  198. data/test/fixtures/xml/usps/tracking_response_failure.xml +11 -0
  199. data/test/fixtures/xml/usps/tracking_response_not_available.xml +12 -0
  200. data/test/fixtures/xml/usps/tracking_response_test_error.xml +8 -0
  201. data/test/fixtures/xml/usps/us_rate_request.xml +18 -0
  202. data/test/fixtures/xml/usps/us_rate_request_large.xml +18 -0
  203. data/test/fixtures/xml/usps/world_rate_request_only_country.xml +22 -0
  204. data/test/fixtures/xml/usps/world_rate_request_with_value.xml +24 -0
  205. data/test/fixtures/xml/usps/world_rate_request_without_value.xml +24 -0
  206. data/test/fixtures/xml/usps_returns/external_return_label_response.xml +2 -0
  207. data/test/fixtures/xml/usps_returns/external_return_label_response_failure.xml +10 -0
  208. data/test/remote/australia_post_test.rb +140 -0
  209. data/test/remote/canada_post_pws_platform_test.rb +259 -0
  210. data/test/remote/canada_post_pws_test.rb +169 -0
  211. data/test/remote/canada_post_test.rb +55 -0
  212. data/test/remote/fedex_test.rb +400 -0
  213. data/test/remote/kunaki_test.rb +37 -0
  214. data/test/remote/new_zealand_post_test.rb +149 -0
  215. data/test/remote/shipwire_test.rb +84 -0
  216. data/test/remote/stamps_test.rb +396 -0
  217. data/test/remote/usps_returns_test.rb +72 -0
  218. data/test/remote/usps_test.rb +243 -0
  219. data/test/test_helper.rb +296 -0
  220. data/test/unit/carrier_test.rb +130 -0
  221. data/test/unit/carriers/australia_post_test.rb +181 -0
  222. data/test/unit/carriers/benchmark_test.rb +18 -0
  223. data/test/unit/carriers/canada_post_pws_rating_test.rb +379 -0
  224. data/test/unit/carriers/canada_post_pws_register_test.rb +76 -0
  225. data/test/unit/carriers/canada_post_pws_shipping_test.rb +258 -0
  226. data/test/unit/carriers/canada_post_pws_test.rb +59 -0
  227. data/test/unit/carriers/canada_post_pws_tracking_test.rb +154 -0
  228. data/test/unit/carriers/canada_post_test.rb +148 -0
  229. data/test/unit/carriers/fedex_test.rb +693 -0
  230. data/test/unit/carriers/kunaki_test.rb +56 -0
  231. data/test/unit/carriers/new_zealand_post_test.rb +177 -0
  232. data/test/unit/carriers/shipwire_test.rb +188 -0
  233. data/test/unit/carriers/stamps_test.rb +245 -0
  234. data/test/unit/carriers/ups_test.rb +580 -0
  235. data/test/unit/carriers/usps_returns_test.rb +45 -0
  236. data/test/unit/carriers/usps_test.rb +633 -0
  237. data/test/unit/carriers_test.rb +16 -0
  238. data/test/unit/external_return_label_request_test.rb +258 -0
  239. data/test/unit/location_test.rb +234 -0
  240. data/test/unit/package_item_test.rb +232 -0
  241. data/test/unit/package_test.rb +404 -0
  242. data/test/unit/rate_estimate_test.rb +93 -0
  243. data/test/unit/response_test.rb +38 -0
  244. data/test/unit/shipment_event_test.rb +20 -0
  245. data/test/unit/shipment_packer_test.rb +212 -0
  246. data/test/unit/tracking_response_test.rb +41 -0
  247. metadata +684 -0
@@ -0,0 +1,37 @@
1
+ require 'test_helper'
2
+
3
+ class RemoteKunakiTest < ActiveSupport::TestCase
4
+ include ReactiveShipping::Test::Fixtures
5
+
6
+ def setup
7
+ @carrier = Kunaki.new
8
+ @item1 = { :sku => 'PX002LTGLS', :quantity => 2 }
9
+ @item2 = { :sku => 'PX00MXGKAR', :quantity => 1 }
10
+ @item3 = { :sku => 'PX00ZEDG6F', :quantity => 1 }
11
+ @items = [@item1, @item2, @item3]
12
+ end
13
+
14
+ def test_successful_rates_request
15
+ response = @carrier.find_rates(
16
+ location_fixtures[:ottawa],
17
+ location_fixtures[:beverly_hills],
18
+ package_fixtures.values_at(:book, :wii),
19
+ :items => @items
20
+ )
21
+
22
+ assert response.success?
23
+ assert_equal 4, response.rates.size
24
+ assert_equal ["UPS 2nd Day Air", "UPS Ground", "UPS Next Day Air Saver", "USPS First Class Mail"], response.rates.collect(&:service_name).sort
25
+ end
26
+
27
+ def test_send_no_items
28
+ assert_raises(ActiveUtils::ResponseError) do
29
+ @carrier.find_rates(
30
+ location_fixtures[:ottawa],
31
+ location_fixtures[:beverly_hills],
32
+ package_fixtures.values_at(:book, :wii),
33
+ :items => []
34
+ )
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,149 @@
1
+ require 'test_helper'
2
+
3
+ class RemoteNewZealandPostTest < ActiveSupport::TestCase
4
+ include ReactiveShipping::Test::Credentials
5
+ include ReactiveShipping::Test::Fixtures
6
+
7
+ def setup
8
+ @carrier = NewZealandPost.new(credentials(:new_zealand_post).merge(:test => true))
9
+ @wellington = location_fixtures[:wellington]
10
+ @auckland = location_fixtures[:auckland]
11
+ @ottawa = location_fixtures[:ottawa]
12
+ rescue NoCredentialsFound => e
13
+ skip(e.message)
14
+ end
15
+
16
+ def test_valid_credentials
17
+ assert @carrier.valid_credentials?
18
+ end
19
+
20
+ def test_domestic_response
21
+ response = @carrier.find_rates(@wellington, @auckland, package_fixtures[:wii])
22
+
23
+ assert response.is_a?(RateResponse)
24
+ assert response.success?
25
+ assert response.rates.any?
26
+ assert response.rates.first.is_a?(RateEstimate)
27
+ assert_equal 1, response.params["responses"].size
28
+ assert_equal 1, response.request.size
29
+ assert_equal 1, response.raw_responses.size
30
+ assert response.request.first.size > 0
31
+ assert response.params["responses"].first.size > 0
32
+ assert response.raw_responses.first.size > 0
33
+ end
34
+
35
+ def test_domestic_combined_response
36
+ response = @carrier.find_rates(@wellington, @auckland, package_fixtures.values_at(:book, :small_half_pound))
37
+
38
+ assert response.is_a?(RateResponse)
39
+ assert response.success?
40
+ assert response.rates.any?
41
+ assert response.rates.first.is_a?(RateEstimate)
42
+ assert_equal 2, response.params["responses"].size
43
+ assert_equal 2, response.request.size
44
+ assert_equal 2, response.raw_responses.size
45
+ assert response.request.first.size > 0
46
+ assert response.params["responses"].first.size > 0
47
+ assert response.raw_responses.first.size > 0
48
+ end
49
+
50
+ def test_domestic_failed_response_raises
51
+ skip 'ReactiveShipping::ResponseError expected but nothing was raised.'
52
+ assert_raises ReactiveShipping::ResponseError do
53
+ @carrier.find_rates(@wellington, @auckland, package_fixtures[:shipping_container])
54
+ end
55
+ end
56
+
57
+ def test_domestic_failed_response_message
58
+ skip 'Expected /Length can only be between 0 and 150cm/ to match "success".'
59
+ error = @carrier.find_rates(@wellington, @auckland, package_fixtures[:shipping_container]) rescue $!
60
+ assert_match /Length can only be between 0 and 150cm/, error.message
61
+ end
62
+
63
+ def test_domestic_combined_response_prices
64
+ response_book = @carrier.find_rates(@wellington, @auckland, package_fixtures[:book])
65
+ response_small_half_pound = @carrier.find_rates(@wellington, @auckland, package_fixtures[:small_half_pound])
66
+ response_combined = @carrier.find_rates(@wellington, @auckland, package_fixtures.values_at(:book, :small_half_pound))
67
+
68
+ assert response_combined.is_a?(RateResponse)
69
+ assert response_combined.success?
70
+ assert response_book.rates.first.is_a?(RateEstimate)
71
+ assert response_small_half_pound.rates.first.is_a?(RateEstimate)
72
+ assert response_combined.rates.first.is_a?(RateEstimate)
73
+
74
+ sum_book_prices = response_book.rates.sum(&:price)
75
+ sum_small_half_pound_prices = response_small_half_pound.rates.sum(&:price)
76
+ sum_combined_prices = response_combined.rates.sum(&:price)
77
+
78
+ assert sum_book_prices > 0
79
+ assert sum_small_half_pound_prices > 0
80
+ assert sum_combined_prices > 0
81
+ assert sum_combined_prices <= sum_book_prices + sum_small_half_pound_prices
82
+
83
+ # uncomment this test for visual display of combining rates
84
+ # puts "\nBook:"
85
+ # response_wii.rate_estimates.each{ |r| puts "\nTotal Price: #{r.total_price}\nService Name: #{r.service_name} (#{r.service_code})" }
86
+ # puts "\Small half pound:"
87
+ # response_book.rate_estimates.each{ |r| puts "\nTotal Price: #{r.total_price}\nService Name: #{r.service_name} (#{r.service_code})" }
88
+ # puts "\nCombined"
89
+ # response_combined.rate_estimates.each{ |r| puts "\nTotal Price: #{r.total_price}\nService Name: #{r.service_name} (#{r.service_code})" }
90
+ end
91
+
92
+ def test_international_book_response
93
+ response = @carrier.find_rates(@wellington, @ottawa, package_fixtures[:book])
94
+ assert response.is_a?(RateResponse)
95
+ assert response.success?
96
+ assert response.rates.any?
97
+ assert response.rates.first.is_a?(RateEstimate)
98
+ end
99
+
100
+ def test_international_poster_response
101
+ response = @carrier.find_rates(@wellington, @ottawa, package_fixtures[:poster])
102
+ assert response.is_a?(RateResponse)
103
+ assert response.success?
104
+ assert response.rates.any?
105
+ assert response.rates.first.is_a?(RateEstimate)
106
+ end
107
+
108
+ def test_international_combined_response
109
+ response = @carrier.find_rates(@wellington, @ottawa, package_fixtures.values_at(:book, :poster))
110
+ assert response.is_a?(RateResponse)
111
+ assert response.success?
112
+ assert response.rates.any?
113
+ assert response.rates.first.is_a?(RateEstimate)
114
+ assert_equal 2, response.params["responses"].size
115
+ assert_equal 2, response.request.size
116
+ assert_equal 2, response.raw_responses.size
117
+ assert response.request.first.size > 0
118
+ assert response.params["responses"].first.size > 0
119
+ assert response.raw_responses.first.size > 0
120
+ end
121
+
122
+ def test_international_shipping_container_response
123
+ response = @carrier.find_rates(@wellington, @ottawa, package_fixtures[:shipping_container])
124
+ assert response.is_a?(RateResponse)
125
+ assert response.success?
126
+ assert_equal 0, response.rates.size
127
+ end
128
+
129
+ def test_international_gold_bar_response
130
+ response = @carrier.find_rates(@wellington, @ottawa, package_fixtures[:largest_gold_bar])
131
+ assert response.is_a?(RateResponse)
132
+ assert response.success?
133
+ assert_equal 0, response.rates.size
134
+ end
135
+
136
+ def test_international_empty_package_response
137
+ response = @carrier.find_rates(@wellington, @ottawa, package_fixtures[:just_zero_weight])
138
+ assert response.is_a?(RateResponse)
139
+ assert response.success?
140
+ assert_equal 0, response.rates.size
141
+ end
142
+
143
+ def test_international_just_country_given
144
+ response = @carrier.find_rates(@wellington, Location.new(:country => 'CZ'), package_fixtures[:book])
145
+ assert response.is_a?(RateResponse)
146
+ assert response.success?
147
+ assert response.rates.size > 0
148
+ end
149
+ end
@@ -0,0 +1,84 @@
1
+ require 'test_helper'
2
+
3
+ class RemoteShipwireTest < ActiveSupport::TestCase
4
+ include ReactiveShipping::Test::Credentials
5
+ include ReactiveShipping::Test::Fixtures
6
+
7
+ def setup
8
+ @carrier = Shipwire.new(credentials(:shipwire))
9
+ @item1 = { :sku => 'AF0001', :quantity => 2 }
10
+ @item2 = { :sku => 'AF0002', :quantity => 1 }
11
+ @items = [@item1, @item2]
12
+ rescue NoCredentialsFound => e
13
+ skip(e.message)
14
+ end
15
+
16
+ def test_successful_domestic_rates_request_for_single_line_item
17
+ response = @carrier.find_rates(
18
+ location_fixtures[:ottawa],
19
+ location_fixtures[:beverly_hills],
20
+ package_fixtures.values_at(:book, :wii),
21
+ :items => [@item1],
22
+ :order_id => '#1000'
23
+ )
24
+
25
+ assert response.success?
26
+ assert_equal 2, response.rates.size
27
+ assert_equal Set['2D', 'GD'], Set.new(response.rates.map(&:service_code))
28
+ end
29
+
30
+ def test_successful_domestic_rates_request_for_multiple_line_items
31
+ response = @carrier.find_rates(
32
+ location_fixtures[:ottawa],
33
+ location_fixtures[:beverly_hills],
34
+ package_fixtures.values_at(:book, :wii),
35
+ :items => @items,
36
+ :order_id => '#1000'
37
+ )
38
+
39
+ assert response.success?
40
+ assert_equal 2, response.rates.size
41
+ assert_equal Set['2D', 'GD'], Set.new(response.rates.map(&:service_code))
42
+ end
43
+
44
+ def test_successful_international_rates_request_for_single_line_item
45
+ # skip 'ReactiveShipping::ResponseError: No shipping rates could be found for the destination address'
46
+ response = @carrier.find_rates(
47
+ location_fixtures[:ottawa],
48
+ location_fixtures[:london],
49
+ package_fixtures.values_at(:book, :wii),
50
+ :items => [@item1],
51
+ :order_id => '#1000'
52
+ )
53
+
54
+ assert response.success?
55
+ assert_equal 3, response.rates.size
56
+ assert_equal Set['1D', '2D', 'GD'], Set.new(response.rates.map(&:service_code))
57
+ end
58
+
59
+ def test_invalid_xml_raises_response_content_error
60
+ @carrier.expects(:ssl_post).returns("")
61
+
62
+ assert_raises ReactiveShipping::ResponseContentError do
63
+ @carrier.find_rates(
64
+ location_fixtures[:ottawa],
65
+ location_fixtures[:london],
66
+ package_fixtures.values_at(:book, :wii),
67
+ :items => @items,
68
+ :order_id => '#1000'
69
+ )
70
+ end
71
+ end
72
+
73
+ def test_validate_credentials_with_valid_credentials
74
+ assert @carrier.valid_credentials?
75
+ end
76
+
77
+ def test_validate_credentials_with_invalid_credentials
78
+ shipwire = Shipwire.new(
79
+ :login => 'your@email.com',
80
+ :password => 'password'
81
+ )
82
+ refute shipwire.valid_credentials?
83
+ end
84
+ end
@@ -0,0 +1,396 @@
1
+ require 'test_helper'
2
+
3
+ class RemoteStampsTest < ActiveSupport::TestCase
4
+ include ReactiveShipping::Test::Credentials
5
+ include ReactiveShipping::Test::Fixtures
6
+
7
+ def setup
8
+ @carrier = Stamps.new(credentials(:stamps).merge(test: true))
9
+ rescue NoCredentialsFound => e
10
+ skip(e.message)
11
+ end
12
+
13
+ def test_valid_credentials
14
+ assert @carrier.valid_credentials?
15
+ end
16
+
17
+ def test_account_info
18
+ skip 'ReactiveShipping::ResponseError: Unable to write data to the transport connection: An existing connection was forcibly closed by the remote host.'
19
+ @account_info = @carrier.account_info
20
+
21
+ assert_equal 'ReactiveShipping::StampsAccountInfoResponse', @account_info.class.name
22
+ end
23
+
24
+ def test_purchase_postage
25
+ skip '<#<ReactiveShipping::ResponseError: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.>>.'
26
+ purchase_amount = 10.62 # Based on the amount used in the track shipment tests
27
+
28
+ account = @carrier.account_info
29
+ response = @carrier.purchase_postage(purchase_amount, account.control_total)
30
+ assert response.success?
31
+ end
32
+
33
+ def test_validation_domestic
34
+ response = @carrier.validate_address(location_fixtures[:new_york_with_name])
35
+
36
+ assert_equal 'BOB BOBSEN', response.address.name
37
+ assert_equal '780 3RD AVE RM 2601', response.address.address1
38
+ assert_nil response.address.address2
39
+ assert_equal 'NEW YORK', response.address.city
40
+ assert_equal 'NY', response.address.state
41
+ assert_equal '10017-2177', response.address.zip
42
+
43
+ assert_equal [], response.candidate_addresses
44
+
45
+ assert response.address_match?
46
+ assert response.city_state_zip_ok?
47
+
48
+ assert_instance_of String, response.cleanse_hash
49
+ assert_instance_of String, response.override_hash
50
+ end
51
+
52
+ def test_validation_puerto_rico
53
+ puerto_rico_with_name = Location.new(location_fixtures[:puerto_rico].to_hash.merge(name: 'Bob Bobsen'))
54
+
55
+ response = @carrier.validate_address(puerto_rico_with_name)
56
+
57
+ assert_equal 'BOB BOBSEN', response.address.name
58
+ assert_equal '1 CALLE NUEVA', response.address.address1
59
+ assert_equal 'BARCELONETA', response.address.city
60
+ assert_equal 'PR', response.address.province
61
+ assert_equal '00617-3101', response.address.postal_code
62
+
63
+ assert_equal [], response.candidate_addresses
64
+
65
+ assert response.address_match?
66
+ assert response.city_state_zip_ok?
67
+
68
+ assert_instance_of String, response.cleanse_hash
69
+ assert_instance_of String, response.override_hash
70
+ end
71
+
72
+ def test_validatation_ottawa
73
+ ottawa_with_name = Location.new(location_fixtures[:ottawa].to_hash.merge(name: 'Bob Bobsen'))
74
+
75
+ response = @carrier.validate_address(ottawa_with_name)
76
+
77
+ assert_equal 'BOB BOBSEN', response.address.name
78
+ assert_equal '110 LAURIER AVENUE WEST', response.address.address1
79
+ assert_equal 'OTTAWA', response.address.city
80
+ assert_equal 'ON', response.address.province
81
+ assert_equal 'K1P 1J1', response.address.postal_code
82
+ assert_equal 'CA', response.address.country_code
83
+ assert_equal '1-613-580-2400', response.address.phone
84
+
85
+ assert_equal [], response.candidate_addresses
86
+
87
+ assert response.address_match?
88
+ assert response.city_state_zip_ok?
89
+
90
+ assert_instance_of String, response.cleanse_hash
91
+ assert_instance_of String, response.override_hash
92
+ end
93
+
94
+ def test_validation_with_candidates
95
+ missing_quadrant = Location.new(
96
+ name: 'The White House',
97
+ address1: '1600 Pennsylvania Ave',
98
+ city: 'Washington',
99
+ state: 'DC',
100
+ zip: '20500'
101
+ )
102
+
103
+ response = @carrier.validate_address(missing_quadrant)
104
+
105
+ assert_equal 'THE WHITE HOUSE', response.address.name
106
+ assert_equal '1600 PENNSYLVANIA AVE NW', response.address.address1
107
+ assert_equal 'WASHINGTON', response.address.city
108
+ assert_equal 'DC', response.address.province
109
+ assert_equal '20500-0003', response.address.postal_code
110
+
111
+ assert_equal 7, response.candidate_addresses.length
112
+
113
+ assert !response.address_match?
114
+ assert response.city_state_zip_ok?
115
+
116
+ assert_nil response.cleanse_hash
117
+ assert_instance_of String, response.override_hash
118
+ end
119
+
120
+ def test_shipment
121
+ response = @carrier.create_shipment(
122
+ location_fixtures[:beverly_hills],
123
+ location_fixtures[:new_york_with_name],
124
+ package_fixtures[:book],
125
+ [],
126
+
127
+ service: 'US-PM',
128
+ image_type: 'Epl',
129
+ return_image_data: true,
130
+ sample_only: true
131
+ )
132
+
133
+ assert_equal 'Stamps', response.rate.carrier
134
+ assert_equal 'USPS Priority Mail', response.rate.service_name
135
+ assert_equal 'US-PM', response.rate.service_code
136
+ assert_equal 'USD', response.rate.currency
137
+ assert_equal '90210', response.rate.origin.zip
138
+ assert_equal '10017', response.rate.destination.zip
139
+ assert_equal 'US', response.rate.destination.country_code
140
+
141
+ assert_kind_of Integer, response.rate.total_price
142
+ assert_instance_of String, response.stamps_tx_id
143
+
144
+ assert_nil response.label_url
145
+
146
+ assert_equal ";\r\n; ", response.image[0..4]
147
+ end
148
+
149
+ def test_international_shipment
150
+ ottawa_with_name = Location.new(location_fixtures[:ottawa].to_hash.merge(name: 'Bob Bobsen'))
151
+
152
+ response = @carrier.create_shipment(
153
+ location_fixtures[:new_york_with_name],
154
+ ottawa_with_name,
155
+ package_fixtures[:declared_value],
156
+ line_item_fixture,
157
+
158
+ service: 'US-PMI',
159
+ content_type: 'Merchandise',
160
+ sample_only: true
161
+
162
+ )
163
+
164
+ assert_equal 'Stamps', response.rate.carrier
165
+ assert_equal 'USPS Priority Mail International', response.rate.service_name
166
+ assert_equal 'US-PMI', response.rate.service_code
167
+ assert_equal 'USD', response.rate.currency
168
+ assert_equal '10017', response.rate.origin.zip
169
+ assert_equal 'K1P 1J1', response.rate.destination.zip
170
+ assert_equal 'CA', response.rate.destination.country_code
171
+
172
+ assert_kind_of Integer, response.rate.total_price
173
+ assert_instance_of String, response.stamps_tx_id
174
+ assert_instance_of String, response.label_url
175
+
176
+ assert_equal "https://", response.label_url[0..7]
177
+ assert_equal "%PDF", response.image[0..3]
178
+ end
179
+
180
+ def test_track_shipment
181
+ skip '<#<ReactiveShipping::ResponseError: Insufficient Postage>>.'
182
+
183
+ # Tracking is not available for sample only shipments
184
+ shipment = @carrier.create_shipment(
185
+ location_fixtures[:beverly_hills],
186
+ location_fixtures[:new_york_with_name],
187
+ package_fixtures[:book],
188
+ [],
189
+
190
+ service: 'US-MM',
191
+ insured_value: 70,
192
+ add_ons: %w(US-A-INS US-A-DC)
193
+
194
+ )
195
+ tracking = @carrier.find_tracking_info(shipment.tracking_number)
196
+
197
+ assert_equal :stamps, tracking.carrier
198
+ assert_equal "Stamps", tracking.carrier_name
199
+ assert_equal :electronic_notification, tracking.status
200
+ assert_equal "ElectronicNotification", tracking.status_code
201
+
202
+ assert_equal 1, tracking.shipment_events.length
203
+
204
+ event = tracking.shipment_events.first
205
+ assert_equal "Electronic Notification", event.name
206
+ assert_equal "90210", event.location.zip
207
+
208
+ assert_instance_of Time, event.time
209
+ end
210
+
211
+ def test_track_with_stamps_tx_id
212
+ skip '<#<ReactiveShipping::ResponseError: Insufficient Postage>>.'
213
+ # Tracking is not available for sample only shipments
214
+ shipment = @carrier.create_shipment(
215
+ location_fixtures[:beverly_hills],
216
+ location_fixtures[:new_york_with_name],
217
+ package_fixtures[:book],
218
+ [],
219
+
220
+ service: 'US-MM',
221
+ insured_value: 70,
222
+ add_ons: %w(US-A-INS US-A-DC)
223
+ )
224
+ tracking = @carrier.find_tracking_info(shipment.stamps_tx_id, stamps_tx_id: true)
225
+
226
+ assert_equal :stamps, tracking.carrier
227
+ assert_equal "Stamps", tracking.carrier_name
228
+ assert_equal :electronic_notification, tracking.status
229
+ assert_equal "ElectronicNotification", tracking.status_code
230
+
231
+ assert_equal 1, tracking.shipment_events.length
232
+
233
+ event = tracking.shipment_events.first
234
+ assert_equal "Electronic Notification", event.name
235
+ assert_equal "90210", event.location.zip
236
+
237
+ assert_instance_of Time, event.time
238
+ end
239
+
240
+ def test_tracking_with_bad_number
241
+ assert_raises(ResponseError) do
242
+ @carrier.find_tracking_info('abc123xyz')
243
+ end
244
+ end
245
+
246
+ def test_zip_to_zip
247
+ response = @carrier.find_rates(
248
+ Location.new(:zip => 40524),
249
+ Location.new(:zip => 40515),
250
+ Package.new(16, [12, 6, 2], units: :imperial)
251
+ )
252
+ assert response.success?
253
+ end
254
+
255
+ def test_add_ons
256
+ response = @carrier.find_rates(
257
+ location_fixtures[:beverly_hills],
258
+ location_fixtures[:new_york],
259
+ package_fixtures[:book],
260
+ add_ons: 'US-A-DC'
261
+ )
262
+
263
+ assert response.success?, response.message
264
+ end
265
+
266
+ def test_just_country_given
267
+ response = @carrier.find_rates(
268
+ location_fixtures[:beverly_hills],
269
+ Location.new(:country => 'CZ'),
270
+ Package.new(100, [5, 10, 20])
271
+ )
272
+
273
+ assert response.success?, response.message
274
+ end
275
+
276
+ def test_us_to_canada
277
+ response = @carrier.find_rates(
278
+ location_fixtures[:beverly_hills],
279
+ location_fixtures[:ottawa],
280
+ package_fixtures[:american_wii]
281
+ )
282
+
283
+ refute response.rates.empty?
284
+ end
285
+
286
+ def test_domestic_rates
287
+ response = @carrier.find_rates(
288
+ location_fixtures[:new_york],
289
+ location_fixtures[:beverly_hills],
290
+ package_fixtures[:american_wii]
291
+ )
292
+
293
+ assert response.success?, response.message
294
+ assert_instance_of Hash, response.params
295
+ assert_instance_of String, response.xml
296
+ assert_instance_of Array, response.rates
297
+ refute response.rates.empty?
298
+
299
+ rate = response.rates.first
300
+ assert_equal 'Stamps', rate.carrier
301
+ assert_equal 'USD', rate.currency
302
+ assert_kind_of Integer, rate.total_price
303
+ assert_kind_of Integer, rate.price
304
+ assert_instance_of String, rate.service_name
305
+ assert_instance_of String, rate.service_code
306
+ assert_instance_of Array, rate.package_rates
307
+
308
+ package = rate.packages.first
309
+ assert_equal package_fixtures[:american_wii].weight, package.weight
310
+ assert_equal package_fixtures[:american_wii].inches, package.inches
311
+ assert_equal package_fixtures[:american_wii].value, package.value
312
+ assert_equal package_fixtures[:american_wii].options[:units], package.options[:units]
313
+ end
314
+
315
+ def test_international_rates
316
+ response = @carrier.find_rates(
317
+ location_fixtures[:beverly_hills],
318
+ location_fixtures[:ottawa],
319
+ package_fixtures[:book]
320
+ )
321
+
322
+ assert response.success?, response.message
323
+ assert_instance_of Hash, response.params
324
+ assert_instance_of String, response.xml
325
+ assert_instance_of Array, response.rates
326
+ refute response.rates.empty?
327
+
328
+ rate = response.rates.first
329
+ assert_equal 'Stamps', rate.carrier
330
+ assert_equal 'USD', rate.currency
331
+ assert_kind_of Integer, rate.total_price
332
+ assert_kind_of Integer, rate.price
333
+ assert_instance_of String, rate.service_name
334
+ assert_instance_of String, rate.service_code
335
+ assert_instance_of Array, rate.package_rates
336
+
337
+ package = rate.packages.first
338
+ assert_equal package_fixtures[:book].weight, package.weight
339
+ assert_equal package_fixtures[:book].inches, package.inches
340
+ end
341
+
342
+ def test_us_to_us_possession
343
+ response = @carrier.find_rates(
344
+ location_fixtures[:beverly_hills],
345
+ location_fixtures[:puerto_rico],
346
+ package_fixtures[:american_wii]
347
+ )
348
+
349
+ refute response.rates.empty?
350
+ end
351
+
352
+ def test_bare_packages_domestic
353
+ response = @carrier.find_rates(
354
+ location_fixtures[:beverly_hills], # imperial (U.S. origin)
355
+ location_fixtures[:new_york],
356
+ Package.new(0, 0)
357
+ )
358
+
359
+ assert response.success?, response.message
360
+ end
361
+
362
+ def test_bare_packages_international
363
+ response = @carrier.find_rates(
364
+ location_fixtures[:beverly_hills], # imperial (U.S. origin)
365
+ location_fixtures[:ottawa],
366
+ Package.new(0, 0)
367
+ )
368
+ assert response.success?, response.message
369
+ end
370
+
371
+ def test_first_class_packages_with_mail_type
372
+ response = @carrier.find_rates(
373
+ location_fixtures[:beverly_hills], # imperial (U.S. origin)
374
+ location_fixtures[:new_york],
375
+ Package.new(0, 0),
376
+
377
+ service: 'US-FC',
378
+ package_type: 'Package'
379
+ )
380
+
381
+ assert response.success?, response.message
382
+ end
383
+
384
+ def test_first_class_packages_with_invalid_mail_type
385
+ assert_raises(ResponseError) do
386
+ @carrier.find_rates(
387
+ location_fixtures[:beverly_hills], # imperial (U.S. origin)
388
+ location_fixtures[:new_york],
389
+ Package.new(0, 0),
390
+
391
+ service: 'US-FC',
392
+ package_type: 'Invalid'
393
+ )
394
+ end
395
+ end
396
+ end