rasti-form 0.1.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 (45) hide show
  1. checksums.yaml +7 -0
  2. data/.coveralls.yml +2 -0
  3. data/.gitignore +9 -0
  4. data/.ruby-gemset +1 -0
  5. data/.ruby-version +1 -0
  6. data/.travis.yml +11 -0
  7. data/Gemfile +4 -0
  8. data/LICENSE.txt +21 -0
  9. data/README.md +131 -0
  10. data/Rakefile +24 -0
  11. data/lib/rasti/form/castable.rb +25 -0
  12. data/lib/rasti/form/errors.rb +41 -0
  13. data/lib/rasti/form/formatable.rb +19 -0
  14. data/lib/rasti/form/types/array.rb +36 -0
  15. data/lib/rasti/form/types/boolean.rb +42 -0
  16. data/lib/rasti/form/types/enum.rb +38 -0
  17. data/lib/rasti/form/types/float.rb +33 -0
  18. data/lib/rasti/form/types/form.rb +40 -0
  19. data/lib/rasti/form/types/hash.rb +39 -0
  20. data/lib/rasti/form/types/integer.rb +21 -0
  21. data/lib/rasti/form/types/regexp.rb +28 -0
  22. data/lib/rasti/form/types/string.rb +23 -0
  23. data/lib/rasti/form/types/symbol.rb +23 -0
  24. data/lib/rasti/form/types/time.rb +40 -0
  25. data/lib/rasti/form/types/uuid.rb +19 -0
  26. data/lib/rasti/form/version.rb +5 -0
  27. data/lib/rasti/form.rb +173 -0
  28. data/lib/rasti-form.rb +1 -0
  29. data/rasti-form.gemspec +37 -0
  30. data/spec/coverage_helper.rb +7 -0
  31. data/spec/form_spec.rb +310 -0
  32. data/spec/minitest_helper.rb +13 -0
  33. data/spec/types/array_spec.rb +22 -0
  34. data/spec/types/boolean_spec.rb +24 -0
  35. data/spec/types/enum_spec.rb +20 -0
  36. data/spec/types/float_spec.rb +18 -0
  37. data/spec/types/form_spec.rb +41 -0
  38. data/spec/types/hash_spec.rb +20 -0
  39. data/spec/types/integer_spec.rb +18 -0
  40. data/spec/types/regexp_spec.rb +20 -0
  41. data/spec/types/string_spec.rb +16 -0
  42. data/spec/types/symbol_spec.rb +16 -0
  43. data/spec/types/time_spec.rb +25 -0
  44. data/spec/types/uuid_spec.rb +18 -0
  45. metadata +228 -0
