active_interaction 4.1.0 → 5.0.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 (77) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +128 -1
  3. data/README.md +63 -28
  4. data/lib/active_interaction/array_input.rb +77 -0
  5. data/lib/active_interaction/base.rb +14 -98
  6. data/lib/active_interaction/concerns/active_recordable.rb +3 -3
  7. data/lib/active_interaction/concerns/missable.rb +2 -2
  8. data/lib/active_interaction/errors.rb +6 -88
  9. data/lib/active_interaction/exceptions.rb +47 -0
  10. data/lib/active_interaction/filter/column.rb +59 -0
  11. data/lib/active_interaction/filter/error.rb +40 -0
  12. data/lib/active_interaction/filter.rb +44 -53
  13. data/lib/active_interaction/filters/abstract_date_time_filter.rb +9 -6
  14. data/lib/active_interaction/filters/abstract_numeric_filter.rb +7 -3
  15. data/lib/active_interaction/filters/array_filter.rb +34 -6
  16. data/lib/active_interaction/filters/boolean_filter.rb +4 -3
  17. data/lib/active_interaction/filters/date_filter.rb +1 -1
  18. data/lib/active_interaction/filters/date_time_filter.rb +1 -1
  19. data/lib/active_interaction/filters/decimal_filter.rb +1 -1
  20. data/lib/active_interaction/filters/float_filter.rb +1 -1
  21. data/lib/active_interaction/filters/hash_filter.rb +23 -15
  22. data/lib/active_interaction/filters/integer_filter.rb +1 -1
  23. data/lib/active_interaction/filters/interface_filter.rb +12 -12
  24. data/lib/active_interaction/filters/object_filter.rb +9 -3
  25. data/lib/active_interaction/filters/record_filter.rb +21 -11
  26. data/lib/active_interaction/filters/string_filter.rb +1 -1
  27. data/lib/active_interaction/filters/symbol_filter.rb +1 -1
  28. data/lib/active_interaction/filters/time_filter.rb +4 -4
  29. data/lib/active_interaction/hash_input.rb +43 -0
  30. data/lib/active_interaction/input.rb +23 -0
  31. data/lib/active_interaction/inputs.rb +157 -46
  32. data/lib/active_interaction/locale/en.yml +0 -1
  33. data/lib/active_interaction/locale/fr.yml +0 -1
  34. data/lib/active_interaction/locale/it.yml +0 -1
  35. data/lib/active_interaction/locale/ja.yml +0 -1
  36. data/lib/active_interaction/locale/pt-BR.yml +0 -1
  37. data/lib/active_interaction/modules/validation.rb +6 -17
  38. data/lib/active_interaction/version.rb +1 -1
  39. data/lib/active_interaction.rb +43 -36
  40. data/spec/active_interaction/array_input_spec.rb +166 -0
  41. data/spec/active_interaction/base_spec.rb +15 -240
  42. data/spec/active_interaction/concerns/active_modelable_spec.rb +3 -3
  43. data/spec/active_interaction/concerns/active_recordable_spec.rb +7 -7
  44. data/spec/active_interaction/concerns/hashable_spec.rb +8 -8
  45. data/spec/active_interaction/concerns/missable_spec.rb +9 -9
  46. data/spec/active_interaction/concerns/runnable_spec.rb +34 -32
  47. data/spec/active_interaction/errors_spec.rb +60 -43
  48. data/spec/active_interaction/{filter_column_spec.rb → filter/column_spec.rb} +3 -10
  49. data/spec/active_interaction/filter_spec.rb +6 -6
  50. data/spec/active_interaction/filters/abstract_date_time_filter_spec.rb +2 -2
  51. data/spec/active_interaction/filters/abstract_numeric_filter_spec.rb +2 -2
  52. data/spec/active_interaction/filters/array_filter_spec.rb +99 -16
  53. data/spec/active_interaction/filters/boolean_filter_spec.rb +12 -11
  54. data/spec/active_interaction/filters/date_filter_spec.rb +32 -27
  55. data/spec/active_interaction/filters/date_time_filter_spec.rb +34 -29
  56. data/spec/active_interaction/filters/decimal_filter_spec.rb +20 -18
  57. data/spec/active_interaction/filters/file_filter_spec.rb +7 -7
  58. data/spec/active_interaction/filters/float_filter_spec.rb +19 -17
  59. data/spec/active_interaction/filters/hash_filter_spec.rb +16 -18
  60. data/spec/active_interaction/filters/integer_filter_spec.rb +24 -22
  61. data/spec/active_interaction/filters/interface_filter_spec.rb +105 -82
  62. data/spec/active_interaction/filters/object_filter_spec.rb +52 -36
  63. data/spec/active_interaction/filters/record_filter_spec.rb +61 -39
  64. data/spec/active_interaction/filters/string_filter_spec.rb +7 -7
  65. data/spec/active_interaction/filters/symbol_filter_spec.rb +6 -6
  66. data/spec/active_interaction/filters/time_filter_spec.rb +57 -34
  67. data/spec/active_interaction/hash_input_spec.rb +58 -0
  68. data/spec/active_interaction/i18n_spec.rb +22 -17
  69. data/spec/active_interaction/inputs_spec.rb +167 -23
  70. data/spec/active_interaction/integration/array_interaction_spec.rb +3 -7
  71. data/spec/active_interaction/modules/validation_spec.rb +8 -31
  72. data/spec/spec_helper.rb +8 -0
  73. data/spec/support/concerns.rb +2 -2
  74. data/spec/support/filters.rb +27 -51
  75. data/spec/support/interactions.rb +4 -4
  76. metadata +40 -91
  77. data/lib/active_interaction/filter_column.rb +0 -57
