etsy 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. data/.gitignore +8 -0
  2. data/.travis.yml +8 -0
  3. data/Gemfile +10 -0
  4. data/README.md +300 -0
  5. data/Rakefile +2 -30
  6. data/etsy.gemspec +36 -0
  7. data/lib/etsy.rb +46 -17
  8. data/lib/etsy/address.rb +47 -0
  9. data/lib/etsy/basic_client.rb +1 -1
  10. data/lib/etsy/category.rb +84 -0
  11. data/lib/etsy/country.rb +27 -0
  12. data/lib/etsy/image.rb +7 -3
  13. data/lib/etsy/listing.rb +107 -8
  14. data/lib/etsy/model.rb +99 -3
  15. data/lib/etsy/payment_template.rb +33 -0
  16. data/lib/etsy/profile.rb +49 -0
  17. data/lib/etsy/request.rb +85 -17
  18. data/lib/etsy/response.rb +80 -4
  19. data/lib/etsy/section.rb +16 -0
  20. data/lib/etsy/secure_client.rb +49 -4
  21. data/lib/etsy/shipping_template.rb +32 -0
  22. data/lib/etsy/shop.rb +21 -12
  23. data/lib/etsy/transaction.rb +18 -0
  24. data/lib/etsy/user.rb +45 -13
  25. data/lib/etsy/verification_request.rb +2 -2
  26. data/test/fixtures/address/getUserAddresses.json +12 -0
  27. data/test/fixtures/category/findAllSubCategoryChildren.json +78 -0
  28. data/test/fixtures/category/findAllTopCategory.json +347 -0
  29. data/test/fixtures/category/findAllTopCategory.single.json +18 -0
  30. data/test/fixtures/category/findAllTopCategoryChildren.json +308 -0
  31. data/test/fixtures/category/getCategory.multiple.json +28 -0
  32. data/test/fixtures/category/getCategory.single.json +18 -0
  33. data/test/fixtures/country/getCountry.json +1 -0
  34. data/test/fixtures/listing/findAllListingActive.category.json +827 -0
  35. data/test/fixtures/listing/{findAllShopListingsActive.json → findAllShopListings.json} +0 -0
  36. data/test/fixtures/listing/getListing.multiple.json +1 -0
  37. data/test/fixtures/listing/getListing.single.json +1 -0
  38. data/test/fixtures/payment_template/getPaymentTemplate.json +1 -0
  39. data/test/fixtures/profile/new.json +28 -0
  40. data/test/fixtures/section/getShopSection.json +18 -0
  41. data/test/fixtures/shipping_template/getShippingTemplate.json +1 -0
  42. data/test/fixtures/shop/getShop.single.json +4 -3
  43. data/test/fixtures/transaction/findAllShopTransactions.json +1 -0
  44. data/test/fixtures/user/getUser.single.withProfile.json +38 -0
  45. data/test/fixtures/user/getUser.single.withShops.json +41 -0
  46. data/test/test_helper.rb +9 -4
  47. data/test/unit/etsy/address_test.rb +61 -0
  48. data/test/unit/etsy/category_test.rb +106 -0
  49. data/test/unit/etsy/country_test.rb +64 -0
  50. data/test/unit/etsy/listing_test.rb +112 -5
  51. data/test/unit/etsy/model_test.rb +64 -0
  52. data/test/unit/etsy/payment_template_test.rb +68 -0
  53. data/test/unit/etsy/profile_test.rb +111 -0
  54. data/test/unit/etsy/request_test.rb +89 -53
  55. data/test/unit/etsy/response_test.rb +118 -4
  56. data/test/unit/etsy/section_test.rb +28 -0
  57. data/test/unit/etsy/secure_client_test.rb +27 -5
  58. data/test/unit/etsy/shipping_template_test.rb +24 -0
  59. data/test/unit/etsy/shop_test.rb +12 -5
  60. data/test/unit/etsy/transaction_test.rb +52 -0
  61. data/test/unit/etsy/user_test.rb +147 -8
  62. data/test/unit/etsy/verification_request_test.rb +3 -3
  63. data/test/unit/etsy_test.rb +19 -7
  64. metadata +133 -77
  65. data/README.rdoc +0 -208
  66. data/lib/etsy/version.rb +0 -13
