From 4f98eb38e863774f3469aedad362956da6a08356 Mon Sep 17 00:00:00 2001 From: Khoa Nguyen Date: Tue, 29 Mar 2011 19:22:52 +1100 Subject: [PATCH] add Australia Post carrier - move fixture data from test_helper into its own file --- lib/active_shipping/shipping/carriers.rb | 5 +- .../shipping/carriers/australia_post.rb | 80 +++++++++++ test/fixture_helper.rb | 129 ++++++++++++++++++ test/remote/australia_post_test.rb | 54 ++++++++ test/test_helper.rb | 128 +---------------- 5 files changed, 267 insertions(+), 129 deletions(-) create mode 100644 lib/active_shipping/shipping/carriers/australia_post.rb create mode 100644 test/fixture_helper.rb create mode 100644 test/remote/australia_post_test.rb diff --git a/lib/active_shipping/shipping/carriers.rb b/lib/active_shipping/shipping/carriers.rb index a76f565c0..9eb677cfb 100644 --- a/lib/active_shipping/shipping/carriers.rb +++ b/lib/active_shipping/shipping/carriers.rb @@ -6,15 +6,16 @@ require 'active_shipping/shipping/carriers/kunaki' require 'active_shipping/shipping/carriers/canada_post' require 'active_shipping/shipping/carriers/new_zealand_post' +require 'active_shipping/shipping/carriers/australia_post' module ActiveMerchant module Shipping module Carriers class < '2000', :country => 'Australia') + @@api_url = "http://drc.edeliver.com.au/ratecalc.asp" + + def find_rates(origin, destination, package, options = {}) + rates = [] + + origin = self.class.default_location unless origin.is_a?(Location) + + options[:service_type] = Array(options[:service_type]).flatten + if options[:service_type].empty? + if destination.country.to_s == 'Australia' + options[:service_type] = %w[STANDARD EXPRESS] + else + options[:service_type] = %w[AIR SEA] + end + end + + options[:service_type].each do |service_type| + rate_request_url = build_rate_request(origin, destination, package, {:service_type => service_type}) + response = ssl_get(rate_request_url) + rates << parse_rate_response(origin, destination, package, response, {:service_type => service_type}) + end + + rates + end + + protected + + def self.default_location + @@default_location + end + + private + + def build_rate_request(origin, destination, package, options) + self.class.api_url + "?" + { + Pickup_Postcode: destination.postal_code, + Destination_Postcode: origin.postal_code, + Country: destination.country.code(:alpha2), + Service_Type: options[:service_type], + Weight: package.grams, + Length: package.centimetres(:length) * 10, + Width: package.centimetres(:width) * 10, + Height: package.centimetres(:height) * 10, + Quantity: 1 + }.to_param + end + + def parse_rate_response(origin, destination, package, response, options) + price = nil, delivery_date = nil + + response.scan( /(\w+)=(.+)/ ).each do |key, value| + value.strip! + + case key + when 'charge' + price = value.to_f + when 'days' + delivery_date = value.to_i.days.from_now + when 'err_msg' + raise "Error: #{value}" unless value == "OK" + else + raise "Unknown response from #{self.class.api_url}: #{key} => #{value}" + end + end + + RateEstimate.new(origin, destination, self.class.name, options[:service_type], + :total_price => price, :currency => 'AUD', :package => package, :delivery_date => delivery_date) + end + end + end +end diff --git a/test/fixture_helper.rb b/test/fixture_helper.rb new file mode 100644 index 000000000..57152307b --- /dev/null +++ b/test/fixture_helper.rb @@ -0,0 +1,129 @@ +module ActiveMerchant + module Shipping + module TestFixtures + + mattr_reader :packages, :locations + + @@packages = { + :just_ounces => Package.new(16, nil, :units => :imperial), + :just_grams => Package.new(1000, nil), + :all_imperial => Package.new(16, [1,8,12], :units => :imperial), + :all_metric => Package.new(1000, [2,20,40]), + :book => Package.new(250, [14, 19, 2]), + :wii => Package.new((7.5 * 16), [15, 10, 4.5], :units => :imperial, :value => 269.99, :currency => 'GBP'), + :american_wii => Package.new((7.5 * 16), [15, 10, 4.5], :units => :imperial, :value => 269.99, :currency => 'USD'), + :worthless_wii => Package.new((7.5 * 16), [15, 10, 4.5], :units => :imperial, :value => 0.0, :currency => 'USD'), + :poster => Package.new(100, [93,10], :cylinder => true), + :small_half_pound => Package.new(8, [1,1,1], :units => :imperial), + :big_half_pound => Package.new((16 * 50), [24,24,36], :units => :imperial), + :chocolate_stuff => Package.new(80, [2,6,12], :units => :imperial), + :shipping_container => Package.new(2200000, [2440, 2600, 6058], :description => '20 ft Standard Container', :units => :metric) + } + + @@locations = { + :bare_ottawa => Location.new(:country => 'CA', :postal_code => 'K1P 1J1'), + :bare_beverly_hills => Location.new(:country => 'US', :zip => '90210'), + :ottawa => Location.new(:country => 'CA', :province => 'ON', :city => 'Ottawa', + :address1 => '110 Laurier Avenue West', :postal_code => 'K1P 1J1', + :phone => '1-613-580-2400', :fax => '1-613-580-2495'), + :beverly_hills => Location.new(:country => 'US', :state => 'CA', :city => 'Beverly Hills', + :address1 => '455 N. Rexford Dr.', :address2 => '3rd Floor', :zip => '90210', + :phone => '1-310-285-1013', :fax => '1-310-275-8159'), + :real_home_as_commercial => Location.new( + :country => 'US', + :city => 'Tampa', + :state => 'FL', + :address1 => '7926 Woodvale Circle', + :zip => '33615', + :address_type => 'commercial'), # means that UPS will default to commercial if it doesn't know + :fake_home_as_commercial => Location.new( + :country => 'US', + :state => 'FL', + :address1 => '123 fake st.', + :zip => '33615', + :address_type => 'commercial'), + :real_google_as_commercial => Location.new( + :country => 'US', + :city => 'Mountain View', + :state => 'CA', + :address1 => '1600 Amphitheatre Parkway', + :zip => '94043', + :address_type => 'commercial'), + :real_google_as_residential => Location.new( + :country => 'US', + :city => 'Mountain View', + :state => 'CA', + :address1 => '1600 Amphitheatre Parkway', + :zip => '94043', + :address_type => 'residential'), # means that will default to residential if it doesn't know + :fake_google_as_commercial => Location.new( + :country => 'US', + :city => 'Mountain View', + :state => 'CA', + :address1 => '123 bogusland dr.', + :zip => '94043', + :address_type => 'commercial'), + :fake_google_as_residential => Location.new( + :country => 'US', + :city => 'Mountain View', + :state => 'CA', + :address1 => '123 bogusland dr.', + :zip => '94043', + :address_type => 'residential'), # means that will default to residential if it doesn't know + :fake_home_as_residential => Location.new( + :country => 'US', + :state => 'FL', + :address1 => '123 fake st.', + :zip => '33615', + :address_type => 'residential'), + :real_home_as_residential => Location.new( + :country => 'US', + :city => 'Tampa', + :state => 'FL', + :address1 => '7926 Woodvale Circle', + :zip => '33615', + :address_type => 'residential'), + :london => Location.new( + :country => 'GB', + :city => 'London', + :address1 => '170 Westminster Bridge Rd.', + :zip => 'SE1 7RW'), + :new_york => Location.new( + :country => 'US', + :city => 'New York', + :state => 'NY', + :address1 => '780 3rd Avenue', + :address2 => 'Suite 2601', + :zip => '10017'), + :new_york_with_name => Location.new( + :name => "Bob Bobsen", + :country => 'US', + :city => 'New York', + :state => 'NY', + :address1 => '780 3rd Avenue', + :address2 => 'Suite 2601', + :zip => '10017'), + :wellington => Location.new( + :country => 'NZ', + :city => 'Wellington', + :address1 => '85 Victoria St', + :address2 => 'Te Aro', + :postal_code => '6011'), + :sydney => Location.new( + :country => 'Australia', + :city => 'Sydney', + :address1 => '1 Regent St', + :address2 => 'Suite 101', + :postal_code => '2000'), + :melbourne => Location.new( + :country => 'Australia', + :city => 'Melbourne', + :address1 => '1 Collins St', + :address2 => 'Suite 101', + :postal_code => '3000') + } + + end + end +end + diff --git a/test/remote/australia_post_test.rb b/test/remote/australia_post_test.rb new file mode 100644 index 000000000..f0b18bcde --- /dev/null +++ b/test/remote/australia_post_test.rb @@ -0,0 +1,54 @@ +require 'test_helper' + +class AustraliaPostTest < Test::Unit::TestCase + + def setup + @packages = TestFixtures.packages + @locations = TestFixtures.locations + @carrier = AustraliaPost.new + end + + def test_successful_rate_request + # local postage + %w[STANDARD EXPRESS].each do |service_type| + rates = @carrier.find_rates(@locations[:sydney], @locations[:melbourne], @packages[:book], :service_type => service_type) + assert rates.any? + assert rates.first.is_a? RateEstimate + assert_equal rates.size, 1 + end + + @carrier.find_rates(@locations[:sydney], @locations[:melbourne], @packages[:book]).each do |rate| + assert rate.service_name =~ /STANDARD|EXPRESS/ + end + + # international postage + %w[AIR SEA].each do |service_type| + rates = @carrier.find_rates(@locations[:sydney], @locations[:beverly_hills], @packages[:book], :service_type => service_type) + assert rates.any? + assert rates.first.is_a? RateEstimate + assert_equal rates.size, 1 + end + + @carrier.find_rates(@locations[:sydney], @locations[:beverly_hills], @packages[:book]).each do |rate| + assert rate.service_name =~ /AIR|SEA/ + end + end + + def test_failure_rate_request + begin + # can't use air service for local + @carrier.find_rates(@locations[:sydney], @locations[:melbourne], @packages.values_at(:book), 'AIR') + + flunk "expected an ActiveMerchant::Shipping::ResponseError to be raised" + rescue => exception + end + + begin + # economy no longer available + @carrier.find_rates(@locations[:sydney], @locations[:wellington], @packages.values_at(:book), 'ECONOMY') + + flunk "expected an ActiveMerchant::Shipping::ResponseError to be raised" + rescue => exception + end + end +end diff --git a/test/test_helper.rb b/test/test_helper.rb index b516e2fcb..c56cc261c 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -4,6 +4,7 @@ require 'test/unit' require 'active_shipping' require 'mocha' +require 'fixture_helper' XmlNode # trigger autorequire @@ -57,130 +58,3 @@ def symbolize_keys(hash) end end end - -module ActiveMerchant - module Shipping - module TestFixtures - - mattr_reader :packages, :locations - - @@packages = { - :just_ounces => Package.new(16, nil, :units => :imperial), - :just_grams => Package.new(1000, nil), - :all_imperial => Package.new(16, [1,8,12], :units => :imperial), - :all_metric => Package.new(1000, [2,20,40]), - :book => Package.new(250, [14, 19, 2]), - :wii => Package.new((7.5 * 16), [15, 10, 4.5], :units => :imperial, :value => 269.99, :currency => 'GBP'), - :american_wii => Package.new((7.5 * 16), [15, 10, 4.5], :units => :imperial, :value => 269.99, :currency => 'USD'), - :worthless_wii => Package.new((7.5 * 16), [15, 10, 4.5], :units => :imperial, :value => 0.0, :currency => 'USD'), - :poster => Package.new(100, [93,10], :cylinder => true), - :small_half_pound => Package.new(8, [1,1,1], :units => :imperial), - :big_half_pound => Package.new((16 * 50), [24,24,36], :units => :imperial), - :chocolate_stuff => Package.new(80, [2,6,12], :units => :imperial), - :shipping_container => Package.new(2200000, [2440, 2600, 6058], :description => '20 ft Standard Container', :units => :metric) - } - - @@locations = { - :bare_ottawa => Location.new(:country => 'CA', :postal_code => 'K1P 1J1'), - :bare_beverly_hills => Location.new(:country => 'US', :zip => '90210'), - :ottawa => Location.new( :country => 'CA', - :province => 'ON', - :city => 'Ottawa', - :address1 => '110 Laurier Avenue West', - :postal_code => 'K1P 1J1', - :phone => '1-613-580-2400', - :fax => '1-613-580-2495'), - :beverly_hills => Location.new( - :country => 'US', - :state => 'CA', - :city => 'Beverly Hills', - :address1 => '455 N. Rexford Dr.', - :address2 => '3rd Floor', - :zip => '90210', - :phone => '1-310-285-1013', - :fax => '1-310-275-8159'), - :real_home_as_commercial => Location.new( - :country => 'US', - :city => 'Tampa', - :state => 'FL', - :address1 => '7926 Woodvale Circle', - :zip => '33615', - :address_type => 'commercial'), # means that UPS will default to commercial if it doesn't know - :fake_home_as_commercial => Location.new( - :country => 'US', - :state => 'FL', - :address1 => '123 fake st.', - :zip => '33615', - :address_type => 'commercial'), - :real_google_as_commercial => Location.new( - :country => 'US', - :city => 'Mountain View', - :state => 'CA', - :address1 => '1600 Amphitheatre Parkway', - :zip => '94043', - :address_type => 'commercial'), - :real_google_as_residential => Location.new( - :country => 'US', - :city => 'Mountain View', - :state => 'CA', - :address1 => '1600 Amphitheatre Parkway', - :zip => '94043', - :address_type => 'residential'), # means that will default to residential if it doesn't know - :fake_google_as_commercial => Location.new( - :country => 'US', - :city => 'Mountain View', - :state => 'CA', - :address1 => '123 bogusland dr.', - :zip => '94043', - :address_type => 'commercial'), - :fake_google_as_residential => Location.new( - :country => 'US', - :city => 'Mountain View', - :state => 'CA', - :address1 => '123 bogusland dr.', - :zip => '94043', - :address_type => 'residential'), # means that will default to residential if it doesn't know - :fake_home_as_residential => Location.new( - :country => 'US', - :state => 'FL', - :address1 => '123 fake st.', - :zip => '33615', - :address_type => 'residential'), - :real_home_as_residential => Location.new( - :country => 'US', - :city => 'Tampa', - :state => 'FL', - :address1 => '7926 Woodvale Circle', - :zip => '33615', - :address_type => 'residential'), - :london => Location.new( - :country => 'GB', - :city => 'London', - :address1 => '170 Westminster Bridge Rd.', - :zip => 'SE1 7RW'), - :new_york => Location.new( - :country => 'US', - :city => 'New York', - :state => 'NY', - :address1 => '780 3rd Avenue', - :address2 => 'Suite 2601', - :zip => '10017'), - :new_york_with_name => Location.new( - :name => "Bob Bobsen", - :country => 'US', - :city => 'New York', - :state => 'NY', - :address1 => '780 3rd Avenue', - :address2 => 'Suite 2601', - :zip => '10017'), - :wellington => Location.new( - :country => 'NZ', - :city => 'Wellington', - :address1 => '85 Victoria St', - :address2 => 'Te Aro', - :postal_code => '6011') - } - - end - end -end