schemacop 1.0.2 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -1
  3. data/.rubocop.yml +59 -1
  4. data/CHANGELOG.md +10 -0
  5. data/README.md +389 -199
  6. data/Rakefile +2 -0
  7. data/VERSION +1 -1
  8. data/doc/Schemacop.html +41 -130
  9. data/doc/Schemacop/ArrayValidator.html +329 -0
  10. data/doc/Schemacop/BooleanValidator.html +145 -0
  11. data/doc/Schemacop/Collector.html +535 -0
  12. data/doc/Schemacop/Exceptions.html +39 -39
  13. data/doc/Schemacop/Exceptions/InvalidSchemaError.html +124 -0
  14. data/doc/Schemacop/Exceptions/ValidationError.html +124 -0
  15. data/doc/Schemacop/FieldNode.html +409 -0
  16. data/doc/Schemacop/FloatValidator.html +158 -0
  17. data/doc/Schemacop/HashValidator.html +263 -0
  18. data/doc/Schemacop/IntegerValidator.html +158 -0
  19. data/doc/Schemacop/NilValidator.html +145 -0
  20. data/doc/Schemacop/Node.html +1426 -0
  21. data/doc/Schemacop/NodeResolver.html +242 -0
  22. data/doc/Schemacop/NodeSupportingField.html +590 -0
  23. data/doc/Schemacop/NodeSupportingType.html +614 -0
  24. data/doc/Schemacop/NodeWithBlock.html +289 -0
  25. data/doc/Schemacop/NumberValidator.html +232 -0
  26. data/doc/Schemacop/ObjectValidator.html +288 -0
  27. data/doc/Schemacop/RootNode.html +171 -0
  28. data/doc/Schemacop/Schema.html +697 -0
  29. data/doc/Schemacop/StringValidator.html +295 -0
  30. data/doc/ScopedEnv.html +351 -0
  31. data/doc/_index.html +190 -47
  32. data/doc/class_list.html +24 -31
  33. data/doc/css/full_list.css +32 -31
  34. data/doc/css/style.css +244 -91
  35. data/doc/file.README.html +428 -232
  36. data/doc/file_list.html +26 -30
  37. data/doc/frames.html +7 -16
  38. data/doc/index.html +428 -232
  39. data/doc/inheritance.graphml +524 -0
  40. data/doc/inheritance.pdf +825 -0
  41. data/doc/js/app.js +106 -77
  42. data/doc/js/full_list.js +170 -135
  43. data/doc/method_list.html +494 -38
  44. data/doc/top-level-namespace.html +36 -36
  45. data/lib/schemacop.rb +22 -7
  46. data/lib/schemacop/collector.rb +34 -0
  47. data/lib/schemacop/exceptions.rb +2 -8
  48. data/lib/schemacop/field_node.rb +26 -0
  49. data/lib/schemacop/node.rb +127 -0
  50. data/lib/schemacop/node_resolver.rb +14 -0
  51. data/lib/schemacop/node_supporting_field.rb +62 -0
  52. data/lib/schemacop/node_supporting_type.rb +112 -0
  53. data/lib/schemacop/node_with_block.rb +16 -0
  54. data/lib/schemacop/root_node.rb +4 -0
  55. data/lib/schemacop/schema.rb +61 -0
  56. data/lib/schemacop/scoped_env.rb +18 -0
  57. data/lib/schemacop/validator/array_validator.rb +30 -0
  58. data/lib/schemacop/validator/boolean_validator.rb +5 -0
  59. data/lib/schemacop/validator/float_validator.rb +5 -0
  60. data/lib/schemacop/validator/hash_validator.rb +18 -0
  61. data/lib/schemacop/validator/integer_validator.rb +5 -0
  62. data/lib/schemacop/validator/nil_validator.rb +5 -0
  63. data/lib/schemacop/validator/number_validator.rb +19 -0
  64. data/lib/schemacop/validator/object_validator.rb +21 -0
  65. data/lib/schemacop/validator/string_validator.rb +37 -0
  66. data/schemacop.gemspec +7 -5
  67. data/test/custom_check_test.rb +86 -0
  68. data/test/custom_if_test.rb +95 -0
  69. data/test/nil_dis_allow_test.rb +41 -0
  70. data/test/short_forms_test.rb +316 -0
  71. data/test/test_helper.rb +6 -0
  72. data/test/types_test.rb +83 -0
  73. data/test/validator_array_test.rb +97 -0
  74. data/test/validator_boolean_test.rb +15 -0
  75. data/test/validator_float_test.rb +57 -0
  76. data/test/validator_hash_test.rb +71 -0
  77. data/test/validator_integer_test.rb +46 -0
  78. data/test/validator_nil_test.rb +13 -0
  79. data/test/validator_number_test.rb +60 -0
  80. data/test/validator_object_test.rb +87 -0
  81. data/test/validator_string_test.rb +76 -0
  82. metadata +78 -14
  83. data/doc/Schemacop/Exceptions/Base.html +0 -127
  84. data/doc/Schemacop/Exceptions/InvalidSchema.html +0 -141
  85. data/doc/Schemacop/Exceptions/Validation.html +0 -142
  86. data/doc/Schemacop/MethodValidation.html +0 -120
  87. data/doc/Schemacop/MethodValidation/ClassMethods.html +0 -196
  88. data/doc/Schemacop/Validator.html +0 -254
  89. data/lib/schemacop/validator.rb +0 -145
  90. data/test/schemacop_validator_test.rb +0 -257
