kosher 0.0.3 → 0.1.0

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.
@@ -0,0 +1,38 @@
1
+ require "spec_helper"
2
+
3
+ module Kosher
4
+ describe Algorithm do
5
+ use_vcr_cassette 'batch-request'
6
+
7
+ let(:asins) do
8
+
9
+ # The last ASIN does not exist.
10
+ %w{
11
+ 0816614024 0143105825 0485113600 0816616779 0942299078
12
+ 0816614008 144006654X 0486400360 0486417670 087220474X
13
+ 0486454398 0268018359 1604246014 184467598X 0312427182
14
+ 1844674282 0745640974 0745646441 0826489540 2081232191 }
15
+ end
16
+
17
+ let(:algorithm) do
18
+ request = Request.new(credentials)
19
+ request.locale = :us
20
+ request.batchify(asins)
21
+ request.get
22
+ end
23
+
24
+ describe "#items" do
25
+ it "should return found items" do
26
+ algorithm.items.count.should eql 19
27
+ algorithm.items.first.should be_a Item
28
+ end
29
+ end
30
+
31
+ describe "#errors" do
32
+ it "should return ASINs that are not found" do
33
+ algorithm.errors.count.should eql 1
34
+ algorithm.errors.first.should eql '2081232191'
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,31 @@
1
+ require "spec_helper"
2
+
3
+ module Kosher
4
+ describe Condition do
5
+ describe "#to_i" do
6
+ def this(str)
7
+ Condition.new(str).to_i
8
+ end
9
+
10
+ it "casts as integer" do
11
+ this("new").should eql 1
12
+ this("mint").should eql 2
13
+ this("verygood").should eql 3
14
+ this("good").should eql 4
15
+ this("acceptable").should eql 5
16
+ end
17
+
18
+ it "casts unrecognized conditions as 6" do
19
+ this("refurbished").should eql 6
20
+ end
21
+ end
22
+
23
+ describe "#kosher?" do
24
+ it "returns true if condition is good or better" do
25
+ Condition.new("verygood").should be_kosher
26
+ Condition.new("good").should be_kosher
27
+ Condition.new("acceptable").should_not be_kosher
28
+ end
29
+ end
30
+ end
31
+ end
@@ -1,9 +1,13 @@
1
1
  require "spec_helper"
2
2
 
3
3
  module Kosher
4
- describe String do
5
- def this(val)
6
- Kosher::String.new(val)
4
+ describe Description do
5
+ def this(value)
6
+ Description.new(value)
7
+ end
8
+
9
+ it "inherits from String" do
10
+ Description.ancestors.should include String
7
11
  end
8
12
 
9
13
  it "validates a blank description" do
@@ -14,7 +18,7 @@ module Kosher
14
18
  this("foo").should be_kosher
15
19
  end
16
20
 
17
- it "does not validate advance reviews" do
21
+ it "does not validate advance review copies" do
18
22
  this("Uncorrected review copy").should_not be_kosher
19
23
  this("arc").should_not be_kosher
20
24
  this("arc.").should_not be_kosher
