reform 2.3.0.rc1 → 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.
Files changed (65) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +5 -1
  3. data/.travis.yml +7 -11
  4. data/CHANGES.md +43 -3
  5. data/Gemfile +2 -5
  6. data/ISSUE_TEMPLATE.md +1 -1
  7. data/LICENSE.txt +1 -1
  8. data/README.md +7 -9
  9. data/Rakefile +6 -10
  10. data/lib/reform/contract.rb +7 -7
  11. data/lib/reform/contract/custom_error.rb +41 -0
  12. data/lib/reform/contract/validate.rb +10 -6
  13. data/lib/reform/errors.rb +27 -15
  14. data/lib/reform/form.rb +22 -11
  15. data/lib/reform/form/call.rb +1 -1
  16. data/lib/reform/form/composition.rb +2 -2
  17. data/lib/reform/form/dry.rb +22 -60
  18. data/lib/reform/form/dry/input_hash.rb +37 -0
  19. data/lib/reform/form/populator.rb +9 -11
  20. data/lib/reform/form/prepopulate.rb +3 -2
  21. data/lib/reform/form/validate.rb +19 -12
  22. data/lib/reform/result.rb +36 -9
  23. data/lib/reform/validation.rb +10 -8
  24. data/lib/reform/validation/groups.rb +2 -4
  25. data/lib/reform/version.rb +1 -1
  26. data/reform.gemspec +9 -9
  27. data/test/benchmarking.rb +10 -11
  28. data/test/call_test.rb +8 -8
  29. data/test/changed_test.rb +13 -13
  30. data/test/coercion_test.rb +56 -24
  31. data/test/composition_test.rb +49 -51
  32. data/test/contract/custom_error_test.rb +55 -0
  33. data/test/contract_test.rb +18 -18
  34. data/test/default_test.rb +3 -3
  35. data/test/deserialize_test.rb +14 -17
  36. data/test/docs/validation_test.rb +134 -0
  37. data/test/errors_test.rb +131 -86
  38. data/test/feature_test.rb +9 -11
  39. data/test/fixtures/dry_error_messages.yml +65 -52
  40. data/test/form_option_test.rb +3 -3
  41. data/test/form_test.rb +6 -6
  42. data/test/from_test.rb +17 -21
  43. data/test/inherit_test.rb +28 -35
  44. data/test/module_test.rb +23 -28
  45. data/test/parse_option_test.rb +12 -12
  46. data/test/parse_pipeline_test.rb +3 -3
  47. data/test/populate_test.rb +146 -93
  48. data/test/populator_skip_test.rb +3 -4
  49. data/test/prepopulator_test.rb +20 -21
  50. data/test/read_only_test.rb +12 -1
  51. data/test/readable_test.rb +7 -7
  52. data/test/reform_test.rb +38 -42
  53. data/test/save_test.rb +16 -19
  54. data/test/setup_test.rb +15 -15
  55. data/test/skip_if_test.rb +30 -19
  56. data/test/skip_setter_and_getter_test.rb +8 -9
  57. data/test/test_helper.rb +12 -5
  58. data/test/validate_test.rb +160 -140
  59. data/test/validation/dry_validation_test.rb +407 -236
  60. data/test/validation/result_test.rb +29 -31
  61. data/test/validation_library_provided_test.rb +3 -3
  62. data/test/virtual_test.rb +46 -6
  63. data/test/writeable_test.rb +13 -13
  64. metadata +32 -29
  65. data/test/readonly_test.rb +0 -14
data/test/setup_test.rb CHANGED
@@ -20,29 +20,29 @@ class SetupTest < MiniTest::Spec
20
20
  end
21
21
  end
22
22
 
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") }
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 (:album) { Album.new("The Dissent Of Man", [song, song_with_composer], artist) }
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.must_equal "The Dissent Of Man"
35
- form.songs[0].title.must_equal "Broken"
34
+ assert_equal form.name, "The Dissent Of Man"
35
+ assert_equal form.songs[0].title, "Broken"
36
36
  assert_nil form.songs[0].composer
37
- form.songs[1].title.must_equal "Resist Stance"
38
- form.songs[1].composer.name.must_equal "Greg Graffin"
39
- form.artist.name.must_equal "Bad Religion"
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].must_be_kind_of Reform::Form
43
- form.songs[1].must_be_kind_of Reform::Form
44
- form.songs[1].composer.must_be_kind_of Reform::Form
45
- form.artist.must_be_kind_of Reform::Form
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 'test_helper'
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
7
  class AlbumForm < TestForm
