activeinteractor 1.0.0.beta.3 → 1.0.0.beta.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,162 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe ActiveInteractor::Organizer::InteractorInterface do
6
+ describe '.new' do
7
+ subject(:instance) { described_class.new(interactor_class, options) }
8
+
9
+ context 'with an interactor that does not exist' do
10
+ let(:interactor_class) { :an_interactor_that_does_not_exist }
11
+ let(:options) { {} }
12
+
13
+ describe '#interactor_class' do
14
+ subject { instance.interactor_class }
15
+
16
+ it { is_expected.to be_nil }
17
+ end
18
+ end
19
+
20
+ RSpec.shared_examples 'an instance of InteractorInterface correctly parse options' do
21
+ context 'with options {:if => :some_method }' do
22
+ let(:options) { { if: :some_method } }
23
+
24
+ describe '#filters' do
25
+ subject { instance.filters }
26
+
27
+ it { is_expected.to eq(if: :some_method) }
28
+ end
29
+
30
+ describe '#perform_options' do
31
+ subject { instance.perform_options }
32
+
33
+ it { is_expected.to be_empty }
34
+ end
35
+ end
36
+
37
+ context 'with options {:if => -> { context.test == true } }' do
38
+ let(:options) { { if: -> { context.test == true } } }
39
+
40
+ describe '#filters' do
41
+ subject { instance.filters }
42
+
43
+ it { expect(subject[:if]).not_to be_nil }
44
+ it { expect(subject[:if]).to be_a Proc }
45
+ end
46
+
47
+ describe '#perform_options' do
48
+ subject { instance.perform_options }
49
+
50
+ it { is_expected.to be_empty }
51
+ end
52
+ end
53
+
54
+ context 'with options {:unless => :some_method }' do
55
+ let(:options) { { unless: :some_method } }
56
+
57
+ describe '#filters' do
58
+ subject { instance.filters }
59
+
60
+ it { is_expected.to eq(unless: :some_method) }
61
+ end
62
+
63
+ describe '#perform_options' do
64
+ subject { instance.perform_options }
65
+
66
+ it { is_expected.to be_empty }
67
+ end
68
+ end
69
+
70
+ context 'with options {:unless => -> { context.test == true } }' do
71
+ let(:options) { { unless: -> { context.test == true } } }
72
+
73
+ describe '#filters' do
74
+ subject { instance.filters }
75
+
76
+ it { expect(subject[:unless]).not_to be_nil }
77
+ it { expect(subject[:unless]).to be_a Proc }
78
+ end
79
+
80
+ describe '#perform_options' do
81
+ subject { instance.perform_options }
82
+
83
+ it { is_expected.to be_empty }
84
+ end
85
+ end
86
+
87
+ context 'with options { :validate => false }' do
88
+ let(:options) { { validate: false } }
89
+
90
+ describe '#filters' do
91
+ subject { instance.filters }
92
+
93
+ it { is_expected.to be_empty }
94
+ end
95
+
96
+ describe '#perform_options' do
97
+ subject { instance.perform_options }
98
+
99
+ it { is_expected.to eq(validate: false) }
100
+ end
101
+ end
102
+
103
+ context 'with options { :if => :some_method, :validate => false }' do
104
+ let(:options) { { if: :some_method, validate: false } }
105
+
106
+ describe '#filters' do
107
+ subject { instance.filters }
108
+
109
+ it { is_expected.to eq(if: :some_method) }
110
+ end
111
+
112
+ describe '#perform_options' do
113
+ subject { instance.perform_options }
114
+
115
+ it { is_expected.to eq(validate: false) }
116
+ end
117
+ end
118
+ end
119
+
120
+ context 'with an existing interactor' do
121
+ before { build_interactor }
122
+
123
+ context 'when interactors are passed as contants' do
124
+ let(:interactor_class) { TestInteractor }
125
+ let(:options) { {} }
126
+
127
+ include_examples 'an instance of InteractorInterface correctly parse options'
128
+
129
+ describe '#interactor_class' do
130
+ subject { instance.interactor_class }
131
+
132
+ it { is_expected.to eq TestInteractor }
133
+ end
134
+ end
135
+
136
+ context 'when interactors are passed as symbols' do
137
+ let(:interactor_class) { :test_interactor }
138
+ let(:options) { {} }
139
+
140
+ include_examples 'an instance of InteractorInterface correctly parse options'
141
+
142
+ describe '#interactor_class' do
143
+ subject { instance.interactor_class }
144
+
145
+ it { is_expected.to eq TestInteractor }
146
+ end
147
+ end
148
+
149
+ context 'when interactors are passed as strings' do
150
+ let(:interactor_class) { 'TestInteractor' }
151
+ let(:options) { {} }
152
+ include_examples 'an instance of InteractorInterface correctly parse options'
153
+
154
+ describe '#interactor_class' do
155
+ subject { instance.interactor_class }
156
+
157
+ it { is_expected.to eq TestInteractor }
158
+ end
159
+ end
160
+ end
161
+ end
162
+ end
@@ -51,58 +51,46 @@ RSpec.describe ActiveInteractor::Organizer do
51
51
  end
