kippt 2.0.1 → 3.0

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 (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