6
8
  property :title
7
9
 
8
- property :hit, skip_if: lambda { |options| options[:fragment]["title"]=="" } do
10
+ property :hit, skip_if: ->(options) { options[:fragment]["title"] == "" } do
9
11
  property :title
10
12
  validation do
11
- required(:title).filled
13
+ params { required(:title).filled }
12
14
  end
13
15
  end
14
16
 
@@ -21,30 +23,26 @@ 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"}).must_equal true
32
- form.hit.title.must_equal "Altar Of Sacrifice"
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" => ""}).must_equal true
36
+ assert form.validate("hit" => {"title" => ""})
39
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}]).must_equal true
46
- form.songs.size.must_equal 1
47
- form.songs[0].title.must_equal "Waste Of Breath"
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
 
@@ -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" => ""}]).must_equal true
64
- form.songs.size.must_equal 1
65
- form.songs[0].title.must_equal "Apathy"
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"}]).must_equal true
71
- form.songs.size.must_equal 1
72
- form.songs[0].title.must_equal "Apathy"
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
@@ -31,24 +31,23 @@ class SetupSkipSetterAndGetterTest < MiniTest::Spec
31
31
  end
32
32
  end
33
33
 
34
- let (:artist) { Artist.new("Bad Religion") }
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.must_equal "GREATEST HITS"
42
- form.artist.name.must_equal "bad religion"
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.must_equal "ECNATSTSISER" # first, setter called, then getter.
47
- form.artist.name.must_equal "greg graffi"
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.must_equal "ecnatstsiseR" # setter called, but not getter.
52
- album.artist.name.must_equal "Greg Graffi"
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,12 @@
1
1
  require "reform"
2
- require 'minitest/autorun'
2
+ require "minitest/autorun"
3
3
  require "representable/debug"
4
4
  require "declarative/testing"
5
5
  require "pp"
6
- require 'byebug'
6
+ require "pry-byebug"
7
7
 
8
8
  require "reform/form/dry"
9
+
9
10
  # setup test classes so we can test without dry being included
10
11
  class TestForm < Reform::Form
11
12
  feature Reform::Form::Dry
@@ -15,6 +16,10 @@ class TestContract < Reform::Contract
15
16
  feature Reform::Form::Dry
16
17
  end
17
18
 
19
+ module Types
20
+ include Dry.Types()
21
+ end
22
+
18
23
  class BaseTest < MiniTest::Spec
19
24
  class AlbumForm < TestForm
20
25
  property :title
@@ -34,11 +39,14 @@ class BaseTest < MiniTest::Spec
34
39
  Label = Struct.new(:name)
35
40
  Length = Struct.new(:minutes, :seconds)
36
41
 
37
-
38
- let (:hit) { Song.new("Roxanne") }
42
+ let(:hit) { Song.new("Roxanne") }
39
43
  end
40
44
 
41
45
  MiniTest::Spec.class_eval do
46
+ Song = Struct.new(:title, :album, :composer)
47
+ Album = Struct.new(:name, :songs, :artist)
48
+ Artist = Struct.new(:name)
49
+
42
50
  module Saveable
43
51
  def save
44
52
  @saved = true
@@ -49,4 +57,3 @@ MiniTest::Spec.class_eval do
49
57
  end
50
58
  end
51
59
  end
52
-
@@ -1,25 +1,21 @@
1
- require 'test_helper'
1
+ require "test_helper"
2
2
 
3
3
  class ContractValidateTest < MiniTest::Spec
4
- Song = Struct.new(:title, :album, :composer)
5
- Album = Struct.new(:name, :songs, :artist)
6
- Artist = Struct.new(:name)
7
-
8
4
  class AlbumForm < TestContract
9
5
  property :name
10
6
  validation do
11
- required(:name).filled
7
+ params { required(:name).filled }
12
8
  end
13
9
 
14
10
  collection :songs do
15
11
  property :title
16
12
  validation do
17
- required(:title).filled
13
+ params { required(:title).filled }
18
14
  end
19
15
 
20
16
  property :composer do
21
17
  validation do
22
- required(:name).filled
18
+ params { required(:name).filled }
23
19
  end
24
20
  property :name
25
21
  end