@@ -19,15 +19,33 @@ module Etsy
19
19
  2.times { r.to_hash }
20
20
  end
21
21
 
22
- should "have a record count" do
23
- r = Response.new('')
24
- r.expects(:to_hash).with().returns('count' => 1)
22
+ should "have a record count when the response is not paginated" do
23
+ raw_response = mock
24
+ raw_response.stubs(:body => '{ "count": 1 }')
25
+ r = Response.new(raw_response)
25
26
 
26
27
  r.count.should == 1
27
28
  end
28
29
 
30
+ should "have a record count when the response is paginated" do
31
+ raw_response = mock
32
+ raw_response.stubs(:body => '{ "count": 100, "results": [{},{}], "pagination": {} }')
33
+ r = Response.new(raw_response)
34
+
35
+ r.count.should == 2
36
+ end
37
+
38
+ should "return a count of 0 when the response is paginated and the results are empty" do
39
+ raw_response = mock
40
+ raw_response.stubs(:body => '{ "count": 100, "results": null, "pagination": {} }')
41
+ r = Response.new(raw_response)
42
+
43
+ r.count.should == 0
44
+ end
45
+
29
46
  should "return an array if there are multiple results entries" do
30
47
  r = Response.new('')
48
+ r.expects(:code).with().returns('200')
31
49
  r.expects(:count).with().returns(2)
32
50
  r.expects(:to_hash).with().returns('results' => %w(one two))
33
51
 
@@ -36,14 +54,110 @@ module Etsy
36
54
 
37
55
  should "return a single value for results if there is only 1 result" do
38
56
  r = Response.new('')
57
+ r.expects(:code).with().returns('200')
39
58
  r.expects(:count).with().returns(1)
40
59
  r.expects(:to_hash).with().returns('results' => ['foo'])
41
60
 
42
61
  r.result.should == 'foo'
43
62
  end
44
63
 
64
+ should "provide the complete raw body" do
65
+ raw_response = mock
66
+ raw_response.stubs(:body => "I am not JSON")
67
+ r = Response.new(raw_response)
68
+
69
+ r.body.should == 'I am not JSON'
70
+ end
71
+
72
+ should "raise an invalid JSON exception if the response is not json" do
73
+ raw_response = mock
74
+ raw_response.stubs(:body => "I am not JSON")
75
+ r = Response.new(raw_response)
76
+
77
+ lambda { r.to_hash }.should raise_error(Etsy::EtsyJSONInvalid)
78
+ end
79
+
80
+ should "raise OAuthTokenRevoked" do
81
+ raw_response = mock
82
+ raw_response.stubs(:body => "oauth_problem=token_revoked")
83
+ r = Response.new(raw_response)
84
+
85
+ lambda { r.to_hash }.should raise_error(Etsy::OAuthTokenRevoked)
86
+ end
87
+
88
+ should "raise MissingShopID" do
89
+ raw_response = mock
90
+ raw_response.stubs(:body => "something Shop with PK shop_id something")
91
+ r = Response.new(raw_response)
92
+
93
+ lambda { r.to_hash }.should raise_error(Etsy::MissingShopID)
94
+ end
95
+
96
+ should "raise InvalidUserID" do
97
+ raw_response = mock
98
+ raw_response.stubs(:body => "'someguy' is not a valid user_id")
99
+ r = Response.new(raw_response)
100
+
101
+ lambda { r.to_hash }.should raise_error(Etsy::InvalidUserID)
102
+ end
103
+
104
+ should "raise TemporaryIssue" do
105
+ raw_response = mock
106
+ raw_response.stubs(:body => "something Temporary Etsy issue something")
107
+ r = Response.new(raw_response)
108
+
109
+ lambda { r.to_hash }.should raise_error(Etsy::TemporaryIssue)
110
+
111
+ raw_response = mock
112
+ raw_response.stubs(:body => "something Resource temporarily unavailable something")
113
+ r = Response.new(raw_response)
114
+
115
+ lambda { r.to_hash }.should raise_error(Etsy::TemporaryIssue)
116
+
117
+ raw_response = mock
118
+ raw_response.stubs(:body => "something You have exceeded your API limit something")
119
+ r = Response.new(raw_response)
120
+
121
+ lambda { r.to_hash }.should raise_error(Etsy::TemporaryIssue)
122
+ end
123
+
124
+ should "provide the code" do
125
+ raw_response = mock
126
+ raw_response.expects(:code => "400")
127
+ r = Response.new(raw_response)
128
+
129
+ r.code.should == '400'
130
+ end
131
+
132
+ should "consider a code of 2xx successful" do
133
+ raw_response = mock
134
+
135
+ raw_response.expects(:code => "200")
136
+ r = Response.new(raw_response)
137
+ r.should be_success
138
+
139
+ raw_response.expects(:code => "201")
140
+ r = Response.new(raw_response)
141
+ r.should be_success
142
+ end
143
+
144
+ should "consider a code of 4xx unsuccessful" do
145
+ raw_response = mock
146
+
147
+ raw_response.expects(:code => "404")
148
+ r = Response.new(raw_response)
149
+ r.should_not be_success
150
+ end
151
+
152
+ should "consider a code of 5xx unsuccessful" do
153
+ raw_response = mock
154
+
155
+ raw_response.expects(:code => "500")
156
+ r = Response.new(raw_response)
157
+ r.should_not be_success
158
+ end
45
159
  end