@@ -0,0 +1,35 @@
1
+ require 'spec_helper'
2
+
3
+ module Kosher
4
+ describe Item do
5
+ describe ".build" do
6
+ use_vcr_cassette '0143105825', :match_requests_on => [:host]
7
+
8
+ let(:asin) { '0143105825' }
9
+
10
+ let(:response) do
11
+ request = Request.new(credentials)
12
+ request.locale = :us
13
+ request.batchify([asin])
14
+ algorithm = request.get
15
+
16
+ algorithm.instance_variable_get(:@response)
17
+ end
18
+
19
+ let(:item) do
20
+ doc = response.find('Item').first
21
+ Item.build(doc)
22
+ end
23
+
24
+ it "should build an item" do
25
+ item.should be_a Item
26
+ item.asin.should eql asin
27
+ end
28
+
29
+ it "should build the offers of an item" do
30
+ item.offers.count.should > 0
31
+ item.offers.first.should be_a Offer
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,123 @@
1
+ require 'spec_helper'
2
+
3
+ module Kosher
4
+ describe Offer do
5
+ let(:offer) { Fabricate(:offer) }
6
+
7
+ describe ".build" do
8
+ use_vcr_cassette '0143105825', :match_requests_on => [:host]
9
+
10
+ let(:asin) { '0143105825' }
11
+
12
+ let(:doc) do
13
+ request = Request.new(credentials)
14
+ request.locale = :us
15
+ request.batchify([asin])
16
+ algorithm = request.get
17
+
18
+ response = algorithm.instance_variable_get(:@response)
19
+ response.find('Offer').first
20
+ end
21
+
22
+ it "should build an offer" do
23
+ offer = Offer.build(doc)
24
+
25
+ offer.should be_a Offer
26
+ expect do
27
+ offer.kosher?
28
+ end.should_not raise_error
29
+ end
30
+
31
+ it "should handle blank descriptions" do
32
+ doc['OfferAttributes']['ConditionNote'] = ''
33
+ offer = Offer.build(doc)
34
+
35
+ offer.description.should eql ''
36
+ end
37
+ end
38
+
39
+ describe "#kosher?" do
40
+ context "when condition is kosher" do
41
+ before do
42
+ offer.condition = Fabricate(:kosher_condition, :in_words => 'new')
43
+ end
44
+
45
+ context "when seller is kosher" do
46
+ before do
47
+ offer.seller = Fabricate(:good_seller)
48
+ end
49
+
50
+ context "when description is kosher" do
51
+ context "when offer ships now" do
52
+ it "returns true" do
53
+ offer.should be_kosher
54
+ end
55
+ end
56
+
57
+ context "when offer does not ship now" do
58
+ before do
59
+ offer.ships_in = 96
60
+ end
61
+
62
+ it "returns false" do
63
+ offer.should_not be_kosher
64
+ end
65
+ end
66
+ end
67
+
68
+ context "when description is not kosher" do
69
+ before do
70
+ offer.description = Kosher::Description.new("Withdrawn library book")
71
+ end
72
+
73
+ it "returns false" do
74
+ offer.should_not be_kosher
75
+ end
76
+ end
77
+ end
78
+
79
+ context "when seller is not kosher" do
80
+ before do
81
+ offer.seller = Fabricate(:bad_seller)
82
+ end
83
+
84
+ it "returns false" do
85
+ offer.should_not be_kosher
86
+ end
87
+ end
88
+ end
89
+
90
+ context "when condition is not kosher" do
91
+ before do
92
+ offer.condition = Fabricate(:kosher_condition, :in_words => "acceptable")
93
+ end
94
+
95
+ it "returns false" do
96
+ offer.should_not be_kosher
97
+ end
98
+ end
99
+ end
100
+
101
+ describe "#ships_now?" do
102
+ context "when offer ships within 48 hours" do
103
+ before do
104
+ offer.ships_in = 48
105
+ end
106
+
107
+ it "returns true" do
108
+ offer.send(:ships_now?).should be_true
109
+ end
110
+ end
111
+
112
+ context "when offer ships in over 48 hours" do
113
+ before do
114
+ offer.ships_in = 96
115
+ end
116
+
117
+ it "returns false" do
118
+ offer.send(:ships_now?).should be_false
119
+ end
120
+ end
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,42 @@
1
+ require 'spec_helper'
2
+
3
+ module Kosher
4
+ describe Request do
5
+ let(:request) { Request.new(credentials) }
6
+
7
+ describe ".new" do
8
+ it "should define a batch request" do
9
+ request.parameters['Operation'].should eql 'ItemLookup'
10
+ request.parameters['ItemLookup.Shared.IdType'].should eql 'ASIN'
11
+ request.parameters['ItemLookup.Shared.Condition'].should eql 'All'
12
+ request.parameters['ItemLookup.Shared.MerchantId'].should eql 'All'
13
+ request.parameters['ItemLookup.Shared.ResponseGroup'].should eql ['OfferFull', 'SalesRank']
14
+ end
15
+ end
16
+
17
+ describe "#batchify" do
18
+ it "should add up to 20 ASINs to the worker's parameters" do
19
+ asins = (0..19).to_a
20
+ request.batchify(asins)
21
+
22
+ request.parameters['ItemLookup.1.ItemId'].should eql (0..9).to_a
23
+ request.parameters['ItemLookup.2.ItemId'].should eql (10..19).to_a
24
+ end
25
+ end
26
+
27
+ describe "#request" do
28
+ before do
29
+ VCR.http_stubbing_adapter.http_connections_allowed = true
30
+ end
31
+
32
+ it "should return an algorithm" do
33
+ Kosher::Request.stub!(:get)
34
+
35
+ request.locale = :us
36
+ request.batchify('foo')
37
+
38
+ request.get.should be_a Algorithm
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,65 @@
1
+ require "spec_helper"
2
+
3
+ module Kosher
4
+ describe Seller do
5
+ describe ".build" do
6
+ use_vcr_cassette "0143105825", :match_requests_on => [:host]
7
+
8
+ let(:asin) { '0143105825' }
9
+
10
+ let(:response) do
11
+ request = Request.new(credentials)
12
+ request.locale = :us
13
+ request.batchify([asin])
14
+ algorithm = request.get
15
+
16
+ algorithm.instance_variable_get(:@response)
17
+ end
18
+
19
+ let(:sellers) do
20
+ response.find("Merchant")
21
+ end
22
+
23
+ it "builds a seller" do
24
+ seller = Seller.build(sellers.first)
25
+
26
+ seller.merchant_id.should match /^[0-9A-Z]{13,14}$/
27
+ seller.average_rating.should be_an_instance_of Float
28
+ end
29
+
30
+ it "builds a newly-launched seller" do
31
+ doc = sellers.detect { |doc| doc["AverageFeedbackRating"] == "0.0" }
32
+ new_seller = Seller.build(doc)
33
+
34
+ new_seller.average_rating.should eql 0.0
35
+ end
36
+ end
37
+
38
+ describe "#kosher?" do
39
+ it "returns true if seller's average rating is 0.0" do
40
+ seller = Fabricate(:new_seller)
41
+ seller.should be_kosher
42
+ end
43
+
44
+ it "returns true if seller's average rating is above 4.7" do
45
+ seller = Fabricate(:good_seller)
46
+ seller.should be_kosher
47
+ end
48
+
49
+ it "returns false if sellers' average rating is 4.7 or below" do
50
+ seller = Fabricate(:bad_seller)
51
+ seller.should_not be_kosher
52
+ end
53
+
54
+ it "returns false if seller is blacklisted" do
55
+ seller = Fabricate(:good_seller)
56
+ seller.should be_kosher
57
+
58
+ seller.merchant_id = Faker::Amazon.merchant_id
59
+ Seller.blacklist = [seller.merchant_id]
60
+
61
+ seller.should_not be_kosher
62
+ end
63
+ end
64
+ end
65
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,7 +1,8 @@
1
- require "rubygems"
2
- require "bundler/setup"
3
- require "rspec"
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ require 'rspec'
4
+ require 'fabrication'
4
5
 
