etsy 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +8 -0
- data/.travis.yml +8 -0
- data/Gemfile +10 -0
- data/README.md +300 -0
- data/Rakefile +2 -30
- data/etsy.gemspec +36 -0
- data/lib/etsy.rb +46 -17
- data/lib/etsy/address.rb +47 -0
- data/lib/etsy/basic_client.rb +1 -1
- data/lib/etsy/category.rb +84 -0
- data/lib/etsy/country.rb +27 -0
- data/lib/etsy/image.rb +7 -3
- data/lib/etsy/listing.rb +107 -8
- data/lib/etsy/model.rb +99 -3
- data/lib/etsy/payment_template.rb +33 -0
- data/lib/etsy/profile.rb +49 -0
- data/lib/etsy/request.rb +85 -17
- data/lib/etsy/response.rb +80 -4
- data/lib/etsy/section.rb +16 -0
- data/lib/etsy/secure_client.rb +49 -4
- data/lib/etsy/shipping_template.rb +32 -0
- data/lib/etsy/shop.rb +21 -12
- data/lib/etsy/transaction.rb +18 -0
- data/lib/etsy/user.rb +45 -13
- data/lib/etsy/verification_request.rb +2 -2
- data/test/fixtures/address/getUserAddresses.json +12 -0
- data/test/fixtures/category/findAllSubCategoryChildren.json +78 -0
- data/test/fixtures/category/findAllTopCategory.json +347 -0
- data/test/fixtures/category/findAllTopCategory.single.json +18 -0
- data/test/fixtures/category/findAllTopCategoryChildren.json +308 -0
- data/test/fixtures/category/getCategory.multiple.json +28 -0
- data/test/fixtures/category/getCategory.single.json +18 -0
- data/test/fixtures/country/getCountry.json +1 -0
- data/test/fixtures/listing/findAllListingActive.category.json +827 -0
- data/test/fixtures/listing/{findAllShopListingsActive.json → findAllShopListings.json} +0 -0
- data/test/fixtures/listing/getListing.multiple.json +1 -0
- data/test/fixtures/listing/getListing.single.json +1 -0
- data/test/fixtures/payment_template/getPaymentTemplate.json +1 -0
- data/test/fixtures/profile/new.json +28 -0
- data/test/fixtures/section/getShopSection.json +18 -0
- data/test/fixtures/shipping_template/getShippingTemplate.json +1 -0
- data/test/fixtures/shop/getShop.single.json +4 -3
- data/test/fixtures/transaction/findAllShopTransactions.json +1 -0
- data/test/fixtures/user/getUser.single.withProfile.json +38 -0
- data/test/fixtures/user/getUser.single.withShops.json +41 -0
- data/test/test_helper.rb +9 -4
- data/test/unit/etsy/address_test.rb +61 -0
- data/test/unit/etsy/category_test.rb +106 -0
- data/test/unit/etsy/country_test.rb +64 -0
- data/test/unit/etsy/listing_test.rb +112 -5
- data/test/unit/etsy/model_test.rb +64 -0
- data/test/unit/etsy/payment_template_test.rb +68 -0
- data/test/unit/etsy/profile_test.rb +111 -0
- data/test/unit/etsy/request_test.rb +89 -53
- data/test/unit/etsy/response_test.rb +118 -4
- data/test/unit/etsy/section_test.rb +28 -0
- data/test/unit/etsy/secure_client_test.rb +27 -5
- data/test/unit/etsy/shipping_template_test.rb +24 -0
- data/test/unit/etsy/shop_test.rb +12 -5
- data/test/unit/etsy/transaction_test.rb +52 -0
- data/test/unit/etsy/user_test.rb +147 -8
- data/test/unit/etsy/verification_request_test.rb +3 -3
- data/test/unit/etsy_test.rb +19 -7
- metadata +133 -77
- data/README.rdoc +0 -208
- 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
|
28
|
-
|
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 "
|
35
|
-
Etsy.
|
36
|
-
|
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('', :
|
39
|
-
r.
|
37
|
+
r = Request.new('/user', :limit => '1')
|
38
|
+
r.parameters.should == {:limit => '1', :api_key => 'key'}
|
40
39
|
end
|
41
40
|
|
42
|
-
should "
|
43
|
-
Etsy.stubs(:
|
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(''
|
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
|
-
|
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 "
|
57
|
-
|
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('',
|
61
|
-
r.
|
62
|
-
end
|
58
|
+
r = Request.new('/user', params)
|
59
|
+
r.stubs(:parameters).with().returns(params)
|
63
60
|
|
64
|
-
|
65
|
-
|
66
|
-
Etsy.stubs(:access_mode).returns(:read_write)
|
61
|
+
r.query.split('&').sort.should == %w(limit=1 other=yes)
|
62
|
+
end
|
67
63
|
|
68
|
-
|
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 "
|
72
|
-
|
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
|
-
|
75
|
-
r
|
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
|
79
|
-
r = Request.new('/
|
80
|
-
|
81
|
-
r.
|
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
|
85
|
-
|
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
|
-
|
88
|
-
r.
|
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
|
-
|
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
|
102
|
-
Etsy.stubs(:access_mode).returns(:
|
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
|
-
|
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
|
123
|
-
Etsy.stubs(:access_mode).returns(:
|
124
|
-
|
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
|
134
|
-
Etsy.stubs(:access_mode).returns(:
|
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
|
|