46
160
 
47
161
 
48
162
  end
49
- end
163
+ end
@@ -0,0 +1,28 @@
1
+ require File.expand_path('../../../test_helper', __FILE__)
2
+
3
+ module Etsy
4
+ class SectionTest < Test::Unit::TestCase
5
+ context "An instance of the Section class" do
6
+ setup do
7
+ data = read_fixture('section/getShopSection.json')
8
+ @section = Section.new(data.first)
9
+ end
10
+
11
+ should "have an id" do
12
+ @section.id.should == 11045327
13
+ end
14
+
15
+ should "have an title" do
16
+ @section.title.should == "Blue Items"
17
+ end
18
+
19
+ should "have an user_id" do
20
+ @section.user_id.should == 9569349
21
+ end
22
+
23
+ should "have an active_listing_count" do
24
+ @section.active_listing_count.should == 7
25
+ end
26
+ end
27
+ end
28
+ end
@@ -5,15 +5,17 @@ module Etsy
5
5
 
6
6
  context "An instance of the SecureClient class" do
7
7
 
8
- should "be able to generate an OAuth consumer" do
8
+ should "be able to generate an OAuth consumer for the sandbox" do
9
+ Etsy.stubs(:environment).returns :sandbox
10
+ Etsy.stubs(:host).returns 'sandbox'
9
11
  Etsy.stubs(:api_key).returns('key')
10
12
  Etsy.stubs(:api_secret).returns('secret')
13
+ Etsy.stubs(:permission_scopes).returns(['scope_one', 'scope_two'])
11
14
 
12
15
  OAuth::Consumer.stubs(:new).with('key', 'secret', {
13
- :site => 'http://openapi.etsy.com',
14
- :request_token_path => '/v2/sandbox/oauth/request_token',
15
- :access_token_path => '/v2/sandbox/oauth/access_token',
16
- :authorize_url => 'https://www.etsy.com/oauth/signin'
16
+ :site => 'http://sandbox',
17
+ :request_token_path => '/v2/oauth/request_token?scope=scope_one+scope_two',
18
+ :access_token_path => '/v2/oauth/access_token',
17
19
  }).returns('consumer')
18
20
 
19
21
  client = SecureClient.new
@@ -21,6 +23,26 @@ module Etsy
21
23
  client.consumer.should == 'consumer'
22
24
  end
23
25
 
