active_interaction 5.3.0 → 5.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +13 -0
  3. data/README.md +2 -2
  4. data/lib/active_interaction/errors.rb +1 -1
  5. data/lib/active_interaction/version.rb +1 -1
  6. metadata +26 -112
  7. data/spec/active_interaction/array_input_spec.rb +0 -164
  8. data/spec/active_interaction/base_spec.rb +0 -536
  9. data/spec/active_interaction/concerns/active_modelable_spec.rb +0 -43
  10. data/spec/active_interaction/concerns/active_recordable_spec.rb +0 -47
  11. data/spec/active_interaction/concerns/hashable_spec.rb +0 -44
  12. data/spec/active_interaction/concerns/missable_spec.rb +0 -97
  13. data/spec/active_interaction/concerns/runnable_spec.rb +0 -395
  14. data/spec/active_interaction/errors_spec.rb +0 -223
  15. data/spec/active_interaction/filter/column_spec.rb +0 -85
  16. data/spec/active_interaction/filter_spec.rb +0 -58
  17. data/spec/active_interaction/filters/abstract_date_time_filter_spec.rb +0 -11
  18. data/spec/active_interaction/filters/abstract_numeric_filter_spec.rb +0 -11
  19. data/spec/active_interaction/filters/array_filter_spec.rb +0 -248
  20. data/spec/active_interaction/filters/boolean_filter_spec.rb +0 -85
  21. data/spec/active_interaction/filters/date_filter_spec.rb +0 -176
  22. data/spec/active_interaction/filters/date_time_filter_spec.rb +0 -187
  23. data/spec/active_interaction/filters/decimal_filter_spec.rb +0 -124
  24. data/spec/active_interaction/filters/file_filter_spec.rb +0 -38
  25. data/spec/active_interaction/filters/float_filter_spec.rb +0 -109
  26. data/spec/active_interaction/filters/hash_filter_spec.rb +0 -127
  27. data/spec/active_interaction/filters/integer_filter_spec.rb +0 -102
  28. data/spec/active_interaction/filters/interface_filter_spec.rb +0 -459
  29. data/spec/active_interaction/filters/object_filter_spec.rb +0 -235
  30. data/spec/active_interaction/filters/record_filter_spec.rb +0 -204
  31. data/spec/active_interaction/filters/string_filter_spec.rb +0 -58
  32. data/spec/active_interaction/filters/symbol_filter_spec.rb +0 -44
  33. data/spec/active_interaction/filters/time_filter_spec.rb +0 -249
  34. data/spec/active_interaction/grouped_input_spec.rb +0 -15
  35. data/spec/active_interaction/hash_input_spec.rb +0 -56
  36. data/spec/active_interaction/i18n_spec.rb +0 -111
  37. data/spec/active_interaction/inputs_spec.rb +0 -264
  38. data/spec/active_interaction/integration/array_interaction_spec.rb +0 -87
  39. data/spec/active_interaction/integration/boolean_interaction_spec.rb +0 -11
  40. data/spec/active_interaction/integration/date_interaction_spec.rb +0 -3
  41. data/spec/active_interaction/integration/date_time_interaction_spec.rb +0 -3
  42. data/spec/active_interaction/integration/file_interaction_spec.rb +0 -17
  43. data/spec/active_interaction/integration/float_interaction_spec.rb +0 -3
  44. data/spec/active_interaction/integration/hash_interaction_spec.rb +0 -106
  45. data/spec/active_interaction/integration/integer_interaction_spec.rb +0 -3
  46. data/spec/active_interaction/integration/interface_interaction_spec.rb +0 -18
  47. data/spec/active_interaction/integration/object_interaction_spec.rb +0 -12
  48. data/spec/active_interaction/integration/record_integration_spec.rb +0 -3
  49. data/spec/active_interaction/integration/string_interaction_spec.rb +0 -3
  50. data/spec/active_interaction/integration/symbol_interaction_spec.rb +0 -3
  51. data/spec/active_interaction/integration/time_interaction_spec.rb +0 -86
  52. data/spec/active_interaction/modules/validation_spec.rb +0 -55
  53. data/spec/spec_helper.rb +0 -22
  54. data/spec/support/concerns.rb +0 -13
  55. data/spec/support/filters.rb +0 -227
  56. 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