fassbinder 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/fassbinder.gemspec CHANGED
@@ -19,9 +19,8 @@ Gem::Specification.new do |s|
19
19
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
20
  s.require_paths = ['lib']
21
21
 
22
- s.add_dependency('kosher', '~> 0.2.4')
22
+ s.add_dependency('kosher', '~> 0.2.7')
23
23
  s.add_dependency('sucker', '~> 1.3.1')
24
- s.add_development_dependency('fabrication', '~> 0.9.5')
25
24
  s.add_development_dependency('rspec', '~> 2.5.0')
26
25
  s.add_development_dependency('ruby-debug19', '~> 0.11.6')
27
26
  s.add_development_dependency('vcr', '~> 1.7.0')
data/lib/fassbinder.rb CHANGED
@@ -1,7 +1,7 @@
1
+ require 'kosher'
1
2
  require 'sucker'
2
3
 
3
- require 'fassbinder/algorithm'
4
4
  require 'fassbinder/errors'
5
5
  require 'fassbinder/item'
6
- require 'fassbinder/offer'
7
6
  require 'fassbinder/request'
7
+ require 'fassbinder/response_wrapper'
@@ -0,0 +1,4 @@
1
+ module Fassbinder
2
+ class Item < Struct.new(:asin, :count, :rank, :offers)
3
+ end
4
+ end
@@ -16,7 +16,7 @@ module Fassbinder
16
16
  end
17
17
 
18
18
  def get
19
- Algorithm.new(super)
19
+ ResponseWrapper.new(super, locale)
20
20
  end
21
21
  end
22
22
  end
@@ -0,0 +1,68 @@
1
+ module Fassbinder
2
+ class ResponseWrapper
3
+ def initialize(response, locale)
4
+ raise InvalidResponseError unless response.valid?
5
+
6
+ @response = response
7
+ @locale = locale
8
+ end
9
+
10
+ # And I don't believe that melodramatic feelings are laughable -
11
+ # they should be taken absolutely seriously.
12
+ def items
13
+ @response.map('Item') do |doc|
14
+ Item.new(
15
+ doc['ASIN'],
16
+ doc['Offers']['TotalOffers'].to_i,
17
+ doc['SalesRank'].to_i,
18
+ [doc['Offers']['Offer']].flatten.compact.map do |doc|
19
+ if doc['OfferListing']['Price']['CurrencyCode'] == 'JPY'
20
+ doc['OfferListing']['Price']['Amount'] = doc['OfferListing']['Price']['Amount'].to_i * 100
21
+ end
22
+
23
+ Kosher::Offer.new(
24
+ doc['OfferListing']['OfferListingId'],
25
+ Kosher::Item.new(doc['OfferListing']['Price']['Amount'].to_i,
26
+ doc['OfferListing']['Price']['CurrencyCode'],
27
+ doc['OfferListing']['Quantity'].to_i,
28
+ Kosher::Condition.new(case doc['OfferAttributes']['SubCondition']
29
+ when 'new' then 1
30
+ when 'mint' then 2
31
+ when 'verygood' then 3
32
+ when 'good' then 4
33
+ when 'acceptable' then 5
34
+ else 6
35
+ end),
36
+ Kosher::Description.new(doc['OfferAttributes']['ConditionNote'].to_s)),
37
+ Kosher::Seller.new(doc['Merchant']['MerchantId'],
38
+ doc['Merchant']['Name'],
39
+ doc['Merchant']['AverageFeedbackRating'].to_f,
40
+ Kosher::Location.new((doc['Merchant']['Location']['CountryCode'] rescue nil), (doc['Merchant']['Location']['StateCode'] rescue nil))),
41
+ Kosher::Shipping.new(doc['OfferListing']['IsEligibleForSuperSaverShipping'] == '1' ?
42
+ 0 : (case @locale
43
+ when :us then 399
44
+ when :uk then 280
45
+ when :de then 299
46
+ when :ca then 649
47
+ when :fr then 300
48
+ when :jp then 25000
49
+ end),
50
+ doc['OfferListing']['Price']['CurrencyCode'],
51
+ Kosher::Availability.new(doc['OfferListing']['AvailabilityAttributes']['MaximumHours'].to_i))
52
+ )
53
+ end
54
+ )
55
+ end
56
+ end
57
+
58
+ def errors
59
+ @response.errors.map do |error|
60
+ error['Message'].scan(/[0-9A-Z]{10}/).first rescue nil
61
+ end.compact
62
+ end
63
+
64
+ def response
65
+ @response
66
+ end
67
+ end
68
+ end
@@ -1,3 +1,3 @@
1
1
  module Fassbinder