@@ -18,11 +18,12 @@ describe ActiveInteraction::TimeFilter, :filter do
18
18
 
19
19
  context 'with a time zone' do
20
20
  before do
21
- time_zone = double
22
- allow(Time).to receive(:zone).and_return(time_zone)
23
-
24
21
  time_with_zone = double
22
+
23
+ time_zone = double
25
24
  allow(time_zone).to receive(:at).and_return(time_with_zone)
25
+
26
+ allow(Time).to receive(:zone).and_return(time_zone)
26
27
  end
27
28
 
28
29
  it 'raises an error' do
@@ -34,14 +35,14 @@ describe ActiveInteraction::TimeFilter, :filter do
34
35
  end
35
36
  end
36
37
 
37
- describe '#cast' do
38
- let(:result) { filter.send(:cast, value, nil) }
38
+ describe '#process' do
39
+ let(:result) { filter.process(value, nil) }
39
40
 
40
41
  context 'with a Time' do
41
42
  let(:value) { Time.new }
42
43
 
43
44
  it 'returns the Time' do
44
- expect(result).to eql value
45
+ expect(result.value).to eql value
45
46
  end
46
47
  end
47
48
 
@@ -49,7 +50,24 @@ describe ActiveInteraction::TimeFilter, :filter do
49
50
  let(:value) { '2011-12-13 14:15:16 +1718' }
50
51
 
51
52
  it 'returns a Time' do
52
- expect(result).to eql Time.parse(value)
53
+ expect(result.value).to eql Time.parse(value)
54
+ end
55
+
56
+ context 'with a time zone' do
57
+ before do
58
+ klass = double
59
+ allow(klass).to receive(:parse).with(value).and_return(nil)
60
+
61
+ allow(filter).to receive(:matches?).and_return(false)
62
+ allow(filter).to receive(:klass).and_return(klass)
63
+ end
64
+
65
+ it 'indicates an error the string is not parsable' do
66
+ error = result.errors.first
67
+
68
+ expect(error).to be_an_instance_of ActiveInteraction::Filter::Error
69
+ expect(error.type).to be :invalid_type
70
+ end
53
71
  end
54
72
 
55
73
  context 'with format' do
@@ -58,7 +76,7 @@ describe ActiveInteraction::TimeFilter, :filter do
58
76
  let(:value) { '13/12/2011 14:15:16 +1718' }
59
77
 
60
78
  it 'returns a Time' do
61
- expect(result).to eql Time.strptime(value, format)
79
+ expect(result.value).to eql Time.strptime(value, format)
62
80
  end
63
81
  end
64
82
  end
@@ -66,19 +84,21 @@ describe ActiveInteraction::TimeFilter, :filter do
66
84
  context 'with an invalid String' do
67
85
  let(:value) { 'invalid' }
68
86
 
69
- it 'raises an error' do
70
- expect do
71
- result
72
- end.to raise_error ActiveInteraction::InvalidValueError
87
+ it 'indicates an error' do
88
+ error = result.errors.first
89
+
90
+ expect(error).to be_an_instance_of ActiveInteraction::Filter::Error
91
+ expect(error.type).to be :invalid_type
73
92
  end
