active_interaction 5.1.0 → 5.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +61 -0
- data/README.md +11 -12
- data/lib/active_interaction/base.rb +2 -0
- data/lib/active_interaction/errors.rb +16 -16
- data/lib/active_interaction/filter.rb +9 -12
- data/lib/active_interaction/filters/array_filter.rb +1 -1
- data/lib/active_interaction/filters/hash_filter.rb +5 -1
- data/lib/active_interaction/grouped_input.rb +23 -3
- data/lib/active_interaction/locale/es.yml +23 -0
- data/lib/active_interaction/version.rb +1 -1
- metadata +13 -115
- data/spec/active_interaction/array_input_spec.rb +0 -166
- data/spec/active_interaction/base_spec.rb +0 -537
- data/spec/active_interaction/concerns/active_modelable_spec.rb +0 -45
- data/spec/active_interaction/concerns/active_recordable_spec.rb +0 -49
- data/spec/active_interaction/concerns/hashable_spec.rb +0 -46
- data/spec/active_interaction/concerns/missable_spec.rb +0 -99
- data/spec/active_interaction/concerns/runnable_spec.rb +0 -397
- data/spec/active_interaction/errors_spec.rb +0 -196
- data/spec/active_interaction/filter/column_spec.rb +0 -87
- data/spec/active_interaction/filter_spec.rb +0 -39
- data/spec/active_interaction/filters/abstract_date_time_filter_spec.rb +0 -13
- data/spec/active_interaction/filters/abstract_numeric_filter_spec.rb +0 -13
- data/spec/active_interaction/filters/array_filter_spec.rb +0 -245
- data/spec/active_interaction/filters/boolean_filter_spec.rb +0 -87
- data/spec/active_interaction/filters/date_filter_spec.rb +0 -178
- data/spec/active_interaction/filters/date_time_filter_spec.rb +0 -189
- data/spec/active_interaction/filters/decimal_filter_spec.rb +0 -126
- data/spec/active_interaction/filters/file_filter_spec.rb +0 -40
- data/spec/active_interaction/filters/float_filter_spec.rb +0 -110
- data/spec/active_interaction/filters/hash_filter_spec.rb +0 -129
- data/spec/active_interaction/filters/integer_filter_spec.rb +0 -104
- data/spec/active_interaction/filters/interface_filter_spec.rb +0 -461
- data/spec/active_interaction/filters/object_filter_spec.rb +0 -237
- data/spec/active_interaction/filters/record_filter_spec.rb +0 -206
- data/spec/active_interaction/filters/string_filter_spec.rb +0 -60
- data/spec/active_interaction/filters/symbol_filter_spec.rb +0 -46
- data/spec/active_interaction/filters/time_filter_spec.rb +0 -251
- data/spec/active_interaction/grouped_input_spec.rb +0 -17
- data/spec/active_interaction/hash_input_spec.rb +0 -58
- data/spec/active_interaction/i18n_spec.rb +0 -113
- data/spec/active_interaction/inputs_spec.rb +0 -266
- data/spec/active_interaction/integration/array_interaction_spec.rb +0 -88
- data/spec/active_interaction/integration/boolean_interaction_spec.rb +0 -5
- data/spec/active_interaction/integration/date_interaction_spec.rb +0 -5
- data/spec/active_interaction/integration/date_time_interaction_spec.rb +0 -5
- data/spec/active_interaction/integration/file_interaction_spec.rb +0 -18
- data/spec/active_interaction/integration/float_interaction_spec.rb +0 -5
- data/spec/active_interaction/integration/hash_interaction_spec.rb +0 -76
- data/spec/active_interaction/integration/integer_interaction_spec.rb +0 -5
- data/spec/active_interaction/integration/interface_interaction_spec.rb +0 -19
- data/spec/active_interaction/integration/object_interaction_spec.rb +0 -14
- data/spec/active_interaction/integration/record_integration_spec.rb +0 -5
- data/spec/active_interaction/integration/string_interaction_spec.rb +0 -5
- data/spec/active_interaction/integration/symbol_interaction_spec.rb +0 -5
- data/spec/active_interaction/integration/time_interaction_spec.rb +0 -88
- data/spec/active_interaction/modules/validation_spec.rb +0 -57
- data/spec/spec_helper.rb +0 -20
- data/spec/support/concerns.rb +0 -13
- data/spec/support/filters.rb +0 -227
- data/spec/support/interactions.rb +0 -124
@@ -1,45 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
shared_examples_for 'ActiveModel' do
|
4
|
-
it 'includes ActiveModel::Conversion' do
|
5
|
-
expect(subject).to be_a_kind_of ActiveModel::Conversion
|
6
|
-
end
|
7
|
-
|
8
|
-
it 'includes ActiveModel::Validations' do
|
9
|
-
expect(subject).to be_a_kind_of ActiveModel::Validations
|
10
|
-
end
|
11
|
-
|
12
|
-
it 'extends ActiveModel::Naming' do
|
13
|
-
expect(subject.class).to be_a_kind_of ActiveModel::Naming
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
describe ActiveInteraction::ActiveModelable do
|
18
|
-
include_context 'concerns', described_class
|
19
|
-
|
20
|
-
it_behaves_like 'ActiveModel'
|
21
|
-
|
22
|
-
describe '.i18n_scope' do
|
23
|
-
it 'returns the scope' do
|
24
|
-
expect(klass.i18n_scope).to be :active_interaction
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
describe '#i18n_scope' do
|
29
|
-
it 'returns the scope' do
|
30
|
-
expect(instance.i18n_scope).to be :active_interaction
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
describe '#new_record?' do
|
35
|
-
it 'returns true' do
|
36
|
-
expect(instance).to be_new_record
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
describe '#persisted?' do
|
41
|
-
it 'returns false' do
|
42
|
-
expect(instance).to_not be_persisted
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
@@ -1,49 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
InteractionWithFloatFilter = Class.new(TestInteraction) do
|
4
|
-
float :thing
|
5
|
-
end
|
6
|
-
|
7
|
-
describe ActiveInteraction::ActiveRecordable do
|
8
|
-
include_context 'interactions'
|
9
|
-
|
10
|
-
let(:described_class) { InteractionWithFloatFilter }
|
11
|
-
|
12
|
-
describe '#column_for_attribute(name)' do
|
13
|
-
let(:column) { outcome.column_for_attribute(name) }
|
14
|
-
|
15
|
-
context 'name is not an input name' do
|
16
|
-
let(:name) { SecureRandom.hex }
|
17
|
-
|
18
|
-
it 'returns nil if the attribute cannot be found' do
|
19
|
-
expect(column).to be_nil
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
context 'name is an input name' do
|
24
|
-
let(:name) { described_class.filters.keys.first }
|
25
|
-
|
26
|
-
it 'returns a Filter::Column' do
|
27
|
-
expect(column).to be_a ActiveInteraction::Filter::Column
|
28
|
-
end
|
29
|
-
|
30
|
-
it 'returns a Filter::Column of type boolean' do
|
31
|
-
expect(column.type).to be :float
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
describe '#has_attribute?' do
|
37
|
-
it 'returns true if the filter exists' do
|
38
|
-
expect(outcome).to have_attribute(:thing)
|
39
|
-
end
|
40
|
-
|
41
|
-
it 'works with strings' do
|
42
|
-
expect(outcome).to have_attribute('thing')
|
43
|
-
end
|
44
|
-
|
45
|
-
it 'returns false if the filter does not exist' do
|
46
|
-
expect(outcome).to_not have_attribute(:not_a_filter)
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
@@ -1,46 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe ActiveInteraction::Hashable do
|
4
|
-
include_context 'concerns', described_class
|
5
|
-
|
6
|
-
describe '#hash(*args, &block)' do
|
7
|
-
context 'with no arguments' do
|
8
|
-
let(:hash) { instance.hash }
|
9
|
-
|
10
|
-
it 'returns an Integer' do
|
11
|
-
expect(hash).to be_an Integer
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
context 'with arguments' do
|
16
|
-
let(:arguments) { [:attribute, {}] }
|
17
|
-
let(:hash) { instance.hash(*arguments) }
|
18
|
-
|
19
|
-
before { allow(instance).to receive(:method_missing) }
|
20
|
-
|
21
|
-
it 'calls method_missing' do
|
22
|
-
hash
|
23
|
-
expect(instance).to have_received(:method_missing).once
|
24
|
-
.with(:hash, *arguments)
|
25
|
-
end
|
26
|
-
|
27
|
-
context 'with a block' do
|
28
|
-
let(:block) { proc {} }
|
29
|
-
let(:hash) { instance.hash(*arguments, &block) }
|
30
|
-
|
31
|
-
it 'calls method_missing' do
|
32
|
-
hash
|
33
|
-
expect(instance).to have_received(:method_missing).once
|
34
|
-
.with(:hash, *arguments)
|
35
|
-
end
|
36
|
-
|
37
|
-
it 'passes the block to method_missing' do
|
38
|
-
allow(instance).to receive(:method_missing) do |*, &other_block|
|
39
|
-
expect(other_block).to equal block
|
40
|
-
end
|
41
|
-
hash(&block)
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
@@ -1,99 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe ActiveInteraction::Missable do
|
4
|
-
include_context 'concerns', described_class
|
5
|
-
|
6
|
-
describe '#respond_to?(slug, include_all = false)' do
|
7
|
-
context 'with invalid slug' do
|
8
|
-
let(:slug) { :slug }
|
9
|
-
|
10
|
-
it 'returns false' do
|
11
|
-
expect(instance).to_not respond_to(slug)
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
context 'with valid slug' do
|
16
|
-
let(:slug) { :boolean }
|
17
|
-
|
18
|
-
it 'returns true' do
|
19
|
-
expect(instance).to respond_to(slug)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
describe '#method(sym)' do
|
25
|
-
context 'with invalid slug' do
|
26
|
-
let(:slug) { :slug }
|
27
|
-
|
28
|
-
it 'returns false' do
|
29
|
-
expect { instance.method(slug) }.to raise_error NameError
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
context 'with valid slug' do
|
34
|
-
let(:slug) { :boolean }
|
35
|
-
|
36
|
-
it 'returns true' do
|
37
|
-
expect(instance.method(slug)).to be_a Method
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
describe '#method_missing' do
|
43
|
-
context 'with invalid slug' do
|
44
|
-
let(:slug) { :slug }
|
45
|
-
|
46
|
-
it 'calls super' do
|
47
|
-
expect do
|
48
|
-
instance.public_send(slug)
|
49
|
-
end.to raise_error NameError
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
context 'with valid slug' do
|
54
|
-
let(:filter) { ActiveInteraction::Filter.factory(slug) }
|
55
|
-
let(:slug) { :boolean }
|
56
|
-
|
57
|
-
it 'returns self' do
|
58
|
-
expect(instance.public_send(slug)).to eql instance
|
59
|
-
end
|
60
|
-
|
61
|
-
it 'yields' do
|
62
|
-
expect do |b|
|
63
|
-
instance.public_send(slug, &b)
|
64
|
-
end.to yield_with_args(filter, [], {})
|
65
|
-
end
|
66
|
-
|
67
|
-
context 'with names' do
|
68
|
-
let(:names) { %i[a b c] }
|
69
|
-
|
70
|
-
it 'yields' do
|
71
|
-
expect do |b|
|
72
|
-
instance.public_send(:boolean, *names, &b)
|
73
|
-
end.to yield_with_args(filter, names, {})
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
context 'with options' do
|
78
|
-
let(:options) { { a: nil, b: false, c: true } }
|
79
|
-
|
80
|
-
it 'yields' do
|
81
|
-
expect do |b|
|
82
|
-
instance.public_send(:boolean, options, &b)
|
83
|
-
end.to yield_with_args(filter, [], options)
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
context 'with names & options' do
|
88
|
-
let(:names) { %i[a b c] }
|
89
|
-
let(:options) { { a: nil, b: false, c: true } }
|
90
|
-
|
91
|
-
it 'yields' do
|
92
|
-
expect do |b|
|
93
|
-
instance.public_send(:boolean, *names, options, &b)
|
94
|
-
end.to yield_with_args(filter, names, options)
|
95
|
-
end
|
96
|
-
end
|
97
|
-
end
|
98
|
-
end
|
99
|
-
end
|
@@ -1,397 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe ActiveInteraction::Runnable do
|
4
|
-
include_context 'concerns', described_class
|
5
|
-
|
6
|
-
class WrappableFailingInteraction # rubocop:disable Lint/ConstantDefinitionInBlock
|
7
|
-
include ActiveInteraction::Runnable
|
8
|
-
|
9
|
-
def execute
|
10
|
-
errors.add(:base)
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
shared_context 'with an error' do
|
15
|
-
before { instance.errors.add(:base) }
|
16
|
-
end
|
17
|
-
|
18
|
-
shared_context 'with a validator' do
|
19
|
-
before { klass.validate { errors.add(:base) } }
|
20
|
-
end
|
21
|
-
|
22
|
-
shared_context 'with #execute defined' do
|
23
|
-
before { klass.send(:define_method, :execute) { rand } }
|
24
|
-
end
|
25
|
-
|
26
|
-
context 'validations' do
|
27
|
-
describe '#runtime_errors' do
|
28
|
-
include_context 'with an error'
|
29
|
-
|
30
|
-
it 'is invalid' do
|
31
|
-
instance.result = nil
|
32
|
-
expect(instance).to_not be_valid
|
33
|
-
end
|
34
|
-
|
35
|
-
it 'becomes valid if errors are cleared' do
|
36
|
-
instance.result = nil
|
37
|
-
instance.errors.clear
|
38
|
-
instance.result = nil
|
39
|
-
expect(instance).to be_valid
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
context 'callbacks' do
|
45
|
-
describe '.set_callback' do
|
46
|
-
include_context 'with #execute defined'
|
47
|
-
|
48
|
-
shared_examples 'set_callback examples' do |name|
|
49
|
-
context name do
|
50
|
-
it 'does not raise an error' do
|
51
|
-
expect do
|
52
|
-
klass.set_callback name, :before, -> {}
|
53
|
-
end.to_not raise_error
|
54
|
-
end
|
55
|
-
|
56
|
-
%i[after around before].each do |type|
|
57
|
-
it type do
|
58
|
-
has_run = false
|
59
|
-
|
60
|
-
klass.set_callback name, type, -> { has_run = true }
|
61
|
-
|
62
|
-
klass.run
|
63
|
-
expect(has_run).to be_truthy
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
include_examples 'set_callback examples', :validate
|
70
|
-
include_examples 'set_callback examples', :execute
|
71
|
-
|
72
|
-
context 'execute with composed interaction' do
|
73
|
-
class WithFailingCompose # rubocop:disable Lint/ConstantDefinitionInBlock
|
74
|
-
include ActiveInteraction::Runnable
|
75
|
-
|
76
|
-
def execute
|
77
|
-
compose(WrappableFailingInteraction)
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
context 'around' do
|
82
|
-
it 'is yielded errors from composed interactions' do
|
83
|
-
block_result = nil
|
84
|
-
WithFailingCompose.set_callback :execute, :around do |_, block|
|
85
|
-
block_result = block.call
|
86
|
-
end
|
87
|
-
|
88
|
-
WithFailingCompose.run
|
89
|
-
expect(block_result).to be_an(ActiveInteraction::Errors)
|
90
|
-
expect(block_result).to include(:base)
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
context 'after' do
|
95
|
-
it 'is yielded errors from composed interactions' do
|
96
|
-
has_run = false
|
97
|
-
WithFailingCompose.set_callback :execute, :after do
|
98
|
-
has_run = true
|
99
|
-
end
|
100
|
-
|
101
|
-
WithFailingCompose.run
|
102
|
-
expect(has_run).to be_truthy
|
103
|
-
end
|
104
|
-
|
105
|
-
context 'using if' do
|
106
|
-
it 'yields errors to the if' do
|
107
|
-
has_run = false
|
108
|
-
WithFailingCompose.set_callback :execute, :after, if: -> { errors.any? } do
|
109
|
-
has_run = true
|
110
|
-
end
|
111
|
-
|
112
|
-
WithFailingCompose.run
|
113
|
-
expect(has_run).to be_truthy
|
114
|
-
end
|
115
|
-
end
|
116
|
-
end
|
117
|
-
end
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
describe '#errors' do
|
122
|
-
it 'returns the errors' do
|
123
|
-
expect(instance.errors).to be_an ActiveInteraction::Errors
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
describe '#execute' do
|
128
|
-
it 'raises an error' do
|
129
|
-
expect { instance.execute }.to raise_error NotImplementedError
|
130
|
-
end
|
131
|
-
end
|
132
|
-
|
133
|
-
describe '#result' do
|
134
|
-
it 'returns the result' do
|
135
|
-
expect(instance.result).to be_nil
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
describe '#result=' do
|
140
|
-
let(:result) { double }
|
141
|
-
|
142
|
-
it 'returns the result' do
|
143
|
-
expect((instance.result = result)).to eql result
|
144
|
-
end
|
145
|
-
|
146
|
-
it 'sets the result' do
|
147
|
-
instance.result = result
|
148
|
-
expect(instance.result).to eql result
|
149
|
-
end
|
150
|
-
|
151
|
-
context 'with an error' do
|
152
|
-
include_context 'with an error'
|
153
|
-
|
154
|
-
it 'sets the result' do
|
155
|
-
instance.result = result
|
156
|
-
expect(instance.result).to eql result
|
157
|
-
end
|
158
|
-
end
|
159
|
-
|
160
|
-
context 'with a validator' do
|
161
|
-
include_context 'with a validator'
|
162
|
-
|
163
|
-
it 'sets the result' do
|
164
|
-
instance.result = result
|
165
|
-
expect(instance.result).to eql result
|
166
|
-
end
|
167
|
-
end
|
168
|
-
end
|
169
|
-
|
170
|
-
describe '#valid?' do
|
171
|
-
let(:result) { double }
|
172
|
-
|
173
|
-
it 'returns true' do
|
174
|
-
expect(instance).to be_valid
|
175
|
-
end
|
176
|
-
|
177
|
-
context 'with an error' do
|
178
|
-
include_context 'with an error'
|
179
|
-
|
180
|
-
it 'returns true' do
|
181
|
-
expect(instance).to be_valid
|
182
|
-
end
|
183
|
-
end
|
184
|
-
|
185
|
-
context 'with a validator' do
|
186
|
-
include_context 'with a validator'
|
187
|
-
|
188
|
-
it 'returns false' do
|
189
|
-
expect(instance).to_not be_valid
|
190
|
-
end
|
191
|
-
|
192
|
-
it 'does not duplicate errors on subsequent calls' do
|
193
|
-
instance.valid?
|
194
|
-
count = instance.errors.count
|
195
|
-
instance.valid?
|
196
|
-
|
197
|
-
expect(instance.errors.count).to eql count
|
198
|
-
end
|
199
|
-
end
|
200
|
-
end
|
201
|
-
|
202
|
-
describe '.run' do
|
203
|
-
let(:outcome) { klass.run }
|
204
|
-
|
205
|
-
it 'raises an error' do
|
206
|
-
expect { outcome }.to raise_error NotImplementedError
|
207
|
-
end
|
208
|
-
|
209
|
-
context 'with #execute defined' do
|
210
|
-
include_context 'with #execute defined'
|
211
|
-
|
212
|
-
it 'returns an instance of Runnable' do
|
213
|
-
expect(outcome).to be_a klass
|
214
|
-
end
|
215
|
-
|
216
|
-
it 'sets the result' do
|
217
|
-
expect(outcome.result).to_not be_nil
|
218
|
-
end
|
219
|
-
|
220
|
-
context 'with a validator' do
|
221
|
-
include_context 'with a validator'
|
222
|
-
|
223
|
-
it 'returns an instance of Runnable' do
|
224
|
-
expect(outcome).to be_a klass
|
225
|
-
end
|
226
|
-
|
227
|
-
it 'sets the result to nil' do
|
228
|
-
expect(outcome.result).to be_nil
|
229
|
-
end
|
230
|
-
end
|
231
|
-
end
|
232
|
-
|
233
|
-
context 'caches the result of the run' do
|
234
|
-
context 'when it is invalid' do
|
235
|
-
let(:klass) do
|
236
|
-
Class.new(ActiveInteraction::Base) do
|
237
|
-
invalid = [false, true].cycle
|
238
|
-
|
239
|
-
validate do |interaction|
|
240
|
-
interaction.errors.add(:base, 'failed') unless invalid.next
|
241
|
-
end
|
242
|
-
|
243
|
-
def execute
|
244
|
-
true
|
245
|
-
end
|
246
|
-
end
|
247
|
-
end
|
248
|
-
|
249
|
-
it 'fails' do
|
250
|
-
expect(outcome).to_not be_valid
|
251
|
-
expect(outcome.result).to be_nil
|
252
|
-
expect(outcome).to_not be_valid
|
253
|
-
expect(outcome.result).to be_nil
|
254
|
-
end
|
255
|
-
end
|
256
|
-
|
257
|
-
context 'when it is valid' do
|
258
|
-
let(:klass) do
|
259
|
-
Class.new(ActiveInteraction::Base) do
|
260
|
-
valid = [true, false].cycle
|
261
|
-
|
262
|
-
validate do |interaction|
|
263
|
-
interaction.errors.add(:base, 'failed') unless valid.next
|
264
|
-
end
|
265
|
-
|
266
|
-
def execute
|
267
|
-
true
|
268
|
-
end
|
269
|
-
end
|
270
|
-
end
|
271
|
-
|
272
|
-
it 'succeeds' do
|
273
|
-
expect(outcome).to be_valid
|
274
|
-
expect(outcome.result).to be true
|
275
|
-
expect(outcome).to be_valid
|
276
|
-
expect(outcome.result).to be true
|
277
|
-
end
|
278
|
-
end
|
279
|
-
end
|
280
|
-
|
281
|
-
context 'with valid post-execution state' do
|
282
|
-
before do
|
283
|
-
klass.class_exec do
|
284
|
-
attr_accessor :attribute
|
285
|
-
|
286
|
-
validate { errors.add(:attribute) unless attribute }
|
287
|
-
|
288
|
-
def execute
|
289
|
-
self.attribute = true
|
290
|
-
end
|
291
|
-
end
|
292
|
-
end
|
293
|
-
|
294
|
-
it 'is invalid' do
|
295
|
-
expect(outcome).to_not be_valid
|
296
|
-
end
|
297
|
-
|
298
|
-
it 'stays invalid' do
|
299
|
-
outcome.attribute = false
|
300
|
-
expect(outcome).to_not be_valid
|
301
|
-
end
|
302
|
-
end
|
303
|
-
|
304
|
-
context 'with invalid post-execution state' do
|
305
|
-
before do
|
306
|
-
klass.class_exec do
|
307
|
-
attr_accessor :attribute
|
308
|
-
|
309
|
-
validate { errors.add(:attribute) if attribute }
|
310
|
-
|
311
|
-
def execute
|
312
|
-
self.attribute = true
|
313
|
-
end
|
314
|
-
end
|
315
|
-
end
|
316
|
-
|
317
|
-
it 'is valid' do
|
318
|
-
expect(outcome).to be_valid
|
319
|
-
end
|
320
|
-
|
321
|
-
it 'stays valid' do
|
322
|
-
outcome.attribute = true
|
323
|
-
expect(outcome).to be_valid
|
324
|
-
end
|
325
|
-
end
|
326
|
-
|
327
|
-
context 'with failing composition' do
|
328
|
-
class CheckInnerForFailure # rubocop:disable Lint/ConstantDefinitionInBlock
|
329
|
-
include ActiveInteraction::Runnable
|
330
|
-
|
331
|
-
attr_reader :caught_error
|
332
|
-
|
333
|
-
def execute
|
334
|
-
compose(WrappableFailingInteraction)
|
335
|
-
rescue StandardError
|
336
|
-
@caught_error = true
|
337
|
-
raise
|
338
|
-
end
|
339
|
-
end
|
340
|
-
|
341
|
-
it 'throws an error from the inner interaction' do
|
342
|
-
outcome = CheckInnerForFailure.run
|
343
|
-
expect(outcome.caught_error).to be true
|
344
|
-
end
|
345
|
-
end
|
346
|
-
|
347
|
-
context 'with block not called and error in execute around callback' do
|
348
|
-
class CheckExecuteAroundCallbackForFailure # rubocop:disable Lint/ConstantDefinitionInBlock
|
349
|
-
include ActiveInteraction::ActiveModelable
|
350
|
-
include ActiveInteraction::Runnable
|
351
|
-
|
352
|
-
set_callback :execute, :around, -> { errors.add(:base, 'invalid') }
|
353
|
-
|
354
|
-
def execute
|
355
|
-
true
|
356
|
-
end
|
357
|
-
end
|
358
|
-
|
359
|
-
it 'is invalid' do
|
360
|
-
outcome = CheckExecuteAroundCallbackForFailure.run
|
361
|
-
expect(outcome).to_not be_valid
|
362
|
-
end
|
363
|
-
end
|
364
|
-
end
|
365
|
-
|
366
|
-
describe '.run!' do
|
367
|
-
let(:result) { klass.run! }
|
368
|
-
|
369
|
-
it 'raises an error' do
|
370
|
-
expect { result }.to raise_error NotImplementedError
|
371
|
-
end
|
372
|
-
|
373
|
-
context 'with #execute defined' do
|
374
|
-
include_context 'with #execute defined'
|
375
|
-
|
376
|
-
it 'returns the result' do
|
377
|
-
expect(result).to_not be_nil
|
378
|
-
end
|
379
|
-
|
380
|
-
context 'with a validator' do
|
381
|
-
include_context 'with a validator'
|
382
|
-
|
383
|
-
it 'raises an error' do
|
384
|
-
expect do
|
385
|
-
result
|
386
|
-
end.to raise_error ActiveInteraction::InvalidInteractionError
|
387
|
-
end
|
388
|
-
|
389
|
-
it 'adds interaction instance to this error' do
|
390
|
-
expect { result }.to raise_error do |error|
|
391
|
-
expect(error.interaction).to be_a klass
|
392
|
-
end
|
393
|
-
end
|
394
|
-
end
|
395
|
-
end
|
396
|
-
end
|
397
|
-
end
|