2
- VERSION = '0.0.1'
2
+ VERSION = '0.0.2'
3
3
  end
@@ -35,7 +35,7 @@ module Fassbinder
35
35
  request.locale = :us
36
36
  request.batchify('foo')
37
37
 
38
- request.get.should be_a Algorithm
38
+ request.get.should be_a ResponseWrapper
39
39
  end
40
40
  end
41
41
  end
@@ -0,0 +1,49 @@
1
+ require 'spec_helper'
2
+
3
+ module Fassbinder
4
+ describe ResponseWrapper do
5
+ describe ".new" do
6
+ it "raises an error if response is not valid" do
7
+ response = mock('Response')
8
+ response.stub!(:valid?).and_return(false)
9
+
10
+ expect do
11
+ ResponseWrapper.new(response, :us)
12
+ end.to raise_error InvalidResponseError
13
+ end
14
+ end
15
+
16
+ describe "#books" do
17
+ use_vcr_cassette 'batch-request'
18
+
19
+ let(:asins) do
20
+ # The last ASIN does not exist.
21
+ %w{
22
+ 0816614024 0143105825 0485113600 0816616779 0942299078
23
+ 0816614008 144006654X 0486400360 0486417670 087220474X
24
+ 0486454398 0268018359 1604246014 184467598X 0312427182
25
+ 1844674282 0745640974 0745646441 0826489540 2081232191 }
26
+ end
27
+
28
+ let(:response_wrapper) do
29
+ request = Request.new(credentials)
30
+ request.locale = :us
31
+ request.batchify(asins)
32
+ request.get
33
+ end
34
+
35
+ it "should return found books" do
36
+ debugger
37
+ response_wrapper.items.count.should eql 19
38
+ response_wrapper.items.first.should be_a Book
39
+ end
40
+ end
41
+
42
+ describe "#errors" do
43
+ it "should return ASINs that are not found" do
44
+ algorithm.errors.count.should eql 1
45
+ algorithm.errors.first.should eql '2081232191'
46
+ end
47
+ end
48
+ end
49
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,7 +1,6 @@
1
1
  require 'rubygems'
2
2
  require 'bundler/setup'
3
3
  require 'rspec'
4
- require 'fabrication'
5
4
 
6
5
  require File.expand_path('../../lib/fassbinder', __FILE__)
7
6
 
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: fassbinder
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.0.1
5
+ version: 0.0.2
6
6
  platform: ruby
7
7
  authors:
8
8
  - Paper Cavalier
@@ -21,7 +21,7 @@ dependencies:
21
21
  requirements:
22
22
  - - ~>
23
23
  - !ruby/object:Gem::Version
24
- version: 0.2.4
24
+ version: 0.2.7
25
25
  type: :runtime
26
26
  version_requirements: *id001
27
27
  - !ruby/object:Gem::Dependency
@@ -35,61 +35,50 @@ dependencies:
35
35
  version: 1.3.1
36
36
  type: :runtime
37
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
38
  - !ruby/object:Gem::Dependency
50
39
  name: rspec
51
40
  prerelease: false
52
- requirement: &id004 !ruby/object:Gem::Requirement
41
+ requirement: &id003 !ruby/object:Gem::Requirement
53
42
  none: false
54
43
  requirements:
55
44
  - - ~>
56
45
  - !ruby/object:Gem::Version
57
46
  version: 2.5.0
58
47
  type: :development
59
- version_requirements: *id004
48
+ version_requirements: *id003
60
49
  - !ruby/object:Gem::Dependency
61
50
  name: ruby-debug19
62
51
  prerelease: false
63
- requirement: &id005 !ruby/object:Gem::Requirement
52
+ requirement: &id004 !ruby/object:Gem::Requirement
64
53
  none: false