74
93
 
75
94
  context 'with format' do
76
95
  include_context 'with format'
77
96
 
78
- it do
79
- expect do
80
- result
81
- end.to raise_error ActiveInteraction::InvalidValueError
97
+ it 'indicates an error' do
98
+ error = result.errors.first
99
+
100
+ expect(error).to be_an_instance_of ActiveInteraction::Filter::Error
101
+ expect(error.type).to be :invalid_type
82
102
  end
83
103
  end
84
104
  end
@@ -93,7 +113,7 @@ describe ActiveInteraction::TimeFilter, :filter do
93
113
  end
94
114
 
95
115
  it 'returns a Time' do
96
- expect(result).to eql Time.parse(value)
116
+ expect(result.value).to eql Time.parse(value)
97
117
  end
98
118
  end
99
119
 
@@ -110,17 +130,18 @@ describe ActiveInteraction::TimeFilter, :filter do
110
130
  include_context 'optional'
111
131
 
112
132
  it 'returns the default' do
113
- expect(result).to eql options[:default]
133
+ expect(result.value).to eql options[:default]
114
134
  end
115
135
  end
116
136
 
117
137
  context 'required' do
118
138
  include_context 'required'
119
139
 
120
- it 'raises an error' do
121
- expect do
122
- result
123
- end.to raise_error ActiveInteraction::MissingValueError
140
+ it 'indicates an error' do
141
+ error = result.errors.first
142
+
143
+ expect(error).to be_an_instance_of ActiveInteraction::Filter::Error
144
+ expect(error.type).to be :missing
124
145
  end
125
146
  end
126
147
  end
@@ -129,7 +150,7 @@ describe ActiveInteraction::TimeFilter, :filter do
129
150
  let(:value) { rand(1 << 16) }
130
151
 
131
152
  it 'returns the Time' do
132
- expect(result).to eql Time.at(value)
153
+ expect(result.value).to eql Time.at(value)
133
154
  end
134
155
  end
135
156
 
@@ -143,7 +164,7 @@ describe ActiveInteraction::TimeFilter, :filter do
143
164
  end
144
165
 
145
166
  it 'returns the Time' do
146
- expect(result).to eql Time.at(value)
167
+ expect(result.value).to eql Time.at(value)
147
168
  end
148
169
  end
149
170
 
@@ -167,7 +188,7 @@ describe ActiveInteraction::TimeFilter, :filter do
167
188
 
168
189
  it 'returns a Time' do
169
190
  expect(
170
- result
191
+ result.value
171
192
  ).to eql Time.new(year, month, day, hour, min, sec)
172
193
  end
173
194
  end
@@ -176,10 +197,11 @@ describe ActiveInteraction::TimeFilter, :filter do
176
197
  context 'empty' do
177
198
  let(:value) { ActiveInteraction::GroupedInput.new }
178
199
 
179
- it 'raises an error' do
180
- expect do
181
- result
182
- end.to raise_error ActiveInteraction::InvalidValueError
200
+ it 'indicates an error' do
201
+ error = result.errors.first
202
+
203
+ expect(error).to be_an_instance_of ActiveInteraction::Filter::Error
204
+ expect(error.type).to be :invalid_type
183
205
  end
184
206
  end
185
207
 
@@ -190,10 +212,11 @@ describe ActiveInteraction::TimeFilter, :filter do
190
212
  )
191
213
  end
192
214
 
193
- it 'raises an error' do
194
- expect do
195
- result
196
- end.to raise_error ActiveInteraction::InvalidValueError
215
+ it 'indicates an error' do
216
+ error = result.errors.first
217
+
218
+ expect(error).to be_an_instance_of ActiveInteraction::Filter::Error
219
+ expect(error.type).to be :invalid_type
197
220
  end
198
221
  end
199
222
  end
@@ -201,7 +224,7 @@ describe ActiveInteraction::TimeFilter, :filter do
201
224
 
202
225
  describe '#database_column_type' do
203
226
  it 'returns :datetime' do
204
- expect(filter.database_column_type).to eql :datetime
227
+ expect(filter.database_column_type).to be :datetime
205
228
  end
206
229
  end
207
230
 
