kippt 2.0.1 → 3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +15 -0
  2. data/.travis.yml +1 -4
  3. data/CHANGELOG.md +24 -0
  4. data/Gemfile +4 -0
  5. data/README.md +14 -4
  6. data/TODO.md +16 -0
  7. data/lib/kippt.rb +8 -3
  8. data/lib/kippt/client.rb +6 -6
  9. data/lib/kippt/clip.rb +17 -9
  10. data/lib/kippt/clip_collection.rb +2 -2
  11. data/lib/kippt/clip_likes.rb +29 -0
  12. data/lib/kippt/clips.rb +8 -37
  13. data/lib/kippt/collection.rb +1 -2
  14. data/lib/kippt/collection_resource.rb +39 -55
  15. data/lib/kippt/comment.rb +2 -4
  16. data/lib/kippt/comment_collection.rb +1 -2
  17. data/lib/kippt/comments.rb +5 -3
  18. data/lib/kippt/connection.rb +7 -3
  19. data/lib/kippt/favorite.rb +46 -0
  20. data/lib/kippt/favorites.rb +20 -0
  21. data/lib/kippt/followers.rb +6 -4
  22. data/lib/kippt/following.rb +6 -4
  23. data/lib/kippt/helpers.rb +17 -0
  24. data/lib/kippt/like.rb +4 -6
  25. data/lib/kippt/like_collection.rb +11 -0
  26. data/lib/kippt/likes.rb +2 -30
  27. data/lib/kippt/list.rb +8 -2
  28. data/lib/kippt/list_collection.rb +2 -2
  29. data/lib/kippt/lists.rb +2 -4
  30. data/lib/kippt/read_collection_resource.rb +43 -0
  31. data/lib/kippt/root_clips.rb +39 -0
  32. data/lib/kippt/saves.rb +4 -3
  33. data/lib/kippt/user.rb +10 -6
  34. data/lib/kippt/user_clips.rb +6 -26
  35. data/lib/kippt/user_collection.rb +0 -3
  36. data/lib/kippt/user_likes.rb +29 -0
  37. data/lib/kippt/user_lists.rb +0 -5
  38. data/lib/kippt/users.rb +3 -8
  39. data/lib/kippt/version.rb +1 -1
  40. data/spec/kippt/client_spec.rb +36 -2
  41. data/spec/kippt/clip_likes_spec.rb +14 -0
  42. data/spec/kippt/clip_spec.rb +89 -3
  43. data/spec/kippt/clips_spec.rb +27 -5
  44. data/spec/kippt/comment_spec.rb +1 -1
  45. data/spec/kippt/comments_spec.rb +30 -5
  46. data/spec/kippt/favorite_spec.rb +38 -0
  47. data/spec/kippt/favorites_spec.rb +18 -0
  48. data/spec/kippt/follow_relationship_spec.rb +30 -0
  49. data/spec/kippt/followers_spec.rb +6 -9
  50. data/spec/kippt/following_spec.rb +6 -9
  51. data/spec/kippt/like_spec.rb +38 -0
  52. data/spec/kippt/likes_spec.rb +21 -0
  53. data/spec/kippt/list_spec.rb +43 -10
  54. data/spec/kippt/lists_spec.rb +12 -0
  55. data/spec/kippt/saves_spec.rb +3 -3
  56. data/spec/kippt/user_clips_spec.rb +14 -2
  57. data/spec/kippt/user_likes_spec.rb +14 -0
  58. data/spec/kippt/user_lists_spec.rb +12 -0
  59. data/spec/kippt/user_spec.rb +11 -0
  60. data/spec/kippt/users_spec.rb +2 -1
  61. data/spec/shared_examples/collection.rb +117 -0
  62. data/spec/shared_examples/collection_resource.rb +13 -0
  63. data/spec/shared_examples/read_collection_resource.rb +77 -0
  64. data/spec/shared_examples/resource.rb +80 -0
  65. data/spec/spec_helper.rb +2 -298
  66. metadata +33 -26
  67. data/lib/core_ext/open_struct.rb +0 -5
