amazon-associates 0.6.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. data/.gitignore +3 -0
  2. data/CHANGELOG +29 -0
  3. data/LICENSE +21 -0
  4. data/README.rdoc +84 -0
  5. data/Rakefile +62 -0
  6. data/VERSION.yml +5 -0
  7. data/amazon-associates.gemspec +118 -0
  8. data/lib/amazon-associates.rb +90 -0
  9. data/lib/amazon-associates/caching/filesystem_cache.rb +121 -0
  10. data/lib/amazon-associates/errors.rb +23 -0
  11. data/lib/amazon-associates/extensions/core.rb +31 -0
  12. data/lib/amazon-associates/extensions/hpricot.rb +115 -0
  13. data/lib/amazon-associates/request.rb +143 -0
  14. data/lib/amazon-associates/requests/browse_node.rb +10 -0
  15. data/lib/amazon-associates/requests/cart.rb +81 -0
  16. data/lib/amazon-associates/requests/item.rb +13 -0
  17. data/lib/amazon-associates/responses/browse_node_lookup_response.rb +10 -0
  18. data/lib/amazon-associates/responses/cart_responses.rb +26 -0
  19. data/lib/amazon-associates/responses/item_lookup_response.rb +16 -0
  20. data/lib/amazon-associates/responses/item_search_response.rb +20 -0
  21. data/lib/amazon-associates/responses/response.rb +27 -0
  22. data/lib/amazon-associates/responses/similarity_lookup_response.rb +9 -0
  23. data/lib/amazon-associates/types/api_result.rb +8 -0
  24. data/lib/amazon-associates/types/browse_node.rb +48 -0
  25. data/lib/amazon-associates/types/cart.rb +87 -0
  26. data/lib/amazon-associates/types/customer_review.rb +15 -0
  27. data/lib/amazon-associates/types/editorial_review.rb +8 -0
  28. data/lib/amazon-associates/types/error.rb +8 -0
  29. data/lib/amazon-associates/types/image.rb +37 -0
  30. data/lib/amazon-associates/types/image_set.rb +11 -0
  31. data/lib/amazon-associates/types/item.rb +156 -0
  32. data/lib/amazon-associates/types/listmania_list.rb +9 -0
  33. data/lib/amazon-associates/types/measurement.rb +47 -0
  34. data/lib/amazon-associates/types/offer.rb +10 -0
  35. data/lib/amazon-associates/types/ordinal.rb +24 -0
  36. data/lib/amazon-associates/types/price.rb +29 -0
  37. data/lib/amazon-associates/types/requests.rb +50 -0
  38. data/spec/requests/browse_node_lookup_spec.rb +41 -0
  39. data/spec/requests/item_search_spec.rb +27 -0
  40. data/spec/spec_helper.rb +8 -0
  41. data/spec/types/cart_spec.rb +294 -0
  42. data/spec/types/item_spec.rb +55 -0
  43. data/spec/types/measurement_spec.rb +43 -0
  44. data/test/amazon/browse_node_test.rb +34 -0
  45. data/test/amazon/cache_test.rb +33 -0
  46. data/test/amazon/caching/filesystem_cache_test.rb +198 -0
  47. data/test/amazon/item_test.rb +397 -0
  48. data/test/test_helper.rb +9 -0
  49. data/test/utilities/filesystem_test_helper.rb +35 -0
  50. metadata +216 -0