@@ -30,18 +26,18 @@ class ContractValidateTest < MiniTest::Spec
30
26
  end
31
27
  end
32
28
 
33
- let (:song) { Song.new("Broken") }
34
- let (:song_with_composer) { Song.new("Resist Stance", nil, composer) }
35
- let (:composer) { Artist.new("Greg Graffin") }
36
- let (:artist) { Artist.new("Bad Religion") }
37
- let (:album) { Album.new("The Dissent Of Man", [song, song_with_composer], artist) }
29
+ let(:song) { Song.new("Broken") }
30
+ let(:song_with_composer) { Song.new("Resist Stance", nil, composer) }
31
+ let(:composer) { Artist.new("Greg Graffin") }
32
+ let(:artist) { Artist.new("Bad Religion") }
33
+ let(:album) { Album.new("The Dissent Of Man", [song, song_with_composer], artist) }
38
34
 
39
- let (:form) { AlbumForm.new(album) }
35
+ let(:form) { AlbumForm.new(album) }
40
36
 
41
37
  # valid
42
38
  it do
43
- form.validate.must_equal true
44
- form.errors.messages.inspect.must_equal "{}"
39
+ assert form.validate
40
+ assert_equal form.errors.messages.inspect, "{}"
45
41
  end
46
42
 
47
43
  # invalid
@@ -49,35 +45,29 @@ class ContractValidateTest < MiniTest::Spec
49
45
  album.songs[1].composer.name = nil
50
46
  album.name = nil
51
47
 
52
- form.validate.must_equal false
53
- form.errors.messages.inspect.must_equal "{:name=>[\"must be filled\"], :\"songs.composer.name\"=>[\"must be filled\"]}"
48
+ assert_equal form.validate, false
49
+ assert_equal form.errors.messages.inspect, "{:name=>[\"must be filled\"], :\"songs.composer.name\"=>[\"must be filled\"]}"
54
50
  end
55
51
  end
56
52
 
57
-
58
53
  # no configuration results in "sync" (formerly known as parse_strategy: :sync).
59
54
  class ValidateWithoutConfigurationTest < MiniTest::Spec
60
- Song = Struct.new(:title, :album, :composer)
61
- Album = Struct.new(:name, :songs, :artist)
62
- Artist = Struct.new(:name)
63
-
64
55
  class AlbumForm < TestForm
65
56
  property :name
66
57
  validation do
67
- required(:name).filled
58
+ params { required(:name).filled }
68
59
  end
69
60
 
70
61
  collection :songs do
71
-
72
62
  property :title
73
63
  validation do
74
- required(:title).filled
64
+ params { required(:title).filled }
75
65
  end
76
66
 
77
67
  property :composer do
78
68
  property :name
79
69
  validation do
80
- required(:name).filled
70
+ params { required(:name).filled }
81
71
  end
82
72
  end
83
73
  end
@@ -87,62 +77,63 @@ class ValidateWithoutConfigurationTest < MiniTest::Spec
87
77
  end
88
78
  end
89
79
 
90
- let (:song) { Song.new("Broken") }
91
- let (:song_with_composer) { Song.new("Resist Stance", nil, composer) }
92
- let (:composer) { Artist.new("Greg Graffin") }
93
- let (:artist) { Artist.new("Bad Religion") }
94
- let (:album) { Album.new("The Dissent Of Man", [song, song_with_composer], artist) }
80
+ let(:song) { Song.new("Broken") }
81
+ let(:song_with_composer) { Song.new("Resist Stance", nil, composer) }
82
+ let(:composer) { Artist.new("Greg Graffin") }
83
+ let(:artist) { Artist.new("Bad Religion") }
84
+ let(:album) { Album.new("The Dissent Of Man", [song, song_with_composer], artist) }
95
85
 
96
- let (:form) { AlbumForm.new(album) }
86
+ let(:form) { AlbumForm.new(album) }
97
87
 
98
88
  # valid.
99
89
  it do
100
- object_ids = {song: form.songs[0].object_id, song_with_composer: form.songs[1].object_id,
101
- artist: form.artist.object_id, composer: form.songs[1].composer.object_id}
90
+ object_ids = {
91
+ song: form.songs[0].object_id, song_with_composer: form.songs[1].object_id,
92
+ artist: form.artist.object_id, composer: form.songs[1].composer.object_id
93
+ }
102
94
 
