goodreads 0.2.1 → 0.2.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.
- data/.travis.yml +1 -1
- data/Gemfile +2 -3
- data/README.md +111 -48
- data/examples/oauth.md +57 -0
- data/goodreads.gemspec +6 -6
- data/lib/goodreads/client/authors.rb +8 -0
- data/lib/goodreads/client/friends.rb +12 -0
- data/lib/goodreads/client/groups.rb +15 -0
- data/lib/goodreads/client.rb +10 -6
- data/lib/goodreads/request.rb +16 -11
- data/lib/goodreads/version.rb +1 -1
- data/spec/client_spec.rb +265 -151
- data/spec/fixtures/author.xml +1 -1
- data/spec/fixtures/author_by_name.xml +17 -0
- data/spec/fixtures/friends.xml +30 -0
- data/spec/fixtures/group.xml +364 -0
- data/spec/fixtures/group_list.xml +422 -0
- data/spec/goodreads_spec.rb +14 -14
- metadata +102 -98
data/spec/client_spec.rb
CHANGED
@@ -2,181 +2,295 @@ require 'spec_helper'
|
|
2
2
|
require 'oauth'
|
3
3
|
|
4
4
|
describe 'Client' do
|
5
|
-
|
6
|
-
|
7
|
-
@client = Goodreads::Client.new(:api_key => 'SECRET_KEY')
|
8
|
-
end
|
9
|
-
|
10
|
-
it 'raises error on invalid config parameter' do
|
11
|
-
proc { Goodreads::Client.new(nil) }.
|
12
|
-
should raise_error ArgumentError, "Options hash required."
|
13
|
-
|
14
|
-
proc { Goodreads::Client.new('foo') }.
|
15
|
-
should raise_error ArgumentError, "Options hash required."
|
16
|
-
end
|
5
|
+
let(:client) { Goodreads::Client.new(:api_key => 'SECRET_KEY') }
|
6
|
+
before(:each) { Goodreads.reset_configuration }
|
17
7
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
proc { @client.book('6732019') }.should_not raise_error
|
8
|
+
describe '#new' do
|
9
|
+
it 'requires an argument' do
|
10
|
+
expect { Goodreads::Client.new(nil) }.
|
11
|
+
to raise_error ArgumentError, "Options hash required."
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'requires a hash argument' do
|
15
|
+
expect { Goodreads::Client.new('foo') }.
|
16
|
+
to raise_error ArgumentError, "Options hash required."
|
17
|
+
end
|
29
18
|
end
|
30
|
-
|
31
|
-
|
32
|
-
stub_with_key_get('/book/
|
33
|
-
|
19
|
+
|
20
|
+
describe '#book_by_isbn' do
|
21
|
+
before { stub_with_key_get('/book/isbn', {:isbn => '0307463745'}, 'book.xml') }
|
22
|
+
|
23
|
+
it 'returns a book by isbn' do
|
24
|
+
book = client.book_by_isbn('0307463745')
|
25
|
+
|
26
|
+
book.should respond_to :id
|
27
|
+
book.should respond_to :title
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'when book does not exist' do
|
31
|
+
before do
|
32
|
+
stub_request(:get, "http://www.goodreads.com/book/isbn?format=xml&isbn=123456789&key=SECRET_KEY").
|
33
|
+
to_return(:status => 404, :body => "", :headers => {})
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'raises Goodreads::NotFound' do
|
37
|
+
expect { client.book_by_isbn('123456789') }.to raise_error Goodreads::NotFound
|
38
|
+
end
|
39
|
+
end
|
34
40
|
end
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
+
|
42
|
+
describe '#search_books' do
|
43
|
+
before { stub_with_key_get('/search/index', {:q => 'Rework'}, 'search_books_by_name.xml') }
|
44
|
+
|
45
|
+
it 'returns book search results' do
|
46
|
+
result = client.search_books('Rework')
|
47
|
+
|
48
|
+
result.should be_a Hashie::Mash
|
49
|
+
result.should respond_to :query
|
50
|
+
result.should respond_to :total_results
|
51
|
+
result.should respond_to :results
|
52
|
+
result.results.should respond_to :work
|
53
|
+
result.query.should eq 'Rework'
|
54
|
+
result.results.work.size.should eq 3
|
55
|
+
result.results.work.first.id.should eq 6928276
|
56
|
+
end
|
41
57
|
end
|
42
|
-
|
43
|
-
|
44
|
-
stub_with_key_get('/
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
@reviews.size.should_not == 0
|
49
|
-
@reviews.each do |r|
|
50
|
-
r.respond_to?(:id).should == true
|
58
|
+
|
59
|
+
describe '#book' do
|
60
|
+
before { stub_with_key_get('/book/show', {:id => '6732019'}, 'book.xml') }
|
61
|
+
|
62
|
+
it 'returns a book by goodreads id' do
|
63
|
+
expect { client.book('6732019') }.not_to raise_error
|
51
64
|
end
|
52
65
|
end
|
53
|
-
|
54
|
-
|
55
|
-
stub_with_key_get('/
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
@reviews.size.should_not == 0
|
60
|
-
@reviews.each do |r|
|
61
|
-
r.respond_to?(:id).should == true
|
66
|
+
|
67
|
+
describe '#book_by_title' do
|
68
|
+
before { stub_with_key_get('/book/title', {:title => 'Rework'}, 'book.xml') }
|
69
|
+
|
70
|
+
it 'returns a book by title' do
|
71
|
+
expect { client.book_by_title('Rework') }.not_to raise_error
|
62
72
|
end
|
63
73
|
end
|
74
|
+
|
75
|
+
describe '#recent_reviews' do
|
76
|
+
before { stub_with_key_get('/review/recent_reviews', {}, 'recent_reviews.xml') }
|
77
|
+
|
78
|
+
it 'returns recent reviews' do
|
79
|
+
reviews = client.recent_reviews
|
80
|
+
|
81
|
+
reviews.should be_an Array
|
82
|
+
reviews.should_not be_empty
|
83
|
+
reviews.first.should respond_to :id
|
84
|
+
end
|
85
|
+
|
86
|
+
context 'with :skip_cropped => true' do
|
87
|
+
before { stub_with_key_get('/review/recent_reviews', {}, 'recent_reviews.xml') }
|
64
88
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
@review.id.should == '166204831'
|
89
|
+
it 'returns only full reviews' do
|
90
|
+
reviews = client.recent_reviews(:skip_cropped => true)
|
91
|
+
reviews.should be_an Array
|
92
|
+
reviews.should_not be_empty
|
93
|
+
end
|
94
|
+
end
|
72
95
|
end
|
73
|
-
|
74
|
-
it 'raises Goodreads::NotFound if review was not found' do
|
75
|
-
stub_request(:get, "http://www.goodreads.com/review/show?format=xml&id=12345&key=SECRET_KEY").
|
76
|
-
to_return(:status => 404, :body => "", :headers => {})
|
77
96
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
97
|
+
describe '#review' do
|
98
|
+
before { stub_with_key_get('/review/show', {:id => '166204831'}, 'review.xml') }
|
99
|
+
|
100
|
+
it 'returns review details' do
|
101
|
+
review = client.review('166204831')
|
102
|
+
|
103
|
+
review.should be_a Hashie::Mash
|
104
|
+
review.id.should eq '166204831'
|
105
|
+
end
|
106
|
+
|
107
|
+
context 'when review does not exist' do
|
108
|
+
before do
|
109
|
+
stub_request(:get, "http://www.goodreads.com/review/show?format=xml&id=12345&key=SECRET_KEY").
|
110
|
+
to_return(:status => 404, :body => "", :headers => {})
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'raises Goodreads::NotFound' do
|
114
|
+
expect { client.review('12345') }.to raise_error Goodreads::NotFound
|
115
|
+
end
|
116
|
+
end
|
89
117
|
end
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
118
|
+
|
119
|
+
describe '#author' do
|
120
|
+
before { stub_with_key_get('/author/show', {:id => '18541'}, 'author.xml') }
|
121
|
+
|
122
|
+
it 'returns author details' do
|
123
|
+
author = client.author('18541')
|
124
|
+
|
125
|
+
author.should be_a Hashie::Mash
|
126
|
+
author.id.should eq '18541'
|
127
|
+
author.name.should eq "Tim O'Reilly"
|
128
|
+
author.link.should eq 'http://www.goodreads.com/author/show/18541.Tim_O_Reilly'
|
129
|
+
author.fans_count.should eq 109
|
130
|
+
author.image_url.should eq 'http://photo.goodreads.com/authors/1199698411p5/18541.jpg'
|
131
|
+
author.small_image_url.should eq 'http://photo.goodreads.com/authors/1199698411p2/18541.jpg'
|
132
|
+
author.about.should eq ''
|
133
|
+
author.influences.should eq ''
|
134
|
+
author.works_count.should eq '34'
|
135
|
+
author.gender.should eq 'male'
|
136
|
+
author.hometown.should eq 'Cork'
|
137
|
+
author.born_at.should eq '1954/06/06'
|
138
|
+
author.died_at.should be_nil
|
139
|
+
end
|
140
|
+
|
141
|
+
context 'when author does not exist' do
|
142
|
+
before do
|
143
|
+
stub_request(:get, "http://www.goodreads.com/author/show?format=xml&id=12345&key=SECRET_KEY").
|
144
|
+
to_return(:status => 404, :body => "", :headers => {})
|
145
|
+
end
|
146
|
+
|
147
|
+
it 'raises Goodreads::NotFound' do
|
148
|
+
expect { client.author('12345') }.to raise_error Goodreads::NotFound
|
149
|
+
end
|
150
|
+
end
|
96
151
|
end
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
152
|
+
|
153
|
+
describe '#author_by_name' do
|
154
|
+
before do
|
155
|
+
stub_with_key_get('/api/author_url', {:id => 'Orson Scott Card'}, 'author_by_name.xml')
|
156
|
+
end
|
157
|
+
|
158
|
+
it 'returns author details' do
|
159
|
+
author = client.author_by_name('Orson Scott Card')
|
160
|
+
|
161
|
+
author.should be_a Hashie::Mash
|
162
|
+
author.id.should eq '589'
|
163
|
+
author.name.should eq 'Orson Scott Card'
|
164
|
+
author.link.should eq 'http://www.goodreads.com/author/show/589.Orson_Scott_Card?utm_medium=api&utm_source=author_link'
|
165
|
+
end
|
107
166
|
end
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
167
|
+
|
168
|
+
describe '#user' do
|
169
|
+
before { stub_with_key_get('/user/show', {:id => '878044'}, 'user.xml') }
|
170
|
+
|
171
|
+
it 'returns user details' do
|
172
|
+
user = client.user('878044')
|
173
|
+
|
174
|
+
user.should be_a Hashie::Mash
|
175
|
+
user.id.should eq '878044'
|
176
|
+
user.name.should eq 'Jan'
|
177
|
+
user.user_name.should eq 'janmt'
|
178
|
+
end
|
179
|
+
|
180
|
+
context 'when user does not exist' do
|
181
|
+
before do
|
182
|
+
stub_request(:get, "http://www.goodreads.com/user/show?format=xml&id=12345&key=SECRET_KEY").
|
183
|
+
to_return(:status => 404, :body => "", :headers => {})
|
184
|
+
end
|
185
|
+
|
186
|
+
it 'raises Goodreads::NotFound' do
|
187
|
+
expect { client.user('12345') }.to raise_error Goodreads::NotFound
|
188
|
+
end
|
189
|
+
end
|
114
190
|
end
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
@search.results.work.first.id.should == 6928276
|
191
|
+
|
192
|
+
describe '#friends' do
|
193
|
+
before { client.stub(:oauth_request).and_return(Hash.from_xml(fixture('friends.xml'))['GoodreadsResponse']) }
|
194
|
+
|
195
|
+
it 'returns friend details' do
|
196
|
+
friends = client.friends('878044')
|
197
|
+
|
198
|
+
friends.should be_an_instance_of Hashie::Mash
|
199
|
+
friends.should respond_to :user
|
200
|
+
friends.user.size.should eq friends.end.to_i
|
201
|
+
friends.user.first.should respond_to :name
|
202
|
+
end
|
128
203
|
end
|
129
204
|
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
205
|
+
describe '#shelf' do
|
206
|
+
it "returns list of books for a user's specified shelf" do
|
207
|
+
stub_with_key_get('/review/list/1.xml', {:shelf => 'to-read', :v => '2'}, 'to-read.xml')
|
208
|
+
|
209
|
+
shelf = client.shelf('1', 'to-read')
|
210
|
+
|
211
|
+
shelf.should respond_to :start
|
212
|
+
shelf.should respond_to :end
|
213
|
+
shelf.should respond_to :total
|
214
|
+
shelf.should respond_to :books
|
215
|
+
|
216
|
+
shelf.start.should eq 1
|
217
|
+
shelf.end.should eq 20
|
218
|
+
shelf.total.should eq 40
|
219
|
+
shelf.books.length.should eq 20
|
220
|
+
shelf.books.first.id.should eq '45590939'
|
221
|
+
shelf.books.first.book.title.strip.should eq 'The Demon-Haunted World: Science as a Candle in the Dark'
|
222
|
+
end
|
223
|
+
|
224
|
+
it "paginates book lists from a user's shelf" do
|
225
|
+
stub_with_key_get('/review/list/1.xml', {:shelf => 'to-read', :v => '2', :page => '2'}, 'to-read-p2.xml')
|
226
|
+
|
227
|
+
shelf = client.shelf('1', 'to-read', :page => 2)
|
228
|
+
|
229
|
+
shelf.start.should eq 21
|
230
|
+
shelf.end.should eq 40
|
231
|
+
shelf.total.should eq 40
|
232
|
+
shelf.books.length.should eq 20
|
233
|
+
shelf.books.first.id.should eq '107804211'
|
234
|
+
shelf.books.first.book.title.should match /Your Money or Your Life/
|
235
|
+
end
|
236
|
+
|
237
|
+
it "returns an empty array when shelf is empty" do
|
238
|
+
stub_with_key_get('/review/list/1.xml', {:shelf => 'to-read', :v => '2'}, 'empty.xml')
|
239
|
+
|
240
|
+
shelf = client.shelf('1', 'to-read')
|
241
|
+
|
242
|
+
shelf.start.should eq 0
|
243
|
+
shelf.end.should eq 0
|
244
|
+
shelf.total.should eq 0
|
245
|
+
shelf.books.length.should eq 0
|
246
|
+
end
|
146
247
|
end
|
147
248
|
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
249
|
+
describe '#user_id' do
|
250
|
+
let(:consumer) { OAuth::Consumer.new('API_KEY', 'SECRET_KEY', :site => 'http://www.goodreads.com') }
|
251
|
+
let(:token) { OAuth::AccessToken.new(consumer, 'ACCESS_TOKEN', 'ACCESS_SECRET') }
|
252
|
+
|
253
|
+
before do
|
254
|
+
stub_request(:get, "http://www.goodreads.com/api/auth_user").
|
255
|
+
to_return(:status => 200, :body => fixture('oauth_response.xml'), :headers => {})
|
256
|
+
end
|
257
|
+
|
258
|
+
it 'returns id of the user with oauth authentication' do
|
259
|
+
client = Goodreads::Client.new(:api_key => 'SECRET_KEY', :oauth_token => token)
|
260
|
+
client.user_id.should eq '2003928'
|
261
|
+
end
|
159
262
|
end
|
160
263
|
|
161
|
-
|
162
|
-
stub_with_key_get('/
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
264
|
+
describe '#group' do
|
265
|
+
before { stub_with_key_get('/group/show', {:id => '1'}, 'group.xml') }
|
266
|
+
|
267
|
+
it "returns group details" do
|
268
|
+
group = client.group('1')
|
269
|
+
|
270
|
+
group.should be_a Hashie::Mash
|
271
|
+
group.id.should eq '1'
|
272
|
+
group.title.should eq 'Goodreads Feedback'
|
273
|
+
group.access.should eq 'public'
|
274
|
+
group.location.should eq ''
|
275
|
+
group.category.should eq 'Business'
|
276
|
+
group.subcategory.should eq 'Companies'
|
277
|
+
group.group_users_count.should eq '10335'
|
278
|
+
end
|
170
279
|
end
|
171
280
|
|
172
|
-
|
173
|
-
|
174
|
-
:status => 200, :body => fixture('oauth_response.xml'), :headers => {})
|
281
|
+
describe '#group_list' do
|
282
|
+
before { stub_with_key_get('/group/list', {:id => '1', :sort => 'my_activity'}, 'group_list.xml') }
|
175
283
|
|
176
|
-
|
177
|
-
|
284
|
+
it "returns groups a given user is a member of" do
|
285
|
+
group_list = client.group_list('1')
|
178
286
|
|
179
|
-
|
180
|
-
|
287
|
+
group_list.should be_a Hashie::Mash
|
288
|
+
group_list.total.should eq '107'
|
289
|
+
group_list.group.count.should eq 50
|
290
|
+
group_list.group[0].id.should eq '1'
|
291
|
+
group_list.group[0].title.should eq 'Goodreads Feedback'
|
292
|
+
group_list.group[1].id.should eq '220'
|
293
|
+
group_list.group[2].users_count.should eq '530'
|
294
|
+
end
|
181
295
|
end
|
182
296
|
end
|
data/spec/fixtures/author.xml
CHANGED
@@ -0,0 +1,17 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<GoodreadsResponse>
|
3
|
+
<Request>
|
4
|
+
<authentication>true</authentication>
|
5
|
+
<key><![CDATA[SECRET_KEY]]></key>
|
6
|
+
<method><![CDATA[api_author_link]]></method>
|
7
|
+
</Request>
|
8
|
+
|
9
|
+
|
10
|
+
<author id="589">
|
11
|
+
<name><![CDATA[Orson Scott Card]]></name>
|
12
|
+
<link>http://www.goodreads.com/author/show/589.Orson_Scott_Card?utm_medium=api&utm_source=author_link</link>
|
13
|
+
</author>
|
14
|
+
|
15
|
+
|
16
|
+
|
17
|
+
</GoodreadsResponse>
|
@@ -0,0 +1,30 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<GoodreadsResponse>
|
3
|
+
<Request>
|
4
|
+
<authentication>true</authentication>
|
5
|
+
<key><![CDATA[SECRET_KEY]]></key>
|
6
|
+
<method><![CDATA[friend_user]]></method>
|
7
|
+
</Request>
|
8
|
+
<friends start="1" end="2" total="2">
|
9
|
+
<user>
|
10
|
+
<id>1421455</id>
|
11
|
+
<name>Amy Chamberlain</name>
|
12
|
+
<link><![CDATA[http://www.goodreads.com/user/show/1421455-amy-chamberlain]]></link>
|
13
|
+
<image_url><![CDATA[http://d.gr-assets.com/users/1315014486p3/1421455.jpg]]></image_url>
|
14
|
+
<small_image_url><![CDATA[http://d.gr-assets.com/users/1315014486p2/1421455.jpg]]></small_image_url>
|
15
|
+
<friends_count>29</friends_count>
|
16
|
+
<reviews_count>475</reviews_count>
|
17
|
+
<created_at>Sun Mar 20 19:39:06 -0700 2011</created_at>
|
18
|
+
</user>
|
19
|
+
<user>
|
20
|
+
<id>17764795</id>
|
21
|
+
<name>Lisa Teran</name>
|
22
|
+
<link><![CDATA[http://www.goodreads.com/user/show/17764795-lisa-teran]]></link>
|
23
|
+
<image_url><![CDATA[http://d.gr-assets.com/users/1361688877p3/17764795.jpg]]></image_url>
|
24
|
+
<small_image_url><![CDATA[http://d.gr-assets.com/users/1361688877p2/17764795.jpg]]></small_image_url>
|
25
|
+
<friends_count>35</friends_count>
|
26
|
+
<reviews_count>5</reviews_count>
|
27
|
+
<created_at>Sat Feb 23 22:53:57 -0800 2013</created_at>
|
28
|
+
</user>
|
29
|
+
</friends>
|
30
|
+
</GoodreadsResponse>
|