trackerific 0.7.1 → 0.7.2

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 (59) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +6 -0
  3. data/Gemfile.lock +43 -1
  4. data/README.rdoc +58 -60
  5. data/lib/trackerific.rb +17 -20
  6. data/lib/trackerific/builders/base/soap.rb +21 -0
  7. data/lib/trackerific/builders/base/xml.rb +38 -0
  8. data/lib/trackerific/builders/fedex.rb +46 -0
  9. data/lib/trackerific/builders/ups.rb +32 -0
  10. data/lib/trackerific/builders/usps.rb +19 -0
  11. data/lib/trackerific/environment.rb +11 -0
  12. data/lib/trackerific/error.rb +3 -1
  13. data/lib/trackerific/parsers/base.rb +35 -0
  14. data/lib/trackerific/parsers/fedex.rb +59 -0
  15. data/lib/trackerific/parsers/ups.rb +66 -0
  16. data/lib/trackerific/parsers/usps.rb +51 -0
  17. data/lib/trackerific/services/base.rb +23 -10
  18. data/lib/trackerific/services/concerns/soap.rb +45 -0
  19. data/lib/trackerific/services/concerns/xml.rb +44 -0
  20. data/lib/trackerific/services/fedex.rb +9 -79
  21. data/lib/trackerific/services/mock_service.rb +4 -12
  22. data/lib/trackerific/services/ups.rb +11 -95
  23. data/lib/trackerific/services/usps.rb +21 -181
  24. data/lib/trackerific/soap/wsdl.rb +17 -0
  25. data/lib/trackerific/version.rb +1 -1
  26. data/spec/fixtures/fedex/error.xml +1 -10
  27. data/spec/fixtures/fedex/success.xml +1 -74
  28. data/spec/fixtures/ups/malformed.xml +10 -0
  29. data/spec/fixtures/ups/request.xml +1 -0
  30. data/spec/fixtures/usps/malformed.xml +2 -0
  31. data/spec/fixtures/usps/request.xml +1 -0
  32. data/spec/lib/trackerific/builders/base/soap_spec.rb +29 -0
  33. data/spec/lib/trackerific/builders/base/xml_spec.rb +35 -0
  34. data/spec/lib/trackerific/builders/fedex_spec.rb +70 -0
  35. data/spec/lib/trackerific/builders/ups_spec.rb +11 -0
  36. data/spec/lib/trackerific/builders/usps_spec.rb +11 -0
  37. data/spec/lib/trackerific/environment_spec.rb +45 -0
  38. data/spec/lib/trackerific/parsers/base_spec.rb +62 -0
  39. data/spec/lib/trackerific/parsers/ups_spec.rb +71 -0
  40. data/spec/lib/trackerific/parsers/usps_spec.rb +77 -0
  41. data/spec/lib/trackerific/services/base_spec.rb +56 -0
  42. data/spec/lib/trackerific/services/concerns/soap_spec.rb +71 -0
  43. data/spec/lib/trackerific/services/concerns/xml_spec.rb +65 -0
  44. data/spec/lib/trackerific/services/fedex_spec.rb +43 -45
  45. data/spec/lib/trackerific/services/ups_spec.rb +23 -2
  46. data/spec/lib/trackerific/services/usps_spec.rb +44 -34
  47. data/spec/lib/trackerific/services_spec.rb +7 -0
  48. data/spec/lib/trackerific/soap/wsdl_spec.rb +29 -0
  49. data/spec/lib/trackerific/version_spec.rb +1 -1
  50. data/spec/lib/trackerific_spec.rb +2 -11
  51. data/spec/spec_helper.rb +17 -1
  52. data/spec/support/reload.rb +6 -0
  53. data/spec/support/trackerific.rb +7 -0
  54. data/trackerific.gemspec +2 -0
  55. data/vendor/wsdl/fedex/TrackService_v8.wsdl +2284 -0
  56. metadata +81 -7
  57. data/lib/trackerific/configuration.rb +0 -7
  58. data/spec/fixtures/usps/city_state_lookup.xml +0 -8
  59. data/spec/lib/trackerific/configuration_spec.rb +0 -13