5
- require File.expand_path("../../lib/kosher", __FILE__)
6
+ require File.expand_path('../../lib/kosher', __FILE__)
6
7
 
7
8
  Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
@@ -0,0 +1,3 @@
1
+ def credentials
2
+ @credentials ||= YAML::load_file(File.dirname(__FILE__) + "/credentials.yml")
3
+ end
@@ -0,0 +1,19 @@
1
+ module Faker
2
+ module Amazon
3
+ class << self
4
+ def asin
5
+ raw = 9.times.map { rand(10).to_s }
6
+ (raw << Bookland::ISBN.new.send(:check_digit_10, raw)).join
7
+ end
8
+
9
+ def ean
10
+ Bookland::ISBN.to_13(asin)
11
+ end
12
+
13
+ def merchant_id
14
+ seed = ('A'..'Z').to_a + (0..9).to_a
15
+ 14.times.map { seed[rand(seed.size)] }.join
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,12 @@
1
+ require 'vcr'
2
+
3
+ VCR.config do |c|
4
+ c.cassette_library_dir = "#{File.dirname(__FILE__)}/../fixtures/cassette_library"
5
+ c.stub_with :webmock
6
+ c.ignore_localhost = true
7
+ c.default_cassette_options = { :record => :new_episodes }
8
+ end
9
+
10
+ RSpec.configure do |config|
11
+ config.extend VCR::RSpec::Macros
12
+ end
metadata CHANGED
@@ -1,12 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kosher
3
3
  version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 0
7
- - 0
8
- - 3
9
- version: 0.0.3
4
+ prerelease:
5
+ version: 0.1.0
10
6
  platform: ruby
11
7
  authors:
12
8
  - Paper Cavalier
@@ -14,27 +10,88 @@ autorequire:
14
10
  bindir: bin
15
11
  cert_chain: []
16
12
 
17
- date: 2011-01-06 00:00:00 +00:00
13
+ date: 2011-03-03 00:00:00 +00:00
18
14
  default_executable:
19
15
  dependencies:
20
16
  - !ruby/object:Gem::Dependency
21
- name: rspec
17
+ name: sucker
22
18
  prerelease: false