@@ -0,0 +1,58 @@
1
+ require 'spec_helper'
2
+
3
+ describe ActiveInteraction::HashInput do
4
+ subject(:input) do
5
+ described_class.new(filter,
6
+ value: value,
7
+ error: error,
8
+ children: children
9
+ )
10
+ end
11
+
12
+ let(:filter) do
13
+ ActiveInteraction::HashFilter.new(:h, &block)
14
+ end
15
+ let(:block) { proc { integer :i } }
16
+ let(:value) { nil }
17
+ let(:error) { nil }
18
+ let(:children) { {} }
19
+
20
+ describe '#errors' do
21
+ context 'with no errors' do
22
+ it 'returns an empty array' do
23
+ expect(input.errors).to be_empty
24
+ end
25
+ end
26
+
27
+ context 'with an error on the hash' do
28
+ let(:error) { ActiveInteraction::Filter::Error.new(filter, :invalid_type) }
29
+
30
+ it 'returns one error in the array' do
31
+ expect(input.errors.size).to be 1
32
+
33
+ error = input.errors.first
34
+ expect(error.name).to be filter.name
35
+ expect(error.type).to be :invalid_type
36
+ end
37
+ end
38
+
39
+ context 'with children with errors' do
40
+ let(:child_i) do
41
+ filter = ActiveInteraction::IntegerFilter.new(:i)
42
+ ActiveInteraction::Input.new(filter,
43
+ value: nil,
44
+ error: ActiveInteraction::Filter::Error.new(filter, :missing)
45
+ )
46
+ end
47
+ let(:children) { { i: child_i } }
48
+
49
+ it 'returns the error' do
50
+ expect(input.errors.size).to be 1
51
+
52
+ error = input.errors.first
53
+ expect(error.name).to be :"#{filter.name}.i"
54
+ expect(error.type).to be :missing
55
+ end
56
+ end
57
+ end
58
+ end
@@ -15,20 +15,23 @@ I18nInteraction = Class.new(TestInteraction) do
15
15
  end
16
16
  end
17
17
 
18
+ TYPES = ActiveInteraction::Filter
19
+ .const_get(:CLASSES)
20
+ .keys
21
+ .map(&:to_s)
22
+
18
23
  describe I18nInteraction do
19
24
  include_context 'interactions'
20
25
 
21
- TYPES = ActiveInteraction::Filter # rubocop:disable Lint/ConstantDefinitionInBlock
22
- .const_get(:CLASSES)
23
- .map { |slug, _| slug.to_s }
24
-
25
26
  shared_examples 'translation' do |locale|
26
- before do
27
- @locale = I18n.locale
27
+ around do |example|
28
+ old_locale = I18n.locale
28
29
  I18n.locale = locale
29
- end
30
30
 
31
- after { I18n.locale = @locale }
31
+ example.run
32
+
33
+ I18n.locale = old_locale
34
+ end
32
35
 
33
36
  context 'types' do
34
37
  TYPES.each do |type|
@@ -81,16 +84,12 @@ describe I18nInteraction do
81
84
  end
82
85
 
83
86
  context 'hsilgne' do
84
- before do
85
- # This must appear before including the translation examples so that the
86
- # locale is available before it is assigned.
87
- locale = :hsilgne
88
- I18n.config.available_locales = I18n.config.available_locales + [locale] unless I18n.locale_available?(locale)
89
- end
87
+ # This must appear before including the translation examples so that the
88
+ # locale is available before it is assigned.
89
+ around do |example|
90
+ old_locals = I18n.config.available_locales
91
+ I18n.config.available_locales += [:hsilgne]
90
92
 
91
- include_examples 'translation', :hsilgne
92
-
93
- before do
94
93
  I18n.backend.store_translations('hsilgne',
95
94
  active_interaction: {
96
95
  errors: {
@@ -103,6 +102,12 @@ describe I18nInteraction do
103
102
  types: TYPES.each_with_object({}) { |e, a| a[e] = e.reverse }
104
103
  }
105
104
  )
105
+
106
+ example.run
107
+
108
+ I18n.config.available_locales = old_locals
106
109
  end
110
+
111
+ include_examples 'translation', :hsilgne
107
112
  end
108
113
  end
@@ -1,11 +1,14 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe ActiveInteraction::Inputs do
4
- subject(:inputs) { described_class.new }
4
+ subject(:inputs) { described_class.new(args, base_class.new) }
5
+
6
+ let(:args) { {} }
7
+ let(:base_class) { ActiveInteraction::Base }
5
8
 
6
9
  describe '.reserved?(name)' do
7
10
  it 'returns true for anything starting with "_interaction_"' do
8
- expect(described_class.reserved?('_interaction_')).to be_truthy
11
+ expect(described_class).to be_reserved('_interaction_')
9
12
  end
10
13
 
11
14
  it 'returns true for existing instance methods' do
@@ -13,21 +16,20 @@ describe ActiveInteraction::Inputs do
13
16
  (ActiveInteraction::Base.instance_methods - Object.instance_methods) +
14
17
  (ActiveInteraction::Base.private_instance_methods - Object.private_instance_methods)
15
18
  ).each do |method|