103
- form.validate(
95
+ assert form.validate(
104
96
  "name" => "Best Of",
105
97
  "songs" => [{"title" => "Fallout"}, {"title" => "Roxanne", "composer" => {"name" => "Sting"}}],
106
- "artist" => {"name" => "The Police"},
107
- ).must_equal true
98
+ "artist" => {"name" => "The Police"}
99
+ )
108
100
 
109
- form.errors.messages.inspect.must_equal "{}"
101
+ assert_equal form.errors.messages.inspect, "{}"
110
102
 
111
103
  # form has updated.
112
- form.name.must_equal "Best Of"
113
- form.songs[0].title.must_equal "Fallout"
114
- form.songs[1].title.must_equal "Roxanne"
115
- form.songs[1].composer.name.must_equal "Sting"
116
- form.artist.name.must_equal "The Police"
104
+ assert_equal form.name, "Best Of"
105
+ assert_equal form.songs[0].title, "Fallout"
106
+ assert_equal form.songs[1].title, "Roxanne"
107
+ assert_equal form.songs[1].composer.name, "Sting"
108
+ assert_equal form.artist.name, "The Police"
117
109
 
118
110
  # objects are still the same.
119
- form.songs[0].object_id.must_equal object_ids[:song]
120
- form.songs[1].object_id.must_equal object_ids[:song_with_composer]
121
- form.songs[1].composer.object_id.must_equal object_ids[:composer]
122
- form.artist.object_id.must_equal object_ids[:artist]
123
-
111
+ assert_equal form.songs[0].object_id, object_ids[:song]
112
+ assert_equal form.songs[1].object_id, object_ids[:song_with_composer]
113
+ assert_equal form.songs[1].composer.object_id, object_ids[:composer]
114
+ assert_equal form.artist.object_id, object_ids[:artist]
124
115
 
125
116
  # model has not changed, yet.
126
- album.name.must_equal "The Dissent Of Man"
127
- album.songs[0].title.must_equal "Broken"
128
- album.songs[1].title.must_equal "Resist Stance"
129
- album.songs[1].composer.name.must_equal "Greg Graffin"
130
- album.artist.name.must_equal "Bad Religion"
117
+ assert_equal album.name, "The Dissent Of Man"
118
+ assert_equal album.songs[0].title, "Broken"
119
+ assert_equal album.songs[1].title, "Resist Stance"
120
+ assert_equal album.songs[1].composer.name, "Greg Graffin"
121
+ assert_equal album.artist.name, "Bad Religion"
131
122
  end
132
123
 
133
124
  # with symbols.
134
125
  it do
135
- form.validate(
126
+ assert form.validate(
136
127
  name: "Best Of",
137
128
  songs: [{title: "The X-Creep"}, {title: "Trudging", composer: {name: "SNFU"}}],
138
- artist: {name: "The Police"},
139
- ).must_equal true
140
-
141
- form.name.must_equal "Best Of"
142
- form.songs[0].title.must_equal "The X-Creep"
143
- form.songs[1].title.must_equal "Trudging"
144
- form.songs[1].composer.name.must_equal "SNFU"
145
- form.artist.name.must_equal "The Police"
129
+ artist: {name: "The Police"}
130
+ )
131
+
132
+ assert_equal form.name, "Best Of"
133
+ assert_equal form.songs[0].title, "The X-Creep"
134
+ assert_equal form.songs[1].title, "Trudging"
135
+ assert_equal form.songs[1].composer.name, "SNFU"
136
+ assert_equal form.artist.name, "The Police"
146
137
  end
147
138
 
148
139
  # throws exception when no populators.
@@ -156,120 +147,113 @@ class ValidateWithoutConfigurationTest < MiniTest::Spec
156
147
  end
157
148
 
158
149
  class ValidateWithInternalPopulatorOptionTest < MiniTest::Spec
159
- Song = Struct.new(:title, :album, :composer)
160
- Album = Struct.new(:name, :songs, :artist)
161
- Artist = Struct.new(:name)
162
-
163
150
  class AlbumForm < TestForm
164
151
  property :name
165
152
  validation do
166
- required(:name).filled
153
+ params { required(:name).filled }
167
154
  end
168
155
 
169
156
  collection :songs,