23
19
  requirement: &id001 !ruby/object:Gem::Requirement
24
20
  none: false
25
21
  requirements:
26
22
  - - ~>
27
23
  - !ruby/object:Gem::Version
28
- segments:
29
- - 2
30
- - 4
31
- - 0
32
- version: 2.4.0
33
- type: :development
24
+ version: 1.3.1
25
+ type: :runtime
34
26
  version_requirements: *id001
35
- description: Have you ever wondered if you should buy a book?
36
- email:
37
- - code@papercvalier.com
27
+ - !ruby/object:Gem::Dependency
28
+ name: throttler
29
+ prerelease: false
30
+ requirement: &id002 !ruby/object:Gem::Requirement
31
+ none: false
32
+ requirements:
33
+ - - ~>
34
+ - !ruby/object:Gem::Version
35
+ version: 0.2.4
36
+ type: :runtime
37
+ version_requirements: *id002
38
+ - !ruby/object:Gem::Dependency
39
+ name: fabrication
40
+ prerelease: false
41
+ requirement: &id003 !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ~>
45
+ - !ruby/object:Gem::Version
46
+ version: 0.9.5
47
+ type: :development
48
+ version_requirements: *id003
49
+ - !ruby/object:Gem::Dependency
50
+ name: rspec
51
+ prerelease: false
52
+ requirement: &id004 !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ~>
56
+ - !ruby/object:Gem::Version
57
+ version: 2.5.0
58
+ type: :development
59
+ version_requirements: *id004
60
+ - !ruby/object:Gem::Dependency
61
+ name: ruby-debug19
62
+ prerelease: false
63
+ requirement: &id005 !ruby/object:Gem::Requirement
64
+ none: false
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: 0.11.6
69
+ type: :development
70
+ version_requirements: *id005
71
+ - !ruby/object:Gem::Dependency
72
+ name: vcr
73
+ prerelease: false
74
+ requirement: &id006 !ruby/object:Gem::Requirement
75
+ none: false
76
+ requirements:
77
+ - - ~>
78
+ - !ruby/object:Gem::Version
79
+ version: 1.7.0
80
+ type: :development
81
+ version_requirements: *id006
82
+ - !ruby/object:Gem::Dependency
83
+ name: webmock
84
+ prerelease: false
85
+ requirement: &id007 !ruby/object:Gem::Requirement
86
+ none: false
87
+ requirements:
88
+ - - ~>
89
+ - !ruby/object:Gem::Version
90
+ version: 1.6.2
91
+ type: :development
92
+ version_requirements: *id007
93
+ description: Kosher wraps Amazon in a loving embrace.
94
+ email: code@papercavalier.com
38
95
  executables: []
39
96
 
40
97
  extensions: []
@@ -43,23 +100,39 @@ extra_rdoc_files: []
43
100
 
44
101
  files:
45
102
  - .gitignore
46
- - .rspec
47
- - .rvmrc
48
103
  - Gemfile
49
104
  - LICENSE
50
105
  - README.md
51
106
  - Rakefile
52
107
  - kosher.gemspec
53
108
  - lib/kosher.rb
54
- - lib/kosher/regexps.rb
55
- - lib/kosher/string.rb
109
+ - lib/kosher/algorithm.rb
110
+ - lib/kosher/condition.rb
111
+ - lib/kosher/description.rb
112
+ - lib/kosher/item.rb
113
+ - lib/kosher/offer.rb
114
+ - lib/kosher/request.rb
115
+ - lib/kosher/seller.rb
56
116
  - lib/kosher/version.rb
57
- - spec/kosher/string_spec.rb
58
- - spec/kosher_spec.rb
117
+ - spec/fabricators/condition_fabricator.rb
118
+ - spec/fabricators/offer_fabricator.rb
119
+ - spec/fabricators/seller_fabricator.rb
120
+ - spec/fixtures/cassette_library/0143105825.yml
121
+ - spec/fixtures/cassette_library/batch-request.yml
122
+ - spec/kosher/algorithm_spec.rb
123
+ - spec/kosher/condition_spec.rb
124
+ - spec/kosher/description_spec.rb
125
+ - spec/kosher/item_spec.rb
126
+ - spec/kosher/offer_spec.rb
127
+ - spec/kosher/request_spec.rb
128
+ - spec/kosher/seller_spec.rb
59
129
  - spec/spec_helper.rb
130
+ - spec/support/credentials.rb
131
+ - spec/support/faker.rb
132
+ - spec/support/vcr.rb
60
133
  - walter_benjamin.jpg
