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
@@ -0,0 +1,64 @@
1
+ require File.expand_path('../../../test_helper', __FILE__)
2
+
3
+ module Etsy
4
+ class TestModel
5
+ include Etsy::Model
6
+ end
7
+
8
+ class ModelTest < Test::Unit::TestCase
9
+
10
+ def mock_empty_request(options = {})
11
+ body = options.delete(:body) { '{}' }
12
+ Request.expects(:new).with('', options).returns(stub(:get => stub(:body => body, :code => 200)))
13
+ end
14
+
15
+ context 'An instance of a Model' do
16
+
17
+ should 'perform no requests if :limit is 0' do
18
+ Request.expects(:new).never
19
+ TestModel.get_all('', :limit => 0)
20
+ end
21
+
22
+ should 'perform only one request if :limit is less than 100' do
23
+ mock_empty_request(:limit => 10, :offset => 0).once
24
+ TestModel.get_all('', :limit => 10)
25
+ end
26
+
27
+ should 'perform only one request if :limit is equal to 100' do
28
+ mock_empty_request(:limit => 100, :offset => 0).once
29
+ TestModel.get_all('', :limit => 100)
30
+ end
31
+
32
+ should 'perform multiple requests if :limit is greater than 100' do
33
+ mock_empty_request(:limit => 100, :offset => 0).once
34
+ mock_empty_request(:limit => 50, :offset => 100).once
35
+
36
+ TestModel.get_all('', :limit => 150)
37
+ end
38
+
39
+ should 'perform only one request if :limit is :all and count is less than 100' do
40
+ mock_empty_request(:limit => 100, :offset => 0, :body => '{"count": 10}').once
41
+ TestModel.get_all('', :limit => :all)
42
+ end
43
+
44
+ should 'perform only one request if :limit is :all and count is equal to 100' do
45
+ mock_empty_request(:limit => 100, :offset => 0, :body => '{"count": 100}').once
46
+ TestModel.get_all('', :limit => :all)
47
+ end
48
+
49
+ should 'perform only one request if :limit is :all and :offset is greater than count' do
50
+ mock_empty_request(:limit => 100, :offset => 40, :body => '{"count": 25}').once
51
+ TestModel.get_all('', :limit => :all, :offset => 40)
52
+ end
53
+
54
+ should 'perform multiple requests if :limit is :all and count is greater than 100' do
55
+ body = '{"count": 210}'
56
+ mock_empty_request(:limit => 100, :offset => 0, :body => body).once
57
+ mock_empty_request(:limit => 100, :offset => 100, :body => body).once
58
+ mock_empty_request(:limit => 10, :offset => 200, :body => body).once
59
+
60
+ TestModel.get_all('', :limit => :all)
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,68 @@
1
+ require File.expand_path('../../../test_helper', __FILE__)
2
+
3
+ module Etsy
4
+ class PaymentTemplateTest < Test::Unit::TestCase
5
+ context "An instance of the PaymentTemplate class" do
6
+ setup do
7
+ data = read_fixture('payment_template/getPaymentTemplate.json')
8
+ @payment_template = PaymentTemplate.new(data.first)
9
+ end
10
+
11
+ should "have an id" do
12
+ @payment_template.id.should == 51
13
+ end
14
+
15
+ should "have attribute: allow_check" do
16
+ @payment_template.allow_check.should == false
17
+ end
18
+
19
+ should "have attribute: allow_mo" do
20
+ @payment_template.allow_mo.should == false
21
+ end
22
+
23
+ should "have attribute: allow_other" do
24
+ @payment_template.allow_other.should == true
25
+ end
26
+
27
+ should "have attribute: allow_paypal" do
28
+ @payment_template.allow_paypal.should == true
29
+ end
30
+
31
+ should "have attribute: allow_cc" do
32
+ @payment_template.allow_cc.should == false
33
+ end
34
+
35
+ should "have attribute: paypal_email" do
36
+ @payment_template.paypal_email.should == "user@example.com"
37
+ end
38
+
39
+ should "have attribute: name" do
40
+ @payment_template.name.should == "Example Template"
41
+ end
42
+
43
+ should "have attribute: first_line" do
44
+ @payment_template.first_line.should == nil
45
+ end
46
+
47
+ should "have attribute: second_line" do
48
+ @payment_template.second_line.should == nil
49
+ end
50
+
51
+ should "have attribute: city" do
52
+ @payment_template.city.should == "Chicago"
53
+ end
54
+
55
+ should "have attribute: state" do
56
+ @payment_template.state.should == "IL"
57
+ end
58
+
59
+ should "have attribute: zip" do
60
+ @payment_template.zip.should == "60605"
61
+ end
62
+
63
+ should "have attribute: country_id" do
64
+ @payment_template.country_id.should == 4
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,111 @@
1
+ require File.expand_path('../../../test_helper', __FILE__)
2
+
3
+ module Etsy
4
+ class ProfileTest < Test::Unit::TestCase
5
+
6
+ # The Etsy profile can only be accessed as an association through other resources.
7
+ # There are no finders.
8
+ context "An instance of the Profile class" do
9
+
10
+ context "with response data" do
11
+ setup do
12
+ data = read_fixture('profile/new.json')
13
+ @profile = Profile.new(data)
14
+ end
15
+
16
+ should "have a value for :id" do
17
+ @profile.id.should == 123
18
+ end
19
+
20
+ should "have a value for :user_id" do
21
+ @profile.user_id.should == 5327518
22
+ end
23
+
24
+ should "have a value for :username" do
25
+ @profile.username.should == "littletjane"
26
+ end
27
+
28
+ should "have a value for :bio" do
29
+ @profile.bio.should == "I make stuff"
30
+ end
31
+
32
+ should "have a value for :gender" do
33
+ @profile.gender.should == "female"
34
+ end
35
+
36
+ should "have a value for :birth_day" do
37
+ @profile.birth_day.should == "01"
38
+ end
39
+
40
+ should "have a value for :birth_month" do
41
+ @profile.birth_month.should == "01"
42
+ end
43
+
44
+ should "have a value for :birth_year" do
45
+ @profile.birth_year.should == "1970"
46
+ end
47
+
48
+ should "have a value for :joined_at" do
49
+ @profile.joined_at.should == Time.at(1225392413)
50
+ end
51
+
52
+ should "have a value for :materials" do
53
+ @profile.materials.should == []
54
+ end
55
+
56
+ should "have a value for :country_id" do
57
+ @profile.country_id.should == 209
58
+ end
59
+
60
+ should "have a value for :city" do
61
+ @profile.city.should == "BigCity"
62
+ end
63
+
64
+ should "have a value for :avatar_id" do
65
+ @profile.avatar_id.should == 345
66
+ end
67
+
68
+ should "have a value for :location" do
69
+ @profile.location.should == "HQ"
70
+ end
71
+
72
+ should "have a value for :region" do
73
+ @profile.region.should == "The Desert"
74
+ end
75
+
76
+ should "have a value for :lat" do
77
+ @profile.lat.should == 39.5304
78
+ end
79
+
80
+ should "have a value for :lon" do
81
+ @profile.lon.should == -119.8144
82
+ end
83
+
84
+ should "have a value for :transaction_buy_count" do
85
+ @profile.transaction_buy_count.should == 19
86
+ end
87
+
88
+ should "have a value for :transaction_sold_count" do
89
+ @profile.transaction_sold_count.should == 16
90
+ end
91
+
92
+ should "have a value for :seller?" do
93
+ @profile.seller?.should == true
94
+ end
95
+
96
+ should "have a value for :image" do
97
+ @profile.image.should == 'some_image.jpg'
98
+ end
99
+
100
+ should "have a value for :first_name" do
101
+ @profile.first_name.should == 'Tinker'
102
+ end
103
+
104
+ should "have a value for :last_name" do
105
+ @profile.last_name.should == 'Bell'
106
+ end
107
+ end
108
+
109
+ end
110
+ end
111
+ end
@@ -5,10 +5,6 @@ module Etsy
5
5
 
