cardmagic-etsy 0.3.2

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 (93) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +8 -0
  3. data/.travis.yml +13 -0
  4. data/Gemfile +11 -0
  5. data/LICENSE +9 -0
  6. data/README.md +348 -0
  7. data/Rakefile +12 -0
  8. data/etsy.gemspec +34 -0
  9. data/lib/etsy.rb +223 -0
  10. data/lib/etsy/about.rb +15 -0
  11. data/lib/etsy/address.rb +47 -0
  12. data/lib/etsy/attribute_value.rb +46 -0
  13. data/lib/etsy/basic_client.rb +32 -0
  14. data/lib/etsy/category.rb +84 -0
  15. data/lib/etsy/country.rb +27 -0
  16. data/lib/etsy/favorite_listing.rb +26 -0
  17. data/lib/etsy/image.rb +44 -0
  18. data/lib/etsy/listing.rb +296 -0
  19. data/lib/etsy/model.rb +127 -0
  20. data/lib/etsy/payment_template.rb +33 -0
  21. data/lib/etsy/profile.rb +49 -0
  22. data/lib/etsy/receipt.rb +37 -0
  23. data/lib/etsy/request.rb +150 -0
  24. data/lib/etsy/response.rb +128 -0
  25. data/lib/etsy/section.rb +16 -0
  26. data/lib/etsy/secure_client.rb +131 -0
  27. data/lib/etsy/shipping_info.rb +27 -0
  28. data/lib/etsy/shipping_template.rb +41 -0
  29. data/lib/etsy/shop.rb +88 -0
  30. data/lib/etsy/transaction.rb +29 -0
  31. data/lib/etsy/user.rb +109 -0
  32. data/lib/etsy/variation/property_set.rb +71 -0
  33. data/lib/etsy/verification_request.rb +17 -0
  34. data/lib/etsy/version.rb +3 -0
  35. data/test/fixtures/about/getAbout.json +16 -0
  36. data/test/fixtures/address/getUserAddresses.json +12 -0
  37. data/test/fixtures/attribute_value/findAllListingPropertyValues.json +44 -0
  38. data/test/fixtures/category/findAllSubCategoryChildren.json +78 -0
  39. data/test/fixtures/category/findAllTopCategory.json +347 -0
  40. data/test/fixtures/category/findAllTopCategory.single.json +18 -0
  41. data/test/fixtures/category/findAllTopCategoryChildren.json +308 -0
  42. data/test/fixtures/category/getCategory.multiple.json +28 -0
  43. data/test/fixtures/category/getCategory.single.json +18 -0
  44. data/test/fixtures/country/getCountry.json +1 -0
  45. data/test/fixtures/favorite_listing/findAllFavoriteListings.json +1 -0
  46. data/test/fixtures/image/findAllListingImages.json +102 -0
  47. data/test/fixtures/listing/findAllListingActive.category.json +827 -0
  48. data/test/fixtures/listing/findAllShopListings.json +69 -0
  49. data/test/fixtures/listing/getListing.multiple.json +1 -0
  50. data/test/fixtures/listing/getListing.single.includeImages.json +1 -0
  51. data/test/fixtures/listing/getListing.single.json +1 -0
  52. data/test/fixtures/payment_template/getPaymentTemplate.json +1 -0
  53. data/test/fixtures/profile/new.json +28 -0
  54. data/test/fixtures/receipt/findAllShopReceipts.json +28 -0
  55. data/test/fixtures/section/getShopSection.json +18 -0
  56. data/test/fixtures/shipping_info/getShippingInfo.json +1 -0
  57. data/test/fixtures/shipping_template/getShippingTemplate.json +1 -0
  58. data/test/fixtures/shop/findAllShop.json +1 -0
  59. data/test/fixtures/shop/findAllShop.single.json +1 -0
  60. data/test/fixtures/shop/getShop.multiple.json +1 -0
  61. data/test/fixtures/shop/getShop.single.json +34 -0
  62. data/test/fixtures/transaction/findAllShopTransactions.json +1 -0
  63. data/test/fixtures/user/getUser.multiple.json +29 -0
  64. data/test/fixtures/user/getUser.single.json +13 -0
  65. data/test/fixtures/user/getUser.single.private.json +18 -0
  66. data/test/fixtures/user/getUser.single.withProfile.json +38 -0
  67. data/test/fixtures/user/getUser.single.withShops.json +41 -0
  68. data/test/test_helper.rb +45 -0
  69. data/test/unit/etsy/address_test.rb +61 -0
  70. data/test/unit/etsy/attribute_value_test.rb +67 -0
  71. data/test/unit/etsy/basic_client_test.rb +30 -0
  72. data/test/unit/etsy/category_test.rb +106 -0
  73. data/test/unit/etsy/country_test.rb +64 -0
  74. data/test/unit/etsy/favorite_listing_test.rb +44 -0
  75. data/test/unit/etsy/image_test.rb +51 -0
  76. data/test/unit/etsy/listing_test.rb +268 -0
  77. data/test/unit/etsy/model_test.rb +64 -0
  78. data/test/unit/etsy/payment_template_test.rb +68 -0
  79. data/test/unit/etsy/profile_test.rb +111 -0
  80. data/test/unit/etsy/receipt_test.rb +107 -0
  81. data/test/unit/etsy/request_test.rb +190 -0
  82. data/test/unit/etsy/response_test.rb +175 -0
  83. data/test/unit/etsy/section_test.rb +28 -0
  84. data/test/unit/etsy/secure_client_test.rb +132 -0
  85. data/test/unit/etsy/shipping_info_test.rb +24 -0
  86. data/test/unit/etsy/shipping_template_test.rb +24 -0
  87. data/test/unit/etsy/shop_about_test.rb +43 -0
  88. data/test/unit/etsy/shop_test.rb +116 -0
  89. data/test/unit/etsy/transaction_test.rb +61 -0
  90. data/test/unit/etsy/user_test.rb +250 -0
  91. data/test/unit/etsy/verification_request_test.rb +26 -0
  92. data/test/unit/etsy_test.rb +173 -0
  93. metadata +293 -0
