instructure-active_model-better_errors 1.6.3.rails2

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 (45) hide show
  1. data/.document +5 -0
  2. data/.gitmodules +3 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +3 -0
  5. data/Gemfile +18 -0
  6. data/LICENSE.txt +20 -0
  7. data/README.md +183 -0
  8. data/Rakefile +57 -0
  9. data/VERSION +1 -0
  10. data/active_model-better_errors.gemspec +110 -0
  11. data/lib/active_model/better_errors.rb +17 -0
  12. data/lib/active_model/error_collecting/array_reporter.rb +9 -0
  13. data/lib/active_model/error_collecting/core_ext.rb +6 -0
  14. data/lib/active_model/error_collecting/emulation.rb +65 -0
  15. data/lib/active_model/error_collecting/error_collection.rb +86 -0
  16. data/lib/active_model/error_collecting/error_message.rb +88 -0
  17. data/lib/active_model/error_collecting/error_message_set.rb +33 -0
  18. data/lib/active_model/error_collecting/errors.rb +52 -0
  19. data/lib/active_model/error_collecting/hash_reporter.rb +9 -0
  20. data/lib/active_model/error_collecting/human_array_reporter.rb +9 -0
  21. data/lib/active_model/error_collecting/human_hash_reporter.rb +15 -0
  22. data/lib/active_model/error_collecting/human_message_formatter.rb +72 -0
  23. data/lib/active_model/error_collecting/human_message_reporter.rb +32 -0
  24. data/lib/active_model/error_collecting/machine_array_reporter.rb +19 -0
  25. data/lib/active_model/error_collecting/machine_hash_reporter.rb +22 -0
  26. data/lib/active_model/error_collecting/message_reporter.rb +17 -0
  27. data/lib/active_model/error_collecting/reporter.rb +14 -0
  28. data/lib/active_model/error_collecting.rb +49 -0
  29. data/spec/lib/active_model/better_errors_spec.rb +7 -0
  30. data/spec/lib/active_model/error_collecting/emulation_spec.rb +45 -0
  31. data/spec/lib/active_model/error_collecting/error_collection_spec.rb +205 -0
  32. data/spec/lib/active_model/error_collecting/error_message_set_spec.rb +96 -0
  33. data/spec/lib/active_model/error_collecting/error_message_spec.rb +293 -0
  34. data/spec/lib/active_model/error_collecting/errors_spec.rb +95 -0
  35. data/spec/lib/active_model/error_collecting/human_array_reporter_spec.rb +33 -0
  36. data/spec/lib/active_model/error_collecting/human_hash_reporter_spec.rb +32 -0
  37. data/spec/lib/active_model/error_collecting/human_message_formatter_spec.rb +22 -0
  38. data/spec/lib/active_model/error_collecting/human_message_reporter_spec.rb +61 -0
  39. data/spec/lib/active_model/error_collecting/machine_array_reporter_spec.rb +40 -0
  40. data/spec/lib/active_model/error_collecting/machine_hash_reporter_spec.rb +40 -0
  41. data/spec/lib/active_model/error_collecting_spec.rb +22 -0
  42. data/spec/spec_helper.rb +30 -0
  43. data/spec/support/models.rb +7 -0
  44. data/test/integration.rb +10 -0
  45. metadata +308 -0