26
+ should "be able to generate an OAuth consumer in production" do
27
+ Etsy.stubs(:environment).returns :production
28
+ Etsy.stubs(:host).returns 'production'
29
+ Etsy.stubs(:api_key).returns('key')
30
+ Etsy.stubs(:api_secret).returns('secret')
31
+ Etsy.stubs(:permission_scopes).returns(['scope_one', 'scope_two'])
32
+
33
+ OAuth::Consumer.stubs(:new).with('key', 'secret', {
34
+ :site => 'http://production',
35
+ :request_token_path => '/v2/oauth/request_token?scope=scope_one+scope_two',
36
+ :access_token_path => '/v2/oauth/access_token',
37
+ }).returns('consumer')
38
+
39
+ client = SecureClient.new
40
+
41
+ client.consumer.should == 'consumer'
42
+ end
43
+
44
+
45
+
24
46
  should "be able to generate a request token" do
25
47
  Etsy.stubs(:callback_url).with().returns('callback_url')
26
48
  consumer = stub() {|c| c.stubs(:get_request_token).with(:oauth_callback => 'callback_url').returns('toke') }
@@ -0,0 +1,24 @@
1
+ require File.expand_path('../../../test_helper', __FILE__)
2
+
3
+ module Etsy
4
+ class ShippingTemplateTest < Test::Unit::TestCase
5
+ context "An instance of the ShippingTemplate class" do
6
+ setup do
7
+ data = read_fixture('shipping_template/getShippingTemplate.json')
8
+ @shipping_template = ShippingTemplate.new(data.first)
9
+ end
10
+
11
+ should "have an id" do
12
+ @shipping_template.id.should == 212
13
+ end
14
+
15
+ should "have an title" do
16
+ @shipping_template.title.should == "Small Items"
17
+ end
18
+
19
+ should "have an user_id" do
20
+ @shipping_template.user_id.should == 14888443
21
+ end
22
+ end
23
+ end
24
+ end
@@ -26,7 +26,7 @@ module Etsy
26
26
  end
27
27
 
28
28
  should "allow a configurable limit when finding all shops" do
29
- shops = mock_request('/shops', {:limit => 100}, 'Shop', 'findAllShop.json')
29
+ shops = mock_request('/shops', {:limit => 100, :offset => 0}, 'Shop', 'findAllShop.json')
30
30
  Shop.all(:limit => 100).should == shops
31
31
  end
32
32
 
@@ -49,7 +49,15 @@ module Etsy
49
49
  end
50
50
 
51
51
  should "have a value for :image_url" do
52
- @shop.image_url.should == "http://ny-image2.etsy.com/iusb_760x100.7358402.jpg"
52
+ @shop.image_url.should == "http://ny-image3.etsy.com/iusb_760x100.8484779.jpg"
53
+ end
54
+
55
+ should "have a value for :url" do
56
+ @shop.url.should == "http://www.etsy.com/shop/littletjane"
57
+ end
58
+
59
+ should "have a value for :favorers_count" do
60
+ @shop.favorers_count.should == 684
53
61
  end
54
62
 
55
63
  should "have a value for :active_listings_count" do
@@ -86,12 +94,11 @@ module Etsy
86
94
  shop = Shop.new
87
95
  shop.stubs(:id).with().returns(1)
88
96
 
89
- Listing.stubs(:find_all_by_shop_id).with(1).returns('listings')
97
+ Listing.stubs(:find_all_by_shop_id).with(1, {}).returns('listings')
90
98
 
91
99
  shop.listings.should == 'listings'
92
100
  end
93
-
94
101
  end
95
102
 
96
103
  end