@@ -10,4 +10,60 @@ describe Trackerific::Services::Base do
10
10
  AnotherTestService.name.should eq :another_test_service
11
11
  end
12
12
  end
13
+
14
+ describe "#track" do
15
+ it "should create a new instance and call #track with the given id" do
16
+ TestService.any_instance.should_receive(:track).with('ID')
17
+ TestService.track('ID')
18
+ end
19
+ end
20
+
21
+ describe "#credentials" do
22
+ it "should read the credentials for the service from Trackerific.config" do
23
+ TestService.credentials.should eq({ :user => 'test' })
24
+ end
25
+ end
26
+
27
+ describe "#can_track?" do
28
+ context "when #credentials is nil" do
29
+ before { TestService.stub(:credentials).and_return(nil) }
30
+
31
+ it "should return false even if it matches one of #package_id_matchers" do
32
+ TestService.can_track?("TEST").should be_false
33
+ end
34
+ end
35
+
36
+ context "when #credentials is defined" do
37
+ before { Trackerific.stub(:credentials).and_return({:user => 'test'}) }
38
+
39
+ subject { TestService.can_track?(id) }
40
+
41
+ context "when the given id matches one of #package_id_matchers" do
42
+ let(:id) { 'TEST' }
43
+ it { should be_true }
44
+ end
45
+
46
+ context "when the given id doesn't match any of #package_id_matchers" do
47
+ let(:id) { 'invalid' }
48
+ it { should be_false }
49
+ end
50
+ end
51
+ end
52
+
53
+ describe "#package_id_matchers" do
54
+ it "should raise a NotImplementedError when not overridden" do
55
+ expect {
56
+ Trackerific::Services::Base.package_id_matchers
57
+ }.to raise_error NotImplementedError
58
+ end
59
+ end
60
+
61
+ context "when creating a new instance without credentials" do
62
+ before { TestService.stub(:credentials).and_return(nil) }
63
+ it "should raise a Trackerific::Error" do
64
+ expect {
65
+ TestService.new
66
+ }.to raise_error Trackerific::Error
67
+ end
68
+ end
13
69
  end