@@ -0,0 +1,117 @@
1
+ shared_examples_for "collection" do
2
+ it "is Enumberable" do
3
+ subject.should be_a(Enumerable)
4
+ end
5
+
6
+ describe "#offset" do
7
+ it "returns offset of the results" do
8
+ subject.offset.should eq 0
9
+ end
10
+ end
11
+
12
+ describe "#limit" do
13
+ it "returns limit of the results" do
14
+ subject.limit.should eq 20
15
+ end
16
+ end
17
+
18
+ describe "#objects" do
19
+ it "returns the objects generated from the data" do
20
+ subject.objects.each do |object|
21
+ object.should be_a(subject.object_class)
22
+ end
23
+ end
24
+ end
25
+
26
+ describe "#[]" do
27
+ it "returns a object by index" do
28
+ subject[0].id.should eq data["objects"][0]["id"]
29
+ end
30
+ end
31
+
32
+ describe "#each" do
33
+ it "loops through the objects" do
34
+ ids = []
35
+ subject.each {|object| ids << object.id }
36
+ ids.should eq data["objects"].map { |node| node["id"] }
37
+ end
38
+ end
39
+
40
+ describe "#next_page?" do
41
+ context "there is a next page" do
42
+ it "returns url of the page" do
43
+ subject_with_multiple_pages.next_page?.should eq data_with_multiple_pages["meta"]["next"]
44
+ end
45
+ end
46
+
47
+ context "there is no next page" do
48
+ it "returns nil" do
49
+ subject.next_page?.should eq nil
50
+ end
51
+ end
52
+ end
53
+
54
+ describe "#next_page" do
55
+ context "if there is a next page" do
56
+ let(:collection_resource) { stub }
57
+
58
+ it "gets the next page of results from the collection resource" do
59
+ client.stub(:collection_resource_for).and_return(collection_resource)
60
+
61
+ results = stub
62
+ collection_resource.should_receive(:collection_from_url).
63
+ with(data_with_multiple_pages["meta"]["next"]).
64
+ and_return(results)
65
+
66
+ subject_with_multiple_pages.next_page.should eq results
67
+ end
68
+ end
69
+
70
+ context "if there is no next page" do
71
+ it "raises an error" do
72
+ lambda {
73
+ subject.next_page
74
+ }.should raise_error(Kippt::APIError, "There is no next page")
75
+ end
76
+ end
77
+ end
78
+
79
+ describe "#previous_page?" do
80
+ context "there is a previous page" do
81
+ it "returns url of the page" do
82
+ subject_with_multiple_pages.previous_page?.should eq data_with_multiple_pages["meta"]["previous"]
83
+ end
84
+ end
85
+
86
+ context "there is no previous page" do
87
+ it "returns nil" do
88
+ subject.previous_page?.should be_nil
89
+ end
90
+ end
91
+ end
92
+
93
+ describe "#previous_page" do
94
+ context "if there is a previous page" do
95
+ let(:collection_resource) { stub }
96
+
97
+ it "gets the previous page of results from the collection resource" do
98
+ client.stub(:collection_resource_for).and_return(collection_resource)
99
+
100
+ results = stub
101
+ collection_resource.should_receive(:collection_from_url).
102
+ with(data_with_multiple_pages["meta"]["previous"]).
103
+ and_return(results)
104
+
105
+ subject_with_multiple_pages.previous_page.should eq results
106
+ end
107
+ end
108
+
109
+ context "if there is no previous page" do
110
+ it "raises an error" do
111
+ lambda {
112
+ subject.previous_page
113
+ }.should raise_error(Kippt::APIError, "There is no previous page")
114
+ end
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,13 @@
1
+ shared_examples_for "collection resource" do
2
+ it_behaves_like "read collection resource"
3
+
4
+ describe "#create" do
5
+ let(:resource) { double :resource }
6
+
7
+ it "builds and saves a resource" do
8
+ resource.should_receive :save
9
+ subject.should_receive(:build).with(:an => "attribute").and_return(resource)
10
+ subject.create(:an => "attribute")
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,77 @@
1
+ shared_examples_for "read collection resource" do
2
+
3
+ describe "#fetch" do
4
+ it "returns collection class" do
5
+ stub_get("/#{base_uri}").
6
+ to_return(:status => 200, :body => fixture("#{collection_fixture}.json"))
7
+ all_resources = subject.fetch
8
+ all_resources.is_a? collection_class
9
+ end
10
+
11
+ it "accepts limit and offset options" do
12
+ stub_get("/#{base_uri}?limit=10&offset=100").
13
+ to_return(:status => 200, :body => fixture("#{collection_fixture}.json"))
14
+ resources = subject.fetch(:limit => 10, :offset => 100)
15
+ end
16
+
17
+ context "when passed unrecognized arguments" do
18
+ it "raises error" do
19
+ lambda {
20
+ subject.fetch(:foobar => true)
21
+ }.should raise_error(
22
+ ArgumentError, "Unrecognized argument: foobar")
23
+ end
24
+ end
25
+ end
26
+
27
+ describe "#[]" do
28
+ it "fetches single resource" do
29
+ stub_get("/#{base_uri}/10").
30
+ to_return(:status => 200, :body => fixture("#{singular_fixture}.json"))
31
+ subject[10].id.should eq 10
32
+ end
33
+
34
+ it "returns resource" do
35
+ stub_get("/#{base_uri}/10").
36
+ to_return(:status => 200, :body => fixture("#{singular_fixture}.json"))
37
+ subject[10].should be_a(resource_class)
38
+ end
39
+
40
+ context "when resource is not found" do
41
+ it "raises exception" do
42
+ stub_get("/#{base_uri}/10").
43
+ to_return(:status => 404, :body => {"message" => "Resource not found."})
44
+ lambda {
45
+ subject[10]
46
+ }.should raise_error(
47
+ Kippt::APIError, "Resource could not be loaded: Resource not found.")
48
+ end
49
+ end
50
+ end
51
+
52
+ describe "#find" do
53
+ it "exists" do
54
+ subject.respond_to?(:find).should be_true
55
+ end
56
+ end
57
+
58
+ describe "#collection_from_url" do
59
+ it "returns a new collection" do
60
+ stub_get("/#{base_uri}/?limit=20&offset=20").
61
+ to_return(:status => 200, :body => fixture("#{collection_fixture}.json"))
62
+ collection = subject.collection_from_url("/api/#{base_uri}/?limit=20&offset=20")
63
+ collection.should be_a(collection_class)
64
+ end
65
+
66
+ context "when passed URL is blank" do
67
+ it "raises ArgumentError" do
68
+ lambda {
69
+ subject.collection_from_url("")
70
+ }.should raise_error(ArgumentError, "The parameter URL can't be blank")
71
+ lambda {
72
+ subject.collection_from_url(nil)
73
+ }.should raise_error(ArgumentError, "The parameter URL can't be blank")
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,80 @@
1
+ shared_examples_for "resource" do
2
+ describe "attribute accessors" do
3
+ it "delegates to attributes" do
4
+ attributes.each do |attribute_name|
5
+ subject.send(attribute_name).should eq data[attribute_name.to_s]
6
+ end
7
+ end
8
+ end
9
+
10
+ describe "mapped attribute accessors" do
11
+ it "delegates to attributes and wraps with to a object" do
12
+ mapped_attributes.each do |attribute_name, attribute_class|
13
+ subject.send(attribute_name).class.to_s.should eq attribute_class
14
+ end
15
+ end
16
+ end
17
+
18
+ describe "#destroy" do
19
+ let(:collection_resource) { stub }
20
+
21
+ it "sends delete request to the server" do
22
+ client.stub(:collection_resource_for).and_return(collection_resource)
23
+ collection_resource.should_receive(:destroy_resource).with(subject).and_return(true)
24
+ subject.destroy.should be_true
25
+ end
26
+ end
27
+
28
+ describe "#save" do
29
+ context "with valid parameters" do
30
+ let(:collection_resource) { stub }
31
+
32
+ before do
33
+ client.stub(:collection_resource_for).and_return(collection_resource)
34
+ end
35
+
36
+ it "sends POST request to server" do
37
+ collection_resource.should_receive(:save_resource).with(subject).and_return({})
38
+ subject.save
39
+ end
40
+
41
+ it "returns true" do
42
+ collection_resource.stub(:save_resource).and_return(
43
+ {:success => true})
44
+ subject.save.should be_true
45
+ end
46
+
47
+ it "sets the updated attributes received from the server" do
48
+ collection_resource.stub(:save_resource).and_return(
49
+ {:success => true, :resource => {:id => 9999}})
50
+ subject.save
51
+ subject.id.should eq 9999
52
+ end
53
+ end
54
+
55
+ context "with invalid parameters" do
56
+ let(:collection_resource) { stub }
57
+
58
+ before do
59
+ client.stub(:collection_resource_for).and_return(collection_resource)
60
+ collection_resource.stub(:save_resource).and_return({:success => false, :error_message => "No url."})
61
+ end
62
+
63
+ it "sets an error messages" do
64
+ subject.save
65
+ subject.errors.should eq ["No url."]
66
+ end
67
+
68
+ it "returns false" do
69
+ subject.save.should be_false
70
+ end
71
+
72
+ it "clears previous errors" do
73
+ subject.save
74
+ subject.errors.should eq ["No url."]
75
+ subject.save
76
+ subject.errors.should eq ["No url."]
77
+ end
78
+ end
79
+ end
80
+ end
@@ -7,6 +7,8 @@ require "kippt"
7
7
  require "rspec"
