etsy 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
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