6
6
  context "The Request class" do
7
7
 
8
- should "know the host" do
9
- Request.host.should == 'openapi.etsy.com'
10
- end
11
-
12
8
  should "be able to retrieve a response" do
13
9
  http_response = stub()
14
10
  response = stub()
@@ -20,74 +16,100 @@ module Etsy
20
16
 
21
17
  Request.get('/user', :one => 'two').should == response
22
18
  end
19
+
20
+ should "require OAuth credentials if :require_secure is set" do
21
+ lambda do
22
+ Request.new('/path', :require_secure => true)
23
+ end.should raise_error(/Secure connection required/)
24
+ end
23
25
  end
24
26
 
25
27
  context "An instance of the Request class" do
26
28
 
27
- should "know the base path for the sandbox read-only environment" do
28
- Etsy.stubs(:environment).returns(:sandbox)
29
- Etsy.stubs(:access_mode).returns(:read_only)
30
-
31
- Request.new('').base_path.should == '/v2/sandbox/public'
29
+ should "know the base path" do
30
+ Request.new('').base_path.should == '/v2'
32
31
  end
33
32
 
34
- should "know the base path for the sandbox read/write environment when the access information is present" do
35
- Etsy.stubs(:environment).returns(:sandbox)
36
- Etsy.stubs(:access_mode).returns(:read_write)
33
+ should "append the api_key to the parameters in basic mode" do
34
+ Etsy.expects(:api_key).with().returns('key')
35
+ Request.stubs(:secure?).returns(false)
37
36
 
