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,232 @@
1
+ require 'test_helper'
2
+
3
+ class PackageItemTest < ActiveSupport::TestCase
4
+ setup do
5
+ @name = "Fancy Pants"
6
+ @weight = 100
7
+ @value = 1299
8
+ @quantity = 3
9
+ @sku = "1234567890"
10
+ @hs_code = "1234.56.78"
11
+ @options = {
12
+ units: :metric,
13
+ sku: @sku,
14
+ hs_code: @hs_code,
15
+ type: :actual,
16
+ }
17
+
18
+ @item = PackageItem.new(@name, @weight, @value, @quantity, @options)
19
+ @mass = Measured::Weight.new(@weight, :grams)
20
+ end
21
+
22
+ test "#initialize with all attributes" do
23
+ assert_equal @name, @item.name
24
+ assert_equal @options, @item.options
25
+ assert_equal @hs_code, @item.hs_code
26
+ assert_equal @sku, @item.sku
27
+ assert_equal @value, @item.value
28
+ assert_equal @quantity, @item.quantity
29
+ end
30
+
31
+ test "#initialize assumes symbol keys" do
32
+ options = {
33
+ "units" => :imperial,
34
+ "sku" => @sku,
35
+ "hs_code" => @hs_code,
36
+ }
37
+ @item = PackageItem.new(@name, @weight, @value, @quantity, options)
38
+
39
+ assert_nil @item.hs_code
40
+ assert_nil @item.sku
41
+ refute_equal @weight, @item.ounces
42
+ assert_equal @weight, @item.grams
43
+ end
44
+
45
+ test "#initialize with a negative quantity" do
46
+ assert_equal 1, PackageItem.new(@name, @weight, @value, -1).quantity
47
+ assert_equal 1, PackageItem.new(@name, @weight, @value, 0).quantity
48
+ end
49
+
50
+ test "#initialize weight mass object" do
51
+ @item = PackageItem.new(@name, @mass, @value, @quantity, @options)
52
+ assert_equal @mass, @item.weight
53
+ end
54
+
55
+ test "#initialize weight default metric" do
56
+ assert_equal @weight, @item.grams
57
+ refute_equal @weight, @item.ounces
58
+ end
59
+
60
+ test "#initialize weight accepts imperial" do
61
+ @item = PackageItem.new(@name, @weight, @value, @quantity, @options.merge(units: :imperial))
62
+
63
+ assert_equal @weight, @item.ounces
64
+ refute_equal @weight, @item.grams
65
+ end
66
+
67
+ test "#initialize_weight accepts metric" do
68
+ @item = PackageItem.new(@name, @weight, @value, @quantity, @options.merge(units: :metric))
69
+
70
+ assert_equal @weight, @item.grams
71
+ refute_equal @weight, @item.ounces
72
+ end
73
+
74
+ test "#initialize weight does not accept strings" do
75
+ @item = PackageItem.new(@name, @weight, @value, @quantity, @options.merge(units: "imperial"))
76
+
77
+ assert_equal @weight, @item.grams
78
+ refute_equal @weight, @item.ounces
79
+ end
80
+
81
+ test "#initialize value from cents" do
82
+ @item = PackageItem.new(@name, @weight, "1.23", @quantity, @options)
83
+
84
+ assert_equal 123, @item.value
85
+ end
86
+
87
+ test "#weight default lookup" do
88
+ assert_equal @mass, @item.weight
89
+ assert_instance_of Measured::Weight, @item.weight
90
+ end
91
+
92
+ test "#weight type: actual" do
93
+ assert_equal @mass, @item.weight(type: :actual)
94
+ assert_instance_of Measured::Weight, @item.weight(type: :actual)
95
+ end
96
+
97
+ test "#weight type: volumetric" do
98
+ begin
99
+ assert_equal :todo, @item.weight(type: :volumetric)
100
+ assert_instance_of Measured::Weight, @item.weight(type: :volumetric)
101
+ flunk "This code path is broken but passed unexpectedly"
102
+ rescue NoMethodError
103
+ skip "This code path is broken"
104
+ end
105
+ end
106
+
107
+ test "#weight type: dimensional" do
108
+ begin
109
+ assert_equal :todo, @item.weight(type: :dimensional)
110
+ assert_instance_of Measured::Weight, @item.weight(type: :dimensional)
111
+ flunk "This code path is broken but passed unexpectedly"
112
+ rescue NoMethodError
113
+ skip "This code path is broken"
114
+ end
115
+ end
116
+
117
+ test "#weight type: billable is the max of weight and volumetric" do
118
+ begin
119
+ assert_equal :todo, @item.weight(type: :billable)
120
+ assert_instance_of Measured::Weight, @item.weight(type: :billable)
121
+ flunk "This code path is broken but passed unexpectedly"
122
+ rescue NoMethodError
123
+ skip "This code path is broken"
124
+ end
125
+ end
126
+
127
+ test "#grams is the value" do
128
+ assert_equal 100, @item.grams
129
+ end
130
+
131
+ test "#grams accepts options with type" do
132
+ begin
133
+ assert_equal :todo, @item.grams(type: :volumetric)
134
+ flunk "This code path is broken but passed unexpectedly"
135
+ rescue NoMethodError
136
+ skip "This code path is broken"
137
+ end
138
+ end
139
+
140
+ test "#grams converts to another unit" do
141
+ @item = PackageItem.new(@name, 100, @value, @quantity, @options.merge(units: :imperial))
142
+
143
+ assert_in_delta 2834.9, @item.grams, 0.1
144
+ end
145
+
146
+ test "#grams aliases to g" do
147
+ assert_equal @item.grams, @item.g
148
+ end
149
+
150
+ test "#ounces is the value" do
151
+ @item = PackageItem.new(@name, @weight, @value, @quantity, @options.merge(units: :imperial))
152
+
153
+ assert_equal 100, @item.ounces
154
+ end
155
+
156
+ test "#ounces accepts options with type" do
157
+ begin
158
+ assert_equal :todo, @item.ounces(type: :volumetric)
159
+ flunk "This code path is broken but passed unexpectedly"
160
+ rescue NoMethodError
161
+ skip "This code path is broken"
162
+ end
163
+ end
164
+
165
+ test "#ounces converts to another unit" do
166
+ @item = PackageItem.new(@name, @weight, @value, @quantity, @options.merge(units: :metric))
167
+
168
+ assert_in_delta 3.5, @item.ounces, 0.1
169
+ end
170
+
171
+ test "#ounces aliases to oz" do
172
+ assert_equal @item.ounces, @item.oz
173
+ end
174
+
175
+ test "#pounds is the value" do
176
+ @item = PackageItem.new(@name, 32, @value, @quantity, @options.merge(units: :imperial))
177
+
178
+ assert_equal 2, @item.pounds
179
+ end
180
+
181
+ test "#pounds accepts options with type" do
182
+ begin
183
+ assert_equal :todo, @item.pounds(type: :volumetric)
184
+ flunk "This code path is broken but passed unexpectedly"
185
+ rescue
186
+ skip "This code path is broken"
187
+ end
188
+ end
189
+
190
+ test "#pounds converts to another unit" do
191
+ @item = PackageItem.new(@name, 1000, @value, @quantity, @options.merge(units: :metric))
192
+
193
+ assert_in_delta 2.2, @item.pounds, 0.1
194
+ end
195
+
196
+ test "#pounds aliases to lb" do
197
+ assert_equal @item.pounds, @item.lb
198
+ end
199
+
200
+ test "#pounds aliases to lbs" do
201
+ assert_equal @item.pounds, @item.lbs
202
+ end
203
+
204
+ test "#kilograms is the value" do
205
+ @item = PackageItem.new(@name, 1000, @value, @quantity, @options.merge(units: :metric))
206
+
207
+ assert_equal 1, @item.kilograms
208
+ end
209
+
210
+ test "#kilograms accepts options with type" do
211
+ begin
212
+ assert_equal :todo, @item.kilograms(type: :volumetric)
213
+ flunk "This code path is broken but passed unexpectedly"
214
+ rescue
215
+ skip "This code path is broken"
216
+ end
217
+ end
218
+
219
+ test "#kilograms converts to another unit" do
220
+ @item = PackageItem.new(@name, 1000, @value, @quantity, @options.merge(units: :imperial))
221
+
222
+ assert_in_delta 28.3, @item.kilograms, 0.1
223
+ end
224
+
225
+ test "#kilograms aliases to kg" do
226
+ assert_equal @item.kilograms, @item.kg
227
+ end
228
+
229
+ test "#kilograms aliases to kgs" do
230
+ assert_equal @item.kilograms, @item.kgs
231
+ end
232
+ end
@@ -0,0 +1,404 @@
1
+ require 'test_helper'
2
+
3
+ class PackageTest < ActiveSupport::TestCase
4
+ setup do
5
+ @weight = 100
6
+ @dimensions = [5, 6, 7]
7
+ @value = 1299
8
+ @currency = "USD"
9
+ @cylinder = false
10
+ @tube = false
11
+ @gift = false
12
+ @oversized = false
13
+ @unpackaged = false
14
+ @dim_units = :metric
15
+ @units = :metric
16
+ @weight_units = :metric
17
+ @options = {
18
+ value: @value,
19
+ currency: @currency,
20
+ cylinder: @cylinder,
21
+ tube: @tube,
22
+ gift: @gift,
23
+ oversized: @oversized,
24
+ unpackaged: @unpackaged,
25
+ dim_units: @dim_units,
26
+ units: @units,
27
+ weight_units: @weight_units,
28
+ }
29
+
30
+ @package = Package.new(@weight, @dimensions, @options)
31
+ @imperial_package = Package.new(@weight, @dimensions, @options.merge(units: :imperial, dim_units: :imperial, weight_units: :imperial))
32
+
33
+ @mass = Measured::Weight.new(@weight, :grams)
34
+ end
35
+
36
+ test "#initialize package from mass" do
37
+ ten_pounds = Measured::Weight.new(10, :pounds)
38
+ package = Package.new(ten_pounds, [])
39
+ assert_equal ten_pounds, package.weight
40
+ end
41
+
42
+ test "#initialize with defaults" do
43
+ assert_equal @value, @package.value
44
+ assert_equal @currency, @package.currency
45
+ assert_equal @cylinder, @package.cylinder?
46
+ assert_equal @tube, @package.tube?
47
+ assert_equal @oversized, @package.oversized?
48
+ assert_equal @unpackaged, @package.unpackaged?
49
+ assert_equal @gift, @package.gift?
50
+ end
51
+
52
+ test "#initialize with currency cents" do
53
+ @package = Package.new(@weight, @dimensions, value: money)
54
+ assert_equal @currency, @package.currency
55
+ assert_equal @value, @package.value
56
+ end
57
+
58
+ test "#initialize sorts the passed in dimensions" do
59
+ @package = Package.new(@weight, [9, 8, 7], @options)
60
+
61
+ assert_equal [7, 8, 9], @package.centimetres
62
+ end
63
+
64
+ test "#initialize sets default dimensions if blank" do
65
+ @package = Package.new(@weight, [], @options)
66
+
67
+ assert_equal [0, 0, 0], @package.centimetres
68
+ end
69
+
70
+ test "#initialize increases dimension size to three elements in the array and pads" do
71
+ @package = Package.new(@weight, [2], @options)
72
+
73
+ assert_equal [2, 2, 2], @package.centimetres
74
+ end
75
+
76
+ test "#initialize default units" do
77
+ assert_equal @dimensions, @package.centimetres
78
+ assert_equal @weight, @package.grams
79
+ end
80
+
81
+ test "#initialize units" do
82
+ assert_equal @dimensions, @imperial_package.inches
83
+ end
84
+
85
+ test "#initialize weight_units" do
86
+ @package = Package.new(@weight, @dimensions, @options.merge(weight_units: :imperial))
87
+
88
+ assert_equal @weight, @package.ounces
89
+ end
90
+
91
+ test "#unpackaged?" do
92
+ assert_predicate Package.new(@weight, @dimensions, unpackaged: true), :unpackaged?
93
+ refute_predicate Package.new(@weight, @dimensions, unpackaged: false), :unpackaged?
94
+ end
95
+
96
+ test "#oversized?" do
97
+ assert_predicate Package.new(@weight, @dimensions, oversized: true), :oversized?
98
+ refute_predicate Package.new(@weight, @dimensions, oversized: false), :oversized?
99
+ end
100
+
101
+ test "#gift?" do
102
+ assert_predicate Package.new(@weight, @dimensions, gift: true), :gift?
103
+ refute_predicate Package.new(@weight, @dimensions, gift: false), :gift?
104
+ end
105
+
106
+ test "#cylinder? and #tube? check both values" do
107
+ @package = Package.new(@weight, @dimensions, cylinder: false, tube: false)
108
+ refute_predicate @package, :cylinder?
109
+ refute_predicate @package, :tube?
110
+
111
+ @package = Package.new(@weight, @dimensions, cylinder: true, tube: false)
112
+ assert_predicate @package, :cylinder?
113
+ assert_predicate @package, :tube?
114
+
115
+ @package = Package.new(@weight, @dimensions, cylinder: false, tube: true)
116
+ assert_predicate @package, :cylinder?
117
+ assert_predicate @package, :tube?
118
+
119
+ @package = Package.new(@weight, @dimensions, cylinder: true, tube: true)
120
+ assert_predicate @package, :cylinder?
121
+ assert_predicate @package, :tube?
122
+ end
123
+
124
+ test "#inches performs lookup with a numerical index" do
125
+ assert_equal @dimensions[0], @imperial_package.inches(0)
126
+ assert_equal @dimensions[1], @imperial_package.inches(1)
127
+ assert_equal @dimensions[2], @imperial_package.inches(2)
128
+ assert_nil @imperial_package.inches(3)
129
+ end
130
+
131
+ test "#inches for dimension x" do
132
+ assert_equal @dimensions[2], @imperial_package.inches(:x)
133
+ assert_equal @dimensions[2], @imperial_package.inches(:max)
134
+ assert_equal @dimensions[2], @imperial_package.inches(:length)
135
+ assert_equal @dimensions[2], @imperial_package.inches(:long)
136
+ end
137
+
138
+ test "#inches for dimension y" do
139
+ assert_equal @dimensions[1], @imperial_package.inches(:y)
140
+ assert_equal @dimensions[1], @imperial_package.inches(:mid)
141
+ assert_equal @dimensions[1], @imperial_package.inches(:width)
142
+ assert_equal @dimensions[1], @imperial_package.inches(:wide)
143
+ end
144
+
145
+ test "#inches for dimension z" do
146
+ assert_equal @dimensions[0], @imperial_package.inches(:z)
147
+ assert_equal @dimensions[0], @imperial_package.inches(:min)
148
+ assert_equal @dimensions[0], @imperial_package.inches(:height)
149
+ assert_equal @dimensions[0], @imperial_package.inches(:depth)
150
+ assert_equal @dimensions[0], @imperial_package.inches(:high)
151
+ assert_equal @dimensions[0], @imperial_package.inches(:deep)
152
+ end
153
+
154
+ test "#inches for girth of a cylinder" do
155
+ @imperial_package = Package.new(@weight, @dimensions, @options.merge(cylinder: true, units: :imperial, dim_units: :imperial))
156
+
157
+ assert_predicate @imperial_package, :cylinder?
158
+ assert_in_delta 17.2, @imperial_package.inches(:girth), 1
159
+ assert_in_delta 17.2, @imperial_package.inches(:around), 1
160
+ assert_in_delta 17.2, @imperial_package.inches(:circumference), 1
161
+
162
+ end
163
+
164
+ test "#inches for girth of a non cylinder" do
165
+ refute_predicate @imperial_package, :cylinder?
166
+ assert_in_delta 22, @imperial_package.inches(:girth), 1
167
+ assert_in_delta 22, @imperial_package.inches(:around), 1
168
+ assert_in_delta 22, @imperial_package.inches(:circumference), 1
169
+ end
170
+
171
+ test "#inches for the volume of a cylinder" do
172
+ @imperial_package = Package.new(@weight, @dimensions, @options.merge(cylinder: true, units: :imperial, dim_units: :imperial))
173
+
174
+ assert_predicate @imperial_package, :cylinder?
175
+ assert_in_delta 522.4, @imperial_package.inches(:volume), 1
176
+ end
177
+
178
+ test "#inches for volume" do
179
+ refute_predicate @imperial_package, :cylinder?
180
+ assert_equal 210, @imperial_package.inches(:volume)
181
+ end
182
+
183
+ test "#inches for box_volume" do
184
+ assert_equal 210, @imperial_package.inches(:box_volume)
185
+ end
186
+
187
+ test "#inches of an unknown value" do
188
+ assert_nil @imperial_package.inches(:unknown)
189
+ end
190
+
191
+ test "#inches alias to #in" do
192
+ assert_equal @dimensions, @imperial_package.inches
193
+ assert_equal @dimensions, @imperial_package.in
194
+ end
195
+
196
+ test "#centimetres performs lookup with a numerical index" do
197
+ assert_equal @dimensions[0], @package.centimetres(0)
198
+ assert_equal @dimensions[1], @package.centimetres(1)
199
+ assert_equal @dimensions[2], @package.centimetres(2)
200
+ assert_nil @package.centimetres(3)
201
+ end
202
+
203
+ test "#centimetres for dimension x" do
204
+ assert_equal @dimensions[2], @package.centimetres(:x)
205
+ assert_equal @dimensions[2], @package.centimetres(:max)
206
+ assert_equal @dimensions[2], @package.centimetres(:length)
207
+ assert_equal @dimensions[2], @package.centimetres(:long)
208
+ end
209
+
210
+ test "#centimetres for dimension y" do
211
+ assert_equal @dimensions[1], @package.centimetres(:y)
212
+ assert_equal @dimensions[1], @package.centimetres(:mid)
213
+ assert_equal @dimensions[1], @package.centimetres(:width)
214
+ assert_equal @dimensions[1], @package.centimetres(:wide)
215
+ end
216
+
217
+ test "#centimetres for dimension z" do
218
+ assert_equal @dimensions[0], @package.centimetres(:z)
219
+ assert_equal @dimensions[0], @package.centimetres(:min)
220
+ assert_equal @dimensions[0], @package.centimetres(:height)
221
+ assert_equal @dimensions[0], @package.centimetres(:depth)
222
+ assert_equal @dimensions[0], @package.centimetres(:high)
223
+ assert_equal @dimensions[0], @package.centimetres(:deep)
224
+ end
225
+
226
+ test "#centimetres for girth of a cylinder" do
227
+ @package = Package.new(@weight, @dimensions, @options.merge(cylinder: true, units: :metric, dim_units: :metric))
228
+
229
+ assert_predicate @package, :cylinder?
230
+ assert_in_delta 17.2, @package.centimetres(:girth), 1
231
+ assert_in_delta 17.2, @package.centimetres(:around), 1
232
+ assert_in_delta 17.2, @package.centimetres(:circumference), 1
233
+
234
+ end
235
+
236
+ test "#centimetres for girth of a non-cylinder" do
237
+ refute_predicate @package, :cylinder?
238
+ assert_in_delta 22, @package.centimetres(:girth), 1
239
+ assert_in_delta 22, @package.centimetres(:around), 1
240
+ assert_in_delta 22, @package.centimetres(:circumference), 1
241
+ end
242
+
243
+ test "#centimetres for the volume of a cylinder" do
244
+ @package = Package.new(@weight, @dimensions, @options.merge(cylinder: true, units: :metric, dim_units: :metric))
245
+
246
+ assert_predicate @package, :cylinder?
247
+ assert_in_delta 522.4, @package.centimetres(:volume), 1
248
+ end
249
+
250
+ test "#centimetres for volume" do
251
+ refute_predicate @package, :cylinder?
252
+ assert_equal 210, @package.centimetres(:volume)
253
+ end
254
+
255
+ test "#centimetres for box_volume" do
256
+ assert_equal 210, @package.centimetres(:box_volume)
257
+ end
258
+
259
+ test "#centimetres of an unknown value" do
260
+ assert_nil @package.centimetres(:unknown)
261
+ end
262
+
263
+ test "#centimetres alias to #cm" do
264
+ assert_equal @dimensions, @package.centimetres
265
+ assert_equal @dimensions, @package.cm
266
+ end
267
+
268
+ test "#weight" do
269
+ assert_equal @mass, @package.weight
270
+ assert_instance_of Measured::Weight, @package.weight
271
+ end
272
+
273
+ test "#weight for actual" do
274
+ assert_equal @mass, @package.weight(type: :actual)
275
+ assert_instance_of Measured::Weight, @package.weight(type: :actual)
276
+ end
277
+
278
+ test "#weight volumetric" do
279
+ assert_equal Measured::Weight.new(35, :grams), @package.weight(type: :volumetric)
280
+ end
281
+
282
+ test "#weight dimensional" do
283
+ assert_equal Measured::Weight.new(35, :grams), @package.weight(type: :dimensional)
284
+ end
285
+
286
+ test "#weight billable is the max of weight and volumetric" do
287
+ assert_equal Measured::Weight.new(100, :grams), @package.weight(type: :billable)
288
+
289
+ @package = Package.new(500, [1, 1, 1], @options)
290
+ assert_equal Measured::Weight.new(500, :grams), @package.weight(type: :billable)
291
+ end
292
+
293
+ test "#grams value" do
294
+ assert_equal 100, @package.grams
295
+ end
296
+
297
+ test "#grams accepts options with type" do
298
+ assert_in_delta 35, @package.grams(type: :volumetric), 1
299
+ end
300
+
301
+ test "#grams converts to another unit from another system" do
302
+ @package = Package.new(@weight, @dimensions, weight_units: :imperial)
303
+
304
+ assert_in_delta 2834.9, @package.grams, 1
305
+ end
306
+
307
+ test "#grams alias to #g" do
308
+ assert_equal @package.grams, @package.g
309
+ end
310
+
311
+ test "#ounces value" do
312
+ assert_equal 100, @imperial_package.ounces
313
+ end
314
+
315
+ test "#ounces accepts options with type" do
316
+ assert_in_delta 20.2, @imperial_package.ounces(type: :volumetric), 1
317
+ end
318
+
319
+ test "#ounces converts to another unit from another system" do
320
+ assert_in_delta 3.5, @package.ounces, 1
321
+ end
322
+
323
+ test "#ounces alias to #oz" do
324
+ assert_equal @imperial_package.ounces, @imperial_package.oz
325
+ end
326
+
327
+ test "#pounds value" do
328
+ assert_equal 6.25, @imperial_package.pounds
329
+ end
330
+
331
+ test "#pounds accepts options with type" do
332
+ assert_in_delta 0.07, @package.pounds(type: :volumetric), 0.01
333
+ end
334
+
335
+ test "#pounds converts to another unit from another system" do
336
+ assert_in_delta 0.22, @package.pounds, 0.01
337
+ end
338
+
339
+ test "#pounds alias to #lb" do
340
+ assert_equal @package.pounds, @package.lb
341
+ end
342
+
343
+ test "#pounds alias to #lbs" do
344
+ assert_equal @package.pounds, @package.lbs
345
+ end
346
+
347
+ test "#kilograms value" do
348
+ assert_equal 0.1, @package.kilograms
349
+ end
350
+
351
+ test "#kilograms accepts options with type" do
352
+ assert_equal 0.035, @package.kilograms(type: :volumetric)
353
+ end
354
+
355
+ test "#kilograms converts to another unit from another system" do
356
+ assert_in_delta 2.8, @imperial_package.kilograms, 1
357
+ end
358
+
359
+ test "#kilograms alias to #kg" do
360
+ assert_equal 0.1, @package.kg
361
+ end
362
+
363
+ test "#kilograms alias to #kgs" do
364
+ assert_equal @package.kilograms, @package.kgs
365
+ end
366
+
367
+ test ".cents_from nil" do
368
+ assert_nil Package.cents_from(nil)
369
+ end
370
+
371
+ test ".cents_from cents on a money object" do
372
+ assert_equal @value, Package.cents_from(money)
373
+ end
374
+
375
+ test ".cents_from float" do
376
+ assert_equal 120, Package.cents_from(1.2)
377
+ end
378
+
379
+ test ".cents_from string" do
380
+ assert_equal 120, Package.cents_from("1.20")
381
+ end
382
+
383
+ test ".cents_from integer" do
384
+ assert_equal 12, Package.cents_from(12)
385
+ end
386
+
387
+ test ".cents_from an unhandled object" do
388
+ exception = assert_raises NoMethodError do
389
+ Package.cents_from(Object.new)
390
+ end
391
+ assert_match /undefined method `to_i'/, exception.message
392
+ end
393
+
394
+ private
395
+
396
+ def money
397
+ @money ||= begin
398
+ value = Class.new { attr_accessor :currency, :cents }.new
399
+ value.currency = @currency
400
+ value.cents = @value
401
+ value
402
+ end
403
+ end
404
+ end