@@ -0,0 +1,175 @@
1
+ require File.expand_path('../../../test_helper', __FILE__)
2
+
3
+ module Etsy
4
+ class ResponseTest < Test::Unit::TestCase
5
+
6
+ context "An instance of the Response class" do
7
+
8
+ should "be able to return the total" do
9
+ r = Response.new(stub(:body => '{ "count": 42 }'))
10
+
11
+ r.total.should == 42
12
+ end
13
+
14
+ should "be able to decode the JSON data to a hash" do
15
+ data = '{ "foo":"bar" }'
16
+
17
+ r = Response.new(stub(:body => data))
18
+ r.to_hash.should == {'foo' => 'bar'}
19
+ end
20
+
21
+ should "only decode the JSON data once" do
22
+ JSON.expects(:parse).once.returns({})
23
+
24
+ r = Response.new(stub(:body => '{ "foo":"bar" }'))
25
+ 2.times { r.to_hash }
26
+ end
27
+
28
+ should "have a record count when the response is not paginated" do
29
+ raw_response = mock
30
+ raw_response.stubs(:body => '{ "count": 1 }')
31
+ r = Response.new(raw_response)
32
+
33
+ r.count.should == 1
34
+ end
35
+
36
+ should "have a record count when the response is paginated" do
37
+ raw_response = mock
38
+ raw_response.stubs(:body => '{ "count": 100, "results": [{},{}], "pagination": {} }')
39
+ r = Response.new(raw_response)
40
+
41
+ r.count.should == 2
42
+ end
43
+
44
+ should "return a count of 0 when the response is paginated and the results are empty" do
45
+ raw_response = mock
46
+ raw_response.stubs(:body => '{ "count": 100, "results": null, "pagination": {} }')
47
+ r = Response.new(raw_response)
48
+
49
+ r.count.should == 0
50
+ end
51
+
52
+ should "return an array if there are multiple results entries" do
53
+ r = Response.new('')
54
+ r.expects(:code).with().returns('200')
55
+ r.expects(:count).with().returns(2)
56
+ r.expects(:to_hash).with().returns('results' => %w(one two))
57
+
58
+ r.result.should == %w(one two)
59
+ end
60
+
61
+ should "return a single value for results if there is only 1 result" do
62
+ r = Response.new('')
63
+ r.expects(:code).with().returns('200')
64
+ r.expects(:count).with().returns(1)
65
+ r.expects(:to_hash).with().returns('results' => ['foo'])
66
+
67
+ r.result.should == 'foo'
68
+ end
69
+
70
+ should "provide the complete raw body" do
71
+ raw_response = mock
72
+ raw_response.stubs(:body => "I am not JSON")
73
+ r = Response.new(raw_response)
74
+
75
+ r.body.should == 'I am not JSON'
76
+ end
77
+
78
+ should "raise an invalid JSON exception if the response is not json" do
79
+ raw_response = mock
80
+ raw_response.stubs(:body => "I am not JSON", :code => 500)
81
+ r = Response.new(raw_response)
82
+
83
+ exception = assert_raises(Etsy::EtsyJSONInvalid) { r.to_hash }
84
+ assert_equal( 500, exception.code )
85
+ assert_equal( "I am not JSON", exception.data )
86
+ end
87
+
88
+ should "raise OAuthTokenRevoked" do
89
+ raw_response = mock
90
+ raw_response.stubs(:body => "oauth_problem=token_revoked")
91
+ r = Response.new(raw_response)
92
+
93
+ lambda { r.to_hash }.should raise_error(Etsy::OAuthTokenRevoked)
94
+ end
95
+
96
+ should "raise MissingShopID" do
97
+ raw_response = mock
98
+ raw_response.stubs(:body => "something Shop with PK shop_id something")
99
+ r = Response.new(raw_response)
100
+
101
+ lambda { r.to_hash }.should raise_error(Etsy::MissingShopID)
102
+ end
103
+
104
+ should "raise InvalidUserID" do
105
+ raw_response = mock
106
+ raw_response.stubs(:body => "'someguy' is not a valid user_id")
107
+ r = Response.new(raw_response)
108
+
109
+ lambda { r.to_hash }.should raise_error(Etsy::InvalidUserID)
110
+ end
111
+
112
+ should "raise TemporaryIssue" do
113
+ raw_response = mock
114
+ raw_response.stubs(:body => "something Temporary Etsy issue something")
115
+ r = Response.new(raw_response)
116
+
117
+ lambda { r.to_hash }.should raise_error(Etsy::TemporaryIssue)
118
+ end
119
+
120
+ should "raise ResourceUnavailable" do
121
+ raw_response = mock
122
+ raw_response.stubs(:body => "something Resource temporarily unavailable something")
123
+ r = Response.new(raw_response)
124
+
125
+ lambda { r.to_hash }.should raise_error(Etsy::ResourceUnavailable)
126
+ end
127
+
128
+ should "raise ExceededRateLimit" do
129
+ raw_response = mock
130
+ raw_response.stubs(:body => "something You have exceeded your API limit something")
131
+ r = Response.new(raw_response)
132
+
133
+ lambda { r.to_hash }.should raise_error(Etsy::ExceededRateLimit)
134
+ end
135
+
136
+ should "provide the code" do
137
+ raw_response = mock
138
+ raw_response.expects(:code => "400")
139
+ r = Response.new(raw_response)
140
+
141
+ r.code.should == '400'
142
+ end
143
+
144
+ should "consider a code of 2xx successful" do
145
+ raw_response = mock
146
+
147
+ raw_response.expects(:code => "200")
148
+ r = Response.new(raw_response)
149
+ r.should be_success
150
+
151
+ raw_response.expects(:code => "201")
152
+ r = Response.new(raw_response)
153
+ r.should be_success
154
+ end
155
+
156
+ should "consider a code of 4xx unsuccessful" do
157
+ raw_response = mock
158
+
159
+ raw_response.expects(:code => "404")
160
+ r = Response.new(raw_response)
161
+ r.should_not be_success
162
+ end
163
+
164
+ should "consider a code of 5xx unsuccessful" do
165
+ raw_response = mock
166
+
167
+ raw_response.expects(:code => "500")
168
+ r = Response.new(raw_response)
169
+ r.should_not be_success
170
+ end
171
+ end
172
+
173
+
174
+ end
175
+ 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
@@ -0,0 +1,132 @@
1
+ require File.expand_path('../../../test_helper', __FILE__)
2
+
3
+ module Etsy
4
+ class SecureClientTest < Test::Unit::TestCase
5
+
6
+ context "An instance of the SecureClient class" do
7
+
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'
11
+ Etsy.stubs(:api_key).returns('key')
12
+ Etsy.stubs(:api_secret).returns('secret')
13
+ Etsy.stubs(:permission_scopes).returns(['scope_one', 'scope_two'])
14
+
15
+ OAuth::Consumer.stubs(:new).with('key', 'secret', {
16
+ :site => 'https://sandbox',
17
+ :request_token_path => '/v2/oauth/request_token?scope=scope_one+scope_two',
18
+ :access_token_path => '/v2/oauth/access_token',
19
+ }).returns('consumer')
20
+
21
+ client = SecureClient.new
22
+
23
+ client.consumer.should == 'consumer'
24
+ end
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 => 'https://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
+
46
+ should "be able to generate a request token" do
47
+ Etsy.stubs(:callback_url).with().returns('callback_url')
48
+ consumer = stub() {|c| c.stubs(:get_request_token).with(:oauth_callback => 'callback_url').returns('toke') }
49
+
50
+ client = SecureClient.new
51
+ client.stubs(:consumer).returns(consumer)
52
+
53
+ client.request_token.should == 'toke'
54
+ end
55
+
56
+ context "with request data" do
57
+ setup do
58
+ @client = SecureClient.new(:request_token => 'toke', :request_secret => 'secret', :verifier => 'verify')
59
+ @client.stubs(:consumer).returns('consumer')
60
+ end
61
+
62
+ should "be able to generate an oauth client" do
63
+ request_token = stub()
64
+ request_token.stubs(:get_access_token).with(:oauth_verifier => 'verify').returns('client')
65
+
66
+ OAuth::RequestToken.stubs(:new).with('consumer', 'toke', 'secret').returns(request_token)
67
+
68
+ @client.client_from_request_data.should == 'client'
69
+ end
70
+
71
+ should "know to generate a client from request data" do
72
+ @client.stubs(:client_from_request_data).returns('client')
73
+ @client.client.should == 'client'
74
+ end
75
+ end
76
+
77
+ context "with access data" do
78
+ setup do
79
+ @client = SecureClient.new(:access_token => 'toke', :access_secret => 'secret')
80
+ @client.stubs(:consumer).returns('consumer')
81
+ end
82
+
83
+ should "know the :access_token" do
84
+ @client.access_token.should == 'toke'
85
+ end
86
+
87
+ should "know the access secret" do
88
+ @client.access_secret.should == 'secret'
89
+ end
90
+
91
+ should "be able to generate an oauth client" do
92
+ OAuth::AccessToken.stubs(:new).with('consumer', 'toke', 'secret').returns('client')
93
+ @client.client_from_access_data.should == 'client'
94
+ end
95
+
96
+ should "be able to generate a client" do
97
+ @client.stubs(:client_from_access_data).returns('client')
98
+ @client.client.should == 'client'
99
+ end
100
+ end
101
+
102
+ context "with a client" do
103
+ setup do
104
+ @client = SecureClient.new
105
+ @client.stubs(:client).returns(stub(:token => 'toke', :secret => 'secret'))
106
+ end
107
+
108
+ should "know the access token" do
109
+ @client.access_token.should == 'toke'
110
+ end
111
+
112
+ should "know the access_secret" do
113
+ @client.access_secret.should == 'secret'
114
+ end
115
+ end
116
+
117
+ should "delegate :get to :client" do
118
+ url = 'http://etsy.com/'
119
+
120
+ oauth_client = stub()
121
+ oauth_client.stubs(:get).with(url).returns('something')
122
+
123
+ client = SecureClient.new
124
+ client.stubs(:client).returns(oauth_client)
125
+
126
+ client.get(url).should == 'something'
127
+ end
128
+
129
+ end
130
+
131
+ end
132
+ end
@@ -0,0 +1,24 @@
1
+ require File.expand_path('../../../test_helper', __FILE__)
2
+
3
+ module Etsy
4
+ class ShippingInfoTest < Test::Unit::TestCase
5
+ context "An instance of the ShippingInfo class" do
6
+ setup do
7
+ data = read_fixture('shipping_info/getShippingInfo.json')
8
+ @shipping_info = ShippingInfo.new(data.first)
9
+ end
10
+
11
+ should "have an id" do
12
+ @shipping_info.id.should == 212
13
+ end
14
+
15
+ should "have an title" do
16
+ @shipping_info.primary_cost.should == "$9.99"
17
+ end
18
+
19
+ should "have an listing_id" do
20
+ @shipping_info.listing_id.should == 14888443
21
+ end
22
+ end
23
+ end
24
+ end
@@ -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
@@ -0,0 +1,43 @@
1
+ require File.expand_path('../../../test_helper', __FILE__)
2
+
3
+ module Etsy
4
+ class AboutTest < Test::Unit::TestCase
5
+ context "An instance of the About class" do
6
+ setup do
7
+ data = read_fixture('about/getAbout.json')
8
+ @about = About.new(data.first)
9
+ end
10
+
11
+ should "have a shop id" do
12
+ @about.shop_id.should == 8740774
13
+ end
14
+
15
+ should "have a status" do
16
+ @about.status.should == "active"
17
+ end
18
+
19
+ should "have a story_headline" do
20
+ @about.story_headline.should == 'A shop long in the making...'
21
+ end
22
+
23
+ should "have a story_leading_paragraph" do
24
+ @about.story_leading_paragraph.should == 'This is the leading paragraph'
25
+ end
26
+
27
+ should "have a story" do
28
+ @about.story.should == "I grew up with strong women in my family who all had a love of creating. My mom and grandma always encouraged a lifelong love of creating Working with glass, wire, and mineral components brings back my graduate school days, when I studied these items from a scientific point-of-view. Here&#39;s hoping I can create something that gives you a little sparkle in your life!"
29
+ end
30
+
31
+ should "have a related_links" do
32
+ @about.related_links.should == {
33
+ "link-0"=> {"title"=> "facebook", "url"=> "https://www.facebook.com/pebbleplusmetal/"},
34
+ "link-1"=> {"title"=> "pinterest", "url"=> "https://www.pinterest.com/PebblePlusMetal/pebble%2Bmetal/"}
35
+ }
36
+ end
37
+
38
+ should "have a url" do
39
+ @about.url.should == 'https://www.etsy.com/shop/PebblePlusMetal/about'
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,116 @@
1
+ require File.expand_path('../../../test_helper', __FILE__)
2
+
3
+ module Etsy
4
+ class ShopTest < Test::Unit::TestCase
5
+
6
+ context "The Shop class" do
7
+
8
+ should "be able to find a single shop" do
9
+ shops = mock_request('/shops/littletjane', {}, 'Shop', 'getShop.single.json')
10
+ Shop.find('littletjane').should == shops.first
11
+ end
12
+
13
+ should "be able to find multiple shops" do
14
+ shops = mock_request('/shops/littletjane,reagent', {}, 'Shop', 'getShop.multiple.json')
15
+ Shop.find('littletjane', 'reagent').should == shops
16
+ end
17
+
18
+ should "be able to find all shops" do
19
+ shops = mock_request('/shops', {}, 'Shop', 'findAllShop.json')
20
+ Shop.all.should == shops
21
+ end
22
+
23
+ should "return an array of shops if there is only 1 result returned" do
24
+ shops = mock_request('/shops', {}, 'Shop', 'findAllShop.single.json')
25
+ Shop.all.should == shops
26
+ end
27
+
28
+ should "allow a configurable limit when finding all shops" do
29
+ shops = mock_request('/shops', {:limit => 100, :offset => 0}, 'Shop', 'findAllShop.json')
30
+ Shop.all(:limit => 100).should == shops
31
+ end
32
+
33
+ end
34
+
35
+ context "An instance of the Shop class" do
36
+
37
+ context "with response data" do
38
+ setup do
39
+ data = read_fixture('shop/getShop.single.json')
40
+ @shop = Shop.new(data.first)
41
+ end
42
+
43
+ should "have a value for :id" do
44
+ @shop.id.should == 5500349
45
+ end
46
+
47
+ should "have a value for :user_id" do
48
+ @shop.user_id.should == 5327518
49
+ end
50
+
51
+ should "have a value for :image_url" do
52
+ @shop.image_url.should == "http://ny-image3.etsy.com/iusb_760x100.8484779.jpg"
53
+ end
54
+
55
+ should "have a value for :icon_url" do
56
+ @shop.icon_url.should == "https://img0.etsystatic.com/173/0/8740774/isla_fullxfull.22739584_nydzpho0.jpg"
57
+ end
58
+
59
+ should "have a value for :url" do
60
+ @shop.url.should == "http://www.etsy.com/shop/littletjane"
61
+ end
62
+
63
+ should "have a value for :favorers_count" do
64
+ @shop.favorers_count.should == 684
65
+ end
66
+
67
+ should "have a value for :active_listings_count" do
68
+ @shop.active_listings_count.should == 0
69
+ end
70
+
71
+ should "have a value for :updated_at" do
72
+ @shop.updated_at.should == Time.at(1274923984)
73
+ end
74
+
75
+ should "have a value for :created_at" do
76
+ @shop.created_at.should == Time.at(1237430331)
77
+ end
78
+
79
+ should "have a value for :name" do
80
+ @shop.name.should == "littletjane"
81
+ end
82
+
83
+ should "have a value for :title" do
84
+ @shop.title.should == "a cute and crafty mix of handmade goods."
85
+ end
86
+
87
+ should "have a value for :message" do
88
+ @shop.message.should == "thanks!"
89
+ end
90
+
91
+ should "have a value for :announcement" do
92
+ @shop.announcement.should == "announcement"
93
+ end
94
+
95
+ end
96
+
97
+ should "have a collection of listings" do
98
+ shop = Shop.new
99
+ shop.stubs(:id).with().returns(1)
100
+
101
+ Listing.stubs(:find_all_by_shop_id).with(1, {}).returns('listings')
102
+
103
+ shop.listings.should == 'listings'
104
+ end
105
+
106
+ should "have an About object" do
107
+ shop = Shop.new
108
+
109
+ About.stubs(:find_by_shop).with(shop).returns('about')
110
+
111
+ shop.about.should == 'about'
112
+ end
113
+ end
114
+
115
+ end
116
+ end