supplejack_client 1.0.5 → 1.0.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -2
  3. data/.ruby-version +1 -0
  4. data/.travis.yml +2 -2
  5. data/Gemfile +4 -2
  6. data/README.md +3 -3
  7. data/lib/generators/locales/en.yml +5 -3
  8. data/lib/generators/supplejack/install_generator.rb +5 -3
  9. data/lib/generators/templates/supplejack_client.rb +5 -3
  10. data/lib/supplejack/concept.rb +5 -3
  11. data/lib/supplejack/config.rb +5 -3
  12. data/lib/supplejack/controllers/helpers.rb +5 -3
  13. data/lib/supplejack/engine.rb +5 -3
  14. data/lib/supplejack/exceptions.rb +8 -3
  15. data/lib/supplejack/facet.rb +5 -3
  16. data/lib/supplejack/item.rb +7 -5
  17. data/lib/supplejack/item_relation.rb +7 -4
  18. data/lib/supplejack/log_subscriber.rb +5 -3
  19. data/lib/supplejack/paginated_collection.rb +5 -3
  20. data/lib/supplejack/record.rb +5 -3
  21. data/lib/supplejack/request.rb +18 -4
  22. data/lib/supplejack/search.rb +5 -3
  23. data/lib/supplejack/story.rb +232 -0
  24. data/lib/supplejack/story_item.rb +149 -0
  25. data/lib/supplejack/story_item_relation.rb +81 -0
  26. data/lib/supplejack/url_formats/item_hash.rb +5 -3
  27. data/lib/supplejack/user.rb +9 -3
  28. data/lib/supplejack/user_set.rb +28 -26
  29. data/lib/supplejack/user_set_relation.rb +5 -3
  30. data/lib/supplejack/user_story_relation.rb +141 -0
  31. data/lib/supplejack/util.rb +5 -3
  32. data/lib/supplejack/version.rb +7 -5
  33. data/lib/supplejack_client.rb +14 -3
  34. data/spec/spec_helper.rb +7 -5
  35. data/spec/supplejack/concept_spec.rb +5 -3
  36. data/spec/supplejack/facet_spec.rb +5 -3
  37. data/spec/supplejack/item_relation_spec.rb +5 -3
  38. data/spec/supplejack/item_spec.rb +7 -5
  39. data/spec/supplejack/log_subscriber_spec.rb +5 -3
  40. data/spec/supplejack/paginated_collection_spec.rb +5 -3
  41. data/spec/supplejack/record_spec.rb +5 -3
  42. data/spec/supplejack/request_spec.rb +5 -3
  43. data/spec/supplejack/search_spec.rb +5 -3
  44. data/spec/supplejack/story_item_relation_spec.rb +149 -0
  45. data/spec/supplejack/story_item_spec.rb +114 -0
  46. data/spec/supplejack/story_spec.rb +401 -0
  47. data/spec/supplejack/user_set_relation_spec.rb +5 -3
  48. data/spec/supplejack/user_set_spec.rb +9 -7
  49. data/spec/supplejack/user_spec.rb +5 -3
  50. data/spec/supplejack/user_story_relation_spec.rb +157 -0
  51. data/stories_integration_test.rb +97 -0
  52. data/supplejack_client.gemspec +9 -3
  53. metadata +32 -10