38
- r = Request.new('', :access_token => 'toke', :access_secret => 'secret')
39
- r.base_path.should == '/v2/sandbox/private'
37
+ r = Request.new('/user', :limit => '1')
38
+ r.parameters.should == {:limit => '1', :api_key => 'key'}
40
39
  end
41
40
 
42
- should "know the base path for the sandbox read/write environment when the access information is not present" do
43
- Etsy.stubs(:environment).returns(:sandbox)
44
- Etsy.stubs(:access_mode).returns(:read_write)
41
+ should "not append the api_key to the parameters in secure mode" do
42
+ Etsy.stubs(:access_mode).returns(:authenticated)
45
43
 
46
- Request.new('').base_path.should == '/v2/sandbox/public'
44
+ r = Request.new('/user', :limit => '1', :access_token => 'token', :access_secret => 'secret')
45
+ r.parameters.should == {:limit => '1'}
47
46
  end
48
47
 
49
- should "know the base path for the production read-only environment" do
50
- Etsy.stubs(:environment).returns(:production)
51
- Etsy.stubs(:access_mode).returns(:read_only)
52
48
 
53
- Request.new('').base_path.should == '/v2/public'
49
+ should "be able to generate query parameters" do
50
+ r = Request.new('/user')
51
+ r.expects(:parameters).with().returns(:api_key => 'foo')
52
+ r.query.should == 'api_key=foo'
54
53
  end
55
54
 
56
- should "know the base path for the production read-write environment when access information is present" do
57
- Etsy.stubs(:environment).returns(:production)
58
- Etsy.stubs(:access_mode).returns(:read_write)
55
+ should "be able to join multiple query parameters" do
56
+ params = {:limit => '1', :other => 'yes'}
59
57
 
60
- r = Request.new('', :access_token => 'toke', :access_secret => 'secret')
61
- r.base_path.should == '/v2/private'
62
- end
58
+ r = Request.new('/user', params)
59
+ r.stubs(:parameters).with().returns(params)
63
60
 
64
- should "know the base path for the production read-write environment when access information is not present" do
65
- Etsy.stubs(:environment).returns(:production)
66
- Etsy.stubs(:access_mode).returns(:read_write)
61
+ r.query.split('&').sort.should == %w(limit=1 other=yes)
62
+ end
67
63
 
68
- Request.new('').base_path.should == '/v2/public'
64
+ should "be able to request a single association" do
65
+ r = Request.new('/foo', {:includes => 'Thunder'})
66
+ r.stubs(:parameters).with().returns({:a => :b})
67
+ CGI.parse(r.query).should == { "a" => ["b"], "includes" => ["Thunder"] }
69
68
  end
70
69
 
71
- should "append the api_key and detail_level to the parameters" do
72
- Etsy.expects(:api_key).with().returns('key')
70
+ should "be able make simplified association requests" do
71
+ r = Request.new('/foo', {:includes => ['Thunder', 'Lightning']})
72
+ r.stubs(:parameters).with().returns({:a => :b})
73
+ CGI.parse(r.query).should == { "a" => ["b"], "includes" => ["Thunder,Lightning"] }
74
+ end
73
75
 
74
- r = Request.new('/user', :limit => '1')
75
- r.parameters.should == {:limit => '1', :api_key => 'key', :detail_level => 'high'}
76
+ should "be able to generate detailed association queries" do
77
+ r = Request.new('/foo')
78
+ r.association(:resource => 'Lightning').should == 'Lightning'
76
79
  end
77
80
 
78
- should "be able to generate query parameters" do
79
- r = Request.new('/user')
80
- r.expects(:parameters).with().returns(:api_key => 'foo')
81
- r.query.should == 'api_key=foo'
81
+ should "be able to specify fields in association query" do
82
+ r = Request.new('/foo')
83
+ params = {:resource => 'Lightning', :fields => ['one', 'two']}
84
+ r.association(params).should == 'Lightning(one,two)'
82
85
  end