@@ -0,0 +1,112 @@
1
+ module Schemacop
2
+ class NodeSupportingType < NodeWithBlock
3
+ block_method :type
4
+
5
+ def self.build(options, &block)
6
+ new(nil, options, &block)
7
+ end
8
+
9
+ def initialize(options = {}, &block)
10
+ super(options)
11
+
12
+ @types = []
13
+ exec_block(&block)
14
+
15
+ if @types.none?
16
+ fail Exceptions::InvalidSchemaError, 'Block must contain a type definition or not be given at all.' if block_given?
17
+ type :object
18
+ end
19
+
20
+ # if @types.none?
21
+ # super(options)
22
+ # exec_block(&block)
23
+ # if @types.none?
24
+ # fail Exceptions::InvalidSchemaError, 'Block must contain a type definition or not be given at all.' if block_given?
25
+ # end
26
+ # else
27
+ # super({})
28
+ # end
29
+ end
30
+
31
+ def exec_block(&block)
32
+ super
33
+ rescue NoMethodError
34
+ @types = []
35
+ type :hash, {}, &block
36
+ end
37
+
38
+ # required signature:
39
+ # First argument must be a type or an array of types
40
+ # Following arguments may be subtypes
41
+ # Last argument may be an options hash.
42
+ # Options and given block are passed to the last specified type.
43
+ # Not permitted to give subtypes / options / a block if an array of types is given.
44
+ #
45
+ # TODO: Probably change this method so that the 'rescue NoMethodError'
46
+ # happens in here directly and not in the constructor. This way we can
47
+ # always call 'type', even if we don't have one and the type is auto-guessed
48
+ # as it formerly was the case in the constructor.
49
+ def type(*args, &block)
50
+ options = args.last.is_a?(Hash) ? args.pop : {}
51
+ types = [*args.shift]
52
+ subtypes = args
53
+
54
+ unless types.any?
55
+ fail Exceptions::InvalidSchemaError, 'At least one type must be given.'
56
+ end
57
+
58
+ if subtypes.any? && types.size > 1
59
+ fail Exceptions::InvalidSchemaError, "First given type can't be an array if subtypes are given."
60
+ end
61
+
62
+ if types.size > 1 && options.any?
63
+ fail Exceptions::InvalidSchemaError, 'No options can be specified if multiple types are given.'
64
+ end
65
+
66
+ types.each do |type|
67
+ klass = resolve_type_klass(type)
68
+
69
+ if subtypes.any?
70
+ unless klass <= NodeSupportingType
71
+ fail "Node #{klass} does not support subtypes."
72
+ end
73
+
74
+ child = klass.new do
75
+ self.type(*subtypes, options, &block)
76
+ end
77
+
78
+ # child = klass.build(options)
79
+ #
80
+ #
81
+ # child.type(*subtypes, &block)
82
+ else
83
+ if klass == ObjectValidator && type.is_a?(Class)
84
+ options[:classes] = type
85
+ end
86
+
87
+ child = klass.new(options, &block)
88
+ end
89
+
90
+ @types << child
91
+ end
92
+ end
93
+
94
+ def validate(data, collector)
95
+ super
96
+
97
+ validate_types(data, collector)
98
+ end
99
+
100
+ protected
101
+
102
+ def validate_types(data, collector)
103
+ unless (match = @types.find { |t| t.type_matches?(data) })
104
+ allowed_types = @types.map(&:type_label)
105
+
106
+ collector.error "Data type not matching: #{data.class}, allowed types: #{allowed_types.join('; ')}"
107
+ return
108
+ end
109
+ match.validate(data, collector)
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,16 @@
1
+ module Schemacop
2
+ class NodeWithBlock < Node
3
+ class_attribute :block_methods
4
+ self.block_methods = [].freeze
5
+
6
+ def self.block_method(name)
7
+ self.block_methods += [name]
8
+ end
9
+
10
+ def exec_block(&block)
11
+ return unless block_given?
12
+ se = ScopedEnv.new(self, self.class.block_methods)
13
+ se.instance_exec(&block)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,4 @@
1
+ module Schemacop
2
+ class RootNode < NodeSupportingType
3
+ end
4
+ end
@@ -0,0 +1,61 @@
1
+ module Schemacop
2
+ class Schema
3
+ # Create a new Schema
4
+ #
5
+ # For detailed usage, please refer to README.md in the root of this project.
6
+ #
7
+ # @param args [Array] An array of arguments to apply to the root node of the
8
+ # Schema.
9
+ # @param block A block with further Schema specification.
10
+ # @raise [Schemacop::Exceptions::InvalidSchemaError] If the Schema defined
11
+ # is invalid.
12
+ def initialize(*args, &block)
13
+ @root = HashValidator.new do
14
+ req :root, *args, &block
15
+ end
16
+ end
17
+
18
+ # Query data validity
19
+ #
20
+ # @param data The data to validate.
21
+ # @return [Boolean] True if the data is valid, false otherwise.
22
+ def valid?(data)
23
+ validate(data).valid?
24
+ end
25
+
26
+ # Query data validity
27
+ #
28
+ # @param data The data to validate.
29
+ # @return [Boolean] True if data is invalid, false otherwise.
30
+ def invalid?(data)
31
+ !valid?(data)
32
+ end
33
+
34
+ # Validate data for the defined Schema
35
+ #
36
+ # @param data The data to validate.
37
+ # @return [Schemacop::Collector] The object that collected errors
38
+ # throughout the validation.
39
+ def validate(data)
40
+ collector = Collector.new
41
+ @root.fields[:root].validate({ root: data }, collector)
42
+ return collector
43
+ end
44
+
45
+ # Validate data for the defined Schema
46
+ #
47
+ # @param data The data to validate.
48
+ # @raise [Schemacop::Exceptions::ValidationError] If the data is invalid,
49
+ # this exception is thrown.
50
+ # @return nil
51
+ def validate!(data)
52
+ collector = validate(data)
53
+
54
+ unless collector.valid?
55
+ fail Exceptions::ValidationError, collector.exception_message
56
+ end
57
+
58
+ return nil
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,18 @@
1
+ class ScopedEnv
2
+ def initialize(delegation_object, methods)
3
+ @delegation_object = delegation_object
4
+ @methods = methods
5
+ end
6
+
7
+ def method_missing(symbol, *args, &block)
8
+ if @methods.include?(symbol)
9
+ @delegation_object.send(symbol, *args, &block)
10
+ else
11
+ super
12
+ end
13
+ end
14
+
15
+ def respond_to_missing?(symbol, include_private = false)
16
+ @methods.include?(symbol) || super
17
+ end
18
+ end
@@ -0,0 +1,30 @@
1
+ module Schemacop
2
+ class ArrayValidator < NodeSupportingType
3
+ register symbols: :array, klasses: Array
4
+
5
+ option :min # Minimal number of elements
6
+ option :max # Maximal number of elements
7
+ option :nil # Whether to allow nil values
8
+
9
+ def initialize(*args)
10
+ super
11
+ type(:nil) if option(:nil)
12
+ end
13
+
14
+ def validate(data, collector)
15
+ validate_custom_check(data, collector)
16
+
17
+ if option?(:min) && data.size < option(:min)
18
+ collector.error "Array must have more (>=) than #{option(:min)} elements."
19
+ end
20
+ if option?(:max) && data.size > option(:max)
21
+ collector.error "Array must have less (<=) than #{option(:max)} elements."
22
+ end
23
+ data.each_with_index do |entry, index|
24
+ collector.path("[#{index}]") do
25
+ validate_types(entry, collector)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,5 @@
1
+ module Schemacop
2
+ class BooleanValidator < Node
3
+ register symbols: :boolean, klasses: [TrueClass, FalseClass]
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ module Schemacop
2
+ class FloatValidator < NumberValidator
3
+ register symbols: :float, klasses: Float
4
+ end
5
+ end
@@ -0,0 +1,18 @@
1
+ module Schemacop
2
+ class HashValidator < NodeSupportingField
3
+ register symbols: :hash, klasses: Hash
4
+
5
+ def validate(data, collector)
6
+ super
7
+
8
+ allowed_fields = @fields.keys
9
+ obsolete_keys = data.keys - allowed_fields
10
+
11
+ collector.error "Obsolete keys: #{obsolete_keys.inspect}." if obsolete_keys.any?
12
+
13
+ @fields.values.each do |field|
14
+ field.validate(data, collector)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,5 @@
1
+ module Schemacop
2
+ class IntegerValidator < NumberValidator
3
+ register symbols: :integer, klasses: Integer
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ module Schemacop
2
+ class NilValidator < Node
3
+ register symbols: :nil, klasses: NilClass
4
+ end
5
+ end
@@ -0,0 +1,19 @@
1
+ module Schemacop
2
+ class NumberValidator < Node
3
+ register symbols: :number, klasses: [Integer, Float]
4
+
5
+ option :min
6
+ option :max
7
+
8
+ def validate(data, collector)
9
+ super
10
+
11
+ if option?(:min) && data < option(:min)
12
+ collector.error "Value must be >= #{option(:min)}."
13
+ end
14
+ if option?(:max) && data > option(:max)
15
+ collector.error "Value must be <= #{option(:max)}."
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,21 @@
1
+ module Schemacop
2
+ class ObjectValidator < Node
3
+ register symbols: :object, klasses: Object
4
+
5
+ option :classes
6
+
7
+ def type_label
8
+ "#{super} (#{classes.join(', ')})"
9
+ end
10
+
11
+ def type_matches?(data)
12
+ super && (classes.empty? || classes.include?(data.class)) && !data.nil?
13
+ end
14
+
15
+ private
16
+
17
+ def classes
18
+ [*option(:classes)]
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,37 @@
1
+ module Schemacop
2
+ class StringValidator < Node
3
+ register symbols: :string, klasses: String
4
+
5
+ option :min
6
+ option :max
7
+
8
+ def initialize(options = {})
9
+ super(options)
10
+
11
+ validate_options!
12
+ end
13
+
14
+ def validate(data, collector)
15
+ super
16
+
17
+ if option?(:min) && data.size < option(:min)
18
+ collector.error "String must be longer (>=) than #{option(:min)} characters."
19
+ end
20
+ if option?(:max) && data.size > option(:max)
21
+ collector.error "String must be shorter (<=) than #{option(:max)} characters."
22
+ end
23
+ end
24
+
25
+ protected
26
+
27
+ def validate_options!
28
+ option_schema = Schema.new :integer, min: 0
29
+
30
+ if option?(:min) && option_schema.invalid?(option(:min))
31
+ fail Exceptions::InvalidSchemaError, 'String option :min must be an integer >= 0.'
32
+ elsif option?(:max) && option_schema.invalid?(option(:max))
33
+ fail Exceptions::InvalidSchemaError, 'String option :max must be an integer >= 0.'
34
+ end
35
+ end
36
+ end
37
+ end
data/schemacop.gemspec CHANGED
@@ -1,18 +1,20 @@
1
1
  # -*- encoding: utf-8 -*-
