active_interaction 4.0.5 → 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 +149 -6
  3. data/README.md +67 -32
  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 +36 -10
  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 -24
  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 +45 -95
  77. data/lib/active_interaction/filter_column.rb +0 -57
@@ -14,11 +14,7 @@ class RecordThing
14
14
  end
15
15
 
16
16
  def self.finds_bad_value(_)
17
- ''
18
- end
19
-
20
- def self.passthrough(obj)
21
- obj
17
+ Object.new
22
18
  end
23
19
  end
24
20
 
@@ -27,23 +23,19 @@ BackupRecordThing = RecordThing
27
23
 
28
24
  describe ActiveInteraction::RecordFilter, :filter do
29
25
  include_context 'filters'
30
- it_behaves_like 'a filter'
31
-
32
26
  before do
33
27
  options[:class] = RecordThing
34
28
  end
35
29
 
36
- describe '#cast' do
37
- before do
38
- options[:finder] = :finder
39
- end
30
+ it_behaves_like 'a filter'
40
31
 
32
+ describe '#process' do
41
33
  let(:value) { RecordThing.new }
42
- let(:result) { filter.send(:cast, value, nil) }
34
+ let(:result) { filter.process(value, nil) }
43
35
 
44
36
  context 'with an instance of the class' do
45
37
  it 'returns the instance' do
46
- expect(result).to eql value
38
+ expect(result.value).to eql value
47
39
  end
48
40
 
49
41
  context 'with an instance that is a subclass' do
@@ -51,18 +43,18 @@ describe ActiveInteraction::RecordFilter, :filter do
51
43
  let(:value) { subclass.new }
52
44
 
53
45
  it 'returns the instance' do
54
- expect(result).to eql value
46
+ expect(result.value).to eql value
55
47
  end
56
48
  end
57
49
 
58
50
  it 'handles reconstantizing' do
59
- expect(result).to eql value
51
+ expect(result.value).to eql value
60
52
 
61
53
  Object.send(:remove_const, :RecordThing)
62
54
  RecordThing = BackupRecordThing # rubocop:disable Lint/ConstantDefinitionInBlock
63
55
  value = RecordThing.new
64
56
 
65
- expect(filter.send(:cast, value, nil)).to eql value
57
+ expect(filter.process(value, nil).value).to eql value
66
58
  end
67
59
 
68
60
  it 'handles reconstantizing subclasses' do
@@ -73,11 +65,12 @@ describe ActiveInteraction::RecordFilter, :filter do
73
65
  class SubRecordThing < RecordThing; end # rubocop:disable Lint/ConstantDefinitionInBlock
74
66
  value = SubRecordThing.new
75
67
 
76
- expect(filter.send(:cast, value, nil)).to eql value
68
+ expect(filter.process(value, nil).value).to eql value
77
69
  end
78
70
 
79
71
  context 'without the class available' do
80
72
  before { Object.send(:remove_const, :RecordThing) }
73
+
81
74
  after { RecordThing = BackupRecordThing } # rubocop:disable Lint/ConstantDefinitionInBlock
82
75
 
83
76
  it 'does not raise an error on initialization' do
@@ -92,7 +85,7 @@ describe ActiveInteraction::RecordFilter, :filter do
92
85
  end
93
86
 
94
87
  it 'returns the instance' do
95
- expect(result).to eql value
88
+ expect(result.value).to eql value
96
89
  end
97
90
  end
98
91
 
@@ -102,7 +95,7 @@ describe ActiveInteraction::RecordFilter, :filter do
102
95
  end
103
96
 
104
97
  it 'returns the instance' do
105
- expect(result).to eql value
98
+ expect(result.value).to eql value
106
99
  end
107
100
  end
108
101
 
@@ -112,7 +105,7 @@ describe ActiveInteraction::RecordFilter, :filter do
112
105
  before { options[:class] = RecordThings }
113
106
 
114
107
  it 'returns the instance' do
115
- expect(result).to eql value
108
+ expect(result.value).to eql value
116
109
  end
117
110
  end
118
111
 
@@ -129,48 +122,77 @@ describe ActiveInteraction::RecordFilter, :filter do
129
122
  end
130
123
 
131
124
  context 'with a value that does not match the class' do
132
- let(:value) { '' }
125
+ let(:value) { 1 }
133
126
 
134
- it 'calls the finder' do
135
- expect(result).to eql RecordThing.finder(value)
127
+ it 'calls the default finder' do
128
+ allow(RecordThing).to receive(:find)
129
+ result
130
+ expect(RecordThing).to have_received(:find).with(value)
136
131
  end
137
132
 
138
133
  context 'with a custom finder' do
134
+ before do
135
+ options[:finder] = :finder
136
+ end
137
+
139
138
  it 'calls the custom finder' do
140
- expect(result).to eql RecordThing.finder(value)
139
+ allow(RecordThing).to receive(:finder)
140
+ result
141
+ expect(RecordThing).to have_received(:finder).with(value)
141
142
  end
142
143
  end
143
- end
144
- end
145
144
 
146
- describe '#clean' do
147
- context 'with a value that does not match the class' do
148
145
  context 'that returns a nil' do
149
- let(:value) { '' }
146
+ let(:value) { 1 }
150
147
 
151
148
  before do
152
149
  options[:default] = RecordThing.new
153
150
  options[:finder] = :finds_nil
154
151
  end
155
152
 
