activeinteractor 0.1.7 → 1.0.0.beta.1
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +36 -1
- data/README.md +397 -395
- data/lib/active_interactor.rb +12 -30
- data/lib/active_interactor/base.rb +18 -8
- data/lib/active_interactor/context.rb +4 -181
- data/lib/active_interactor/context/attributes.rb +37 -149
- data/lib/active_interactor/context/base.rb +141 -0
- data/lib/active_interactor/context/loader.rb +45 -0
- data/lib/active_interactor/error.rb +22 -15
- data/lib/active_interactor/interactor.rb +24 -57
- data/lib/active_interactor/interactor/callbacks.rb +64 -76
- data/lib/active_interactor/interactor/context.rb +97 -63
- data/lib/active_interactor/interactor/worker.rb +22 -65
- data/lib/active_interactor/organizer.rb +180 -164
- data/lib/active_interactor/version.rb +2 -3
- data/lib/rails/generators/active_interactor.rb +2 -37
- data/lib/rails/generators/active_interactor/application_interactor_generator.rb +23 -0
- data/lib/rails/generators/active_interactor/install_generator.rb +8 -12
- data/lib/rails/generators/active_interactor/templates/application_context.rb +4 -0
- data/lib/rails/generators/{templates/application_interactor.erb → active_interactor/templates/application_interactor.rb} +0 -0
- data/lib/rails/generators/active_interactor/templates/application_organizer.rb +4 -0
- data/lib/rails/generators/active_interactor/templates/initializer.erb +5 -0
- data/lib/rails/generators/interactor/context/rspec_generator.rb +19 -0
- data/lib/rails/generators/interactor/context/templates/rspec.erb +7 -0
- data/lib/rails/generators/interactor/context/templates/test_unit.erb +9 -0
- data/lib/rails/generators/interactor/context/test_unit_generator.rb +19 -0
- data/lib/rails/generators/interactor/context_generator.rb +19 -0
- data/lib/rails/generators/interactor/interactor_generator.rb +8 -3
- data/lib/rails/generators/interactor/organizer_generator.rb +8 -3
- data/lib/rails/generators/interactor/rspec_generator.rb +4 -3
- data/lib/rails/generators/interactor/templates/context.erb +4 -0
- data/lib/rails/generators/{templates → interactor/templates}/interactor.erb +0 -0
- data/lib/rails/generators/{templates → interactor/templates}/organizer.erb +1 -1
- data/lib/rails/generators/{templates → interactor/templates}/rspec.erb +0 -0
- data/lib/rails/generators/{templates → interactor/templates}/test_unit.erb +0 -0
- data/lib/rails/generators/interactor/test_unit_generator.rb +4 -3
- data/spec/active_interactor/base_spec.rb +51 -0
- data/spec/active_interactor/context/base_spec.rb +229 -0
- data/spec/active_interactor/error_spec.rb +43 -0
- data/spec/active_interactor/interactor/worker_spec.rb +89 -0
- data/spec/active_interactor/organizer_spec.rb +178 -0
- data/spec/active_interactor_spec.rb +26 -0
- data/spec/integration/basic_callback_integration_spec.rb +355 -0
- data/spec/integration/basic_context_integration_spec.rb +73 -0
- data/spec/integration/basic_integration_spec.rb +220 -0
- data/spec/integration/basic_validations_integration_spec.rb +204 -0
- data/spec/spec_helper.rb +44 -0
- data/spec/support/helpers/factories.rb +41 -0
- data/spec/support/shared_examples/a_class_with_interactor_callback_methods_example.rb +99 -0
- data/spec/support/shared_examples/a_class_with_interactor_context_methods_example.rb +58 -0
- data/spec/support/shared_examples/a_class_with_interactor_methods_example.rb +21 -0
- data/spec/support/shared_examples/a_class_with_organizer_callback_methods_example.rb +39 -0
- data/spec/support/spec_helpers.rb +7 -0
- metadata +68 -138
- data/lib/active_interactor/configuration.rb +0 -38
- data/lib/active_interactor/interactor/execution.rb +0 -24
- data/lib/rails/generators/templates/initializer.erb +0 -15
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
RSpec.describe ActiveInteractor::Error::ContextFailure do
|
6
|
+
subject { described_class.new }
|
7
|
+
|
8
|
+
it { is_expected.to respond_to :context }
|
9
|
+
|
10
|
+
context 'when context is equal to nil' do
|
11
|
+
subject { described_class.new(nil) }
|
12
|
+
|
13
|
+
it { is_expected.to have_attributes(message: 'Context failed!') }
|
14
|
+
end
|
15
|
+
|
16
|
+
context 'when context is an instance of "TestContext"' do
|
17
|
+
before { build_context }
|
18
|
+
subject { described_class.new(TestContext.new) }
|
19
|
+
|
20
|
+
it { is_expected.to have_attributes(message: 'TestContext failed!') }
|
21
|
+
it 'is expected to have an instance of TestContext' do
|
22
|
+
expect(subject.context).to be_a TestContext
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
RSpec.describe ActiveInteractor::Error::InvalidContextClass do
|
28
|
+
subject { described_class.new }
|
29
|
+
|
30
|
+
it { is_expected.to respond_to :class_name }
|
31
|
+
|
32
|
+
context 'when class_name is equal to nil' do
|
33
|
+
subject { described_class.new(nil) }
|
34
|
+
|
35
|
+
it { is_expected.to have_attributes(message: 'invalid context class ') }
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'when class_name is equal to "MyContect"' do
|
39
|
+
subject { described_class.new('MyContext') }
|
40
|
+
|
41
|
+
it { is_expected.to have_attributes(message: 'invalid context class MyContext') }
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
RSpec.describe ActiveInteractor::Interactor::Worker do
|
6
|
+
context 'with interactor class TestInteractor' do
|
7
|
+
before { build_interactor }
|
8
|
+
let(:interactor) { TestInteractor.new }
|
9
|
+
|
10
|
+
describe '#execute_perform' do
|
11
|
+
subject { described_class.new(interactor).execute_perform }
|
12
|
+
|
13
|
+
it { is_expected.to be_an TestInteractor.context_class }
|
14
|
+
|
15
|
+
context 'when context fails' do
|
16
|
+
before do
|
17
|
+
allow_any_instance_of(TestInteractor).to receive(:perform)
|
18
|
+
.and_raise(ActiveInteractor::Error::ContextFailure)
|
19
|
+
end
|
20
|
+
|
21
|
+
it { expect { subject }.not_to raise_error }
|
22
|
+
it { is_expected.to be_an TestInteractor.context_class }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe '#execute_perform!' do
|
27
|
+
subject { described_class.new(interactor).execute_perform! }
|
28
|
+
|
29
|
+
it { is_expected.to be_an TestInteractor.context_class }
|
30
|
+
|
31
|
+
it 'is expected to run perform callbacks on interactor' do
|
32
|
+
expect_any_instance_of(TestInteractor).to receive(:run_callbacks)
|
33
|
+
.with(:perform)
|
34
|
+
subject
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'calls #perform on interactor instance' do
|
38
|
+
expect_any_instance_of(TestInteractor).to receive(:perform)
|
39
|
+
subject
|
40
|
+
end
|
41
|
+
|
42
|
+
context 'when interactor context is invalid on :calling' do
|
43
|
+
before do
|
44
|
+
allow_any_instance_of(TestInteractor.context_class).to receive(:valid?)
|
45
|
+
.with(:calling)
|
46
|
+
.and_return(false)
|
47
|
+
end
|
48
|
+
|
49
|
+
it { expect { subject }.to raise_error(ActiveInteractor::Error::ContextFailure) }
|
50
|
+
it 'rollsback the interactor context' do
|
51
|
+
expect_any_instance_of(TestInteractor).to receive(:context_rollback!)
|
52
|
+
expect { subject }.to raise_error(ActiveInteractor::Error::ContextFailure)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
context 'when interactor context is invalid on :called' do
|
57
|
+
before do
|
58
|
+
allow_any_instance_of(TestInteractor.context_class).to receive(:valid?)
|
59
|
+
.with(:calling)
|
60
|
+
.and_return(true)
|
61
|
+
allow_any_instance_of(TestInteractor.context_class).to receive(:valid?)
|
62
|
+
.with(:called)
|
63
|
+
.and_return(false)
|
64
|
+
end
|
65
|
+
|
66
|
+
it { expect { subject }.to raise_error(ActiveInteractor::Error::ContextFailure) }
|
67
|
+
it 'rollsback the interactor context' do
|
68
|
+
expect_any_instance_of(TestInteractor).to receive(:context_rollback!)
|
69
|
+
expect { subject }.to raise_error(ActiveInteractor::Error::ContextFailure)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe '#execute_rollback' do
|
75
|
+
subject { described_class.new(interactor).execute_rollback }
|
76
|
+
|
77
|
+
it 'is expected to run rollback callbacks on interactor' do
|
78
|
+
expect_any_instance_of(TestInteractor).to receive(:run_callbacks)
|
79
|
+
.with(:rollback)
|
80
|
+
subject
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'calls #context_rollback on interactor instance' do
|
84
|
+
expect_any_instance_of(TestInteractor).to receive(:context_rollback!)
|
85
|
+
subject
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,178 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
RSpec.describe ActiveInteractor::Organizer do
|
6
|
+
let(:interactor_class) { described_class }
|
7
|
+
include_examples 'a class with interactor methods'
|
8
|
+
include_examples 'a class with interactor callback methods'
|
9
|
+
include_examples 'a class with interactor context methods'
|
10
|
+
include_examples 'a class with organizer callback methods'
|
11
|
+
|
12
|
+
describe '.contextualize_with' do
|
13
|
+
subject { described_class.contextualize_with(klass) }
|
14
|
+
|
15
|
+
context 'with an class that does not exist' do
|
16
|
+
let(:klass) { 'SomeClassThatDoesNotExist' }
|
17
|
+
|
18
|
+
it { expect { subject }.to raise_error(ActiveInteractor::Error::InvalidContextClass) }
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'with context class TestContext' do
|
22
|
+
before { build_context }
|
23
|
+
|
24
|
+
context 'when passed as a string' do
|
25
|
+
let(:klass) { 'TestContext' }
|
26
|
+
|
27
|
+
it 'assigns the context class' do
|
28
|
+
subject
|
29
|
+
expect(described_class.context_class).to eq TestContext
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context 'when passed as a symbol' do
|
34
|
+
let(:klass) { :test_context }
|
35
|
+
|
36
|
+
it 'assigns the context class' do
|
37
|
+
subject
|
38
|
+
expect(described_class.context_class).to eq TestContext
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context 'when passed as a constant' do
|
43
|
+
let(:klass) { TestContext }
|
44
|
+
|
45
|
+
it 'assigns the context class' do
|
46
|
+
subject
|
47
|
+
expect(described_class.context_class).to eq TestContext
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe '.organize' do
|
54
|
+
subject { interactor_class }
|
55
|
+
context 'with two existing interactors' do
|
56
|
+
let!(:interactor1) { build_interactor('TestInteractor1') }
|
57
|
+
let!(:interactor2) { build_interactor('TestInteractor2') }
|
58
|
+
|
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
|
71
|
+
build_organizer do
|
72
|
+
organize :test_interactor_1, :test_interactor_2
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
it { is_expected.to have_attributes(organized: [TestInteractor1, TestInteractor2]) }
|
77
|
+
|
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
|
83
|
+
end
|
84
|
+
|
85
|
+
it { is_expected.to have_attributes(organized: [TestInteractor1, TestInteractor2]) }
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
context 'when interactors are passed as strings' do
|
90
|
+
let(:interactor_class) do
|
91
|
+
build_organizer do
|
92
|
+
organize 'TestInteractor1', 'TestInteractor2'
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
it { is_expected.to have_attributes(organized: [TestInteractor1, TestInteractor2]) }
|
97
|
+
|
98
|
+
context 'having a non existance interactor' do
|
99
|
+
let(:interactor_class) do
|
100
|
+
build_organizer do
|
101
|
+
organize 'TestInteractor1', 'InteractorThatDoesntExist', 'TestInteractor2'
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
it { is_expected.to have_attributes(organized: [TestInteractor1, TestInteractor2]) }
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
describe '#perform' do
|
112
|
+
subject { interactor_class.perform }
|
113
|
+
context 'with two existing interactors' do
|
114
|
+
let!(:interactor1) { build_interactor('TestInteractor1') }
|
115
|
+
let!(:interactor2) { build_interactor('TestInteractor2') }
|
116
|
+
let(:interactor_class) do
|
117
|
+
build_organizer do
|
118
|
+
organize TestInteractor1, TestInteractor2
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
it { is_expected.to be_a interactor_class.context_class }
|
123
|
+
it 'is expected to call #perform on both interactors' do
|
124
|
+
expect_any_instance_of(interactor1).to receive(:perform)
|
125
|
+
expect_any_instance_of(interactor2).to receive(:perform)
|
126
|
+
subject
|
127
|
+
end
|
128
|
+
|
129
|
+
context 'when the first interactor context fails' do
|
130
|
+
let!(:interactor1) do
|
131
|
+
build_interactor('TestInteractor1') do
|
132
|
+
def perform
|
133
|
+
context.fail!
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
it { expect { subject }.not_to raise_error }
|
139
|
+
it { is_expected.to be_a interactor_class.context_class }
|
140
|
+
it 'is expected to call #perform on the first interactor' do
|
141
|
+
expect_any_instance_of(interactor1).to receive(:perform)
|
142
|
+
subject
|
143
|
+
end
|
144
|
+
it 'is expected to not call #perform on the second interactor' do
|
145
|
+
expect_any_instance_of(interactor2).not_to receive(:perform)
|
146
|
+
subject
|
147
|
+
end
|
148
|
+
it 'is expected to call #rollback on the first interactor' do
|
149
|
+
expect_any_instance_of(interactor1).to receive(:rollback)
|
150
|
+
subject
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
context 'when the second interactor context fails' do
|
155
|
+
let!(:interactor2) do
|
156
|
+
build_interactor('TestInteractor2') do
|
157
|
+
def perform
|
158
|
+
context.fail!
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
it { expect { subject }.not_to raise_error }
|
164
|
+
it { is_expected.to be_a interactor_class.context_class }
|
165
|
+
it 'is expected to call #perform on both interactors' do
|
166
|
+
expect_any_instance_of(interactor1).to receive(:perform)
|
167
|
+
expect_any_instance_of(interactor2).to receive(:perform)
|
168
|
+
subject
|
169
|
+
end
|
170
|
+
it 'is expected to call #rollback on both interactors' do
|
171
|
+
expect_any_instance_of(interactor1).to receive(:rollback)
|
172
|
+
expect_any_instance_of(interactor2).to receive(:rollback)
|
173
|
+
subject
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
RSpec.describe ActiveInteractor do
|
6
|
+
describe '::VERSION' do
|
7
|
+
subject { described_class::VERSION }
|
8
|
+
|
9
|
+
it { is_expected.to be_a String }
|
10
|
+
end
|
11
|
+
|
12
|
+
describe '.logger' do
|
13
|
+
subject { described_class.logger }
|
14
|
+
|
15
|
+
it { is_expected.to be_a Logger }
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '.logger=' do
|
19
|
+
subject { described_class.logger = logger }
|
20
|
+
let!(:original_logger) { described_class.logger }
|
21
|
+
let(:logger) { double(:logger) }
|
22
|
+
after { described_class.logger = original_logger }
|
23
|
+
|
24
|
+
it { expect { subject }.to change { described_class.logger }.to(logger) }
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,355 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
RSpec.describe 'Basic Callback Integration', type: :integration do
|
6
|
+
describe 'An interactor with after context validation callbacks' do
|
7
|
+
let(:interactor_class) do
|
8
|
+
build_interactor do
|
9
|
+
context_validates :test_field, presence: true
|
10
|
+
after_context_validation :downcase_test_field
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def downcase_test_field
|
15
|
+
context.test_field = context.test_field.downcase
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
include_examples 'a class with interactor methods'
|
21
|
+
include_examples 'a class with interactor callback methods'
|
22
|
+
include_examples 'a class with interactor context methods'
|
23
|
+
|
24
|
+
describe '.perform' do
|
25
|
+
subject { interactor_class.perform(context_attributes) }
|
26
|
+
|
27
|
+
context 'with valid context attributes' do
|
28
|
+
let(:context_attributes) { { test_field: 'TEST' } }
|
29
|
+
|
30
|
+
it { is_expected.to be_a interactor_class.context_class }
|
31
|
+
it { is_expected.to be_successful }
|
32
|
+
it { is_expected.to have_attributes(test_field: 'test') }
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe 'An interactor with conditional after context validation callbacks' do
|
38
|
+
let(:interactor_class) do
|
39
|
+
build_interactor do
|
40
|
+
context_validates :test_field, presence: true
|
41
|
+
after_context_validation :downcase_test_field, if: -> { context.should_downcase }
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def downcase_test_field
|
46
|
+
context.test_field = context.test_field.downcase
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
include_examples 'a class with interactor methods'
|
52
|
+
include_examples 'a class with interactor callback methods'
|
53
|
+
include_examples 'a class with interactor context methods'
|
54
|
+
|
55
|
+
describe '.perform' do
|
56
|
+
subject { interactor_class.perform(context_attributes) }
|
57
|
+
|
58
|
+
context 'with :test_field "TEST" and :should_downcase true' do
|
59
|
+
let(:context_attributes) { { test_field: 'TEST', should_downcase: true } }
|
60
|
+
|
61
|
+
it { is_expected.to be_a interactor_class.context_class }
|
62
|
+
it { is_expected.to be_successful }
|
63
|
+
it { is_expected.to have_attributes(test_field: 'test') }
|
64
|
+
end
|
65
|
+
|
66
|
+
context 'with :test_field "TEST" and :should_downcase false' do
|
67
|
+
let(:context_attributes) { { test_field: 'TEST', should_downcase: false } }
|
68
|
+
|
69
|
+
it { is_expected.to be_a interactor_class.context_class }
|
70
|
+
it { is_expected.to be_successful }
|
71
|
+
it { is_expected.to have_attributes(test_field: 'TEST') }
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
describe 'An interactor with after perform callbacks' do
|
77
|
+
let(:interactor_class) do
|
78
|
+
build_interactor do
|
79
|
+
after_perform :test_after_perform
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
def test_after_perform; end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
include_examples 'a class with interactor methods'
|
88
|
+
include_examples 'a class with interactor callback methods'
|
89
|
+
include_examples 'a class with interactor context methods'
|
90
|
+
|
91
|
+
describe '.perform' do
|
92
|
+
subject { interactor_class.perform }
|
93
|
+
|
94
|
+
it { is_expected.to be_a interactor_class.context_class }
|
95
|
+
it { is_expected.to be_successful }
|
96
|
+
it 'is expected to call #test_after_perform' do
|
97
|
+
expect_any_instance_of(interactor_class).to receive(:test_after_perform)
|
98
|
+
subject
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
describe 'An interactor with after rollback callbacks' do
|
104
|
+
let(:interactor_class) do
|
105
|
+
build_interactor do
|
106
|
+
after_rollback :test_after_rollback
|
107
|
+
|
108
|
+
def perform
|
109
|
+
context.fail!
|
110
|
+
end
|
111
|
+
|
112
|
+
private
|
113
|
+
|
114
|
+
def test_after_rollback; end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
include_examples 'a class with interactor methods'
|
119
|
+
include_examples 'a class with interactor callback methods'
|
120
|
+
include_examples 'a class with interactor context methods'
|
121
|
+
|
122
|
+
describe '.perform' do
|
123
|
+
subject { interactor_class.perform }
|
124
|
+
|
125
|
+
it { is_expected.to be_a interactor_class.context_class }
|
126
|
+
it 'is expected to call #test_after_rollback' do
|
127
|
+
expect_any_instance_of(interactor_class).to receive(:test_after_rollback)
|
128
|
+
subject
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
describe 'An interactor with around perform callbacks' do
|
134
|
+
let(:interactor_class) do
|
135
|
+
build_interactor do
|
136
|
+
around_perform :test_around_perform
|
137
|
+
|
138
|
+
def perform
|
139
|
+
context.perform_step << 2
|
140
|
+
end
|
141
|
+
|
142
|
+
private
|
143
|
+
|
144
|
+
def test_around_perform
|
145
|
+
context.perform_step = []
|
146
|
+
context.perform_step << 1
|
147
|
+
yield
|
148
|
+
context.perform_step << 3
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
include_examples 'a class with interactor methods'
|
154
|
+
include_examples 'a class with interactor callback methods'
|
155
|
+
include_examples 'a class with interactor context methods'
|
156
|
+
|
157
|
+
describe '.perform' do
|
158
|
+
subject { interactor_class.perform }
|
159
|
+
|
160
|
+
it { is_expected.to be_a interactor_class.context_class }
|
161
|
+
it { is_expected.to have_attributes(perform_step: [1, 2, 3]) }
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
describe 'An interactor with around rollback callbacks' do
|
166
|
+
let(:interactor_class) do
|
167
|
+
build_interactor do
|
168
|
+
around_rollback :test_around_rollback
|
169
|
+
|
170
|
+
def perform
|
171
|
+
context.fail!
|
172
|
+
end
|
173
|
+
|
174
|
+
def rollback
|
175
|
+
context.rollback_step << 2
|
176
|
+
end
|
177
|
+
|
178
|
+
private
|
179
|
+
|
180
|
+
def test_around_rollback
|
181
|
+
context.rollback_step = []
|
182
|
+
context.rollback_step << 1
|
183
|
+
yield
|
184
|
+
context.rollback_step << 3
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
include_examples 'a class with interactor methods'
|
190
|
+
include_examples 'a class with interactor callback methods'
|
191
|
+
include_examples 'a class with interactor context methods'
|
192
|
+
|
193
|
+
describe '.perform' do
|
194
|
+
subject { interactor_class.perform }
|
195
|
+
|
196
|
+
it { is_expected.to be_a interactor_class.context_class }
|
197
|
+
it { is_expected.to have_attributes(rollback_step: [1, 2, 3]) }
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
describe 'An interactor with before perform callbacks' do
|
202
|
+
let(:interactor_class) do
|
203
|
+
build_interactor do
|
204
|
+
before_perform :test_before_perform
|
205
|
+
|
206
|
+
private
|
207
|
+
|
208
|
+
def test_before_perform; end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
include_examples 'a class with interactor methods'
|
213
|
+
include_examples 'a class with interactor callback methods'
|
214
|
+
include_examples 'a class with interactor context methods'
|
215
|
+
|
216
|
+
describe '.perform' do
|
217
|
+
subject { interactor_class.perform }
|
218
|
+
|
219
|
+
it { is_expected.to be_a interactor_class.context_class }
|
220
|
+
it { is_expected.to be_successful }
|
221
|
+
it 'is expected to call #test_before_perform' do
|
222
|
+
expect_any_instance_of(interactor_class).to receive(:test_before_perform)
|
223
|
+
subject
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
describe 'An interactor with before rollback callbacks' do
|
229
|
+
let(:interactor_class) do
|
230
|
+
build_interactor do
|
231
|
+
before_rollback :test_before_rollback
|
232
|
+
|
233
|
+
def perform
|
234
|
+
context.fail!
|
235
|
+
end
|
236
|
+
|
237
|
+
private
|
238
|
+
|
239
|
+
def test_before_rollback; end
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
include_examples 'a class with interactor methods'
|
244
|
+
include_examples 'a class with interactor callback methods'
|
245
|
+
include_examples 'a class with interactor context methods'
|
246
|
+
|
247
|
+
describe '.perform' do
|
248
|
+
subject { interactor_class.perform }
|
249
|
+
|
250
|
+
it { is_expected.to be_a interactor_class.context_class }
|
251
|
+
it 'is expected to call #test_before_rollback' do
|
252
|
+
expect_any_instance_of(interactor_class).to receive(:test_before_rollback)
|
253
|
+
subject
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
describe 'An organizer with after each callbacks' do
|
259
|
+
let!(:interactor1) { build_interactor('TestInteractor1') }
|
260
|
+
let!(:interactor2) { build_interactor('TestInteractor2') }
|
261
|
+
let(:interactor_class) do
|
262
|
+
build_organizer do
|
263
|
+
after_each_perform :test_after_each_perform
|
264
|
+
organize TestInteractor1, TestInteractor2
|
265
|
+
|
266
|
+
private
|
267
|
+
|
268
|
+
def test_after_each_perform; end
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
include_examples 'a class with interactor methods'
|
273
|
+
include_examples 'a class with interactor callback methods'
|
274
|
+
include_examples 'a class with interactor context methods'
|
275
|
+
include_examples 'a class with organizer callback methods'
|
276
|
+
|
277
|
+
describe '.perform' do
|
278
|
+
subject { interactor_class.perform }
|
279
|
+
|
280
|
+
it { is_expected.to be_a interactor_class.context_class }
|
281
|
+
it 'is expected to call #test_after_each_perform twice' do
|
282
|
+
expect_any_instance_of(interactor_class).to receive(:test_after_each_perform)
|
283
|
+
.exactly(:twice)
|
284
|
+
subject
|
285
|
+
end
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
describe 'An organizer with around each callbacks' do
|
290
|
+
let!(:interactor1) { build_interactor('TestInteractor1') }
|
291
|
+
let!(:interactor2) { build_interactor('TestInteractor2') }
|
292
|
+
let(:interactor_class) do
|
293
|
+
build_organizer do
|
294
|
+
around_each_perform :test_around_each_perform
|
295
|
+
organize TestInteractor1, TestInteractor2
|
296
|
+
|
297
|
+
private
|
298
|
+
|
299
|
+
def find_index
|
300
|
+
(context.around_each_step.last || 0) + 1
|
301
|
+
end
|
302
|
+
|
303
|
+
def test_around_each_perform
|
304
|
+
context.around_each_step ||= []
|
305
|
+
context.around_each_step << find_index
|
306
|
+
yield
|
307
|
+
context.around_each_step << find_index
|
308
|
+
end
|
309
|
+
end
|
310
|
+
end
|
311
|
+
|
312
|
+
include_examples 'a class with interactor methods'
|
313
|
+
include_examples 'a class with interactor callback methods'
|
314
|
+
include_examples 'a class with interactor context methods'
|
315
|
+
include_examples 'a class with organizer callback methods'
|
316
|
+
|
317
|
+
describe '.perform' do
|
318
|
+
subject { interactor_class.perform }
|
319
|
+
|
320
|
+
it { is_expected.to be_a interactor_class.context_class }
|
321
|
+
it { is_expected.to have_attributes(around_each_step: [1, 2, 3, 4]) }
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
325
|
+
describe 'An organizer with before each callbacks' do
|
326
|
+
let!(:interactor1) { build_interactor('TestInteractor1') }
|
327
|
+
let!(:interactor2) { build_interactor('TestInteractor2') }
|
328
|
+
let(:interactor_class) do
|
329
|
+
build_organizer do
|
330
|
+
before_each_perform :test_before_each_perform
|
331
|
+
organize TestInteractor1, TestInteractor2
|
332
|
+
|
333
|
+
private
|
334
|
+
|
335
|
+
def test_before_each_perform; end
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
339
|
+
include_examples 'a class with interactor methods'
|
340
|
+
include_examples 'a class with interactor callback methods'
|
341
|
+
include_examples 'a class with interactor context methods'
|
342
|
+
include_examples 'a class with organizer callback methods'
|
343
|
+
|
344
|
+
describe '.perform' do
|
345
|
+
subject { interactor_class.perform }
|
346
|
+
|
347
|
+
it { is_expected.to be_a interactor_class.context_class }
|
348
|
+
it 'is expected to call #test_before_each_perform twice' do
|
349
|
+
expect_any_instance_of(interactor_class).to receive(:test_before_each_perform)
|
350
|
+
.exactly(:twice)
|
351
|
+
subject
|
352
|
+
end
|
353
|
+
end
|
354
|
+
end
|
355
|
+
end
|