@@ -0,0 +1,71 @@
1
+ require 'spec_helper'
2
+
3
+ describe Trackerific::Services::Concerns::SOAP do
4
+ class TestConcernsSOAP
5
+ include Trackerific::Services::Concerns::SOAP
6
+
7
+ def initialize
8
+ @credentials = { user_id: 'USER ID' }
9
+ end
10
+ end
11
+
12
+ subject { TestConcernsSOAP }
13
+
14
+ it { should respond_to :soap_track_operation }
15
+ it { should respond_to :soap_track_operation= }
16
+ it { should respond_to :soap_builder }
17
+ it { should respond_to :soap_builder= }
18
+ it { should respond_to :soap_parser }
19
+ it { should respond_to :soap_parser= }
20
+ it { should respond_to :soap_wsdl }
21
+ it { should respond_to :soap_wsdl= }
22
+
23
+ describe "#track" do
24
+ let(:track_operation) { double(:track_operation) }
25
+ let(:package_id) { "PACKAGE ID" }
26
+
27
+ let(:builder) { double(:builder) }
28
+ let(:builder_instance) { double(:builder_instance) }
29
+ let(:builder_hash) { {'this' => 'hash'} }
30
+
31
+ let(:parser) { double(:parser) }
32
+ let(:parser_instance) { double(:parser_instance) }
33
+ let(:parser_response) { double(:parser_response) }
34
+
35
+ let(:wsdl) { 'fedex/TrackService_v8' }
36
+ let(:wsdl_path) { Trackerific::SOAP::WSDL.path(wsdl) }
37
+ let(:client) { double(:savon_client) }
38
+ let(:soap_request) { double(:soap_request) }
39
+
40
+ before do
41
+ TestConcernsSOAP.stub(:soap_track_operation).and_return(track_operation)
42
+ TestConcernsSOAP.stub(:soap_wsdl).and_return(wsdl)
43
+ TestConcernsSOAP.stub(:soap_builder).and_return(builder)
44
+ TestConcernsSOAP.stub(:soap_parser).and_return(parser)
45
+
46
+ builder.stub(:members).and_return([:user_id, :package_id])
47
+ builder.should_receive(:new).with("USER ID", package_id).and_return(builder_instance)
48
+ builder_instance.stub(:hash).and_return(builder_hash)
49
+
50
+ Savon.should_receive(:client).with(convert_request_keys_to: :camelcase, wsdl: wsdl_path).and_return(client)
51
+ client.should_receive(:call).with(track_operation, message: builder_hash).and_return(soap_request)
52
+
53
+ parser.should_receive(:new).with(package_id, soap_request).and_return(parser_instance)
54
+ parser_instance.should_receive(:parse).and_return(parser_response)
55
+ end
56
+
57
+ subject { TestConcernsSOAP.new.track(package_id) }
58
+
59
+ context "when the parser responds with a Trackerific::Error" do
60
+ let(:parser_response) { Trackerific::Error.new }
61
+ it "should raise the error" do
62
+ expect { subject }.to raise_error Trackerific::Error
63
+ end
64
+ end
65
+
66
+ context "when the parser responds with a Trackerific::Details" do
67
+ let(:parser_response) { Trackerific::Details.new }
68
+ it { should be parser_response }
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,65 @@
1
+ require 'spec_helper'
2
+
3
+ describe Trackerific::Services::Concerns::XML do
4
+ class TestConcernsXML
5
+ include Trackerific::Services::Concerns::XML
6
+
7
+ def initialize
8
+ @credentials = { user_id: 'USER ID' }
9
+ end
10
+ end
11
+
12
+ subject { TestConcernsXML }
13
+
14
+ it { should respond_to :xml_endpoint }
15
+ it { should respond_to :xml_endpoint= }
16
+ it { should respond_to :xml_parser }
17
+ it { should respond_to :xml_parser= }
18
+ it { should respond_to :xml_builder }
19
+ it { should respond_to :xml_builder= }
20
+
21
+ describe "#track" do
22
+ let(:endpoint) { "/endpoint" }
23
+ let(:package_id) { "PACKAGE ID" }
24
+
25
+ let(:parser) { double(:parser) }
26
+ let(:parser_instance) { double(:parser_instance) }
27
+ let(:parser_response) { double(:parser_response) }
28
+
29
+ let(:builder) { double(:builder) }
30
+ let(:builder_instance) { double(:builder_instance) }
31
+
32
+ let(:http_response) { double(:http_response) }
33
+
34
+ let(:xml) { "<xml></xml>" }
35
+
36
+ before do
37
+ TestConcernsXML.stub(:xml_endpoint).and_return(endpoint)
38
+ TestConcernsXML.stub(:xml_parser).and_return(parser)
39
+ TestConcernsXML.stub(:xml_builder).and_return(builder)
40
+
41
+ builder.stub(:members).and_return([:user_id, :package_id])
42
+ builder.should_receive(:new).with('USER ID', package_id).and_return(builder_instance)
43
+ builder_instance.stub(:xml).and_return(xml)
44
+
45
+ TestConcernsXML.should_receive(:post).with(endpoint, body: xml).and_return(http_response)
46
+
47
+ parser.should_receive(:new).with(package_id, http_response).and_return(parser_instance)
48
+ parser_instance.should_receive(:parse).and_return(parser_response)
49
+ end
50
+
51
+ subject { TestConcernsXML.new.track(package_id) }
52
+
53
+ context "when the parser responds with a Trackerific::Error" do
54
+ let(:parser_response) { Trackerific::Error.new }
55
+ it "should raise the error" do
56
+ expect { subject }.to raise_error Trackerific::Error
57
+ end
58
+ end
59
+
60
+ context "when the parser responds with a Trackerific::Details" do
61
+ let(:parser_response) { Trackerific::Details.new }
62
+ it { should be parser_response }
63
+ end
64
+ end
65
+ end
@@ -1,73 +1,71 @@
1
1
  require 'spec_helper'
