Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Added USPS International Shipping Rate (IntlRateV2) functionality

USPS::Request::InternationalShippingRatesLookup can be used with
USPS::Request::Package::InternationalPackage to calculate international
shipping rates.
Because of the profileration of shipping-rate-related classes, the files
have been reorganized.

Squashed commit of the following:

commit a1cd232
Author: Nicholas Yianilos <npy@reenhanced.com>
Date:   Tue Sep 18 11:54:35 2012 -0400

    fixed bug related to required properties in Packages

commit 565f3d3
Author: Nicholas Yianilos <npy@reenhanced.com>
Date:   Tue Sep 18 11:01:10 2012 -0400

    updated 'missing package' error messages

commit fac4887
Author: Nicholas Yianilos <npy@reenhanced.com>
Date:   Tue Sep 18 10:23:34 2012 -0400

    added specs for response

commit f3b92d8
Author: Nicholas Yianilos <npy@reenhanced.com>
Date:   Mon Sep 17 10:15:23 2012 -0400

    tests for international package request and lookup

commit a9e7769
Author: Nicholas Yianilos <npy@reenhanced.com>
Date:   Thu Sep 13 15:34:39 2012 -0400

    allow package to be initialized in block, not just with option hash

commit 3901ddd
Author: Nicholas Yianilos <npy@reenhanced.com>
Date:   Thu Sep 13 15:29:22 2012 -0400

    always include dimension elements, even if they're blank