65
54
  requirements:
66
55
  - - ~>
67
56
  - !ruby/object:Gem::Version
68
57
  version: 0.11.6
69
58
  type: :development
70
- version_requirements: *id005
59
+ version_requirements: *id004
71
60
  - !ruby/object:Gem::Dependency
72
61
  name: vcr
73
62
  prerelease: false
74
- requirement: &id006 !ruby/object:Gem::Requirement
63
+ requirement: &id005 !ruby/object:Gem::Requirement
75
64
  none: false
76
65
  requirements:
77
66
  - - ~>
78
67
  - !ruby/object:Gem::Version
79
68
  version: 1.7.0
80
69
  type: :development
81
- version_requirements: *id006
70
+ version_requirements: *id005
82
71
  - !ruby/object:Gem::Dependency
83
72
  name: webmock
84
73
  prerelease: false
85
- requirement: &id007 !ruby/object:Gem::Requirement
74
+ requirement: &id006 !ruby/object:Gem::Requirement
86
75
  none: false
87
76
  requirements:
88
77
  - - ~>
89
78
  - !ruby/object:Gem::Version
90
79
  version: 1.6.2
91
80
  type: :development
92
- version_requirements: *id007
81
+ version_requirements: *id006
93
82
  description: Fassbinder wraps Amazon in a loving embrace.
94
83
  email: code@papercavalier.com
95
84
  executables: []
@@ -106,30 +95,15 @@ files:
106
95
  - Rakefile
107
96
  - fassbinder.gemspec
108
97
  - lib/fassbinder.rb
109
- - lib/fassbinder/algorithm.rb
110
- - lib/fassbinder/book.rb
111
- - lib/fassbinder/condition.rb
112
- - lib/fassbinder/description.rb
113
98
  - lib/fassbinder/errors.rb
114
- - lib/fassbinder/offer.rb
99
+ - lib/fassbinder/item.rb
115
100
  - lib/fassbinder/request.rb
116
- - lib/fassbinder/seller.rb
117
- - lib/fassbinder/struct.rb
101
+ - lib/fassbinder/response_wrapper.rb
118
102
  - lib/fassbinder/version.rb
119
- - spec/fabricators/condition_fabricator.rb
120
- - spec/fabricators/offer_fabricator.rb
121
- - spec/fabricators/seller_fabricator.rb
122
- - spec/fassbinder/algorithm_spec.rb
123
- - spec/fassbinder/book_spec.rb
124
- - spec/fassbinder/condition_spec.rb
125
- - spec/fassbinder/description_spec.rb
126
- - spec/fassbinder/offer_spec.rb
127
103
  - spec/fassbinder/request_spec.rb
128
- - spec/fassbinder/seller_spec.rb
129
- - spec/fassbinder/struct_spec.rb
104
+ - spec/fassbinder/response_wrapper_spec.rb
130
105
  - spec/spec_helper.rb
131
106
  - spec/support/credentials.rb
132
- - spec/support/faker.rb
133
107
  - spec/support/vcr.rb
134
108
  has_rdoc: true
135
109
  homepage: https://rubygems.org/gems/fassbinder
@@ -160,18 +134,8 @@ signing_key:
160
134
  specification_version: 3
161
135
  summary: Wraps Amazon in a loving embrace.
162
136
  test_files:
163
- - spec/fabricators/condition_fabricator.rb
164
- - spec/fabricators/offer_fabricator.rb
165
- - spec/fabricators/seller_fabricator.rb
166
- - spec/fassbinder/algorithm_spec.rb
167
- - spec/fassbinder/book_spec.rb
168
- - spec/fassbinder/condition_spec.rb
169
- - spec/fassbinder/description_spec.rb
170
- - spec/fassbinder/offer_spec.rb
171
137
  - spec/fassbinder/request_spec.rb
172
- - spec/fassbinder/seller_spec.rb
173
- - spec/fassbinder/struct_spec.rb
138
+ - spec/fassbinder/response_wrapper_spec.rb
174
139
  - spec/spec_helper.rb
175
140
  - spec/support/credentials.rb