83
86
 
84
- should "be able to join multiple query parameters" do
85
- params = {:limit => '1', :other => 'yes'}
87
+ should "be able to specify limit in association query" do
88
+ r = Request.new('/foo')
89
+ params = {:resource => 'Lightning', :limit => 3}
90
+ r.association(params).should == 'Lightning:3:0'
91
+ end
86
92
 
87
- r = Request.new('/user', params)
88
- r.stubs(:parameters).with().returns(params)
93
+ should "be able to specify offset in association query" do
94
+ r = Request.new('/foo')
95
+ params = {:resource => 'Lightning', :offset => 7}
96
+ r.association(params).should == 'Lightning:25:7'
97
+ end
89
98
 
90
- r.query.split('&').sort.should == %w(limit=1 other=yes)
99
+ should "be able to join multiple resources in association query" do
100
+ params = {
101
+ :a => 'b',
102
+ :includes => [
103
+ {:resource => 'Lightning'},
104
+ {:resource => 'Thunder'}
105
+ ]
106
+ }
107
+ r = Request.new('/foo', params)
108
+ r.stubs(:base_path).with().returns('/base')
109
+ r.stubs(:parameters).with().returns(:a => 'b')
110
+ uri = URI.parse(r.endpoint_url)
111
+ uri.path.should == '/base/foo'
112
+ CGI.parse(uri.query).should == { "a" => ["b"], "includes" => ["Lightning,Thunder"] }
91
113
  end
92
114
 
93
115
  should "be able to determine the endpoint URI when in read-only mode" do
@@ -98,8 +120,8 @@ module Etsy
98
120
  r.endpoint_url.should == '/base/user?a=b'
99
121
  end
100
122
 
101
- should "be able to determine the endpoint URI when in read-write mode" do
102
- Etsy.stubs(:access_mode).returns(:read_write)
123
+ should "be able to determine the endpoint URI when in authenticated mode" do
124
+ Etsy.stubs(:access_mode).returns(:authenticated)
103
125
 
104
126
  r = Request.new('/user', :access_token => 'toke', :access_secret => 'secret')
105
127
  r.stubs(:base_path).with().returns('/base')
@@ -110,7 +132,7 @@ module Etsy
110
132
 
111
133
  should "know the client for read-only mode" do
112
134
  Etsy.stubs(:access_mode).returns(:read_only)
113
- Request.stubs(:host).returns('example.com')
135
+ Etsy.stubs(:host).returns('example.com')
114
136
 
115
137
  BasicClient.stubs(:new).with('example.com').returns('client')
116
138
 
@@ -119,9 +141,9 @@ module Etsy
119
141
  r.client.should == 'client'
120
142
  end
121
143
 
122
- should "know the client for read-write mode when there is no access token information" do
123
- Etsy.stubs(:access_mode).returns(:read_write)
124
- Request.stubs(:host).returns('example.com')
144
+ should "know the client for authenticated mode when there is no access token information" do
145
+ Etsy.stubs(:access_mode).returns(:authenticated)
146
+ Etsy.stubs(:host).returns('example.com')
125
147
 
126
148
  BasicClient.stubs(:new).with('example.com').returns('client')
127
149
 
@@ -130,8 +152,8 @@ module Etsy
130
152
  r.client.should == 'client'
131
153
  end
132
154
 
133
- should "know the client for read-write mode when there is access token information" do
134
- Etsy.stubs(:access_mode).returns(:read_write)
155
+ should "know the client for authenticated mode when there is access token information" do
156
+ Etsy.stubs(:access_mode).returns(:authenticated)
135
157
  SecureClient.stubs(:new).with(:access_token => 'toke', :access_secret => 'secret').returns('client')
136
158
 
137
159
  r = Request.new('', :access_token => 'toke', :access_secret => 'secret')
@@ -149,6 +171,20 @@ module Etsy
149
171
  r.get.should == 'response'
150
172
  end
151
173
 
174
+ should "not modify the options hash passed to it" do
175
+ options = { :includes => 'Lightning',
176
+ :access_token => 'token',
177
+ :access_secret => 'secret',
178
+ :fields => [:id],
179
+ :limit => 100,
180
+ :offset => 100 }
181
+ options_copy = options.dup
182
+
183
+ Request.new('', options)
184
+
185
+ options.should == options_copy
186
+ end
187
+
152
188
  end
153
189
 
154
190