schemacop 1.0.2 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -1
- data/.rubocop.yml +59 -1
- data/CHANGELOG.md +10 -0
- data/README.md +389 -199
- data/Rakefile +2 -0
- data/VERSION +1 -1
- data/doc/Schemacop.html +41 -130
- data/doc/Schemacop/ArrayValidator.html +329 -0
- data/doc/Schemacop/BooleanValidator.html +145 -0
- data/doc/Schemacop/Collector.html +535 -0
- data/doc/Schemacop/Exceptions.html +39 -39
- data/doc/Schemacop/Exceptions/InvalidSchemaError.html +124 -0
- data/doc/Schemacop/Exceptions/ValidationError.html +124 -0
- data/doc/Schemacop/FieldNode.html +409 -0
- data/doc/Schemacop/FloatValidator.html +158 -0
- data/doc/Schemacop/HashValidator.html +263 -0
- data/doc/Schemacop/IntegerValidator.html +158 -0
- data/doc/Schemacop/NilValidator.html +145 -0
- data/doc/Schemacop/Node.html +1426 -0
- data/doc/Schemacop/NodeResolver.html +242 -0
- data/doc/Schemacop/NodeSupportingField.html +590 -0
- data/doc/Schemacop/NodeSupportingType.html +614 -0
- data/doc/Schemacop/NodeWithBlock.html +289 -0
- data/doc/Schemacop/NumberValidator.html +232 -0
- data/doc/Schemacop/ObjectValidator.html +288 -0
- data/doc/Schemacop/RootNode.html +171 -0
- data/doc/Schemacop/Schema.html +697 -0
- data/doc/Schemacop/StringValidator.html +295 -0
- data/doc/ScopedEnv.html +351 -0
- data/doc/_index.html +190 -47
- data/doc/class_list.html +24 -31
- data/doc/css/full_list.css +32 -31
- data/doc/css/style.css +244 -91
- data/doc/file.README.html +428 -232
- data/doc/file_list.html +26 -30
- data/doc/frames.html +7 -16
- data/doc/index.html +428 -232
- data/doc/inheritance.graphml +524 -0
- data/doc/inheritance.pdf +825 -0
- data/doc/js/app.js +106 -77
- data/doc/js/full_list.js +170 -135
- data/doc/method_list.html +494 -38
- data/doc/top-level-namespace.html +36 -36
- data/lib/schemacop.rb +22 -7
- data/lib/schemacop/collector.rb +34 -0
- data/lib/schemacop/exceptions.rb +2 -8
- data/lib/schemacop/field_node.rb +26 -0
- data/lib/schemacop/node.rb +127 -0
- data/lib/schemacop/node_resolver.rb +14 -0
- data/lib/schemacop/node_supporting_field.rb +62 -0
- data/lib/schemacop/node_supporting_type.rb +112 -0
- data/lib/schemacop/node_with_block.rb +16 -0
- data/lib/schemacop/root_node.rb +4 -0
- data/lib/schemacop/schema.rb +61 -0
- data/lib/schemacop/scoped_env.rb +18 -0
- data/lib/schemacop/validator/array_validator.rb +30 -0
- data/lib/schemacop/validator/boolean_validator.rb +5 -0
- data/lib/schemacop/validator/float_validator.rb +5 -0
- data/lib/schemacop/validator/hash_validator.rb +18 -0
- data/lib/schemacop/validator/integer_validator.rb +5 -0
- data/lib/schemacop/validator/nil_validator.rb +5 -0
- data/lib/schemacop/validator/number_validator.rb +19 -0
- data/lib/schemacop/validator/object_validator.rb +21 -0
- data/lib/schemacop/validator/string_validator.rb +37 -0
- data/schemacop.gemspec +7 -5
- data/test/custom_check_test.rb +86 -0
- data/test/custom_if_test.rb +95 -0
- data/test/nil_dis_allow_test.rb +41 -0
- data/test/short_forms_test.rb +316 -0
- data/test/test_helper.rb +6 -0
- data/test/types_test.rb +83 -0
- data/test/validator_array_test.rb +97 -0
- data/test/validator_boolean_test.rb +15 -0
- data/test/validator_float_test.rb +57 -0
- data/test/validator_hash_test.rb +71 -0
- data/test/validator_integer_test.rb +46 -0
- data/test/validator_nil_test.rb +13 -0
- data/test/validator_number_test.rb +60 -0
- data/test/validator_object_test.rb +87 -0
- data/test/validator_string_test.rb +76 -0
- metadata +78 -14
- data/doc/Schemacop/Exceptions/Base.html +0 -127
- data/doc/Schemacop/Exceptions/InvalidSchema.html +0 -141
- data/doc/Schemacop/Exceptions/Validation.html +0 -142
- data/doc/Schemacop/MethodValidation.html +0 -120
- data/doc/Schemacop/MethodValidation/ClassMethods.html +0 -196
- data/doc/Schemacop/Validator.html +0 -254
- data/lib/schemacop/validator.rb +0 -145
- 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,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,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,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
|
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 = "
|
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 = "
|
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/
|
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/
|
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
|