16
- expect(described_class.reserved?(method)).to be_truthy
19
+ expect(described_class).to be_reserved(method)
17
20
  end
18
21
  end
19
22
 
20
23
  it 'returns false for anything else' do
21
- expect(described_class.reserved?(SecureRandom.hex)).to be_falsey
24
+ expect(described_class).to_not be_reserved(SecureRandom.hex)
22
25
  end
23
26
  end
24
27
 
25
- describe '.process(inputs)' do
26
- let(:inputs) { {} }
27
- let(:result) { described_class.process(inputs) }
28
+ describe '#normalized' do
29
+ let(:result) { inputs.normalized }
28
30
 
29
31
  context 'with invalid inputs' do
30
- let(:inputs) { nil }
32
+ let(:args) { nil }
31
33
 
32
34
  it 'raises an error' do
33
35
  expect { result }.to raise_error ArgumentError
@@ -35,7 +37,7 @@ describe ActiveInteraction::Inputs do
35
37
  end
36
38
 
37
39
  context 'with non-hash inputs' do
38
- let(:inputs) { [%i[k v]] }
40
+ let(:args) { [%i[k v]] }
39
41
 
40
42
  it 'raises an error' do
41
43
  expect { result }.to raise_error ArgumentError
@@ -43,15 +45,7 @@ describe ActiveInteraction::Inputs do
43
45
  end
44
46
 
45
47
  context 'with ActionController::Parameters inputs' do
46
- let(:inputs) { ActionController::Parameters.new }
47
-
48
- it 'does not raise an error' do
49
- expect { result }.to_not raise_error
50
- end
51
- end
52
-
53
- context 'with Inputs inputs' do
54
- let(:inputs) { ActiveInteraction::Inputs.new }
48
+ let(:args) { ::ActionController::Parameters.new }
55
49
 
56
50
  it 'does not raise an error' do
57
51
  expect { result }.to_not raise_error
@@ -59,17 +53,17 @@ describe ActiveInteraction::Inputs do
59
53
  end
60
54
 
61
55
  context 'with simple inputs' do
62
- before { inputs[:key] = :value }
56
+ before { args[:key] = :value }
63
57
 
64
58
  it 'sends them straight through' do
65
- expect(result).to eql inputs
59
+ expect(result).to eql args
66
60
  end
67
61
  end
68
62
 
69
63
  context 'with groupable inputs' do
70
64
  context 'without a matching simple input' do
71
65
  before do