2
- # stub: schemacop 1.0.2 ruby lib
2
+ # stub: schemacop 2.0.0 ruby lib
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = "schemacop".freeze
6
- s.version = "1.0.2"
6
+ s.version = "2.0.0"
7
7
 
8
8
  s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
9
9
  s.require_paths = ["lib".freeze]
10
10
  s.authors = ["Sitrox".freeze]
11
- s.date = "2016-10-06"
12
- s.files = [".gitignore".freeze, ".releaser_config".freeze, ".rubocop.yml".freeze, ".travis.yml".freeze, ".yardopts".freeze, "CHANGELOG.md".freeze, "Gemfile".freeze, "LICENSE".freeze, "README.md".freeze, "RUBY_VERSION".freeze, "Rakefile".freeze, "VERSION".freeze, "doc/Schemacop.html".freeze, "doc/Schemacop/Exceptions.html".freeze, "doc/Schemacop/Exceptions/Base.html".freeze, "doc/Schemacop/Exceptions/InvalidSchema.html".freeze, "doc/Schemacop/Exceptions/Validation.html".freeze, "doc/Schemacop/MethodValidation.html".freeze, "doc/Schemacop/MethodValidation/ClassMethods.html".freeze, "doc/Schemacop/Validator.html".freeze, "doc/_index.html".freeze, "doc/class_list.html".freeze, "doc/css/common.css".freeze, "doc/css/full_list.css".freeze, "doc/css/style.css".freeze, "doc/file.README.html".freeze, "doc/file_list.html".freeze, "doc/frames.html".freeze, "doc/index.html".freeze, "doc/js/app.js".freeze, "doc/js/full_list.js".freeze, "doc/js/jquery.js".freeze, "doc/method_list.html".freeze, "doc/top-level-namespace.html".freeze, "lib/schemacop.rb".freeze, "lib/schemacop/exceptions.rb".freeze, "lib/schemacop/validator.rb".freeze, "schemacop.gemspec".freeze, "test/schemacop_validator_test.rb".freeze]
11
+ s.date = "2017-05-15"
12
+ s.files = [".gitignore".freeze, ".releaser_config".freeze, ".rubocop.yml".freeze, ".travis.yml".freeze, ".yardopts".freeze, "CHANGELOG.md".freeze, "Gemfile".freeze, "LICENSE".freeze, "README.md".freeze, "RUBY_VERSION".freeze, "Rakefile".freeze, "VERSION".freeze, "doc/Schemacop.html".freeze, "doc/Schemacop/ArrayValidator.html".freeze, "doc/Schemacop/BooleanValidator.html".freeze, "doc/Schemacop/Collector.html".freeze, "doc/Schemacop/Exceptions.html".freeze, "doc/Schemacop/Exceptions/InvalidSchemaError.html".freeze, "doc/Schemacop/Exceptions/ValidationError.html".freeze, "doc/Schemacop/FieldNode.html".freeze, "doc/Schemacop/FloatValidator.html".freeze, "doc/Schemacop/HashValidator.html".freeze, "doc/Schemacop/IntegerValidator.html".freeze, "doc/Schemacop/NilValidator.html".freeze, "doc/Schemacop/Node.html".freeze, "doc/Schemacop/NodeResolver.html".freeze, "doc/Schemacop/NodeSupportingField.html".freeze, "doc/Schemacop/NodeSupportingType.html".freeze, "doc/Schemacop/NodeWithBlock.html".freeze, "doc/Schemacop/NumberValidator.html".freeze, "doc/Schemacop/ObjectValidator.html".freeze, "doc/Schemacop/RootNode.html".freeze, "doc/Schemacop/Schema.html".freeze, "doc/Schemacop/StringValidator.html".freeze, "doc/ScopedEnv.html".freeze, "doc/_index.html".freeze, "doc/class_list.html".freeze, "doc/css/common.css".freeze, "doc/css/full_list.css".freeze, "doc/css/style.css".freeze, "doc/file.README.html".freeze, "doc/file_list.html".freeze, "doc/frames.html".freeze, "doc/index.html".freeze, "doc/inheritance.graphml".freeze, "doc/inheritance.pdf".freeze, "doc/js/app.js".freeze, "doc/js/full_list.js".freeze, "doc/js/jquery.js".freeze, "doc/method_list.html".freeze, "doc/top-level-namespace.html".freeze, "lib/schemacop.rb".freeze, "lib/schemacop/collector.rb".freeze, "lib/schemacop/exceptions.rb".freeze, "lib/schemacop/field_node.rb".freeze, "lib/schemacop/node.rb".freeze, "lib/schemacop/node_resolver.rb".freeze, "lib/schemacop/node_supporting_field.rb".freeze, "lib/schemacop/node_supporting_type.rb".freeze, "lib/schemacop/node_with_block.rb".freeze, "lib/schemacop/root_node.rb".freeze, "lib/schemacop/schema.rb".freeze, "lib/schemacop/scoped_env.rb".freeze, "lib/schemacop/validator/array_validator.rb".freeze, "lib/schemacop/validator/boolean_validator.rb".freeze, "lib/schemacop/validator/float_validator.rb".freeze, "lib/schemacop/validator/hash_validator.rb".freeze, "lib/schemacop/validator/integer_validator.rb".freeze, "lib/schemacop/validator/nil_validator.rb".freeze, "lib/schemacop/validator/number_validator.rb".freeze, "lib/schemacop/validator/object_validator.rb".freeze, "lib/schemacop/validator/string_validator.rb".freeze, "schemacop.gemspec".freeze, "test/custom_check_test.rb".freeze, "test/custom_if_test.rb".freeze, "test/nil_dis_allow_test.rb".freeze, "test/short_forms_test.rb".freeze, "test/test_helper.rb".freeze, "test/types_test.rb".freeze, "test/validator_array_test.rb".freeze, "test/validator_boolean_test.rb".freeze, "test/validator_float_test.rb".freeze, "test/validator_hash_test.rb".freeze, "test/validator_integer_test.rb".freeze, "test/validator_nil_test.rb".freeze, "test/validator_number_test.rb".freeze, "test/validator_object_test.rb".freeze, "test/validator_string_test.rb".freeze]
13
+ s.homepage = "https://github.com/sitrox/schemacop".freeze
14
+ s.licenses = ["MIT".freeze]
13
15
  s.rubygems_version = "2.6.6".freeze