170
- internal_populator: lambda { |input, options|
171
- collection = options[:represented].songs
172
- (item = collection[options[:index]]) ? item : collection.insert(options[:index], Song.new) } do
173
-
157
+ internal_populator: ->(input, options) {
158
+ collection = options[:represented].songs
159
+ (item = collection[options[:index]]) ? item : collection.insert(options[:index], Song.new)
160
+ } do
174
161
  property :title
175
162
  validation do
176
- required(:title).filled
163
+ params { required(:title).filled }
177
164
  end
178
165
 
179
- property :composer, internal_populator: lambda { |input, options| (item = options[:represented].composer) ? item : Artist.new } do
166
+ property :composer, internal_populator: ->(input, options) { (item = options[:represented].composer) ? item : Artist.new } do
180
167
  property :name
181
168
  validation do
182
- required(:name).filled
169
+ params { required(:name).filled }
183
170
  end
184
171
  end
185
172
  end
186
173
 
187
- property :artist, internal_populator: lambda { |input, options| (item = options[:represented].artist) ? item : Artist.new } do
174
+ property :artist, internal_populator: ->(input, options) { (item = options[:represented].artist) ? item : Artist.new } do
188
175
  property :name
189
176
  validation do
190
- required(:name).filled
177
+ params { required(:name).filled }
191
178
  end
192
179
  end
193
180
  end
194
181
 
195
- let (:song) { Song.new("Broken") }
196
- let (:song_with_composer) { Song.new("Resist Stance", nil, composer) }
197
- let (:composer) { Artist.new("Greg Graffin") }
198
- let (:artist) { Artist.new("Bad Religion") }
199
- let (:album) { Album.new("The Dissent Of Man", [song, song_with_composer], artist) }
182
+ let(:song) { Song.new("Broken") }
183
+ let(:song_with_composer) { Song.new("Resist Stance", nil, composer) }
184
+ let(:composer) { Artist.new("Greg Graffin") }
185
+ let(:artist) { Artist.new("Bad Religion") }
186
+ let(:album) { Album.new("The Dissent Of Man", [song, song_with_composer], artist) }
200
187
 
201
- let (:form) { AlbumForm.new(album) }
188
+ let(:form) { AlbumForm.new(album) }
202
189
 
203
190
  # valid.
204
191
  it("xxx") do
205
- form.validate(
192
+ assert form.validate(
206
193
  "name" => "Best Of",
207
194
  "songs" => [{"title" => "Fallout"}, {"title" => "Roxanne", "composer" => {"name" => "Sting"}}],
208
- "artist" => {"name" => "The Police"},
209
- ).must_equal true
195
+ "artist" => {"name" => "The Police"}
196
+ )
210
197
 
211
- form.errors.messages.inspect.must_equal "{}"
198
+ assert_equal form.errors.messages.inspect, "{}"
212
199
 
213
200
  # form has updated.
214
- form.name.must_equal "Best Of"
215
- form.songs[0].title.must_equal "Fallout"
216
- form.songs[1].title.must_equal "Roxanne"
217
- form.songs[1].composer.name.must_equal "Sting"
218
- form.artist.name.must_equal "The Police"
219
-
201
+ assert_equal form.name, "Best Of"
202
+ assert_equal form.songs[0].title, "Fallout"
203
+ assert_equal form.songs[1].title, "Roxanne"
204
+ assert_equal form.songs[1].composer.name, "Sting"
205
+ assert_equal form.artist.name, "The Police"
220
206
 
221
207
  # model has not changed, yet.
222
- album.name.must_equal "The Dissent Of Man"
223
- album.songs[0].title.must_equal "Broken"
224
- album.songs[1].title.must_equal "Resist Stance"
225
- album.songs[1].composer.name.must_equal "Greg Graffin"
226
- album.artist.name.must_equal "Bad Religion"
208
+ assert_equal album.name, "The Dissent Of Man"
209
+ assert_equal album.songs[0].title, "Broken"
210
+ assert_equal album.songs[1].title, "Resist Stance"
211
+ assert_equal album.songs[1].composer.name, "Greg Graffin"
212
+ assert_equal album.artist.name, "Bad Religion"
227
213
  end
228
214
 
229
215
  # invalid.
230
216
  it do
231
- form.validate(
217
+ assert_equal form.validate(
232
218
  "name" => "",
233
219
  "songs" => [{"title" => "Fallout"}, {"title" => "Roxanne", "composer" => {"name" => ""}}],
234
220
  "artist" => {"name" => ""},
235
- ).must_equal false
221
+ ), false
236
222
 