61
134
  has_rdoc: true
62
- homepage: ""
135
+ homepage: https://rubygems.org/gems/kosher
63
136
  licenses: []
64
137
 
65
138
  post_install_message:
@@ -72,25 +145,34 @@ required_ruby_version: !ruby/object:Gem::Requirement
72
145
  requirements:
73
146
  - - ">="
74
147
  - !ruby/object:Gem::Version
75
- segments:
76
- - 0
77
148
  version: "0"
78
149
  required_rubygems_version: !ruby/object:Gem::Requirement
79
150
  none: false
80
151
  requirements:
81
152
  - - ">="
82
153
  - !ruby/object:Gem::Version
83
- segments:
84
- - 0
85
154
  version: "0"
86
155
  requirements: []
87
156
 
88
157
  rubyforge_project: kosher
89
- rubygems_version: 1.3.7
158
+ rubygems_version: 1.5.2
90
159
  signing_key:
91
160
  specification_version: 3
92
- summary: Kosher validates descriptions
161
+ summary: Wraps Amazon in a loving embrace.
93
162
  test_files:
94
- - spec/kosher/string_spec.rb
95
- - spec/kosher_spec.rb
163
+ - spec/fabricators/condition_fabricator.rb
164
+ - spec/fabricators/offer_fabricator.rb
165
+ - spec/fabricators/seller_fabricator.rb
166
+ - spec/fixtures/cassette_library/0143105825.yml
167
+ - spec/fixtures/cassette_library/batch-request.yml
168
+ - spec/kosher/algorithm_spec.rb
169
+ - spec/kosher/condition_spec.rb
170
+ - spec/kosher/description_spec.rb
171
+ - spec/kosher/item_spec.rb
172
+ - spec/kosher/offer_spec.rb
173
+ - spec/kosher/request_spec.rb
174
+ - spec/kosher/seller_spec.rb
96
175
  - spec/spec_helper.rb
176
+ - spec/support/credentials.rb
177
+ - spec/support/faker.rb
178
+ - spec/support/vcr.rb
data/.rspec DELETED
@@ -1,2 +0,0 @@
1
- --color
2
- --format documentation
data/.rvmrc DELETED
@@ -1 +0,0 @@
1
- rvm --create use 1.9.2@kosher
@@ -1,7 +0,0 @@
1
- module Kosher
2
- DAMAGED = "\\b(?:missing|torn|broken|split|discard|withdrawn|rent|stain|school|damaged|water)"
3
- EXLIBRARY = "(?:e?x|discarded|retired|former|has|have)[\\s._-]*lib"
4
- MARKED = "(highlight|hilit|underlin)"
5
- MISSING_VOL = "(vols?|volume) only"
6
- REVIEW_COPY = "\\b(?:uncorrected|advanced?\\sreview|arc)\\b"
7
- end
data/lib/kosher/string.rb DELETED
@@ -1,50 +0,0 @@
1
- module Kosher
2
- class String < String
3
- def kosher?
4
- !(present? && (
5
- damaged? ||
6
- ex_library? ||
7
- marked? ||
8
- missing_volume? ||
9
- review_copy?))
10
- end
11
-
12
- private
13
-
14
- def expect(str)
15
- !!match(Regexp.new(str, true))
16
- end
17
-
18
- def do_not_expect(str)
19
- !match(Regexp.new(str, true))
20
- end
21
-
22
- def damaged?
23
- expect(DAMAGED)
24
- end
25
-
26
- def ex_library?
27
- expect(EXLIBRARY) && do_not_expect(negation_of(EXLIBRARY))
28
- end
29
-
30
- def marked?
31
- expect(MARKED) && do_not_expect(negation_of(MARKED))
32
- end
33
-
34
- def missing_volume?
35
- expect(MISSING_VOL)
36
- end
37
-
38
- def negation_of(str)
39
- "(?:no|not an?)\\s+#{str}"
40
- end
41
-
42
- def present?
43
- self != ''
44
- end
45
-
46
- def review_copy?
47
- expect(REVIEW_COPY)
48
- end
49
- end
50
- end
data/spec/kosher_spec.rb DELETED
@@ -1,9 +0,0 @@
1
- require "spec_helper"
2
-
3
- describe Kosher do
4
- describe(".new") do
5
- it "returns an instance of Kosher::String" do
6
- Kosher.new("foo").should be_a_kind_of Kosher::String
7
- end
8
- end
9
- end