52
52
 
53
53
  describe '.organize' do
54
- subject { interactor_class }
55
54
  context 'with two existing interactors' do
56
55
  let!(:interactor1) { build_interactor('TestInteractor1') }
57
56
  let!(:interactor2) { build_interactor('TestInteractor2') }
58
57
 
59
- context 'when interactors are passed as contants' do
60
- let(:interactor_class) do
61
- build_organizer do
62
- organize TestInteractor1, TestInteractor2
63
- end
64
- end
65
-
66
- it { is_expected.to have_attributes(organized: [TestInteractor1, TestInteractor2]) }
67
- end
68
-
69
- context 'when interactors are passed as symbols' do
70
- let(:interactor_class) do
58
+ context 'when interactors are passed as args' do
59
+ let(:organizer) do
71
60
  build_organizer do
72
61
  organize :test_interactor_1, :test_interactor_2
73
62
  end
74
63
  end
75
64
 
76
- it { is_expected.to have_attributes(organized: [TestInteractor1, TestInteractor2]) }
65
+ describe '.organized' do
66
+ subject { organizer.organized }
77
67
 
78
- context 'having a non existance interactor' do
79
- let(:interactor_class) do
80
- build_organizer do
81
- organize :test_interactor_1, :interactor_that_doesnt_exist, :test_interactor_2
82
- end
68
+ it { expect(subject.collection).to all(be_a ActiveInteractor::Organizer::InteractorInterface) }
69
+ it 'is expected to organize the approriate interactors' do
70
+ expect(subject.collection.first.interactor_class).to eq TestInteractor1
71
+ expect(subject.collection.last.interactor_class).to eq TestInteractor2
83
72
  end
84
-
85
- it { is_expected.to have_attributes(organized: [TestInteractor1, TestInteractor2]) }
86
73
  end
87
74
  end
88
75
 
89
- context 'when interactors are passed as strings' do
90
- let(:interactor_class) do
76
+ context 'when a block is passed' do
77
+ let(:organizer) do
91
78
  build_organizer do
92
- organize 'TestInteractor1', 'TestInteractor2'
79
+ organize do
80
+ add :test_interactor_1
81
+ add :test_interactor_2
82
+ end
93
83
  end
94
84
  end
95
85
 
96
- it { is_expected.to have_attributes(organized: [TestInteractor1, TestInteractor2]) }
86
+ describe '.organized' do
87
+ subject { organizer.organized }
97
88
 
98
- context 'having a non existance interactor' do
99
- let(:interactor_class) do
100
- build_organizer do
101
- organize 'TestInteractor1', 'InteractorThatDoesntExist', 'TestInteractor2'
102
- end
89
+ it { expect(subject.collection).to all(be_a ActiveInteractor::Organizer::InteractorInterface) }
90
+ it 'is expected to organize the approriate interactors' do
91
+ expect(subject.collection.first.interactor_class).to eq TestInteractor1
92
+ expect(subject.collection.last.interactor_class).to eq TestInteractor2
103
93
  end
104
-
105
- it { is_expected.to have_attributes(organized: [TestInteractor1, TestInteractor2]) }
106
94
  end
107
95
  end
108
96
  end
@@ -126,6 +114,22 @@ RSpec.describe ActiveInteractor::Organizer do
126
114
  subject
127
115
  end
128
116
 
117
+ context 'with options :skip_each_perform_callbacks eq to true' do
118
+ subject { interactor_class.perform({}, skip_each_perform_callbacks: true) }
119
+
120
+ it { is_expected.to be_a interactor_class.context_class }
121
+ it 'is expected to invoke #perform on both interactors' do
122
+ expect_any_instance_of(interactor1).to receive(:perform)
123
+ expect_any_instance_of(interactor2).to receive(:perform)
124
+ subject
125
+ end
126
+ it 'is expected not to invoke #run_callbacks with :each_perform' do
127
+ expect_any_instance_of(interactor_class).not_to receive(:run_callbacks)
128
+ .with(:each_perform)
129
+ subject
130
+ end
131
+ end
132
+
129
133
  context 'when the first interactor context fails' do