97
- end
104
+ end
@@ -0,0 +1,52 @@
1
+ require File.expand_path('../../../test_helper', __FILE__)
2
+
3
+ module Etsy
4
+ class TransactionTest < Test::Unit::TestCase
5
+
6
+ context "The Transaction class" do
7
+
8
+ should "be able to find transactions for a shop" do
9
+ transactions = mock_request('/shops/1/transactions', {'key' => 'value'}, 'Transaction', 'findAllShopTransactions.json')
10
+ Transaction.find_all_by_shop_id(1, {'key' => 'value'}).should == transactions
11
+ end
12
+
13
+ end
14
+
15
+ context "An instance of the Transaction class" do
16
+
17
+ context "with response data" do
18
+ setup do
19
+ data = read_fixture('transaction/findAllShopTransactions.json')
20
+ @transaction = Transaction.new(data.first)
21
+ end
22
+
23
+ should "have a value for :id" do
24
+ @transaction.id.should == 27230877
25
+ end
26
+
27
+ should "have a value for :quantity" do
28
+ @transaction.quantity.should == 1
29
+ end
30
+
31
+ should "have a value for :buyer_id" do
32
+ @transaction.buyer_id.should == 9641557
33
+ end
34
+
35
+ should "have a value for :listing_id" do
36
+ @transaction.listing_id.should == 41680579
37
+ end
38
+ end
39
+
40
+ should "know the buyer" do
41
+ User.stubs(:find).with(1).returns('user')
42
+
43
+ transaction = Transaction.new
44
+ transaction.stubs(:buyer_id).with().returns(1)
45
+
46
+ transaction.buyer.should == 'user'
47
+ end
48
+
49
+ end
50
+
51
+ end
52
+ end
@@ -15,15 +15,42 @@ module Etsy
15
15
  User.find('littletjane', 'reagent').should == users
16
16
  end
17
17
 
18
- should "be able to find the current logged in user" do
19
- oauth_keys = {:access_token => 'token', :access_secret => 'secret'}
20
- users = mock_request('/users/__SELF__', oauth_keys, 'User', 'getUser.single.json')
21
- User.myself('token', 'secret').should == users.first
18
+ should "be able to pass options when finding a user" do
19
+ options = {:limit => 90, :offset => 90}
20
+ users = mock_request('/users/littletjane', options, 'User', 'getUser.single.json')
21
+ User.find('littletjane', options).should == users.first
22
+ end
23
+
24
+ should "be able to find the authenticated user" do
25
+ options = {:access_token => 'token', :access_secret => 'secret'}
26
+ users = mock_request('/users/__SELF__', options, 'User', 'getUser.single.json')
27
+ User.myself('token', 'secret', options).should == users.first
22
28
  end
23
29
  end
24
30
 
25
31
  context "An instance of the User class" do
26
32
 
33
+ context "requested with oauth access token" do
34
+ setup do
35
+ options = {:access_token => 'token', :access_secret => 'secret'}
36
+
37
+ data = read_fixture('user/getUser.single.json')
38
+ response = 'response'
39
+ response.stubs(:result).with().returns [data]
40
+ Request.stubs(:get).with('/users/__SELF__', options).returns response
41
+
42
+ @user = User.find('__SELF__', options)
43
+ end
44
+
45
+ should "persist the token" do
46
+ @user.token.should == 'token'
47
+ end
48
+
49
+ should "persist the secret" do
50
+ @user.secret.should == 'secret'
51
+ end
52
+ end
53
+
27
54
  context "with public response data" do
28
55
  setup do
29
56
  data = read_fixture('user/getUser.single.json')
@@ -50,7 +77,7 @@ module Etsy
50
77
  context "with private response data" do
51
78
  setup do
52
79
  data = read_fixture('user/getUser.single.private.json')
53
- @user = User.new(data.first)
80
+ @user = User.new(data.first, 'token', 'secret')
54
81
  end
55
82
 
56
83
  should "have an email address" do
@@ -58,6 +85,118 @@ module Etsy
58
85
  end
59
86
  end
60
87
 
