mws-connect 0.0.1

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 (57) hide show
  1. data/.gitignore +19 -0
  2. data/.sublime-project +19 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +111 -0
  6. data/Rakefile +1 -0
  7. data/lib/mws.rb +34 -0
  8. data/lib/mws/apis.rb +6 -0
  9. data/lib/mws/apis/feeds.rb +20 -0
  10. data/lib/mws/apis/feeds/api.rb +103 -0
  11. data/lib/mws/apis/feeds/distance.rb +23 -0
  12. data/lib/mws/apis/feeds/feed.rb +114 -0
  13. data/lib/mws/apis/feeds/image_listing.rb +44 -0
  14. data/lib/mws/apis/feeds/inventory.rb +77 -0
  15. data/lib/mws/apis/feeds/measurement.rb +32 -0
  16. data/lib/mws/apis/feeds/money.rb +31 -0
  17. data/lib/mws/apis/feeds/price_listing.rb +48 -0
  18. data/lib/mws/apis/feeds/product.rb +173 -0
  19. data/lib/mws/apis/feeds/sale_price.rb +31 -0
  20. data/lib/mws/apis/feeds/shipping.rb +160 -0
  21. data/lib/mws/apis/feeds/submission_info.rb +45 -0
  22. data/lib/mws/apis/feeds/submission_result.rb +87 -0
  23. data/lib/mws/apis/feeds/transaction.rb +37 -0
  24. data/lib/mws/apis/feeds/weight.rb +19 -0
  25. data/lib/mws/apis/orders.rb +23 -0
  26. data/lib/mws/connection.rb +84 -0
  27. data/lib/mws/enum.rb +81 -0
  28. data/lib/mws/errors.rb +32 -0
  29. data/lib/mws/query.rb +45 -0
  30. data/lib/mws/serializer.rb +81 -0
  31. data/lib/mws/signer.rb +20 -0
  32. data/lib/mws/utils.rb +50 -0
  33. data/mws.gemspec +25 -0
  34. data/scripts/catalog-workflow +136 -0
  35. data/spec/mws/apis/feeds/api_spec.rb +229 -0
  36. data/spec/mws/apis/feeds/distance_spec.rb +43 -0
  37. data/spec/mws/apis/feeds/feed_spec.rb +92 -0
  38. data/spec/mws/apis/feeds/image_listing_spec.rb +109 -0
  39. data/spec/mws/apis/feeds/inventory_spec.rb +135 -0
  40. data/spec/mws/apis/feeds/measurement_spec.rb +84 -0
  41. data/spec/mws/apis/feeds/money_spec.rb +43 -0
  42. data/spec/mws/apis/feeds/price_listing_spec.rb +90 -0
  43. data/spec/mws/apis/feeds/product_spec.rb +264 -0
  44. data/spec/mws/apis/feeds/shipping_spec.rb +78 -0
  45. data/spec/mws/apis/feeds/submission_info_spec.rb +111 -0
  46. data/spec/mws/apis/feeds/submission_result_spec.rb +157 -0
  47. data/spec/mws/apis/feeds/transaction_spec.rb +64 -0
  48. data/spec/mws/apis/feeds/weight_spec.rb +43 -0
  49. data/spec/mws/apis/orders_spec.rb +9 -0
  50. data/spec/mws/connection_spec.rb +331 -0
  51. data/spec/mws/enum_spec.rb +166 -0
  52. data/spec/mws/query_spec.rb +104 -0
  53. data/spec/mws/serializer_spec.rb +187 -0
  54. data/spec/mws/signer_spec.rb +67 -0
  55. data/spec/mws/utils_spec.rb +147 -0
  56. data/spec/spec_helper.rb +10 -0
  57. metadata +220 -0
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+
3
+ module Mws::Apis::Feeds
4
+
5
+ describe Distance do
6
+
7
+ context '.new' do
8
+
9
+ it 'should default to feet' do
10
+ distance = Distance.new 40
11
+ distance.amount.should == 40
12
+ distance.unit.should == :feet
13
+ end
14
+
15
+ it 'should accept a valid unit override' do
16
+ distance = Distance.new 0, :meters
17
+ distance.amount.should == 0
18
+ distance.unit.should == :meters
19
+ end
20
+
21
+ it 'should validate the unit override' do
22
+ expect {
23
+ Distance.new 40, :acres
24
+ }.to raise_error Mws::Errors::ValidationError, "Invalid unit of measure 'acres'"
25
+ end
26
+
27
+ end
28
+
29
+ context '#to_xml' do
30
+
31
+ it 'should properly serialize to XML' do
32
+ distance = Distance.new 25, :inches
33
+ expected = Nokogiri::XML::Builder.new do
34
+ Distance 25, unitOfMeasure: 'inches'
35
+ end.doc.root.to_xml
36
+ distance.to_xml.should == expected
37
+ end
38
+
39
+ end
40
+
41
+ end
42
+
43
+ end
@@ -0,0 +1,92 @@
1
+ require 'spec_helper'
2
+
3
+ module Mws::Apis::Feeds
4
+
5
+ describe Feed do
6
+
7
+ let(:merchant) { 'GSWCJ4UBA31UTJ' }
8
+ let(:message_type) { :image }
9
+
10
+ context '.new' do
11
+
12
+ it 'should require a merchant identifier' do
13
+ expect { Feed.new(nil, message_type) }.to raise_error Mws::Errors::ValidationError,
14
+ 'Merchant identifier is required.'
15
+ end
16
+
17
+ it 'should require a valid message type' do
18
+ expect { Feed.new(merchant, nil) }.to raise_error Mws::Errors::ValidationError,
19
+ 'A valid message type is required.'
20
+ end
21
+
22
+ it 'shoud default purge and replace to false' do
23
+ Feed.new(merchant, message_type).purge_and_replace.should be false
24
+ end
25
+
26
+ it 'should accept overrides to purge and replace' do
27
+ Feed.new(merchant, message_type, true).purge_and_replace.should be true
28
+ end
29
+
30
+ it 'should accept a block to append messages to the feed' do
31
+ feed = Feed.new(merchant, message_type) do
32
+ message ImageListing.new('1', 'http://foo.com/bar.jpg'), :delete
33
+ message ImageListing.new('1', 'http://bar.com/foo.jpg')
34
+ end
35
+ feed.messages.size.should == 2
36
+ first = feed.messages.first
37
+ first.id.should == 1
38
+ first.type.should == :image
39
+ first.operation_type.should == :delete
40
+ first.resource.should == ImageListing.new('1', 'http://foo.com/bar.jpg')
41
+ second = feed.messages.last
42
+ second.id.should == 2
43
+ second.type.should == :image
44
+ second.operation_type.should == :update
45
+ second.resource.should == ImageListing.new('1', 'http://bar.com/foo.jpg')
46
+ end
47
+
48
+ end
49
+
50
+ context '#to_xml' do
51
+
52
+ it 'shoud properly serialize to xml' do
53
+ expected = Nokogiri::XML::Builder.new {
54
+ AmazonEnvelope('xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance', 'xsi:noNamespaceSchemaLocation' => 'amznenvelope.xsd') {
55
+ Header {
56
+ DocumentVersion '1.01'
57
+ MerchantIdentifier 'GSWCJ4UBA31UTJ'
58
+ }
59
+ MessageType 'ProductImage'
60
+ PurgeAndReplace false
61
+ Message {
62
+ MessageID 1
63
+ OperationType 'Delete'
64
+ ProductImage {
65
+ SKU 1
66
+ ImageType 'Main'
67
+ ImageLocation 'http://foo.com/bar.jpg'
68
+ }
69
+ }
70
+ Message {
71
+ MessageID 2
72
+ OperationType 'Update'
73
+ ProductImage {
74
+ SKU 1
75
+ ImageType 'Main'
76
+ ImageLocation 'http://bar.com/foo.jpg'
77
+ }
78
+ }
79
+ }
80
+ }.to_xml
81
+ actual = Feed.new(merchant, message_type) do
82
+ message ImageListing.new('1', 'http://foo.com/bar.jpg'), :delete
83
+ message ImageListing.new('1', 'http://bar.com/foo.jpg')
84
+ end.to_xml
85
+ actual.should == expected
86
+ end
87
+
88
+ end
89
+
90
+ end
91
+
92
+ end
@@ -0,0 +1,109 @@
1
+ require 'spec_helper'
2
+
3
+ module Mws::Apis::Feeds
4
+
5
+ describe ImageListing do
6
+
7
+ let(:sku) { '987612345' }
8
+ let(:url) { 'http://domain.com/images/foo.png' }
9
+ let(:type) { :alt1 }
10
+ let(:listing) { ImageListing.new sku, url, type }
11
+
12
+ context '.new' do
13
+
14
+ it 'should construct an image listing with url and type' do
15
+ listing.sku.should == sku
16
+ listing.url.should == url
17
+ listing.type.should == type
18
+ end
19
+
20
+ it 'should default the image listing type to main' do
21
+ listing = ImageListing.new sku, url
22
+ listing.sku.should == sku
23
+ listing.url.should == url
24
+ listing.type.should == :main
25
+ end
26
+
27
+ it 'should require non-nil sku' do
28
+ expect { ImageListing.new(nil, url) }.to raise_error Mws::Errors::ValidationError,
29
+ 'SKU is required.'
30
+ end
31
+
32
+ it 'should require a non-empty sku' do
33
+ expect { ImageListing.new('', url) }.to raise_error Mws::Errors::ValidationError,
34
+ 'SKU is required.'
35
+ end
36
+
37
+ it 'should require a sku that is not all whitespace' do
38
+ expect { ImageListing.new(' ', url) }.to raise_error Mws::Errors::ValidationError,
39
+ 'SKU is required.'
40
+ end
41
+
42
+ it 'should require a non-nil url' do
43
+ expect { ImageListing.new(sku, nil) }.to raise_error Mws::Errors::ValidationError,
44
+ 'URL must be an unsecured http address.'
45
+ end
46
+
47
+ it 'should require a valid url' do
48
+ expect { ImageListing.new(sku, 'this is not a url') }.to raise_error Mws::Errors::ValidationError,
49
+ 'URL must be an unsecured http address.'
50
+ end
51
+
52
+ it 'should require an http url' do
53
+ expect { ImageListing.new(sku, 'ftp://domain.com/images/foo.png') }.to raise_error Mws::Errors::ValidationError,
54
+ 'URL must be an unsecured http address.'
55
+ end
56
+
57
+ it 'should require an unsecure url' do
58
+ expect { ImageListing.new(sku, 'https://domain.com/images/foo.png') }.to raise_error Mws::Errors::ValidationError,
59
+ 'URL must be an unsecured http address.'
60
+ end
61
+
62
+ end
63
+
64
+ context '#==' do
65
+
66
+ it 'should be reflexive' do
67
+ (listing == listing).should be true
68
+ end
69
+
70
+ it 'should be symmetric' do
71
+ a = listing
72
+ b = ImageListing.new(sku, url, type)
73
+ c = ImageListing.new(sku, url)
74
+ (a == b).should == (b == a)
75
+ (a == c).should == (c == a)
76
+ end
77
+
78
+ it 'should be transitive' do
79
+ a = listing
80
+ b = ImageListing.new(sku, url, type)
81
+ c = ImageListing.new(sku, url, type)
82
+ (a == c).should == (a == b && b == c)
83
+ end
84
+
85
+ it 'should handle comparison to nil' do
86
+ (listing == nil).should be false
87
+ end
88
+
89
+ end
90
+
91
+ context '#to_xml' do
92
+
93
+ it 'shoud properly serialize to xml' do
94
+ expected = Nokogiri::XML::Builder.new {
95
+ ProductImage {
96
+ SKU sku
97
+ ImageType 'PT1'
98
+ ImageLocation url
99
+ }
100
+ }.doc.root.to_xml
101
+ actual = listing.to_xml
102
+ actual.should == expected
103
+ end
104
+
105
+ end
106
+
107
+ end
108
+
109
+ end
@@ -0,0 +1,135 @@
1
+ require 'spec_helper'
2
+
3
+ module Mws::Apis::Feeds
4
+
5
+ describe Inventory do
6
+
7
+ context '.new' do
8
+
9
+ it 'should require non-nil sku' do
10
+ expect { Inventory.new(nil, quantity: 1) }.to raise_error Mws::Errors::ValidationError,
11
+ 'SKU is required.'
12
+ end
13
+
14
+ it 'should require a non-empty sku' do
15
+ expect { Inventory.new('', quantity: 1) }.to raise_error Mws::Errors::ValidationError,
16
+ 'SKU is required.'
17
+ end
18
+
19
+ it 'should require a sku that is not all whitespace' do
20
+ expect { Inventory.new(' ', quantity: 1) }.to raise_error Mws::Errors::ValidationError,
21
+ 'SKU is required.'
22
+ end
23
+
24
+ it 'should accept a valid value for sku' do
25
+ Inventory.new('987612345', quantity: 1).sku.should == '987612345'
26
+ end
27
+
28
+ it 'should require one of available, quantity or lookup' do
29
+ expect { Inventory.new('987612345', {}) }.to raise_error Mws::Errors::ValidationError,
30
+ "One and only one of 'available', 'quantity' or 'lookup' must be specified."
31
+ end
32
+
33
+ it 'should require a boolean value for available' do
34
+ expect { Inventory.new('987612345', available: 1) }.to raise_error Mws::Errors::ValidationError,
35
+ 'Available must be either true or false.'
36
+ end
37
+
38
+ it 'should accept a valid value for available' do
39
+ Inventory.new('98712345', available: true).available.should be true
40
+ end
41
+
42
+ it 'should require quantity to be a whole number greater than or equal to zero' do
43
+ expect { Inventory.new('987612345', quantity: -1) }.to raise_error Mws::Errors::ValidationError,
44
+ 'Quantity must be a whole number greater than or equal to zero.'
45
+ end
46
+
47
+ it 'should accept a valid value for quantity' do
48
+ Inventory.new('987612345', quantity: 1).quantity.should == 1
49
+ end
50
+
51
+ it 'should require a boolean value for lookup' do
52
+ expect { Inventory.new('987612345', lookup: 'Yes') }.to raise_error Mws::Errors::ValidationError,
53
+ 'Lookup must be either true or false.'
54
+ end
55
+
56
+ it 'should accept a valid value for lookup' do
57
+ Inventory.new('987612345', lookup: true).lookup.should be true
58
+ end
59
+
60
+ it 'should accept only one of available, quantity or lookup' do
61
+ expect {
62
+ Inventory.new('987612345', available: true, quantity: 1, lookup: 'FulfillmentNetwork')
63
+ }.to raise_error Mws::Errors::ValidationError,
64
+ "One and only one of 'available', 'quantity' or 'lookup' must be specified."
65
+ end
66
+
67
+ it 'should accept a valid fulfillment center' do
68
+ Inventory.new('987612345', quantity: 1, fulfillment_center: 'foo').fulfillment.center.should == 'foo'
69
+ end
70
+
71
+ it 'should require fulfillment latency to be a whole number greater than zero' do
72
+ expect {
73
+ Inventory.new('987612345', quantity: 1, fulfillment_latency: 0)
74
+ }.to raise_error Mws::Errors::ValidationError,
75
+ 'Fulfillment latency must be a whole number greater than zero.'
76
+ end
77
+
78
+ it 'should accept a valid fulfillment latency' do
79
+ Inventory.new('987612345', quantity: 1, fulfillment_latency: 1).fulfillment.latency.should == 1
80
+ end
81
+
82
+ it 'should require fulfillment type to be either AFN or MFN' do
83
+ expect {
84
+ Inventory.new('987612345', quantity: 1, fulfillment_type: 'foo')
85
+ }.to raise_error Mws::Errors::ValidationError,
86
+ "Fulfillment type must be either 'AFN' or 'MFN'."
87
+ end
88
+
89
+ it 'should accept a valid fulfillment type' do
90
+ Inventory.new('987612345', quantity: 1, fulfillment_type: :mfn).fulfillment.type.should == :mfn
91
+ end
92
+
93
+ it 'should require the restock date to be in the future' do
94
+ expect {
95
+ Inventory.new('987612345', quantity: 0, restock: Time.now)
96
+ }.to raise_error Mws::Errors::ValidationError,
97
+ 'Restock date must be in the future.'
98
+ end
99
+
100
+ it 'should accept a valid restock date' do
101
+ restock = 4.days.from_now
102
+ Inventory.new('987612345', quantity: 0, restock: restock).restock.should == restock
103
+ end
104
+
105
+ end
106
+
107
+ context '#xml_for' do
108
+
109
+ it 'should properly serialize to XML' do
110
+ restock = 4.days.from_now
111
+ inventory = Inventory.new('987612345',
112
+ quantity: 5,
113
+ fulfillment_center: 'A1B2C3D4E5',
114
+ fulfillment_latency: 3,
115
+ fulfillment_type: :mfn,
116
+ restock: restock
117
+ )
118
+ expected = Nokogiri::XML::Builder.new do
119
+ Inventory {
120
+ SKU '987612345'
121
+ FulfillmentCenterID 'A1B2C3D4E5'
122
+ Quantity 5
123
+ RestockDate restock.iso8601
124
+ FulfillmentLatency 3
125
+ SwitchFulfillmentTo 'MFN'
126
+ }
127
+ end.doc.root.to_xml
128
+ inventory.to_xml.should == expected
129
+ end
130
+
131
+ end
132
+
133
+ end
134
+
135
+ end
@@ -0,0 +1,84 @@
1
+ require 'spec_helper'
2
+
3
+ module Mws::Apis::Feeds
4
+
5
+ class Temperature < Measurement
6
+
7
+ Unit = Mws::Enum.for(
8
+ fahrenheit: 'Fahrenheight',
9
+ celcius: 'Celcius',
10
+ kelvin: 'Kelvin'
11
+ )
12
+
13
+ def initialize(amount, unit=:fahrenheit)
14
+ super amount, unit
15
+ end
16
+
17
+ end
18
+
19
+ describe Measurement do
20
+
21
+ context '.new' do
22
+
23
+ it 'should default to fahrenheit' do
24
+ temp = Temperature.new 40
25
+ temp.amount.should == 40
26
+ temp.unit.should == :fahrenheit
27
+ end
28
+
29
+ it 'should accept a valid unit override' do
30
+ temp = Temperature.new 0, :kelvin
31
+ temp.amount.should == 0
32
+ temp.unit.should == :kelvin
33
+ end
34
+
35
+ it 'should validate the unit override' do
36
+ expect {
37
+ Temperature.new 40, :ounces
38
+ }.to raise_error Mws::Errors::ValidationError, "Invalid unit of measure 'ounces'"
39
+ end
40
+
41
+ end
42
+
43
+ context '#==' do
44
+
45
+ it 'should be reflexive' do
46
+ a = Temperature.new 25, :celcius
47
+ (a == a).should be true
48
+ end
49
+
50
+ it 'should be symmetric' do
51
+ a = Temperature.new 25, :celcius
52
+ b = Temperature.new 25, :celcius
53
+ (a == b).should == (b == a)
54
+ end
55
+
56
+ it 'should be transitive' do
57
+ a = Temperature.new 25, :celcius
58
+ b = Temperature.new 25, :celcius
59
+ c = Temperature.new 25, :celcius
60
+ (a == c).should == (a == b && b == c)
61
+ end
62
+
63
+ it 'should handle comparison to nil' do
64
+ a = Temperature.new 25, :celcius
65
+ (a == nil).should be false
66
+ end
67
+
68
+ end
69
+
70
+ context '#to_xml' do
71
+
72
+ it 'should properly serialize to XML' do
73
+ temp = Temperature.new 25, :celcius
74
+ expected = Nokogiri::XML::Builder.new do
75
+ Temperature 25, unitOfMeasure: 'Celcius'
76
+ end.doc.root.to_xml
77
+ temp.to_xml.should == expected
78
+ end
79
+
80
+ end
81
+
82
+ end
83
+
84
+ end