130
134
  let!(:interactor1) do
131
135
  build_interactor('TestInteractor1') do
@@ -115,12 +115,6 @@ RSpec.describe 'Basic Integration', type: :integration do
115
115
  it { is_expected.to be < ActiveInteractor::Context::Base }
116
116
  end
117
117
 
118
- describe '.organized' do
119
- subject { interactor_class.organized }
120
-
121
- it { is_expected.to eq [TestInteractor1, TestInteractor2] }
122
- end
123
-
124
118
  describe '.perform' do
125
119
  subject { interactor_class.perform }
126
120
 
@@ -254,12 +248,6 @@ RSpec.describe 'Basic Integration', type: :integration do
254
248
  it { is_expected.to be < ActiveInteractor::Context::Base }
255
249
  end
256
250
 
257
- describe '.organized' do
258
- subject { interactor_class.organized }
259
-
260
- it { is_expected.to eq [TestInteractor1, TestInteractor2] }
261
- end
262
-
263
251
  describe '.perform' do
264
252
  subject { interactor_class.perform }
265
253
 
@@ -268,4 +256,315 @@ RSpec.describe 'Basic Integration', type: :integration do
268
256
  it { is_expected.to have_attributes(test_field_1: 'test 1', test_field_2: 'test 2') }
269
257
  end
270
258
  end
