active_interaction 5.3.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 +26 -0
- data/README.md +2 -2
- data/lib/active_interaction/errors.rb +1 -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 -164
- data/spec/active_interaction/base_spec.rb +0 -536
- data/spec/active_interaction/concerns/active_modelable_spec.rb +0 -43
- data/spec/active_interaction/concerns/active_recordable_spec.rb +0 -47
- data/spec/active_interaction/concerns/hashable_spec.rb +0 -44
- data/spec/active_interaction/concerns/missable_spec.rb +0 -97
- data/spec/active_interaction/concerns/runnable_spec.rb +0 -395
- data/spec/active_interaction/errors_spec.rb +0 -223
- data/spec/active_interaction/filter/column_spec.rb +0 -85
- data/spec/active_interaction/filter_spec.rb +0 -58
- data/spec/active_interaction/filters/abstract_date_time_filter_spec.rb +0 -11
- data/spec/active_interaction/filters/abstract_numeric_filter_spec.rb +0 -11
- data/spec/active_interaction/filters/array_filter_spec.rb +0 -248
- data/spec/active_interaction/filters/boolean_filter_spec.rb +0 -85
- data/spec/active_interaction/filters/date_filter_spec.rb +0 -176
- data/spec/active_interaction/filters/date_time_filter_spec.rb +0 -187
- data/spec/active_interaction/filters/decimal_filter_spec.rb +0 -124
- data/spec/active_interaction/filters/file_filter_spec.rb +0 -38
- data/spec/active_interaction/filters/float_filter_spec.rb +0 -109
- data/spec/active_interaction/filters/hash_filter_spec.rb +0 -127
- data/spec/active_interaction/filters/integer_filter_spec.rb +0 -102
- data/spec/active_interaction/filters/interface_filter_spec.rb +0 -459
- data/spec/active_interaction/filters/object_filter_spec.rb +0 -235
- data/spec/active_interaction/filters/record_filter_spec.rb +0 -204
- data/spec/active_interaction/filters/string_filter_spec.rb +0 -58
- data/spec/active_interaction/filters/symbol_filter_spec.rb +0 -44
- data/spec/active_interaction/filters/time_filter_spec.rb +0 -249
- data/spec/active_interaction/grouped_input_spec.rb +0 -15
- data/spec/active_interaction/hash_input_spec.rb +0 -56
- data/spec/active_interaction/i18n_spec.rb +0 -111
- data/spec/active_interaction/inputs_spec.rb +0 -264
- data/spec/active_interaction/integration/array_interaction_spec.rb +0 -87
- data/spec/active_interaction/integration/boolean_interaction_spec.rb +0 -11
- data/spec/active_interaction/integration/date_interaction_spec.rb +0 -3
- data/spec/active_interaction/integration/date_time_interaction_spec.rb +0 -3
- data/spec/active_interaction/integration/file_interaction_spec.rb +0 -17
- data/spec/active_interaction/integration/float_interaction_spec.rb +0 -3
- data/spec/active_interaction/integration/hash_interaction_spec.rb +0 -106
- data/spec/active_interaction/integration/integer_interaction_spec.rb +0 -3
- data/spec/active_interaction/integration/interface_interaction_spec.rb +0 -18
- data/spec/active_interaction/integration/object_interaction_spec.rb +0 -12
- data/spec/active_interaction/integration/record_integration_spec.rb +0 -3
- data/spec/active_interaction/integration/string_interaction_spec.rb +0 -3
- data/spec/active_interaction/integration/symbol_interaction_spec.rb +0 -3
- data/spec/active_interaction/integration/time_interaction_spec.rb +0 -86
- data/spec/active_interaction/modules/validation_spec.rb +0 -55
- data/spec/spec_helper.rb +0 -22
- data/spec/support/concerns.rb +0 -13
- data/spec/support/filters.rb +0 -227
- data/spec/support/interactions.rb +0 -124
@@ -1,86 +0,0 @@
|
|
1
|
-
TimeWithZone = Class.new do
|
2
|
-
attr_reader :time
|
3
|
-
|
4
|
-
def initialize(time)
|
5
|
-
@time = time
|
6
|
-
end
|
7
|
-
|
8
|
-
def ==(other)
|
9
|
-
!other.nil? && time == other.time
|
10
|
-
end
|
11
|
-
|
12
|
-
def at(*args)
|
13
|
-
TimeWithZone.new(Time.at(*args) + 1)
|
14
|
-
end
|
15
|
-
|
16
|
-
def parse(*args)
|
17
|
-
TimeWithZone.new(Time.parse(*args) + 1)
|
18
|
-
rescue ArgumentError
|
19
|
-
nil
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
TimeInteraction = Class.new(TestInteraction) do
|
24
|
-
time :a
|
25
|
-
end
|
26
|
-
|
27
|
-
RSpec.describe TimeInteraction do
|
28
|
-
include_context 'interactions'
|
29
|
-
it_behaves_like 'an interaction', :time, -> { Time.now }
|
30
|
-
|
31
|
-
context 'with a time zone' do
|
32
|
-
let(:a) { nil }
|
33
|
-
|
34
|
-
before do
|
35
|
-
inputs[:a] = a
|
36
|
-
|
37
|
-
allow(Time).to receive(:zone).and_return(TimeWithZone.new(0))
|
38
|
-
end
|
39
|
-
|
40
|
-
context 'with an integer' do
|
41
|
-
let(:a) { rand(1 << 16) }
|
42
|
-
|
43
|
-
it 'returns the correct value' do
|
44
|
-
expect(result[:a]).to eq TimeWithZone.new(0).at(a)
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
context 'with a string' do
|
49
|
-
let(:a) { '2011-12-13T14:15:16Z' }
|
50
|
-
|
51
|
-
it 'returns the correct value' do
|
52
|
-
expect(result[:a]).to eq TimeWithZone.new(0).parse(a)
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
context 'with an invalid String' do
|
57
|
-
let(:a) { 'invalid' }
|
58
|
-
|
59
|
-
it 'is invalid' do
|
60
|
-
expect(outcome).to be_invalid
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
context 'with a Time' do
|
65
|
-
let(:a) { Time.now }
|
66
|
-
|
67
|
-
it 'returns the correct value' do
|
68
|
-
expect(result[:a]).to eql a
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
context 'with a TimeZone' do
|
73
|
-
let(:a) { TimeWithZone.new(Time.now) }
|
74
|
-
|
75
|
-
it 'returns the correct value' do
|
76
|
-
expect(result[:a]).to eql a
|
77
|
-
end
|
78
|
-
|
79
|
-
it 'handles time zone changes' do
|
80
|
-
outcome
|
81
|
-
allow(Time).to receive(:zone).and_return(nil)
|
82
|
-
expect(described_class.run(inputs)).to be_invalid
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
@@ -1,55 +0,0 @@
|
|
1
|
-
RSpec.describe ActiveInteraction::Validation do
|
2
|
-
describe '.validate(context, filters, inputs)' do
|
3
|
-
let(:inputs) { {} }
|
4
|
-
let(:filter) { ActiveInteraction::Filter.new(:name, {}) }
|
5
|
-
let(:interaction) do
|
6
|
-
name = filter.name
|
7
|
-
klass = Class.new(ActiveInteraction::Base) { attr_writer(name) }
|
8
|
-
klass.filters[name] = filter
|
9
|
-
klass.new
|
10
|
-
end
|
11
|
-
let(:result) do
|
12
|
-
described_class.validate(interaction, interaction.class.filters, inputs)
|
13
|
-
end
|
14
|
-
|
15
|
-
context 'no filters are given' do
|
16
|
-
let(:interaction) { Class.new(ActiveInteraction::Base).new }
|
17
|
-
|
18
|
-
it 'returns no errors' do
|
19
|
-
expect(result).to eql []
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
context 'filter returns no errors' do
|
24
|
-
let(:inputs) { { name: 1 } }
|
25
|
-
|
26
|
-
before do
|
27
|
-
allow(filter).to receive(:process).and_return(ActiveInteraction::Input.new(filter, value: 1))
|
28
|
-
end
|
29
|
-
|
30
|
-
it 'returns no errors' do
|
31
|
-
expect(result).to eql []
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
context 'filter returns with errors' do
|
36
|
-
before do
|
37
|
-
allow(filter).to receive(:process).and_return(ActiveInteraction::Input.new(filter, error: exception))
|
38
|
-
end
|
39
|
-
|
40
|
-
context 'Filter::Error' do
|
41
|
-
let(:filter) { ActiveInteraction::ArrayFilter.new(:name, [1.0, 'a']) { float } }
|
42
|
-
|
43
|
-
let(:exception) { ActiveInteraction::Filter::Error.new(filter, :invalid_type) }
|
44
|
-
|
45
|
-
it 'returns an :invalid_type error' do
|
46
|
-
type = I18n.translate(
|
47
|
-
"#{ActiveInteraction::Base.i18n_scope}.types.#{filter.class.slug}"
|
48
|
-
)
|
49
|
-
|
50
|
-
expect(result).to eql [[filter.name, :invalid_type, { type: type }]]
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
data/spec/spec_helper.rb
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
require 'i18n'
|
2
|
-
I18n.config.enforce_available_locales = true if I18n.config.respond_to?(:enforce_available_locales)
|
3
|
-
|
4
|
-
require 'active_interaction'
|
5
|
-
require 'active_record'
|
6
|
-
|
7
|
-
Dir['./spec/support/**/*.rb'].sort.each { |f| require f }
|
8
|
-
|
9
|
-
RSpec.configure do |config|
|
10
|
-
config.run_all_when_everything_filtered = true
|
11
|
-
config.filter_run_including :focus
|
12
|
-
|
13
|
-
config.disable_monkey_patching!
|
14
|
-
|
15
|
-
config.before(:suite) do
|
16
|
-
if ActiveRecord.respond_to?(:index_nested_attribute_errors)
|
17
|
-
ActiveRecord.index_nested_attribute_errors = false
|
18
|
-
else
|
19
|
-
ActiveRecord::Base.index_nested_attribute_errors = false
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
data/spec/support/concerns.rb
DELETED
data/spec/support/filters.rb
DELETED
@@ -1,227 +0,0 @@
|
|
1
|
-
RSpec.shared_context 'filters' do
|
2
|
-
subject(:filter) { described_class.new(name, options, &block) }
|
3
|
-
|
4
|
-
let(:block) { nil }
|
5
|
-
let(:name) { SecureRandom.hex.to_sym }
|
6
|
-
let(:options) { {} }
|
7
|
-
|
8
|
-
shared_context 'optional' do
|
9
|
-
before do
|
10
|
-
options[:default] = nil
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
shared_context 'required' do
|
15
|
-
before do
|
16
|
-
options.delete(:default)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
RSpec.shared_examples_for 'a filter' do
|
22
|
-
include_context 'filters'
|
23
|
-
|
24
|
-
describe '.factory' do
|
25
|
-
context 'with an invalid slug' do
|
26
|
-
it 'raises an error' do
|
27
|
-
expect do
|
28
|
-
described_class.factory(:invalid)
|
29
|
-
end.to raise_error ActiveInteraction::MissingFilterError
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
context 'with a valid slug' do
|
34
|
-
it 'returns a Filter' do
|
35
|
-
expect(
|
36
|
-
described_class.factory(described_class.slug)
|
37
|
-
).to eql described_class
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
describe '.slug' do
|
43
|
-
it 'returns a symbol' do
|
44
|
-
expect(described_class.slug).to be_a Symbol
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
describe '#process' do
|
49
|
-
let(:value) { nil }
|
50
|
-
|
51
|
-
context 'optional' do
|
52
|
-
include_context 'optional'
|
53
|
-
|
54
|
-
it 'returns the default' do
|
55
|
-
expect(filter.process(value, nil).value).to eql options[:default]
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
context 'required' do
|
60
|
-
include_context 'required'
|
61
|
-
|
62
|
-
it 'indicates an error' do
|
63
|
-
error = filter.process(value, nil).errors.first
|
64
|
-
|
65
|
-
expect(error).to be_an_instance_of ActiveInteraction::Filter::Error
|
66
|
-
expect(error.type).to be :missing
|
67
|
-
end
|
68
|
-
|
69
|
-
context 'with an invalid value' do
|
70
|
-
let(:value) { Object.new }
|
71
|
-
|
72
|
-
it 'indicates an error' do
|
73
|
-
error = filter.process(value, nil).errors.first
|
74
|
-
|
75
|
-
expect(error).to be_an_instance_of ActiveInteraction::Filter::Error
|
76
|
-
expect(error.type).to be :invalid_type
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
context 'with an invalid default' do
|
82
|
-
before do
|
83
|
-
options[:default] = Object.new
|
84
|
-
end
|
85
|
-
|
86
|
-
it 'raises an error' do
|
87
|
-
expect do
|
88
|
-
filter.process(value, nil)
|
89
|
-
end.to raise_error ActiveInteraction::InvalidDefaultError
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
# BasicObject is missing a lot of methods
|
94
|
-
context 'with a BasicObject' do
|
95
|
-
let(:value) { BasicObject.new }
|
96
|
-
|
97
|
-
it 'indicates an error' do
|
98
|
-
error = filter.process(value, nil).errors.first
|
99
|
-
|
100
|
-
expect(error).to be_an_instance_of ActiveInteraction::Filter::Error
|
101
|
-
expect(error.type).to be :invalid_type
|
102
|
-
end
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
describe '#default' do
|
107
|
-
context 'optional' do
|
108
|
-
include_context 'optional'
|
109
|
-
|
110
|
-
it 'returns the default' do
|
111
|
-
expect(filter.default(nil)).to eql options[:default]
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
context 'required' do
|
116
|
-
include_context 'required'
|
117
|
-
|
118
|
-
it 'raises an error' do
|
119
|
-
expect do
|
120
|
-
filter.default(nil)
|
121
|
-
end.to raise_error ActiveInteraction::NoDefaultError
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
|
-
context 'with an invalid default' do
|
126
|
-
before do
|
127
|
-
options[:default] = Object.new
|
128
|
-
end
|
129
|
-
|
130
|
-
it 'raises an error' do
|
131
|
-
expect do
|
132
|
-
filter.default(nil)
|
133
|
-
end.to raise_error ActiveInteraction::InvalidDefaultError
|
134
|
-
end
|
135
|
-
end
|
136
|
-
|
137
|
-
context 'with a callable default' do
|
138
|
-
include_context 'optional'
|
139
|
-
|
140
|
-
before do
|
141
|
-
default = options[:default]
|
142
|
-
options[:default] = -> { default }
|
143
|
-
end
|
144
|
-
|
145
|
-
it 'returns the default' do
|
146
|
-
expect(filter.default(nil)).to eql options[:default].call
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
|
-
context 'with a callable default that takes an argument' do
|
151
|
-
include_context 'optional'
|
152
|
-
|
153
|
-
it 'returns the default' do
|
154
|
-
default = options[:default]
|
155
|
-
|
156
|
-
spec = self
|
157
|
-
filter # Necessary to bring into scope for lambda.
|
158
|
-
options[:default] = lambda do |this|
|
159
|
-
spec.expect(this).to be filter
|
160
|
-
default
|
161
|
-
end
|
162
|
-
|
163
|
-
expect(filter.default(nil)).to be default
|
164
|
-
end
|
165
|
-
end
|
166
|
-
end
|
167
|
-
|
168
|
-
describe '#desc' do
|
169
|
-
it 'returns nil' do
|
170
|
-
expect(filter.desc).to be_nil
|
171
|
-
end
|
172
|
-
|
173
|
-
context 'with a description' do
|
174
|
-
let(:desc) { SecureRandom.hex }
|
175
|
-
|
176
|
-
before do
|
177
|
-
options[:desc] = desc
|
178
|
-
end
|
179
|
-
|
180
|
-
it 'returns the description' do
|
181
|
-
expect(filter.desc).to eql desc
|
182
|
-
end
|
183
|
-
end
|
184
|
-
end
|
185
|
-
|
186
|
-
describe '#filters' do
|
187
|
-
it 'returns Hash' do
|
188
|
-
expect(filter.filters).to be_a Hash
|
189
|
-
end
|
190
|
-
end
|
191
|
-
|
192
|
-
describe '#default?' do
|
193
|
-
context 'optional' do
|
194
|
-
include_context 'optional'
|
195
|
-
|
196
|
-
it 'returns true' do
|
197
|
-
expect(filter).to be_default
|
198
|
-
end
|
199
|
-
end
|
200
|
-
|
201
|
-
context 'required' do
|
202
|
-
include_context 'required'
|
203
|
-
|
204
|
-
it 'returns false' do
|
205
|
-
expect(filter).to_not be_default
|
206
|
-
end
|
207
|
-
end
|
208
|
-
end
|
209
|
-
|
210
|
-
describe '#name' do
|
211
|
-
it 'returns the name' do
|
212
|
-
expect(filter.name).to eql name
|
213
|
-
end
|
214
|
-
end
|
215
|
-
|
216
|
-
describe '#options' do
|
217
|
-
it 'returns the options' do
|
218
|
-
expect(filter.options).to eql options
|
219
|
-
end
|
220
|
-
end
|
221
|
-
|
222
|
-
describe '#database_column_type' do
|
223
|
-
it 'returns a symbol' do
|
224
|
-
expect(filter.database_column_type).to be_a Symbol
|
225
|
-
end
|
226
|
-
end
|
227
|
-
end
|
@@ -1,124 +0,0 @@
|
|
1
|
-
TestInteraction = Class.new(ActiveInteraction::Base) do
|
2
|
-
def self.name
|
3
|
-
SecureRandom.hex
|
4
|
-
end
|
5
|
-
|
6
|
-
def execute
|
7
|
-
inputs
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
|
-
RSpec.shared_context 'interactions' do
|
12
|
-
let(:inputs) { {} }
|
13
|
-
let(:outcome) { described_class.run(inputs) }
|
14
|
-
let(:result) { outcome.result }
|
15
|
-
end
|
16
|
-
|
17
|
-
RSpec.shared_examples_for 'an interaction' do |type, generator, adjust_output = nil, **filter_options|
|
18
|
-
include_context 'interactions'
|
19
|
-
|
20
|
-
let(:described_class) do
|
21
|
-
Class.new(TestInteraction) do
|
22
|
-
public_send(type, :required, filter_options)
|
23
|
-
public_send(type, :optional,
|
24
|
-
filter_options.merge(
|
25
|
-
default: nil
|
26
|
-
)
|
27
|
-
)
|
28
|
-
public_send(type, :default,
|
29
|
-
filter_options.merge(
|
30
|
-
default: generator.call
|
31
|
-
)
|
32
|
-
)
|
33
|
-
public_send(type, :defaults1, :defaults2,
|
34
|
-
filter_options.merge(
|
35
|
-
default: generator.call
|
36
|
-
)
|
37
|
-
)
|
38
|
-
public_send(type, :defaults3,
|
39
|
-
filter_options.merge(
|
40
|
-
default: -> { required }
|
41
|
-
)
|
42
|
-
)
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
context 'with an invalid lazy default' do
|
47
|
-
let(:described_class) do
|
48
|
-
Class.new(TestInteraction) do
|
49
|
-
public_send(type, :default,
|
50
|
-
filter_options.merge(default: -> { Object.new })
|
51
|
-
)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
it 'raises an error' do
|
56
|
-
expect { outcome }.to raise_error ActiveInteraction::InvalidDefaultError
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
context 'without required inputs' do
|
61
|
-
it 'is invalid' do
|
62
|
-
expect(outcome).to be_invalid
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
context 'with inputs[:required]' do
|
67
|
-
let(:required) { generator.call }
|
68
|
-
|
69
|
-
before { inputs[:required] = required }
|
70
|
-
|
71
|
-
it 'is valid' do
|
72
|
-
expect(outcome).to be_valid
|
73
|
-
end
|
74
|
-
|
75
|
-
it 'returns the correct value for :required' do
|
76
|
-
expect(result[:required]).to eql(adjust_output ? adjust_output.call(required) : required)
|
77
|
-
end
|
78
|
-
|
79
|
-
it 'returns nil for :optional' do
|
80
|
-
expect(result[:optional]).to be_nil
|
81
|
-
end
|
82
|
-
|
83
|
-
it 'does not return nil for :default' do
|
84
|
-
expect(result[:default]).to_not be_nil
|
85
|
-
end
|
86
|
-
|
87
|
-
it 'does not return nil for :default when given nil' do
|
88
|
-
inputs[:default] = nil
|
89
|
-
expect(result[:default]).to_not be_nil
|
90
|
-
end
|
91
|
-
|
92
|
-
it 'does not return nil for :defaults1' do
|
93
|
-
expect(result[:defaults1]).to_not be_nil
|
94
|
-
end
|
95
|
-
|
96
|
-
it 'does not return nil for :defaults2' do
|
97
|
-
expect(result[:defaults2]).to_not be_nil
|
98
|
-
end
|
99
|
-
|
100
|
-
it 'evaluates :defaults3 in the interaction binding' do
|
101
|
-
expect(result[:defaults3]).to eql result[:required]
|
102
|
-
end
|
103
|
-
|
104
|
-
context 'with inputs[:optional]' do
|
105
|
-
let(:optional) { generator.call }
|
106
|
-
|
107
|
-
before { inputs[:optional] = optional }
|
108
|
-
|
109
|
-
it 'returns the correct value for :optional' do
|
110
|
-
expect(result[:optional]).to eql(adjust_output ? adjust_output.call(optional) : optional)
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
|
-
context 'with inputs[:default]' do
|
115
|
-
let(:default) { generator.call }
|
116
|
-
|
117
|
-
before { inputs[:default] = default }
|
118
|
-
|
119
|
-
it 'returns the correct value for :default' do
|
120
|
-
expect(result[:default]).to eql(adjust_output ? adjust_output.call(default) : default)
|
121
|
-
end
|
122
|
-
end
|
123
|
-
end
|
124
|
-
end
|