interaktor 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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