@@ -0,0 +1,19 @@
1
+ module Rasti
2
+ class Form
3
+ module Types
4
+ class UUID
5
+ class << self
6
+
7
+ include Formatable
8
+
9
+ private
10
+
11
+ def format
12
+ /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}+$/
13
+ end
14
+
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,5 @@
1
+ module Rasti
2
+ class Form
3
+ VERSION = '0.1.0'
4
+ end
5
+ end
data/lib/rasti/form.rb ADDED
@@ -0,0 +1,173 @@
1
+ require 'json'
2
+ require 'multi_require'
3
+
4
+ module Rasti
5
+ class Form
6
+
7
+ extend MultiRequire
8
+
9
+ require_relative_pattern 'form/*'
10
+ require_relative_pattern 'form/types/*'
11
+
12
+ class << self
13
+
14
+ def [](attributes)
15
+ Class.new(self) do
16
+ attributes.each do |name, type, options={}|
17
+ attribute name, type, options
18
+ end
19
+
20
+ def self.inherited(subclass)
21
+ subclass.instance_variable_set :@attributes, attributes.dup
22
+ end
23
+ end
24
+ end
25
+
26
+ def attribute(name, type, options={})
27
+ attributes[name.to_sym] = options.merge(type: type)
28
+ attr_reader name
29
+ end
30
+
31
+ def attributes
32
+ @attributes ||= {}
33
+ end
34
+
35
+ def attribute_names
36
+ attributes.keys
37
+ end
38
+
39
+ def to_s
40
+ "#{name || self.superclass.name}[#{attribute_names.map(&:inspect).join(', ')}]"
41
+ end
42
+ alias_method :inspect, :to_s
43
+
44
+ end
45
+
46
+ def initialize(attrs={})
47
+ assign_attributes attrs
48
+ set_defaults
49
+ validate!
50
+ end
51
+
52
+ def to_s
53
+ "#<#{self.class.name || self.class.superclass.name}[#{to_h.map { |n,v| "#{n}: #{v.inspect}" }.join(', ')}]>"
54
+ end
55
+ alias_method :inspect, :to_s
56
+
57
+ def attributes
58
+ assigned_attribute_names.each_with_object({}) do |name, hash|
59
+ hash[name] = serialize(read_attribute(name))
60
+ end
61
+ end
62
+ alias_method :to_h, :attributes
63
+
64
+ def assigned?(name)
65
+ assigned_attribute_names.include? name
66
+ end
67
+
68
+ def ==(other)
69
+ other.kind_of?(self.class) && other.attributes == attributes
70
+ end
71
+
72
+ def eql?(other)
73
+ other.instance_of?(self.class) && other.attributes == attributes
74
+ end
75
+
76
+ def hash
77
+ [self.class, attributes].hash
78
+ end
79
+
80
+ private
81
+
82
+ def assign_attributes(attrs={})
83
+ self.class.attribute_names.each do |name|
84
+ begin
85
+ write_attribute name, attrs[name] if attrs.key? name
86
+
87
+ rescue CastError => error
88
+ errors[name] << error.message
89
+
90
+ rescue ValidationError => error
91
+ error.errors.each do |inner_name, inner_errors|
92
+ inner_errors.each { |message| errors["#{name}.#{inner_name}"] << message }
93
+ end
94
+ end
95
+ end
96
+ end
97
+
98
+ def set_defaults
99
+ (self.class.attribute_names - attributes.keys).each do |name|
100
+ if self.class.attributes[name].key? :default
101
+ value = self.class.attributes[name][:default]
102
+ write_attribute name, value.is_a?(Proc) ? value.call(self) : value
103
+ end
104
+ end
105
+ end
106
+
107
+ def assigned_attribute_names
108
+ self.class.attribute_names & instance_variables.map { |v| v.to_s[1..-1].to_sym }
109
+ end
110
+
111
+ def serialize(value)
112
+ if value.kind_of? Array
113
+ value.map { |v| serialize v }
114
+ elsif value.kind_of? Form
115
+ value.attributes
116
+ else
117
+ value
118
+ end
119
+ end
120
+
121
+ def read_attribute(name)
122
+ instance_variable_get "@#{name}"
123
+ end
124
+
125
+ def write_attribute(name, value)
126
+ typed_value = value.nil? ? nil : self.class.attributes[name][:type].cast(value)
127
+ instance_variable_set "@#{name}", typed_value
128
+ end
129
+
130
+ def fetch(attribute)
131
+ attribute.to_s.split('.').inject(self) do |target, attr_name|
132
+ target.nil? ? nil : target.public_send(attr_name)
133
+ end
134
+ end
135
+
136
+ def validate!
137
+ validate
138
+ raise ValidationError.new(errors) unless errors.empty?
139
+ end
140
+
141
+ def validate
142
+ end
143
+
144
+ def errors
145
+ @errors ||= Hash.new { |hash, key| hash[key] = [] }
146
+ end
147
+
148
+ def assert(key, condition, message)
149
+ return true if condition
150
+
151
+ errors[key] << message
152
+ false
153
+ end
154
+
155
+ def assert_present(attribute)
156
+ assert attribute, !fetch(attribute).nil?, 'not present'
157
+ end
158
+
159
+ def assert_not_empty(attribute)
160
+ if assert_present attribute
161
+ value = fetch attribute
162
+ assert attribute, value.is_a?(String) ? !value.strip.empty? : !value.empty?, 'is empty'
163
+ end
164
+ end
165
+
166
+ def assert_included_in(attribute, set)
167
+ if assert_present attribute
168
+ assert attribute, set.include?(fetch(attribute)), "not included in #{set.map { |e| e.is_a?(::String) ? "'#{e}'" : e.inspect }.join(', ')}"
169
+ end
170
+ end
171
+
172
+ end
173
+ end
data/lib/rasti-form.rb ADDED
@@ -0,0 +1 @@
1
+ require_relative 'rasti/form'
@@ -0,0 +1,37 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'rasti/form/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'rasti-form'
8
+ spec.version = Rasti::Form::VERSION
9
+ spec.authors = ['Gabriel Naiman']
10
+ spec.email = ['gabynaiman@gmail.com']
11
+ spec.summary = 'Forms validations and type casting'
12
+ spec.description = 'Forms validations and type casting'
13
+ spec.homepage = 'https://github.com/gabynaiman/rasti-form'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_runtime_dependency 'multi_require', '~> 1.0'
22
+
23
+ spec.add_development_dependency 'bundler', '~> 1.12'
24
+ spec.add_development_dependency 'rake', '~> 11.0'
25
+ spec.add_development_dependency 'minitest', '~> 5.0'
26
+ spec.add_development_dependency 'minitest-colorin', '~> 0.1'
27
+ spec.add_development_dependency 'minitest-line', '~> 0.6'
28
+ spec.add_development_dependency 'simplecov', '~> 0.12'
29
+ spec.add_development_dependency 'coveralls', '~> 0.8'
30
+ spec.add_development_dependency 'pry-nav', '~> 0.2'
31
+
32
+ if RUBY_VERSION < '2'
33
+ spec.add_development_dependency 'term-ansicolor', '~> 1.3.0'
34
+ spec.add_development_dependency 'tins', '~> 1.6.0'
35
+ spec.add_development_dependency 'json', '~> 1.8'
36
+ end
37
+ end
@@ -0,0 +1,7 @@
1
+ require 'simplecov'
2
+ require 'coveralls'
3
+
4
+ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new [SimpleCov::Formatter::HTMLFormatter, Coveralls::SimpleCov::Formatter]
5
+ SimpleCov.start do
6
+ add_group 'Types', 'lib/rasti/form/types'
7
+ end
data/spec/form_spec.rb ADDED
@@ -0,0 +1,310 @@
1
+ require 'minitest_helper'
2
+
3
+ describe Rasti::Form do
4
+
5
+ let(:point_class) { Rasti::Form[x: Rasti::Form::Types::Integer, y: Rasti::Form::Types::Integer] }
6
+
7
+ let(:point_subclass) { Class.new point_class }
8
+
9
+ def build_form(&block)
10
+ Class.new(Rasti::Form) do
11
+ class_eval &block
12
+ end
13
+ end
14
+
15
+ describe 'Initialization' do
16
+
17
+ it 'All attributes' do
18
+ point = point_class.new x: 1, y: 2
19
+ point.x.must_equal 1
20
+ point.y.must_equal 2
21
+ point.assigned?(:x).must_equal true
22
+ point.assigned?(:y).must_equal true
23
+ end
24
+
25
+ it 'Some attributes' do
26
+ point = point_class.new x: 1
27
+ point.x.must_equal 1
28
+ point.y.must_be_nil
29
+ point.assigned?(:x).must_equal true
30
+ point.assigned?(:y).must_equal false
31
+ end
32
+
33
+ it 'Whitout attributes' do
34
+ point = point_class.new
35
+ point.x.must_be_nil
36
+ point.y.must_be_nil
37
+ point.assigned?(:x).must_equal false
38
+ point.assigned?(:y).must_equal false
39
+ end
40
+
41
+ it 'Extra attributes' do
42
+ point = point_class.new z: 3
43
+ point.x.must_be_nil
44
+ point.y.must_be_nil
45
+ point.assigned?(:x).must_equal false
46
+ point.assigned?(:y).must_equal false
47
+ proc { point.z }.must_raise NoMethodError
48
+ point.attributes.must_be_empty
49
+ end
50
+
51
+ describe 'Casting' do
52
+
53
+ it 'Attribute' do
54
+ form = build_form do
55
+ attribute :text, Rasti::Form::Types::String
56
+ end
57
+
58
+ f = form.new text: 123
59
+ f.text.must_equal "123"
60
+ end
61
+
62
+ it 'Nested attributes' do
63
+ form = build_form do
64
+ attribute :range, Rasti::Form::Types::Form[min: Rasti::Form::Types::Integer, max: Rasti::Form::Types::Integer]
65
+ end
66
+
67
+ f = form.new range: {min: '1', max: '10'}
68
+ f.range.min.must_equal 1
69
+ f.range.max.must_equal 10
70
+ end
71
+
72
+ it 'Nested form' do
73
+ range = build_form do
74
+ attribute :min, Rasti::Form::Types::Integer
75
+ attribute :max, Rasti::Form::Types::Integer
76
+ end
77
+
78
+ form = build_form do
79
+ attribute :range, Rasti::Form::Types::Form[range]
80
+ end
81
+
82
+ f = form.new range: {min: '1', max: '10'}
83
+ f.range.min.must_equal 1
84
+ f.range.max.must_equal 10
85
+ end
86
+
87
+ it 'Invalid attributes' do
88
+ form = build_form do
89
+ attribute :boolean, Rasti::Form::Types::Boolean
90
+ attribute :number, Rasti::Form::Types::Integer
91
+ end
92
+
93
+ error = proc { form.new boolean: 'x', number: 'y' }.must_raise Rasti::Form::ValidationError
94
+ error.message.must_equal 'Validation error: {"boolean":["Invalid cast: \'x\' -> Rasti::Form::Types::Boolean"],"number":["Invalid cast: \'y\' -> Rasti::Form::Types::Integer"]}'
95
+ end
96
+
97
+ it 'Invalid nested attributes' do
98
+ form = build_form do
99
+ attribute :range, Rasti::Form::Types::Form[min: Rasti::Form::Types::Integer, max: Rasti::Form::Types::Integer]
100
+ end
101
+
102
+ error = proc { form.new range: {min: 'x', max: 'y'} }.must_raise Rasti::Form::ValidationError
103
+ error.message.must_equal "Validation error: {\"range.min\":[\"Invalid cast: 'x' -> Rasti::Form::Types::Integer\"],\"range.max\":[\"Invalid cast: 'y' -> Rasti::Form::Types::Integer\"]}"
104
+ end
105
+
106
+ it 'Invalid form attributes' do
107
+ range = build_form do
108
+ attribute :min, Rasti::Form::Types::Integer
109
+ attribute :max, Rasti::Form::Types::Integer
110
+ end
111
+
112
+ form = build_form do
113
+ attribute :range, Rasti::Form::Types::Form[range]
114
+ end
115
+
116
+ error = proc { form.new range: {min: 'x', max: 'y'} }.must_raise Rasti::Form::ValidationError
117
+ error.message.must_equal "Validation error: {\"range.min\":[\"Invalid cast: 'x' -> Rasti::Form::Types::Integer\"],\"range.max\":[\"Invalid cast: 'y' -> Rasti::Form::Types::Integer\"]}"
118
+ end
119
+
120
+ end
121
+
122
+ end
123
+
124
+ describe 'Defaults' do
125
+
126
+ it 'Value' do
127
+ form = build_form do
128
+ attribute :text, Rasti::Form::Types::String, default: 'xyz'
129
+ end
130
+
131
+ f = form.new
132
+ f.text.must_equal 'xyz'
133
+ end
134
+
135
+ it 'Block' do
136
+ form = build_form do
137
+ attribute :time_1, Rasti::Form::Types::Time['%F']
138
+ attribute :time_2, Rasti::Form::Types::Time['%F'], default: ->(f) { f.time_1 }
139
+ end
140
+
141
+ f = form.new time_1: Time.now
142
+ f.time_2.must_equal f.time_1
143
+ end
144
+
145
+ end
146
+
147
+ describe 'Validations' do
148
+
149
+ it 'Required' do
150
+ form = build_form do
151
+ attribute :text, Rasti::Form::Types::String
152
+
153
+ def validate
154
+ assert_present :text
155
+ end
156
+ end
157
+
158
+ error = proc { form.new }.must_raise Rasti::Form::ValidationError
159
+ error.message.must_equal 'Validation error: {"text":["not present"]}'
160
+ end
161
+
162
+ it 'Not empty string' do
163
+ form = build_form do
164
+ attribute :text, Rasti::Form::Types::String
165
+
166
+ def validate
167
+ assert_not_empty :text
168
+ end
169
+ end
170
+
171
+ error = proc { form.new text: ' ' }.must_raise Rasti::Form::ValidationError
172
+ error.message.must_equal 'Validation error: {"text":["is empty"]}'
173
+ end
174
+
175
+ it 'Not empty array' do
176
+ form = build_form do
177
+ attribute :array, Rasti::Form::Types::Array[Rasti::Form::Types::String]
178
+
179
+ def validate
180
+ assert_not_empty :array
181
+ end
182
+ end
183
+
184
+ error = proc { form.new array: [] }.must_raise Rasti::Form::ValidationError
185
+ error.message.must_equal 'Validation error: {"array":["is empty"]}'
186
+ end
187
+
188
+ it 'Included in values list' do
189
+ form = build_form do
190
+ attribute :text, Rasti::Form::Types::String
191
+
192
+ def validate
193
+ assert_included_in :text, %w(value_1 value_2)
194
+ end
195
+ end
196
+
197
+ error = proc { form.new text: 'xyz' }.must_raise Rasti::Form::ValidationError
198
+ error.message.must_equal 'Validation error: {"text":["not included in \'value_1\', \'value_2\'"]}'
199
+ end
200
+
201
+ it 'Nested form' do
202
+ form = build_form do
203
+ attribute :range, Rasti::Form::Types::Form[min: Rasti::Form::Types::Integer, max: Rasti::Form::Types::Integer]
204
+
205
+ def validate
206
+ assert_present 'range.min'
207
+ assert_present 'range.max'
208
+ end
209
+ end
210
+
211
+ error = proc { form.new }.must_raise Rasti::Form::ValidationError
212
+ error.message.must_equal 'Validation error: {"range.min":["not present"],"range.max":["not present"]}'
213
+ end
214
+
215
+ it 'Nested validation' do
216
+ range = build_form do
217
+ attribute :min, Rasti::Form::Types::Integer
218
+ attribute :max, Rasti::Form::Types::Integer
219
+
220
+ def validate
221
+ assert :min, min < max, 'Min must be less than Max' if min && max
222
+ end
223
+ end
224
+
225
+ form = build_form do
226
+ attribute :range, Rasti::Form::Types::Form[range]
227
+ end
228
+
229
+ error = proc { form.new range: {min: 2, max: 1} }.must_raise Rasti::Form::ValidationError
230
+ error.message.must_equal 'Validation error: {"range.min":["Min must be less than Max"]}'
231
+ end
232
+
233
+ end
234
+
235
+ describe 'Comparable' do
236
+
237
+ it 'Equivalency (==)' do
238
+ point_1 = point_class.new x: 1, y: 2
239
+ point_2 = point_subclass.new x: 1, y: 2
240
+ point_3 = point_class.new x: 2, y: 1
241
+
242
+ assert point_1 == point_2
243
+ refute point_1 == point_3
244
+ end
245
+
246
+ it 'Equality (eql?)' do
247
+ point_1 = point_class.new x: 1, y: 2
248
+ point_2 = point_class.new x: 1, y: 2
249
+ point_3 = point_subclass.new x: 1, y: 2
250
+ point_4 = point_class.new x: 2, y: 1
251
+
252
+ assert point_1.eql?(point_2)
253
+ refute point_1.eql?(point_3)
254
+ refute point_1.eql?(point_4)
255
+ end
256
+
257
+ it 'hash' do
258
+ point_1 = point_class.new x: 1, y: 2
259
+ point_2 = point_class.new x: 1, y: 2
260
+ point_3 = point_subclass.new x: 1, y: 2
261
+ point_4 = point_class.new x: 2, y: 1
262
+
263
+ point_1.hash.must_equal point_2.hash
264
+ point_1.hash.wont_equal point_3.hash
265
+ point_1.hash.wont_equal point_4.hash
266
+ end
267
+
268
+ end
269
+
270
+ it 'Attributes (to_h)' do
271
+ t = Rasti::Form::Types
272
+ address_class = Rasti::Form[street: t::String, number: t::Integer]
273
+ contact_class = Rasti::Form[
274
+ name: t::String,
275
+ age: t::Integer,
276
+ phones: t::Hash[t::Symbol, t::Integer],
277
+ addresses: t::Array[t::Form[address_class]]
278
+ ]
279
+
280
+ attributes = {
281
+ name: 'John',
282
+ age: 24,
283
+ phones: {
284
+ office: 1234567890,
285
+ house: 456456456
286
+ },
287
+ addresses: [
288
+ {street: 'Lexington Avenue', number: 123},
289
+ {street: 'Park Avenue', number: 456}
290
+ ]
291
+ }
292
+
293
+ contact = contact_class.new attributes
294
+
295
+ contact.attributes.must_equal attributes
296
+ contact.attributes.must_equal contact.to_h
297
+ end
298
+
299
+ it 'to_s' do
300
+ point_class.to_s.must_equal 'Rasti::Form[:x, :y]'
301
+ point_class.new(x: '1', y: '2').to_s.must_equal '#<Rasti::Form[x: 1, y: 2]>'
302
+ end
303
+
304
+ it 'Subclass' do
305
+ point = point_subclass.new x: 1, y: 2
306
+ point.x.must_equal 1
307
+ point.y.must_equal 2
308
+ end
309
+
310
+ end
@@ -0,0 +1,13 @@
1
+ require 'coverage_helper'
2
+ require 'minitest/autorun'
3
+ require 'minitest/colorin'
4
+ require 'pry-nav'
5
+ require 'rasti-form'
6
+
7
+ module Minitest
8
+ class Test
9
+ def as_string(value)
10
+ value.is_a?(::String) ? "'#{value}'" : value.inspect
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,22 @@
1
+ require 'minitest_helper'
2
+
3
+ describe Rasti::Form::Types::Array do
4
+
5
+ array = [1, '2', Time.now]
6
+
7
+ it "#{array.inspect} -> #{array.map(&:to_i)}" do
8
+ Rasti::Form::Types::Array[Rasti::Form::Types::Integer].cast(array).must_equal array.map(&:to_i)
9
+ end
10
+
11
+ it "#{array.inspect} -> #{array.map(&:to_s)}" do
12
+ Rasti::Form::Types::Array[Rasti::Form::Types::String].cast(array).must_equal array.map(&:to_s)
13
+ end
14
+
15
+ [[nil], nil, 1, 'text', :symbol, {a: 1, b: 2}, Object.new].each do |value|
16
+ it "#{value.inspect} -> CastError" do
17
+ error = proc { Rasti::Form::Types::Array[Rasti::Form::Types::String].cast(value) }.must_raise Rasti::Form::CastError
18
+ error.message.must_equal "Invalid cast: #{as_string(value)} -> Rasti::Form::Types::Array[Rasti::Form::Types::String]"
19
+ end
20
+ end
21
+
22
+ end
@@ -0,0 +1,24 @@
1
+ require 'minitest_helper'
2
+
3
+ describe Rasti::Form::Types::Boolean do
4
+
5
+ [true, 'true', 'True', 'TRUE', 'T'].each do |value|
6
+ it "#{value.inspect} -> true" do
7
+ Rasti::Form::Types::Boolean.cast(value).must_equal true
8
+ end
9
+ end
10
+
11
+ [false, 'false', 'False', 'FALSE', 'F'].each do |value|
12
+ it "#{value.inspect} -> false" do
13
+ Rasti::Form::Types::Boolean.cast(value).must_equal false
14
+ end
15
+ end
16
+
17
+ [nil, 'text', 123, :false, :true, Time.now, [1,2], {a: 1, b: 2}, Object.new].each do |value|
18
+ it "#{value.inspect} -> CastError" do
19
+ error = proc { Rasti::Form::Types::Boolean.cast(value) }.must_raise Rasti::Form::CastError
20
+ error.message.must_equal "Invalid cast: #{as_string(value)} -> Rasti::Form::Types::Boolean"
21
+ end
22
+ end
23
+
24
+ end
@@ -0,0 +1,20 @@
1
+ require 'minitest_helper'
2
+
3
+ describe Rasti::Form::Types::Enum do
4
+
5
+ enum = Rasti::Form::Types::Enum[:a,:b,:c]
6
+
7
+ [:a, 'b', "c"].each do |value|
8
+ it "#{value.inspect} -> #{enum}" do
9
+ Rasti::Form::Types::Enum[:a,:b,:c].cast(value).must_equal value.to_s
10
+ end
11
+ end
12
+
13
+ [nil, 'text', :symbol, '999'.to_sym, [1,2], {a: 1, b: 2}, Object.new].each do |value|
14
+ it "#{value.inspect} -> CastError" do
15
+ error = proc { Rasti::Form::Types::Enum[:a,:b,:c].cast(value) }.must_raise Rasti::Form::CastError
16
+ error.message.must_equal "Invalid cast: #{as_string(value)} -> Rasti::Form::Types::Enum[\"a\", \"b\", \"c\"]"
17
+ end
18
+ end
19
+
20
+ end
@@ -0,0 +1,18 @@
1
+ require 'minitest_helper'
2
+
3
+ describe Rasti::Form::Types::Float do
4
+
5
+ [100, '200', Time.now,2.0,"12.5"].each do |value|
6
+ it "#{value.inspect} -> #{value.to_i}" do
7
+ Rasti::Form::Types::Float.cast(value).must_equal value.to_f
8
+ end
9
+ end
10
+
11
+ [nil, 'text', :symbol, '999'.to_sym, [1,2], {a: 1, b: 2}, Object.new, "1.", ".2","."].each do |value|
12
+ it "#{value.inspect} -> CastError" do
13
+ error = proc { Rasti::Form::Types::Float.cast(value) }.must_raise Rasti::Form::CastError
14
+ error.message.must_equal "Invalid cast: #{as_string(value)} -> Rasti::Form::Types::Float"
15
+ end
16
+ end
17
+
18
+ end