237
- form.errors.messages.inspect.must_equal "{:name=>[\"must be filled\"], :\"songs.composer.name\"=>[\"must be filled\"], :\"artist.name\"=>[\"must be filled\"]}"
223
+ assert_equal form.errors.messages.inspect, "{:name=>[\"must be filled\"], :\"songs.composer.name\"=>[\"must be filled\"], :\"artist.name\"=>[\"must be filled\"]}"
238
224
  end
239
225
 
240
226
  # adding to collection via :instance.
241
227
  # valid.
242
228
  it do
243
- form.validate(
244
- "songs" => [{"title" => "Fallout"}, {"title" => "Roxanne"}, {"title" => "Rime Of The Ancient Mariner"}],
245
- ).must_equal true
229
+ assert form.validate(
230
+ "songs" => [{"title" => "Fallout"}, {"title" => "Roxanne"}, {"title" => "Rime Of The Ancient Mariner"}]
231
+ )
246
232
 
247
- form.errors.messages.inspect.must_equal "{}"
233
+ assert_equal form.errors.messages.inspect, "{}"
248
234
 
249
235
  # form has updated.
250
- form.name.must_equal "The Dissent Of Man"
251
- form.songs[0].title.must_equal "Fallout"
252
- form.songs[1].title.must_equal "Roxanne"
253
- form.songs[1].composer.name.must_equal "Greg Graffin"
254
- form.songs[1].title.must_equal "Roxanne"
255
- form.songs[2].title.must_equal "Rime Of The Ancient Mariner" # new song added.
256
- form.songs.size.must_equal 3
257
- form.artist.name.must_equal "Bad Religion"
258
-
236
+ assert_equal form.name, "The Dissent Of Man"
237
+ assert_equal form.songs[0].title, "Fallout"
238
+ assert_equal form.songs[1].title, "Roxanne"
239
+ assert_equal form.songs[1].composer.name, "Greg Graffin"
240
+ assert_equal form.songs[1].title, "Roxanne"
241
+ assert_equal form.songs[2].title, "Rime Of The Ancient Mariner" # new song added.
242
+ assert_equal form.songs.size, 3
243
+ assert_equal form.artist.name, "Bad Religion"
259
244
 
260
245
  # model has not changed, yet.
261
- album.name.must_equal "The Dissent Of Man"
262
- album.songs[0].title.must_equal "Broken"
263
- album.songs[1].title.must_equal "Resist Stance"
264
- album.songs[1].composer.name.must_equal "Greg Graffin"
265
- album.songs.size.must_equal 2
266
- album.artist.name.must_equal "Bad Religion"
246
+ assert_equal album.name, "The Dissent Of Man"
247
+ assert_equal album.songs[0].title, "Broken"
248
+ assert_equal album.songs[1].title, "Resist Stance"
249
+ assert_equal album.songs[1].composer.name, "Greg Graffin"
250
+ assert_equal album.songs.size, 2
251
+ assert_equal album.artist.name, "Bad Religion"
267
252
  end
268
253
 
269
-
270
254
  # allow writeable: false even in the deserializer.
271
255
  class SongForm < TestForm
272
- property :title, deserializer: { writeable: false }
256
+ property :title, deserializer: {writeable: false}
273
257
  end
274
258
 
275
259
  it do
@@ -278,13 +262,57 @@ class ValidateWithInternalPopulatorOptionTest < MiniTest::Spec
278
262
  assert_nil form.title
279
263
  form.title = "Unopened"
280
264
  form.sync # only the deserializer is marked as not-writeable.
281
- song.title.must_equal "Unopened"
265
+ assert_equal song.title, "Unopened"
266
+ end
267
+ end
268
+
269
+ # memory leak test
270
+ class ValidateUsingDifferentFormObject < MiniTest::Spec
271
+ class AlbumForm < TestForm
272
+ property :name
273
+
274
+ validation do
275
+ option :form
276
+
277
+ params { required(:name).filled(:str?) }
278
+
279
+ rule(:name) do
280
+ if form.name == 'invalid'
281
+ key.failure('Invalid name')
282
+ end
283
+ end
284
+ end
285
+ end
286
+
287
+ let(:album) { Album.new }
288
+
289
+ let(:form) { AlbumForm.new(album) }
290
+
291
+ it 'sets name correctly' do
292
+ assert form.validate(name: 'valid')
293
+ form.sync
294
+ assert_equal form.model.name, 'valid'
295
+ end
296
+
297
+ it 'validates presence of name' do
298
+ refute form.validate(name: nil)
299
+ assert_equal form.errors[:name], ["must be filled"]
300
+ end
301
+
302
+ it 'validates type of name' do
303
+ refute form.validate(name: 1)
304
+ assert_equal form.errors[:name], ["must be a string"]
305
+ end
306
+
307
+ it 'when name is invalid' do
308
+ refute form.validate(name: 'invalid')
309
+ assert_equal form.errors[:name], ["Invalid name"]
282
310
  end