156
- it 'raises an error' do
157
- expect do
158
- filter.clean(value, nil)
159
- end.to raise_error ActiveInteraction::InvalidValueError
153
+ it 'indicates an error' do
154
+ error = filter.process(value, nil).errors.first
155
+
156
+ expect(error).to be_an_instance_of ActiveInteraction::Filter::Error
157
+ expect(error.type).to be :invalid_type
160
158
  end
161
159
  end
162
160
 
163
161
  context 'that returns an invalid value' do
164
- let(:value) { '' }
162
+ let(:value) { 1 }
165
163
 
166
164
  before do
167
165
  options[:finder] = :finds_bad_value
168
166
  end
169
167
 
170
- it 'raises an error' do
171
- expect do
172
- filter.clean(value, nil)
173
- end.to raise_error ActiveInteraction::InvalidValueError
168
+ it 'indicates an error' do
169
+ error = filter.process(value, nil).errors.first
170
+
171
+ expect(error).to be_an_instance_of ActiveInteraction::Filter::Error
172
+ expect(error.type).to be :invalid_type
173
+ end
174
+ end
175
+ end
176
+
177
+ context 'with a blank String' do
178
+ let(:value) { ' ' }
179
+
180
+ context 'optional' do
181
+ include_context 'optional'
182
+
183
+ it 'returns the default' do
184
+ expect(filter.process(value, nil).value).to eql options[:default]
185
+ end
186
+ end
187
+
188
+ context 'required' do
189
+ include_context 'required'
190
+
191
+ it 'indicates an error' do
192
+ error = filter.process(value, nil).errors.first
193
+
194
+ expect(error).to be_an_instance_of ActiveInteraction::Filter::Error
195
+ expect(error.type).to be :missing
174
196
  end
175
197
  end
176
198
  end
@@ -178,7 +200,7 @@ describe ActiveInteraction::RecordFilter, :filter do
178
200
 
179
201
  describe '#database_column_type' do
180
202
  it 'returns :string' do
181
- expect(filter.database_column_type).to eql :string
203
+ expect(filter.database_column_type).to be :string
182
204
  end
183
205
  end
184
206
  end
@@ -10,14 +10,14 @@ describe ActiveInteraction::StringFilter, :filter do
10
10
  end
11
11
  end
12
12
 
13
- describe '#cast' do
14
- let(:result) { filter.send(:cast, value, nil) }
13
+ describe '#process' do
14
+ let(:result) { filter.process(value, nil) }
15
15
 
16
16
  context 'with a String' do
17
17
  let(:value) { SecureRandom.hex }
18
18
 
19
19
  it 'returns the String' do
20
- expect(result).to eql value
20
+ expect(result.value).to eql value
21
21
  end
22
22
  end
23
23
 
@@ -31,7 +31,7 @@ describe ActiveInteraction::StringFilter, :filter do
31
31
  end
32
32
 
33
33
  it 'returns the String' do
34
- expect(result).to eql value.to_str
34
+ expect(result.value).to eql value.to_str
35
35
  end
36
36
  end
37
37
 
@@ -39,14 +39,14 @@ describe ActiveInteraction::StringFilter, :filter do
39
39
  let(:value) { " #{SecureRandom.hex} " }
40
40
 
41
41
  it 'returns the stripped string' do
42
- expect(result).to eql value.strip
42
+ expect(result.value).to eql value.strip
43
43
  end
44
44
 
45
45
  context 'without strip' do
46
46
  include_context 'without strip'
47
47
 
48
48
  it 'returns the String' do
49
- expect(result).to eql value
49
+ expect(result.value).to eql value
50
50
  end
51
51
  end
52
52
  end
@@ -54,7 +54,7 @@ describe ActiveInteraction::StringFilter, :filter do
54
54
 
55
55
  describe '#database_column_type' do
56
56
  it 'returns :string' do
57
- expect(filter.database_column_type).to eql :string
57
+ expect(filter.database_column_type).to be :string
58
58
  end
59
59
  end
60
60
  end
@@ -4,14 +4,14 @@ describe ActiveInteraction::SymbolFilter, :filter do
4
4
  include_context 'filters'
5
5
  it_behaves_like 'a filter'
6
6
 
7
- describe '#cast' do
8
- let(:result) { filter.send(:cast, value, nil) }
7
+ describe '#process' do
8
+ let(:result) { filter.process(value, nil) }
9
9
 
10
10
  context 'with a Symbol' do
11
11
  let(:value) { SecureRandom.hex.to_sym }
12
12
 
13
13
  it 'returns the Symbol' do
14
- expect(result).to eql value
14
+ expect(result.value).to eql value
15
15
  end
16
16
  end
17
17
 
@@ -25,7 +25,7 @@ describe ActiveInteraction::SymbolFilter, :filter do
25
25
  end
26
26
 
27
27
  it 'returns a symbol' do
28
- expect(result).to eql value.to_sym
28
+ expect(result.value).to eql value.to_sym
29
29
  end
30
30
  end
31
31
 
@@ -33,14 +33,14 @@ describe ActiveInteraction::SymbolFilter, :filter do
33
33
  let(:value) { SecureRandom.hex }
34
34
 
35
35
  it 'returns a Symbol' do
36
- expect(result).to eql value.to_sym
36
+ expect(result.value).to eql value.to_sym
37
37
  end
38
38
  end
39
39
  end
40
40
 
41
41
  describe '#database_column_type' do
42
42
  it 'returns :string' do
43
- expect(filter.database_column_type).to eql :string
43
+ expect(filter.database_column_type).to be :string
44
44
  end
45
45
  end
46
46
  end
@@ -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