8
8
  require "webmock/rspec"
9
9
 
10
+ Dir["./spec/shared_examples/*.rb"].each {|f| require f }
11
+
10
12
  def stub_get(url)
11
13
  stub_request(:get, kippt_url(url))
12
14
  end
@@ -39,301 +41,3 @@ end
39
41
  def json_fixture(file)
40
42
  MultiJson.load(fixture(file).read)
41
43
  end
42
-
43
- shared_examples_for "collection resource" do
44
- def collection_fixture
45
- base_uri.split("/").last
46
- end
47
-
48
- describe "#all" do
49
- it "returns collection class" do
50
- stub_get("/#{base_uri}").
51
- to_return(:status => 200, :body => fixture("#{collection_fixture}.json"))
52
- all_resources = subject.all
53
- all_resources.is_a? collection_class
54
- end
55
-
56
- it "accepts limit and offset options" do
57
- stub_get("/#{base_uri}?limit=10&offset=100").
58
- to_return(:status => 200, :body => fixture("#{collection_fixture}.json"))
59
- resources = subject.all(:limit => 10, :offset => 100)
60
- end
61
-
62
- context "when passed unrecognized arguments" do
63
- it "raises error" do
64
- lambda {
65
- subject.all(:foobar => true)
66
- }.should raise_error(
67
- ArgumentError, "Unrecognized argument: foobar")
68
- end
69
- end
70
- end
71
-
72
- describe "#[]" do
73
- it "fetches single resource" do
74
- stub_get("/#{base_uri}/10").
75
- to_return(:status => 200, :body => fixture("#{singular_fixture}.json"))
76
- subject[10].id.should eq 10
77
- end
78
-
79
- it "returns resource" do
80
- stub_get("/#{base_uri}/10").
81
- to_return(:status => 200, :body => fixture("#{singular_fixture}.json"))
82
- subject[10].should be_a(resource_class)
83
- end
84
-
85
- context "when resource is not found" do
86
- it "raises exception" do
87
- stub_get("/#{base_uri}/10").
88
- to_return(:status => 404, :body => {"message" => "Resource not found."})
89
- lambda {
90
- subject[10]
91
- subject.all(:foobar => true)
92
- }.should raise_error(
93
- Kippt::APIError, "Resource could not be loaded: Resource not found.")
94
- end
95
- end
96
- end
97
-
98
- describe "#find" do
99
- it "exists" do
100
- subject.respond_to?(:find).should be_true
101
- end
102
- end
103
-
104
- describe "#collection_from_url" do
105
- it "returns a new collection" do
106
- stub_get("/#{base_uri}/?limit=20&offset=20").
107
- to_return(:status => 200, :body => fixture("#{collection_fixture}.json"))
108
- collection = subject.collection_from_url("/api/#{base_uri}/?limit=20&offset=20")
109
- collection.should be_a(collection_class)
110
- end
111
-
112
- context "when passed URL is blank" do
113
- it "raises ArgumentError" do
114
- lambda {
115
- subject.collection_from_url("")
116
- }.should raise_error(ArgumentError, "The parameter URL can't be blank")
117
- lambda {
118
- subject.collection_from_url(nil)
119
- }.should raise_error(ArgumentError, "The parameter URL can't be blank")
120
- end
121
- end
122
- end
123
-
124
- describe "#build" do
125
- it "returns new resource" do
126
- subject.build.should be_a(resource_class)
127
- end
128
-
129
- it "accepts parameters" do
130
- subject.object_class.should_receive(:new).with({:an => "attribute"}, client)
131
- subject.build(:an => "attribute")
132
- end
133
- end
134
- end
135
-
136
- shared_examples_for "collection" do
137
- it "is Enumberable" do
138
- subject.should be_a(Enumerable)
139
- end
140
-
141
- describe "#total_count" do
142
- it "returns total count of resources" do
143
- subject.total_count.should eq data["meta"]["total_count"]
144
- end
145
- end
146
-
147
- describe "#offset" do
148
- it "returns offset of the results" do
149
- subject.offset.should eq 0
150
- end
151
- end
152
-
153
- describe "#limit" do
154
- it "returns limit of the results" do
155
- subject.limit.should eq 20
156
- end
157
- end
158
-
159
- describe "#objects" do
160
- it "returns the objects generated from the data" do
161
- subject.objects.each do |object|
162
- object.should be_a(subject.object_class)
163
- end
164
- end
165
- end
166
-
167
- describe "#[]" do
168
- it "returns a object by index" do
169
- subject[0].id.should eq data["objects"][0]["id"]
170
- end
171
- end
172
-
173
- describe "#each" do
174
- it "loops through the objects" do
175
- ids = []
176
- subject.each {|object| ids << object.id }
177
- ids.should eq data["objects"].map { |node| node["id"] }
178
- end
179
- end
180
-
181
- describe "#next_page?" do
182
- context "there is a next page" do
183
- it "returns url of the page" do
184
- subject_with_multiple_pages.next_page?.should eq data_with_multiple_pages["meta"]["next"]
185
- end
186
- end
187
-
188
- context "there is no next page" do
189
- it "returns nil" do
190
- subject.next_page?.should eq nil
191
- end
192
- end
193
- end
194
-
195
- describe "#next_page" do
196
- context "if there is a next page" do
197
- let(:collection_resource) { stub }
198
-
199
- it "gets the next page of results from the collection resource" do
200
- client.stub(:collection_resource_for).and_return(collection_resource)
201
-
202
- results = stub
203
- collection_resource.should_receive(:collection_from_url).
204
- with(data_with_multiple_pages["meta"]["next"]).
205
- and_return(results)
206
-
207
- subject_with_multiple_pages.next_page.should eq results
208
- end
209
- end
210
-
211
- context "if there is no next page" do
212
- it "raises an error" do
213
- lambda {
214
- subject.next_page
215
- }.should raise_error(Kippt::APIError, "There is no next page")
216
- end
217
- end
218
- end
219
-
220
- describe "#previous_page?" do
221
- context "there is a previous page" do
222
- it "returns url of the page" do
223
- subject_with_multiple_pages.previous_page?.should eq data_with_multiple_pages["meta"]["previous"]
224
- end
225
- end
226
-
227
- context "there is no previous page" do
228
- it "returns nil" do
229
- subject.previous_page?.should be_nil
230
- end
231
- end
232
- end
233
-
234
- describe "#previous_page" do
235
- context "if there is a previous page" do
236
- let(:collection_resource) { stub }
237
-
238
- it "gets the previous page of results from the collection resource" do
239
- client.stub(:collection_resource_for).and_return(collection_resource)
240
-
241
- results = stub
242
- collection_resource.should_receive(:collection_from_url).
243
- with(data_with_multiple_pages["meta"]["previous"]).
244
- and_return(results)
245
-
246
- subject_with_multiple_pages.previous_page.should eq results
247
- end
248
- end
249
-
250
- context "if there is no previous page" do
251
- it "raises an error" do
252
- lambda {
253
- subject.previous_page
254
- }.should raise_error(Kippt::APIError, "There is no previous page")
255
- end
256
- end
257
- end
258
- end
259
-
260
- shared_examples_for "resource" do
261
- describe "attribute accessors" do
262
- it "delegates to attributes" do
263
- attributes.each do |attribute_name|
264
- subject.send(attribute_name).should eq data[attribute_name.to_s]
265
- end
266
- end
267
- end
268
-
269
- describe "mapped attribute accessors" do
270
- it "delegates to attributes and wraps with to a object" do
271
- mapped_attributes.each do |attribute_name, attribute_class|
272
- subject.send(attribute_name).class.to_s.should eq attribute_class
273
- end
274
- end
275
- end
276
-
277
- describe "#destroy" do
278
- let(:collection_resource) { stub }
279
-
280
- it "sends delete request to the server" do
281
- client.stub(:collection_resource_for).and_return(collection_resource)
282
- collection_resource.should_receive(:destroy_resource).with(subject).and_return(true)
283
- subject.destroy.should be_true
284
- end
285
- end
286
-
287
- describe "#save" do
288
- context "with valid parameters" do
289
- let(:collection_resource) { stub }
290
-
291
- before do
292
- client.stub(:collection_resource_for).and_return(collection_resource)
293
- end
294
-
295
- it "sends POST request to server" do
296
- collection_resource.should_receive(:save_resource).with(subject).and_return({})
297
- subject.save
298
- end
299
-
300
- it "returns true" do
301
- collection_resource.stub(:save_resource).and_return(
302
- {:success => true})
303
- subject.save.should be_true
304
- end
305
-
306
- it "sets the updated attributes received from the server" do
307
- collection_resource.stub(:save_resource).and_return(
308
- {:success => true, :resource => {:id => 9999}})
309
- subject.save
310
- subject.id.should eq 9999
311
- end
312
- end
313
-
314
- context "with invalid parameters" do
315
- let(:collection_resource) { stub }
316
-
317
- before do
318
- client.stub(:collection_resource_for).and_return(collection_resource)
319
- collection_resource.stub(:save_resource).and_return({:success => false, :error_message => "No url."})
320
- end
321
-
322
- it "sets an error messages" do
323
- subject.save
324
- subject.errors.should eq ["No url."]
325
- end
326
-
327
- it "returns false" do
328
- subject.save.should be_false
329
- end
330
-
331
- it "clears previous errors" do
332
- subject.save
333
- subject.errors.should eq ["No url."]
334
- subject.save
335
- subject.errors.should eq ["No url."]
336
- end
337
- end
338
- end
339
- end