reform 2.2.4 → 2.6.2
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 +5 -5
- data/.github/workflows/ci.yml +17 -0
- data/.gitignore +5 -1
- data/CHANGES.md +80 -4
- data/CONTRIBUTING.md +31 -0
- data/Gemfile +2 -16
- data/ISSUE_TEMPLATE.md +25 -0
- data/LICENSE.txt +1 -1
- data/README.md +10 -12
- data/Rakefile +6 -10
- data/lib/reform/contract/custom_error.rb +41 -0
- data/lib/reform/contract/validate.rb +53 -23
- data/lib/reform/contract.rb +7 -17
- data/lib/reform/errors.rb +61 -0
- data/lib/reform/form/call.rb +1 -1
- data/lib/reform/form/composition.rb +2 -2
- data/lib/reform/form/dry/input_hash.rb +37 -0
- data/lib/reform/form/dry.rb +25 -35
- data/lib/reform/form/populator.rb +20 -26
- data/lib/reform/form/prepopulate.rb +5 -4
- data/lib/reform/form/validate.rb +29 -14
- data/lib/reform/form.rb +36 -10
- data/lib/reform/result.rb +90 -0
- data/lib/reform/validation/groups.rb +12 -28
- data/lib/reform/validation.rb +19 -11
- data/lib/reform/version.rb +1 -1
- data/lib/reform.rb +1 -0
- data/reform.gemspec +13 -13
- data/test/benchmarking.rb +39 -6
- data/test/call_test.rb +9 -9
- data/test/changed_test.rb +14 -14
- data/test/coercion_test.rb +57 -25
- data/test/composition_test.rb +85 -49
- data/test/contract/custom_error_test.rb +55 -0
- data/test/contract_test.rb +20 -20
- data/test/default_test.rb +4 -4
- data/test/deserialize_test.rb +17 -20
- data/test/docs/validation_test.rb +134 -0
- data/test/errors_test.rb +142 -82
- data/test/feature_test.rb +10 -12
- data/test/fixtures/dry_error_messages.yml +83 -23
- data/test/form_option_test.rb +5 -5
- data/test/form_test.rb +8 -8
- data/test/from_test.rb +18 -22
- data/test/inherit_test.rb +54 -68
- data/test/module_test.rb +27 -32
- data/test/parse_option_test.rb +40 -0
- data/test/parse_pipeline_test.rb +4 -4
- data/test/populate_test.rb +217 -100
- data/test/populator_skip_test.rb +11 -11
- data/test/prepopulator_test.rb +24 -25
- data/test/read_only_test.rb +12 -1
- data/test/readable_test.rb +9 -9
- data/test/reform_test.rb +47 -66
- data/test/save_test.rb +35 -23
- data/test/setup_test.rb +17 -17
- data/test/skip_if_test.rb +33 -22
- data/test/skip_setter_and_getter_test.rb +9 -10
- data/test/test_helper.rb +23 -14
- data/test/validate_test.rb +165 -145
- data/test/validation/dry_validation_test.rb +630 -146
- data/test/validation/result_test.rb +77 -0
- data/test/validation_library_provided_test.rb +16 -0
- data/test/virtual_test.rb +47 -7
- data/test/writeable_test.rb +38 -9
- metadata +46 -38
- data/.travis.yml +0 -11
- data/gemfiles/Gemfile.disposable-0.3 +0 -6
- data/lib/reform/contract/errors.rb +0 -43
- data/lib/reform/form/mongoid.rb +0 -37
- data/lib/reform/form/orm.rb +0 -26
- data/lib/reform/mongoid.rb +0 -4
- data/test/deprecation_test.rb +0 -27
- data/test/readonly_test.rb +0 -14
- data/test/validation/dry_test.rb +0 -60
- data/test/validation/errors.yml +0 -4
data/test/readable_test.rb
CHANGED
|
@@ -1,30 +1,30 @@
|
|
|
1
|
-
require
|
|
1
|
+
require "test_helper"
|
|
2
2
|
|
|
3
3
|
class ReadableTest < MiniTest::Spec
|
|
4
4
|
Credentials = Struct.new(:password)
|
|
5
5
|
|
|
6
|
-
class PasswordForm <
|
|
6
|
+
class PasswordForm < TestForm
|
|
7
7
|
property :password, readable: false
|
|
8
8
|
end
|
|
9
9
|
|
|
10
|
-
let
|
|
11
|
-
let
|
|
10
|
+
let(:cred) { Credentials.new }
|
|
11
|
+
let(:form) { PasswordForm.new(cred) }
|
|
12
12
|
|
|
13
13
|
it {
|
|
14
|
-
form.password
|
|
14
|
+
assert_nil form.password # password not read.
|
|
15
15
|
|
|
16
16
|
form.validate("password" => "123")
|
|
17
17
|
|
|
18
|
-
form.password
|
|
18
|
+
assert_equal form.password, "123"
|
|
19
19
|
|
|
20
20
|
form.sync
|
|
21
|
-
cred.password
|
|
21
|
+
assert_equal cred.password, "123" # password written.
|
|
22
22
|
|
|
23
23
|
hash = {}
|
|
24
24
|
form.save do |nested|
|
|
25
25
|
hash = nested
|
|
26
26
|
end
|
|
27
27
|
|
|
28
|
-
hash
|
|
28
|
+
assert_equal hash, "password" => "123"
|
|
29
29
|
}
|
|
30
|
-
end
|
|
30
|
+
end
|
data/test/reform_test.rb
CHANGED
|
@@ -1,47 +1,46 @@
|
|
|
1
|
-
require
|
|
1
|
+
require "test_helper"
|
|
2
2
|
|
|
3
|
-
# TODO: this test should be removed.
|
|
4
3
|
class ReformTest < Minitest::Spec
|
|
5
|
-
let
|
|
4
|
+
let(:comp) { OpenStruct.new(name: "Duran Duran", title: "Rio") }
|
|
6
5
|
|
|
7
|
-
let
|
|
6
|
+
let(:form) { SongForm.new(comp) }
|
|
8
7
|
|
|
9
|
-
class SongForm <
|
|
8
|
+
class SongForm < TestForm
|
|
10
9
|
property :name
|
|
11
10
|
property :title
|
|
12
11
|
|
|
13
12
|
validation do
|
|
14
|
-
|
|
13
|
+
params { required(:name).filled }
|
|
15
14
|
end
|
|
16
15
|
end
|
|
17
16
|
|
|
18
17
|
describe "(new) form with empty models" do
|
|
19
|
-
let
|
|
18
|
+
let(:comp) { OpenStruct.new }
|
|
20
19
|
|
|
21
20
|
it "returns empty fields" do
|
|
22
|
-
form.title
|
|
23
|
-
form.name
|
|
21
|
+
assert_nil form.title
|
|
22
|
+
assert_nil form.name
|
|
24
23
|
end
|
|
25
24
|
|
|
26
25
|
describe "and submitted values" do
|
|
27
26
|
it "returns filled-out fields" do
|
|
28
27
|
form.validate("name" => "Duran Duran")
|
|
29
28
|
|
|
30
|
-
form.title
|
|
31
|
-
form.name
|
|
29
|
+
assert_nil form.title
|
|
30
|
+
assert_equal form.name, "Duran Duran"
|
|
32
31
|
end
|
|
33
32
|
end
|
|
34
33
|
end
|
|
35
34
|
|
|
36
35
|
describe "(edit) form with existing models" do
|
|
37
36
|
it "returns filled-out fields" do
|
|
38
|
-
form.name
|
|
39
|
-
form.title
|
|
37
|
+
assert_equal form.name, "Duran Duran"
|
|
38
|
+
assert_equal form.title, "Rio"
|
|
40
39
|
end
|
|
41
40
|
end
|
|
42
41
|
|
|
43
42
|
describe "#validate" do
|
|
44
|
-
let
|
|
43
|
+
let(:comp) { OpenStruct.new }
|
|
45
44
|
|
|
46
45
|
it "ignores unmapped fields in input" do
|
|
47
46
|
form.validate("name" => "Duran Duran", :genre => "80s")
|
|
@@ -51,71 +50,58 @@ class ReformTest < Minitest::Spec
|
|
|
51
50
|
end
|
|
52
51
|
|
|
53
52
|
it "returns true when valid" do
|
|
54
|
-
form.validate("name" => "Duran Duran")
|
|
53
|
+
assert_equal form.validate("name" => "Duran Duran"), true
|
|
55
54
|
end
|
|
56
55
|
|
|
57
56
|
it "exposes input via property accessors" do
|
|
58
57
|
form.validate("name" => "Duran Duran")
|
|
59
58
|
|
|
60
|
-
form.name
|
|
59
|
+
assert_equal form.name, "Duran Duran"
|
|
61
60
|
end
|
|
62
61
|
|
|
63
62
|
it "doesn't change model properties" do
|
|
64
63
|
form.validate("name" => "Duran Duran")
|
|
65
64
|
|
|
66
|
-
comp.name
|
|
65
|
+
assert_nil comp.name # don't touch model, yet.
|
|
67
66
|
end
|
|
68
67
|
|
|
69
68
|
# TODO: test errors. test valid.
|
|
70
69
|
describe "invalid input" do
|
|
71
|
-
class ValidatingForm <
|
|
70
|
+
class ValidatingForm < TestForm
|
|
72
71
|
property :name
|
|
73
72
|
property :title
|
|
74
73
|
|
|
75
74
|
validation do
|
|
76
|
-
|
|
77
|
-
|
|
75
|
+
params do
|
|
76
|
+
required(:name).filled
|
|
77
|
+
required(:title).filled
|
|
78
|
+
end
|
|
78
79
|
end
|
|
79
80
|
end
|
|
80
|
-
let
|
|
81
|
+
let(:form) { ValidatingForm.new(comp) }
|
|
81
82
|
|
|
82
83
|
it "returns false when invalid" do
|
|
83
|
-
form.validate({})
|
|
84
|
+
assert_equal form.validate({}), false
|
|
84
85
|
end
|
|
85
86
|
|
|
86
87
|
it "populates errors" do
|
|
87
88
|
form.validate({})
|
|
88
|
-
form.errors.messages
|
|
89
|
+
assert_equal form.errors.messages, name: ["must be filled"], title: ["must be filled"]
|
|
89
90
|
end
|
|
90
91
|
end
|
|
91
92
|
end
|
|
92
93
|
|
|
93
|
-
# FIXME: add this test to reform-rails.
|
|
94
|
-
describe "#errors" do
|
|
95
|
-
before { form.validate({})}
|
|
96
|
-
|
|
97
|
-
it { form.errors.must_be_kind_of Reform::Contract::Errors }
|
|
98
|
-
|
|
99
|
-
it { form.errors.messages.must_equal({}) }
|
|
100
|
-
|
|
101
|
-
it do
|
|
102
|
-
form.validate({"name"=>""})
|
|
103
|
-
form.errors.messages.must_equal({:name=>["must be filled"]})
|
|
104
|
-
end
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
|
|
108
94
|
describe "#save" do
|
|
109
|
-
let
|
|
110
|
-
let
|
|
95
|
+
let(:comp) { OpenStruct.new }
|
|
96
|
+
let(:form) { SongForm.new(comp) }
|
|
111
97
|
|
|
112
98
|
before { form.validate("name" => "Diesel Boy") }
|
|
113
99
|
|
|
114
100
|
it "xxpushes data to models" do
|
|
115
101
|
form.save
|
|
116
102
|
|
|
117
|
-
comp.name
|
|
118
|
-
comp.title
|
|
103
|
+
assert_equal comp.name, "Diesel Boy"
|
|
104
|
+
assert_nil comp.title
|
|
119
105
|
end
|
|
120
106
|
|
|
121
107
|
describe "#save with block" do
|
|
@@ -126,42 +112,39 @@ class ReformTest < Minitest::Spec
|
|
|
126
112
|
hash = map
|
|
127
113
|
end
|
|
128
114
|
|
|
129
|
-
hash
|
|
115
|
+
assert_equal hash, "name" => "Diesel Boy", "title" => nil
|
|
130
116
|
end
|
|
131
117
|
end
|
|
132
118
|
end
|
|
133
119
|
|
|
134
|
-
|
|
135
120
|
describe "#model" do
|
|
136
|
-
it { form.model
|
|
121
|
+
it { assert_equal form.model, comp }
|
|
137
122
|
end
|
|
138
123
|
|
|
139
|
-
|
|
140
124
|
describe "inheritance" do
|
|
141
125
|
class HitForm < SongForm
|
|
142
126
|
property :position
|
|
143
127
|
validation do
|
|
144
|
-
|
|
128
|
+
params { required(:position).filled }
|
|
145
129
|
end
|
|
146
130
|
end
|
|
147
131
|
|
|
148
|
-
let
|
|
132
|
+
let(:form) { HitForm.new(OpenStruct.new()) }
|
|
149
133
|
it do
|
|
150
|
-
form.validate(
|
|
151
|
-
form.title
|
|
152
|
-
form.position
|
|
153
|
-
form.errors.messages
|
|
134
|
+
form.validate("title" => "The Body")
|
|
135
|
+
assert_equal form.title, "The Body"
|
|
136
|
+
assert_nil form.position
|
|
137
|
+
assert_equal form.errors.messages, name: ["must be filled"], position: ["must be filled"]
|
|
154
138
|
end
|
|
155
139
|
end
|
|
156
140
|
end
|
|
157
141
|
|
|
158
|
-
|
|
159
142
|
class OverridingAccessorsTest < BaseTest
|
|
160
|
-
class SongForm <
|
|
143
|
+
class SongForm < TestForm
|
|
161
144
|
property :title
|
|
162
145
|
|
|
163
146
|
def title=(v) # used in #validate.
|
|
164
|
-
super v*2
|
|
147
|
+
super v * 2
|
|
165
148
|
end
|
|
166
149
|
|
|
167
150
|
def title # used in #sync.
|
|
@@ -169,23 +152,22 @@ class OverridingAccessorsTest < BaseTest
|
|
|
169
152
|
end
|
|
170
153
|
end
|
|
171
154
|
|
|
172
|
-
let
|
|
155
|
+
let(:song) { Song.new("Pray") }
|
|
173
156
|
subject { SongForm.new(song) }
|
|
174
157
|
|
|
175
158
|
# override reader for presentation.
|
|
176
|
-
it { subject.title
|
|
177
|
-
|
|
159
|
+
it { assert_equal subject.title, "pray" }
|
|
178
160
|
|
|
179
161
|
describe "#save" do
|
|
180
162
|
before { subject.validate("title" => "Hey Little World") }
|
|
181
163
|
|
|
182
164
|
# reader always used
|
|
183
|
-
it { subject.title
|
|
165
|
+
it { assert_equal subject.title, "hey little worldhey little world" }
|
|
184
166
|
|
|
185
167
|
# the reader is not used when saving/syncing.
|
|
186
168
|
it do
|
|
187
169
|
subject.save do |hash|
|
|
188
|
-
hash["title"]
|
|
170
|
+
assert_equal hash["title"], "Hey Little WorldHey Little World"
|
|
189
171
|
end
|
|
190
172
|
end
|
|
191
173
|
|
|
@@ -193,14 +175,13 @@ class OverridingAccessorsTest < BaseTest
|
|
|
193
175
|
it do
|
|
194
176
|
song.extend(Saveable)
|
|
195
177
|
subject.save
|
|
196
|
-
song.title
|
|
178
|
+
assert_equal song.title, "Hey Little WorldHey Little World"
|
|
197
179
|
end
|
|
198
180
|
end
|
|
199
181
|
end
|
|
200
182
|
|
|
201
|
-
|
|
202
183
|
class MethodInFormTest < MiniTest::Spec
|
|
203
|
-
class AlbumForm <
|
|
184
|
+
class AlbumForm < TestForm
|
|
204
185
|
property :title
|
|
205
186
|
|
|
206
187
|
def title
|
|
@@ -217,7 +198,7 @@ class MethodInFormTest < MiniTest::Spec
|
|
|
217
198
|
end
|
|
218
199
|
|
|
219
200
|
# methods can be used instead of created accessors.
|
|
220
|
-
subject { AlbumForm.new(OpenStruct.new(:
|
|
221
|
-
it { subject.title
|
|
222
|
-
it { subject.hit.title
|
|
201
|
+
subject { AlbumForm.new(OpenStruct.new(hit: OpenStruct.new)) }
|
|
202
|
+
it { assert_equal subject.title, "The Suffer And The Witness" }
|
|
203
|
+
it { assert_equal subject.hit.title, "Drones" }
|
|
223
204
|
end
|
data/test/save_test.rb
CHANGED
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
require
|
|
1
|
+
require "test_helper"
|
|
2
2
|
|
|
3
3
|
class SaveTest < BaseTest
|
|
4
4
|
Song = Struct.new(:title, :album, :composer)
|
|
5
5
|
Album = Struct.new(:name, :songs, :artist)
|
|
6
6
|
Artist = Struct.new(:name)
|
|
7
7
|
|
|
8
|
-
class AlbumForm <
|
|
8
|
+
class AlbumForm < TestForm
|
|
9
9
|
property :name
|
|
10
10
|
validation do
|
|
11
|
-
|
|
11
|
+
params { required(:name).filled }
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
collection :songs do
|
|
15
15
|
property :title
|
|
16
16
|
validation do
|
|
17
|
-
|
|
17
|
+
params { required(:title).filled }
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
property :composer do
|
|
21
21
|
property :name
|
|
22
22
|
validation do
|
|
23
|
-
|
|
23
|
+
params { required(:name).filled }
|
|
24
24
|
end
|
|
25
25
|
end
|
|
26
26
|
end
|
|
@@ -36,45 +36,57 @@ class SaveTest < BaseTest
|
|
|
36
36
|
end
|
|
37
37
|
|
|
38
38
|
def saved?
|
|
39
|
-
@saved
|
|
39
|
+
defined?(@saved) && @saved
|
|
40
40
|
end
|
|
41
41
|
end
|
|
42
42
|
|
|
43
|
+
let(:song) { Song.new("Broken").extend(Saveable) }
|
|
44
|
+
# let(:song_with_composer) { Song.new("Resist Stance", nil, composer).extend(Saveable) }
|
|
45
|
+
let(:composer) { Artist.new("Greg Graffin").extend(Saveable) }
|
|
46
|
+
let(:artist) { Artist.new("Bad Religion").extend(Saveable).extend(Saveable) }
|
|
47
|
+
let(:album) { Album.new("The Dissent Of Man", [song], artist).extend(Saveable) }
|
|
43
48
|
|
|
44
|
-
let
|
|
45
|
-
# let (:song_with_composer) { Song.new("Resist Stance", nil, composer).extend(Saveable) }
|
|
46
|
-
let (:composer) { Artist.new("Greg Graffin").extend(Saveable) }
|
|
47
|
-
let (:artist) { Artist.new("Bad Religion").extend(Saveable).extend(Saveable) }
|
|
48
|
-
let (:album) { Album.new("The Dissent Of Man", [song], artist).extend(Saveable) }
|
|
49
|
-
|
|
50
|
-
let (:form) { AlbumForm.new(album) }
|
|
51
|
-
|
|
49
|
+
let(:form) { AlbumForm.new(album) }
|
|
52
50
|
|
|
53
51
|
it do
|
|
54
52
|
form.validate("songs" => [{"title" => "Fixed"}])
|
|
55
53
|
|
|
56
54
|
form.save
|
|
57
55
|
|
|
58
|
-
album.saved
|
|
59
|
-
album.songs[0].title
|
|
60
|
-
album.songs[0].saved
|
|
61
|
-
album.artist.saved
|
|
56
|
+
assert album.saved?
|
|
57
|
+
assert_equal album.songs[0].title, "Fixed"
|
|
58
|
+
assert album.songs[0].saved?
|
|
59
|
+
assert_nil album.artist.saved?
|
|
62
60
|
end
|
|
63
|
-
end
|
|
64
61
|
|
|
62
|
+
describe "#sync with block" do
|
|
63
|
+
it do
|
|
64
|
+
form = AlbumForm.new(Album.new("Greatest Hits"))
|
|
65
|
+
|
|
66
|
+
form.validate(name: nil) # nil-out the title.
|
|
67
|
+
|
|
68
|
+
nested_hash = nil
|
|
69
|
+
form.sync do |hash|
|
|
70
|
+
nested_hash = hash
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
assert_equal nested_hash, "name" => nil, "artist" => nil
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
65
77
|
|
|
66
78
|
# class SaveWithDynamicOptionsTest < MiniTest::Spec
|
|
67
79
|
# Song = Struct.new(:id, :title, :length) do
|
|
68
80
|
# include Saveable
|
|
69
81
|
# end
|
|
70
82
|
|
|
71
|
-
# class SongForm <
|
|
83
|
+
# class SongForm < TestForm
|
|
72
84
|
# property :title#, save: false
|
|
73
85
|
# property :length, virtual: true
|
|
74
86
|
# end
|
|
75
87
|
|
|
76
|
-
# let
|
|
77
|
-
# let
|
|
88
|
+
# let(:song) { Song.new }
|
|
89
|
+
# let(:form) { SongForm.new(song) }
|
|
78
90
|
|
|
79
91
|
# # we have access to original input value and outside parameters.
|
|
80
92
|
# it "xxx" do
|
|
@@ -83,7 +95,7 @@ end
|
|
|
83
95
|
# form.save(length: lambda { |value, options| form.model.id = "#{value}: #{length_seconds}" })
|
|
84
96
|
|
|
85
97
|
# song.title.must_equal "A Poor Man's Memory"
|
|
86
|
-
# song.length
|
|
98
|
+
# assert_nil song.length
|
|
87
99
|
# song.id.must_equal "10: 120"
|
|
88
100
|
# end
|
|
89
101
|
# end
|
data/test/setup_test.rb
CHANGED
|
@@ -5,7 +5,7 @@ class SetupTest < MiniTest::Spec
|
|
|
5
5
|
Album = Struct.new(:name, :songs, :artist)
|
|
6
6
|
Artist = Struct.new(:name)
|
|
7
7
|
|
|
8
|
-
class AlbumForm <
|
|
8
|
+
class AlbumForm < TestForm
|
|
9
9
|
property :name
|
|
10
10
|
collection :songs do
|
|
11
11
|
property :title
|
|
@@ -20,29 +20,29 @@ class SetupTest < MiniTest::Spec
|
|
|
20
20
|
end
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
-
let
|
|
24
|
-
let
|
|
25
|
-
let
|
|
26
|
-
let
|
|
23
|
+
let(:song) { Song.new("Broken") }
|
|
24
|
+
let(:song_with_composer) { Song.new("Resist Stance", nil, composer) }
|
|
25
|
+
let(:composer) { Artist.new("Greg Graffin") }
|
|
26
|
+
let(:artist) { Artist.new("Bad Religion") }
|
|
27
27
|
|
|
28
28
|
describe "with nested objects" do
|
|
29
|
-
let
|
|
29
|
+
let(:album) { Album.new("The Dissent Of Man", [song, song_with_composer], artist) }
|
|
30
30
|
|
|
31
31
|
it do
|
|
32
32
|
form = AlbumForm.new(album)
|
|
33
33
|
|
|
34
|
-
form.name
|
|
35
|
-
form.songs[0].title
|
|
36
|
-
form.songs[0].composer
|
|
37
|
-
form.songs[1].title
|
|
38
|
-
form.songs[1].composer.name
|
|
39
|
-
form.artist.name
|
|
34
|
+
assert_equal form.name, "The Dissent Of Man"
|
|
35
|
+
assert_equal form.songs[0].title, "Broken"
|
|
36
|
+
assert_nil form.songs[0].composer
|
|
37
|
+
assert_equal form.songs[1].title, "Resist Stance"
|
|
38
|
+
assert_equal form.songs[1].composer.name, "Greg Graffin"
|
|
39
|
+
assert_equal form.artist.name, "Bad Religion"
|
|
40
40
|
|
|
41
41
|
# make sure all is wrapped in forms.
|
|
42
|
-
form.songs[0].
|
|
43
|
-
form.songs[1].
|
|
44
|
-
form.songs[1].composer.
|
|
45
|
-
form.artist.
|
|
42
|
+
assert form.songs[0].is_a? Reform::Form
|
|
43
|
+
assert form.songs[1].is_a? Reform::Form
|
|
44
|
+
assert form.songs[1].composer.is_a? Reform::Form
|
|
45
|
+
assert form.artist.is_a? Reform::Form
|
|
46
46
|
end
|
|
47
47
|
end
|
|
48
|
-
end
|
|
48
|
+
end
|
data/test/skip_if_test.rb
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
require
|
|
1
|
+
require "test_helper"
|
|
2
2
|
|
|
3
3
|
class SkipIfTest < BaseTest
|
|
4
|
+
let(:hit) { Song.new }
|
|
5
|
+
let(:album) { Album.new(nil, hit, [], nil) }
|
|
4
6
|
|
|
5
|
-
class AlbumForm <
|
|
7
|
+
class AlbumForm < TestForm
|
|
6
8
|
property :title
|
|
7
9
|
|
|
8
|
-
property :hit, skip_if:
|
|
10
|
+
property :hit, skip_if: ->(options) { options[:fragment]["title"] == "" } do
|
|
9
11
|
property :title
|
|
10
12
|
validation do
|
|
11
|
-
|
|
13
|
+
params { required(:title).filled }
|
|
12
14
|
end
|
|
13
15
|
end
|
|
14
16
|
|
|
@@ -21,36 +23,32 @@ class SkipIfTest < BaseTest
|
|
|
21
23
|
end
|
|
22
24
|
end
|
|
23
25
|
|
|
24
|
-
|
|
25
|
-
let (:hit) { Song.new }
|
|
26
|
-
let (:album) { Album.new(nil, hit, [], nil) }
|
|
27
|
-
|
|
28
26
|
# deserializes when present.
|
|
29
27
|
it do
|
|
30
28
|
form = AlbumForm.new(album)
|
|
31
|
-
form.validate("hit" => {"title" => "Altar Of Sacrifice"})
|
|
32
|
-
form.hit.title
|
|
29
|
+
assert form.validate("hit" => {"title" => "Altar Of Sacrifice"})
|
|
30
|
+
assert_equal form.hit.title, "Altar Of Sacrifice"
|
|
33
31
|
end
|
|
34
32
|
|
|
35
33
|
# skips deserialization when not present.
|
|
36
34
|
it do
|
|
37
35
|
form = AlbumForm.new(Album.new)
|
|
38
|
-
form.validate("hit" => {"title" => ""})
|
|
39
|
-
form.hit
|
|
36
|
+
assert form.validate("hit" => {"title" => ""})
|
|
37
|
+
assert_nil form.hit # hit hasn't been deserialised.
|
|
40
38
|
end
|
|
41
39
|
|
|
42
40
|
# skips deserialization when not present.
|
|
43
41
|
it do
|
|
44
42
|
form = AlbumForm.new(Album.new(nil, nil, []))
|
|
45
|
-
form.validate("songs" => [{"title" => "Waste Of Breath"}, {"title" => nil}])
|
|
46
|
-
form.songs.size
|
|
47
|
-
form.songs[0].title
|
|
43
|
+
assert form.validate("songs" => [{"title" => "Waste Of Breath"}, {"title" => nil}])
|
|
44
|
+
assert_equal form.songs.size, 1
|
|
45
|
+
assert_equal form.songs[0].title, "Waste Of Breath"
|
|
48
46
|
end
|
|
49
47
|
end
|
|
50
48
|
|
|
51
49
|
class SkipIfAllBlankTest < BaseTest
|
|
52
50
|
# skip_if: :all_blank"
|
|
53
|
-
class AlbumForm <
|
|
51
|
+
class AlbumForm < TestForm
|
|
54
52
|
collection :songs, skip_if: :all_blank, populate_if_empty: BaseTest::Song do
|
|
55
53
|
property :title
|
|
56
54
|
property :length
|
|
@@ -60,15 +58,28 @@ class SkipIfAllBlankTest < BaseTest
|
|
|
60
58
|
# create only one object.
|
|
61
59
|
it do
|
|
62
60
|
form = AlbumForm.new(OpenStruct.new(songs: []))
|
|
63
|
-
form.validate("songs" => [{"title"=>"Apathy"}, {"title"=>"", "length" => ""}])
|
|
64
|
-
form.songs.size
|
|
65
|
-
form.songs[0].title
|
|
61
|
+
assert form.validate("songs" => [{"title" => "Apathy"}, {"title" => "", "length" => ""}])
|
|
62
|
+
assert_equal form.songs.size, 1
|
|
63
|
+
assert_equal form.songs[0].title, "Apathy"
|
|
66
64
|
end
|
|
67
65
|
|
|
68
66
|
it do
|
|
69
67
|
form = AlbumForm.new(OpenStruct.new(songs: []))
|
|
70
|
-
form.validate("songs" => [{"title"=>"", "length" => ""}, {"title"=>"Apathy"}])
|
|
71
|
-
form.songs.size
|
|
72
|
-
form.songs[0].title
|
|
68
|
+
assert form.validate("songs" => [{"title" => "", "length" => ""}, {"title" => "Apathy"}])
|
|
69
|
+
assert_equal form.songs.size, 1
|
|
70
|
+
assert_equal form.songs[0].title, "Apathy"
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
class InvalidOptionsCombinationTest < BaseTest
|
|
75
|
+
it do
|
|
76
|
+
assert_raises(Reform::Form::InvalidOptionsCombinationError) do
|
|
77
|
+
class AlbumForm < TestForm
|
|
78
|
+
collection :songs, skip_if: :all_blank, populator: -> {} do
|
|
79
|
+
property :title
|
|
80
|
+
property :length
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
73
84
|
end
|
|
74
85
|
end
|
|
@@ -7,7 +7,7 @@ class SetupSkipSetterAndGetterTest < MiniTest::Spec
|
|
|
7
7
|
Album = Struct.new(:title, :artist)
|
|
8
8
|
Artist = Struct.new(:name)
|
|
9
9
|
|
|
10
|
-
class AlbumForm <
|
|
10
|
+
class AlbumForm < TestForm
|
|
11
11
|
property :title
|
|
12
12
|
|
|
13
13
|
def title
|
|
@@ -31,24 +31,23 @@ class SetupSkipSetterAndGetterTest < MiniTest::Spec
|
|
|
31
31
|
end
|
|
32
32
|
end
|
|
33
33
|
|
|
34
|
-
let
|
|
35
|
-
|
|
34
|
+
let(:artist) { Artist.new("Bad Religion") }
|
|
36
35
|
|
|
37
36
|
it do
|
|
38
37
|
album = Album.new("Greatest Hits", artist)
|
|
39
38
|
form = AlbumForm.new(album)
|
|
40
39
|
|
|
41
|
-
form.title
|
|
42
|
-
form.artist.name
|
|
40
|
+
assert_equal form.title, "GREATEST HITS"
|
|
41
|
+
assert_equal form.artist.name, "bad religion"
|
|
43
42
|
|
|
44
43
|
form.validate("title" => "Resiststance", "artist" => {"name" => "Greg Graffin"})
|
|
45
44
|
|
|
46
|
-
form.title
|
|
47
|
-
form.artist.name
|
|
45
|
+
assert_equal form.title, "ECNATSTSISER" # first, setter called, then getter.
|
|
46
|
+
assert_equal form.artist.name, "greg graffi"
|
|
48
47
|
|
|
49
48
|
form.sync
|
|
50
49
|
|
|
51
|
-
album.title
|
|
52
|
-
album.artist.name
|
|
50
|
+
assert_equal album.title, "ecnatstsiseR" # setter called, but not getter.
|
|
51
|
+
assert_equal album.artist.name, "Greg Graffi"
|
|
53
52
|
end
|
|
54
|
-
end
|
|
53
|
+
end
|
data/test/test_helper.rb
CHANGED
|
@@ -1,11 +1,26 @@
|
|
|
1
1
|
require "reform"
|
|
2
|
-
require
|
|
2
|
+
require "minitest/autorun"
|
|
3
3
|
require "representable/debug"
|
|
4
4
|
require "declarative/testing"
|
|
5
5
|
require "pp"
|
|
6
6
|
|
|
7
|
+
require "reform/form/dry"
|
|
8
|
+
|
|
9
|
+
# setup test classes so we can test without dry being included
|
|
10
|
+
class TestForm < Reform::Form
|
|
11
|
+
feature Reform::Form::Dry
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
class TestContract < Reform::Contract
|
|
15
|
+
feature Reform::Form::Dry
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
module Types
|
|
19
|
+
include Dry.Types()
|
|
20
|
+
end
|
|
21
|
+
|
|
7
22
|
class BaseTest < MiniTest::Spec
|
|
8
|
-
class AlbumForm <
|
|
23
|
+
class AlbumForm < TestForm
|
|
9
24
|
property :title
|
|
10
25
|
|
|
11
26
|
property :hit do
|
|
@@ -17,17 +32,20 @@ class BaseTest < MiniTest::Spec
|
|
|
17
32
|
end
|
|
18
33
|
end
|
|
19
34
|
|
|
20
|
-
Song = Struct.new(:title, :length)
|
|
35
|
+
Song = Struct.new(:title, :length, :rating)
|
|
21
36
|
Album = Struct.new(:title, :hit, :songs, :band)
|
|
22
37
|
Band = Struct.new(:label)
|
|
23
38
|
Label = Struct.new(:name)
|
|
24
39
|
Length = Struct.new(:minutes, :seconds)
|
|
25
40
|
|
|
26
|
-
|
|
27
|
-
let (:hit) { Song.new("Roxanne") }
|
|
41
|
+
let(:hit) { Song.new("Roxanne") }
|
|
28
42
|
end
|
|
29
43
|
|
|
30
44
|
MiniTest::Spec.class_eval do
|
|
45
|
+
Song = Struct.new(:title, :album, :composer)
|
|
46
|
+
Album = Struct.new(:name, :songs, :artist)
|
|
47
|
+
Artist = Struct.new(:name)
|
|
48
|
+
|
|
31
49
|
module Saveable
|
|
32
50
|
def save
|
|
33
51
|
@saved = true
|
|
@@ -38,12 +56,3 @@ MiniTest::Spec.class_eval do
|
|
|
38
56
|
end
|
|
39
57
|
end
|
|
40
58
|
end
|
|
41
|
-
|
|
42
|
-
require "reform/form/dry"
|
|
43
|
-
Reform::Contract.class_eval do
|
|
44
|
-
feature Reform::Form::Dry
|
|
45
|
-
end
|
|
46
|
-
# FIXME!
|
|
47
|
-
Reform::Form.class_eval do
|
|
48
|
-
feature Reform::Form::Dry
|
|
49
|
-
end
|