amazon-associates 0.6.3
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +3 -0
- data/CHANGELOG +29 -0
- data/LICENSE +21 -0
- data/README.rdoc +84 -0
- data/Rakefile +62 -0
- data/VERSION.yml +5 -0
- data/amazon-associates.gemspec +118 -0
- data/lib/amazon-associates.rb +90 -0
- data/lib/amazon-associates/caching/filesystem_cache.rb +121 -0
- data/lib/amazon-associates/errors.rb +23 -0
- data/lib/amazon-associates/extensions/core.rb +31 -0
- data/lib/amazon-associates/extensions/hpricot.rb +115 -0
- data/lib/amazon-associates/request.rb +143 -0
- data/lib/amazon-associates/requests/browse_node.rb +10 -0
- data/lib/amazon-associates/requests/cart.rb +81 -0
- data/lib/amazon-associates/requests/item.rb +13 -0
- data/lib/amazon-associates/responses/browse_node_lookup_response.rb +10 -0
- data/lib/amazon-associates/responses/cart_responses.rb +26 -0
- data/lib/amazon-associates/responses/item_lookup_response.rb +16 -0
- data/lib/amazon-associates/responses/item_search_response.rb +20 -0
- data/lib/amazon-associates/responses/response.rb +27 -0
- data/lib/amazon-associates/responses/similarity_lookup_response.rb +9 -0
- data/lib/amazon-associates/types/api_result.rb +8 -0
- data/lib/amazon-associates/types/browse_node.rb +48 -0
- data/lib/amazon-associates/types/cart.rb +87 -0
- data/lib/amazon-associates/types/customer_review.rb +15 -0
- data/lib/amazon-associates/types/editorial_review.rb +8 -0
- data/lib/amazon-associates/types/error.rb +8 -0
- data/lib/amazon-associates/types/image.rb +37 -0
- data/lib/amazon-associates/types/image_set.rb +11 -0
- data/lib/amazon-associates/types/item.rb +156 -0
- data/lib/amazon-associates/types/listmania_list.rb +9 -0
- data/lib/amazon-associates/types/measurement.rb +47 -0
- data/lib/amazon-associates/types/offer.rb +10 -0
- data/lib/amazon-associates/types/ordinal.rb +24 -0
- data/lib/amazon-associates/types/price.rb +29 -0
- data/lib/amazon-associates/types/requests.rb +50 -0
- data/spec/requests/browse_node_lookup_spec.rb +41 -0
- data/spec/requests/item_search_spec.rb +27 -0
- data/spec/spec_helper.rb +8 -0
- data/spec/types/cart_spec.rb +294 -0
- data/spec/types/item_spec.rb +55 -0
- data/spec/types/measurement_spec.rb +43 -0
- data/test/amazon/browse_node_test.rb +34 -0
- data/test/amazon/cache_test.rb +33 -0
- data/test/amazon/caching/filesystem_cache_test.rb +198 -0
- data/test/amazon/item_test.rb +397 -0
- data/test/test_helper.rb +9 -0
- data/test/utilities/filesystem_test_helper.rb +35 -0
- 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?('&'), 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
|