interaktor 0.1.3

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,67 @@
1
+ module Interaktor::Organizer
2
+ # When the Interaktor::Organizer module is included in a class, add the
3
+ # relevant class methods and hooks to that class.
4
+ #
5
+ # @param base [Class] the class which is including the Interaktor::Organizer
6
+ # module
7
+ def self.included(base)
8
+ base.class_eval do
9
+ include Interaktor
10
+
11
+ extend ClassMethods
12
+ include InstanceMethods
13
+ end
14
+ end
15
+
16
+ module ClassMethods
17
+ # Declare Interaktors to be invoked as part of the Interaktor::Organizer's
18
+ # invocation. These interaktors are invoked in the order in which they are
19
+ # declared.
20
+ #
21
+ # @param interaktors [Interaktor, Array<Interaktor>]
22
+ #
23
+ # @return [void]
24
+ def organize(*interaktors)
25
+ organized.concat(interaktors.flatten)
26
+ end
27
+
28
+ # An array of declared Interaktors to be invoked.
29
+ #
30
+ # @return [Array<Interaktor>]
31
+ def organized
32
+ @organized ||= []
33
+ end
34
+ end
35
+
36
+ module InstanceMethods
37
+ # Invoke the organized Interaktors. An Interaktor::Organizer is expected
38
+ # NOT to define its own `#call` in favor of this default implementation.
39
+ #
40
+ # @return [void]
41
+ def call
42
+ self.class.organized.each do |interaktor|
43
+ interaktor.call!(context)
44
+ end
45
+ end
46
+
47
+ private
48
+
49
+ # A list of attributes required to invoke the organized Interaktors.
50
+ # Obtained by compiling a list of all required attributes of all organized
51
+ # interaktors. Duplicates are removed.
52
+ #
53
+ # @return [Array<Symbol>]
54
+ def required_attributes
55
+ self.class.organized.map(&:required_attributes).flatten.uniq
56
+ end
57
+
58
+ # A list of optional attributes allowed to be included when invoking the
59
+ # organized Interaktors. Obtained by compiling a list of all optional
60
+ # attributes of all organized interaktors. Duplicates are removed.
61
+ #
62
+ # @return [Array<Symbol>]
63
+ def optional_attributes
64
+ self.class.organized.map(&:optional_attributes).flatten.uniq
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,1786 @@
1
+ describe "Integration" do
2
+ def build_interaktor(&block)
3
+ interaktor = Class.new.send(:include, Interaktor)
4
+ interaktor.class_eval(&block) if block
5
+ interaktor.class_eval do
6
+ def unexpected_error!
7
+ raise "foo"
8
+ end
9
+ end
10
+ interaktor
11
+ end
12
+
13
+ def build_organizer(options = {}, &block)
14
+ organizer = Class.new.send(:include, Interaktor::Organizer)
15
+ organizer.organize(options[:organize]) if options[:organize]
16
+ organizer.class_eval(&block) if block
17
+ organizer.class_eval do
18
+ def unexpected_error!
19
+ raise "foo"
20
+ end
21
+ end
22
+ organizer
23
+ end
24
+
25
+ # rubocop:disable Style/AsciiComments
26
+ #
27
+ # organizer
28
+ # ├─ organizer2
29
+ # │ ├─ interaktor2a
30
+ # │ ├─ interaktor2b
31
+ # │ └─ interaktor2c
32
+ # ├─ interaktor3
33
+ # ├─ organizer4
34
+ # │ ├─ interaktor4a
35
+ # │ ├─ interaktor4b
36
+ # │ └─ interaktor4c
37
+ # └─ interaktor5
38
+ #
39
+ # rubocop:enable Style/AsciiComments
40
+
41
+ let(:organizer) {
42
+ interaktors = [organizer2, interaktor3, organizer4, interaktor5]
43
+ build_organizer(organize: interaktors) do
44
+ around do |interaktor|
45
+ context.steps << :around_before
46
+ interaktor.call
47
+ context.steps << :around_after
48
+ end
49
+
50
+ before do
51
+ context.steps << :before
52
+ end
53
+
54
+ after do
55
+ context.steps << :after
56
+ end
57
+ end
58
+ }
59
+
60
+ let(:organizer2) {
61
+ build_organizer(organize: [interaktor2a, interaktor2b, interaktor2c]) do
62
+ around do |interaktor|
63
+ context.steps << :around_before2
64
+ interaktor.call
65
+ context.steps << :around_after2
66
+ end
67
+
68
+ before do
69
+ context.steps << :before2
70
+ end
71
+
72
+ after do
73
+ context.steps << :after2
74
+ end
75
+ end
76
+ }
77
+
78
+ let(:interaktor2a) {
79
+ build_interaktor do
80
+ around do |interaktor|
81
+ context.steps << :around_before2a
82
+ interaktor.call
83
+ context.steps << :around_after2a
84
+ end
85
+
86
+ before do
87
+ context.steps << :before2a
88
+ end
89
+
90
+ after do
91
+ context.steps << :after2a
92
+ end
93
+
94
+ def call
95
+ context.steps << :call2a
96
+ end
97
+
98
+ def rollback
99
+ context.steps << :rollback2a
100
+ end
101
+ end
102
+ }
103
+
104
+ let(:interaktor2b) {
105
+ build_interaktor do
106
+ around do |interaktor|
107
+ context.steps << :around_before2b
108
+ interaktor.call
109
+ context.steps << :around_after2b
110
+ end
111
+
112
+ before do
113
+ context.steps << :before2b
114
+ end
115
+
116
+ after do
117
+ context.steps << :after2b
118
+ end
119
+
120
+ def call
121
+ context.steps << :call2b
122
+ end
123
+
124
+ def rollback
125
+ context.steps << :rollback2b
126
+ end
127
+ end
128
+ }
129
+
130
+ let(:interaktor2c) {
131
+ build_interaktor do
132
+ around do |interaktor|
133
+ context.steps << :around_before2c
134
+ interaktor.call
135
+ context.steps << :around_after2c
136
+ end
137
+
138
+ before do
139
+ context.steps << :before2c
140
+ end
141
+
142
+ after do
143
+ context.steps << :after2c
144
+ end
145
+
146
+ def call
147
+ context.steps << :call2c
148
+ end
149
+
150
+ def rollback
151
+ context.steps << :rollback2c
152
+ end
153
+ end
154
+ }
155
+
156
+ let(:interaktor3) {
157
+ build_interaktor do
158
+ around do |interaktor|
159
+ context.steps << :around_before3
160
+ interaktor.call
161
+ context.steps << :around_after3
162
+ end
163
+
164
+ before do
165
+ context.steps << :before3
166
+ end
167
+
168
+ after do
169
+ context.steps << :after3
170
+ end
171
+
172
+ def call
173
+ context.steps << :call3
174
+ end
175
+
176
+ def rollback
177
+ context.steps << :rollback3
178
+ end
179
+ end
180
+ }
181
+
182
+ let(:organizer4) {
183
+ build_organizer(organize: [interaktor4a, interaktor4b, interaktor4c]) do
184
+ around do |interaktor|
185
+ context.steps << :around_before4
186
+ interaktor.call
187
+ context.steps << :around_after4
188
+ end
189
+
190
+ before do
191
+ context.steps << :before4
192
+ end
193
+
194
+ after do
195
+ context.steps << :after4
196
+ end
197
+ end
198
+ }
199
+
200
+ let(:interaktor4a) {
201
+ build_interaktor do
202
+ around do |interaktor|
203
+ context.steps << :around_before4a
204
+ interaktor.call
205
+ context.steps << :around_after4a
206
+ end
207
+
208
+ before do
209
+ context.steps << :before4a
210
+ end
211
+
212
+ after do
213
+ context.steps << :after4a
214
+ end
215
+
216
+ def call
217
+ context.steps << :call4a
218
+ end
219
+
220
+ def rollback
221
+ context.steps << :rollback4a
222
+ end
223
+ end
224
+ }
225
+
226
+ let(:interaktor4b) {
227
+ build_interaktor do
228
+ around do |interaktor|
229
+ context.steps << :around_before4b
230
+ interaktor.call
231
+ context.steps << :around_after4b
232
+ end
233
+
234
+ before do
235
+ context.steps << :before4b
236
+ end
237
+
238
+ after do
239
+ context.steps << :after4b
240
+ end
241
+
242
+ def call
243
+ context.steps << :call4b
244
+ end
245
+
246
+ def rollback
247
+ context.steps << :rollback4b
248
+ end
249
+ end
250
+ }
251
+
252
+ let(:interaktor4c) {
253
+ build_interaktor do
254
+ around do |interaktor|
255
+ context.steps << :around_before4c
256
+ interaktor.call
257
+ context.steps << :around_after4c
258
+ end
259
+
260
+ before do
261
+ context.steps << :before4c
262
+ end
263
+
264
+ after do
265
+ context.steps << :after4c
266
+ end
267
+
268
+ def call
269
+ context.steps << :call4c
270
+ end
271
+
272
+ def rollback
273
+ context.steps << :rollback4c
274
+ end
275
+ end
276
+ }
277
+
278
+ let(:interaktor5) {
279
+ build_interaktor do
280
+ around do |interaktor|
281
+ context.steps << :around_before5
282
+ interaktor.call
283
+ context.steps << :around_after5
284
+ end
285
+
286
+ before do
287
+ context.steps << :before5
288
+ end
289
+
290
+ after do
291
+ context.steps << :after5
292
+ end
293
+
294
+ def call
295
+ context.steps << :call5
296
+ end
297
+
298
+ def rollback
299
+ context.steps << :rollback5
300
+ end
301
+ end
302
+ }
303
+
304
+ let(:context) { Interaktor::Context.new(steps: []) }
305
+
306
+ context "when successful" do
307
+ it "calls and runs hooks in the proper sequence" do
308
+ expect {
309
+ organizer.call(context)
310
+ }.to change(context, :steps).from([]).to([
311
+ :around_before, :before,
312
+ :around_before2, :before2,
313
+ :around_before2a, :before2a, :call2a, :after2a, :around_after2a,
314
+ :around_before2b, :before2b, :call2b, :after2b, :around_after2b,
315
+ :around_before2c, :before2c, :call2c, :after2c, :around_after2c,
316
+ :after2, :around_after2,
317
+ :around_before3, :before3, :call3, :after3, :around_after3,
318
+ :around_before4, :before4,
319
+ :around_before4a, :before4a, :call4a, :after4a, :around_after4a,
320
+ :around_before4b, :before4b, :call4b, :after4b, :around_after4b,
321
+ :around_before4c, :before4c, :call4c, :after4c, :around_after4c,
322
+ :after4, :around_after4,
323
+ :around_before5, :before5, :call5, :after5, :around_after5,
324
+ :after, :around_after,
325
+ ])
326
+ end
327
+ end
328
+
329
+ context "when an around hook fails early" do
330
+ let(:organizer) {
331
+ interaktors = [organizer2, interaktor3, organizer4, interaktor5]
332
+ build_organizer(organize: interaktors) do
333
+ around do |interaktor|
334
+ context.fail!
335
+ context.steps << :around_before
336
+ interaktor.call
337
+ context.steps << :around_after
338
+ end
339
+
340
+ before do
341
+ context.fail!
342
+ context.steps << :before
343
+ end
344
+
345
+ after do
346
+ context.steps << :after
347
+ end
348
+ end
349
+ }
350
+
351
+ it "aborts" do
352
+ expect {
353
+ organizer.call(context)
354
+ }.not_to change(context, :steps)
355
+ end
356
+ end
357
+
358
+ context "when an around hook errors early" do
359
+ let(:organizer) {
360
+ interaktors = [organizer2, interaktor3, organizer4, interaktor5]
361
+ build_organizer(organize: interaktors) do
362
+ around do |interaktor|
363
+ unexpected_error!
364
+ context.steps << :around_before
365
+ interaktor.call
366
+ context.steps << :around_after
367
+ end
368
+
369
+ before do
370
+ context.fail!
371
+ context.steps << :before
372
+ end
373
+
374
+ after do
375
+ context.steps << :after
376
+ end
377
+ end
378
+ }
379
+
380
+ it "aborts" do
381
+ expect {
382
+ begin
383
+ organizer.call(context)
384
+ rescue StandardError
385
+ nil
386
+ end
387
+ }.not_to change(context, :steps)
388
+ end
389
+
390
+ it "raises the error" do
391
+ expect {
392
+ organizer.call(context)
393
+ }.to raise_error("foo")
394
+ end
395
+ end
396
+
397
+ context "when a before hook fails" do
398
+ let(:organizer) {
399
+ interaktors = [organizer2, interaktor3, organizer4, interaktor5]
400
+ build_organizer(organize: interaktors) do
401
+ around do |interaktor|
402
+ context.steps << :around_before
403
+ interaktor.call
404
+ context.steps << :around_after
405
+ end
406
+
407
+ before do
408
+ context.fail!
409
+ context.steps << :before
410
+ end
411
+
412
+ after do
413
+ context.steps << :after
414
+ end
415
+ end
416
+ }
417
+
418
+ it "aborts" do
419
+ expect {
420
+ organizer.call(context)
421
+ }.to change(context, :steps).from([]).to([
422
+ :around_before,
423
+ ])
424
+ end
425
+ end
426
+
427
+ context "when a before hook errors" do
428
+ let(:organizer) {
429
+ interaktors = [organizer2, interaktor3, organizer4, interaktor5]
430
+ build_organizer(organize: interaktors) do
431
+ around do |interaktor|
432
+ context.steps << :around_before
433
+ interaktor.call
434
+ context.steps << :around_after
435
+ end
436
+
437
+ before do
438
+ unexpected_error!
439
+ context.steps << :before
440
+ end
441
+
442
+ after do
443
+ context.steps << :after
444
+ end
445
+ end
446
+ }
447
+
448
+ it "aborts" do
449
+ expect {
450
+ begin
451
+ organizer.call(context)
452
+ rescue StandardError
453
+ nil
454
+ end
455
+ }.to change(context, :steps).from([]).to([
456
+ :around_before,
457
+ ])
458
+ end
459
+
460
+ it "raises the error" do
461
+ expect {
462
+ organizer.call(context)
463
+ }.to raise_error("foo")
464
+ end
465
+ end
466
+
467
+ context "when an after hook fails" do
468
+ let(:organizer) {
469
+ interaktors = [organizer2, interaktor3, organizer4, interaktor5]
470
+ build_organizer(organize: interaktors) do
471
+ around do |interaktor|
472
+ context.steps << :around_before
473
+ interaktor.call
474
+ context.steps << :around_after
475
+ end
476
+
477
+ before do
478
+ context.steps << :before
479
+ end
480
+
481
+ after do
482
+ context.fail!
483
+ context.steps << :after
484
+ end
485
+ end
486
+ }
487
+
488
+ it "rolls back successfully called interaktors and the failed interaktor" do
489
+ expect {
490
+ organizer.call(context)
491
+ }.to change(context, :steps).from([]).to([
492
+ :around_before, :before,
493
+ :around_before2, :before2,
494
+ :around_before2a, :before2a, :call2a, :after2a, :around_after2a,
495
+ :around_before2b, :before2b, :call2b, :after2b, :around_after2b,
496
+ :around_before2c, :before2c, :call2c, :after2c, :around_after2c,
497
+ :after2, :around_after2,
498
+ :around_before3, :before3, :call3, :after3, :around_after3,
499
+ :around_before4, :before4,
500
+ :around_before4a, :before4a, :call4a, :after4a, :around_after4a,
501
+ :around_before4b, :before4b, :call4b, :after4b, :around_after4b,
502
+ :around_before4c, :before4c, :call4c, :after4c, :around_after4c,
503
+ :after4, :around_after4,
504
+ :around_before5, :before5, :call5, :after5, :around_after5,
505
+ :rollback5,
506
+ :rollback4c,
507
+ :rollback4b,
508
+ :rollback4a,
509
+ :rollback3,
510
+ :rollback2c,
511
+ :rollback2b,
512
+ :rollback2a,
513
+ ])
514
+ end
515
+ end
516
+
517
+ context "when an after hook errors" do
518
+ let(:organizer) {
519
+ interaktors = [organizer2, interaktor3, organizer4, interaktor5]
520
+ build_organizer(organize: interaktors) do
521
+ around do |interaktor|
522
+ context.steps << :around_before
523
+ interaktor.call
524
+ context.steps << :around_after
525
+ end
526
+
527
+ before do
528
+ context.steps << :before
529
+ end
530
+
531
+ after do
532
+ unexpected_error!
533
+ context.steps << :after
534
+ end
535
+ end
536
+ }
537
+
538
+ it "rolls back successfully called interaktors and the failed interaktor" do
539
+ expect {
540
+ begin
541
+ organizer.call(context)
542
+ rescue StandardError
543
+ nil
544
+ end
545
+ }.to change(context, :steps).from([]).to([
546
+ :around_before, :before,
547
+ :around_before2, :before2,
548
+ :around_before2a, :before2a, :call2a, :after2a, :around_after2a,
549
+ :around_before2b, :before2b, :call2b, :after2b, :around_after2b,
550
+ :around_before2c, :before2c, :call2c, :after2c, :around_after2c,
551
+ :after2, :around_after2,
552
+ :around_before3, :before3, :call3, :after3, :around_after3,
553
+ :around_before4, :before4,
554
+ :around_before4a, :before4a, :call4a, :after4a, :around_after4a,
555
+ :around_before4b, :before4b, :call4b, :after4b, :around_after4b,
556
+ :around_before4c, :before4c, :call4c, :after4c, :around_after4c,
557
+ :after4, :around_after4,
558
+ :around_before5, :before5, :call5, :after5, :around_after5,
559
+ :rollback5,
560
+ :rollback4c,
561
+ :rollback4b,
562
+ :rollback4a,
563
+ :rollback3,
564
+ :rollback2c,
565
+ :rollback2b,
566
+ :rollback2a,
567
+ ])
568
+ end
569
+
570
+ it "raises the error" do
571
+ expect {
572
+ organizer.call(context)
573
+ }.to raise_error("foo")
574
+ end
575
+ end
576
+
577
+ context "when an around hook fails late" do
578
+ let(:organizer) {
579
+ interaktors = [organizer2, interaktor3, organizer4, interaktor5]
580
+ build_organizer(organize: interaktors) do
581
+ around do |interaktor|
582
+ context.steps << :around_before
583
+ interaktor.call
584
+ context.fail!
585
+ context.steps << :around_after
586
+ end
587
+
588
+ before do
589
+ context.steps << :before
590
+ end
591
+
592
+ after do
593
+ context.steps << :after
594
+ end
595
+ end
596
+ }
597
+
598
+ it "rolls back successfully called interaktors and the failed interaktor" do
599
+ expect {
600
+ organizer.call(context)
601
+ }.to change(context, :steps).from([]).to([
602
+ :around_before, :before,
603
+ :around_before2, :before2,
604
+ :around_before2a, :before2a, :call2a, :after2a, :around_after2a,
605
+ :around_before2b, :before2b, :call2b, :after2b, :around_after2b,
606
+ :around_before2c, :before2c, :call2c, :after2c, :around_after2c,
607
+ :after2, :around_after2,
608
+ :around_before3, :before3, :call3, :after3, :around_after3,
609
+ :around_before4, :before4,
610
+ :around_before4a, :before4a, :call4a, :after4a, :around_after4a,
611
+ :around_before4b, :before4b, :call4b, :after4b, :around_after4b,
612
+ :around_before4c, :before4c, :call4c, :after4c, :around_after4c,
613
+ :after4, :around_after4,
614
+ :around_before5, :before5, :call5, :after5, :around_after5,
615
+ :after,
616
+ :rollback5,
617
+ :rollback4c,
618
+ :rollback4b,
619
+ :rollback4a,
620
+ :rollback3,
621
+ :rollback2c,
622
+ :rollback2b,
623
+ :rollback2a,
624
+ ])
625
+ end
626
+ end
627
+
628
+ context "when an around hook errors late" do
629
+ let(:organizer) {
630
+ interaktors = [organizer2, interaktor3, organizer4, interaktor5]
631
+ build_organizer(organize: interaktors) do
632
+ around do |interaktor|
633
+ context.steps << :around_before
634
+ interaktor.call
635
+ unexpected_error!
636
+ context.steps << :around_after
637
+ end
638
+
639
+ before do
640
+ context.steps << :before
641
+ end
642
+
643
+ after do
644
+ context.steps << :after
645
+ end
646
+ end
647
+ }
648
+
649
+ it "rolls back successfully called interaktors and the failed interaktor" do
650
+ expect {
651
+ begin
652
+ organizer.call(context)
653
+ rescue StandardError
654
+ nil
655
+ end
656
+ }.to change(context, :steps).from([]).to([
657
+ :around_before, :before,
658
+ :around_before2, :before2,
659
+ :around_before2a, :before2a, :call2a, :after2a, :around_after2a,
660
+ :around_before2b, :before2b, :call2b, :after2b, :around_after2b,
661
+ :around_before2c, :before2c, :call2c, :after2c, :around_after2c,
662
+ :after2, :around_after2,
663
+ :around_before3, :before3, :call3, :after3, :around_after3,
664
+ :around_before4, :before4,
665
+ :around_before4a, :before4a, :call4a, :after4a, :around_after4a,
666
+ :around_before4b, :before4b, :call4b, :after4b, :around_after4b,
667
+ :around_before4c, :before4c, :call4c, :after4c, :around_after4c,
668
+ :after4, :around_after4,
669
+ :around_before5, :before5, :call5, :after5, :around_after5,
670
+ :after,
671
+ :rollback5,
672
+ :rollback4c,
673
+ :rollback4b,
674
+ :rollback4a,
675
+ :rollback3,
676
+ :rollback2c,
677
+ :rollback2b,
678
+ :rollback2a,
679
+ ])
680
+ end
681
+
682
+ it "raises the error" do
683
+ expect {
684
+ organizer.call(context)
685
+ }.to raise_error("foo")
686
+ end
687
+ end
688
+
689
+ context "when a nested around hook fails early" do
690
+ let(:interaktor3) {
691
+ build_interaktor do
692
+ around do |interaktor|
693
+ context.fail!
694
+ context.steps << :around_before3
695
+ interaktor.call
696
+ context.steps << :around_after3
697
+ end
698
+
699
+ before do
700
+ context.steps << :before3
701
+ end
702
+
703
+ after do
704
+ context.steps << :after3
705
+ end
706
+
707
+ def call
708
+ context.steps << :call3
709
+ end
710
+
711
+ def rollback
712
+ context.steps << :rollback3
713
+ end
714
+ end
715
+ }
716
+
717
+ it "rolls back successfully called interaktors" do
718
+ expect {
719
+ organizer.call(context)
720
+ }.to change(context, :steps).from([]).to([
721
+ :around_before, :before,
722
+ :around_before2, :before2,
723
+ :around_before2a, :before2a, :call2a, :after2a, :around_after2a,
724
+ :around_before2b, :before2b, :call2b, :after2b, :around_after2b,
725
+ :around_before2c, :before2c, :call2c, :after2c, :around_after2c,
726
+ :after2, :around_after2,
727
+ :rollback2c,
728
+ :rollback2b,
729
+ :rollback2a,
730
+ ])
731
+ end
732
+ end
733
+
734
+ context "when a nested around hook errors early" do
735
+ let(:interaktor3) {
736
+ build_interaktor do
737
+ around do |interaktor|
738
+ unexpected_error!
739
+ context.steps << :around_before3
740
+ interaktor.call
741
+ context.steps << :around_after3
742
+ end
743
+
744
+ before do
745
+ context.steps << :before3
746
+ end
747
+
748
+ after do
749
+ context.steps << :after3
750
+ end
751
+
752
+ def call
753
+ context.steps << :call3
754
+ end
755
+
756
+ def rollback
757
+ context.steps << :rollback3
758
+ end
759
+ end
760
+ }
761
+
762
+ it "rolls back successfully called interaktors" do
763
+ expect {
764
+ begin
765
+ organizer.call(context)
766
+ rescue StandardError
767
+ nil
768
+ end
769
+ }.to change(context, :steps).from([]).to([
770
+ :around_before, :before,
771
+ :around_before2, :before2,
772
+ :around_before2a, :before2a, :call2a, :after2a, :around_after2a,
773
+ :around_before2b, :before2b, :call2b, :after2b, :around_after2b,
774
+ :around_before2c, :before2c, :call2c, :after2c, :around_after2c,
775
+ :after2, :around_after2,
776
+ :rollback2c,
777
+ :rollback2b,
778
+ :rollback2a,
779
+ ])
780
+ end
781
+
782
+ it "raises the error" do
783
+ expect {
784
+ organizer.call(context)
785
+ }.to raise_error("foo")
786
+ end
787
+ end
788
+
789
+ context "when a nested before hook fails" do
790
+ let(:interaktor3) {
791
+ build_interaktor do
792
+ around do |interaktor|
793
+ context.steps << :around_before3
794
+ interaktor.call
795
+ context.steps << :around_after3
796
+ end
797
+
798
+ before do
799
+ context.fail!
800
+ context.steps << :before3
801
+ end
802
+
803
+ after do
804
+ context.steps << :after3
805
+ end
806
+
807
+ def call
808
+ context.steps << :call3
809
+ end
810
+
811
+ def rollback
812
+ context.steps << :rollback3
813
+ end
814
+ end
815
+ }
816
+
817
+ it "rolls back successfully called interaktors" do
818
+ expect {
819
+ organizer.call(context)
820
+ }.to change(context, :steps).from([]).to([
821
+ :around_before, :before,
822
+ :around_before2, :before2,
823
+ :around_before2a, :before2a, :call2a, :after2a, :around_after2a,
824
+ :around_before2b, :before2b, :call2b, :after2b, :around_after2b,
825
+ :around_before2c, :before2c, :call2c, :after2c, :around_after2c,
826
+ :after2, :around_after2,
827
+ :around_before3,
828
+ :rollback2c,
829
+ :rollback2b,
830
+ :rollback2a,
831
+ ])
832
+ end
833
+ end
834
+
835
+ context "when a nested before hook errors" do
836
+ let(:interaktor3) {
837
+ build_interaktor do
838
+ around do |interaktor|
839
+ context.steps << :around_before3
840
+ interaktor.call
841
+ context.steps << :around_after3
842
+ end
843
+
844
+ before do
845
+ unexpected_error!
846
+ context.steps << :before3
847
+ end
848
+
849
+ after do
850
+ context.steps << :after3
851
+ end
852
+
853
+ def call
854
+ context.steps << :call3
855
+ end
856
+
857
+ def rollback
858
+ context.steps << :rollback3
859
+ end
860
+ end
861
+ }
862
+
863
+ it "rolls back successfully called interaktors" do
864
+ expect {
865
+ begin
866
+ organizer.call(context)
867
+ rescue StandardError
868
+ nil
869
+ end
870
+ }.to change(context, :steps).from([]).to([
871
+ :around_before, :before,
872
+ :around_before2, :before2,
873
+ :around_before2a, :before2a, :call2a, :after2a, :around_after2a,
874
+ :around_before2b, :before2b, :call2b, :after2b, :around_after2b,
875
+ :around_before2c, :before2c, :call2c, :after2c, :around_after2c,
876
+ :after2, :around_after2,
877
+ :around_before3,
878
+ :rollback2c,
879
+ :rollback2b,
880
+ :rollback2a,
881
+ ])
882
+ end
883
+
884
+ it "raises the error" do
885
+ expect {
886
+ organizer.call(context)
887
+ }.to raise_error("foo")
888
+ end
889
+ end
890
+
891
+ context "when a nested call fails" do
892
+ let(:interaktor3) {
893
+ build_interaktor do
894
+ around do |interaktor|
895
+ context.steps << :around_before3
896
+ interaktor.call
897
+ context.steps << :around_after3
898
+ end
899
+
900
+ before do
901
+ context.steps << :before3
902
+ end
903
+
904
+ after do
905
+ context.steps << :after3
906
+ end
907
+
908
+ def call
909
+ context.fail!
910
+ context.steps << :call3
911
+ end
912
+
913
+ def rollback
914
+ context.steps << :rollback3
915
+ end
916
+ end
917
+ }
918
+
919
+ it "rolls back successfully called interaktors" do
920
+ expect {
921
+ organizer.call(context)
922
+ }.to change(context, :steps).from([]).to([
923
+ :around_before, :before,
924
+ :around_before2, :before2,
925
+ :around_before2a, :before2a, :call2a, :after2a, :around_after2a,
926
+ :around_before2b, :before2b, :call2b, :after2b, :around_after2b,
927
+ :around_before2c, :before2c, :call2c, :after2c, :around_after2c,
928
+ :after2, :around_after2,
929
+ :around_before3, :before3,
930
+ :rollback2c,
931
+ :rollback2b,
932
+ :rollback2a,
933
+ ])
934
+ end
935
+ end
936
+
937
+ context "when a nested call errors" do
938
+ let(:interaktor3) {
939
+ build_interaktor do
940
+ around do |interaktor|
941
+ context.steps << :around_before3
942
+ interaktor.call
943
+ context.steps << :around_after3
944
+ end
945
+
946
+ before do
947
+ context.steps << :before3
948
+ end
949
+
950
+ after do
951
+ context.steps << :after3
952
+ end
953
+
954
+ def call
955
+ unexpected_error!
956
+ context.steps << :call3
957
+ end
958
+
959
+ def rollback
960
+ context.steps << :rollback3
961
+ end
962
+ end
963
+ }
964
+
965
+ it "rolls back successfully called interaktors" do
966
+ expect {
967
+ begin
968
+ organizer.call(context)
969
+ rescue StandardError
970
+ nil
971
+ end
972
+ }.to change(context, :steps).from([]).to([
973
+ :around_before, :before,
974
+ :around_before2, :before2,
975
+ :around_before2a, :before2a, :call2a, :after2a, :around_after2a,
976
+ :around_before2b, :before2b, :call2b, :after2b, :around_after2b,
977
+ :around_before2c, :before2c, :call2c, :after2c, :around_after2c,
978
+ :after2, :around_after2,
979
+ :around_before3, :before3,
980
+ :rollback2c,
981
+ :rollback2b,
982
+ :rollback2a,
983
+ ])
984
+ end
985
+
986
+ it "raises the error" do
987
+ expect {
988
+ organizer.call(context)
989
+ }.to raise_error("foo")
990
+ end
991
+ end
992
+
993
+ context "when a nested after hook fails" do
994
+ let(:interaktor3) {
995
+ build_interaktor do
996
+ around do |interaktor|
997
+ context.steps << :around_before3
998
+ interaktor.call
999
+ context.steps << :around_after3
1000
+ end
1001
+
1002
+ before do
1003
+ context.steps << :before3
1004
+ end
1005
+
1006
+ after do
1007
+ context.fail!
1008
+ context.steps << :after3
1009
+ end
1010
+
1011
+ def call
1012
+ context.steps << :call3
1013
+ end
1014
+
1015
+ def rollback
1016
+ context.steps << :rollback3
1017
+ end
1018
+ end
1019
+ }
1020
+
1021
+ it "rolls back successfully called interaktors and the failed interaktor" do
1022
+ expect {
1023
+ organizer.call(context)
1024
+ }.to change(context, :steps).from([]).to([
1025
+ :around_before, :before,
1026
+ :around_before2, :before2,
1027
+ :around_before2a, :before2a, :call2a, :after2a, :around_after2a,
1028
+ :around_before2b, :before2b, :call2b, :after2b, :around_after2b,
1029
+ :around_before2c, :before2c, :call2c, :after2c, :around_after2c,
1030
+ :after2, :around_after2,
1031
+ :around_before3, :before3, :call3,
1032
+ :rollback3,
1033
+ :rollback2c,
1034
+ :rollback2b,
1035
+ :rollback2a,
1036
+ ])
1037
+ end
1038
+ end
1039
+
1040
+ context "when a nested after hook errors" do
1041
+ let(:interaktor3) {
1042
+ build_interaktor do
1043
+ around do |interaktor|
1044
+ context.steps << :around_before3
1045
+ interaktor.call
1046
+ context.steps << :around_after3
1047
+ end
1048
+
1049
+ before do
1050
+ context.steps << :before3
1051
+ end
1052
+
1053
+ after do
1054
+ unexpected_error!
1055
+ context.steps << :after3
1056
+ end
1057
+
1058
+ def call
1059
+ context.steps << :call3
1060
+ end
1061
+
1062
+ def rollback
1063
+ context.steps << :rollback3
1064
+ end
1065
+ end
1066
+ }
1067
+
1068
+ it "rolls back successfully called interaktors and the failed interaktor" do
1069
+ expect {
1070
+ begin
1071
+ organizer.call(context)
1072
+ rescue StandardError
1073
+ nil
1074
+ end
1075
+ }.to change(context, :steps).from([]).to([
1076
+ :around_before, :before,
1077
+ :around_before2, :before2,
1078
+ :around_before2a, :before2a, :call2a, :after2a, :around_after2a,
1079
+ :around_before2b, :before2b, :call2b, :after2b, :around_after2b,
1080
+ :around_before2c, :before2c, :call2c, :after2c, :around_after2c,
1081
+ :after2, :around_after2,
1082
+ :around_before3, :before3, :call3,
1083
+ :rollback3,
1084
+ :rollback2c,
1085
+ :rollback2b,
1086
+ :rollback2a,
1087
+ ])
1088
+ end
1089
+
1090
+ it "raises the error" do
1091
+ expect {
1092
+ organizer.call(context)
1093
+ }.to raise_error("foo")
1094
+ end
1095
+ end
1096
+
1097
+ context "when a nested around hook fails late" do
1098
+ let(:interaktor3) {
1099
+ build_interaktor do
1100
+ around do |interaktor|
1101
+ context.steps << :around_before3
1102
+ interaktor.call
1103
+ context.fail!
1104
+ context.steps << :around_after3
1105
+ end
1106
+
1107
+ before do
1108
+ context.steps << :before3
1109
+ end
1110
+
1111
+ after do
1112
+ context.steps << :after3
1113
+ end
1114
+
1115
+ def call
1116
+ context.steps << :call3
1117
+ end
1118
+
1119
+ def rollback
1120
+ context.steps << :rollback3
1121
+ end
1122
+ end
1123
+ }
1124
+
1125
+ it "rolls back successfully called interaktors and the failed interaktor" do
1126
+ expect {
1127
+ organizer.call(context)
1128
+ }.to change(context, :steps).from([]).to([
1129
+ :around_before, :before,
1130
+ :around_before2, :before2,
1131
+ :around_before2a, :before2a, :call2a, :after2a, :around_after2a,
1132
+ :around_before2b, :before2b, :call2b, :after2b, :around_after2b,
1133
+ :around_before2c, :before2c, :call2c, :after2c, :around_after2c,
1134
+ :after2, :around_after2,
1135
+ :around_before3, :before3, :call3, :after3,
1136
+ :rollback3,
1137
+ :rollback2c,
1138
+ :rollback2b,
1139
+ :rollback2a,
1140
+ ])
1141
+ end
1142
+ end
1143
+
1144
+ context "when a nested around hook errors late" do
1145
+ let(:interaktor3) {
1146
+ build_interaktor do
1147
+ around do |interaktor|
1148
+ context.steps << :around_before3
1149
+ interaktor.call
1150
+ unexpected_error!
1151
+ context.steps << :around_after3
1152
+ end
1153
+
1154
+ before do
1155
+ context.steps << :before3
1156
+ end
1157
+
1158
+ after do
1159
+ context.steps << :after3
1160
+ end
1161
+
1162
+ def call
1163
+ context.steps << :call3
1164
+ end
1165
+
1166
+ def rollback
1167
+ context.steps << :rollback3
1168
+ end
1169
+ end
1170
+ }
1171
+
1172
+ it "rolls back successfully called interaktors and the failed interaktor" do
1173
+ expect {
1174
+ begin
1175
+ organizer.call(context)
1176
+ rescue StandardError
1177
+ nil
1178
+ end
1179
+ }.to change(context, :steps).from([]).to([
1180
+ :around_before, :before,
1181
+ :around_before2, :before2,
1182
+ :around_before2a, :before2a, :call2a, :after2a, :around_after2a,
1183
+ :around_before2b, :before2b, :call2b, :after2b, :around_after2b,
1184
+ :around_before2c, :before2c, :call2c, :after2c, :around_after2c,
1185
+ :after2, :around_after2,
1186
+ :around_before3, :before3, :call3, :after3,
1187
+ :rollback3,
1188
+ :rollback2c,
1189
+ :rollback2b,
1190
+ :rollback2a,
1191
+ ])
1192
+ end
1193
+
1194
+ it "raises the error" do
1195
+ expect {
1196
+ organizer.call(context)
1197
+ }.to raise_error("foo")
1198
+ end
1199
+ end
1200
+
1201
+ context "when a deeply nested around hook fails early" do
1202
+ let(:interaktor4b) {
1203
+ build_interaktor do
1204
+ around do |interaktor|
1205
+ context.fail!
1206
+ context.steps << :around_before4b
1207
+ interaktor.call
1208
+ context.steps << :around_after4b
1209
+ end
1210
+
1211
+ before do
1212
+ context.steps << :before4b
1213
+ end
1214
+
1215
+ after do
1216
+ context.steps << :after4b
1217
+ end
1218
+
1219
+ def call
1220
+ context.steps << :call4b
1221
+ end
1222
+
1223
+ def rollback
1224
+ context.steps << :rollback4b
1225
+ end
1226
+ end
1227
+ }
1228
+
1229
+ it "rolls back successfully called interaktors" do
1230
+ expect {
1231
+ organizer.call(context)
1232
+ }.to change(context, :steps).from([]).to([
1233
+ :around_before, :before,
1234
+ :around_before2, :before2,
1235
+ :around_before2a, :before2a, :call2a, :after2a, :around_after2a,
1236
+ :around_before2b, :before2b, :call2b, :after2b, :around_after2b,
1237
+ :around_before2c, :before2c, :call2c, :after2c, :around_after2c,
1238
+ :after2, :around_after2,
1239
+ :around_before3, :before3, :call3, :after3, :around_after3,
1240
+ :around_before4, :before4,
1241
+ :around_before4a, :before4a, :call4a, :after4a, :around_after4a,
1242
+ :rollback4a,
1243
+ :rollback3,
1244
+ :rollback2c,
1245
+ :rollback2b,
1246
+ :rollback2a,
1247
+ ])
1248
+ end
1249
+ end
1250
+
1251
+ context "when a deeply nested around hook errors early" do
1252
+ let(:interaktor4b) {
1253
+ build_interaktor do
1254
+ around do |interaktor|
1255
+ unexpected_error!
1256
+ context.steps << :around_before4b
1257
+ interaktor.call
1258
+ context.steps << :around_after4b
1259
+ end
1260
+
1261
+ before do
1262
+ context.steps << :before4b
1263
+ end
1264
+
1265
+ after do
1266
+ context.steps << :after4b
1267
+ end
1268
+
1269
+ def call
1270
+ context.steps << :call4b
1271
+ end
1272
+
1273
+ def rollback
1274
+ context.steps << :rollback4b
1275
+ end
1276
+ end
1277
+ }
1278
+
1279
+ it "rolls back successfully called interaktors" do
1280
+ expect {
1281
+ begin
1282
+ organizer.call(context)
1283
+ rescue StandardError
1284
+ nil
1285
+ end
1286
+ }.to change(context, :steps).from([]).to([
1287
+ :around_before, :before,
1288
+ :around_before2, :before2,
1289
+ :around_before2a, :before2a, :call2a, :after2a, :around_after2a,
1290
+ :around_before2b, :before2b, :call2b, :after2b, :around_after2b,
1291
+ :around_before2c, :before2c, :call2c, :after2c, :around_after2c,
1292
+ :after2, :around_after2,
1293
+ :around_before3, :before3, :call3, :after3, :around_after3,
1294
+ :around_before4, :before4,
1295
+ :around_before4a, :before4a, :call4a, :after4a, :around_after4a,
1296
+ :rollback4a,
1297
+ :rollback3,
1298
+ :rollback2c,
1299
+ :rollback2b,
1300
+ :rollback2a,
1301
+ ])
1302
+ end
1303
+
1304
+ it "raises the error" do
1305
+ expect {
1306
+ organizer.call(context)
1307
+ }.to raise_error("foo")
1308
+ end
1309
+ end
1310
+
1311
+ context "when a deeply nested before hook fails" do
1312
+ let(:interaktor4b) {
1313
+ build_interaktor do
1314
+ around do |interaktor|
1315
+ context.steps << :around_before4b
1316
+ interaktor.call
1317
+ context.steps << :around_after4b
1318
+ end
1319
+
1320
+ before do
1321
+ context.fail!
1322
+ context.steps << :before4b
1323
+ end
1324
+
1325
+ after do
1326
+ context.steps << :after4b
1327
+ end
1328
+
1329
+ def call
1330
+ context.steps << :call4b
1331
+ end
1332
+
1333
+ def rollback
1334
+ context.steps << :rollback4b
1335
+ end
1336
+ end
1337
+ }
1338
+
1339
+ it "rolls back successfully called interaktors" do
1340
+ expect {
1341
+ organizer.call(context)
1342
+ }.to change(context, :steps).from([]).to([
1343
+ :around_before, :before,
1344
+ :around_before2, :before2,
1345
+ :around_before2a, :before2a, :call2a, :after2a, :around_after2a,
1346
+ :around_before2b, :before2b, :call2b, :after2b, :around_after2b,
1347
+ :around_before2c, :before2c, :call2c, :after2c, :around_after2c,
1348
+ :after2, :around_after2,
1349
+ :around_before3, :before3, :call3, :after3, :around_after3,
1350
+ :around_before4, :before4,
1351
+ :around_before4a, :before4a, :call4a, :after4a, :around_after4a,
1352
+ :around_before4b,
1353
+ :rollback4a,
1354
+ :rollback3,
1355
+ :rollback2c,
1356
+ :rollback2b,
1357
+ :rollback2a,
1358
+ ])
1359
+ end
1360
+ end
1361
+
1362
+ context "when a deeply nested before hook errors" do
1363
+ let(:interaktor4b) {
1364
+ build_interaktor do
1365
+ around do |interaktor|
1366
+ context.steps << :around_before4b
1367
+ interaktor.call
1368
+ context.steps << :around_after4b
1369
+ end
1370
+
1371
+ before do
1372
+ unexpected_error!
1373
+ context.steps << :before4b
1374
+ end
1375
+
1376
+ after do
1377
+ context.steps << :after4b
1378
+ end
1379
+
1380
+ def call
1381
+ context.steps << :call4b
1382
+ end
1383
+
1384
+ def rollback
1385
+ context.steps << :rollback4b
1386
+ end
1387
+ end
1388
+ }
1389
+
1390
+ it "rolls back successfully called interaktors" do
1391
+ expect {
1392
+ begin
1393
+ organizer.call(context)
1394
+ rescue StandardError
1395
+ nil
1396
+ end
1397
+ }.to change(context, :steps).from([]).to([
1398
+ :around_before, :before,
1399
+ :around_before2, :before2,
1400
+ :around_before2a, :before2a, :call2a, :after2a, :around_after2a,
1401
+ :around_before2b, :before2b, :call2b, :after2b, :around_after2b,
1402
+ :around_before2c, :before2c, :call2c, :after2c, :around_after2c,
1403
+ :after2, :around_after2,
1404
+ :around_before3, :before3, :call3, :after3, :around_after3,
1405
+ :around_before4, :before4,
1406
+ :around_before4a, :before4a, :call4a, :after4a, :around_after4a,
1407
+ :around_before4b,
1408
+ :rollback4a,
1409
+ :rollback3,
1410
+ :rollback2c,
1411
+ :rollback2b,
1412
+ :rollback2a,
1413
+ ])
1414
+ end
1415
+
1416
+ it "raises the error" do
1417
+ expect {
1418
+ organizer.call(context)
1419
+ }.to raise_error("foo")
1420
+ end
1421
+ end
1422
+
1423
+ context "when a deeply nested call fails" do
1424
+ let(:interaktor4b) {
1425
+ build_interaktor do
1426
+ around do |interaktor|
1427
+ context.steps << :around_before4b
1428
+ interaktor.call
1429
+ context.steps << :around_after4b
1430
+ end
1431
+
1432
+ before do
1433
+ context.steps << :before4b
1434
+ end
1435
+
1436
+ after do
1437
+ context.steps << :after4b
1438
+ end
1439
+
1440
+ def call
1441
+ context.fail!
1442
+ context.steps << :call4b
1443
+ end
1444
+
1445
+ def rollback
1446
+ context.steps << :rollback4b
1447
+ end
1448
+ end
1449
+ }
1450
+
1451
+ it "rolls back successfully called interaktors" do
1452
+ expect {
1453
+ organizer.call(context)
1454
+ }.to change(context, :steps).from([]).to([
1455
+ :around_before, :before,
1456
+ :around_before2, :before2,
1457
+ :around_before2a, :before2a, :call2a, :after2a, :around_after2a,
1458
+ :around_before2b, :before2b, :call2b, :after2b, :around_after2b,
1459
+ :around_before2c, :before2c, :call2c, :after2c, :around_after2c,
1460
+ :after2, :around_after2,
1461
+ :around_before3, :before3, :call3, :after3, :around_after3,
1462
+ :around_before4, :before4,
1463
+ :around_before4a, :before4a, :call4a, :after4a, :around_after4a,
1464
+ :around_before4b, :before4b,
1465
+ :rollback4a,
1466
+ :rollback3,
1467
+ :rollback2c,
1468
+ :rollback2b,
1469
+ :rollback2a,
1470
+ ])
1471
+ end
1472
+ end
1473
+
1474
+ context "when a deeply nested call errors" do
1475
+ let(:interaktor4b) {
1476
+ build_interaktor do
1477
+ around do |interaktor|
1478
+ context.steps << :around_before4b
1479
+ interaktor.call
1480
+ context.steps << :around_after4b
1481
+ end
1482
+
1483
+ before do
1484
+ context.steps << :before4b
1485
+ end
1486
+
1487
+ after do
1488
+ context.steps << :after4b
1489
+ end
1490
+
1491
+ def call
1492
+ unexpected_error!
1493
+ context.steps << :call4b
1494
+ end
1495
+
1496
+ def rollback
1497
+ context.steps << :rollback4b
1498
+ end
1499
+ end
1500
+ }
1501
+
1502
+ it "rolls back successfully called interaktors" do
1503
+ expect {
1504
+ begin
1505
+ organizer.call(context)
1506
+ rescue StandardError
1507
+ nil
1508
+ end
1509
+ }.to change(context, :steps).from([]).to([
1510
+ :around_before, :before,
1511
+ :around_before2, :before2,
1512
+ :around_before2a, :before2a, :call2a, :after2a, :around_after2a,
1513
+ :around_before2b, :before2b, :call2b, :after2b, :around_after2b,
1514
+ :around_before2c, :before2c, :call2c, :after2c, :around_after2c,
1515
+ :after2, :around_after2,
1516
+ :around_before3, :before3, :call3, :after3, :around_after3,
1517
+ :around_before4, :before4,
1518
+ :around_before4a, :before4a, :call4a, :after4a, :around_after4a,
1519
+ :around_before4b, :before4b,
1520
+ :rollback4a,
1521
+ :rollback3,
1522
+ :rollback2c,
1523
+ :rollback2b,
1524
+ :rollback2a,
1525
+ ])
1526
+ end
1527
+
1528
+ it "raises the error" do
1529
+ expect {
1530
+ organizer.call(context)
1531
+ }.to raise_error("foo")
1532
+ end
1533
+ end
1534
+
1535
+ context "when a deeply nested after hook fails" do
1536
+ let(:interaktor4b) {
1537
+ build_interaktor do
1538
+ around do |interaktor|
1539
+ context.steps << :around_before4b
1540
+ interaktor.call
1541
+ context.steps << :around_after4b
1542
+ end
1543
+
1544
+ before do
1545
+ context.steps << :before4b
1546
+ end
1547
+
1548
+ after do
1549
+ context.fail!
1550
+ context.steps << :after4b
1551
+ end
1552
+
1553
+ def call
1554
+ context.steps << :call4b
1555
+ end
1556
+
1557
+ def rollback
1558
+ context.steps << :rollback4b
1559
+ end
1560
+ end
1561
+ }
1562
+
1563
+ it "rolls back successfully called interaktors and the failed interaktor" do
1564
+ expect {
1565
+ organizer.call(context)
1566
+ }.to change(context, :steps).from([]).to([
1567
+ :around_before, :before,
1568
+ :around_before2, :before2,
1569
+ :around_before2a, :before2a, :call2a, :after2a, :around_after2a,
1570
+ :around_before2b, :before2b, :call2b, :after2b, :around_after2b,
1571
+ :around_before2c, :before2c, :call2c, :after2c, :around_after2c,
1572
+ :after2, :around_after2,
1573
+ :around_before3, :before3, :call3, :after3, :around_after3,
1574
+ :around_before4, :before4,
1575
+ :around_before4a, :before4a, :call4a, :after4a, :around_after4a,
1576
+ :around_before4b, :before4b, :call4b,
1577
+ :rollback4b,
1578
+ :rollback4a,
1579
+ :rollback3,
1580
+ :rollback2c,
1581
+ :rollback2b,
1582
+ :rollback2a,
1583
+ ])
1584
+ end
1585
+ end
1586
+
1587
+ context "when a deeply nested after hook errors" do
1588
+ let(:interaktor4b) {
1589
+ build_interaktor do
1590
+ around do |interaktor|
1591
+ context.steps << :around_before4b
1592
+ interaktor.call
1593
+ context.steps << :around_after4b
1594
+ end
1595
+
1596
+ before do
1597
+ context.steps << :before4b
1598
+ end
1599
+
1600
+ after do
1601
+ unexpected_error!
1602
+ context.steps << :after4b
1603
+ end
1604
+
1605
+ def call
1606
+ context.steps << :call4b
1607
+ end
1608
+
1609
+ def rollback
1610
+ context.steps << :rollback4b
1611
+ end
1612
+ end
1613
+ }
1614
+
1615
+ it "rolls back successfully called interaktors and the failed interaktor" do
1616
+ expect {
1617
+ begin
1618
+ organizer.call(context)
1619
+ rescue StandardError
1620
+ nil
1621
+ end
1622
+ }.to change(context, :steps).from([]).to([
1623
+ :around_before, :before,
1624
+ :around_before2, :before2,
1625
+ :around_before2a, :before2a, :call2a, :after2a, :around_after2a,
1626
+ :around_before2b, :before2b, :call2b, :after2b, :around_after2b,
1627
+ :around_before2c, :before2c, :call2c, :after2c, :around_after2c,
1628
+ :after2, :around_after2,
1629
+ :around_before3, :before3, :call3, :after3, :around_after3,
1630
+ :around_before4, :before4,
1631
+ :around_before4a, :before4a, :call4a, :after4a, :around_after4a,
1632
+ :around_before4b, :before4b, :call4b,
1633
+ :rollback4b,
1634
+ :rollback4a,
1635
+ :rollback3,
1636
+ :rollback2c,
1637
+ :rollback2b,
1638
+ :rollback2a,
1639
+ ])
1640
+ end
1641
+
1642
+ it "raises the error" do
1643
+ expect {
1644
+ organizer.call(context)
1645
+ }.to raise_error("foo")
1646
+ end
1647
+ end
1648
+
1649
+ context "when a deeply nested around hook fails late" do
1650
+ let(:interaktor4b) {
1651
+ build_interaktor do
1652
+ around do |interaktor|
1653
+ context.steps << :around_before4b
1654
+ interaktor.call
1655
+ context.fail!
1656
+ context.steps << :around_after4b
1657
+ end
1658
+
1659
+ before do
1660
+ context.steps << :before4b
1661
+ end
1662
+
1663
+ after do
1664
+ context.steps << :after4b
1665
+ end
1666
+
1667
+ def call
1668
+ context.steps << :call4b
1669
+ end
1670
+
1671
+ def rollback
1672
+ context.steps << :rollback4b
1673
+ end
1674
+ end
1675
+ }
1676
+
1677
+ it "rolls back successfully called interaktors and the failed interaktor" do
1678
+ expect {
1679
+ organizer.call(context)
1680
+ }.to change(context, :steps).from([]).to([
1681
+ :around_before, :before,
1682
+ :around_before2, :before2,
1683
+ :around_before2a, :before2a, :call2a, :after2a, :around_after2a,
1684
+ :around_before2b, :before2b, :call2b, :after2b, :around_after2b,
1685
+ :around_before2c, :before2c, :call2c, :after2c, :around_after2c,
1686
+ :after2, :around_after2,
1687
+ :around_before3, :before3, :call3, :after3, :around_after3,
1688
+ :around_before4, :before4,
1689
+ :around_before4a, :before4a, :call4a, :after4a, :around_after4a,
1690
+ :around_before4b, :before4b, :call4b, :after4b,
1691
+ :rollback4b,
1692
+ :rollback4a,
1693
+ :rollback3,
1694
+ :rollback2c,
1695
+ :rollback2b,
1696
+ :rollback2a,
1697
+ ])
1698
+ end
1699
+ end
1700
+
1701
+ context "when a deeply nested around hook errors late" do
1702
+ let(:interaktor4b) {
1703
+ build_interaktor do
1704
+ around do |interaktor|
1705
+ context.steps << :around_before4b
1706
+ interaktor.call
1707
+ unexpected_error!
1708
+ context.steps << :around_after4b
1709
+ end
1710
+
1711
+ before do
1712
+ context.steps << :before4b
1713
+ end
1714
+
1715
+ after do
1716
+ context.steps << :after4b
1717
+ end
1718
+
1719
+ def call
1720
+ context.steps << :call4b
1721
+ end
1722
+
1723
+ def rollback
1724
+ context.steps << :rollback4b
1725
+ end
1726
+ end
1727
+ }
1728
+
1729
+ it "rolls back successfully called interaktors and the failed interaktor" do
1730
+ expect {
1731
+ begin
1732
+ organizer.call(context)
1733
+ rescue StandardError
1734
+ nil
1735
+ end
1736
+ }.to change(context, :steps).from([]).to([
1737
+ :around_before, :before,
1738
+ :around_before2, :before2,
1739
+ :around_before2a, :before2a, :call2a, :after2a, :around_after2a,
1740
+ :around_before2b, :before2b, :call2b, :after2b, :around_after2b,
1741
+ :around_before2c, :before2c, :call2c, :after2c, :around_after2c,
1742
+ :after2, :around_after2,
1743
+ :around_before3, :before3, :call3, :after3, :around_after3,
1744
+ :around_before4, :before4,
1745
+ :around_before4a, :before4a, :call4a, :after4a, :around_after4a,
1746
+ :around_before4b, :before4b, :call4b, :after4b,
1747
+ :rollback4b,
1748
+ :rollback4a,
1749
+ :rollback3,
1750
+ :rollback2c,
1751
+ :rollback2b,
1752
+ :rollback2a,
1753
+ ])
1754
+ end
1755
+
1756
+ it "raises the error" do
1757
+ expect {
1758
+ organizer.call(context)
1759
+ }.to raise_error("foo")
1760
+ end
1761
+ end
1762
+
1763
+ context "when there are multiple organize calls" do
1764
+ it "runs all passed interaktors in correct order" do
1765
+ organizer = build_organizer(organize: [organizer2, interaktor3])
1766
+ organizer.organize(organizer4, interaktor5)
1767
+
1768
+ expect {
1769
+ organizer.call(context)
1770
+ }.to change(context, :steps).from([]).to([
1771
+ :around_before2, :before2,
1772
+ :around_before2a, :before2a, :call2a, :after2a, :around_after2a,
1773
+ :around_before2b, :before2b, :call2b, :after2b, :around_after2b,
1774
+ :around_before2c, :before2c, :call2c, :after2c, :around_after2c,
1775
+ :after2, :around_after2,
1776
+ :around_before3, :before3, :call3, :after3, :around_after3,
1777
+ :around_before4, :before4,
1778
+ :around_before4a, :before4a, :call4a, :after4a, :around_after4a,
1779
+ :around_before4b, :before4b, :call4b, :after4b, :around_after4b,
1780
+ :around_before4c, :before4c, :call4c, :after4c, :around_after4c,
1781
+ :after4, :around_after4,
1782
+ :around_before5, :before5, :call5, :after5, :around_after5,
1783
+ ])
1784
+ end
1785
+ end
1786
+ end