283
311
  end
284
312
 
285
313
  # # not sure if we should catch that in Reform or rather do that in disposable. this is https://github.com/trailblazer/reform/pull/104
286
314
  # # describe ":populator with :empty" do
287
- # # let (:form) {
315
+ # # let(:form) {
288
316
  # # Class.new(Reform::Form) do
289
317
  # # collection :songs, :empty => true, :populator => lambda { |fragment, index, args|
290
318
  # # songs[index] = args.binding[:form].new(Song.new)
@@ -294,7 +322,7 @@ end
294
322
  # # end
295
323
  # # }
296
324
 
297
- # # let (:params) {
325
+ # # let(:params) {
298
326
  # # {
299
327
  # # "songs" => [{"title" => "Fallout"}, {"title" => "Roxanne"}]
300
328
  # # }
@@ -308,10 +336,9 @@ end
308
336
  # # it { subject.songs[1].title.must_equal "Roxanne" }
309
337
  # # end
310
338
 
311
-
312
339
  # # test cardinalities.
313
340
  # describe "with empty collection and cardinality" do
314
- # let (:album) { Album.new }
341
+ # let(:album) { Album.new }
315
342
 
316
343
  # subject { Class.new(Reform::Form) do
317
344
  # include Reform::Form::ActiveModel
@@ -329,7 +356,6 @@ end
329
356
  # validates :hit, :presence => true
330
357
  # end.new(album) }
331
358
 
332
-
333
359
  # describe "invalid" do
334
360
  # before { subject.validate({}).must_equal false }
335
361
 
@@ -342,9 +368,8 @@ end
342
368
  # end
343
369
  # end
344
370
 
345
-
346
371
  # describe "valid" do
347
- # let (:album) { Album.new(nil, Song.new, [Song.new("Urban Myth")]) }
372
+ # let(:album) { Album.new(nil, Song.new, [Song.new("Urban Myth")]) }
348
373
 
349
374
  # before {
350
375
  # subject.validate({"songs" => [{"title"=>"Daddy, Brother, Lover, Little Boy"}], "hit" => {"title"=>"The Horse"}}).
@@ -355,13 +380,9 @@ end
355
380
  # end
356
381
  # end
357
382
 
358
-
359
-
360
-
361
-
362
383
  # # providing manual validator method allows accessing form's API.
363
384
  # describe "with ::validate" do
364
- # let (:form) {
385
+ # let(:form) {
365
386
  # Class.new(Reform::Form) do
366
387
  # property :title
367
388
 
@@ -373,8 +394,8 @@ end
373
394
  # end
374
395
  # }
375
396
 
376
- # let (:params) { {"title" => "Fallout"} }
377
- # let (:song) { Song.new("Englishman") }
397
+ # let(:params) { {"title" => "Fallout"} }
398
+ # let(:song) { Song.new("Englishman") }
378
399
 
379
400
  # subject { form.new(song) }
380
401
 
@@ -384,10 +405,9 @@ end
384
405
  # it { subject.errors.messages.must_equal({:title=>["not lowercase"]}) }
385
406
  # end
386
407
 
387
-
388
408
  # # overriding the reader for a nested form should only be considered when rendering.
389
409
  # describe "with overridden reader for nested form" do
390
- # let (:form) {
410
+ # let(:form) {
391
411
  # Class.new(Reform::Form) do
392
412
  # property :band, :populate_if_empty => lambda { |*| Band.new } do
393
413
  # property :label
@@ -407,7 +427,7 @@ end
407
427
  # end.new(album)
408
428
  # }
409
429
 
410
- # let (:album) { Album.new }
430
+ # let(:album) { Album.new }
411
431
 
412
432
  # # don't use #artist when validating!
413
433
  # it do