259
+
260
+ describe 'A basic with conditionally organized interactors' do
261
+ let!(:test_interactor_1) { build_interactor('TestInteractor1') }
262
+ let!(:test_interactor_2) { build_interactor('TestInteractor2') }
263
+
264
+ context 'with a condition on the first interactor { :if => -> { context.test_1 } } ' \
265
+ 'and a condition on the second interactor { :if => -> { context.test_2 } }' do
266
+ let(:interactor_class) do
267
+ build_organizer do
268
+ organize do
269
+ add :test_interactor_1, if: -> { context.test_1 }
270
+ add :test_interactor_2, if: -> { context.test_2 }
271
+ end
272
+ end
273
+ end
274
+
275
+ include_examples 'a class with interactor methods'
276
+ include_examples 'a class with interactor callback methods'
277
+ include_examples 'a class with interactor context methods'
278
+ include_examples 'a class with organizer callback methods'
279
+
280
+ describe '.perform' do
281
+ subject { interactor_class.perform(context_attributes) }
282
+
283
+ context 'with context_attributes test_1 and test_2 both eq to true' do
284
+ let(:context_attributes) { { test_1: true, test_2: true } }
285
+
286
+ it { is_expected.to be_a interactor_class.context_class }
287
+ it { is_expected.to be_successful }
288
+ it 'is expected to invoke #perform on both interactors' do
289
+ expect_any_instance_of(test_interactor_1).to receive(:perform)
290
+ expect_any_instance_of(test_interactor_2).to receive(:perform)
291
+ subject
292
+ end
293
+ end
294
+
295
+ context 'with context_attributes test_1 eq to true and test_2 eq to false' do
296
+ let(:context_attributes) { { test_1: true, test_2: false } }
297
+
298
+ it { is_expected.to be_a interactor_class.context_class }
299
+ it { is_expected.to be_successful }
300
+ it 'is expected to invoke #perform on the first interactor' do
301
+ expect_any_instance_of(test_interactor_1).to receive(:perform)
302
+ subject
303
+ end
304
+
305
+ it 'is expected not to invoke #perform on the first interactor' do
306
+ expect_any_instance_of(test_interactor_2).not_to receive(:perform)
307
+ subject
308
+ end
309
+ end
310
+
311
+ context 'with context_attributes test_1 eq to false and test_2 eq to true' do
312
+ let(:context_attributes) { { test_1: false, test_2: true } }
313
+
314
+ it { is_expected.to be_a interactor_class.context_class }
315
+ it { is_expected.to be_successful }
316
+ it 'is expected not to invoke #perform on the first interactor' do
317
+ expect_any_instance_of(test_interactor_1).not_to receive(:perform)
318
+ subject
319
+ end
320
+
321
+ it 'is expected to invoke #perform on the first interactor' do
322
+ expect_any_instance_of(test_interactor_2).to receive(:perform)
323
+ subject
324
+ end
325
+ end
326
+
327
+ context 'with context_attributes test_1 and test_2 both eq to false' do
328
+ let(:context_attributes) { { test_1: false, test_2: false } }
329
+
330
+ it { is_expected.to be_a interactor_class.context_class }
331
+ it { is_expected.to be_successful }
332
+ it 'is expected not to invoke #perform on the first interactor' do
333
+ expect_any_instance_of(test_interactor_1).not_to receive(:perform)
334
+ subject
335
+ end
336
+
337
+ it 'is expected not to invoke #perform on the first interactor' do
338
+ expect_any_instance_of(test_interactor_2).not_to receive(:perform)
339
+ subject
340
+ end
341
+ end
342
+ end
343
+ end
344
+
345
+ context 'with a condition on the first interactor { :unless => -> { context.test_1 } } ' \
346
+ 'and a condition on the second interactor { :unless => -> { context.test_2 } }' do
347
+ let(:interactor_class) do
348
+ build_organizer do
349
+ organize do
350
+ add :test_interactor_1, unless: -> { context.test_1 }
351
+ add :test_interactor_2, unless: -> { context.test_2 }
352
+ end
353
+ end
354
+ end
355
+
356
+ include_examples 'a class with interactor methods'
357
+ include_examples 'a class with interactor callback methods'
358
+ include_examples 'a class with interactor context methods'
359
+ include_examples 'a class with organizer callback methods'
360
+
361
+ describe '.perform' do
362
+ subject { interactor_class.perform(context_attributes) }
363
+
364
+ context 'with context_attributes test_1 and test_2 both eq to true' do
365
+ let(:context_attributes) { { test_1: true, test_2: true } }
366
+
367
+ it { is_expected.to be_a interactor_class.context_class }
368
+ it { is_expected.to be_successful }
369
+ it 'is expected not to invoke #perform on the first interactor' do
370
+ expect_any_instance_of(test_interactor_1).not_to receive(:perform)
371
+ subject
372
+ end
373
+
374
+ it 'is expected not to invoke #perform on the second interactor' do
375
+ expect_any_instance_of(test_interactor_2).not_to receive(:perform)
376
+ subject
377
+ end
378
+ end
379
+
380
+ context 'with context_attributes test_1 eq to true and test_2 eq to false' do
381
+ let(:context_attributes) { { test_1: true, test_2: false } }
382
+
383
+ it { is_expected.to be_a interactor_class.context_class }
384
+ it { is_expected.to be_successful }
385
+ it 'is expected not to invoke #perform on the first interactor' do
386
+ expect_any_instance_of(test_interactor_1).not_to receive(:perform)
387
+ subject
388
+ end
389
+
390
+ it 'is expected to invoke #perform on the second interactor' do
391
+ expect_any_instance_of(test_interactor_2).to receive(:perform)
392
+ subject
393
+ end
394
+ end
395
+
396
+ context 'with context_attributes test_1 eq to false and test_2 eq to true' do
397
+ let(:context_attributes) { { test_1: false, test_2: true } }
398
+
399
+ it { is_expected.to be_a interactor_class.context_class }
400
+ it { is_expected.to be_successful }
401
+ it 'is expected to invoke #perform on the first interactor' do
402
+ expect_any_instance_of(test_interactor_1).to receive(:perform)
403
+ subject
404
+ end
405
+
406
+ it 'is expected not to invoke #perform on the second interactor' do
407
+ expect_any_instance_of(test_interactor_2).not_to receive(:perform)
408
+ subject
409
+ end
410
+ end
411
+
412
+ context 'with context_attributes test_1 and test_2 both eq to false' do
413
+ let(:context_attributes) { { test_1: false, test_2: false } }
414
+
415
+ it { is_expected.to be_a interactor_class.context_class }
416
+ it { is_expected.to be_successful }
417
+ it 'is expected to invoke #perform on both interactors' do
418
+ expect_any_instance_of(test_interactor_1).to receive(:perform)
419
+ expect_any_instance_of(test_interactor_2).to receive(:perform)
420
+ subject
421
+ end
422
+ end
423
+ end
424
+ end
425
+
426
+ context 'with a condition on the first interactor { :if => :test_method } and :test_method returning true' do
427
+ let(:interactor_class) do
428
+ build_organizer do
429
+ organize do
430
+ add :test_interactor_1, if: :test_method
431
+ add :test_interactor_2
432
+ end
433
+
434
+ private
435
+
436
+ def test_method
437
+ true
438
+ end
439
+ end
440
+ end
441
+
442
+ include_examples 'a class with interactor methods'
443
+ include_examples 'a class with interactor callback methods'
444
+ include_examples 'a class with interactor context methods'
445
+ include_examples 'a class with organizer callback methods'
446
+
447
+ describe '.perform' do
448
+ subject { interactor_class.perform }
449
+
450
+ it { is_expected.to be_a interactor_class.context_class }
451
+ it { is_expected.to be_successful }
452
+ it 'is expected to invoke #perform on both interactors' do
453
+ expect_any_instance_of(test_interactor_1).to receive(:perform)
454
+ expect_any_instance_of(test_interactor_2).to receive(:perform)
455
+ subject
456
+ end
457
+ end
458
+ end
459
+
460
+ context 'with a condition on the first interactor { :if => :test_method } and :test_method returning false' do
461
+ let(:interactor_class) do
462
+ build_organizer do
463
+ organize do
464
+ add :test_interactor_1, if: :test_method
465
+ add :test_interactor_2
466
+ end
467
+
468
+ private
469
+
470
+ def test_method
471
+ false
472
+ end
473
+ end
474
+ end
475
+
476
+ include_examples 'a class with interactor methods'
477
+ include_examples 'a class with interactor callback methods'
478
+ include_examples 'a class with interactor context methods'
479
+ include_examples 'a class with organizer callback methods'
480
+
481
+ describe '.perform' do
482
+ subject { interactor_class.perform }
483
+
484
+ it { is_expected.to be_a interactor_class.context_class }
485
+ it { is_expected.to be_successful }
486
+ it 'is expected not to invoke #perform on the first interactor' do
487
+ expect_any_instance_of(test_interactor_1).not_to receive(:perform)
488
+ subject
489
+ end
490
+
491
+ it 'is expected to invoke #perform on the second interactor' do
492
+ expect_any_instance_of(test_interactor_2).to receive(:perform)
493
+ subject
494
+ end
495
+ end
496
+ end
497
+
498
+ context 'with a condition on the first interactor { :unless => :test_method } and :test_method returning true' do
499
+ let(:interactor_class) do
500
+ build_organizer do
501
+ organize do
502
+ add :test_interactor_1, unless: :test_method
503
+ add :test_interactor_2
504
+ end
505
+
506
+ private
507
+
508
+ def test_method
509
+ true
510
+ end
511
+ end
512
+ end
513
+
514
+ include_examples 'a class with interactor methods'
515
+ include_examples 'a class with interactor callback methods'
516
+ include_examples 'a class with interactor context methods'
517
+ include_examples 'a class with organizer callback methods'
518
+
519
+ describe '.perform' do
520
+ subject { interactor_class.perform }
521
+
522
+ it { is_expected.to be_a interactor_class.context_class }
523
+ it { is_expected.to be_successful }
524
+ it 'is expected not to invoke #perform on the first interactor' do
525
+ expect_any_instance_of(test_interactor_1).not_to receive(:perform)
526
+ subject
527
+ end
528
+
529
+ it 'is expected to invoke #perform on the second interactor' do
530
+ expect_any_instance_of(test_interactor_2).to receive(:perform)
531
+ subject
532
+ end
533
+ end
534
+ end
535
+
536
+ context 'with a condition on the first interactor { :unless => :test_method } and :test_method returning false' do
537
+ let(:interactor_class) do
538
+ build_organizer do
539
+ organize do
540
+ add :test_interactor_1, unless: :test_method
541
+ add :test_interactor_2
542
+ end
543
+
544
+ private
545
+
546
+ def test_method
547
+ false
548
+ end
549
+ end
550
+ end
551
+
552
+ include_examples 'a class with interactor methods'
553
+ include_examples 'a class with interactor callback methods'
554
+ include_examples 'a class with interactor context methods'
555
+ include_examples 'a class with organizer callback methods'
556
+
557
+ describe '.perform' do
558
+ subject { interactor_class.perform }
559
+
560
+ it { is_expected.to be_a interactor_class.context_class }
561
+ it { is_expected.to be_successful }
562
+ it 'is expected to invoke #perform on both interactors' do
563
+ expect_any_instance_of(test_interactor_1).to receive(:perform)
564
+ expect_any_instance_of(test_interactor_2).to receive(:perform)
565
+ subject
566
+ end
567
+ end
568
+ end
569
+ end
271
570
  end