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.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +26 -0
  3. data/README.md +2 -2
  4. data/lib/active_interaction/errors.rb +1 -1
  5. data/lib/active_interaction/grouped_input.rb +23 -3
  6. data/lib/active_interaction/version.rb +1 -1
  7. metadata +12 -115
  8. data/spec/active_interaction/array_input_spec.rb +0 -164
  9. data/spec/active_interaction/base_spec.rb +0 -536
  10. data/spec/active_interaction/concerns/active_modelable_spec.rb +0 -43
  11. data/spec/active_interaction/concerns/active_recordable_spec.rb +0 -47
  12. data/spec/active_interaction/concerns/hashable_spec.rb +0 -44
  13. data/spec/active_interaction/concerns/missable_spec.rb +0 -97
  14. data/spec/active_interaction/concerns/runnable_spec.rb +0 -395
  15. data/spec/active_interaction/errors_spec.rb +0 -223
  16. data/spec/active_interaction/filter/column_spec.rb +0 -85
  17. data/spec/active_interaction/filter_spec.rb +0 -58
  18. data/spec/active_interaction/filters/abstract_date_time_filter_spec.rb +0 -11
  19. data/spec/active_interaction/filters/abstract_numeric_filter_spec.rb +0 -11
  20. data/spec/active_interaction/filters/array_filter_spec.rb +0 -248
  21. data/spec/active_interaction/filters/boolean_filter_spec.rb +0 -85
  22. data/spec/active_interaction/filters/date_filter_spec.rb +0 -176
  23. data/spec/active_interaction/filters/date_time_filter_spec.rb +0 -187
  24. data/spec/active_interaction/filters/decimal_filter_spec.rb +0 -124
  25. data/spec/active_interaction/filters/file_filter_spec.rb +0 -38
  26. data/spec/active_interaction/filters/float_filter_spec.rb +0 -109
  27. data/spec/active_interaction/filters/hash_filter_spec.rb +0 -127
  28. data/spec/active_interaction/filters/integer_filter_spec.rb +0 -102
  29. data/spec/active_interaction/filters/interface_filter_spec.rb +0 -459
  30. data/spec/active_interaction/filters/object_filter_spec.rb +0 -235
  31. data/spec/active_interaction/filters/record_filter_spec.rb +0 -204
  32. data/spec/active_interaction/filters/string_filter_spec.rb +0 -58
  33. data/spec/active_interaction/filters/symbol_filter_spec.rb +0 -44
  34. data/spec/active_interaction/filters/time_filter_spec.rb +0 -249
  35. data/spec/active_interaction/grouped_input_spec.rb +0 -15
  36. data/spec/active_interaction/hash_input_spec.rb +0 -56
  37. data/spec/active_interaction/i18n_spec.rb +0 -111
  38. data/spec/active_interaction/inputs_spec.rb +0 -264
  39. data/spec/active_interaction/integration/array_interaction_spec.rb +0 -87
  40. data/spec/active_interaction/integration/boolean_interaction_spec.rb +0 -11
  41. data/spec/active_interaction/integration/date_interaction_spec.rb +0 -3
  42. data/spec/active_interaction/integration/date_time_interaction_spec.rb +0 -3
  43. data/spec/active_interaction/integration/file_interaction_spec.rb +0 -17
  44. data/spec/active_interaction/integration/float_interaction_spec.rb +0 -3
  45. data/spec/active_interaction/integration/hash_interaction_spec.rb +0 -106
  46. data/spec/active_interaction/integration/integer_interaction_spec.rb +0 -3
  47. data/spec/active_interaction/integration/interface_interaction_spec.rb +0 -18
  48. data/spec/active_interaction/integration/object_interaction_spec.rb +0 -12
  49. data/spec/active_interaction/integration/record_integration_spec.rb +0 -3
  50. data/spec/active_interaction/integration/string_interaction_spec.rb +0 -3
  51. data/spec/active_interaction/integration/symbol_interaction_spec.rb +0 -3
  52. data/spec/active_interaction/integration/time_interaction_spec.rb +0 -86
  53. data/spec/active_interaction/modules/validation_spec.rb +0 -55
  54. data/spec/spec_helper.rb +0 -22
  55. data/spec/support/concerns.rb +0 -13
  56. data/spec/support/filters.rb +0 -227
  57. 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
@@ -1,13 +0,0 @@
1
- RSpec.shared_context 'concerns' do |concern|
2
- subject(:instance) { klass.new }
3
-
4
- let(:klass) do
5
- Class.new do
6
- include concern
7
-
8
- def self.name
9
- SecureRandom.hex
10
- end
11
- end
12
- end
13
- end
@@ -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