72
- inputs.merge!(
66
+ args.merge!(
73
67
  'key(1i)' => :value1,
74
68
  'key(2i)' => :value2
75
69
  )
@@ -87,7 +81,7 @@ describe ActiveInteraction::Inputs do
87
81
 
88
82
  context 'with a matching simple input' do
89
83
  before do
90
- inputs.merge!(
84
+ args.merge!(
91
85
  'key(1i)' => :value1,
92
86
  key: :value2
93
87
  )
@@ -104,11 +98,161 @@ describe ActiveInteraction::Inputs do
104
98
  end
105
99
 
106
100
  context 'with a reserved name' do
107
- before { inputs[:_interaction_key] = :value }
101
+ before { args[:_interaction_key] = :value }
108
102
 
109
103
  it 'skips the input' do
110
104
  expect(result).to_not have_key(:_interaction_key)
111
105
  end
112
106
  end
113
107
  end
108
+
109
+ describe '#given?' do
110
+ let(:base_class) do
111
+ Class.new(ActiveInteraction::Base) do
112
+ float :x,
113
+ default: nil
114
+
115
+ def execute; end
116
+ end
117
+ end
118
+
119
+ it 'is false when the input is not given' do
120
+ expect(inputs.given?(:x)).to be false
121
+ end
122
+
123
+ it 'is true when the input is nil' do
124
+ args[:x] = nil
125
+ expect(inputs.given?(:x)).to be true
126
+ end
127
+
128
+ it 'is true when the input is given' do
129
+ args[:x] = rand
130
+ expect(inputs.given?(:x)).to be true
131
+ end
132
+
133
+ it 'symbolizes its argument' do
134
+ args[:x] = rand
135
+ expect(inputs.given?('x')).to be true
136
+ end
137
+
138
+ it 'only tracks inputs with filters' do
139
+ args[:y] = rand
140
+ expect(inputs.given?(:y)).to be false
141
+ end
142
+
143
+ context 'nested hash values' do
144
+ let(:base_class) do
145
+ Class.new(ActiveInteraction::Base) do
146
+ hash :x, default: {} do
147
+ boolean :y,
148
+ default: true
149
+ end
150
+
151
+ def execute; end
152
+ end
153
+ end
154
+
155
+ it 'is true when the nested inputs symbols are given' do
156
+ described_class.class_exec do
157
+ def execute
158
+ given?(:x, :y)
159
+ end
160
+ end
161
+
162
+ args[:x] = { y: false }
163
+ expect(inputs.given?(:x, :y)).to be true
164
+ end
165
+
166
+ it 'is true when the nested inputs strings are given' do
167
+ args['x'] = { 'y' => false }
168
+ expect(inputs.given?(:x, :y)).to be true
169
+ end
170
+
171
+ it 'is false when the nested input is not given' do
172
+ args[:x] = {}
173
+ expect(inputs.given?(:x, :y)).to be false
174
+ end
175
+
176
+ it 'is false when the first input is not given' do
177
+ expect(inputs.given?(:x, :y)).to be false
178
+ end
179
+
180
+ it 'is false when the first input is nil' do
181
+ args[:x] = nil
182
+ expect(inputs.given?(:x, :y)).to be false
183
+ end
184
+
185
+ it 'returns false if you go too far' do
186
+ args[:x] = { y: true }
187
+ expect(inputs.given?(:x, :y, :z)).to be false
188
+ end
189
+ end
190
+
191
+ context 'nested array values' do
192
+ let(:base_class) do
193
+ Class.new(ActiveInteraction::Base) do
194
+ array :x do
195
+ hash do
196
+ boolean :y, default: true
197
+ end
198
+ end
199
+
200
+ def execute; end
201
+ end
202
+ end
203
+
204
+ context 'has a positive index' do
205
+ it 'returns true if found' do
206
+ args[:x] = [{ y: true }]
207
+ expect(inputs.given?(:x, 0, :y)).to be true
208
+ end
209
+
210
+ it 'returns false if not found' do
211
+ args[:x] = []
212
+ expect(inputs.given?(:x, 0, :y)).to be false
213
+ end
214
+ end
215
+
216
+ context 'has a negative index' do
217
+ it 'returns true if found' do
218
+ args[:x] = [{ y: true }]
219
+ expect(inputs.given?(:x, -1, :y)).to be true
220
+ end
221
+
222
+ it 'returns false if not found' do
223
+ args[:x] = []
224
+ expect(inputs.given?(:x, -1, :y)).to be false
225
+ end
226
+ end
227
+
228
+ it 'returns false if you go too far' do
229
+ args[:x] = [{}]
230
+ expect(inputs.given?(:x, 10, :y)).to be false
231
+ end
232
+ end
233
+
234
+ context 'multi-part date values' do
235
+ let(:base_class) do
236
+ Class.new(ActiveInteraction::Base) do
237
+ date :thing,
238
+ default: nil
239
+
240
+ def execute; end
241
+ end
242
+ end
243
+
244
+ it 'returns true when the input is given' do
245
+ args.merge!(
246
+ 'thing(1i)' => '2020',
247
+ 'thing(2i)' => '12',
248
+ 'thing(3i)' => '31'
249
+ )
250
+ expect(inputs.given?(:thing)).to be true
251
+ end
252
+
253
+ it 'returns false if not found' do
254
+ expect(inputs.given?(:thing)).to be false
255
+ end
256
+ end
257
+ end
114
258
  end
@@ -1,10 +1,6 @@
1
1
  require 'spec_helper'
2
2
  require 'active_record'
3
- if defined?(JRUBY_VERSION)
4
- require 'activerecord-jdbcsqlite3-adapter'
5
- else
6
- require 'sqlite3'
7
- end
3
+ require 'sqlite3'
8
4
 
9
5
  ActiveRecord::Base.establish_connection(
10
6
  adapter: 'sqlite3',
@@ -36,8 +32,8 @@ end
36
32
  describe ArrayInteraction do
37
33
  include_context 'interactions'
38
34
  it_behaves_like 'an interaction', :array, -> { [] }
39
- it_behaves_like 'an interaction', :array, -> { Element.where('1 = 1') }
40
- it_behaves_like 'an interaction', :array, -> { List.create!.elements }
35
+ it_behaves_like 'an interaction', :array, -> { Element.where('1 = 1') }, ->(result) { result.to_a }
36
+ it_behaves_like 'an interaction', :array, -> { List.create!.elements }, ->(result) { result.to_a }
41
37
 
42
38
  context 'with inputs[:a]' do
43
39
  let(:a) { [[]] }
@@ -22,11 +22,11 @@ describe ActiveInteraction::Validation do
22
22
  end
23
23
  end
24
24
 
25
- context 'filter.cast returns a value' do
25
+ context 'filter returns no errors' do
26
26
  let(:inputs) { { name: 1 } }
27
27
 
28
28
  before do
29
- allow(filter).to receive(:cast).and_return(1)
29
+ allow(filter).to receive(:process).and_return(ActiveInteraction::Input.new(filter, value: 1))
30
30
  end
31
31
 
32
32
  it 'returns no errors' do
@@ -34,14 +34,15 @@ describe ActiveInteraction::Validation do
34
34
  end
35
35
  end
36
36
 
37
- context 'filter throws' do
37
+ context 'filter returns with errors' do
38
38
  before do
39
- allow(filter).to receive(:cast).and_raise(exception)
39
+ allow(filter).to receive(:process).and_return(ActiveInteraction::Input.new(filter, error: exception))
40
40
  end
41
41
 
42
- context 'InvalidValueError' do
43
- let(:exception) { ActiveInteraction::InvalidValueError }
44
- let(:filter) { ActiveInteraction::FloatFilter.new(:name, {}) }
42
+ context 'Filter::Error' do
43
+ let(:filter) { ActiveInteraction::ArrayFilter.new(:name, [1.0, 'a']) { float } }
44
+
45
+ let(:exception) { ActiveInteraction::Filter::Error.new(filter, :invalid_type) }
45
46
 
46
47
  it 'returns an :invalid_type error' do
47
48
  type = I18n.translate(
@@ -51,30 +52,6 @@ describe ActiveInteraction::Validation do
51
52
  expect(result).to eql [[filter.name, :invalid_type, { type: type }]]
52
53
  end
53
54
  end
54
-
55
- context 'MissingValueError' do
56
- let(:exception) { ActiveInteraction::MissingValueError }
57
-
58
- it 'returns a :missing error' do
59
- expect(result).to eql [[filter.name, :missing]]
60
- end
61
- end
62
-
63
- context 'InvalidNestedValueError' do
64
- let(:exception) do
65
- ActiveInteraction::InvalidNestedValueError.new(name, value)
66
- end
67
- let(:name) { SecureRandom.hex.to_sym }
68
- let(:value) { double }
69
-
70
- it 'returns an :invalid_nested error' do
71
- expect(result).to eql [[
72
- filter.name,
73
- :invalid_nested,
74
- { name: name.inspect, value: value.inspect }
75
- ]]
76
- end
77
- end
78
55
  end
79
56
  end
80
57
  end
data/spec/spec_helper.rb CHANGED
@@ -8,4 +8,12 @@ Dir['./spec/support/**/*.rb'].sort.each { |f| require f }
8
8
  RSpec.configure do |config|
9
9
  config.run_all_when_everything_filtered = true
10
10
  config.filter_run_including :focus
11
+
12
+ config.before(:suite) do
13
+ if ::ActiveRecord.respond_to?(:index_nested_attribute_errors)
14
+ ::ActiveRecord.index_nested_attribute_errors = false
15
+ else
16
+ ::ActiveRecord::Base.index_nested_attribute_errors = false
17
+ end
18
+ end
11
19
  end
@@ -1,4 +1,6 @@
1
1
  shared_context 'concerns' do |concern|
2
+ subject(:instance) { klass.new }
3
+
2
4
  let(:klass) do
3
5
  Class.new do
4
6
  include concern
@@ -8,6 +10,4 @@ shared_context 'concerns' do |concern|
8
10
  end
9
11
  end
10
12
  end
11
-
12
- subject(:instance) { klass.new }
13
13
  end