14
16
  s.summary = "Schemacop validates ruby structures consisting of nested hashes and arrays against simple schema definitions.".freeze
15
- s.test_files = ["test/schemacop_validator_test.rb".freeze]
17
+ s.test_files = ["test/custom_check_test.rb".freeze, "test/custom_if_test.rb".freeze, "test/nil_dis_allow_test.rb".freeze, "test/short_forms_test.rb".freeze, "test/test_helper.rb".freeze, "test/types_test.rb".freeze, "test/validator_array_test.rb".freeze, "test/validator_boolean_test.rb".freeze, "test/validator_float_test.rb".freeze, "test/validator_hash_test.rb".freeze, "test/validator_integer_test.rb".freeze, "test/validator_nil_test.rb".freeze, "test/validator_number_test.rb".freeze, "test/validator_object_test.rb".freeze, "test/validator_string_test.rb".freeze]
16
18
 
17
19
  if s.respond_to? :specification_version then
18
20
  s.specification_version = 4
@@ -0,0 +1,86 @@
1
+ require 'test_helper'
2
+
3
+ module Schemacop
4
+ class CustomCheckTest < Minitest::Test
5
+ def test_integer_check_short_form
6
+ s = Schema.new :integer, check: proc { |i| i.even? }
7
+ assert_nil s.validate!(2)
8
+ assert_nil s.validate!(-8)
9
+ assert_nil s.validate!(0)
10
+ assert_verr { s.validate!(1) }
11
+ assert_verr { s.validate!(-7) }
12
+ assert_verr { s.validate!(2.1) }
13
+ end
14
+
15
+ def test_integer_check_with_lambda
16
+ s = Schema.new do
17
+ type :integer, check: ->(i) { i.even? }
18
+ end
19
+
20
+ assert_nil s.validate!(2)
21
+ assert_nil s.validate!(-8)
22
+ assert_nil s.validate!(0)
23
+ assert_verr { s.validate!(1) }
24
+ assert_verr { s.validate!(-7) }
25
+ assert_verr { s.validate!(2.1) }
26
+ end
27
+
28
+ def test_in_type_dsl
29
+ s = Schema.new do
30
+ type :number, check: proc { |x| x == 42 }
31
+ end
32
+ assert_nil s.validate!(42)
33
+ assert_verr { s.validate!(42.1) }
34
+ assert_verr { s.validate!(0) }
35
+ end
36
+
37
+ def test_with_array
38
+ s = Schema.new do
39
+ type :array, check: proc { |a| a.first == 1 } do
40
+ type :integer
41
+ end
42
+ end
43
+ assert_nil s.validate!([1, 2, 3])
44
+ assert_verr { s.validate!([2, 3, 4]) }
45
+ end
46
+
47
+ def test_with_array_nested
48
+ s = Schema.new do
49
+ type :array, check: proc { |a| a.first == 4 } do
50
+ type :integer, check: proc { |i| i >= 2 }
51
+ end
52
+ end
53
+
54
+ assert_nil s.validate!([4, 3, 2])
55
+ assert_verr { s.validate!([3, 2]) }
56
+ assert_verr { s.validate!([4, 1]) }
57
+ end
58
+
59
+ def test_with_hash
60
+ s = Schema.new :hash, check: proc { |h| h.all? { |k, v| k == v } } do
61
+ opt 1, :integer
62
+ opt 'two', :string
63
+ end
64
+ assert_nil s.validate!(1 => 1, 'two' => 'two')
65
+ assert_verr { s.validate!(1 => 2, 'two' => 'two') }
66
+ assert_verr { s.validate!(1 => 1, 'two' => 'one') }
67
+ end
68
+
69
+ def test_mixed_if_check
70
+ s = Schema.new do
71
+ req :first_name,
72
+ :string,
73
+ if: proc { |str| str.start_with?('Sand') },
74
+ check: proc { |str| str == 'Sandy' }
75
+ req :first_name, :string, min: 3
76
+ end
77
+
78
+ assert_nil s.validate!(first_name: 'Bob')
79
+ assert_nil s.validate!(first_name: 'Sandy')
80
+ assert_nil s.validate!(first_name: 'Sansibar')
81
+
82
+ assert_verr { s.validate!(first_name: 'Sandkasten') }
83
+ assert_verr { s.validate!(first_name: 'a') }
84
+ end
85
+ end
86
+ end