supplejack_client 1.0.5 → 1.0.7

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