176
- - spec/support/faker.rb
177
141
  - spec/support/vcr.rb
@@ -1,25 +0,0 @@
1
- module Fassbinder
2
- class Algorithm
3
- def initialize(response)
4
- raise InvalidResponseError unless response.valid?
5
-
6
- @response = response
7
- end
8
-
9
- def books
10
- @response.map('Item') do |item|
11
- Book.build(item)
12
- end
13
- end
14
-
15
- def errors
16
- @response.errors.map do |error|
17
- error['Message'].scan(/[0-9A-Z]{10}/).first rescue nil
18
- end.compact
19
- end
20
-
21
- def response
22
- @response
23
- end
24
- end
25
- end
@@ -1,29 +0,0 @@
1
- module Kosher
2
- class Book < Struct.new(:asin, :offers, :offers_count, :sales_rank)
3
-
4
- class << self
5
- def build(doc)
6
- asin = doc['ASIN']
7
- sales_rank = doc['SalesRank'].to_i
8
- offers_count = doc['Offers']['TotalOffers'].to_i
9
- offers = build_offers(doc['Offers']['Offer'])
10
-
11
- new(asin, offers, offers_count, sales_rank)
12
- end
13
-
14
- private
15
-
16
- def build_offers(offers)
17
- [offers].flatten.compact.map do |offer|
18
-
19
- # Senify Yen because Ruby Money says so
20
- if offer['OfferListing']['Price']['CurrencyCode'] == 'JPY'
21
- offer['OfferListing']['Price']['Amount'] = offer['OfferListing']['Price']['Amount'].to_i * 100
22
- end
23
-
24
- Offer.build(offer)
25
- end
26
- end
27
- end
28
- end
29
- end
@@ -1,29 +0,0 @@
1
- module Kosher
2
- class Condition < Struct.new(:grade)
3
-
4
- alias_method :to_i, :grade
5
-
6
- CONDITIONS = {
7
- 'new' => 1,
8
- 'mint' => 2,
9
- 'verygood' => 3,
10
- 'good' => 4,
11
- 'acceptable' => 5 }
12
-
13
- def initialize(string = '')
14
- self.grade = CONDITIONS[string] || 6
15
- end
16
-
17
- def kosher?
18
- grade <= 4
19
- end
20
-
21
- def new?
22
- grade == 1
23
- end
24
-
25
- def used?
26
- !new?
27
- end
28
- end
29
- end
@@ -1,59 +0,0 @@
1
- module Kosher
2
- class Description < String
3
- DAMAGED = "\\b(?:missing|torn|broken|split|discard|withdrawn|rent|stain|school|damaged|water)"
4
- EXLIB = "(?:e?x|discarded|retired|former|has|have)[\\s._-]*lib"
5
- MARKED = "(highlight|hilit|underlin)"
6
- MISSING_VOL = "(vols?|volume) only"
7
- REVIEW_COPY = "\\b(?:uncorrected|advanced?\\sreview|arc)\\b"
8
-
9
- def kosher?
10
- !(present? && bad?)
11
- end
12
-
13
- private
14
-
15
- def bad?
16
- damaged? ||
17
- ex_library? ||
18
- marked? ||
19
- missing_volume? ||
20
- review_copy?
21
- end
22
-
23
- def damaged?
24
- matches(DAMAGED)
25
- end
26
-
27
- def does_not_match(value)
28
- !match(Regexp.new(value, true))
29
- end
30
-
31
- def ex_library?
32
- matches(EXLIB) && does_not_match(negation_of(EXLIB))
33
- end
34
-
35
- def marked?
36
- matches(MARKED) && does_not_match(negation_of(MARKED))
37
- end
38
-
39
- def matches(value)
40
- !does_not_match(value)
41
- end
42
-
43
- def missing_volume?
44
- matches(MISSING_VOL)
45
- end
46
-
47
- def negation_of(value)
48
- "(?:no|not an?)\\s+#{value}"
49
- end
50
-
51
- def present?
52
- self != ''
53
- end
54
-
55
- def review_copy?
56
- matches(REVIEW_COPY)
57
- end
58
- end
59
- end
@@ -1,38 +0,0 @@
1
- module Kosher
2
- class Offer < Struct.new(
3
- :seller,
4
- :condition,
5
- :description,
6
- :ships_in,
7
- :ships_free,
8
- :cents,
9
- :exchange_id,
10
- :listing_id)
11
-
12
- def self.build(doc)
13
- offer = new
14
- offer.seller = Seller.build(doc['Merchant'])
15
-
16
- attributes = doc['OfferAttributes']
17
- offer.condition = Condition.new(attributes['SubCondition'])
18
- offer.description = Description.new(attributes['ConditionNote'].to_s)
19
-
20
- listing = doc['OfferListing']
21
- offer.ships_in = listing['AvailabilityAttributes']['MaximumHours'].to_i
22
- offer.ships_free = listing['IsEligibleForSuperSaverShipping'] == '1'
23
- offer.cents = listing['Price']['Amount'].to_i
24
- offer.exchange_id = listing['ExchangeId']
25
- offer.listing_id = listing['OfferListingId']
26
-
27
- offer
28
- end
29
-
30
- def kosher?
31
- condition.kosher? && seller.kosher? && description.kosher? && ships_now?
32
- end
33
-
34
- def ships_now?
35
- ships_in.to_i <= 48
36
- end
37
- end
38
- end
@@ -1,29 +0,0 @@
1
- module Kosher
2
- class Seller < Struct.new(:merchant_id, :name, :average_rating)
3
- class << self
4
- attr_accessor :blacklist
5
-
6
- def build(doc)
7
- merchant_id = doc['MerchantId']
8
- name = doc['Name']
9
- average_rating = doc['AverageFeedbackRating'].to_f
10
-
11
- new(merchant_id, name, average_rating)
12
- end
13
- end
14
-
15
- def blacklist
16
- self.class.blacklist
17
- end
18
-
19
- def blacklisted?
20
- blacklist.include?(merchant_id) rescue false
21
- end
22
-
23
- def kosher?
24
- return false if blacklisted?
25
-
26
- average_rating == 0.0 || average_rating > 4.7
27
- end
28
- end
29
- end
@@ -1,15 +0,0 @@
1
- require 'json'
2
-
3
- module Kosher
4
- class Struct < ::Struct
5
- def to_map
6
- map = Hash.new
7
- self.members.each { |m| map[m] = self[m] }
8
- map
9
- end
10
-
11
- def to_json(*a)
12
- to_map.to_json(*a)
13
- end
14
- end
15
- end
@@ -1,7 +0,0 @@
1
- Fabricator(:kosher_condition, :class_name => 'kosher/condition') do
2
- grade 1
3
- end
4
-
5
- Fabricator(:unkosher_condition, :class_name => 'kosher/condition') do
6
- grade 5
7
- end
@@ -1,8 +0,0 @@
1
- Fabricator(:offer, :class_name => 'kosher/offer') do
2
- seller { Fabricate(:good_seller) }
3
- description Kosher::Description.new('')
4
- condition { Fabricate(:kosher_condition) }
5
- ships_free false
6
- ships_in 48
7
- cents 100
8
- end
@@ -1,15 +0,0 @@
1
- Fabricator(:seller, :class_name => 'kosher/seller') do
2
- merchant_id Faker::Amazon.merchant_id
3
- end
4
-
5
- Fabricator(:new_seller, :from => :seller) do
6
- average_rating 0.0
7
- end
8
-
9
- Fabricator(:good_seller, :from => :seller) do
10
- average_rating 5.0
11
- end
12
-
13
- Fabricator(:bad_seller, :from => :seller) do
14
- average_rating 4.5
15
- end
@@ -1,49 +0,0 @@
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 ".new" do
25
- it "raises an error if response is not valid" do
26
- response = mock('Response')
27
- response.stub!(:valid?).and_return(false)
28
-
29
- expect do
30
- Algorithm.new(response)
31
- end.to raise_error InvalidResponseError
32
- end
33
- end
34
-
35
- describe "#books" do
36
- it "should return found books" do
37
- algorithm.items.count.should eql 19
38
- algorithm.items.first.should be_a Book
39
- end
40
- end
41
-
42
- describe "#errors" do
43
- it "should return ASINs that are not found" do
44
- algorithm.errors.count.should eql 1
45
- algorithm.errors.first.should eql '2081232191'
46
- end
47
- end
48
- end
49
- end
@@ -1,50 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module Kosher
4
- describe Item do
5
- it "should descend from Kosher::Struct" do
6
- Item.ancestors.should include Kosher::Struct
7
- end
8
-
9
- describe ".build" do
10
- use_vcr_cassette '0143105825'
11
-
12
- let(:asin) { '0143105825' }
13
-
14
- it "should build an item" do
15
- request = Request.new(credentials)
16
- request.locale = :us
17
- request.batchify([asin])
18
- algorithm = request.get
19
- response = algorithm.instance_variable_get(:@response)
20
- doc = response.find('Item').first
21
- item = Item.build(doc)
22
-
23
- item.should be_a Item
24
- item.asin.should eql asin
25
- item.offers_count.should be > 0
26
- item.sales_rank.should be > 0
27
- item.offers.count.should > 0
28
- item.offers.first.should be_a Offer
29
- end
30
-
31
- it "should senify Yen in Japanese requests" do
32
- request = Request.new(credentials)
33
- request.locale = :jp
34
- request.batchify([asin])
35
- algorithm = request.get
36
- response = algorithm.instance_variable_get(:@response)
37
- doc = response.find('Item').first
38
-
39
- doc['Offers']['Offer'].each do |offer|
40
- offer['OfferListing']['Price']['Amount'] = 1
41
- end
42
- item = Item.build(doc)
43
-
44
- item.offers.each do |offer|
45
- offer.cents.should eql 100
46
- end
47
- end
48
- end
49
- end
50
- end
@@ -1,31 +0,0 @@
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,55 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module Kosher
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
11
- end
12
-
13
- it "validates a blank description" do
14
- this('').should be_kosher
15
- end
16
-
17
- it "validates a non-blank description" do
18
- this('foo').should be_kosher
19
- end
20
-
21
- it "does not validate advance review copies" do
22
- this('Uncorrected review copy').should_not be_kosher
23
- this('arc').should_not be_kosher
24
- this('arc.').should_not be_kosher
25
-
26
- this('marc').should be_kosher
27
- end
28
-
29
- it "does not validate marked books" do
30
- this('Some highlighting').should_not be_kosher
31
- this('Underlining.').should_not be_kosher
32
- this('Good. Hiliting.').should_not be_kosher
33
-
34
- this('No highlighting.').should be_kosher
35
- end
36
-
37
- it "does not validate books with missing volumes" do
38
- this('First vol only.').should_not be_kosher
39
- end
40
-
41
- it "does not validate damaged or worn books" do
42
- this('Different').should be_kosher
43
- this('Rental').should_not be_kosher
44
- this('Torn pages').should_not be_kosher
45
- end
46
-
47
- it "does not validate withdrawn library copies" do
48
- this('xlib').should_not be_kosher
49
- this('ex-library').should_not be_kosher
50
- this('retired library copy').should_not be_kosher
51
-
52
- this('Not an ex-library').should be_kosher
53
- end
54
- end
55
- end
@@ -1,133 +0,0 @@
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'
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 "populates the offer listing ID" do
32
- offer = Offer.build(doc)
33
- offer.listing_id.should_not be_nil
34
- end
35
-
36
- it "populates the exchange ID" do
37
- offer = Offer.build(doc)
38
- offer.exchange_id.should_not be_nil
39
- end
40
-
41
- it "should handle blank descriptions" do
42
- doc['OfferAttributes']['ConditionNote'] = ''
43
- offer = Offer.build(doc)
44
-
45
- offer.description.should eql ''
46
- end
47
- end
48
-
49
- describe "#kosher?" do
50
- context "when condition is kosher" do
51
- before do
52
- offer.condition = Fabricate(:kosher_condition, :grade => 1)
53
- end
54
-
55
- context "when seller is kosher" do
56
- before do
57
- offer.seller = Fabricate(:good_seller)
58
- end
59
-
60
- context "when description is kosher" do
61
- context "when offer ships now" do
62
- it "returns true" do
63
- offer.should be_kosher
64
- end
65
- end
66
-
67
- context "when offer does not ship now" do
68
- before do
69
- offer.ships_in = 96
70
- end
71
-
72
- it "returns false" do
73
- offer.should_not be_kosher
74
- end
75
- end
76
- end
77
-
78
- context "when description is not kosher" do
79
- before do
80
- offer.description = Kosher::Description.new("Withdrawn library book")
81
- end
82
-
83
- it "returns false" do
84
- offer.should_not be_kosher
85
- end
86
- end
87
- end
88
-
89
- context "when seller is not kosher" do
90
- before do
91
- offer.seller = Fabricate(:bad_seller)
92
- end
93
-
94
- it "returns false" do
95
- offer.should_not be_kosher
96
- end
97
- end
98
- end
99
-
100
- context "when condition is not kosher" do
101
- before do
102
- offer.condition = Fabricate(:kosher_condition, :grade => 5)
103
- end
104
-
105
- it "returns false" do
106
- offer.should_not be_kosher
107
- end
108
- end
109
- end
110
-
111
- describe "#ships_now?" do
112
- context "when offer ships within 48 hours" do
113
- before do
114
- offer.ships_in = 48
115
- end
116
-
117
- it "returns true" do
118
- offer.send(:ships_now?).should be_true
119
- end
120
- end
121
-
122
- context "when offer ships in over 48 hours" do
123
- before do
124
- offer.ships_in = 96
125
- end
126
-
127
- it "returns false" do
128
- offer.send(:ships_now?).should be_false
129
- end
130
- end
131
- end
132
- end
133
- end
@@ -1,71 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module Kosher
4
- describe Seller do
5
- describe ".build" do
6
- use_vcr_cassette '0143105825'
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(:seller) do
20
- docs = response.find('Merchant')
21
- Seller.build(docs.first)
22
- end
23
-
24
- it "populates the merchant ID of a seller" do
25
- seller.merchant_id.should match /^[0-9A-Z]{13,14}$/
26
- end
27
-
28
- it "populates the name of a seller" do
29
- seller.name.should_not be_nil
30
- end
31
-
32
- it "populates the average rating of a seller" do
33
- seller.average_rating.should be_an_instance_of Float
34
- end
35
-
36
- it "builds a newly-launched seller" do
37
- doc = response.find('Merchant').detect { |doc| doc["AverageFeedbackRating"] == "0.0" }
38
- new_seller = Seller.build(doc)
39
-
40
- new_seller.average_rating.should eql 0.0
41
- end
42
- end
43
-
44
- describe "#kosher?" do
45
- it "returns true if seller's average rating is 0.0" do
46
- seller = Fabricate(:new_seller)
47
- seller.should be_kosher
48
- end
49
-
50
- it "returns true if seller's average rating is above 4.7" do
51
- seller = Fabricate(:good_seller)
52
- seller.should be_kosher
53
- end
54
-
55
- it "returns false if sellers' average rating is 4.7 or below" do
56
- seller = Fabricate(:bad_seller)
57
- seller.should_not be_kosher
58
- end
59
-
60
- it "returns false if seller is blacklisted" do
61
- seller = Fabricate(:good_seller)
62
- seller.should be_kosher
63
-
64
- seller.merchant_id = Faker::Amazon.merchant_id
65
- Seller.blacklist = [seller.merchant_id]
66
-
67
- seller.should_not be_kosher
68
- end
69
- end
70
- end
71
- end
@@ -1,28 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module Kosher
4
- describe Struct do
5
- before(:all) do
6
- class Foo < Struct.new(:bar); end
7
- end
8
-
9
- describe "to_json" do
10
- it "converts to JSON" do
11
- foo = Foo.new
12
- foo.bar = 1
13
-
14
- foo.to_json.should eql "{\"bar\":1}"
15
- end
16
-
17
- it "handles nested structs" do
18
- foo_1 = Foo.new
19
- foo_2 = Foo.new
20
-
21
- foo_2.bar = 1
22
- foo_1.bar = foo_2
23
-
24
- foo_1.to_json.should eql "{\"bar\":{\"bar\":1}}"
25
- end
26
- end
27
- end
28
- end
@@ -1,19 +0,0 @@
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