storyblok 2.1.1 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,812 @@
1
+ require_relative '../../lib/storyblok/client'
2
+ require_relative '../../lib/storyblok/cache/redis'
3
+ require 'redis'
4
+ require 'spec_helper'
5
+
6
+ describe Storyblok::Client do
7
+ subject { described_class.new(api_version: 1, token: token, version: version) }
8
+
9
+ context "When querying CDN Content" do
10
+
11
+ context "With token defined" do
12
+ let(:token) { '<SPACE_PUBLIC_TOKEN>' }
13
+
14
+ context "When querying stories" do
15
+
16
+ context "When querying the published version" do
17
+ let(:version) { 'published' }
18
+
19
+ context "when querying an existent story by slug" do
20
+ it "returns a story", :vcr do
21
+ expect(subject.story('simple_content')['data']).to eq({
22
+ "story"=> {
23
+ "name"=>"simple_content",
24
+ "created_at"=>"2020-08-20T18:01:55.065Z",
25
+ "published_at"=>"2020-08-20T18:13:34.946Z",
26
+ "alternates"=>[],
27
+ "id"=>18409805,
28
+ "uuid"=>"fe520269-b092-482c-94c4-8028eb81af41",
29
+ "content"=> {
30
+ "_uid"=>"ae111a76-84b7-43cc-a6a0-77a70de1b6f4",
31
+ "component"=>"SimpleTextContentType",
32
+ "SimpleText"=>"Simple Content from a Simple Text PUBLISHED"
33
+ },
34
+ "slug"=>"simple_content",
35
+ "full_slug"=>"simple_content",
36
+ "default_full_slug"=>nil,
37
+ "sort_by_date"=>nil,
38
+ "position"=>0,
39
+ "tag_list"=>[],
40
+ "is_startpage"=>false,
41
+ "parent_id"=>0,
42
+ "meta_data"=>nil,
43
+ "group_id"=>"f905f0f0-569e-4036-bcef-1479e5088956",
44
+ "first_published_at"=>"2020-08-20T18:03:33.759Z",
45
+ "release_id"=>nil,
46
+ "lang"=>"default",
47
+ "path"=>nil,
48
+ "translated_slugs"=>[]
49
+ }
50
+ })
51
+ end
52
+ end
53
+
54
+ context "when querying an story list by slug" do
55
+ it "returns a stories list", :vcr do
56
+ expect(subject.stories(starts_with: 'my-folder-slug')['data']).to eq(
57
+ {
58
+ "stories"=>[
59
+ {
60
+ "name"=>"simple_content_2",
61
+ "created_at"=>"2020-08-20T18:48:44.026Z",
62
+ "published_at"=>"2020-08-20T18:48:59.352Z",
63
+ "alternates"=>[],
64
+ "id"=>18409847,
65
+ "uuid"=>"4b069560-749d-4f2b-8304-97a2a465fb49",
66
+ "content"=>{
67
+ "_uid"=>"ad08db76-4465-4539-880b-6437629d66ff",
68
+ "component"=>"SimpleTextContentType",
69
+ "SimpleText"=>"Simple Content Published"
70
+ },
71
+ "slug"=>"simple_content_2",
72
+ "full_slug"=>"my-folder-slug/simple_content_2",
73
+ "default_full_slug"=>nil,
74
+ "sort_by_date"=>nil,
75
+ "position"=>-10,
76
+ "tag_list"=>["my another tag", "my first tag"],
77
+ "is_startpage"=>false,
78
+ "parent_id"=>18409844,
79
+ "meta_data"=>nil,
80
+ "group_id"=>"0d452376-8b44-4ed6-b9e5-65965adbf0ff",
81
+ "first_published_at"=>"2020-08-20T18:48:59.000Z",
82
+ "release_id"=>nil,
83
+ "lang"=>"default",
84
+ "path"=>nil,
85
+ "translated_slugs"=>[]
86
+ },
87
+ {
88
+ "name"=>"simple_content_1",
89
+ "created_at"=>"2020-08-20T18:45:52.758Z",
90
+ "published_at"=>"2020-08-20T18:46:48.719Z",
91
+ "alternates"=>[],
92
+ "id"=>18409845,
93
+ "uuid"=>"542e19cc-ff06-4f19-ae64-a725c89e3406",
94
+ "content"=>{
95
+ "_uid"=>"e8ac85a4-91eb-42c2-8a18-b6e709b67e9d",
96
+ "component"=>"SimpleTextContentType",
97
+ "SimpleText"=>"Simple Content Published"},
98
+ "slug"=>"simple_content_1",
99
+ "full_slug"=>"my-folder-slug/simple_content_1",
100
+ "default_full_slug"=>nil,
101
+ "sort_by_date"=>nil,
102
+ "position"=>0,
103
+ "tag_list"=>[],
104
+ "is_startpage"=>false,
105
+ "parent_id"=>18409844,
106
+ "meta_data"=>nil,
107
+ "group_id"=>"943ee7f6-b002-44c6-8e26-41b21b6792ea",
108
+ "first_published_at"=>"2020-08-20T18:46:39.840Z",
109
+ "release_id"=>nil,
110
+ "lang"=>"default",
111
+ "path"=>nil,
112
+ "translated_slugs"=>[]
113
+ }
114
+ ]
115
+ }
116
+ )
117
+ end
118
+ end
119
+ end
120
+
121
+ context "When querying the draft version" do
122
+ subject { described_class.new(api_version: 1, token: token) }
123
+
124
+ let(:token) { '<SPACE_PREVIEW_TOKEN>' }
125
+
126
+ context "when querying an existent story by slug" do
127
+ it "returns a story", :vcr do
128
+ expect(subject.story('simple_content')['data']).to eq({
129
+ "story" => {
130
+ "alternates"=>[],
131
+ "content"=>{
132
+ "SimpleText"=>"Simple Content from a Simple Text DRAFT VERSION",
133
+ "_editable"=>"<!--#storyblok\#{\"name\": \"SimpleTextContentType\", \"space\": \"91322\", \"uid\": \"ae111a76-84b7-43cc-a6a0-77a70de1b6f4\", \"id\": \"18409805\"}-->",
134
+ "_uid"=>"ae111a76-84b7-43cc-a6a0-77a70de1b6f4",
135
+ "component"=>"SimpleTextContentType"
136
+ },
137
+ "created_at"=>"2020-08-20T18:01:55.065Z",
138
+ "default_full_slug"=>nil,
139
+ "first_published_at"=>"2020-08-20T18:03:33.759Z",
140
+ "full_slug"=>"simple_content",
141
+ "group_id"=>"f905f0f0-569e-4036-bcef-1479e5088956",
142
+ "id"=>18409805,
143
+ "is_startpage"=>false,
144
+ "lang"=>"default",
145
+ "meta_data"=>nil,
146
+ "name"=>"simple_content",
147
+ "parent_id"=>0,
148
+ "path"=>nil,
149
+ "position"=>0,
150
+ "published_at"=>"2020-08-20T18:13:34.946Z",
151
+ "release_id"=>nil,
152
+ "slug"=>"simple_content",
153
+ "sort_by_date"=>nil,
154
+ "tag_list"=>[],
155
+ "translated_slugs"=>[],
156
+ "uuid"=>"fe520269-b092-482c-94c4-8028eb81af41"
157
+ }
158
+ })
159
+ end
160
+ end
161
+
162
+ context "when querying an story list by slug" do
163
+ it "returns a stories list", :vcr do
164
+ expect(subject.stories(starts_with: 'my-folder-slug')['data']).to eq(
165
+ {
166
+ "stories"=> [
167
+ {
168
+ "name"=>"simple_content_2",
169
+ "created_at"=>"2020-08-20T18:48:44.026Z",
170
+ "published_at"=>"2020-08-20T18:48:59.352Z",
171
+ "alternates"=>[],
172
+ "id"=>18409847,
173
+ "uuid"=>"4b069560-749d-4f2b-8304-97a2a465fb49",
174
+ "content"=> {
175
+ "_uid"=>"ad08db76-4465-4539-880b-6437629d66ff",
176
+ "component"=>"SimpleTextContentType",
177
+ "SimpleText"=>"Simple Content Draft",
178
+ "_editable"=>"<!--#storyblok\#{\"name\": \"SimpleTextContentType\", \"space\": \"91322\", \"uid\": \"ad08db76-4465-4539-880b-6437629d66ff\", \"id\": \"18409847\"}-->"
179
+ },
180
+ "slug"=>"simple_content_2",
181
+ "full_slug"=>"my-folder-slug/simple_content_2",
182
+ "default_full_slug"=>nil,
183
+ "sort_by_date"=>nil,
184
+ "position"=>-10,
185
+ "tag_list"=>["my another tag", "my first tag"],
186
+ "is_startpage"=>false,
187
+ "parent_id"=>18409844,
188
+ "meta_data"=>nil,
189
+ "group_id"=>"0d452376-8b44-4ed6-b9e5-65965adbf0ff",
190
+ "first_published_at"=>"2020-08-20T18:48:59.000Z",
191
+ "release_id"=>nil,
192
+ "lang"=>"default",
193
+ "path"=>nil,
194
+ "translated_slugs"=>[]
195
+ },
196
+ {
197
+ "name"=>"simple_content_1",
198
+ "created_at"=>"2020-08-20T18:45:52.758Z",
199
+ "published_at"=>"2020-08-20T18:46:48.719Z",
200
+ "alternates"=>[],
201
+ "id"=>18409845,
202
+ "uuid"=>"542e19cc-ff06-4f19-ae64-a725c89e3406",
203
+ "content"=> {
204
+ "_uid"=>"e8ac85a4-91eb-42c2-8a18-b6e709b67e9d",
205
+ "component"=>"SimpleTextContentType",
206
+ "SimpleText"=>"Simple Content Draft",
207
+ "_editable"=>"<!--#storyblok\#{\"name\": \"SimpleTextContentType\", \"space\": \"91322\", \"uid\": \"e8ac85a4-91eb-42c2-8a18-b6e709b67e9d\", \"id\": \"18409845\"}-->"
208
+ },
209
+ "slug"=>"simple_content_1",
210
+ "full_slug"=>"my-folder-slug/simple_content_1",
211
+ "default_full_slug"=>nil,
212
+ "sort_by_date"=>nil,
213
+ "position"=>0,
214
+ "tag_list"=>[],
215
+ "is_startpage"=>false,
216
+ "parent_id"=>18409844,
217
+ "meta_data"=>nil,
218
+ "group_id"=>"943ee7f6-b002-44c6-8e26-41b21b6792ea",
219
+ "first_published_at"=>"2020-08-20T18:46:39.840Z",
220
+ "release_id"=>nil,
221
+ "lang"=>"default",
222
+ "path"=>nil,
223
+ "translated_slugs"=>[]
224
+ }
225
+ ]
226
+ }
227
+ )
228
+ end
229
+ end
230
+ end
231
+ end
232
+
233
+ context "When querying datasources" do
234
+ context "When querying the published version" do
235
+ let(:version) { 'published' }
236
+ it "returns a datasources list", :vcr do
237
+ expect(subject.datasources['data']).to eq(
238
+ {
239
+ "datasources" => [
240
+ {
241
+ "dimensions"=>[],
242
+ "id"=>23537,
243
+ "name"=>"my_datasource",
244
+ "slug"=>"my-datasource-slug"
245
+ }
246
+ ]
247
+ }
248
+ )
249
+ end
250
+ end
251
+ end
252
+
253
+ context "When querying datasource_entries" do
254
+ context "When querying the published version" do
255
+ let(:version) { 'published' }
256
+ it "returns a datasource_entries list", :vcr do
257
+ expect(subject.datasource_entries['data']).to eq(
258
+ {
259
+ "datasource_entries"=>[
260
+ {
261
+ "id"=>404023,
262
+ "name"=>"key_1",
263
+ "value"=>"value_1",
264
+ "dimension_value"=>nil
265
+ },
266
+ {
267
+ "id"=>404024,
268
+ "name"=>"key_2",
269
+ "value"=>"value_2",
270
+ "dimension_value"=>nil
271
+ }
272
+ ]
273
+ }
274
+ )
275
+ end
276
+ end
277
+ end
278
+
279
+ context "When querying tags" do
280
+ context "When querying the published version" do
281
+ let(:version) { 'published' }
282
+ it "get a tags list", :vcr do
283
+ expect(subject.tags['data']).to eq(
284
+ {
285
+ "tags"=>[
286
+ {
287
+ "name"=>"my another tag",
288
+ "taggings_count"=>1
289
+ },
290
+ {
291
+ "name"=>"my first tag",
292
+ "taggings_count"=>1
293
+ }
294
+ ]
295
+ }
296
+ )
297
+ end
298
+ end
299
+ end
300
+
301
+ context "When querying links" do
302
+ context "When querying the published version" do
303
+ let(:version) { 'published' }
304
+ it "get a links list", :vcr do
305
+ expect(subject.links['data']).to eq(
306
+ {
307
+ "links" => {
308
+ "4b069560-749d-4f2b-8304-97a2a465fb49"=>{
309
+ "id"=>18409847,
310
+ "is_folder"=>false,
311
+ "is_startpage"=>false,
312
+ "name"=>"simple_content_2",
313
+ "parent_id"=>18409844,
314
+ "position"=>-10,
315
+ "published"=>true,
316
+ "real_path"=>"/my-folder-slug/simple_content_2",
317
+ "slug"=>"my-folder-slug/simple_content_2",
318
+ "uuid"=>"4b069560-749d-4f2b-8304-97a2a465fb49"
319
+ },
320
+ "542e19cc-ff06-4f19-ae64-a725c89e3406"=>{
321
+ "id"=>18409845,
322
+ "is_folder"=>false,
323
+ "is_startpage"=>false,
324
+ "name"=>"simple_content_1",
325
+ "parent_id"=>18409844,
326
+ "position"=>0,
327
+ "published"=>true,
328
+ "real_path"=>"/my-folder-slug/simple_content_1",
329
+ "slug"=>"my-folder-slug/simple_content_1",
330
+ "uuid"=>"542e19cc-ff06-4f19-ae64-a725c89e3406"
331
+ },
332
+ "73330f5f-5dc9-4876-90c6-8ef0f21252a0"=>{
333
+ "id"=>18409844,
334
+ "is_folder"=>true,
335
+ "is_startpage"=>false,
336
+ "name"=>"my_folder_name",
337
+ "parent_id"=>0,
338
+ "position"=>-10,
339
+ "published"=>false,
340
+ "real_path"=>"/my-folder-slug",
341
+ "slug"=>"my-folder-slug",
342
+ "uuid"=>"73330f5f-5dc9-4876-90c6-8ef0f21252a0"
343
+ },
344
+ "fe520269-b092-482c-94c4-8028eb81af41"=>{
345
+ "id"=>18409805,
346
+ "is_folder"=>false,
347
+ "is_startpage"=>false,
348
+ "name"=>"simple_content",
349
+ "parent_id"=>0,
350
+ "position"=>0,
351
+ "published"=>true,
352
+ "real_path"=>"/simple_content",
353
+ "slug"=>"simple_content",
354
+ "uuid"=>"fe520269-b092-482c-94c4-8028eb81af41"
355
+ }
356
+ }
357
+ }
358
+ )
359
+ end
360
+ end
361
+ end
362
+
363
+ context "When querying Space Info" do
364
+ context "When querying the published version", :vcr do
365
+ let(:version) { 'published' }
366
+ it "get the space info" do
367
+ expect(subject.space['data']).to eq(
368
+ {
369
+ "space"=>{
370
+ "id"=>91322,
371
+ "name"=>"My Cool Space",
372
+ "domain"=>"https://quickstart.me.storyblok.com/",
373
+ "version"=>1597954133,
374
+ "language_codes"=>[]
375
+ }
376
+ }
377
+ )
378
+ end
379
+ end
380
+ end
381
+
382
+ context "When getting a content tree" do
383
+ context "When querying the published version" do
384
+ let(:version) { 'published' }
385
+ it "get a content tree", :vcr do
386
+ expect(subject.tree).to eq(
387
+ {
388
+ 18409844 =>
389
+ {
390
+ 'item' =>
391
+ {
392
+ 'id' => 18409844,
393
+ 'slug' => 'my-folder-slug',
394
+ 'name' => 'my_folder_name',
395
+ 'is_folder' => true,
396
+ 'parent_id' => 0,
397
+ 'published' => false,
398
+ 'position' => -10,
399
+ 'uuid' => '73330f5f-5dc9-4876-90c6-8ef0f21252a0',
400
+ 'is_startpage' => false,
401
+ 'real_path' => '/my-folder-slug'
402
+ },
403
+ 'children' =>
404
+ {
405
+ 18409847 =>
406
+ {
407
+ 'item' =>
408
+ {
409
+ 'id' => 18409847,
410
+ 'slug' => 'my-folder-slug/simple_content_2',
411
+ 'name' => 'simple_content_2',
412
+ 'is_folder' => false,
413
+ 'parent_id' => 18409844,
414
+ 'published' => true,
415
+ 'position' => -10,
416
+ 'uuid' => '4b069560-749d-4f2b-8304-97a2a465fb49',
417
+ 'is_startpage' => false,
418
+ 'real_path' => '/my-folder-slug/simple_content_2'
419
+ },
420
+ 'children' => {}
421
+ },
422
+ 18409845 =>
423
+ {
424
+ 'item' =>
425
+ {
426
+ 'id' => 18409845,
427
+ 'slug' => 'my-folder-slug/simple_content_1',
428
+ 'name' => 'simple_content_1',
429
+ 'is_folder' => false,
430
+ 'parent_id' => 18409844,
431
+ 'published' => true,
432
+ 'position' => 0,
433
+ 'uuid' => '542e19cc-ff06-4f19-ae64-a725c89e3406',
434
+ 'is_startpage' => false,
435
+ 'real_path' => '/my-folder-slug/simple_content_1'
436
+ },
437
+ 'children' => {}
438
+ }
439
+ }
440
+ },
441
+ 18409805 =>
442
+ {
443
+ 'item' =>
444
+ {
445
+ 'id' => 18409805,
446
+ 'slug' => 'simple_content',
447
+ 'name' => 'simple_content',
448
+ 'is_folder' => false,
449
+ 'parent_id' => 0,
450
+ 'published' => true,
451
+ 'position' => 0,
452
+ 'uuid' => 'fe520269-b092-482c-94c4-8028eb81af41',
453
+ 'is_startpage' => false,
454
+ 'real_path' => '/simple_content'
455
+ },
456
+ 'children' => {}
457
+ }
458
+ }
459
+ )
460
+ end
461
+ end
462
+ end
463
+
464
+ describe "#get_from_cdn" do
465
+ let(:version) { 'published' }
466
+ it "get a tags list", :vcr do
467
+ expect(subject.get_from_cdn('tags')['data']).to eq(
468
+ {
469
+ "tags"=>[
470
+ {
471
+ "name"=>"my another tag",
472
+ "taggings_count"=>1
473
+ },
474
+ {
475
+ "name"=>"my first tag",
476
+ "taggings_count"=>1
477
+ }
478
+ ]
479
+ }
480
+ )
481
+ end
482
+ end
483
+
484
+ context "When the RestClient::TooManyRequests is raised" do # YOUR API CALL LIMIT HAS BEEN REACHED
485
+ subject { super().tags }
486
+
487
+ let(:version) { 'published' }
488
+ it "auto retry the request for 3 times before raise error" do
489
+ # This cassette was manually edited to allow test this scenario
490
+ VCR.use_cassette('Storyblok_Client/When_querying_CDN_Content/With_token_defined/When_the_RestClient_TooManyRequests_is_raised/auto_retry_the_request_for_3_times_before_raise_error') do
491
+ expect(subject['data']).to eq(
492
+ {
493
+ "tags"=>[
494
+ {
495
+ "name"=>"my another tag",
496
+ "taggings_count"=>1
497
+ },
498
+ {
499
+ "name"=>"my first tag",
500
+ "taggings_count"=>1
501
+ }
502
+ ]
503
+ }
504
+ )
505
+ end
506
+ end
507
+
508
+ it "raises an error after the 3 retry" do
509
+ # This cassette was manually edited to allow test this scenario
510
+ VCR.use_cassette('Storyblok_Client/When_querying_CDN_Content/With_token_defined/When_the_RestClient_TooManyRequests_is_raised/raises an error after the 3 retry') do
511
+ expect{ subject['data'] }.to raise_error(RestClient::TooManyRequests)
512
+ end
513
+ end
514
+ end
515
+
516
+ context "When using a renderer" do
517
+ let(:token) { '<SPACE_PUBLIC_TOKEN>' }
518
+ let(:version) { 'published' }
519
+
520
+ let(:data) {
521
+ {
522
+ 'type' => 'doc',
523
+ 'content' => [
524
+ {
525
+ 'type' => 'paragraph',
526
+ 'content' => [ {'text' => 'Good', 'type' => 'text'}]
527
+ },
528
+ {
529
+ 'type' => 'blok',
530
+ 'attrs' => { 'body' => [{'component' => 'button', 'text' => 'Click me'}] }
531
+ }
532
+ ]
533
+ }
534
+ }
535
+
536
+ context "When setting a renderer at client initialization" do
537
+ subject { described_class.new(api_version: 1, token: token, version: version, component_resolver: component_resolver) }
538
+ let(:component_resolver) { ->(component, data) { "Placeholder for #{component}: #{data['text']}" } }
539
+
540
+ it "returns data rendered with component_resolver" do
541
+ expect(subject.render(data)).to eq("<p>Good</p>Placeholder for button: Click me")
542
+ end
543
+ end
544
+
545
+ context "When setting a renderer after client initialization" do
546
+ subject { described_class.new(api_version: 1, token: token, version: version) }
547
+ let(:component_resolver) { ->(component, data) { "Placeholder for #{component}: #{data['text']}" } }
548
+
549
+ it "set renderer and returns data rendered with component_resolver" do
550
+ subject.set_component_resolver(component_resolver)
551
+ expect(subject.render(data)).to eq("<p>Good</p>Placeholder for button: Click me")
552
+ end
553
+ end
554
+ end
555
+
556
+ context "When caching is enabled", redis_cache: true do
557
+ subject { described_class.new(api_version: 1, token: token, version: version, cache: cache) }
558
+ before { redis_client.keys("storyblok:*").each { |e| redis_client.del(e) } }
559
+ let(:redis_client) {
560
+ raise StandardError, "Environment variable 'REDIS_URL' is not defined" if ENV['REDIS_URL'].nil?
561
+ Redis.new(url: ENV['REDIS_URL'])
562
+ }
563
+
564
+ let(:cache) { Storyblok::Cache::Redis.new(redis: redis_client) }
565
+ let(:token) { '<SPACE_PUBLIC_TOKEN>' }
566
+ let(:version) { 'published' }
567
+ let(:tags_response_expected) { {
568
+ "tags"=>[
569
+ {
570
+ "name"=>"my another tag",
571
+ "taggings_count"=>1
572
+ },
573
+ {
574
+ "name"=>"my first tag",
575
+ "taggings_count"=>1
576
+ }
577
+ ]
578
+ } }
579
+ it "caches the tags list", :vcr do
580
+ expect{ subject.tags }.to change{ redis_client.keys("storyblok:*").size }.from(0).to(2) # stores cache and cache_version
581
+
582
+ expect(subject.tags['data']).to eq(tags_response_expected)
583
+ response_cached = redis_client.get(redis_client.keys("storyblok:<SPACE_PUBLIC_TOKEN>:v:*").first)
584
+ expect(JSON.parse(response_cached)['data']).to eq(tags_response_expected)
585
+ end
586
+
587
+ it "flushes the cache", :vcr do
588
+ subject.tags # caches a request
589
+ expect { subject.flush }.to change { redis_client.get("storyblok:<SPACE_PUBLIC_TOKEN>:version") }.from('0') # generates the next_cache_version
590
+ next_cache_version = redis_client.get("storyblok:<SPACE_PUBLIC_TOKEN>:version")
591
+ next_cache_key_partial = "storyblok:<SPACE_PUBLIC_TOKEN>:v:#{next_cache_version}*"
592
+ expect { subject.tags }.to change { redis_client.keys(next_cache_key_partial).size }.from(0).to(1) # generates the cache using the next_cache_version generated by flush
593
+ expect(subject.tags['data']).to eq(tags_response_expected) # check if response ex correct
594
+ response_cached = redis_client.get(redis_client.keys(next_cache_key_partial).first)
595
+ expect(JSON.parse(response_cached)['data']).to eq(tags_response_expected) # check if the response was correctly cached
596
+ end
597
+ end
598
+ end
599
+ end
600
+
601
+ context "When Managing the Space" do
602
+ context "With oauth_token defined" do
603
+ let(:oauth_token) { '<MY_PERSONAL_ACCESS_TOKEN>' }
604
+ subject { described_class.new(api_version: 1, oauth_token: oauth_token) }
605
+
606
+ context "When performing a GET request" do
607
+ context "Listing spaces" do
608
+ subject { super().get('spaces') }
609
+
610
+ it "returns a space list", :vcr do
611
+ expect(subject['data']).to eq({
612
+ "spaces"=> [
613
+ { "name"=>"Clean Space", "id"=>91322, "euid"=>nil, "owner_id"=>"<OWNER_ID_INTEGER>" },
614
+ { "name"=>"blog_space", "id"=>91112, "euid"=>nil, "owner_id"=>"<OWNER_ID_INTEGER>" },
615
+ { "name"=>"My beta Space", "id"=>88422, "euid"=>"", "owner_id"=>"<OWNER_ID_INTEGER>" },
616
+ { "name"=>"My new Space", "id"=>86092, "euid"=>nil, "owner_id"=>"<OWNER_ID_INTEGER>" },
617
+ { "name"=>"Your demo space", "id"=>85563, "euid"=>nil, "owner_id"=>"<OWNER_ID_INTEGER>" }
618
+ ]
619
+ })
620
+ end
621
+ end
622
+ end
623
+
624
+ context "When performing a POST request" do
625
+ context "Creating a story" do
626
+ subject { super().post("spaces/#{space_id}/stories", story_params) }
627
+ let(:space_id) { 91322 }
628
+ let(:story_params) { { story: { name: 'my awesome new story', slug: 'my-awesome-new-story' } } }
629
+
630
+ it "creates a story", :vcr do
631
+ expect(subject['headers'][:status]).to eq("201 Created")
632
+ expect(subject['data']).to eq({
633
+ "story"=>{
634
+ "name"=>"my awesome new story",
635
+ "parent_id"=>0,
636
+ "group_id"=>"7a015f0b-1585-4e17-8f32-adf2755087bb",
637
+ "alternates"=>[],
638
+ "created_at"=>"2020-08-25T16:23:38.022Z",
639
+ "sort_by_date"=>nil,
640
+ "tag_list"=>[],
641
+ "updated_at"=>"2020-08-25T16:23:38.022Z",
642
+ "published_at"=>nil,
643
+ "id"=>18670449,
644
+ "uuid"=>"defee8f9-0704-4855-aebc-6d37908297ea",
645
+ "is_folder"=>false,
646
+ "content"=>{"component"=>"root", "body"=>[], "_uid"=>"fa221d61-73ba-4435-82a9-26ac1cf4bf11"},
647
+ "published"=>false,
648
+ "slug"=>"my-awesome-new-story",
649
+ "path"=>nil,
650
+ "full_slug"=>"my-awesome-new-story",
651
+ "default_root"=>nil,
652
+ "disble_fe_editor"=>false,
653
+ "parent"=>nil,
654
+ "is_startpage"=>false,
655
+ "unpublished_changes"=>false,
656
+ "meta_data"=>nil,
657
+ "imported_at"=>nil,
658
+ "preview_token"=>{"token"=>"<PREVIEW_TOKEN>", "timestamp"=>"1598372618"},
659
+ "pinned"=>false,
660
+ "breadcrumbs"=>[],
661
+ "publish_at"=>nil,
662
+ "expire_at"=>nil,
663
+ "first_published_at"=>nil,
664
+ "last_author"=>{"id"=>"<OWNER_ID_INTEGER>", "userid"=>"<MY_USER_EMAIL>", "friendly_name"=>"<MY_USER_EMAIL>"},
665
+ "user_ids"=>[],
666
+ "space_role_ids"=>[],
667
+ "translated_slugs"=>[],
668
+ "localized_paths"=>[],
669
+ "position"=>-20,
670
+ "translated_stories"=>[],
671
+ "can_not_view"=>nil
672
+ }
673
+ })
674
+ end
675
+ end
676
+ end
677
+
678
+ context "When performing a PUT request" do
679
+ context "Updating a story" do
680
+ subject { super().put("spaces/#{space_id}/stories/#{story_id}", story_params) }
681
+ let(:space_id) { 91322 }
682
+ let(:story_id) { 18670449 }
683
+ let(:story_params) { { story: { name: 'my awesome updated story' } } }
684
+
685
+ it "updates a story", :vcr do
686
+ expect(subject['headers'][:status]).to eq("200 OK")
687
+ expect(subject['data']).to eq({
688
+ "story"=>{
689
+ "name"=>"my awesome updated story",
690
+ "parent_id"=>0,
691
+ "group_id"=>"7a015f0b-1585-4e17-8f32-adf2755087bb",
692
+ "alternates"=>[],
693
+ "created_at"=>"2020-08-25T16:23:38.022Z",
694
+ "sort_by_date"=>nil,
695
+ "tag_list"=>[],
696
+ "updated_at"=>"2020-08-25T18:03:04.115Z",
697
+ "published_at"=>nil,
698
+ "id"=>18670449,
699
+ "uuid"=>"defee8f9-0704-4855-aebc-6d37908297ea",
700
+ "is_folder"=>false,
701
+ "content"=>{"_uid"=>"fa221d61-73ba-4435-82a9-26ac1cf4bf11", "body"=>[], "component"=>"root"},
702
+ "published"=>false,
703
+ "slug"=>"my-awesome-new-story",
704
+ "path"=>nil,
705
+ "full_slug"=>"my-awesome-new-story",
706
+ "default_root"=>nil,
707
+ "disble_fe_editor"=>false,
708
+ "parent"=>nil,
709
+ "is_startpage"=>false,
710
+ "unpublished_changes"=>true,
711
+ "meta_data"=>nil,
712
+ "imported_at"=>nil,
713
+ "preview_token"=>{"token"=>"d5681a1d0e5d798582a0e6ed791c6bfa1f618e54", "timestamp"=>"1598378584"},
714
+ "pinned"=>false,
715
+ "breadcrumbs"=>[],
716
+ "publish_at"=>nil,
717
+ "expire_at"=>nil,
718
+ "first_published_at"=>nil,
719
+ "last_author"=>{"id"=>"<OWNER_ID_INTEGER>", "userid"=>"<MY_USER_EMAIL>", "friendly_name"=>"<MY_USER_EMAIL>"},
720
+ "user_ids"=>[],
721
+ "space_role_ids"=>[],
722
+ "translated_slugs"=>[],
723
+ "localized_paths"=>[],
724
+ "position"=>-20,
725
+ "translated_stories"=>[],
726
+ "can_not_view"=>nil
727
+ }
728
+ })
729
+ end
730
+ end
731
+ end
732
+
733
+ context "When performing a DELETE request" do
734
+ context "deleting a story" do
735
+ subject { super().delete("spaces/#{space_id}/stories/#{story_id}") }
736
+ let(:space_id) { 91322 }
737
+ let(:story_id) { 18670449 }
738
+ it "deletes a story", :vcr do
739
+ expect(subject['headers'][:status]).to eq("200 OK")
740
+ expect(subject['data']).to eq({
741
+ "story"=> {
742
+ "name"=>"my awesome updated story",
743
+ "parent_id"=>0,
744
+ "group_id"=>"7a015f0b-1585-4e17-8f32-adf2755087bb",
745
+ "alternates"=>[],
746
+ "created_at"=>"2020-08-25T16:23:38.022Z",
747
+ "sort_by_date"=>nil,
748
+ "tag_list"=>[],
749
+ "updated_at"=>"2020-08-25T18:03:04.115Z",
750
+ "published_at"=>nil,
751
+ "id"=>18670449,
752
+ "uuid"=>"defee8f9-0704-4855-aebc-6d37908297ea",
753
+ "is_folder"=>false,
754
+ "content"=>{"_uid"=>"fa221d61-73ba-4435-82a9-26ac1cf4bf11", "body"=>[], "component"=>"root"},
755
+ "published"=>false,
756
+ "slug"=>"my-awesome-new-story",
757
+ "path"=>nil,
758
+ "full_slug"=>"my-awesome-new-story",
759
+ "default_root"=>nil,
760
+ "disble_fe_editor"=>false,
761
+ "parent"=>nil,
762
+ "is_startpage"=>false,
763
+ "unpublished_changes"=>true,
764
+ "meta_data"=>nil,
765
+ "imported_at"=>nil,
766
+ "preview_token"=>{"token"=>"af676cb58efa328b9f6c30251b9212598c66d55b", "timestamp"=>"1598378897"},
767
+ "pinned"=>false,
768
+ "breadcrumbs"=>[],
769
+ "publish_at"=>nil,
770
+ "expire_at"=>nil,
771
+ "first_published_at"=>nil,
772
+ "last_author"=>{"id"=>"<OWNER_ID_INTEGER>", "userid"=>"<MY_USER_EMAIL>", "friendly_name"=>"<MY_USER_EMAIL>"},
773
+ "user_ids"=>[],
774
+ "space_role_ids"=>[],
775
+ "translated_slugs"=>[],
776
+ "localized_paths"=>[],
777
+ "position"=>-20,
778
+ "translated_stories"=>[],
779
+ "can_not_view"=>nil
780
+ }
781
+ })
782
+ end
783
+ end
784
+ end
785
+
786
+ context "When the RestClient::TooManyRequests is raised" do # YOUR API CALL LIMIT HAS BEEN REACHED
787
+ subject { super().get('spaces') }
788
+ it "auto retry the request for 3 times before raise error" do
789
+ # This cassette was manually edited to allow test this scenario
790
+ VCR.use_cassette('Storyblok_Client/When_Managing_the_Space/With_oauth_token_defined/When_the_RestClient_TooManyRequests_is_raised/auto_retry_the_request_for_3_times_before_raise_error') do
791
+ expect(subject['data']).to eq({
792
+ "spaces"=> [
793
+ { "name"=>"Clean Space", "id"=>91322, "euid"=>nil, "owner_id"=>"<OWNER_ID_INTEGER>" },
794
+ { "name"=>"blog_space", "id"=>91112, "euid"=>nil, "owner_id"=>"<OWNER_ID_INTEGER>" },
795
+ { "name"=>"My beta Space", "id"=>88422, "euid"=>"", "owner_id"=>"<OWNER_ID_INTEGER>" },
796
+ { "name"=>"My new Space", "id"=>86092, "euid"=>nil, "owner_id"=>"<OWNER_ID_INTEGER>" },
797
+ { "name"=>"Your demo space", "id"=>85563, "euid"=>nil, "owner_id"=>"<OWNER_ID_INTEGER>" }
798
+ ]
799
+ })
800
+ end
801
+ end
802
+
803
+ it "raises an error after the 3 retry" do
804
+ # This cassette was manually edited to allow test this scenario
805
+ VCR.use_cassette('Storyblok_Client/When_Managing_the_Space/With_oauth_token_defined/When_the_RestClient_TooManyRequests_is_raised/raises an error after the 3 retry') do
806
+ expect{ subject['data'] }.to raise_error(RestClient::TooManyRequests)
807
+ end
808
+ end
809
+ end
810
+ end
811
+ end
812
+ end