@@ -0,0 +1,114 @@
1
+ # The Supplejack Common code is
2
+ # Crown copyright (C) 2014, New Zealand Government,
3
+ # and is licensed under the GNU General Public License, version 3.
4
+ # See https://github.com/DigitalNZ/supplejack_client for details.
5
+ #
6
+ # Supplejack was created by DigitalNZ at the
7
+ # National Library of NZ and the Department of Internal Affairs.
8
+ # http://digitalnz.org/supplejack
9
+
10
+ require 'spec_helper'
11
+
12
+ module Supplejack
13
+ describe StoryItem do
14
+
15
+ describe '#initialize' do
16
+ it 'accepts a hash of attributes' do
17
+ Supplejack::StoryItem.new(type: 'embed', sub_type: 'dnz')
18
+ end
19
+
20
+ it 'accepts a hash with string keys' do
21
+ expect(Supplejack::StoryItem.new({'type' => 'embed', 'sub_type' => 'dnz'}).type).to eq('embed')
22
+ end
23
+
24
+ it 'handles nil attributes' do
25
+ expect(Supplejack::StoryItem.new(nil).type).to be_nil
26
+ end
27
+
28
+ Supplejack::StoryItem::ATTRIBUTES.each do |attribute|
29
+ it "should initialize the attribute #{attribute}" do
30
+ Supplejack::StoryItem.new({attribute => 'value'}).send(attribute).should eq 'value'
31
+ end
32
+ end
33
+ end
34
+
35
+ describe '#save' do
36
+ let(:item) { Supplejack::StoryItem.new(type: 'embed', sub_type: 'dnz', story_id: '1234', api_key: 'abc') }
37
+
38
+ context 'new item' do
39
+ it 'triggers a POST request to create a story_item with the story api_key' do
40
+ expect(item).to receive(:post).with('/stories/1234/items', {api_key: 'abc'}, {item: {meta: {}, type: 'embed', sub_type: 'dnz'}})
41
+
42
+ expect(item.save).to eq(true)
43
+ end
44
+ end
45
+
46
+ context 'existing item' do
47
+ it 'triggers a PATCH request to update a story_item with the story api_key' do
48
+ item.id = 1
49
+ expect(item).to receive(:patch).with('/stories/1234/items/1', params: {api_key: 'abc'}, payload: {item: {meta: {}, type: 'embed', sub_type: 'dnz'}})
50
+
51
+ expect(item.save).to eq(true)
52
+ end
53
+ end
54
+
55
+ context 'HTTP error is raised' do
56
+ before do
57
+ item.stub(:post).and_raise(RestClient::Forbidden.new)
58
+ end
59
+
60
+ it 'returns false when an HTTP error is raised' do
61
+ expect(item.save).to eq(false)
62
+ end
63
+
64
+ it 'stores the error when a error is raised' do
65
+ item.save
66
+
67
+ expect(item.errors).to eq 'Forbidden'
68
+ end
69
+ end
70
+ end
71
+
72
+ describe '#destroy' do
73
+ let(:item) { Supplejack::StoryItem.new(story_id: '1234', api_key: 'abc', id: 5) }
74
+
75
+ it 'triggers a DELETE request with the story api_key' do
76
+ expect(item).to receive(:delete).with('/stories/1234/items/5', {api_key: 'abc'})
77
+
78
+ item.destroy
79
+ end
80
+
81
+ context 'HTTP error is raised' do
82
+ before do
83
+ item.stub(:delete).and_raise(RestClient::Forbidden.new)
84
+ end
85
+
86
+ it 'returns false when a HTTP error is raised' do
87
+ expect(item.destroy).to eq(false)
88
+ end
89
+
90
+ it 'stores the error when a error is raised' do
91
+ item.destroy
92
+
93
+ expect(item.errors).to eq 'Forbidden'
94
+ end
95
+ end
96
+ end
97
+
98
+ describe '#update_attributes' do
99
+ let(:story_item) {Supplejack::StoryItem.new(type: 'foo', sub_type: 'bar')}
100
+
101
+ it 'sets the attributes on the StoryItem' do
102
+ story_item.update_attributes(type: 'Mac')
103
+
104
+ expect(story_item.type).to eq('Mac')
105
+ end
106
+
107
+ it 'saves the StoryItem' do
108
+ expect(story_item).to receive(:save)
109
+
110
+ story_item.update_attributes(type: 'Mac')
111
+ end
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,401 @@
1
+ # The Supplejack Common code is
2
+ # Crown copyright (C) 2014, New Zealand Government,
3
+ # and is licensed under the GNU General Public License, version 3.
4
+ # See https://github.com/DigitalNZ/supplejack_client for details.
5
+ #
6
+ # Supplejack was created by DigitalNZ at the
7
+ # National Library of NZ and the Department of Internal Affairs.
8
+ # http://digitalnz.org/supplejack
9
+
10
+ require 'spec_helper'
11
+
12
+ class SupplejackRecord
13
+ include Supplejack::Record
14
+ end
15
+
16
+ module Supplejack
17
+ describe Story do
18
+ before do
19
+ Supplejack.stub(:enable_caching) { false }
20
+ end
21
+
22
+ describe '#initialize' do
23
+ Supplejack::Story::ATTRIBUTES.reject{|a| a =~ /_at/}.each do |attribute|
24
+ it "initializes the #{attribute}" do
25
+ expect(Supplejack::Story.new({attribute => 'value'}).send(attribute)).to eq 'value'
26
+ end
27
+ end
28
+
29
+
30
+ it 'handles nil attributes' do
31
+ expect{Supplejack::Story.new(nil).attributes}.not_to raise_error
32
+ end
33
+
34
+ it 'initializes a user object' do
35
+ story = Supplejack::Story.new({user: {name: 'Juanito'}})
36
+ expect(story.user).to be_a Supplejack::User
37
+ expect(story.user.name).to eq 'Juanito'
38
+ end
39
+ end
40
+
41
+ [:updated_at, :created_at].each do |field|
42
+ describe "##{field}" do
43
+ let(:story) {Supplejack::Story.new(field => '2012-08-17T10:01:00+12:00')}
44
+
45
+ it "converts it into a time object" do
46
+ expect(story.send(field)).to be_a Time
47
+ end
48
+
49
+ it 'sets it to nil when the time is incorrect' do
50
+ story.send("#{field}=", '838927587hdfhsjdf')
51
+
52
+ expect(story.send(field)).to be_nil
53
+ end
54
+
55
+ it 'accepts a Time object too' do
56
+ time = Time.now
57
+
58
+ story.send("#{field}=", time)
59
+
60
+ expect(story.send(field)).to eq time
61
+ end
62
+ end
63
+ end
64
+
65
+ describe '#attributes' do
66
+ it 'returns a hash of the set attributes' do
67
+ story = Supplejack::Story.new
68
+
69
+ story.name = 'Dogs'
70
+ story.description = 'Hi'
71
+
72
+ expect(story.attributes).to include(name: 'Dogs', description: 'Hi')
73
+ end
74
+ end
75
+
76
+ describe '#api_attributes' do
77
+ it 'only returns the fields that can be modified' do
78
+ story = Supplejack::Story.new(name: 'foo', id: 'bar')
79
+
80
+ attributes = story.api_attributes
81
+
82
+ expect(attributes).to include(:name)
83
+ expect(attributes).not_to include(:id)
84
+ end
85
+ end
86
+
87
+ describe '#tag_list' do
88
+ it 'returns a comma sepparated list of tags' do
89
+ expect(Supplejack::Story.new(tags: ['dog', 'cat']).tag_list).to eq 'dog, cat'
90
+ end
91
+ end
92
+
93
+ describe '#private?' do
94
+ it 'returns true when the privacy is private' do
95
+ expect(Supplejack::Story.new(privacy: 'private').private?).to eq true
96
+ end
97
+
98
+ it 'returns false when the privacy is something else' do
99
+ expect(Supplejack::Story.new(privacy: 'public').private?).to eq false
100
+ end
101
+ end
102
+
103
+ describe '#public?' do
104
+ it 'returns false when the privacy is private' do
105
+ expect(Supplejack::Story.new(privacy: 'private').public?).to eq false
106
+ end
107
+
108
+ it 'returns true when the privacy is public' do
109
+ expect(Supplejack::Story.new(privacy: 'public').public?).to eq true
110
+ end
111
+ end
112
+
113
+ describe '#hidden?' do
114
+ it 'returns false when the privacy is not hidden' do
115
+ expect(Supplejack::Story.new(privacy: 'public').hidden?).to eq false
116
+ end
117
+
118
+ it 'returns true when the privacy is hidden' do
119
+ expect(Supplejack::Story.new(privacy: 'hidden').hidden?).to eq true
120
+ end
121
+ end
122
+
123
+ describe '#new_record?' do
124
+ it "returns true when the user_set doesn't have a id" do
125
+ expect(Supplejack::Story.new.new_record?).to eq true
126
+ end
127
+
128
+ it 'returns false when the user_set has a id' do
129
+ expect(Supplejack::Story.new(id: '1234abc').new_record?).to eq false
130
+ end
131
+ end
132
+
133
+ describe '#api_key' do
134
+ it 'returns the users api_key' do
135
+ expect(Supplejack::Story.new(user: {api_key: 'foobar'}).api_key).to eq 'foobar'
136
+ end
137
+ end
138
+
139
+ describe '#save' do
140
+ context 'Story is a new_record' do
141
+ let(:attributes) {{name: 'Story Name', description: nil, privacy: nil, copyright:nil, featured:nil, approved:nil, tags:nil, record_ids: nil}}
142
+ let(:user) {{api_key: 'foobar'}}
143
+ let(:story) {Supplejack::Story.new(attributes.merge(user: user))}
144
+
145
+ before do
146
+ expect(Supplejack::Story).to receive(:post).with("/stories", {api_key: "foobar"}, {story: attributes}) do
147
+ {
148
+ "id" => "new-id",
149
+ "name" => attributes[:name],
150
+ "description" => "",
151
+ "tags" => [],
152
+ "contents" => []
153
+ }
154
+ end
155
+ end
156
+
157
+ it 'triggers a POST request to /stories.json' do
158
+ expect(story.save).to eq true
159
+ end
160
+
161
+ it 'stores the id of the user_set' do
162
+ story.save
163
+
164
+ expect(story.id).to eq 'new-id'
165
+ end
166
+
167
+ it 'updates the attributes with the response' do
168
+ story.save
169
+
170
+ expect(story.tags).to eq []
171
+ end
172
+
173
+ it 'returns false for anything other that a 200 response' do
174
+ RSpec::Mocks.proxy_for(Supplejack::Story).reset
175
+ Supplejack::Story.stub(:post).and_raise(RestClient::Forbidden.new)
176
+
177
+ expect(story.save).to eq false
178
+ end
179
+ end
180
+
181
+ context 'story is not new' do
182
+ let(:attributes) {{name: 'Story Name', description: 'desc', privacy: nil, copyright:nil, featured:nil, approved:nil, tags:nil, record_ids:nil}}
183
+ let(:user) {{api_key: 'foobar'}}
184
+ let(:story) {Supplejack::Story.new(attributes.merge(user: user, id: '123'))}
185
+
186
+ before do
187
+ expect(Supplejack::Story).to receive(:patch).with("/stories/123", payload: {story: attributes}) do
188
+ {
189
+ "id" => "new-id",
190
+ "name" => attributes[:name],
191
+ "description" => "desc",
192
+ "tags" => [],
193
+ "contents" => []
194
+ }
195
+ end
196
+ end
197
+
198
+ it 'triggers a PATCH request to /stories/123.json with the user set api_key' do
199
+ story.save
200
+ end
201
+
202
+ it 'updates the attributes with the response' do
203
+ story.save
204
+
205
+ expect(story.description).to eq 'desc'
206
+ end
207
+ end
208
+ end
209
+
210
+ describe '#update_attributes' do
211
+ let(:story) {Supplejack::Story.new(name: 'test', description: 'test')}
212
+
213
+ it 'sets the attributes on the Story' do
214
+ story.update_attributes(name: 'Mac')
215
+
216
+ expect(story.name).to eq('Mac')
217
+ end
218
+
219
+ it 'saves the Story' do
220
+ expect(story).to receive(:save)
221
+
222
+ story.update_attributes(name: 'Mac')
223
+ end
224
+ end
225
+
226
+ describe '#attributes=' do
227
+ let(:story) {Supplejack::Story.new(name: 'Foo')}
228
+
229
+ it 'updates the attributes on the story' do
230
+ story.attributes = {name: 'Mac'}
231
+
232
+ expect(story.name).to eq 'Mac'
233
+ end
234
+
235
+ it 'should only update passed attributes' do
236
+ story.id = '12345'
237
+ story.attributes = {name: 'Mac'}
238
+
239
+ expect(story.id).to eq '12345'
240
+ end
241
+ end
242
+
243
+ describe '#destroy' do
244
+ let(:story) {Supplejack::Story.new(id: '999')}
245
+
246
+ it 'executes a delete request to the API with the user set api_key' do
247
+ expect(Supplejack::Story).to receive(:delete).with('/stories/999')
248
+
249
+ expect(story.destroy).to eq(true)
250
+ end
251
+
252
+ it 'returns false when the response is not a 200' do
253
+ expect(Supplejack::Story).to receive(:delete).and_raise(RestClient::Forbidden.new)
254
+
255
+ expect(story.destroy).to eq(false)
256
+ expect(story.errors).to eq 'Forbidden'
257
+ end
258
+
259
+ it 'returns false when it is a new user set' do
260
+ expect(story).to receive(:new_record?) { true }
261
+ expect(Supplejack::Story).not_to receive(:delete)
262
+
263
+ expect(story.destroy).to eq(false)
264
+ end
265
+ end
266
+
267
+ describe '#reload' do
268
+ let(:story) { Supplejack::Story.new(id: '123456') }
269
+
270
+ it 'fetches the set from the api and repopulates the set' do
271
+ expect(Supplejack::Story).to receive(:get).with('/stories/123456') { {'id' => 'abc'} }
272
+
273
+ story.reload
274
+
275
+ expect(story.id).to eq('abc')
276
+ end
277
+
278
+ it 'raises Supplejack::StoryNotFound if the Story is not found' do
279
+ expect(Supplejack::Story).to receive(:get).and_raise(RestClient::ResourceNotFound.new)
280
+
281
+ expect{story.reload}.to raise_error(Supplejack::StoryNotFound)
282
+ end
283
+
284
+ it 'removes the existing @items relation' do
285
+ expect(Supplejack::Story).to receive(:get).with('/stories/123456') { {'id' => 'abc'} }
286
+
287
+ story.items
288
+ story.reload
289
+
290
+ expect(story.instance_variable_get('@items')).to be_nil
291
+ end
292
+ end
293
+
294
+ describe '#viewable_by?' do
295
+ let(:api_key) { '123' }
296
+ let(:user) { { api_key: api_key } }
297
+
298
+ it 'returns true when the Story is public' do
299
+ story = Supplejack::Story.new(privacy: 'public')
300
+
301
+ expect(story.viewable_by?(nil)).to eq(true)
302
+ end
303
+
304
+ it 'returns true when the user_set is hidden' do
305
+ story = Supplejack::Story.new(privacy: 'hidden')
306
+
307
+ expect(story.viewable_by?(nil)).to eq(true)
308
+ end
309
+
310
+ context 'private set' do
311
+ let(:story) { Supplejack::Story.new(privacy: 'private', user: user) }
312
+
313
+ it 'returns false when the user is not present' do
314
+ expect(story.viewable_by?(nil)).to eq(false)
315
+ end
316
+
317
+ it 'returns true when the user has the same api_key as the user_set' do
318
+ expect(story.viewable_by?(Supplejack::User.new(user))).to eq(true)
319
+ end
320
+
321
+ it 'returns false if both the api_key in the user and the set are nil' do
322
+ user = { api_key: nil }
323
+ story = Supplejack::Story.new(privacy: 'private', user: user)
324
+
325
+ expect(story.viewable_by?(Supplejack::User.new(user))).to eq(false)
326
+ end
327
+ end
328
+ end
329
+
330
+ describe '#owned_by?' do
331
+ let(:api_key) { '123456' }
332
+ let(:user) { Supplejack::User.new(api_key: api_key) }
333
+ let(:users_story) { Supplejack::Story.new(user: { api_key: api_key }) }
334
+ let(:other_story) { Supplejack::Story.new(user: { api_key: '123' }) }
335
+ let(:nil_api_key_story) { Supplejack::Story.new(user: { api_key: nil }) }
336
+
337
+ it "returns true when the users api_key is the same as the set's" do
338
+ expect(users_story.owned_by? user).to eq(true)
339
+ end
340
+
341
+ it 'returns false when the set and user have different api_keys' do
342
+ expect(other_story.owned_by? user).to eq(false)
343
+ end
344
+
345
+ it 'returns false when both keys are nil' do
346
+ expect(nil_api_key_story.owned_by? user).to eq(false)
347
+ end
348
+ end
349
+
350
+ describe '#find' do
351
+ let(:attributes) do
352
+ {
353
+ name: 'foo',
354
+ description: 'desc',
355
+ privacy: nil,
356
+ copyright: nil,
357
+ featured: nil,
358
+ approved: nil,
359
+ tags: nil,
360
+ contents: nil,
361
+ created_at: nil,
362
+ updated_at: nil,
363
+ number_of_items: nil,
364
+ id: nil,
365
+ record_ids: nil,
366
+ cover_thumbnail: nil
367
+ }
368
+ end
369
+
370
+ it 'fetches the Story from the API' do
371
+ Supplejack::Story.should_receive(:get).with('/stories/123abc', {}).and_return(attributes)
372
+
373
+ Supplejack::Story.find('123abc')
374
+ end
375
+
376
+ it 'initializes a Story object' do
377
+ Supplejack::Story.should_receive(:get).with('/stories/123abc', {}).and_return(attributes)
378
+
379
+ story = Supplejack::Story.find('123abc')
380
+
381
+ expect(story.attributes).to eq(attributes.symbolize_keys)
382
+ end
383
+
384
+ # I've removed this functionality because I don't understand the use case
385
+ # If we _do_ end up needing it in the future we can re add it
386
+ it 'initializes the Story and sets the user api_key' do
387
+ expect(Supplejack::Story).to receive(:get).with('/stories/123abc', {}).and_return(attributes)
388
+
389
+ story = Supplejack::Story.find('123abc', api_key: '98765')
390
+
391
+ expect(story.api_key).to eq('98765')
392
+ end
393
+
394
+ it 'raises a Supplejack::StoryNotFound' do
395
+ Supplejack::Story.stub(:get).and_raise(RestClient::ResourceNotFound)
396
+
397
+ expect { Supplejack::Story.find(id: '123') }.to raise_error(Supplejack::StoryNotFound)
398
+ end
399
+ end
400
+ end
401
+ end