2
2
 
3
- FEDEX_TRACK_URL = "https://gateway.fedex.com/GatewayDC"
4
-
5
3
  describe Trackerific::Services::FedEx do
6
- it { should be_a Trackerific::Services::Base }
7
-
8
- it "should be registered" do
9
- Trackerific::Services[:fedex].should eq Trackerific::Services::FedEx
10
- described_class.name.should eq :fedex
11
- end
4
+ include Savon::SpecHelper
12
5
 
13
6
  let(:valid_ids) { ["183689015000001", "999999999999999"] }
14
- let(:invalid_ids) { %w[these are not fedex tracking ids] }
7
+ let(:invalid_ids) { %w[these are not valid tracking ids] }
15
8
 
16
- it "should match valid FedEx ids" do
9
+ it "should match valid tracking ids" do
17
10
  valid_ids.all? {|id| described_class.can_track?(id) }.should be_true
18
11
  end
19
12
 
20
- it "should not match invalid FedEx ids" do
13
+ it "should not match invalid tracking ids" do
21
14
  invalid_ids.all? {|id| described_class.can_track?(id) }.should be_false
22
15
  end
23
16
 
17
+ let(:credentials) do
18
+ { :key => "KEY",
19
+ :password => "PASSWORD",
20
+ :account_number => "ACCOUNT NUMBER",
21
+ :meter_number => "METER NUMBER" }
22
+ end
23
+
24
+ let(:fedex) { described_class.new(credentials) }
25
+
24
26
  describe "#track" do
25
- let(:id) { "183689015000001" }
26
- let(:credentials) { { account: "123456789", meter: "123456789" } }
27
- let(:fedex) { described_class.new(credentials) }
27
+ before(:all) { savon.mock! }
28
+ after(:all) { savon.unmock! }
29
+ let(:hash) { double(:hash) }
30
+ let(:package_id) { "PACKAGE ID" }
28
31
 
29
32
  before do
30
- FakeWeb.register_uri(:post, FEDEX_TRACK_URL, body: fixture)
33
+ Trackerific::Builders::FedEx.any_instance.stub(:hash).and_return(hash)
34
+ savon.expects(:track).with(message: hash).returns(fixture)
31
35
  end
32
36
 
33
- after { FakeWeb.clean_registry }
37
+ subject { fedex.track(package_id) }
38
+
39
+ context "with an error response" do
40
+ let(:fixture) { Fixture.read('fedex/error.xml') }
41
+
42
+ it "should raise a Trackerific::Error" do
43
+ expect {
44
+ subject
45
+ }.to raise_error Trackerific::Error
46
+ end
47
+ end
34
48
 
35
49
  context "with a successful response" do
36
50
  let(:fixture) { Fixture.read('fedex/success.xml') }
37
- subject { fedex.track(id) }
38
- it { should be_a Trackerific::Details }
39
- its(:package_id) { should eq id }
40
- its(:summary) { should eq "Delivered" }
41
51
 
42
- describe "#events" do
43
- subject { fedex.track(id).events }
44
- its(:length) { should eq 3 }
52
+ its(:package_id) { should eq package_id }
53
+ its(:summary) { should be_nil }
54
+ its(:weight) { should be_nil }
55
+ its(:via) { should be_nil }
45
56
 
46
- it "should be an Array of Trackerific::Event" do
47
- subject.all? {|el| el.is_a?(Trackerific::Event) }.should be_true
48
- end
57
+ describe "#events" do
58
+ subject { fedex.track(package_id).events }
59
+ its(:length) { should eq 5 }
49
60
 