@@ -0,0 +1,96 @@
1
+ require 'spec_helper'
2
+
3
+ describe ActiveModel::ErrorCollecting::ErrorMessageSet do
4
+ subject(:set) { klass.new base, attribute, errors }
5
+ let(:klass) { ActiveModel::ErrorCollecting::ErrorMessageSet }
6
+ let(:attribute) { :first_name }
7
+ let(:errors) { [] }
8
+ let(:base) { User.new }
9
+
10
+ describe "#initialize" do
11
+ context "with no errors" do
12
+ its(:length) { should == 0 }
13
+ end
14
+
15
+ context "with one error" do
16
+ let(:errors) { [:invalid] }
17
+ its(:length) { should == 1 }
18
+ end
19
+ end
20
+
21
+ describe "#push" do
22
+ before { set.push error, options }
23
+ let(:error) { :invalid }
24
+ let(:options) { nil }
25
+ subject { set.first }
26
+
27
+ describe "without options" do
28
+ it { should be_a ActiveModel::ErrorCollecting::ErrorMessage }
29
+ its(:message) { should == nil }
30
+ its(:type) { should == error }
31
+ end
32
+
33
+ describe "with options" do
34
+ let(:options) { { message: 'Invalid' } }
35
+
36
+ it { should be_a ActiveModel::ErrorCollecting::ErrorMessage }
37
+ its(:message) { should == options[:message] }
38
+ its(:type) { should == error }
39
+ end
40
+ end
41
+
42
+ describe "#<<" do
43
+ before { set << error }
44
+ subject { set.first }
45
+
46
+ describe "when accepting error as a symbol" do
47
+ let(:error) { :invalid }
48
+
49
+ it { should be_a ActiveModel::ErrorCollecting::ErrorMessage }
50
+ its(:message) { should == nil }
51
+ its(:type) { should == error }
52
+ end
53
+
54
+ describe "when accepting error as a tuple" do
55
+ let(:error) { [ :invalid, { message: "OMG!!" } ]}
56
+
57
+ it { should be_a ActiveModel::ErrorCollecting::ErrorMessage }
58
+ its(:message) { should == "OMG!!" }
59
+ its(:type) { should == :invalid }
60
+ end
61
+ end
62
+
63
+ describe "#to_a" do
64
+ let(:errors) { [:invalid, :too_long] }
65
+ subject { set.to_a }
66
+
67
+ it { should be_a Array }
68
+ its(:length) { should == 2 }
69
+ end
70
+
71
+ describe "#empty?" do
72
+ subject { set.empty? }
73
+
74
+ describe "when no error messages" do
75
+ it { should be_true }
76
+ end
77
+
78
+ describe "when contains error messages" do
79
+ let(:errors) { [:invalid, :too_long] }
80
+ it { should be_false }
81
+ end
82
+ end
83
+
84
+ describe "#==" do
85
+ subject { errors == set }
86
+ let(:errors) { [:invalid] }
87
+ let(:expected) { ["is invalid"] }
88
+ specify do
89
+ set.should == expected
90
+ end
91
+
92
+ specify do
93
+ expected.should == set
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,293 @@
1
+ require 'spec_helper'
2
+
3
+ describe ActiveModel::ErrorCollecting::ErrorMessage do
4
+ let(:klass) { ActiveModel::ErrorCollecting::ErrorMessage }
5
+ let(:attribute) { :name }
6
+ let(:base) { User.new }
7
+ subject(:error_message) { klass.build(base, attribute, message, options) }
8
+
9
+ describe ".normalize" do
10
+ subject { klass.normalize message }
11
+ context "when message is a symbol" do
12
+ let(:message) { :invalid }
13
+ it { should == message }
14
+ end
15
+
16
+ context "when message is nil" do
17
+ let(:message) { nil }
18
+ it { should be nil }
19
+ end
20
+
21
+ context "when message is a string" do
22
+ let(:message) { 'bad' }
23
+ it { should == message }
24
+ end
25
+
26
+ context "when message is a proc" do
27
+ let(:message) { proc { 'bad' } }
28
+ it { should == 'bad' }
29
+ end
30
+ end
31
+
32
+ describe ".identify" do
33
+ subject { klass.identify message, override }
34
+ context "when message is a symbol and" do
35
+ let(:message) { :invalid }
36
+
37
+ context "when override is a symbol" do
38
+ let(:override) { :not_good }
39
+ it { should == [:not_good, nil] }
40
+ end
41
+
42
+ context "when override is nil" do
43
+ let(:override) { nil }
44
+ it { should == [:invalid, nil] }
45
+ end
46
+
47
+ context "when override is a string" do
48
+ let(:override) { "invalid" }
49
+ it { should == [:invalid, "invalid"] }
50
+ end
51
+
52
+ context "when override is a proc" do
53
+ let(:override) { proc { "Not good" } }
54
+ it { should == [:invalid, "Not good"] }
55
+ end
56
+ end
57
+
58
+ context "when message is a string and" do
59
+ let(:message) { "Invalid" }
60
+
61
+ context "when override is a symbol" do
62
+ let(:override) { :not_good }
63
+ it { should == [:not_good, "Invalid"] }
64
+ end
65
+
66
+ context "when override is nil" do
67
+ let(:override) { nil }
68
+ it { should == [nil, "Invalid"] }
69
+ end
70
+
71
+ context "when override is a string" do
72
+ let(:override) { "not good" }
73
+ it { should == [nil, "not good"] }
74
+ end
75
+
76
+ context "when override is a proc" do
77
+ let(:override) { proc { "Not Good" } }
78
+ it { should == [nil, "Not Good"] }
79
+ end
80
+ end
81
+
82
+ context "when message is nil and" do
83
+ let(:message) { nil }
84
+
85
+ context "when override is a symbol" do
86
+ let(:override) { :not_good }
87
+ it { should == [:not_good, nil] }
88
+ end
89
+
90
+ context "when override is nil" do
91
+ let(:override) { nil }
92
+ it { should == [nil, nil] }
93
+ end
94
+
95
+ context "when override is a string" do
96
+ let(:override) { "not good" }
97
+ it { should == [nil, "not good"] }
98
+ end
99
+
100
+ context "when override is a proc" do
101
+ let(:override) { proc { "Not Good" } }
102
+ it { should == [nil, "Not Good"] }
103
+ end
104
+ end
105
+
106
+ context "when message is a proc and" do
107
+ let(:message) { proc {"invalid"} }
108
+
109
+ context "when override is a symbol" do
110
+ let(:override) { :not_good }
111
+ it { should == [:not_good, "invalid"] }
112
+ end
113
+
114
+ context "when override is nil" do
115
+ let(:override) { nil }
116
+ it { should == [nil, "invalid"] }
117
+ end
118
+
119
+ context "when override is a string" do
120
+ let(:override) { "not good" }
121
+ it { should == [nil, "not good"] }
122
+ end
123
+
124
+ context "when override is a proc" do
125
+ let(:override) { proc { "Not Good" } }
126
+ it { should == [nil, "Not Good"] }
127
+ end
128
+ end
129
+ end
130
+
131
+
132
+ describe ".build" do
133
+ context "when message is a symbol and" do
134
+ let(:message) { :invalid }
135
+
136
+ context "when options[:message] is a string" do
137
+ let(:options) { { message: "Not Really Valid!" } }
138
+ its(:type) { should == message }
139
+ its(:message) { should == options[:message] }
140
+ end
141
+
142
+ context "when options[:message] is a symbol" do
143
+ let(:options) { { message: :not_really_valid } }
144
+ its(:type) { should == options[:message] }
145
+ its(:message) { should == nil }
146
+ end
147
+
148
+ context "when options[:message] is nil" do
149
+ let(:options) { { message: nil } }
150
+ its(:type) { should == message }
151
+ its(:message) { should == nil }
152
+ end
153
+
154
+ context "when options[:message] is proc" do
155
+ let(:options) { { message: proc { "Not Really Valid!" } } }
156
+ its(:type) { should == message }
157
+ its(:message) { should == options[:message].call }
158
+ end
159
+ end
160
+
161
+ context "when message is a string and" do
162
+ let(:message) { 'Invalid!' }
163
+
164
+ context "when options[:message] is a string" do
165
+ let(:options) { { message: "Not Really Valid!" } }
166
+ its(:type) { should == nil }
167
+ its(:message) { should == options[:message] }
168
+ end
169
+
170
+ context "when options[:message] is a symbol" do
171
+ let(:options) { { message: :not_really_valid } }
172
+ its(:type) { should == options[:message] }
173
+ its(:message) { should == message }
174
+ end
175
+
176
+ context "when options[:message] is nil" do
177
+ let(:options) { { } }
178
+ its(:type) { should == nil }
179
+ its(:message) { should == message }
180
+ end
181
+
182
+ context "when options[:message] is proc" do
183
+ let(:options) { { message: proc { "Not Really Valid!" } } }
184
+ its(:type) { should == nil }
185
+ its(:message) { should == options[:message].call }
186
+ end
187
+ end
188
+
189
+ context "when message is a proc and" do
190
+ let(:message) { proc{ 'Invalid!' } }
191
+
192
+ context "when options[:message] is a string" do
193
+ let(:options) { { message: "Not Really Valid!" } }
194
+ its(:type) { should == nil }
195
+ its(:message) { should == options[:message] }
196
+ end
197
+
198
+ context "when options[:message] is a symbol" do
199
+ let(:options) { { message: :not_really_valid } }
200
+ its(:type) { should == options[:message] }
201
+ its(:message) { should == message.call }
202
+ end
203
+
204
+ context "when options[:message] is nil" do
205
+ let(:options) { { } }
206
+ its(:type) { should == nil }
207
+ its(:message) { should == message.call }
208
+ end
209
+
210
+ context "when options[:message] is proc" do
211
+ let(:options) { { message: proc { "Not Really Valid!" } } }
212
+ its(:type) { should == nil }
213
+ its(:message) { should == options[:message].call }
214
+ end
215
+ end
216
+
217
+
218
+ context "when message is nil and" do
219
+ let(:message) { nil }
220
+
221
+ context "when options[:message] is a string" do
222
+ let(:options) { { message: "Not Really Valid!" } }
223
+ its(:type) { should == nil }
224
+ its(:message) { should == options[:message] }
225
+ end
226
+
227
+ context "when options[:message] is a symbol" do
228
+ let(:options) { { message: :not_really_valid } }
229
+ its(:type) { should == options[:message] }
230
+ its(:message) { should == nil }
231
+ end
232
+
233
+ context "when options[:message] is nil" do
234
+ let(:options) { { } }
235
+ its(:type) { should == nil }
236
+ its(:message) { should == nil }
237
+ end
238
+
239
+ context "when options[:message] is proc" do
240
+ let(:options) { { message: proc { "Not Really Valid!" } } }
241
+ its(:type) { should == nil }
242
+ its(:message) { should == options[:message].call }
243
+ end
244
+ end
245
+
246
+ [
247
+ :if, :unless, :on, :allow_nil, :allow_blank, :strict, :message
248
+ ].each do |field|
249
+ context "when options includes :#{field}" do
250
+ let(:message) { :invalid }
251
+ let(:options) { {} }
252
+ before { options[field] = proc{} }
253
+ its(:options) { should == {} }
254
+ end
255
+ end
256
+ end
257
+
258
+ describe '#initialize' do
259
+ let(:message) { :invalid }
260
+ let(:options) { { message: "Invalid!", count: 12 } }
261
+
262
+ its(:options) { should == { count: 12 } }
263
+ its(:attribute) { should == attribute }
264
+ end
265
+
266
+ describe '#<=>' do
267
+ subject { e1 <=> e2 }
268
+
269
+ context "when attribute is different" do
270
+ let(:e1) { klass.build base, :name, :invalid }
271
+ let(:e2) { klass.build base, :name1, :invalid }
272
+ it {should == nil }
273
+ end
274
+
275
+ context "when type is different" do
276
+ let(:e1) { klass.build base, :name, :invalid }
277
+ let(:e2) { klass.build base, :name, :invalid1 }
278
+ it {should == nil }
279
+ end
280
+
281
+ context "when message is different" do
282
+ let(:e1) { klass.build base, :name, :invalid, :message => "a" }
283
+ let(:e2) { klass.build base, :name, :invalid, :message => "b" }
284
+ it {should == nil }
285
+ end
286
+
287
+ context "when it is the same" do
288
+ let(:e1) { klass.build base, :name, :invalid }
289
+ let(:e2) { klass.build base, :name, :invalid }
290
+ it { should == 0 }
291
+ end
292
+ end
293
+ end
@@ -0,0 +1,95 @@
1
+ require 'spec_helper'
2
+
3
+ describe ActiveModel::ErrorCollecting::Errors do
4
+ subject(:instance) { klass.new base }
5
+ let(:klass) { ActiveModel::ErrorCollecting::Errors }
6
+ let(:base) { User.new }
7
+ let(:reporter_name) { :mock }
8
+ let(:mock_reporter) {
9
+ Class.new do
10
+ def initialize(collection)
11
+ end
12
+ end
13
+ }
14
+
15
+ describe "#initialize" do
16
+ its(:base) { should be base }
17
+ end
18
+
19
+ describe "#error_collection" do
20
+ subject { instance.error_collection }
21
+ it { should be_a ActiveModel::ErrorCollecting::ErrorCollection }
22
+ its(:base) { should be base }
23
+ end
24
+
25
+ describe "#message_reporter" do
26
+ subject { instance.message_reporter }
27
+ let(:mock_reporter) { mock() }
28
+ before {
29
+ instance.
30
+ should_receive(:get_reporter).
31
+ with(:message).
32
+ and_return(mock_reporter)
33
+ }
34
+
35
+ it { should be mock_reporter }
36
+ end
37
+
38
+ describe "#hash_reporter" do
39
+ subject { instance.hash_reporter }
40
+ let(:mock_reporter) { mock() }
41
+ before {
42
+ instance.
43
+ should_receive(:get_reporter).
44
+ with(:hash).
45
+ and_return(mock_reporter)
46
+ }
47
+
48
+ it { should be mock_reporter }
49
+ end
50
+
51
+ describe "#array_reporter" do
52
+ subject { instance.array_reporter }
53
+ let(:mock_reporter) { mock() }
54
+ before {
55
+ instance.
56
+ should_receive(:get_reporter).
57
+ with(:array).
58
+ and_return(mock_reporter)
59
+ }
60
+
61
+ it { should be mock_reporter }
62
+ end
63
+
64
+ describe "#set_reporter" do
65
+ it "should set the reporter class" do
66
+ instance.set_reporter reporter_name, mock_reporter
67
+ reporter_classes = instance.instance_variable_get(:@reporter_classes)
68
+ reporter_classes[reporter_name.to_s].should == mock_reporter
69
+ end
70
+
71
+ it "should delete old reporter instance" do
72
+ reporters = instance.instance_variable_get(:@reporters)
73
+ reporters[reporter_name] = mock()
74
+ instance.set_reporter reporter_name, mock_reporter
75
+ reporters.has_key?(reporter_name.to_s).should be false
76
+ end
77
+ end
78
+
79
+ describe "#get_reporter_class" do
80
+ subject { instance.get_reporter_class(reporter_name) }
81
+ before { instance.set_reporter reporter_name, mock_reporter }
82
+ it { should == mock_reporter }
83
+ end
84
+
85
+ describe "#get_reporter" do
86
+ subject { instance.get_reporter(reporter_name) }
87
+ before { instance.set_reporter reporter_name, mock_reporter }
88
+ it { should be_a mock_reporter }
89
+ end
90
+
91
+ describe "#reporter_classes" do
92
+ subject { instance.reporter_classes }
93
+ it { should == ::ActiveModel::ErrorCollecting.reporters }
94
+ end
95
+ end
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+
3
+ describe ActiveModel::ErrorCollecting::HumanArrayReporter do
4
+ subject(:reporter) { klass.new collection }
5
+ let(:klass) { ActiveModel::ErrorCollecting::HumanArrayReporter }
6
+ let(:collection) { ActiveModel::ErrorCollecting::ErrorCollection.new base}
7
+ let(:base) { User.new }
8
+
9
+ describe "#initialize" do
10
+ its(:collection) { should be collection }
11
+ end
12
+
13
+ describe "#base" do
14
+ its(:base) { should be base }
15
+ end
16
+
17
+ describe "#to_a" do
18
+ subject { reporter.to_a }
19
+ let(:expected) { ['foo', 'bar'] }
20
+ before do
21
+ message_reporter = mock()
22
+ ActiveModel::ErrorCollecting::HumanMessageReporter.
23
+ should_receive(:new).
24
+ and_return(message_reporter)
25
+
26
+ message_reporter.
27
+ should_receive(:full_messages).
28
+ and_return(expected)
29
+ end
30
+
31
+ it { should == expected }
32
+ end
33
+ end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ describe ActiveModel::ErrorCollecting::HumanHashReporter do
4
+ subject(:reporter) { klass.new collection }
5
+ let(:klass) { ActiveModel::ErrorCollecting::HumanHashReporter }
6
+ let(:collection) { ActiveModel::ErrorCollecting::ErrorCollection.new base}
7
+ let(:base) { User.new }
8
+
9
+ describe "#initialize" do
10
+ its(:collection) { should be collection }
11
+ end
12
+
13
+ describe "#base" do
14
+ its(:base) { should be base }
15
+ end
16
+
17
+ describe "#to_hash" do
18
+ subject { reporter.to_hash }
19
+ let(:expected) {{
20
+ first_name: ["is invalid", "can't be empty"],
21
+ last_name: ["is invalid"]
22
+ }}
23
+
24
+ before do
25
+ collection[:first_name] << :invalid
26
+ collection[:first_name] << :empty
27
+ collection[:last_name] << :invalid
28
+ end
29
+
30
+ it { should == expected }
31
+ end
32
+ end
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+
3
+ describe ActiveModel::ErrorCollecting::HumanMessageFormatter do
4
+ subject(:formatter) { klass.new base, error_message }
5
+ let(:klass) { ActiveModel::ErrorCollecting::HumanMessageFormatter }
6
+ let(:base) { User.new }
7
+ let(:error_message) { ActiveModel::ErrorCollecting::ErrorMessage.build base, :first_name, :invalid }
8
+
9
+ describe "#initialize" do
10
+ its(:base) { should be base }
11
+ its(:error_message) { should be error_message }
12
+ its(:attribute) { should be error_message.attribute }
13
+ its(:type) { should be error_message.type }
14
+ its(:message) { should be error_message.message }
15
+ its(:options) { should be error_message.options }
16
+ end
17
+
18
+ describe "#format_message" do
19
+ subject { formatter.format_message }
20
+ it { should == "is invalid" }
21
+ end
22
+ end
@@ -0,0 +1,61 @@
1
+ require 'spec_helper'
2
+
3
+ describe ActiveModel::ErrorCollecting::HumanMessageReporter do
4
+ subject(:reporter) { klass.new collection }
5
+ let(:klass) { ActiveModel::ErrorCollecting::HumanMessageReporter }
6
+ let(:collection) { ActiveModel::ErrorCollecting::ErrorCollection.new base}
7
+ let(:base) { User.new }
8
+
9
+
10
+ describe "#initialize" do
11
+ its(:collection) { should be collection }
12
+ end
13
+
14
+ describe "#base" do
15
+ its(:base) { should be base }
16
+ end
17
+
18
+ describe "#full_message" do
19
+ subject { reporter.full_message attribute, message }
20
+ let(:attribute) { :first_name }
21
+ let(:message) { "is invalid" }
22
+
23
+ it { should == "First name is invalid" }
24
+ end
25
+
26
+ describe "#full_messages" do
27
+ subject { reporter.full_messages }
28
+ let(:expected) {[
29
+ "First name is invalid",
30
+ "First name can't be empty",
31
+ "Last name is invalid"
32
+ ]}
33
+
34
+ before do
35
+ collection[:first_name] << :invalid
36
+ collection[:first_name] << :empty
37
+ collection[:last_name] << :invalid
38
+ end
39
+
40
+ it { should == expected }
41
+ end
42
+
43
+ describe "#generate_message" do
44
+ subject { reporter.generate_message attribute, type, options }
45
+ let(:attribute) { :first_name }
46
+
47
+ context "when passing symbols as message" do
48
+ let(:type) { :too_short }
49
+ let(:options) { {count: 3} }
50
+ let(:expected) { "is too short (minimum is 3 characters)" }
51
+ it { should == expected }
52
+ end
53
+
54
+ context "when passing strings as message" do
55
+ let(:type) { "foo" }
56
+ let(:options) { nil }
57
+ let(:expected) { type }
58
+ it { should == expected }
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,40 @@
1
+ require 'spec_helper'
2
+
3
+ describe ActiveModel::ErrorCollecting::MachineArrayReporter do
4
+ subject(:reporter) { klass.new collection }
5
+ let(:klass) { ActiveModel::ErrorCollecting::MachineArrayReporter }
6
+ let(:collection) { ActiveModel::ErrorCollecting::ErrorCollection.new base}
7
+ let(:base) { User.new }
8
+
9
+ describe "#initialize" do
10
+ its(:collection) { should be collection }
11
+ end
12
+
13
+ describe "#base" do
14
+ its(:base) { should be base }
15
+ end
16
+
17
+ describe "#to_a" do
18
+ subject { reporter.to_a }
19
+
20
+ before do
21
+ collection[:first_name] << :invalid
22
+ collection[:first_name] << [ :too_short, { count: 3 } ]
23
+ collection[:last_name] << :invalid
24
+ end
25
+
26
+ let(:expected) {[{
27
+ attribute: 'first_name',
28
+ type: :invalid
29
+ }, {
30
+ attribute: 'first_name',
31
+ type: :too_short,
32
+ options: { count: 3 }
33
+ },{
34
+ attribute: 'last_name',
35
+ type: :invalid
36
+ }]}
37
+
38
+ it { should == expected }
39
+ end
40
+ end