active_interaction 5.2.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 +39 -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/filters/hash_filter.rb +5 -1
- data/lib/active_interaction/grouped_input.rb +23 -3
- data/lib/active_interaction/version.rb +1 -1
- metadata +12 -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 -60
- 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 -250
- 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,537 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'action_controller'
|
3
|
-
require 'active_support/core_ext/kernel/reporting'
|
4
|
-
|
5
|
-
InteractionWithFilter = Class.new(TestInteraction) do
|
6
|
-
float :thing
|
7
|
-
end
|
8
|
-
|
9
|
-
InteractionWithDateFilter = Class.new(TestInteraction) do
|
10
|
-
date :thing
|
11
|
-
end
|
12
|
-
|
13
|
-
AddInteraction = Class.new(TestInteraction) do
|
14
|
-
float :x, :y
|
15
|
-
|
16
|
-
def execute
|
17
|
-
x + y
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
InterruptInteraction = Class.new(TestInteraction) do
|
22
|
-
object :x, :z,
|
23
|
-
class: Object,
|
24
|
-
default: nil
|
25
|
-
|
26
|
-
# NOTE: the relative position between this method
|
27
|
-
# and the compose line should be preserved.
|
28
|
-
def self.composition_location
|
29
|
-
"#{__FILE__}:#{__LINE__ + 4}:in `execute'"
|
30
|
-
end
|
31
|
-
|
32
|
-
def execute
|
33
|
-
compose(AddInteraction, x: x, y: z)
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
describe ActiveInteraction::Base do
|
38
|
-
subject(:interaction) { described_class.new(inputs) }
|
39
|
-
|
40
|
-
include_context 'interactions'
|
41
|
-
|
42
|
-
describe '.new(inputs = {})' do
|
43
|
-
it 'does not set instance vars for reserved input names' do
|
44
|
-
key = :execute
|
45
|
-
inputs[key] = nil
|
46
|
-
|
47
|
-
expect(interaction.instance_variable_defined?(:"@#{key}")).to be false
|
48
|
-
end
|
49
|
-
|
50
|
-
context 'with a filter' do
|
51
|
-
let(:described_class) { InteractionWithFilter }
|
52
|
-
|
53
|
-
context 'validation' do
|
54
|
-
context 'failing' do
|
55
|
-
before { inputs[:thing] = thing }
|
56
|
-
|
57
|
-
context 'with an invalid value' do
|
58
|
-
let(:thing) { 'a' }
|
59
|
-
|
60
|
-
it 'sets the attribute to the filtered value' do
|
61
|
-
expect(interaction.thing).to equal thing
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
context 'without a value' do
|
66
|
-
let(:thing) { nil }
|
67
|
-
|
68
|
-
it 'sets the attribute to the filtered value' do
|
69
|
-
expect(interaction.thing).to equal thing
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
context 'passing' do
|
75
|
-
before { inputs[:thing] = 1 }
|
76
|
-
|
77
|
-
it 'returns a valid outcome' do
|
78
|
-
expect(interaction).to be_valid
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
context 'with a single input' do
|
84
|
-
before { inputs[:thing] = 1 }
|
85
|
-
|
86
|
-
it 'sets the attribute to the filtered value' do
|
87
|
-
expect(interaction.thing).to be 1.0
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
context 'with multiple inputs' do
|
92
|
-
let(:described_class) { InteractionWithDateFilter }
|
93
|
-
let(:year) { 2012 }
|
94
|
-
let(:month) { 1 }
|
95
|
-
let(:day) { 2 }
|
96
|
-
|
97
|
-
before do
|
98
|
-
inputs.merge!(
|
99
|
-
'thing(1i)' => year.to_s,
|
100
|
-
'thing(2i)' => month.to_s,
|
101
|
-
'thing(3i)' => day.to_s
|
102
|
-
)
|
103
|
-
end
|
104
|
-
|
105
|
-
it 'returns a Date' do
|
106
|
-
expect(interaction.thing).to eql Date.new(year, month, day)
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
describe '.desc' do
|
113
|
-
let(:desc) { SecureRandom.hex }
|
114
|
-
|
115
|
-
it 'returns nil' do
|
116
|
-
expect(described_class.desc).to be_nil
|
117
|
-
end
|
118
|
-
|
119
|
-
context 'with a description' do
|
120
|
-
it 'returns the description' do
|
121
|
-
expect(described_class.desc(desc)).to eql desc
|
122
|
-
end
|
123
|
-
|
124
|
-
it 'saves the description' do
|
125
|
-
described_class.desc(desc)
|
126
|
-
expect(described_class.desc).to eql desc
|
127
|
-
end
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
describe '.method_missing(filter_type, *args, &block)' do
|
132
|
-
it 'raises an error for an invalid filter type' do
|
133
|
-
expect do
|
134
|
-
Class.new(TestInteraction) do
|
135
|
-
not_a_valid_filter_type :thing
|
136
|
-
end
|
137
|
-
end.to raise_error NoMethodError
|
138
|
-
end
|
139
|
-
|
140
|
-
it do
|
141
|
-
expect do
|
142
|
-
Class.new(TestInteraction) do
|
143
|
-
float :_interaction_thing
|
144
|
-
end
|
145
|
-
end.to raise_error ActiveInteraction::InvalidFilterError
|
146
|
-
end
|
147
|
-
|
148
|
-
context 'with a filter' do
|
149
|
-
let(:described_class) { InteractionWithFilter }
|
150
|
-
|
151
|
-
it 'adds an attr_reader' do
|
152
|
-
expect(interaction).to respond_to :thing
|
153
|
-
end
|
154
|
-
|
155
|
-
it 'adds an attr_writer' do
|
156
|
-
expect(interaction).to respond_to :thing=
|
157
|
-
end
|
158
|
-
end
|
159
|
-
|
160
|
-
context 'with multiple filters' do
|
161
|
-
let(:described_class) do
|
162
|
-
Class.new(TestInteraction) do
|
163
|
-
float :thing1, :thing2
|
164
|
-
end
|
165
|
-
end
|
166
|
-
|
167
|
-
%w[thing1 thing2].each do |thing|
|
168
|
-
it "adds an attr_reader for #{thing}" do
|
169
|
-
expect(interaction).to respond_to thing
|
170
|
-
end
|
171
|
-
|
172
|
-
it "adds an attr_writer for #{thing}" do
|
173
|
-
expect(interaction).to respond_to "#{thing}="
|
174
|
-
end
|
175
|
-
end
|
176
|
-
end
|
177
|
-
end
|
178
|
-
|
179
|
-
context 'with a filter' do
|
180
|
-
let(:described_class) { InteractionWithFilter }
|
181
|
-
let(:thing) { rand }
|
182
|
-
|
183
|
-
it 'warns when redefining a filter' do
|
184
|
-
klass = Class.new(described_class)
|
185
|
-
allow(klass).to receive(:warn)
|
186
|
-
expect(klass.boolean(:thing)).to have_received(:warn).with(/\AWARNING:/)
|
187
|
-
end
|
188
|
-
|
189
|
-
describe '.run(inputs = {})' do
|
190
|
-
it "returns an instance of #{described_class}" do
|
191
|
-
expect(outcome).to be_a described_class
|
192
|
-
end
|
193
|
-
|
194
|
-
context 'failing validations' do
|
195
|
-
it 'returns an invalid outcome' do
|
196
|
-
expect(outcome).to_not be_valid
|
197
|
-
end
|
198
|
-
|
199
|
-
it 'sets the result to nil' do
|
200
|
-
expect(result).to be_nil
|
201
|
-
end
|
202
|
-
end
|
203
|
-
|
204
|
-
context 'passing validations' do
|
205
|
-
before { inputs[:thing] = thing }
|
206
|
-
|
207
|
-
context 'failing runtime validations' do
|
208
|
-
around do |example|
|
209
|
-
old_method = described_class.instance_method(:execute)
|
210
|
-
described_class.send(:define_method, :execute) do
|
211
|
-
errors.add(:thing, 'is invalid')
|
212
|
-
errors.add(:thing, :invalid)
|
213
|
-
true
|
214
|
-
end
|
215
|
-
|
216
|
-
example.run
|
217
|
-
|
218
|
-
silence_warnings do
|
219
|
-
described_class.send(:define_method, :execute, old_method)
|
220
|
-
end
|
221
|
-
end
|
222
|
-
|
223
|
-
it 'returns an invalid outcome' do
|
224
|
-
expect(outcome).to be_invalid
|
225
|
-
end
|
226
|
-
|
227
|
-
it 'sets the result' do
|
228
|
-
expect(result).to be true
|
229
|
-
end
|
230
|
-
|
231
|
-
it 'has errors' do
|
232
|
-
expect(outcome.errors.messages[:thing]).to eql [
|
233
|
-
'is invalid',
|
234
|
-
'is invalid'
|
235
|
-
]
|
236
|
-
end
|
237
|
-
|
238
|
-
it 'has detailed errors' do
|
239
|
-
expect(outcome.errors.details[:thing]).to eql [
|
240
|
-
{ error: 'is invalid' },
|
241
|
-
{ error: :invalid }
|
242
|
-
]
|
243
|
-
end
|
244
|
-
end
|
245
|
-
|
246
|
-
it 'returns a valid outcome' do
|
247
|
-
expect(outcome).to be_valid
|
248
|
-
end
|
249
|
-
|
250
|
-
it 'sets the result' do
|
251
|
-
expect(result[:thing]).to eql thing
|
252
|
-
end
|
253
|
-
end
|
254
|
-
end
|
255
|
-
|
256
|
-
describe '.run!(inputs = {})' do
|
257
|
-
subject(:result) { described_class.run!(inputs) }
|
258
|
-
|
259
|
-
context 'failing validations' do
|
260
|
-
it 'raises an error' do
|
261
|
-
expect do
|
262
|
-
result
|
263
|
-
end.to raise_error ActiveInteraction::InvalidInteractionError
|
264
|
-
end
|
265
|
-
end
|
266
|
-
|
267
|
-
context 'passing validations' do
|
268
|
-
before { inputs[:thing] = thing }
|
269
|
-
|
270
|
-
it 'returns the result' do
|
271
|
-
expect(result[:thing]).to eql thing
|
272
|
-
end
|
273
|
-
end
|
274
|
-
end
|
275
|
-
end
|
276
|
-
|
277
|
-
describe '#inputs' do
|
278
|
-
let(:described_class) { InteractionWithFilter }
|
279
|
-
let(:other_val) { SecureRandom.hex }
|
280
|
-
let(:inputs) { { thing: 1, other: other_val } }
|
281
|
-
|
282
|
-
it 'casts filtered inputs' do
|
283
|
-
expect(interaction.inputs[:thing]).to be 1.0
|
284
|
-
end
|
285
|
-
|
286
|
-
it 'strips non-filtered inputs' do
|
287
|
-
expect(interaction.inputs).to_not have_key(:other)
|
288
|
-
end
|
289
|
-
end
|
290
|
-
|
291
|
-
describe '#compose' do
|
292
|
-
let(:described_class) { InterruptInteraction }
|
293
|
-
let(:x) { rand }
|
294
|
-
let(:z) { rand }
|
295
|
-
|
296
|
-
context 'with valid composition' do
|
297
|
-
context 'when inputs is a hash' do
|
298
|
-
let(:inputs) { { x: x, z: z } }
|
299
|
-
|
300
|
-
it 'is valid' do
|
301
|
-
expect(outcome).to be_valid
|
302
|
-
end
|
303
|
-
|
304
|
-
it 'returns the sum' do
|
305
|
-
expect(result).to eql x + z
|
306
|
-
end
|
307
|
-
end
|
308
|
-
|
309
|
-
context 'when inputs is an ActiveInteraction::Inputs' do
|
310
|
-
let(:inputs) { ActiveInteraction::Inputs.new({ x: x, z: z }, described_class.new) }
|
311
|
-
|
312
|
-
it 'is valid' do
|
313
|
-
expect(outcome).to be_valid
|
314
|
-
end
|
315
|
-
|
316
|
-
it 'returns the sum' do
|
317
|
-
expect(result).to eql x + z
|
318
|
-
end
|
319
|
-
end
|
320
|
-
end
|
321
|
-
|
322
|
-
context 'with invalid composition' do
|
323
|
-
it 'is invalid' do
|
324
|
-
expect(outcome).to be_invalid
|
325
|
-
end
|
326
|
-
|
327
|
-
it 'has the correct errors' do
|
328
|
-
expect(outcome.errors.details)
|
329
|
-
.to eql(x: [{ error: :missing }], base: [{ error: 'Y is required' }])
|
330
|
-
end
|
331
|
-
|
332
|
-
it 'has the correct backtrace' do
|
333
|
-
described_class.run!(inputs)
|
334
|
-
rescue ActiveInteraction::InvalidInteractionError => e
|
335
|
-
expect(e.backtrace)
|
336
|
-
.to include(InterruptInteraction.composition_location)
|
337
|
-
end
|
338
|
-
end
|
339
|
-
end
|
340
|
-
|
341
|
-
describe '#execute' do
|
342
|
-
it 'raises an error' do
|
343
|
-
expect { interaction.execute }.to raise_error NotImplementedError
|
344
|
-
end
|
345
|
-
end
|
346
|
-
|
347
|
-
context 'inheritance' do
|
348
|
-
context 'filters' do
|
349
|
-
let(:described_class) { InteractionWithFilter }
|
350
|
-
|
351
|
-
def filters(klass)
|
352
|
-
klass.filters.keys
|
353
|
-
end
|
354
|
-
|
355
|
-
it 'includes the filters from the superclass' do
|
356
|
-
expect(filters(Class.new(described_class))).to include :thing
|
357
|
-
end
|
358
|
-
|
359
|
-
it 'does not mutate the filters on the superclass' do
|
360
|
-
Class.new(described_class) { float :other_thing }
|
361
|
-
|
362
|
-
expect(filters(described_class)).to_not include :other_thing
|
363
|
-
end
|
364
|
-
end
|
365
|
-
|
366
|
-
context 'validators' do
|
367
|
-
it 'does not pollute validators' do
|
368
|
-
a = Class.new(ActiveInteraction::Base) do
|
369
|
-
string :a
|
370
|
-
validates_presence_of :a
|
371
|
-
end
|
372
|
-
|
373
|
-
b = Class.new(ActiveInteraction::Base) do
|
374
|
-
string :b
|
375
|
-
validates_presence_of :b
|
376
|
-
end
|
377
|
-
|
378
|
-
expect(a.validators).to_not eql b.validators
|
379
|
-
end
|
380
|
-
|
381
|
-
it 'gives duped validators to subclasses' do
|
382
|
-
a = Class.new(ActiveInteraction::Base) do
|
383
|
-
string :a
|
384
|
-
validates_presence_of :a
|
385
|
-
end
|
386
|
-
|
387
|
-
b = Class.new(a)
|
388
|
-
|
389
|
-
expect(a.validators).to eql b.validators
|
390
|
-
expect(a.validators).to_not equal b.validators
|
391
|
-
end
|
392
|
-
end
|
393
|
-
end
|
394
|
-
|
395
|
-
describe '.import_filters' do
|
396
|
-
shared_context 'import_filters context' do |only, except|
|
397
|
-
let(:klass) { AddInteraction }
|
398
|
-
|
399
|
-
let(:described_class) do
|
400
|
-
interaction = klass
|
401
|
-
options = {}
|
402
|
-
options[:only] = only unless only.nil?
|
403
|
-
options[:except] = except unless except.nil?
|
404
|
-
|
405
|
-
Class.new(TestInteraction) { import_filters interaction, options }
|
406
|
-
end
|
407
|
-
end
|
408
|
-
|
409
|
-
shared_examples 'import_filters examples' do |only, except|
|
410
|
-
include_context 'import_filters context', only, except
|
411
|
-
|
412
|
-
it 'imports the filters' do
|
413
|
-
expect(described_class.filters).to eql(
|
414
|
-
klass.filters
|
415
|
-
.select { |k, _| only.nil? ? true : [*only].include?(k) }
|
416
|
-
.reject { |k, _| except.nil? ? false : [*except].include?(k) }
|
417
|
-
)
|
418
|
-
end
|
419
|
-
|
420
|
-
it 'does not modify the source' do
|
421
|
-
filters = klass.filters.dup
|
422
|
-
described_class
|
423
|
-
expect(klass.filters).to eql filters
|
424
|
-
end
|
425
|
-
|
426
|
-
it 'responds to readers and writers' do
|
427
|
-
instance = described_class.new
|
428
|
-
|
429
|
-
described_class.filters.each_key do |name|
|
430
|
-
[name, "#{name}="].each do |method|
|
431
|
-
expect(instance).to respond_to method
|
432
|
-
end
|
433
|
-
end
|
434
|
-
end
|
435
|
-
end
|
436
|
-
|
437
|
-
context 'with neither :only nor :except' do
|
438
|
-
include_examples 'import_filters examples', nil, nil
|
439
|
-
end
|
440
|
-
|
441
|
-
context 'with :only' do
|
442
|
-
context 'as an Array' do
|
443
|
-
include_examples 'import_filters examples', [:x], nil
|
444
|
-
end
|
445
|
-
|
446
|
-
context 'as an Symbol' do
|
447
|
-
include_examples 'import_filters examples', :x, nil
|
448
|
-
end
|
449
|
-
end
|
450
|
-
|
451
|
-
context 'with :except' do
|
452
|
-
context 'as an Array' do
|
453
|
-
include_examples 'import_filters examples', nil, [:x]
|
454
|
-
end
|
455
|
-
|
456
|
-
context 'as an Symbol' do
|
457
|
-
include_examples 'import_filters examples', nil, :x
|
458
|
-
end
|
459
|
-
end
|
460
|
-
|
461
|
-
context 'with :only & :except' do
|
462
|
-
include_examples 'import_filters examples', [:x], [:x]
|
463
|
-
end
|
464
|
-
end
|
465
|
-
|
466
|
-
context 'callbacks' do
|
467
|
-
let(:described_class) { Class.new(TestInteraction) }
|
468
|
-
|
469
|
-
%w[filter validate execute].each do |name|
|
470
|
-
%w[before after around].map(&:to_sym).each do |type|
|
471
|
-
it "runs the #{type} #{name} callback" do
|
472
|
-
called = false
|
473
|
-
described_class.set_callback(name, type) { called = true }
|
474
|
-
outcome
|
475
|
-
expect(called).to be_truthy
|
476
|
-
end
|
477
|
-
end
|
478
|
-
end
|
479
|
-
|
480
|
-
context 'with errors during filter' do
|
481
|
-
before do
|
482
|
-
described_class.set_callback(:filter, :before) do
|
483
|
-
errors.add(:base)
|
484
|
-
end
|
485
|
-
end
|
486
|
-
|
487
|
-
it 'is invalid' do
|
488
|
-
expect(outcome).to be_invalid
|
489
|
-
end
|
490
|
-
|
491
|
-
it 'does not run validate callbacks' do
|
492
|
-
called = false
|
493
|
-
described_class.set_callback(:validate, :before) { called = true }
|
494
|
-
outcome
|
495
|
-
expect(called).to be_falsey
|
496
|
-
end
|
497
|
-
|
498
|
-
it 'does not run execute callbacks' do
|
499
|
-
called = false
|
500
|
-
described_class.set_callback(:execute, :before) { called = true }
|
501
|
-
outcome
|
502
|
-
expect(called).to be_falsey
|
503
|
-
end
|
504
|
-
end
|
505
|
-
|
506
|
-
context 'with errors during validate' do
|
507
|
-
before do
|
508
|
-
described_class.set_callback(:validate, :before) do
|
509
|
-
errors.add(:base)
|
510
|
-
end
|
511
|
-
end
|
512
|
-
|
513
|
-
it 'is invalid' do
|
514
|
-
expect(outcome).to be_invalid
|
515
|
-
end
|
516
|
-
|
517
|
-
it 'does not run execute callbacks' do
|
518
|
-
called = false
|
519
|
-
described_class.set_callback(:execute, :before) { called = true }
|
520
|
-
outcome
|
521
|
-
expect(called).to be_falsey
|
522
|
-
end
|
523
|
-
end
|
524
|
-
|
525
|
-
context 'with errors during execute' do
|
526
|
-
before do
|
527
|
-
described_class.set_callback(:execute, :before) do
|
528
|
-
errors.add(:base)
|
529
|
-
end
|
530
|
-
end
|
531
|
-
|
532
|
-
it 'is invalid' do
|
533
|
-
expect(outcome).to be_invalid
|
534
|
-
end
|
535
|
-
end
|
536
|
-
end
|
537
|
-
end
|
@@ -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
|