50
- it "should have the correct event values" do
51
- subject[0].date.to_s.should eq "2010-07-01 10:43:51 -0600"
52
- subject[0].description.should eq "Delivered"
53
- subject[0].location.should eq "GA 30506"
54
- subject[1].date.to_s.should eq "2010-07-01 08:48:00 -0600"
55
- subject[1].description.should eq "On FedEx vehicle for delivery"
56
- subject[1].location.should eq "GA 30601"
57
- subject[2].date.to_s.should eq "2010-07-01 05:07:00 -0600"
58
- subject[2].description.should eq "At local FedEx facility"
59
- subject[2].location.should eq "GA 30601"
61
+ it "should populate its properties with values from the response" do
62
+ subject.all? {|e| e.description.nil? }.should be_true
63
+ subject.all? {|e| e.date.is_a?(DateTime) }.should be_true
64
+ subject.map(&:location).should eq [
65
+ "new york, NY US", "Memphis, TN US", "CITY OF INDUSTRY, CA US",
66
+ "ST JACKSON, MS US", "Ontonagon, MI US" ]
60
67
  end
61
68
  end
62
69
  end
63
-
64
- context "with an error response" do
65
- let(:fixture) { Fixture.read('fedex/error.xml') }
66
- it "should raise a Trackerific::Error" do
67
- expect {
68
- fedex.track(id)
69
- }.to raise_error Trackerific::Error
70
- end
71
- end
72
70
  end
73
71
  end
@@ -5,6 +5,27 @@ UPS_TRACK_URL = 'https://wwwcie.ups.com/ups.app/xml/Track'
5
5
  describe Trackerific::Services::UPS do
6
6
  it { should be_a Trackerific::Services::Base }
7
7
 
8
+ describe "#base_uri" do
9
+ subject { described_class.base_uri }
10
+
11
+ before do
12
+ Trackerific.stub(:env).and_return(env)
13
+ Trackerific.reload!('trackerific/services/ups.rb')
14
+ end
15
+
16
+ after(:all) { Trackerific.reload!('trackerific/services/ups.rb') }
17
+
18
+ context "when Trackerific.env is 'production'" do
19
+ let(:env) { 'production' }
20
+ it { should eq "https://www.ups.com/ups.app/xml" }
21
+ end
22
+
23
+ context "when Trackerific.env is not 'production'" do
24
+ let(:env) { 'development' }
25
+ it { should eq 'https://wwwcie.ups.com/ups.app/xml' }
26
+ end
27
+ end
28
+
8
29
  let(:valid_ids) { ["1Z12345E0291980793"] }
9
30
  let(:invalid_ids) { %w[these are not valid tracking ids] }
10
31
 
@@ -39,8 +60,8 @@ describe Trackerific::Services::UPS do
39
60
  describe "#events" do
40
61
  subject { ups.track(id).events }
41
62
  its(:length) { should eq 1 }
42
- it "should have the correct values" do
43
- subject[0].date.to_s.should eq "2003-03-13T16:00:00+00:00"
63
+ it "should populate the properties from the XML" do
64
+ subject[0].date.should be_a DateTime
44
65
  subject[0].description.should eq "DELIVERED"
45
66
  subject[0].location.should eq "MAYSVILLE 26833 9700 US"
46
67
  end
@@ -1,10 +1,47 @@
1
1
  require 'spec_helper'
2
2
 
3
- USPS_URL = %r|http://testing\.shippingapis\.com/.*|
4
-
5
3
  describe Trackerific::Services::USPS do