commit 163e3d1
Author: Nicholas Yianilos <npy@reenhanced.com>
Date:   Wed Sep 12 17:00:01 2012 -0400

    Implemented RateV2 (Int'l) API. Restructured existing Shipping Rate (V2) functionality. Needs better testing
  • Loading branch information...
commit 235111b2538e5b2ea39bf0310d4c9f0ae83ce4c4 1 parent 95bdba0
Nicholas Yianilos authored
Showing with 490 additions and 62 deletions.
  1. +0 −3  lib/usps.rb
  2. +0 −18 lib/usps/package.rb
  3. +0 −14 lib/usps/package_response.rb
  4. +0 −4 lib/usps/postage.rb
  5. +8 −6 lib/usps/request.rb
  6. +1 −1  lib/usps/request/base.rb
  7. +42 −0 lib/usps/request/international_shipping_rates_lookup.rb
  8. +5 −0 lib/usps/request/package.rb
  9. +37 −0 lib/usps/request/package/base.rb
  10. +18 −0 lib/usps/request/package/domestic_package.rb
  11. +11 −0 lib/usps/request/package/international_package.rb
  12. +1 −1  lib/usps/request/shipping_rates_lookup.rb
  13. +9 −7 lib/usps/response.rb
  14. +27 −0 lib/usps/response/international_shipping_rates_lookup.rb
  15. +4 −0 lib/usps/response/package.rb
  16. +15 −0 lib/usps/response/package/domestic_package.rb
  17. +18 −0 lib/usps/response/package/international_package.rb
  18. +2 −2 lib/usps/response/shipping_rates_lookup.rb
  19. +162 −0 spec/data/international_shipping_rates_lookup.xml
  20. +6 −5 spec/package_spec.rb
  21. +57 −0 spec/request/international_shipping_rates_lookup_spec.rb
  22. +41 −0 spec/request/package/international_package_spec.rb
  23. +1 −1  spec/request/shipping_rates_lookup_spec.rb
  24. +25 −0 spec/response/international_shipping_rates_lookup_spec.rb
View
3  lib/usps.rb
@@ -11,9 +11,6 @@ module USPS
autoload :VERSION, 'usps/version'
autoload :Response, 'usps/response'
autoload :TrackDetail, 'usps/track_detail'
- autoload :Package, 'usps/package'
- autoload :PackageResponse, 'usps/package_response'
- autoload :Postage, 'usps/postage'
class << self
attr_writer :config
View
18 lib/usps/package.rb
@@ -1,18 +0,0 @@
-module USPS
-
- class Package < Struct.new(:id, :service, :origin_zip, :destination_zip, :pounds, :ounces, :container, :size,
- :width, :length, :height, :girth, :value, :amount_to_collect, :first_class_mail_type)
-
- @@required_properties = %w{id service origin_zip destination_zip pounds ounces container size}
-
- def initialize(args = {})
- args.each_pair { |k, v| send("#{k}=", v) }
- yield self if block_given?
-
- @@required_properties.each do |prop|
- raise ArgumentError, "#{prop} is required" unless send(prop)
- end
- end
- end
-
-end
View
14 lib/usps/package_response.rb
@@ -1,14 +0,0 @@
-module USPS
-
- class PackageResponse < Struct.new(:id, :origin_zip, :destination_zip, :pounds, :ounces, :container, :size)
-
- attr_accessor :postages
-
- def initialize(properties = {})
- properties.each_pair { |k, v| send("#{k}=", v) }
- yield self if block_given?
- end
-
- end
-
-end
View
4 lib/usps/postage.rb
@@ -1,4 +0,0 @@
-module USPS
- class Postage < Struct.new(:rate, :mail_service, :class_id)
- end
-end
View
14 lib/usps/request.rb
@@ -1,15 +1,17 @@
module USPS::Request
- autoload :Base, 'usps/request/base'
- autoload :ZipCodeLookup, 'usps/request/zip_code_lookup'
+ autoload :Base, 'usps/request/base'
+ autoload :ZipCodeLookup, 'usps/request/zip_code_lookup'
autoload :CityAndStateLookup, 'usps/request/city_and_state_lookup'
autoload :AddressStandardization, 'usps/request/address_standardization'
# Delivery and Signature confirmation.
# DeliveryConfirmationCertify and SignatureConfirmationCertify should be used for testing
- autoload :DeliveryConfirmation, 'usps/request/delivery_confirmation'
+ autoload :DeliveryConfirmation, 'usps/request/delivery_confirmation'
autoload :DeliveryConfirmationCertify, 'usps/request/delivery_confirmation_certify'
- autoload :TrackingLookup, 'usps/request/tracking_lookup'
- autoload :TrackingFieldLookup, 'usps/request/tracking_field_lookup'
- autoload :ShippingRatesLookup, 'usps/request/shipping_rates_lookup'
+ autoload :TrackingLookup, 'usps/request/tracking_lookup'
+ autoload :TrackingFieldLookup, 'usps/request/tracking_field_lookup'
+ autoload :ShippingRatesLookup, 'usps/request/shipping_rates_lookup'
+ autoload :InternationalShippingRatesLookup, 'usps/request/international_shipping_rates_lookup'
+ autoload :Package, 'usps/request/package'
end
View
2  lib/usps/request/base.rb
@@ -35,7 +35,7 @@ def response_for(xml)
end
def build(&block)
- builder = Builder::XmlMarkup.new(:indent => 0)
+ builder = Builder::XmlMarkup.new(:indent => 2)
builder.tag!(self.class.tag, :USERID => USPS.config.username, &block)
end
end
View
42 lib/usps/request/international_shipping_rates_lookup.rb
@@ -0,0 +1,42 @@
+module USPS::Request
+
+ class InternationalShippingRatesLookup < Base
+ config(
+ :api => 'IntlRateV2',
+ :tag => 'IntlRateV2Request',
+ :secure => false,
+ :response => USPS::Response::InternationalShippingRatesLookup
+ )
+
+ def initialize(*packages)
+ @packages = packages.flatten
+ if @packages.none?
+ raise ArgumentError, 'An IntlRateV2 shipping rate lookup requires at least one package (USPS::Request::Package::InternationalPackage)'
+ end
+ end
+
+ def build
+ super do |xml|
+ xml.Revision 2
+ @packages.each do |package|
+ xml.Package :ID => package.id do
+ xml.Pounds package.pounds
+ xml.Ounces package.ounces
+ xml.Machinable 'true' # for Service=ALL
+ xml.MailType package.mail_type
+ xml.ValueOfContents 103
+ xml.Country package.country
+ xml.Container package.container
+ xml.Size package.size
+ xml.Width package.width
+ xml.Length package.length
+ xml.Height package.height
+ xml.Girth nil
+ xml.CommercialFlag 'N'
+ end
+ end
+ end
+ end
+
+ end
+end
View
5 lib/usps/request/package.rb
@@ -0,0 +1,5 @@
+module USPS::Request::Package
+ autoload :Base, 'usps/request/package/base'
+ autoload :DomesticPackage, 'usps/request/package/domestic_package'
+ autoload :InternationalPackage, 'usps/request/package/international_package'
+end
View
37 lib/usps/request/package/base.rb
@@ -0,0 +1,37 @@
+module USPS::Request::Package
+ class Base
+ attr_accessor :id
+ attr_accessor :pounds, :ounces
+ attr_accessor :container
+ attr_accessor :size
+ attr_accessor :width, :length, :height, :girth
+
+ @required = [:id, :pounds, :ounces, :size]
+
+ def initialize(fields)
+ fields.each { |name, value| send("#{name}=", value) }
+
+ yield self if block_given?
+
+ if fields[:size] == 'LARGE'
+ [:container, :width, :length, :height].each do |field|
+ error "#{field} is required when Size=LARGE" unless send(field)
+ end
+ end
+
+ self.class.required_properties.each do |field|
+ error "#{field} is required" unless send(field)
+ end
+ end
+
+ protected
+
+ def self.required_properties
+ @required + (defined?(super) ? super : [])
+ end
+
+ def error(message)
+ raise ArgumentError.new message
+ end
+ end
+end
View
18 lib/usps/request/package/domestic_package.rb
@@ -0,0 +1,18 @@
+module USPS::Request::Package
+ class DomesticPackage < Base
+ attr_accessor :service
+ attr_accessor :first_class_mail_type
+ attr_accessor :origin_zip, :destination_zip
+ attr_accessor :value
+ attr_accessor :amount_to_collect
+
+ @required = [:service, :origin_zip, :destination_zip]
+
+ def initialize(fields = {})
+ if fields[:service] == 'FIRST CLASS' and !fields[:first_class_mail_type]
+ error "first_class_mail_type is required when Service=FIRST Class"
+ end
+ super
+ end
+ end
+end
View
11 lib/usps/request/package/international_package.rb
@@ -0,0 +1,11 @@
+module USPS::Request::Package
+ class InternationalPackage < Base
+ attr_accessor :country, :mail_type
+
+ @required = [:country, :mail_type]
+
+ def initialize(fields = {})
+ super
+ end
+ end
+end
View
2  lib/usps/request/shipping_rates_lookup.rb
@@ -11,7 +11,7 @@ class ShippingRatesLookup < Base
def initialize(*packages)
@packages = packages.flatten
if @packages.none?
- raise ArgumentError, 'A shipping rate lookup requires at least one package (USPS::Package)'
+ raise ArgumentError, 'A RateV4 shipping rate lookup requires at least one package (USPS::Request::Package::DomesticPackage)'
end
end
View
16 lib/usps/response.rb
@@ -1,9 +1,11 @@
module USPS::Response
- autoload :Base, 'usps/response/base'
- autoload :CityAndStateLookup, 'usps/response/city_and_state_lookup'
- autoload :DeliveryConfirmation, 'usps/response/delivery_confirmation'
- autoload :AddressStandardization, 'usps/response/address_standardization'
- autoload :TrackingLookup, 'usps/response/tracking_lookup'
- autoload :TrackingFieldLookup, 'usps/response/tracking_field_lookup'
- autoload :ShippingRatesLookup, 'usps/response/shipping_rates_lookup'
+ autoload :Base, 'usps/response/base'
+ autoload :CityAndStateLookup, 'usps/response/city_and_state_lookup'
+ autoload :DeliveryConfirmation, 'usps/response/delivery_confirmation'
+ autoload :AddressStandardization, 'usps/response/address_standardization'
+ autoload :TrackingLookup, 'usps/response/tracking_lookup'
+ autoload :TrackingFieldLookup, 'usps/response/tracking_field_lookup'
+ autoload :ShippingRatesLookup, 'usps/response/shipping_rates_lookup'
+ autoload :InternationalShippingRatesLookup, 'usps/response/international_shipping_rates_lookup'
+ autoload :Package, 'usps/response/package'
end
View
27 lib/usps/response/international_shipping_rates_lookup.rb
@@ -0,0 +1,27 @@
+module USPS::Response
+ class InternationalShippingRatesLookup < Base
+ attr_reader :packages
+
+ def initialize(xml)
+ @packages = []
+ xml.search('Package').each do |package_node|
+ @packages << Package::InternationalPackage.new do |package|
+ package.id = package_node.attr('ID')
+ package.services = package_node.search('Service').map do |postage|
+ parse_service(postage)
+ end
+ end
+ end
+ end
+
+ private
+
+ def parse_service(node)
+ Package::InternationalPackage::Service.new.tap do |service|
+ service.id = node.attr('ID')
+ service.description = node.search('SvcDescription').text
+ service.rate = node.search('Postage').text
+ end
+ end
+ end
+end
View
4 lib/usps/response/package.rb
@@ -0,0 +1,4 @@
+module USPS::Response::Package
+ autoload :DomesticPackage, 'usps/response/package/domestic_package'
+ autoload :InternationalPackage, 'usps/response/package/international_package'
+end
View
15 lib/usps/response/package/domestic_package.rb
@@ -0,0 +1,15 @@
+module USPS::Response::Package
+ class DomesticPackage
+ class Postage
+ attr_accessor :rate, :mail_service, :class_id
+ end
+
+ attr_accessor :postages
+ attr_accessor :id, :origin_zip, :destination_zip, :pounds, :ounces, :container, :size
+
+ def initialize(properties = {})
+ properties.each_pair { |k, v| send("#{k}=", v) }
+ yield self if block_given?
+ end
+ end
+end
View
18 lib/usps/response/package/international_package.rb
@@ -0,0 +1,18 @@
+module USPS::Response::Package
+ class InternationalPackage
+ class Service
+ attr_accessor :id, :description, :rate
+ end
+
+ attr_accessor :id
+ attr_accessor :origin_zip, :destination_zip
+ attr_accessor :pounds, :ounces, :container, :size
+
+ attr_accessor :services
+
+ def initialize(properties = {})
+ properties.each_pair { |k, v| send("#{k}=", v) }
+ yield self if block_given?
+ end
+ end
+end
View
4 lib/usps/response/shipping_rates_lookup.rb
@@ -5,7 +5,7 @@ class ShippingRatesLookup < Base
def initialize(xml)
@packages = []
xml.search('Package').each do |package_node|
- @packages << USPS::PackageResponse.new do |package_response|
+ @packages << Package::DomesticPackage.new do |package_response|
package_response.postages = package_node.search('Postage').map { |postage| parse_postage(postage) }
package_response.id = package_node.attr('ID')
package_response.pounds = package_node.search('Pounds').text
@@ -21,7 +21,7 @@ def initialize(xml)
private
def parse_postage(node)
- USPS::Postage.new.tap do |postage|
+ Package::DomesticPackage::Postage.new.tap do |postage|
postage.class_id = node.attr('CLASSID')
postage.mail_service = node.search('MailService').text
postage.rate = node.search('Rate').text
View
162 spec/data/international_shipping_rates_lookup.xml
@@ -0,0 +1,162 @@
+<?xml version="1.0"?>
+<IntlRateV2Response>
+ <Package ID="3">
+ <Prohibitions>Arms, ammunitions, and parts and accessories thereof, except that hunting guns or similar guns belonging to legal persons are admitted with agreement of the Romanian police department.
+Coins; bank notes; currency notes; or securities of any kind payable to bearer; traveler's checks; platinum, gold, or silver (whether manufactured or not), precious stones; jewelry; or other valuable articles.
+Explosives, pyrotechnic products; matches, pyrophoric alloys, and combustible preparations.
+Indecent or obscene books, cards, photographs, manuscripts, typescripts, or other products of the printing industry.
+Perishable infectious biological substances.
+Perishable noninfectious biological substances.
+Radioactive materials.
+Tobacco and manufactured tobacco substitutes.</Prohibitions>
+ <Restrictions>Many items are admitted conditionally subject to permits or certificates (such as veterinary health or phytosanitary certificates for products of animal or vegetable origin) issued by the Romanian legal authorities.
+Pharmaceutical products are admitted only with the agreement of the Ministry of Health.
+Vitamins require a permit issued by the Ministry of Health or Ministry of Agriculture.</Restrictions>
+ <Observations>None.</Observations>
+ <CustomsForms>First-Class Mail International items and Priority Mail International Flat Rate Envelopes and Small Flat Rate Boxes:
+PS Form 2976 (see 123.61)
+Priority Mail International parcels:
+PS Form 2976-A inside 2976-E (envelope)</CustomsForms>
+ <ExpressMail>Country Code:
+RO
+
+Reciprocal Service Name:
+Rapide Post/EMS
+
+Required Customs Form/Endorsement
+1. Correspondence and business papers.
+Two copies of PS Form 2976, Customs - CN 22 and Sender's Declaration. Endorse item clearly next to mailing label as DES DOCUMENTS COMMERCIAL (COMMERCIAL DOCUMENTS).
+
+2. Merchandise samples without commercial value.
+PS Form 2976, Customs - CN 22 and Sender's Declaration. Endorse item clearly next to mailing label as SAMPLES.
+
+3. Merchandise and all articles subject to customs duty.
+PS Form 2976-A, Customs Declaration and Dispatch Note CP 72, inside a PS Form 2976-E, Customs Declaration Envelope CP 91.
+
+Note:
+Coins; banknotes; currency notes, including paper money; securities of any kind payable to bearer; traveler's checks; platinum, gold, and silver; precious stones; jewelry; watches; and other valuable articles are prohibited in Express Mail International shipments to Romania.
+
+Areas Served: All</ExpressMail>
+ <AreasServed>Please reference Express Mail for Areas Served.</AreasServed>
+ <AdditionalRestrictions>No Additional Restrictions Data found.</AdditionalRestrictions>
+ <Service ID="12">
+ <Pounds>7</Pounds>
+ <Ounces>0</Ounces>
+ <Machinable>true</Machinable>
+ <MailType>ALL</MailType>
+ <Container>RECTANGULAR</Container>
+ <Size>LARGE</Size>
+ <Width>12</Width>
+ <Length>12</Length>
+ <Height>13</Height>
+ <Girth>0</Girth>
+ <Country>ROMANIA</Country>
+ <Postage>197.00</Postage>
+ <ExtraServices>
+ <ExtraService>
+ <ServiceID>1</ServiceID>
+ <ServiceName>Insurance</ServiceName>
+ <Available>True</Available>
+ <Price>1.00</Price>
+ <DeclaredValueRequired>True</DeclaredValueRequired>
+ </ExtraService>
+ </ExtraServices>
+ <ValueOfContents>103.00</ValueOfContents>
+ <SvcCommitments>1 - 3 business days</SvcCommitments>
+ <SvcDescription>USPS GXG&amp;lt;sup&amp;gt;&amp;amp;trade;&amp;lt;/sup&amp;gt; Envelopes**</SvcDescription>
+ <MaxDimensions>USPS-Produced regular size cardboard envelope (12-1/2" x 9-1/2"), the legal-sized cardboard envelope (15" x 9-1/2") and the GXG Tyvek envelope (15-1/2" x 12-1/2")</MaxDimensions>
+ <MaxWeight>70</MaxWeight>
+ </Service>
+ <Service ID="1">
+ <Pounds>7</Pounds>
+ <Ounces>0</Ounces>
+ <Machinable>true</Machinable>
+ <MailType>ALL</MailType>
+ <Container>RECTANGULAR</Container>
+ <Size>LARGE</Size>
+ <Width>12</Width>
+ <Length>12</Length>
+ <Height>13</Height>
+ <Girth>0</Girth>
+ <Country>ROMANIA</Country>
+ <Postage>73.45</Postage>
+ <ExtraServices>
+ <ExtraService>
+ <ServiceID>1</ServiceID>
+ <ServiceName>Insurance</ServiceName>
+ <Available>True</Available>
+ <Price>0.85</Price>
+ <DeclaredValueRequired>True</DeclaredValueRequired>
+ </ExtraService>
+ </ExtraServices>
+ <ValueOfContents>103.00</ValueOfContents>
+ <SvcCommitments>3 - 5 business days</SvcCommitments>
+ <SvcDescription>Express Mail&amp;lt;sup&amp;gt;&amp;amp;reg;&amp;lt;/sup&amp;gt; International</SvcDescription>
+ <MaxDimensions>Max. length 36", max. length plus girth 79"</MaxDimensions>
+ <MaxWeight>70</MaxWeight>
+ </Service>
+ <Service ID="17">
+ <Pounds>7</Pounds>
+ <Ounces>0</Ounces>
+ <Machinable>true</Machinable>
+ <MailType>ALL</MailType>
+ <Container>RECTANGULAR</Container>
+ <Size>LARGE</Size>
+ <Width>12</Width>
+ <Length>12</Length>
+ <Height>13</Height>
+ <Girth>0</Girth>
+ <Country>ROMANIA</Country>
+ <Postage>38.00</Postage>
+ <ExtraServices>
+ <ExtraService>
+ <ServiceID>1</ServiceID>
+ <ServiceName>Insurance</ServiceName>
+ <Available>True</Available>
+ <Price>0.85</Price>
+ <DeclaredValueRequired>True</DeclaredValueRequired>
+ </ExtraService>
+ </ExtraServices>
+ <ValueOfContents>103.00</ValueOfContents>
+ <SvcCommitments>3 - 5 business days</SvcCommitments>
+ <SvcDescription>Express Mail&amp;lt;sup&amp;gt;&amp;amp;reg;&amp;lt;/sup&amp;gt; International Legal Flat Rate Envelope</SvcDescription>
+ <MaxDimensions>USPS-Produced Envelope: 15" x 9-1/2"&lt;br&gt;Maximum weight 20 pounds.</MaxDimensions>
+ <MaxWeight>20</MaxWeight>
+ </Service>
+ <Service ID="2">
+ <Pounds>7</Pounds>
+ <Ounces>0</Ounces>
+ <Machinable>true</Machinable>
+ <MailType>ALL</MailType>
+ <Container>RECTANGULAR</Container>
+ <Size>LARGE</Size>
+ <Width>12</Width>
+ <Length>12</Length>
+ <Height>13</Height>
+ <Girth>0</Girth>
+ <Country>ROMANIA</Country>
+ <Postage>61.10</Postage>
+ <ExtraServices>
+ <ExtraService>
+ <ServiceID>1</ServiceID>
+ <ServiceName>Insurance</ServiceName>
+ <Available>True</Available>
+ <Price>2.45</Price>
+ <DeclaredValueRequired>True</DeclaredValueRequired>
+ </ExtraService>
+ <ExtraService>
+ <ServiceID>6</ServiceID>
+ <ServiceName>Certificate of Mailing</ServiceName>
+ <Available>True</Available>
+ <Price>1.15</Price>
+ </ExtraService>
+ </ExtraServices>
+ <ValueOfContents>103.00</ValueOfContents>
+ <ParcelIndemnityCoverage>85.64</ParcelIndemnityCoverage>
+ <SvcCommitments>6 - 10 business days</SvcCommitments>
+ <SvcDescription>Priority Mail&amp;lt;sup&amp;gt;&amp;amp;reg;&amp;lt;/sup&amp;gt; International</SvcDescription>
+ <MaxDimensions>Max. length 42", max. length plus girth combined 79"</MaxDimensions>
+ <MaxWeight>70</MaxWeight>
+ </Service>
+ </Package>
+</IntlRateV2Response>
View
11 spec/package_spec.rb
@@ -1,6 +1,8 @@
require 'spec_helper'
-describe USPS::Package do
+describe USPS::Request::Package::DomesticPackage do
+
+ Package = USPS::Request::Package::DomesticPackage
REQUIRED_PROPERTIES = {
:id => 3,
@@ -15,12 +17,12 @@
it "should be valid when all required properties are specified" do
expect {
- package = USPS::Package.new(REQUIRED_PROPERTIES)
+ package = Package.new(REQUIRED_PROPERTIES)
}.to_not raise_exception
end
it "properties can be set in an initialization block" do
- package = USPS::Package.new(REQUIRED_PROPERTIES) do |p|
+ package = Package.new(REQUIRED_PROPERTIES) do |p|
p.size = "REGULAR"
end
package.size.should == "REGULAR"
@@ -29,9 +31,8 @@
REQUIRED_PROPERTIES.keys.each do |prop|
it "requires #{prop}" do
expect {
- package = USPS::Package.new(required_properties.dup.delete prop)
+ package = Package.new(required_properties.dup.delete prop)
}.to raise_exception
end
end
-
end
View
57 spec/request/international_shipping_rates_lookup_spec.rb
@@ -0,0 +1,57 @@
+require 'spec_helper'
+
+module USPS::Request
+ describe InternationalShippingRatesLookup do
+ it "uses the IntlRateV2 API settings" do
+ InternationalShippingRatesLookup.tap do |klass|
+ klass.secure.should be_false
+ klass.api.should == 'IntlRateV2'
+ klass.tag.should == 'IntlRateV2Request'
+ end
+ end
+
+ it "requires at least one package" do
+ expect {
+ request = InternationalShippingRatesLookup.new
+ }.to raise_exception(ArgumentError)
+ end
+
+ let(:required_properties) do
+ {
+ :id => "42",
+ :country => "Japan",
+ :mail_type => "LargeEnvelope",
+ :pounds => 3,
+ :ounces => 5,
+ :container => 'RECTANGULAR',
+ :size => 'LARGE',
+ }
+ end
+
+ def package_xml_from_attributes(attributes)
+ package = Package::InternationalPackage.new(attributes)
+ request = InternationalShippingRatesLookup.new(package)
+ Nokogiri::XML.parse(request.build)
+ end
+
+ it "builds a valid XML request for USPS IntlRateV2" do
+ package_properties = required_properties.merge(
+ :height => 13,
+ :width => 10,
+ :length => 15
+ )
+ package_xml = package_xml_from_attributes(package_properties)
+
+ package_xml.search('Package').count.should == 1
+ first_package = package_xml.search('Package').first
+ first_package.attr('ID').should == "42"
+ first_package.search('Pounds').text.should == '3'
+ first_package.search('Ounces').text.should == '5'
+ first_package.search('Container').text.should == 'RECTANGULAR'
+ first_package.search('Size').text.should == 'LARGE'
+ first_package.search('Height').text.should == '13'
+ first_package.search('Width').text.should == '10'
+ first_package.search('Length').text.should == '15'
+ end
+ end
+end
View
41 spec/request/package/international_package_spec.rb
@@ -0,0 +1,41 @@
+require 'spec_helper'
+
+module USPS::Request::Package
+ describe USPS::Request::Package::InternationalPackage do
+ VALID_PROPERTIES = {
+ :id => 3,
+ :country => "France",
+ :mail_type => "Package",
+ :pounds => 5,
+ :ounces => 4,
+ :container => 'RECTANGULAR',
+ :size => 'REGULAR'
+ }
+
+ VALID_PROPERTIES.keys.each do |prop|
+ it "requires #{prop}" do
+ expect {
+ package = InternationalPackage.new(required_properties.dup.delete prop)
+ }.to raise_exception
+ end
+ end
+
+ it "properties can be set with an initialization hash and/or block" do
+ package = InternationalPackage.new :id => 3, :country => "France" do |p|
+ p.mail_type = "FlatRate"
+ p.pounds = 4
+ p.ounces = 0
+ p.container = "RECTANGULAR"
+ p.size = "REGULAR"
+ end
+
+ package.id.should == 3
+ package.country.should == "France"
+ package.mail_type.should == "FlatRate"
+ package.pounds.should == 4
+ package.ounces.should == 0
+ package.container.should == "RECTANGULAR"
+ package.size.should == "REGULAR"
+ end
+ end
+end
View
2  spec/request/shipping_rates_lookup_spec.rb
@@ -29,7 +29,7 @@
end
def package_xml_from_attributes(attributes)
- package = USPS::Package.new(attributes)
+ package = USPS::Request::Package::DomesticPackage.new(attributes)
request = USPS::Request::ShippingRatesLookup.new(package)
Nokogiri::XML.parse(request.build)
end
View
25 spec/response/international_shipping_rates_lookup_spec.rb
@@ -0,0 +1,25 @@
+require 'spec_helper'
+
+describe USPS::Response::InternationalShippingRatesLookup do
+
+ it "correctly parses a USPS IntlRateV2 XML response" do
+ response = USPS::Response::InternationalShippingRatesLookup.new(load_xml("international_shipping_rates_lookup.xml"))
+ response.should have(1).packages
+ response.packages.first.tap do |package|
+ package.id.should == '3'
+ package.should have(4).services
+
+ package.services[0].tap do |gxg|
+ gxg.id.should == '12'
+ gxg.rate.should == '197.00'
+ gxg.description.should =~ /USPS GXG/
+ end
+
+ package.services[1].tap do |express|
+ express.id.should == '1'
+ express.rate.should == '73.45'
+ express.description.should =~ /Express Mail/
+ end
+ end
+ end
+end
Please sign in to comment.
Something went wrong with that request. Please try again.