storyblok 2.0.7 → 3.0.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.
@@ -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