4
+ let(:usps_url) { %r|http://testing\.shippingapis\.com/.*| }
5
+
6
6
  it { should be_a Trackerific::Services::Base }
7
7
 
8
+ describe "environment dependent methods/properties" do
9
+ before do
10
+ Trackerific.stub(:env).and_return(env)
11
+ Trackerific.reload!('trackerific/services/usps.rb')
12
+ end
13
+
14
+ after(:all) { Trackerific.reload!('trackerific/services/usps.rb') }
15
+
16
+ context "when Trackerific.env is 'production'" do
17
+ let(:env) { 'production' }
18
+
19
+ describe "#base_uri" do
20
+ subject { described_class.base_uri }
21
+ it { should eq 'http://production.shippingapis.com' }
22
+ end
23
+
24
+ describe "#xml_endpoint" do
25
+ subject { described_class.xml_endpoint }
26
+ it { should eq '/ShippingAPI.dll' }
27
+ end
28
+ end
29
+
30
+ context "when Trackerific.env is not 'production'" do
31
+ let(:env) { 'development' }
32
+
33
+ describe "#base_uri" do
34
+ subject { described_class.base_uri }
35
+ it { should eq 'http://testing.shippingapis.com' }
36
+ end
37
+
38
+ describe "#xml_endpoint" do
39
+ subject { described_class.xml_endpoint }
40
+ it { should eq '/ShippingAPITest.dll' }
41
+ end
42
+ end
43
+ end
44
+
8
45
  let(:valid_ids) { ["EJ958083578US"] }
9
46
  let(:invalid_ids) { %w[these are not valid tracking ids] }
10
47
 
@@ -19,38 +56,11 @@ describe Trackerific::Services::USPS do
19
56
  let(:credentials) { { user_id: '123USERID4567' } }
20
57
  let(:usps) { described_class.new(credentials) }
21
58
 
22
- describe "#city_state_lookup" do
23
- before do
24
- FakeWeb.register_uri(:get, USPS_URL, body: fixture)
25
- end
26
-
27
- after(:all) { FakeWeb.clean_registry }
28
-
29
- context "with a successful response" do
30
- let(:fixture) { Fixture.read('usps/city_state_lookup.xml') }
31
- subject { usps.city_state_lookup("90210") }
32
- it "should have the correct values" do
33
- subject[:city].should eq "BEVERLY HILLS"
34
- subject[:state].should eq "CA"
35
- subject[:zip].should eq "90210"
36
- end
37
- end
38
-
39
- context "with an error response" do
40
- let(:fixture) { Fixture.read('usps/error.xml') }
41
- it "should raise a Trackerific::Error" do
42
- expect {
43
- usps.city_state_lookup("90210")
44
- }.to raise_error Trackerific::Error
45
- end
46
- end
47
- end
48
-
49
59
  describe "#track" do
50
60
  let(:id) { 'EJ958083578US' }
51
61
 
52
62
  before do
53
- FakeWeb.register_uri(:get, USPS_URL, body: fixture)
63
+ FakeWeb.register_uri(:get, usps_url, body: fixture)
54
64
  end
55
65
 
56
66
  after(:all) { FakeWeb.clean_registry }
@@ -71,15 +81,15 @@ describe Trackerific::Services::USPS do
71
81
  describe "#events" do
72
82
  subject { usps.track(id).events }
73
83
  its(:length) { should eq 3 }
74
- it "should have the correct values" do
84
+ it "should populate the properties from the XML" do
75
85
  subject[0].date.to_s.should eq "2013-05-30T11:07:00+00:00"
76
- subject[0].description.should eq "Notice left"
86
+ subject[0].description.should eq "NOTICE LEFT"
77
87
  subject[0].location.should eq "WILMINGTON, DE 19801"
78
88
  subject[1].date.to_s.should eq "2013-05-30T10:08:00+00:00"
79
- subject[1].description.should eq "Arrival at unit"
89
+ subject[1].description.should eq "ARRIVAL AT UNIT"
80
90
  subject[1].location.should eq "WILMINGTON, DE 19850"
81
91
  subject[2].date.to_s.should eq "2013-05-29T09:55:00+00:00"
82
- subject[2].description.should eq "Accept or pickup"
92
+ subject[2].description.should eq "ACCEPT OR PICKUP"
83
93
  subject[2].location.should eq "EDGEWATER, NJ 07020"
84
94
  end
85
95
  end