reform 2.3.3 → 2.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.
- checksums.yaml +4 -4
- data/.gitignore +1 -1
- data/.travis.yml +0 -3
- data/CHANGES.md +9 -0
- data/Gemfile +1 -1
- data/LICENSE.txt +1 -1
- data/README.md +5 -5
- data/Rakefile +1 -12
- data/lib/reform/contract/validate.rb +1 -1
- data/lib/reform/form/dry.rb +47 -9
- data/lib/reform/validation/groups.rb +0 -1
- data/lib/reform/version.rb +1 -1
- data/test/call_test.rb +23 -0
- data/test/changed_test.rb +6 -6
- data/test/coercion_test.rb +17 -17
- data/test/{composition_new_api.rb → composition_test.rb} +27 -28
- data/test/{contract_new_api.rb → contract_test.rb} +8 -8
- data/test/default_test.rb +2 -2
- data/test/deserialize_test.rb +8 -8
- data/test/docs/validation_test.rb +134 -0
- data/test/{errors_new_api.rb → errors_test.rb} +41 -41
- data/test/feature_test.rb +2 -2
- data/test/fixtures/dry_error_messages.yml +64 -54
- data/test/{form_option_new_api.rb → form_option_test.rb} +1 -1
- data/test/{form_new_api.rb → form_test.rb} +3 -3
- data/test/from_test.rb +10 -10
- data/test/{inherit_new_api.rb → inherit_test.rb} +17 -17
- data/test/{module_new_api.rb → module_test.rb} +10 -10
- data/test/parse_option_test.rb +7 -7
- data/test/parse_pipeline_test.rb +1 -1
- data/test/{populate_new_api.rb → populate_test.rb} +112 -53
- data/test/populator_skip_test.rb +2 -2
- data/test/prepopulator_test.rb +15 -15
- data/test/read_only_test.rb +2 -2
- data/test/readable_test.rb +3 -3
- data/test/{reform_new_api.rb → reform_test.rb} +19 -19
- data/test/{save_new_api.rb → save_test.rb} +4 -4
- data/test/setup_test.rb +9 -9
- data/test/{skip_if_new_api.rb → skip_if_test.rb} +12 -12
- data/test/skip_setter_and_getter_test.rb +6 -6
- data/test/test_helper.rb +5 -6
- data/test/{validate_new_api.rb → validate_test.rb} +65 -78
- data/test/validation/{dry_validation_new_api.rb → dry_validation_test.rb} +124 -123
- data/test/validation/result_test.rb +14 -14
- data/test/virtual_test.rb +7 -7
- data/test/writeable_test.rb +8 -8
- metadata +35 -68
- data/Appraisals +0 -8
- data/gemfiles/0.13.0.gemfile +0 -8
- data/gemfiles/1.5.0.gemfile +0 -9
- data/lib/reform/form/dry/new_api.rb +0 -45
- data/lib/reform/form/dry/old_api.rb +0 -61
- data/test/call_new_api.rb +0 -23
- data/test/call_old_api.rb +0 -23
- data/test/composition_old_api.rb +0 -184
- data/test/contract_old_api.rb +0 -77
- data/test/errors_old_api.rb +0 -230
- data/test/fixtures/dry_new_api_error_messages.yml +0 -104
- data/test/form_old_api.rb +0 -57
- data/test/form_option_old_api.rb +0 -24
- data/test/inherit_old_api.rb +0 -105
- data/test/module_old_api.rb +0 -146
- data/test/populate_old_api.rb +0 -304
- data/test/reform_old_api.rb +0 -202
- data/test/save_old_api.rb +0 -101
- data/test/skip_if_old_api.rb +0 -92
- data/test/validate_old_api.rb +0 -410
- data/test/validation/dry_validation_old_api.rb +0 -772
data/test/call_new_api.rb
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
require "test_helper"
|
2
|
-
|
3
|
-
class CallTest < Minitest::Spec
|
4
|
-
Song = Struct.new(:title)
|
5
|
-
|
6
|
-
class SongForm < TestForm
|
7
|
-
property :title
|
8
|
-
|
9
|
-
validation do
|
10
|
-
params { required(:title).filled }
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
let(:form) { SongForm.new(Song.new) }
|
15
|
-
|
16
|
-
it { _(form.(title: "True North").success?).must_equal true }
|
17
|
-
it { _(form.(title: "True North").failure?).must_equal false }
|
18
|
-
it { _(form.(title: "").success?).must_equal false }
|
19
|
-
it { _(form.(title: "").failure?).must_equal true }
|
20
|
-
|
21
|
-
it { _(form.(title: "True North").errors.messages).must_equal({}) }
|
22
|
-
it { _(form.(title: "").errors.messages).must_equal(title: ["must be filled"]) }
|
23
|
-
end
|
data/test/call_old_api.rb
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
require "test_helper"
|
2
|
-
|
3
|
-
class CallTest < Minitest::Spec
|
4
|
-
Song = Struct.new(:title)
|
5
|
-
|
6
|
-
class SongForm < TestForm
|
7
|
-
property :title
|
8
|
-
|
9
|
-
validation do
|
10
|
-
required(:title).filled
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
let(:form) { SongForm.new(Song.new) }
|
15
|
-
|
16
|
-
it { _(form.(title: "True North").success?).must_equal true }
|
17
|
-
it { _(form.(title: "True North").failure?).must_equal false }
|
18
|
-
it { _(form.(title: "").success?).must_equal false }
|
19
|
-
it { _(form.(title: "").failure?).must_equal true }
|
20
|
-
|
21
|
-
it { _(form.(title: "True North").errors.messages).must_equal({}) }
|
22
|
-
it { _(form.(title: "").errors.messages).must_equal(title: ["must be filled"]) }
|
23
|
-
end
|
data/test/composition_old_api.rb
DELETED
@@ -1,184 +0,0 @@
|
|
1
|
-
require "test_helper"
|
2
|
-
|
3
|
-
class FormCompositionInheritanceTest < MiniTest::Spec
|
4
|
-
module SizePrice
|
5
|
-
include Reform::Form::Module
|
6
|
-
|
7
|
-
property :price
|
8
|
-
property :size
|
9
|
-
|
10
|
-
module InstanceMethods
|
11
|
-
def price(for_size: size)
|
12
|
-
case for_size.to_sym
|
13
|
-
when :s then super() * 1
|
14
|
-
when :m then super() * 2
|
15
|
-
when :l then super() * 3
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
class OutfitForm < TestForm
|
22
|
-
include Reform::Form::Composition
|
23
|
-
include SizePrice
|
24
|
-
|
25
|
-
property :price, inherit: true, on: :tshirt
|
26
|
-
property :size, inherit: true, on: :measurement
|
27
|
-
end
|
28
|
-
|
29
|
-
let(:measurement) { Measurement.new(:l) }
|
30
|
-
let(:tshirt) { Tshirt.new(2, :m) }
|
31
|
-
let(:form) { OutfitForm.new(tshirt: tshirt, measurement: measurement) }
|
32
|
-
|
33
|
-
Tshirt = Struct.new(:price, :size)
|
34
|
-
Measurement = Struct.new(:size)
|
35
|
-
|
36
|
-
it { _(form.price).must_equal 6 }
|
37
|
-
it { _(form.price(for_size: :s)).must_equal 2 }
|
38
|
-
end
|
39
|
-
|
40
|
-
class FormCompositionTest < MiniTest::Spec
|
41
|
-
Song = Struct.new(:id, :title, :band)
|
42
|
-
Requester = Struct.new(:id, :name, :requester)
|
43
|
-
Band = Struct.new(:title)
|
44
|
-
|
45
|
-
class RequestForm < TestForm
|
46
|
-
include Composition
|
47
|
-
|
48
|
-
property :name, on: :requester
|
49
|
-
property :requester_id, on: :requester, from: :id
|
50
|
-
properties :title, :id, on: :song
|
51
|
-
# property :channel # FIXME: what about the "main model"?
|
52
|
-
property :channel, virtual: true, on: :song
|
53
|
-
property :requester, on: :requester
|
54
|
-
property :captcha, on: :song, virtual: true
|
55
|
-
|
56
|
-
validation do
|
57
|
-
required(:name).filled
|
58
|
-
required(:title).filled
|
59
|
-
end
|
60
|
-
|
61
|
-
property :band, on: :song do
|
62
|
-
property :title
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
let(:form) { RequestForm.new(song: song, requester: requester) }
|
67
|
-
let(:song) { Song.new(1, "Rio", band) }
|
68
|
-
let(:requester) { Requester.new(2, "Duran Duran", "MCP") }
|
69
|
-
let(:band) { Band.new("Duran^2") }
|
70
|
-
|
71
|
-
# delegation form -> composition works
|
72
|
-
it { _(form.id).must_equal 1 }
|
73
|
-
it { _(form.title).must_equal "Rio" }
|
74
|
-
it { _(form.name).must_equal "Duran Duran" }
|
75
|
-
it { _(form.requester_id).must_equal 2 }
|
76
|
-
it { assert_nil form.channel }
|
77
|
-
it { _(form.requester).must_equal "MCP" } # same name as composed model.
|
78
|
-
it { assert_nil form.captcha }
|
79
|
-
|
80
|
-
# #model just returns <Composition>.
|
81
|
-
it { _(form.mapper).must_be_kind_of Disposable::Composition }
|
82
|
-
|
83
|
-
# #model[] -> composed models
|
84
|
-
it { _(form.model[:requester]).must_equal requester }
|
85
|
-
it { _(form.model[:song]).must_equal song }
|
86
|
-
|
87
|
-
it "creates Composition for you" do
|
88
|
-
_(form.validate("title" => "Greyhound", "name" => "Frenzal Rhomb")).must_equal true
|
89
|
-
_(form.validate("title" => "", "name" => "Frenzal Rhomb")).must_equal false
|
90
|
-
end
|
91
|
-
|
92
|
-
describe "#save" do
|
93
|
-
# #save with {}
|
94
|
-
it do
|
95
|
-
hash = {}
|
96
|
-
|
97
|
-
form.save do |map|
|
98
|
-
hash[:name] = form.name
|
99
|
-
hash[:title] = form.title
|
100
|
-
end
|
101
|
-
|
102
|
-
_(hash).must_equal({name: "Duran Duran", title: "Rio"})
|
103
|
-
end
|
104
|
-
|
105
|
-
it "provides nested symbolized hash as second block argument" do
|
106
|
-
form.validate("title" => "Greyhound", "name" => "Frenzal Rhomb", "channel" => "JJJ", "captcha" => "wonderful")
|
107
|
-
|
108
|
-
hash = nil
|
109
|
-
|
110
|
-
form.save do |map|
|
111
|
-
hash = map
|
112
|
-
end
|
113
|
-
|
114
|
-
_(hash).must_equal({
|
115
|
-
song: {"title" => "Greyhound", "id" => 1, "channel" => "JJJ", "captcha" => "wonderful", "band" => {"title" => "Duran^2"}},
|
116
|
-
requester: {"name" => "Frenzal Rhomb", "id" => 2, "requester" => "MCP"}
|
117
|
-
}
|
118
|
-
)
|
119
|
-
end
|
120
|
-
|
121
|
-
it "xxx pushes data to models and calls #save when no block passed" do
|
122
|
-
song.extend(Saveable)
|
123
|
-
requester.extend(Saveable)
|
124
|
-
band.extend(Saveable)
|
125
|
-
|
126
|
-
form.validate("title" => "Greyhound", "name" => "Frenzal Rhomb", "captcha" => "1337")
|
127
|
-
_(form.captcha).must_equal "1337" # TODO: move to separate test.
|
128
|
-
|
129
|
-
form.save
|
130
|
-
|
131
|
-
_(requester.name).must_equal "Frenzal Rhomb"
|
132
|
-
_(requester.saved?).must_equal true
|
133
|
-
_(song.title).must_equal "Greyhound"
|
134
|
-
_(song.saved?).must_equal true
|
135
|
-
_(song.band.title).must_equal "Duran^2"
|
136
|
-
_(song.band.saved?).must_equal true
|
137
|
-
end
|
138
|
-
|
139
|
-
it "returns true when models all save successfully" do
|
140
|
-
song.extend(Saveable)
|
141
|
-
requester.extend(Saveable)
|
142
|
-
band.extend(Saveable)
|
143
|
-
|
144
|
-
_(form.save).must_equal true
|
145
|
-
end
|
146
|
-
|
147
|
-
it "returns false when one or more models don't save successfully" do
|
148
|
-
module Unsaveable
|
149
|
-
def save
|
150
|
-
false
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
|
-
song.extend(Unsaveable)
|
155
|
-
requester.extend(Saveable)
|
156
|
-
band.extend(Saveable)
|
157
|
-
|
158
|
-
_(form.save).must_equal false
|
159
|
-
end
|
160
|
-
end
|
161
|
-
end
|
162
|
-
|
163
|
-
class FormCompositionCollectionTest < MiniTest::Spec
|
164
|
-
Book = Struct.new(:id, :name)
|
165
|
-
Library = Struct.new(:id) do
|
166
|
-
def books
|
167
|
-
[Book.new(1, "My book")]
|
168
|
-
end
|
169
|
-
end
|
170
|
-
|
171
|
-
class LibraryForm < TestForm
|
172
|
-
include Reform::Form::Composition
|
173
|
-
|
174
|
-
collection :books, on: :library do
|
175
|
-
property :id
|
176
|
-
property :name
|
177
|
-
end
|
178
|
-
end
|
179
|
-
|
180
|
-
let(:form) { LibraryForm.new(library: library) }
|
181
|
-
let(:library) { Library.new(2) }
|
182
|
-
|
183
|
-
it { form.save { |hash| _(hash).must_equal({library: {"books" => [{"id" => 1, "name" => "My book"}]}}) } }
|
184
|
-
end
|
data/test/contract_old_api.rb
DELETED
@@ -1,77 +0,0 @@
|
|
1
|
-
require "test_helper"
|
2
|
-
|
3
|
-
class ContractTest < MiniTest::Spec
|
4
|
-
Song = Struct.new(:title, :album, :composer)
|
5
|
-
Album = Struct.new(:name, :duration, :songs, :artist)
|
6
|
-
Artist = Struct.new(:name)
|
7
|
-
|
8
|
-
class ArtistForm < TestForm
|
9
|
-
property :name
|
10
|
-
end
|
11
|
-
|
12
|
-
class AlbumForm < TestContract
|
13
|
-
property :name
|
14
|
-
|
15
|
-
properties :duration
|
16
|
-
properties :year, :style, readable: false
|
17
|
-
|
18
|
-
validation do
|
19
|
-
required(:name).filled
|
20
|
-
end
|
21
|
-
|
22
|
-
collection :songs do
|
23
|
-
property :title
|
24
|
-
validation do
|
25
|
-
required(:title).filled
|
26
|
-
end
|
27
|
-
|
28
|
-
property :composer do
|
29
|
-
property :name
|
30
|
-
validation do
|
31
|
-
required(:name).filled
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
property :artist, form: ArtistForm
|
37
|
-
end
|
38
|
-
|
39
|
-
let(:song) { Song.new("Broken") }
|
40
|
-
let(:song_with_composer) { Song.new("Resist Stance", nil, composer) }
|
41
|
-
let(:composer) { Artist.new("Greg Graffin") }
|
42
|
-
let(:artist) { Artist.new("Bad Religion") }
|
43
|
-
let(:album) { Album.new("The Dissent Of Man", 123, [song, song_with_composer], artist) }
|
44
|
-
|
45
|
-
let(:form) { AlbumForm.new(album) }
|
46
|
-
|
47
|
-
# accept `property form: SongForm`.
|
48
|
-
it do
|
49
|
-
_(form.artist).must_be_instance_of ArtistForm
|
50
|
-
end
|
51
|
-
|
52
|
-
describe ".properties" do
|
53
|
-
it "defines a property when called with one argument" do
|
54
|
-
_(form).must_respond_to :duration
|
55
|
-
end
|
56
|
-
|
57
|
-
it "defines several properties when called with multiple arguments" do
|
58
|
-
_(form).must_respond_to :year
|
59
|
-
_(form).must_respond_to :style
|
60
|
-
end
|
61
|
-
|
62
|
-
it "passes options to each property when options are provided" do
|
63
|
-
readable = AlbumForm.new(album).options_for(:style)[:readable]
|
64
|
-
_(readable).must_equal false
|
65
|
-
end
|
66
|
-
|
67
|
-
it "returns the list of defined properties" do
|
68
|
-
returned_value = AlbumForm.properties(:hello, :world, virtual: true)
|
69
|
-
_(returned_value).must_equal %i[hello world]
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
describe "#options_for" do
|
74
|
-
it { _(AlbumForm.options_for(:name).extend(Declarative::Inspect).inspect).must_equal "#<Disposable::Twin::Definition: @options={:private_name=>:name, :name=>\"name\"}>" }
|
75
|
-
it { _(AlbumForm.new(album).options_for(:name).extend(Declarative::Inspect).inspect).must_equal "#<Disposable::Twin::Definition: @options={:private_name=>:name, :name=>\"name\"}>" }
|
76
|
-
end
|
77
|
-
end
|
data/test/errors_old_api.rb
DELETED
@@ -1,230 +0,0 @@
|
|
1
|
-
require "test_helper"
|
2
|
-
|
3
|
-
class ErrorsTest < MiniTest::Spec
|
4
|
-
class AlbumForm < TestForm
|
5
|
-
property :title
|
6
|
-
validation do
|
7
|
-
required(:title).filled
|
8
|
-
end
|
9
|
-
|
10
|
-
property :artists, default: []
|
11
|
-
property :producer do
|
12
|
-
property :name
|
13
|
-
end
|
14
|
-
|
15
|
-
property :hit do
|
16
|
-
property :title
|
17
|
-
validation do
|
18
|
-
required(:title).filled
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
collection :songs do
|
23
|
-
property :title
|
24
|
-
validation do
|
25
|
-
required(:title).filled
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
property :band do # yepp, people do crazy stuff like that.
|
30
|
-
property :name
|
31
|
-
property :label do
|
32
|
-
property :name
|
33
|
-
validation do
|
34
|
-
required(:name).filled
|
35
|
-
end
|
36
|
-
end
|
37
|
-
# TODO: make band a required object.
|
38
|
-
|
39
|
-
validation do
|
40
|
-
configure do
|
41
|
-
config.messages_file = "test/fixtures/dry_error_messages.yml"
|
42
|
-
|
43
|
-
def good_musical_taste?(value)
|
44
|
-
value != "Nickelback"
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
required(:name).filled(:good_musical_taste?)
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
validation do
|
53
|
-
required(:title).filled
|
54
|
-
required(:artists).each(:str?)
|
55
|
-
required(:producer).schema do
|
56
|
-
required(:name).filled
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
let(:album_title) { "Blackhawks Over Los Angeles" }
|
62
|
-
let(:album) do
|
63
|
-
OpenStruct.new(
|
64
|
-
title: album_title,
|
65
|
-
hit: song,
|
66
|
-
songs: songs, # TODO: document this requirement,
|
67
|
-
band: Struct.new(:name, :label).new("Epitaph", OpenStruct.new),
|
68
|
-
producer: Struct.new(:name).new("Sun Records")
|
69
|
-
)
|
70
|
-
end
|
71
|
-
let(:song) { OpenStruct.new(title: "Downtown") }
|
72
|
-
let(:songs) { [song = OpenStruct.new(title: "Calling"), song] }
|
73
|
-
let(:form) { AlbumForm.new(album) }
|
74
|
-
|
75
|
-
describe "#validate with invalid array property" do
|
76
|
-
it do
|
77
|
-
_(form.validate(
|
78
|
-
title: "Swimming Pool - EP",
|
79
|
-
band: {
|
80
|
-
name: "Marie Madeleine",
|
81
|
-
label: {name: "Ekler'o'shocK"}
|
82
|
-
},
|
83
|
-
artists: [42, "Good Charlotte", 43]
|
84
|
-
)).must_equal false
|
85
|
-
_(form.errors.messages).must_equal(artists: {0 => ["must be a string"], 2 => ["must be a string"]})
|
86
|
-
_(form.errors.size).must_equal(1)
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
describe "#errors without #validate" do
|
91
|
-
it do
|
92
|
-
_(form.errors.size).must_equal 0
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
describe "blank everywhere" do
|
97
|
-
before do
|
98
|
-
form.validate(
|
99
|
-
"hit" => {"title" => ""},
|
100
|
-
"title" => "",
|
101
|
-
"songs" => [{"title" => ""}, {"title" => ""}],
|
102
|
-
"producer" => {"name" => ""}
|
103
|
-
)
|
104
|
-
end
|
105
|
-
|
106
|
-
it do
|
107
|
-
_(form.errors.messages).must_equal(
|
108
|
-
title: ["must be filled"],
|
109
|
-
"hit.title": ["must be filled"],
|
110
|
-
"songs.title": ["must be filled"],
|
111
|
-
"band.label.name": ["must be filled"],
|
112
|
-
"producer.name": ["must be filled"]
|
113
|
-
)
|
114
|
-
end
|
115
|
-
|
116
|
-
# it do
|
117
|
-
# form.errors.must_equal({:title => ["must be filled"]})
|
118
|
-
# TODO: this should only contain local errors?
|
119
|
-
# end
|
120
|
-
|
121
|
-
# nested forms keep their own Errors:
|
122
|
-
it { _(form.producer.errors.messages).must_equal(name: ["must be filled"]) }
|
123
|
-
it { _(form.hit.errors.messages).must_equal(title: ["must be filled"]) }
|
124
|
-
it { _(form.songs[0].errors.messages).must_equal(title: ["must be filled"]) }
|
125
|
-
|
126
|
-
it do
|
127
|
-
_(form.errors.messages).must_equal(
|
128
|
-
title: ["must be filled"],
|
129
|
-
"hit.title": ["must be filled"],
|
130
|
-
"songs.title": ["must be filled"],
|
131
|
-
"band.label.name": ["must be filled"],
|
132
|
-
"producer.name": ["must be filled"]
|
133
|
-
)
|
134
|
-
_(form.errors.size).must_equal(5)
|
135
|
-
end
|
136
|
-
end
|
137
|
-
|
138
|
-
describe "#validate with main form invalid" do
|
139
|
-
it do
|
140
|
-
_(form.validate("title" => "", "band" => {"label" => {name: "Fat Wreck"}}, "producer" => nil)).must_equal false
|
141
|
-
_(form.errors.messages).must_equal(title: ["must be filled"], producer: ["must be a hash"])
|
142
|
-
_(form.errors.size).must_equal(2)
|
143
|
-
end
|
144
|
-
end
|
145
|
-
|
146
|
-
describe "#validate with middle nested form invalid" do
|
147
|
-
before { @result = form.validate("hit" => {"title" => ""}, "band" => {"label" => {name: "Fat Wreck"}}) }
|
148
|
-
|
149
|
-
it { _(@result).must_equal false }
|
150
|
-
it { _(form.errors.messages).must_equal("hit.title": ["must be filled"]) }
|
151
|
-
it { _(form.errors.size).must_equal(1) }
|
152
|
-
end
|
153
|
-
|
154
|
-
describe "#validate with collection form invalid" do
|
155
|
-
before { @result = form.validate("songs" => [{"title" => ""}], "band" => {"label" => {name: "Fat Wreck"}}) }
|
156
|
-
|
157
|
-
it { _(@result).must_equal false }
|
158
|
-
it { _(form.errors.messages).must_equal("songs.title": ["must be filled"]) }
|
159
|
-
it { _(form.errors.size).must_equal(1) }
|
160
|
-
end
|
161
|
-
|
162
|
-
describe "#validate with collection and 2-level-nested invalid" do
|
163
|
-
before { @result = form.validate("songs" => [{"title" => ""}], "band" => {"label" => {}}) }
|
164
|
-
|
165
|
-
it { _(@result).must_equal false }
|
166
|
-
it { _(form.errors.messages).must_equal("songs.title": ["must be filled"], "band.label.name": ["must be filled"]) }
|
167
|
-
it { _(form.errors.size).must_equal(2) }
|
168
|
-
end
|
169
|
-
|
170
|
-
describe "#validate with nested form using :base invalid" do
|
171
|
-
it do
|
172
|
-
result = form.validate("songs" => [{"title" => "Someday"}], "band" => {"name" => "Nickelback", "label" => {"name" => "Roadrunner Records"}})
|
173
|
-
_(result).must_equal false
|
174
|
-
_(form.errors.messages).must_equal("band.name": ["you're a bad person"])
|
175
|
-
_(form.errors.size).must_equal(1)
|
176
|
-
end
|
177
|
-
end
|
178
|
-
|
179
|
-
describe "#add" do
|
180
|
-
let(:album_title) { nil }
|
181
|
-
it do
|
182
|
-
form.errors.add(:before, "validate")
|
183
|
-
form.errors.add(:before, "validate 2")
|
184
|
-
form.errors.add(:title, "before validate")
|
185
|
-
result = form.validate("songs" => [{"title" => "Someday"}], "band" => {"name" => "Nickelback", "label" => {"name" => "Roadrunner Records"}})
|
186
|
-
_(result).must_equal false
|
187
|
-
_(form.errors.messages).must_equal(before: ["validate", "validate 2"], title: ["before validate", "must be filled"], "band.name": ["you're a bad person"])
|
188
|
-
# add a new custom error
|
189
|
-
form.errors.add(:policy, "error_text")
|
190
|
-
_(form.errors.messages).must_equal(before: ["validate", "validate 2"], title: ["before validate", "must be filled"], "band.name": ["you're a bad person"], policy: ["error_text"])
|
191
|
-
# does not duplicate errors
|
192
|
-
form.errors.add(:title, "must be filled")
|
193
|
-
_(form.errors.messages).must_equal(before: ["validate", "validate 2"], title: ["before validate", "must be filled"], "band.name": ["you're a bad person"], policy: ["error_text"])
|
194
|
-
# merge existing errors
|
195
|
-
form.errors.add(:policy, "another error")
|
196
|
-
_(form.errors.messages).must_equal(before: ["validate", "validate 2"], title: ["before validate", "must be filled"], "band.name": ["you're a bad person"], policy: ["error_text", "another error"])
|
197
|
-
end
|
198
|
-
end
|
199
|
-
|
200
|
-
describe "correct #validate" do
|
201
|
-
before do
|
202
|
-
@result = form.validate(
|
203
|
-
"hit" => {"title" => "Sacrifice"},
|
204
|
-
"title" => "Second Heat",
|
205
|
-
"songs" => [{"title" => "Heart Of A Lion"}],
|
206
|
-
"band" => {"label" => {name: "Fat Wreck"}}
|
207
|
-
)
|
208
|
-
end
|
209
|
-
|
210
|
-
it { _(@result).must_equal true }
|
211
|
-
it { _(form.hit.title).must_equal "Sacrifice" }
|
212
|
-
it { _(form.title).must_equal "Second Heat" }
|
213
|
-
it { _(form.songs.first.title).must_equal "Heart Of A Lion" }
|
214
|
-
it do
|
215
|
-
skip "WE DON'T NEED COUNT AND EMPTY? ON THE CORE ERRORS OBJECT"
|
216
|
-
_(form.errors.size).must_equal(0)
|
217
|
-
_(form.errors.empty?).must_equal(true)
|
218
|
-
end
|
219
|
-
end
|
220
|
-
|
221
|
-
describe "Errors#to_s" do
|
222
|
-
before { form.validate("songs" => [{"title" => ""}], "band" => {"label" => {}}) }
|
223
|
-
|
224
|
-
# to_s is aliased to messages
|
225
|
-
it {
|
226
|
-
skip "why do we need Errors#to_s ?"
|
227
|
-
_(form.errors.to_s).must_equal "{:\"songs.title\"=>[\"must be filled\"], :\"band.label.name\"=>[\"must be filled\"]}"
|
228
|
-
}
|
229
|
-
end
|
230
|
-
end
|