88
+ context "requested with associated shops" do
89
+ setup do
90
+ data = read_fixture('user/getUser.single.withShops.json')
91
+ @user = User.new(data.first)
92
+ end
93
+
94
+ should "have shops" do
95
+ @user.shops.each do |shop|
96
+ shop.class.should == Shop
97
+ end
98
+ end
99
+
100
+ # This assumes for now that a user can have only one shop belonging to them
101
+ should "return the first shop belonging to the user" do
102
+ @user.shop.should == @user.shops.first
103
+ end
104
+ end
105
+
106
+ context "requested without associated shops" do
107
+ setup do
108
+ @data_without_shops = read_fixture('user/getUser.single.json')
109
+ @data_with_shops = read_fixture('user/getUser.single.withShops.json')
110
+ @options = {:fields => 'user_id', :includes => 'Shops'}
111
+
112
+ @user_without_shops = User.new(@data_without_shops.first)
113
+ @user_with_shops = User.new(@data_with_shops.first)
114
+ end
115
+
116
+ should "make a call to the API to retrieve it if requested" do
117
+ User.expects(:find).with('littletjane', @options).returns @user_with_shops
118
+ @user_without_shops.shops
119
+ end
120
+
121
+ should "not call the api twice" do
122
+ User.expects(:find).once.with('littletjane', @options).returns @user_with_shops
123
+ @user_without_shops.shops
124
+ @user_without_shops.shops
125
+ end
126
+
127
+ should "return a list of populated shop instances" do
128
+ User.stubs(:find).with('littletjane', @options).returns @user_with_shops
129
+ @user_without_shops.shops.first.name.should == 'LittleJane'
130
+ end
131
+
132
+ should "make the call with authentication if oauth is used" do
133
+ user = User.new(@data_without_shops.first, 'token', 'secret')
134
+ oauth = {:access_token => 'token', :access_secret => 'secret'}
135
+ User.expects(:find).with('littletjane', @options.merge(oauth)).returns @user_with_shops
136
+ user.shops
137
+ end
138
+ end
139
+
140
+ context "requested with an associated profile" do
141
+ setup do
142
+ data = read_fixture('user/getUser.single.withProfile.json')
143
+ @user = User.new(data.first)
144
+ end
145
+
146
+ should "have a profile" do
147
+ @user.profile.class.should == Profile
148
+ end
149
+ end
150
+
151
+ context "requested without an associated profile" do
152
+ setup do
153
+ @data_without_profile = read_fixture('user/getUser.single.json')
154
+ @data_with_profile = read_fixture('user/getUser.single.withProfile.json')
155
+ @options = {:fields => 'user_id', :includes => 'Profile'}
156
+
157
+ @user_without_profile = User.new(@data_without_profile.first)
158
+ @user_with_profile = User.new(@data_with_profile.first)
159
+ end
160
+
161
+ should "make a call to the API to retrieve it if requested" do
162
+ User.expects(:find).with('littletjane', @options).returns @user_with_profile
163
+ @user_without_profile.profile
164
+ end
165
+
166
+ should "not call the api twice" do
167
+ User.expects(:find).once.with('littletjane', @options).returns @user_with_profile
168
+ @user_without_profile.profile
169
+ @user_without_profile.profile
170
+ end
171
+
172
+ should "return a populated profile instance" do
173
+ User.stubs(:find).with('littletjane', @options).returns @user_with_profile
174
+ @user_without_profile.profile.bio.should == 'I make stuff'
175
+ end
176
+
177
+ should "make the call with authentication if oauth is used" do
178
+ user = User.new(@data_without_profile.first, 'token', 'secret')
179
+ oauth = {:access_token => 'token', :access_secret => 'secret'}
180
+ User.expects(:find).with('littletjane', @options.merge(oauth)).returns @user_with_profile
181
+ user.profile
182
+ end
183
+ end
184
+
185
+ context "instantiated with oauth token" do
186
+ setup do
187
+ @user = User.new(nil, 'token', 'secret')
188
+ end
189
+
190
+ should "have the token" do
191
+ @user.token.should == 'token'
192
+ end
193
+
194
+ should "have the secret" do
195
+ @user.secret.should == 'secret'
196
+ end
197
+
198
+ end
199
+
61
200
  should "know when the user was created" do
62
201
  user = User.new
63
202
  user.stubs(:created).returns(1)
@@ -66,13 +205,13 @@ module Etsy
66
205
  end
67
206
  end
68
207
 
69
- should "know the shop for a user" do
208
+ should "know the addresses for a user" do
70
209
  user = User.new
71
210
  user.stubs(:username).with().returns('username')
72
211
 
73
- Shop.stubs(:find).with('username').returns('shop')
212
+ Address.stubs(:find).with('username', {}).returns('addresses')
74
213
 
75
- user.shop.should == 'shop'
214
+ user.addresses.should == 'addresses'
76
215
  end
77
216
 
78
217
  end