@@ -0,0 +1,55 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ module Amazon
4
+ module Associates
5
+ describe Item do
6
+ before(:all) do
7
+ @item = Amazon::Associates::item_lookup("0545010225").item
8
+ end
9
+
10
+ it "should equal anything with the same #asin" do
11
+ asin = @item.asin
12
+ @item.should == Struct.new(:asin).new(asin)
13
+ end
14
+
15
+ describe "query for items", :shared => true do
16
+ it "should return a list of items" do
17
+ @result.should have_at_least(10).items
18
+ @result.each {|item| item.should be_an_instance_of(Item) }
19
+ end
20
+ end
21
+
22
+ describe "query for related items", :shared => true do
23
+ it_should_behave_like "query for items"
24
+ it "should not include the item related to the result" do
25
+ @result.should_not include(@item)
26
+ end
27
+ end
28
+
29
+ describe ".similar" do
30
+ before(:all) do
31
+ @result = Item.similar(@item.asin)
32
+ end
33
+ it_should_behave_like "query for related items"
34
+ end
35
+
36
+ describe ".all" do
37
+ before(:all) do
38
+ @result = Item.all("search_index"=>"Blended", "keywords"=>"potter")
39
+ end
40
+ it_should_behave_like "query for items"
41
+
42
+ it "should handle hashes with indifferent access" do
43
+ Item.all(HashWithIndifferentAccess.new("search_index"=>"Blended", "keywords"=>"hello")).should_not == nil
44
+ end
45
+ end
46
+
47
+ describe "#similar" do
48
+ before(:all) do
49
+ @result = @item.similar
50
+ end
51
+ it_should_behave_like "query for related items"
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,43 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe "measurement object", :shared => true do
4
+ it "should take a quantity and units" do
5
+ m = measurement_with(:value => 11.3, :units => 'inches')
6
+ m.value.should == 11.3
7
+ m.units.should == 'inches'
8
+ end
9
+
10
+ it "should default units to 'pixels', as we use it mostly for images" do
11
+ m = measurement_with(:value => 22.19)
12
+ m.value.should == 22.19
13
+ m.units.should == 'pixels'
14
+ end
15
+
16
+ it "should translate 'hundredths-' units to standard quantities" do
17
+ m = measurement_with(:value => 1130, :units => 'hundredths-inches')
18
+ m.value.should == 11.3
19
+ m.units.should == 'inches'
20
+ end
21
+ end
22
+
23
+ describe Amazon::Associates::Measurement do
24
+ describe "#initialize" do
25
+ def measurement_with(opts)
26
+ Amazon::Associates::Measurement.new(*opts.values_at(:value, :units).compact)
27
+ end
28
+
29
+ it_should_behave_like "measurement object"
30
+ end
31
+
32
+ describe "#from_xml" do
33
+ def measurement_with(opts)
34
+ doc = ROXML::XML::Document.new
35
+ doc.root = ROXML::XML::Node.new('width', doc)
36
+ doc.root.add_child( Nokogiri::XML::Text.new(opts[:value].to_s, doc))
37
+ doc.root['Units'] = opts[:units] unless opts[:units].blank?
38
+ Amazon::Associates::Measurement.from_xml(doc.root)
39
+ end
40
+
41
+ it_should_behave_like "measurement object"
42
+ end
43
+ end
@@ -0,0 +1,34 @@
1
+ require File.dirname(__FILE__) + "/../test_helper"
2
+
3
+ class Amazon::Associates::BrowseNodeLookupTest < Test::Unit::TestCase
4
+ include FilesystemTestHelper
5
+
6
+ def setup
7
+ set_valid_caching_options
8
+ end
9
+
10
+ def test_browse_node_lookup_with_invalid_request
11
+ assert_raise(Amazon::Associates::RequiredParameterMissing) do
12
+ Amazon::Associates.browse_node_lookup(nil)
13
+ end
14
+ end
15
+
16
+ def test_browse_node_lookup_with_no_result
17
+ assert_raise(Amazon::Associates::InvalidParameterValue) do
18
+ Amazon::Associates.browse_node_lookup("abc")
19
+ end
20
+ end
21
+
22
+ def test_items_have_browsenodes
23
+ item = Amazon::Associates.item_lookup('B000ROI682', :response_group => 'BrowseNodes').items.first
24
+ assert item.browse_nodes.size > 1
25
+ item.browse_nodes.each do |browsenode|
26
+ assert_kind_of Amazon::Associates::BrowseNode, browsenode
27
+ assert !browsenode.to_s.include?('&amp;'), browsenode.to_s
28
+ end
29
+ end
30
+
31
+ def test_browse_nodes_have_top_sellers
32
+ assert !Amazon::Associates.browse_node_lookup(:response_group => 'TopSellers', :browse_node_id => 493964).browse_nodes.first.top_sellers.empty?
33
+ end
34
+ end
@@ -0,0 +1,33 @@
1
+ require File.dirname(__FILE__) + "/../test_helper"
2
+
3
+ module Amazon
4
+ module Associates
5
+ class CacheTest < Test::Unit::TestCase
6
+ include FilesystemTestHelper
7
+ context "caching get" do
8
+ setup do
9
+ set_valid_caching_options(CACHE_TEST_PATH)
10
+ end
11
+
12
+ teardown do
13
+ reset_cache
14
+ end
15
+
16
+ should "optionally allow for a caching strategy in configuration" do
17
+ assert_nothing_raised do
18
+ set_valid_caching_options(CACHE_TEST_PATH)
19
+ end
20
+ assert Amazon::Associates.caching_enabled?
21
+ end
22
+
23
+ should "raise an exception if a caching strategy is specified that is not found" do
24
+ assert_raise Amazon::Associates::ConfigurationError do
25
+ Amazon::Associates.configure do |options|
26
+ options[:caching_strategy] = "foo"
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,198 @@
1
+ require File.dirname(__FILE__) + "/../../test_helper"
2
+
3
+ module Amazon
4
+ module Associates
5
+ class FilesystemCacheTest < Test::Unit::TestCase
6
+ include FilesystemTestHelper
7
+ context "setting up filesystem caching" do
8
+ teardown do
9
+ Amazon::Associates.configure do |options|
10
+ options[:caching_strategy] = nil
11
+ options[:caching_options] = nil
12
+ end
13
+ end
14
+
15
+ should "require a caching options hash with a cache_path key" do
16
+ assert_raise Amazon::Associates::ConfigurationError do
17
+ Amazon::Associates.configure do |options|
18
+ options[:caching_strategy] = :filesystem
19
+ options[:caching_options] = nil
20
+ end
21
+ end
22
+ end
23
+
24
+ should "raise an exception when a cache_path is specified that doesn't exist" do
25
+ assert_raise Amazon::Associates::ConfigurationError do
26
+ Amazon::Associates.configure do |options|
27
+ options[:caching_strategy] = :filesystem
28
+ options[:caching_options] = {:cache_path => "foo123"}
29
+ end
30
+ end
31
+ end
32
+
33
+ should "set default values for disk_quota and sweep_frequency" do
34
+ Amazon::Associates.configure do |options|
35
+ options[:caching_strategy] = :filesystem
36
+ options[:caching_options] = {:cache_path => "."}
37
+ end
38
+
39
+ assert_equal Amazon::Associates::FilesystemCache.disk_quota, Amazon::Associates::FilesystemCache.disk_quota
40
+ assert_equal Amazon::Associates::FilesystemCache.sweep_frequency, Amazon::Associates::FilesystemCache.sweep_frequency
41
+ end
42
+
43
+ should "override the default value for disk quota if I specify one" do
44
+ quota = 400
45
+ Amazon::Associates.configure do |options|
46
+ options[:caching_strategy] = :filesystem
47
+ options[:caching_options] = {:cache_path => ".", :disk_quota => quota}
48
+ end
49
+
50
+ assert_equal quota, Amazon::Associates::FilesystemCache.disk_quota
51
+ end
52
+
53
+ should "override the default value for cache_frequency if I specify one" do
54
+ frequency = 4
55
+ Amazon::Associates.configure do |options|
56
+ options[:caching_strategy] = :filesystem
57
+ options[:caching_options] = {:cache_path => ".", :sweep_frequency => frequency}
58
+ end
59
+
60
+ assert_equal frequency, Amazon::Associates::FilesystemCache.sweep_frequency
61
+ end
62
+ end
63
+
64
+ context "caching a request" do
65
+
66
+ setup do
67
+ set_valid_caching_options(CACHE_TEST_PATH)
68
+ @resp = Amazon::Associates.item_lookup("0974514055")
69
+ @filename = Digest::SHA1.hexdigest(@resp.url)
70
+ end
71
+
72
+ teardown do
73
+ reset_cache
74
+ end
75
+
76
+ should "create a folder in the cache path with the first three letters of the digested filename" do
77
+ assert FileTest.exists?(File.join(CACHE_TEST_PATH, @filename[0..2]))
78
+ end
79
+
80
+ should "create a file in the cache path with a digested version of the url " do
81
+ assert FileTest.exists?(File.join(CACHE_TEST_PATH, @filename[0..2], @filename))
82
+ end
83
+
84
+ should "create a file in the cache path with the response inside it" do
85
+ open(File.join(CACHE_TEST_PATH + @filename[0..2], @filename)) do |f|
86
+ response = Marshal.load(f)
87
+ equivalent = eval(ROXML::XML::Parser.parse(response.body).root.name).from_xml(response.body, @resp.url)
88
+
89
+ assert_equal @resp, equivalent
90
+ end
91
+ end
92
+
93
+ should "not attemt to cache cart requests" do
94
+ Amazon::Associates::FilesystemCache.expects(:cache).never
95
+
96
+ resp = Amazon::Associates.cart_create(:items => {"0974514055" => 2})
97
+ filename = Digest::SHA1.hexdigest(resp.url)
98
+ assert !FileTest.exists?(File.join(CACHE_TEST_PATH, filename[0..2], filename))
99
+ end
100
+ end
101
+
102
+ context "getting a cached request" do
103
+ setup do
104
+ set_valid_caching_options(CACHE_TEST_PATH)
105
+ do_request
106
+ end
107
+
108
+ teardown do
109
+ reset_cache
110
+ end
111
+
112
+ should "not do an http request the second time the lookup is performed due a cached copy" do
113
+ Net::HTTP.expects(:get_response).never
114
+ do_request
115
+ end
116
+
117
+ should "return the same response as the original request" do
118
+ original = @resp
119
+ do_request
120
+ assert_equal(original, @resp)
121
+ end
122
+
123
+ should "not include cache parameters in the response" do
124
+ assert_no_match(/CachingOptions/, @resp.url)
125
+ assert_no_match(/caching_options/, @resp.url)
126
+ assert_no_match(/cache_path/, @resp.url)
127
+ assert_no_match(/disk_quota/, @resp.url)
128
+ end
129
+ end
130
+
131
+ context "sweeping cached requests" do
132
+ setup do
133
+ set_valid_caching_options(CACHE_TEST_PATH)
134
+ do_request
135
+ end
136
+
137
+ teardown do
138
+ reset_cache
139
+ end
140
+
141
+ should "not perform the sweep if the timestamp is within the range of the sweep frequency and quota is not exceeded" do
142
+ Amazon::Associates::FilesystemCache.expects(:sweep_time_expired?).returns(false)
143
+ Amazon::Associates::FilesystemCache.expects(:disk_quota_exceeded?).returns(false)
144
+
145
+ Amazon::Associates::FilesystemCache.expects(:perform_sweep).never
146
+
147
+ do_request
148
+ end
149
+
150
+ should "perform a sweep if the quota is exceeded" do
151
+ Amazon::Associates::FilesystemCache.stubs(:sweep_time_expired?).returns(false)
152
+ Amazon::Associates::FilesystemCache.expects(:disk_quota_exceeded?).once.returns(true)
153
+
154
+ Amazon::Associates::FilesystemCache.expects(:perform_sweep).once
155
+
156
+ do_request
157
+ end
158
+
159
+ should "perform a sweep if the sweep time is expired" do
160
+ Amazon::Associates::FilesystemCache.expects(:sweep_time_expired?).once.returns(true)
161
+ Amazon::Associates::FilesystemCache.stubs(:disk_quota_exceeded?).returns(false)
162
+ Amazon::Associates::FilesystemCache.expects(:perform_sweep).once
163
+
164
+ do_request
165
+ end
166
+
167
+ should "create a timestamp file after performing a sweep" do
168
+ Amazon::Associates::FilesystemCache.expects(:sweep_time_expired?).once.returns(true)
169
+
170
+ do_request
171
+ assert FileTest.exists?(File.join(CACHE_TEST_PATH, ".amz_timestamp"))
172
+ end
173
+
174
+ should "purge the cache when performing a sweep" do
175
+ (0..9).each do |n|
176
+ test = File.open(File.join(CACHE_TEST_PATH, "test_file_#{n}"), "w")
177
+ test.puts Time.now
178
+ test.close
179
+ end
180
+
181
+ Amazon::Associates::FilesystemCache.expects(:sweep_time_expired?).once.returns(true)
182
+ do_request
183
+
184
+ (0..9).each do |n|
185
+ assert !FileTest.exists?(File.join(CACHE_TEST_PATH, "test_file_#{n}"))
186
+ end
187
+ end
188
+
189
+ end
190
+
191
+ protected
192
+ def do_request
193
+ @resp = Amazon::Associates.item_lookup("0974514055")
194
+ end
195
+ end
196
+
197
+ end
198
+ end
@@ -0,0 +1,397 @@
1
+ require File.join(File.dirname(__FILE__), '../test_helper')
2
+
3
+ module Amazon
4
+ module Associates
5
+ class ItemTest < Test::Unit::TestCase
6
+ include FilesystemTestHelper
7
+
8
+ ## Test item_search
9
+ def setup
10
+ set_valid_caching_options
11
+ @ruby_search = Amazon::Associates.item_search('ruby')
12
+ end
13
+
14
+ def test_item_search
15
+ assert @ruby_search.request.valid?
16
+ assert @ruby_search.total_results >= 3600
17
+ assert @ruby_search.total_pages >= 360
18
+ end
19
+
20
+ def test_page_should_be_one_for_first_page
21
+ assert_equal 1, @ruby_search.current_page
22
+ end
23
+
24
+ def test_item_search_response_type
25
+ assert_equal ItemSearchResponse, @ruby_search.class
26
+ end
27
+
28
+ def test_argument_hash
29
+ assert_equal Hash, @ruby_search.operation_request.arguments.class
30
+ end
31
+
32
+ def test_item_search_with_paging
33
+ resp = Amazon::Associates.item_search('ruby', :item_page => 2)
34
+ assert resp.request.valid?
35
+ assert 2, resp.current_page
36
+ end
37
+
38
+ def test_item_search_with_response_group_array
39
+ resp = Amazon::Associates.item_search('ruby', :response_group => %w{Small ItemAttributes Images})
40
+ assert resp.request.valid?
41
+ end
42
+
43
+ def test_item_search_with_invalid_request
44
+ assert_raise Amazon::Associates::RequiredParameterMissing do
45
+ Amazon::Associates.item_search(nil)
46
+ end
47
+ end
48
+
49
+ def test_item_search_with_no_result
50
+ assert_raise Amazon::Associates::ItemNotFound, ' We did not find any matches for your request.' do
51
+ Amazon::Associates.item_search('afdsafds')
52
+ end
53
+ end
54
+
55
+ def test_item_search_uk
56
+ resp = Amazon::Associates.item_search('ruby', :country => 'uk')
57
+ assert resp.request.valid?
58
+ end
59
+
60
+ def test_item_search_not_keywords
61
+ resp = Amazon::Associates.item_search(:author => 'rowling')
62
+ assert resp.request.valid?
63
+ end
64
+
65
+ def test_item_search_by_author
66
+ resp = Amazon::Associates.item_search('dave', :type => :author)
67
+ assert resp.request.valid?
68
+ end
69
+
70
+ def test_text_at
71
+ item = Amazon::Associates.item_search("0974514055", :response_group => 'Large').items.first
72
+
73
+ # one item
74
+ assert_equal "Programming Ruby: The Pragmatic Programmers' Guide, Second Edition",
75
+ item.attributes['Title']
76
+
77
+ # multiple items
78
+ assert_equal ['Dave Thomas', 'Chad Fowler', 'Andy Hunt'],
79
+ item.authors
80
+
81
+ #ordinals
82
+ assert_equal Amazon::Associates::Ordinal.new(2), item.edition
83
+ end
84
+
85
+ def test_item_search_should_handle_string_argument_keys_as_well_as_symbols
86
+ Amazon::Associates.item_search('potter', 'search_index' => 'Books')
87
+ end
88
+
89
+ def test_hash_at_handles_specific_types
90
+ item = Amazon::Associates.item_search('ipod', :search_index => 'All', :response_group => 'Small,Offers,ItemAttributes,VariationSummary,Images,BrowseNodes').items.first
91
+
92
+ # Measurements & Image
93
+ assert_equal(Amazon::Associates::Image.new("http://ecx.images-amazon.com/images/I/41zt-RXYhfL._SL75_.jpg",
94
+ Amazon::Associates::Measurement.new(56, 'pixels'),
95
+ Amazon::Associates::Measurement.new(75, 'pixels')),
96
+ item.small_image)
97
+
98
+ # bools
99
+ assert !item.offers.empty?
100
+ assert_equal true, item.offers.first.is_eligible_for_super_saver_shipping?
101
+ assert_equal false, item.batteries_included?
102
+
103
+ # price
104
+ assert_equal Amazon::Associates::Price.new('$249.99', 24999, 'USD'), item.list_price
105
+
106
+ # integers
107
+ assert_instance_of Fixnum, item.total_new_offers
108
+ assert_instance_of Fixnum, item.total_offers
109
+
110
+ # attributes
111
+ assert item.image_sets['primary'], item.image_sets.inspect
112
+ assert_equal "Mary GrandPré", Amazon::Associates.item_lookup('0545010225').item.creators['Illustrator']
113
+
114
+ # browsenodes
115
+ nodes = item.browse_nodes.detect {|n| n.name == 'MP3 Players' }
116
+ assert_equal 'MP3 Players', nodes.name
117
+ assert_equal 'Audio & Video', nodes.parent.name
118
+ assert_equal 'Apple', nodes.parent.parent.name
119
+ assert_equal 'Custom Brands', nodes.parent.parent.parent.name
120
+
121
+ # ordinals
122
+ # in test_text_at, above
123
+ end
124
+
125
+ def test_price_should_handle_price_too_low_to_display
126
+ assert_equal 'Too low to display', Amazon::Associates.item_lookup('B000W79GQA', :response_group => 'Offers').item.lowest_new_price.to_s
127
+ end
128
+
129
+ def test_hash_at_handles_string_editions
130
+ Amazon::Associates.item_search("potter", :item_page => 3, :response_group => 'Small,Offers,ItemAttributes,VariationSummary,Images').items.each do |item|
131
+ assert item
132
+ end
133
+ end
134
+
135
+ def test_hash_at_makes_arrays_from_lists
136
+ item = Amazon::Associates.item_search("0974514055", :response_group => 'Large').items.first
137
+
138
+ # when <listmanialists> contains a bunch of <listmanialist>s, return an array
139
+ assert_equal(["R35BVGTHX7WEKZ", "R195F9SN6I3YQH", "R14L8RHCLAYQMY", "RCWKKCCVL5FGL", "R2IJ2M3X3ITVAR",
140
+ "R3MGYO2P65FC8J", "R2VY37TQWQM0VJ", "R3DB3MYO22PHZ6", "R192F79G3UXHJ5", "R1L6QNM215M7FB"],
141
+ item.listmania_lists.map(&:id))
142
+
143
+ review = item.editorial_reviews.first
144
+ # when there's a single child, make sure it's parsed rather than returned as a string
145
+ assert_equal "Product Description", review.source
146
+ assert review.content.is_a?(String)
147
+ assert review.content.size > 100
148
+ assert review.content.starts_with?("Ruby is an increasingly popular, fully object-oriented d")
149
+ end
150
+
151
+ ## Test item_lookup
152
+ def test_item_lookup
153
+ resp = Amazon::Associates.item_lookup('0974514055')
154
+ assert_equal "Programming Ruby: The Pragmatic Programmers' Guide, Second Edition",
155
+ resp.item.attributes['Title']
156
+ end
157
+
158
+ def test_item_lookup_with_invalid_request
159
+ assert_raise Amazon::Associates::RequiredParameterMissing, 'Your request is missing required parameters. Required parameters include ItemId.' do
160
+ Amazon::Associates.item_lookup(nil)
161
+ end
162
+ end
163
+
164
+ def test_item_lookup_with_no_result
165
+ assert_raise Amazon::Associates::InvalidParameterValue, 'ABC is not a valid value for ItemId. Please change this value and retry your request.' do
166
+ resp = Amazon::Associates.item_lookup('abc')
167
+ raise resp.inspect
168
+ end
169
+ end
170
+
171
+ def test_hpricot_extensions
172
+ item = Amazon::Associates.item_lookup('0974514055').item
173
+
174
+ assert_equal "Programming Ruby: The Pragmatic Programmers' Guide, Second Edition", item.attributes['Title']
175
+ assert item.authors.is_a?(Array)
176
+ assert 3, item.authors.size
177
+ assert_equal "Dave Thomas", item.authors.first
178
+ end
179
+ end
180
+
181
+ class Amazon::Associates::ItemTestsBroughtInFromAssociateGem < Test::Unit::TestCase
182
+ include FilesystemTestHelper
183
+
184
+ def setup
185
+ set_valid_caching_options
186
+ Amazon::Associates.options.merge!(:response_group => "Large")
187
+ end
188
+
189
+ ## Test item_search
190
+ def test_item_search
191
+ resp = Amazon::Associates.item_search("ruby")
192
+ assert(resp.request.valid?, resp.inspect)
193
+ assert(resp.total_results >= 3600)
194
+ assert(resp.total_pages >= 360)
195
+ end
196
+
197
+ def test_item_search_with_paging
198
+ resp = Amazon::Associates.item_search("ruby", :item_page => 2)
199
+ assert resp.request.valid?, resp.inspect
200
+ assert 2, resp.current_page
201
+ end
202
+
203
+ def test_item_search_with_no_result
204
+ assert_raise(Amazon::Associates::ItemNotFound) do
205
+ Amazon::Associates.item_search("afdsafds")
206
+ end
207
+ end
208
+
209
+ def test_item_search_uk
210
+ resp = Amazon::Associates.item_search("ruby", :country => :uk)
211
+ assert resp.request.valid?
212
+ end
213
+
214
+ def test_item_search_by_author
215
+ resp = Amazon::Associates.item_search("dave", :type => :author)
216
+ assert resp.request.valid?
217
+ end
218
+
219
+ def test_item_get
220
+ resp = Amazon::Associates.item_search("0974514055")
221
+ item = resp.items.first
222
+
223
+ # test get
224
+ assert_equal "Programming Ruby: The Pragmatic Programmers' Guide, Second Edition",
225
+ item.attributes['Title']
226
+
227
+ # test get_array
228
+ assert_equal ['Dave Thomas', 'Chad Fowler', 'Andy Hunt'], item.authors
229
+
230
+ # test get_hash
231
+ small_image = item.image_sets.values.first.small
232
+
233
+ assert small_image.url != nil
234
+ assert_equal 75, small_image.height.value
235
+ assert_equal 59, small_image.width.value
236
+ end
237
+
238
+ ## Test item_lookup
239
+ def test_item_lookup
240
+ resp = Amazon::Associates.item_lookup("0974514055")
241
+ assert_equal "Programming Ruby: The Pragmatic Programmers' Guide, Second Edition",
242
+ resp.items.first.attributes['Title']
243
+ end
244
+
245
+ def test_item_lookup_with_invalid_request
246
+ assert_raise(Amazon::Associates::RequiredParameterMissing) do
247
+ Amazon::Associates.item_lookup(nil)
248
+ end
249
+ end
250
+
251
+ def test_item_lookup_with_no_result
252
+ assert_raise(Amazon::Associates::InvalidParameterValue) do
253
+ resp = Amazon::Associates.item_lookup("abc")
254
+ end
255
+ end
256
+
257
+ def test_search_and_convert
258
+ resp = Amazon::Associates.item_lookup("0974514055")
259
+ title = resp.items.first.attributes['Title']
260
+ authors = resp.items.first.authors
261
+
262
+ assert_equal "Programming Ruby: The Pragmatic Programmers' Guide, Second Edition", title
263
+ assert authors.is_a?(Array)
264
+ assert 3, authors.size
265
+ assert_equal "Dave Thomas", authors.first
266
+ end
267
+ end
268
+
269
+ class ItemTestBroughtIn < Test::Unit::TestCase
270
+ include FilesystemTestHelper
271
+
272
+ def setup
273
+ set_valid_caching_options
274
+ end
275
+
276
+ def test_find_all_should_return_items
277
+ item = Item.find(:all, :keywords => 'upside').first
278
+ assert item
279
+ assert_kind_of Item, item
280
+ end
281
+
282
+ def test_find_all_and_find_first_should_yield_same_first
283
+ params = {:keywords => 'jelly'}
284
+ assert_equal Item.find(:all, params).first, Item.find(:first, params)
285
+ end
286
+
287
+ def test_find_second_page_returns_different_items_than_first
288
+ params = {:keywords => 'potter'}
289
+ assert_not_equal Item.find(:first, params.merge(:page => 1)),
290
+ Item.find(:first, params.merge(:page => 2))
291
+ end
292
+
293
+ def test_item_creator_should_be_unpacked
294
+ p "Pending: we're losing info from attributes..."
295
+ # asin = '0545010225'
296
+ # item = Item.find(asin)
297
+ # assert_equal("Mary GrandPré",
298
+ # Amazon::Associates.item_lookup(asin).items.first.attributes["Creator"])
299
+ end
300
+
301
+ def test_item_list_price_present
302
+ assert Item.find('0545010225').list_price
303
+ end
304
+
305
+ def test_item_performers_unpacked_to_array
306
+ assert_equal(["Robert Downey Jr.", "Gwyneth Paltrow", "Terrence Howard", "Jeff Bridges", "Leslie Bibb"],
307
+ Item.find('B00005JPS8').attributes['Actor'])
308
+ end
309
+
310
+ def test_image_sets_should_be_unpacked
311
+ item = Item.find(:first, :keywords => 'potter')
312
+ assert !item.image_sets.empty?
313
+ end
314
+
315
+ def test_missing_item_should_throw
316
+ assert_raise Amazon::Associates::InvalidParameterValue do
317
+ Item.find('abc')
318
+ end
319
+ end
320
+
321
+ def test_find_no_page_returns_same_items_as_first
322
+ params = {:keywords => 'potter'}
323
+ assert_equal Item.find(:first, params),
324
+ Item.find(:first, params.merge(:page => 1))
325
+ end
326
+
327
+ def test_find_with_different_sort_returns_different
328
+ params = {:keywords => 'potter'}
329
+ assert_not_equal Item.find(:first, params.merge(:sort => Amazon::Associates::SORT_TYPES['Books'][3])),
330
+ Item.find(:first, params.merge(:sort => Amazon::Associates::SORT_TYPES['Books'][7]))
331
+ assert_equal Item.find(:first, params.merge(:sort => Amazon::Associates::SORT_TYPES['Books'][3])),
332
+ Item.find(:first, params.merge(:sort => Amazon::Associates::SORT_TYPES['Books'][3]))
333
+ end
334
+
335
+ def test_find_too_far_a_page_is_error
336
+ assert_raise Amazon::Associates::ParameterOutOfRange do
337
+ Item.find(:first, :keywords => 'potter', :page => 9999)
338
+ end
339
+ end
340
+
341
+ def test_none_found_is_error
342
+ assert_raise Amazon::Associates::ItemNotFound do
343
+ Item.find(:first, :keywords => 'zjvalk', :page => 400)
344
+ end
345
+ end
346
+
347
+ def test_pagination_basics
348
+ results = Item.find(:all, :keywords => 'potter', :search_index => 'All')
349
+ assert_equal 4000, results.total_entries
350
+ assert_equal 1, results.current_page
351
+ end
352
+
353
+ def test_pagination_sets_current_page
354
+ [3, 7].each do |page|
355
+ assert_equal page, Item.find(:all, :keywords => 'potter', :page => page).current_page
356
+ end
357
+ end
358
+
359
+ def test_should_reject_unknown_args
360
+ assert_raise ArgumentError do
361
+ Item.find(:first, :keywords => 'potter', :itempage => 12)
362
+ end
363
+ end
364
+
365
+ def test_find_should_work_for_blended_merchants_and_all
366
+ assert Item.find(:first, :keywords => 'blackberry', :search_index => 'Blended')
367
+ assert Item.find(:first, :keywords => 'blackberry', :search_index => 'All')
368
+ assert Item.find(:first, :keywords => 'blackberry', :search_index => 'Merchants')
369
+ end
370
+
371
+ def test_find_top_sellers_should_return_items
372
+ assert !Item.find(:top_sellers, :browse_node_id => 520432).empty?
373
+ end
374
+
375
+ def test_should_find_one
376
+ item_asin = '0545010225'
377
+ item = Item.find(item_asin)
378
+ assert item
379
+ assert item.is_a?(Item)
380
+ assert_equal item_asin, item.asin
381
+ end
382
+
383
+ def test_find_one_and_first_should_be_equivalent
384
+ # TODO: or maybe a subset?
385
+ item1 = Item.find(:first, :keywords => 'potter')
386
+ item2 = Item.find(item1.asin)
387
+ assert_equal item1, item2
388
+ end
389
+
390
+ def test_should_raise_on_bad_request
391
+ assert_raise ArgumentError do
392
+ Item.find(20)
393
+ end
394
+ end
395
+ end
396
+ end
397
+ end