schemacop 3.0.15 → 3.0.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +1 -1
- data/.rubocop.yml +3 -0
- data/CHANGELOG.md +20 -0
- data/LICENSE +1 -1
- data/README.md +4 -3
- data/README_V3.md +114 -1
- data/Rakefile +3 -3
- data/VERSION +1 -1
- data/lib/schemacop/v2/collector.rb +1 -1
- data/lib/schemacop/v3/array_node.rb +32 -3
- data/lib/schemacop/v3/global_context.rb +1 -1
- data/lib/schemacop/v3/hash_node.rb +14 -4
- data/lib/schemacop/v3/node.rb +5 -3
- data/lib/schemacop/v3/object_node.rb +1 -1
- data/lib/schemacop/v3.rb +1 -1
- data/lib/schemacop.rb +5 -2
- data/schemacop.gemspec +18 -30
- data/test/unit/schemacop/v2/nil_dis_allow_test.rb +1 -1
- data/test/unit/schemacop/v2/validator_symbol_test.rb +1 -1
- data/test/unit/schemacop/v3/array_node_test.rb +106 -0
- data/test/unit/schemacop/v3/boolean_node_test.rb +1 -1
- data/test/unit/schemacop/v3/global_context_test.rb +9 -9
- data/test/unit/schemacop/v3/hash_node_test.rb +127 -0
- data/test/unit/schemacop/v3/integer_node_test.rb +5 -0
- data/test/unit/schemacop/v3/node_test.rb +8 -0
- data/test/unit/schemacop/v3/number_node_test.rb +5 -0
- data/test/unit/schemacop/v3/string_node_test.rb +4 -0
- data/test/unit/schemacop/v3/symbol_node_test.rb +2 -2
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d7be04fe24124ae7715ad4bf2ac992d97e0e7fbc924df352ddb09094e02ace5d
|
4
|
+
data.tar.gz: c9a21f9cd191d54ad1f56a9434fd47a63a420e4dbe9a890baacfb6a1354b2c1c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 661976d31dc6cfa271cd3347b786e47c7c213f128d36e7431116c5244ae89eff7ad72f25eceead000eb26afd0096bafd39c270f087aea7caac95e23277dc1169
|
7
|
+
data.tar.gz: 18f397c6759b4c801a949e310b0cc8c1938972abc08f9e0a59800dab121c7f028143769157969786e61b931973a5f467379290df7103d480dd0d253bbd0987c6
|
data/.github/workflows/ruby.yml
CHANGED
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,25 @@
|
|
1
1
|
# Change log
|
2
2
|
|
3
|
+
## 3.0.18 (2022-07-27)
|
4
|
+
|
5
|
+
* Add option `ignore_obsolete_properties` to `HashNode` for Schemacop v3
|
6
|
+
|
7
|
+
## 3.0.17 (2022-06-08)
|
8
|
+
|
9
|
+
* Add options `filter` and `reject` to array nodes which allow to filter arrays
|
10
|
+
before they are validated.
|
11
|
+
|
12
|
+
* `#64545`: Fix an issue where `cast_str` in conjunction with `number` notes
|
13
|
+
lead to parsing errors when the given number had a leading zero, e.g. parsing
|
14
|
+
the string `08` lead to an error, as the number was interpreted as an octal
|
15
|
+
string. Numbers are now always being treated as decimal with base 10.
|
16
|
+
|
17
|
+
## 3.0.16 (2021-11-23)
|
18
|
+
|
19
|
+
* Add setting `Schemacop.v3_default_options` which allows to set default node
|
20
|
+
options vor V3 schemas. This is particularly useful for the option `cast_str`
|
21
|
+
to allow string casting globally.
|
22
|
+
|
3
23
|
## 3.0.15 (2021-10-11)
|
4
24
|
|
5
25
|
* Add support for custom string formatters
|
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -14,9 +14,10 @@ Schemacop is tested with the following ruby versions:
|
|
14
14
|
|
15
15
|
* 2.6.2
|
16
16
|
* 2.7.1
|
17
|
-
* 3.0.
|
17
|
+
* 3.0.1
|
18
|
+
* 3.1.0
|
18
19
|
|
19
|
-
Other ruby versions might work but are not covered by our
|
20
|
+
Other ruby versions might work but are not covered by our automated tests.
|
20
21
|
|
21
22
|
## Basic example
|
22
23
|
|
@@ -118,4 +119,4 @@ To run tests:
|
|
118
119
|
|
119
120
|
## Copyright
|
120
121
|
|
121
|
-
Copyright © 2016 -
|
122
|
+
Copyright © 2016 - 2022 Sitrox. See `LICENSE` for further details.
|
data/README_V3.md
CHANGED
@@ -21,6 +21,7 @@
|
|
21
21
|
13. [Reference](#reference)
|
22
22
|
5. [Context](#context)
|
23
23
|
6. [External schemas](#external-schemas)
|
24
|
+
7. [Default options](#default-options)
|
24
25
|
|
25
26
|
## Validation
|
26
27
|
|
@@ -339,6 +340,8 @@ integer can be done.
|
|
339
340
|
When set to `true`, this node also accepts strings that can be casted to an integer, e.g.
|
340
341
|
the values `'-5'` or `'42'`. Please note that you can only validate numbers which
|
341
342
|
are in the `Integer` format. Blank strings will be treated equally as `nil`.
|
343
|
+
Strings will be parsed with base 10, so only decimal numbers are allowed.
|
344
|
+
Leading zeroes will be ignored.
|
342
345
|
|
343
346
|
#### Examples
|
344
347
|
|
@@ -420,7 +423,9 @@ With the various available options, validations on the value of the number can b
|
|
420
423
|
When set to `true`, this node also accepts strings that can be casted to a number, e.g.
|
421
424
|
the values `'0.1'` or `'3.1415'`. Please note that you can only validate numbers which
|
422
425
|
are in the `Integer` or `Float` format, i.e. values like `'1.5r'` or `'(4 + 0i)'` will
|
423
|
-
not work. Blank strings will be treated equally as `nil`.
|
426
|
+
not work. Blank strings will be treated equally as `nil`. Strings will be
|
427
|
+
parsed with base 10, so only decimal numbers are allowed. Leading zeroes will
|
428
|
+
be ignored.
|
424
429
|
|
425
430
|
#### Examples
|
426
431
|
|
@@ -590,6 +595,26 @@ It consists of one or multiple values, which can be validated using arbitrary no
|
|
590
595
|
each other, or if there may be duplicate values. By default, this is false,
|
591
596
|
i.e. duplicate values are allowed
|
592
597
|
|
598
|
+
* `filter`
|
599
|
+
This option allows you to filter an array *before it is validated*. When using
|
600
|
+
casting, this also filters the data returned by the validator. If the given value
|
601
|
+
is a `Symbol`, the method with the given name will be executed on each array
|
602
|
+
item in order to determine whether it is kept. If the given value is a `Proc`,
|
603
|
+
it will be called for each array item to determine whether it is kept. Both
|
604
|
+
functions or Procs are expected to return either `true` or `false`.
|
605
|
+
|
606
|
+
This is the inverse of option `reject`.
|
607
|
+
|
608
|
+
* `reject`
|
609
|
+
This option allows you to filter an array *before it is validated*. When using
|
610
|
+
casting, this also filters the data returned by the validator. If the given value
|
611
|
+
is a `Symbol`, the method with the given name will be executed on each array
|
612
|
+
item in order to determine whether it is removed. If the given value is a `Proc`,
|
613
|
+
it will be called for each array item to determine whether it is removed. Both
|
614
|
+
functions or Procs are expected to return either `true` or `false`.
|
615
|
+
|
616
|
+
This is the inverse of option `filter`.
|
617
|
+
|
593
618
|
#### Contains
|
594
619
|
|
595
620
|
The `array` node features the *contains* node, which you can use with the DSL
|
@@ -765,6 +790,53 @@ schema.validate!([1, 'foo']) # => [1, "foo"]
|
|
765
790
|
schema.validate!([1, :bar]) # => Schemacop::Exceptions::ValidationError: /[1]: Matches 0 definitions but should match exactly 1.
|
766
791
|
```
|
767
792
|
|
793
|
+
#### Filtering
|
794
|
+
|
795
|
+
Using the options `filter` and `reject`, arrays can be filtered. Filtering
|
796
|
+
happens before validation. Both options behave in the same way, with the only
|
797
|
+
difference being that `filter` uses a inclusive approach and `reject` an
|
798
|
+
exclusive (see [filter](https://apidock.com/ruby/Array/filter) and
|
799
|
+
[reject](https://apidock.com/ruby/Array/reject] in the Ruby API, as they behave
|
800
|
+
in a similar manor).
|
801
|
+
|
802
|
+
You can either pass a Symbol which specifies the name of the method that is
|
803
|
+
called on each array item:
|
804
|
+
|
805
|
+
```ruby
|
806
|
+
# FYI: This example requires active_support for the blank? method
|
807
|
+
schema = Schemacop::Schema3.new :array, reject: :blank? do
|
808
|
+
list :string
|
809
|
+
end
|
810
|
+
|
811
|
+
schema.validate!(['', 'foo']) # => ["foo"]
|
812
|
+
```
|
813
|
+
|
814
|
+
You can also pass a proc to `filter` or `reject`:
|
815
|
+
|
816
|
+
```ruby
|
817
|
+
schema = Schemacop::Schema3.new :array, filter: ->(value) { value.is_a?(String) } do
|
818
|
+
list :string
|
819
|
+
end
|
820
|
+
|
821
|
+
schema.validate!(['foo', 42]) # => ["foo"]
|
822
|
+
```
|
823
|
+
|
824
|
+
Note that the given method name or proc should work with all element types that
|
825
|
+
could possibly be in the (unvalidated) array. If a `NoMethodError` is
|
826
|
+
encountered during a single filtering iteration, the element will be left in the
|
827
|
+
array and, in most cases, trigger a validation error later:
|
828
|
+
|
829
|
+
```ruby
|
830
|
+
schema = Schemacop::Schema3.new :array, reject: :zero? do
|
831
|
+
list :integer
|
832
|
+
end
|
833
|
+
|
834
|
+
# In this example, the value 'foo' does not respond to the method `zero?` which
|
835
|
+
# lead to a `NoMethodError` that is caught by Schemacop which in turn leaves the
|
836
|
+
# value in the array.
|
837
|
+
schema.validate!(['foo', 42, 0]) # => Schemacop::Exceptions::ValidationError: /[0]: Invalid type, got type "String", expected "integer".
|
838
|
+
```
|
839
|
+
|
768
840
|
### Hash
|
769
841
|
|
770
842
|
Type: `:hash`\
|
@@ -792,6 +864,13 @@ It consists of key-value-pairs that can be validated using arbitrary nodes.
|
|
792
864
|
* `max_properties`
|
793
865
|
Specifies the (inclusive) maximum number of properties a hash must contain.
|
794
866
|
|
867
|
+
* `ignore_obsolete_properties`
|
868
|
+
Similar to `additional_properties`. If this is set to `true`, all additional
|
869
|
+
properties are allowed (i.e. they pass the validation), but they are removed
|
870
|
+
from the result hash. This is useful e.g. to validate params coming from the
|
871
|
+
controller, as this only allows white-listed params and removes any params
|
872
|
+
which are not whitelisted (i.e. similar to strong params from Rails).
|
873
|
+
|
795
874
|
#### Specifying properties
|
796
875
|
|
797
876
|
Hash nodes support a block in which you can specify the required hash contents.
|
@@ -999,6 +1078,22 @@ schema.validate!({foo: :bar}) # => Schemacop::Exceptions::ValidationError:
|
|
999
1078
|
schema.validate!({Foo: :bar}) # => Schemacop::Exceptions::ValidationError: /: Property name :Foo does not match "^[a-z]+$". /Foo: Invalid type, got type "Symbol", expected "array".
|
1000
1079
|
```
|
1001
1080
|
|
1081
|
+
##### Ignoring obsolete properties
|
1082
|
+
|
1083
|
+
By enabling `ignore_obsolete_properties`, you can filter out any unspecified params,
|
1084
|
+
while still passing validation:
|
1085
|
+
|
1086
|
+
```ruby
|
1087
|
+
# This schema will accept any additional properties, but remove them from the result
|
1088
|
+
schema = Schemacop::Schema3.new :hash, ignore_obsolete_properties: true do
|
1089
|
+
int? :foo
|
1090
|
+
end
|
1091
|
+
|
1092
|
+
schema.validate!({}) # => {}
|
1093
|
+
schema.validate!({foo: :bar}) # => {"foo"=>:bar}
|
1094
|
+
schema.validate!({foo: :bar, baz: 42}) # => {"foo"=>:bar}
|
1095
|
+
```
|
1096
|
+
|
1002
1097
|
##### Dependencies
|
1003
1098
|
|
1004
1099
|
Using the DSL method `dep`, you can specifiy (non-nested) property dependencies:
|
@@ -1449,3 +1544,21 @@ Schemacop::V3::GlobalContext.eager_load!
|
|
1449
1544
|
As mentioned before, you can also use the external schemas without having to
|
1450
1545
|
eager-load them, but if you use the schemas multiple times, it might be better
|
1451
1546
|
to eager-load them on start of your application / script.
|
1547
|
+
|
1548
|
+
## Default options
|
1549
|
+
|
1550
|
+
Using the setting `Schemacop.v3_default_options`, you can specify a hash
|
1551
|
+
containing default options that will be used for every schemacop node (options
|
1552
|
+
not supported by a particular node are automatically ignored). Options passed
|
1553
|
+
directly to a node still take precedence. The setting can be set in an
|
1554
|
+
initializer:
|
1555
|
+
|
1556
|
+
```ruby
|
1557
|
+
# config/initializers/schemacop.rb
|
1558
|
+
Schemacop.v3_default_options = { cast_str: true }.freeze
|
1559
|
+
|
1560
|
+
# Example schema: As cast_str is enabled in the default options, strings will
|
1561
|
+
# automatically be casted where supported.
|
1562
|
+
schema = Schemacop::Schema3.new(:integer)
|
1563
|
+
schema.validate!('42') # => 42
|
1564
|
+
```
|
data/Rakefile
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
task :gemspec do
|
2
2
|
gemspec = Gem::Specification.new do |spec|
|
3
3
|
spec.name = 'schemacop'
|
4
|
-
spec.version =
|
4
|
+
spec.version = File.read('VERSION').chomp
|
5
5
|
spec.authors = ['Sitrox']
|
6
6
|
spec.summary = %(
|
7
7
|
Schemacop validates ruby structures consisting of nested hashes and arrays
|
@@ -24,13 +24,13 @@ task :gemspec do
|
|
24
24
|
spec.add_development_dependency 'minitest'
|
25
25
|
spec.add_development_dependency 'minitest-reporters'
|
26
26
|
spec.add_development_dependency 'colorize'
|
27
|
-
spec.add_development_dependency 'rubocop', '
|
27
|
+
spec.add_development_dependency 'rubocop', '1.24.1'
|
28
28
|
spec.add_development_dependency 'pry'
|
29
29
|
spec.add_development_dependency 'byebug'
|
30
30
|
spec.add_development_dependency 'simplecov', '0.21.2'
|
31
31
|
end
|
32
32
|
|
33
|
-
File.
|
33
|
+
File.write('schemacop.gemspec', gemspec.to_ruby.strip)
|
34
34
|
end
|
35
35
|
|
36
36
|
begin
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.0.
|
1
|
+
3.0.18
|
@@ -60,7 +60,7 @@ module Schemacop::V2
|
|
60
60
|
def exception_message
|
61
61
|
# rubocop:disable Style/StringConcatenation
|
62
62
|
return "Schemacop validation failed:\n" + @exceptions.map do |e|
|
63
|
-
"- #{e[:path].join
|
63
|
+
"- #{e[:path].join}: #{e[:message]}"
|
64
64
|
end.join("\n")
|
65
65
|
# rubocop:enable Style/StringConcatenation
|
66
66
|
end
|
@@ -10,7 +10,7 @@ module Schemacop
|
|
10
10
|
supports_children
|
11
11
|
|
12
12
|
def self.allowed_options
|
13
|
-
super + ATTRIBUTES + %i[additional_items]
|
13
|
+
super + ATTRIBUTES + %i[additional_items reject filter]
|
14
14
|
end
|
15
15
|
|
16
16
|
def self.dsl_methods
|
@@ -80,7 +80,10 @@ module Schemacop
|
|
80
80
|
super_data = super
|
81
81
|
return if super_data.nil?
|
82
82
|
|
83
|
-
#
|
83
|
+
# Preprocess
|
84
|
+
super_data = preprocess_array(super_data)
|
85
|
+
|
86
|
+
# Validate length
|
84
87
|
length = super_data.size
|
85
88
|
|
86
89
|
if options[:min_items] && length < options[:min_items]
|
@@ -163,11 +166,37 @@ module Schemacop
|
|
163
166
|
end
|
164
167
|
end
|
165
168
|
|
166
|
-
return result
|
169
|
+
return preprocess_array(result)
|
167
170
|
end
|
168
171
|
|
169
172
|
protected
|
170
173
|
|
174
|
+
def preprocess_array(value)
|
175
|
+
# Handle filter
|
176
|
+
if options[:filter]
|
177
|
+
block = Proc.new(&options[:filter])
|
178
|
+
|
179
|
+
value = value.filter do |item|
|
180
|
+
block.call(item)
|
181
|
+
rescue NoMethodError
|
182
|
+
true
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
# Handle reject
|
187
|
+
if options[:reject]
|
188
|
+
block = Proc.new(&options[:reject])
|
189
|
+
|
190
|
+
value = value.reject do |item|
|
191
|
+
block.call(item)
|
192
|
+
rescue NoMethodError
|
193
|
+
false
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
return value
|
198
|
+
end
|
199
|
+
|
171
200
|
def list?
|
172
201
|
list_item.present?
|
173
202
|
end
|
@@ -86,7 +86,7 @@ module Schemacop
|
|
86
86
|
begin
|
87
87
|
@current_schemas = []
|
88
88
|
env = ScopedEnv.new(self, DSL_METHODS)
|
89
|
-
env.instance_eval
|
89
|
+
env.instance_eval File.read(path)
|
90
90
|
rescue StandardError => e
|
91
91
|
fail "Could not load schema #{path.inspect}: #{e.message}"
|
92
92
|
end
|
@@ -14,7 +14,7 @@ module Schemacop
|
|
14
14
|
attr_reader :properties
|
15
15
|
|
16
16
|
def self.allowed_options
|
17
|
-
super + ATTRIBUTES - %i[dependencies] + %i[additional_properties]
|
17
|
+
super + ATTRIBUTES - %i[dependencies] + %i[additional_properties ignore_obsolete_properties]
|
18
18
|
end
|
19
19
|
|
20
20
|
def self.dsl_methods
|
@@ -55,8 +55,8 @@ module Schemacop
|
|
55
55
|
end
|
56
56
|
|
57
57
|
json = {}
|
58
|
-
json[:properties] =
|
59
|
-
json[:patternProperties] =
|
58
|
+
json[:properties] = properties.values.map { |p| [p.name, p.as_json] }.to_h if properties.any?
|
59
|
+
json[:patternProperties] = pattern_properties.values.map { |p| [V3.sanitize_exp(p.name), p.as_json] }.to_h if pattern_properties.any?
|
60
60
|
|
61
61
|
# In schemacop, by default, additional properties are not allowed,
|
62
62
|
# the users explicitly need to enable additional properties
|
@@ -141,7 +141,7 @@ module Schemacop
|
|
141
141
|
result.in_path(name) do
|
142
142
|
property_patterns[match]._validate(additional_property, result: result)
|
143
143
|
end
|
144
|
-
|
144
|
+
elsif !options[:ignore_obsolete_properties]
|
145
145
|
result.error "Obsolete property #{name.to_s.inspect}."
|
146
146
|
end
|
147
147
|
elsif options[:additional_properties].is_a?(Node)
|
@@ -235,10 +235,20 @@ module Schemacop
|
|
235
235
|
fail Schemacop::Exceptions::InvalidSchemaError, 'Option "additional_properties" must be a boolean value'
|
236
236
|
end
|
237
237
|
|
238
|
+
# Cannot set additional_properties and ignore_obsolete_properties option to true at the same time
|
239
|
+
if @options[:additional_properties].is_a?(TrueClass) && options[:ignore_obsolete_properties].is_a?(TrueClass)
|
240
|
+
fail Schemacop::Exceptions::InvalidSchemaError, 'Cannot set "additional_properties" and "ignore_obsolete_properties" to true at the same time'
|
241
|
+
end
|
242
|
+
|
238
243
|
# Default the additional_properties option to false if it's not given
|
239
244
|
if @options[:additional_properties].nil?
|
240
245
|
@options[:additional_properties] = false
|
241
246
|
end
|
247
|
+
|
248
|
+
# Default the ignore_obsolete_properties option to false if it's not given
|
249
|
+
if @options[:ignore_obsolete_properties].nil?
|
250
|
+
@options[:ignore_obsolete_properties] = false
|
251
|
+
end
|
242
252
|
end
|
243
253
|
|
244
254
|
def validate_self
|
data/lib/schemacop/v3/node.rb
CHANGED
@@ -30,6 +30,8 @@ module Schemacop
|
|
30
30
|
|
31
31
|
node = klass.new(**options, &block)
|
32
32
|
|
33
|
+
options = Schemacop.v3_default_options.slice(*klass.allowed_options).merge(options)
|
34
|
+
|
33
35
|
if options.delete(:cast_str)
|
34
36
|
format = NodeRegistry.name(klass)
|
35
37
|
one_of_options = {
|
@@ -197,10 +199,10 @@ module Schemacop
|
|
197
199
|
|
198
200
|
# Apply default #
|
199
201
|
if data.nil?
|
200
|
-
if
|
201
|
-
data = default
|
202
|
-
else
|
202
|
+
if default.nil?
|
203
203
|
return nil
|
204
|
+
else
|
205
|
+
data = default
|
204
206
|
end
|
205
207
|
end
|
206
208
|
|
data/lib/schemacop/v3.rb
CHANGED
@@ -9,7 +9,7 @@ module Schemacop
|
|
9
9
|
return exp if exp.is_a?(String)
|
10
10
|
|
11
11
|
_start_slash, caret, exp, dollar, _end_slash, flags = exp.inspect.match(%r{^(/?)(\^)?(.*?)(\$)?(/?)([ixm]*)?$}).captures
|
12
|
-
flags = flags.
|
12
|
+
flags = flags.chars
|
13
13
|
|
14
14
|
if flags.delete('i')
|
15
15
|
exp = "(?i)(#{exp})"
|
data/lib/schemacop.rb
CHANGED
@@ -16,6 +16,9 @@ module Schemacop
|
|
16
16
|
mattr_accessor :string_formatters
|
17
17
|
self.string_formatters = {}
|
18
18
|
|
19
|
+
mattr_accessor :v3_default_options
|
20
|
+
self.v3_default_options = {}
|
21
|
+
|
19
22
|
def self.register_string_formatter(name, pattern:, handler:)
|
20
23
|
name = name.to_s.dasherize.to_sym
|
21
24
|
|
@@ -72,7 +75,7 @@ module Schemacop
|
|
72
75
|
register_string_formatter(
|
73
76
|
:integer,
|
74
77
|
pattern: /^-?[0-9]+$/,
|
75
|
-
handler: ->(value) { Integer(value) }
|
78
|
+
handler: ->(value) { Integer(value, 10) }
|
76
79
|
)
|
77
80
|
|
78
81
|
register_string_formatter(
|
@@ -84,7 +87,7 @@ module Schemacop
|
|
84
87
|
register_string_formatter(
|
85
88
|
:'integer-list',
|
86
89
|
pattern: /^(-?[0-9]+)(,-?[0-9]+)*$/,
|
87
|
-
handler: ->(value) { value.split(',').map(
|
90
|
+
handler: ->(value) { value.split(',').map { |i| Integer(i, 10) } }
|
88
91
|
)
|
89
92
|
|
90
93
|
def self.with_context(context)
|
data/schemacop.gemspec
CHANGED
@@ -1,49 +1,37 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
|
-
# stub: schemacop 3.0.
|
2
|
+
# stub: schemacop 3.0.18 ruby lib
|
3
3
|
|
4
4
|
Gem::Specification.new do |s|
|
5
5
|
s.name = "schemacop".freeze
|
6
|
-
s.version = "3.0.
|
6
|
+
s.version = "3.0.18"
|
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 = "
|
11
|
+
s.date = "2022-07-27"
|
12
12
|
s.files = [".github/workflows/ruby.yml".freeze, ".gitignore".freeze, ".releaser_config".freeze, ".rubocop.yml".freeze, ".yardopts".freeze, "CHANGELOG.md".freeze, "Gemfile".freeze, "LICENSE".freeze, "README.md".freeze, "README_V2.md".freeze, "README_V3.md".freeze, "RUBY_VERSION".freeze, "Rakefile".freeze, "VERSION".freeze, "lib/schemacop.rb".freeze, "lib/schemacop/base_schema.rb".freeze, "lib/schemacop/exceptions.rb".freeze, "lib/schemacop/railtie.rb".freeze, "lib/schemacop/schema.rb".freeze, "lib/schemacop/schema2.rb".freeze, "lib/schemacop/schema3.rb".freeze, "lib/schemacop/scoped_env.rb".freeze, "lib/schemacop/v2.rb".freeze, "lib/schemacop/v2/caster.rb".freeze, "lib/schemacop/v2/collector.rb".freeze, "lib/schemacop/v2/dupper.rb".freeze, "lib/schemacop/v2/field_node.rb".freeze, "lib/schemacop/v2/node.rb".freeze, "lib/schemacop/v2/node_resolver.rb".freeze, "lib/schemacop/v2/node_supporting_field.rb".freeze, "lib/schemacop/v2/node_supporting_type.rb".freeze, "lib/schemacop/v2/node_with_block.rb".freeze, "lib/schemacop/v2/validator/array_validator.rb".freeze, "lib/schemacop/v2/validator/boolean_validator.rb".freeze, "lib/schemacop/v2/validator/float_validator.rb".freeze, "lib/schemacop/v2/validator/hash_validator.rb".freeze, "lib/schemacop/v2/validator/integer_validator.rb".freeze, "lib/schemacop/v2/validator/nil_validator.rb".freeze, "lib/schemacop/v2/validator/number_validator.rb".freeze, "lib/schemacop/v2/validator/object_validator.rb".freeze, "lib/schemacop/v2/validator/string_validator.rb".freeze, "lib/schemacop/v2/validator/symbol_validator.rb".freeze, "lib/schemacop/v3.rb".freeze, "lib/schemacop/v3/all_of_node.rb".freeze, "lib/schemacop/v3/any_of_node.rb".freeze, "lib/schemacop/v3/array_node.rb".freeze, "lib/schemacop/v3/boolean_node.rb".freeze, "lib/schemacop/v3/combination_node.rb".freeze, "lib/schemacop/v3/context.rb".freeze, "lib/schemacop/v3/dsl_scope.rb".freeze, "lib/schemacop/v3/global_context.rb".freeze, "lib/schemacop/v3/hash_node.rb".freeze, "lib/schemacop/v3/integer_node.rb".freeze, "lib/schemacop/v3/is_not_node.rb".freeze, "lib/schemacop/v3/node.rb".freeze, "lib/schemacop/v3/node_registry.rb".freeze, "lib/schemacop/v3/number_node.rb".freeze, "lib/schemacop/v3/numeric_node.rb".freeze, "lib/schemacop/v3/object_node.rb".freeze, "lib/schemacop/v3/one_of_node.rb".freeze, "lib/schemacop/v3/reference_node.rb".freeze, "lib/schemacop/v3/result.rb".freeze, "lib/schemacop/v3/string_node.rb".freeze, "lib/schemacop/v3/symbol_node.rb".freeze, "schemacop.gemspec".freeze, "test/lib/test_helper.rb".freeze, "test/schemas/nested/group.rb".freeze, "test/schemas/user.rb".freeze, "test/unit/schemacop/v2/casting_test.rb".freeze, "test/unit/schemacop/v2/collector_test.rb".freeze, "test/unit/schemacop/v2/custom_check_test.rb".freeze, "test/unit/schemacop/v2/custom_if_test.rb".freeze, "test/unit/schemacop/v2/defaults_test.rb".freeze, "test/unit/schemacop/v2/empty_test.rb".freeze, "test/unit/schemacop/v2/nil_dis_allow_test.rb".freeze, "test/unit/schemacop/v2/node_resolver_test.rb".freeze, "test/unit/schemacop/v2/short_forms_test.rb".freeze, "test/unit/schemacop/v2/types_test.rb".freeze, "test/unit/schemacop/v2/validator_array_test.rb".freeze, "test/unit/schemacop/v2/validator_boolean_test.rb".freeze, "test/unit/schemacop/v2/validator_float_test.rb".freeze, "test/unit/schemacop/v2/validator_hash_test.rb".freeze, "test/unit/schemacop/v2/validator_integer_test.rb".freeze, "test/unit/schemacop/v2/validator_nil_test.rb".freeze, "test/unit/schemacop/v2/validator_number_test.rb".freeze, "test/unit/schemacop/v2/validator_object_test.rb".freeze, "test/unit/schemacop/v2/validator_string_test.rb".freeze, "test/unit/schemacop/v2/validator_symbol_test.rb".freeze, "test/unit/schemacop/v3/all_of_node_test.rb".freeze, "test/unit/schemacop/v3/any_of_node_test.rb".freeze, "test/unit/schemacop/v3/array_node_test.rb".freeze, "test/unit/schemacop/v3/boolean_node_test.rb".freeze, "test/unit/schemacop/v3/global_context_test.rb".freeze, "test/unit/schemacop/v3/hash_node_test.rb".freeze, "test/unit/schemacop/v3/integer_node_test.rb".freeze, "test/unit/schemacop/v3/is_not_node_test.rb".freeze, "test/unit/schemacop/v3/node_test.rb".freeze, "test/unit/schemacop/v3/number_node_test.rb".freeze, "test/unit/schemacop/v3/object_node_test.rb".freeze, "test/unit/schemacop/v3/one_of_node_test.rb".freeze, "test/unit/schemacop/v3/reference_node_test.rb".freeze, "test/unit/schemacop/v3/string_node_test.rb".freeze, "test/unit/schemacop/v3/symbol_node_test.rb".freeze]
|
13
13
|
s.homepage = "https://github.com/sitrox/schemacop".freeze
|
14
14
|
s.licenses = ["MIT".freeze]
|
15
|
-
s.rubygems_version = "3.
|
15
|
+
s.rubygems_version = "3.2.15".freeze
|
16
16
|
s.summary = "Schemacop validates ruby structures consisting of nested hashes and arrays against simple schema definitions.".freeze
|
17
17
|
s.test_files = ["test/lib/test_helper.rb".freeze, "test/schemas/nested/group.rb".freeze, "test/schemas/user.rb".freeze, "test/unit/schemacop/v2/casting_test.rb".freeze, "test/unit/schemacop/v2/collector_test.rb".freeze, "test/unit/schemacop/v2/custom_check_test.rb".freeze, "test/unit/schemacop/v2/custom_if_test.rb".freeze, "test/unit/schemacop/v2/defaults_test.rb".freeze, "test/unit/schemacop/v2/empty_test.rb".freeze, "test/unit/schemacop/v2/nil_dis_allow_test.rb".freeze, "test/unit/schemacop/v2/node_resolver_test.rb".freeze, "test/unit/schemacop/v2/short_forms_test.rb".freeze, "test/unit/schemacop/v2/types_test.rb".freeze, "test/unit/schemacop/v2/validator_array_test.rb".freeze, "test/unit/schemacop/v2/validator_boolean_test.rb".freeze, "test/unit/schemacop/v2/validator_float_test.rb".freeze, "test/unit/schemacop/v2/validator_hash_test.rb".freeze, "test/unit/schemacop/v2/validator_integer_test.rb".freeze, "test/unit/schemacop/v2/validator_nil_test.rb".freeze, "test/unit/schemacop/v2/validator_number_test.rb".freeze, "test/unit/schemacop/v2/validator_object_test.rb".freeze, "test/unit/schemacop/v2/validator_string_test.rb".freeze, "test/unit/schemacop/v2/validator_symbol_test.rb".freeze, "test/unit/schemacop/v3/all_of_node_test.rb".freeze, "test/unit/schemacop/v3/any_of_node_test.rb".freeze, "test/unit/schemacop/v3/array_node_test.rb".freeze, "test/unit/schemacop/v3/boolean_node_test.rb".freeze, "test/unit/schemacop/v3/global_context_test.rb".freeze, "test/unit/schemacop/v3/hash_node_test.rb".freeze, "test/unit/schemacop/v3/integer_node_test.rb".freeze, "test/unit/schemacop/v3/is_not_node_test.rb".freeze, "test/unit/schemacop/v3/node_test.rb".freeze, "test/unit/schemacop/v3/number_node_test.rb".freeze, "test/unit/schemacop/v3/object_node_test.rb".freeze, "test/unit/schemacop/v3/one_of_node_test.rb".freeze, "test/unit/schemacop/v3/reference_node_test.rb".freeze, "test/unit/schemacop/v3/string_node_test.rb".freeze, "test/unit/schemacop/v3/symbol_node_test.rb".freeze]
|
18
18
|
|
19
19
|
if s.respond_to? :specification_version then
|
20
20
|
s.specification_version = 4
|
21
|
+
end
|
21
22
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
else
|
35
|
-
s.add_dependency(%q<activesupport>.freeze, [">= 4.0"])
|
36
|
-
s.add_dependency(%q<ruby2_keywords>.freeze, ["= 0.0.4"])
|
37
|
-
s.add_dependency(%q<bundler>.freeze, [">= 0"])
|
38
|
-
s.add_dependency(%q<rake>.freeze, [">= 0"])
|
39
|
-
s.add_dependency(%q<minitest>.freeze, [">= 0"])
|
40
|
-
s.add_dependency(%q<minitest-reporters>.freeze, [">= 0"])
|
41
|
-
s.add_dependency(%q<colorize>.freeze, [">= 0"])
|
42
|
-
s.add_dependency(%q<rubocop>.freeze, ["= 0.92.0"])
|
43
|
-
s.add_dependency(%q<pry>.freeze, [">= 0"])
|
44
|
-
s.add_dependency(%q<byebug>.freeze, [">= 0"])
|
45
|
-
s.add_dependency(%q<simplecov>.freeze, ["= 0.21.2"])
|
46
|
-
end
|
23
|
+
if s.respond_to? :add_runtime_dependency then
|
24
|
+
s.add_runtime_dependency(%q<activesupport>.freeze, [">= 4.0"])
|
25
|
+
s.add_runtime_dependency(%q<ruby2_keywords>.freeze, ["= 0.0.4"])
|
26
|
+
s.add_development_dependency(%q<bundler>.freeze, [">= 0"])
|
27
|
+
s.add_development_dependency(%q<rake>.freeze, [">= 0"])
|
28
|
+
s.add_development_dependency(%q<minitest>.freeze, [">= 0"])
|
29
|
+
s.add_development_dependency(%q<minitest-reporters>.freeze, [">= 0"])
|
30
|
+
s.add_development_dependency(%q<colorize>.freeze, [">= 0"])
|
31
|
+
s.add_development_dependency(%q<rubocop>.freeze, ["= 1.24.1"])
|
32
|
+
s.add_development_dependency(%q<pry>.freeze, [">= 0"])
|
33
|
+
s.add_development_dependency(%q<byebug>.freeze, [">= 0"])
|
34
|
+
s.add_development_dependency(%q<simplecov>.freeze, ["= 0.21.2"])
|
47
35
|
else
|
48
36
|
s.add_dependency(%q<activesupport>.freeze, [">= 4.0"])
|
49
37
|
s.add_dependency(%q<ruby2_keywords>.freeze, ["= 0.0.4"])
|
@@ -52,7 +40,7 @@ Gem::Specification.new do |s|
|
|
52
40
|
s.add_dependency(%q<minitest>.freeze, [">= 0"])
|
53
41
|
s.add_dependency(%q<minitest-reporters>.freeze, [">= 0"])
|
54
42
|
s.add_dependency(%q<colorize>.freeze, [">= 0"])
|
55
|
-
s.add_dependency(%q<rubocop>.freeze, ["=
|
43
|
+
s.add_dependency(%q<rubocop>.freeze, ["= 1.24.1"])
|
56
44
|
s.add_dependency(%q<pry>.freeze, [">= 0"])
|
57
45
|
s.add_dependency(%q<byebug>.freeze, [">= 0"])
|
58
46
|
s.add_dependency(%q<simplecov>.freeze, ["= 0.21.2"])
|
@@ -462,6 +462,112 @@ module Schemacop
|
|
462
462
|
end
|
463
463
|
end
|
464
464
|
|
465
|
+
def test_reject_with_symbol
|
466
|
+
schema :array, min_items: 3, max_items: 3, reject: :blank? do
|
467
|
+
list :symbol
|
468
|
+
end
|
469
|
+
|
470
|
+
input = [:foo, :bar, :baz, :'']
|
471
|
+
input_was = input.dup
|
472
|
+
|
473
|
+
assert_validation(input)
|
474
|
+
assert_cast(input, %i[foo bar baz])
|
475
|
+
|
476
|
+
assert_equal input, input_was
|
477
|
+
end
|
478
|
+
|
479
|
+
def test_reject_with_proc
|
480
|
+
schema :array, reject: ->(i) { i > 5 } do
|
481
|
+
list :integer, maximum: 5
|
482
|
+
end
|
483
|
+
|
484
|
+
input = [1, 2, 3, 4, 5, 6]
|
485
|
+
input_was = input.dup
|
486
|
+
|
487
|
+
assert_validation(input)
|
488
|
+
assert_cast(input, [1, 2, 3, 4, 5])
|
489
|
+
|
490
|
+
assert_equal input, input_was
|
491
|
+
end
|
492
|
+
|
493
|
+
def test_reject_with_argument_error
|
494
|
+
schema :array, reject: :zero? do
|
495
|
+
list :integer
|
496
|
+
end
|
497
|
+
|
498
|
+
assert_validation([0, 1, 2, :a]) do
|
499
|
+
error '/[2]', 'Invalid type, got type "Symbol", expected "integer".'
|
500
|
+
end
|
501
|
+
end
|
502
|
+
|
503
|
+
def test_filter_with_symbol
|
504
|
+
schema :array, min_items: 3, max_items: 3, filter: :present? do
|
505
|
+
list :symbol
|
506
|
+
end
|
507
|
+
|
508
|
+
input = [:foo, :bar, :baz, :'']
|
509
|
+
input_was = input.dup
|
510
|
+
|
511
|
+
assert_validation(input)
|
512
|
+
assert_cast(input, %i[foo bar baz])
|
513
|
+
|
514
|
+
assert_equal input, input_was
|
515
|
+
end
|
516
|
+
|
517
|
+
def test_filter_with_proc
|
518
|
+
schema :array, filter: ->(i) { i <= 5 } do
|
519
|
+
list :integer, maximum: 5
|
520
|
+
end
|
521
|
+
|
522
|
+
input = [1, 2, 3, 4, 5, 6]
|
523
|
+
input_was = input.dup
|
524
|
+
|
525
|
+
assert_validation(input)
|
526
|
+
assert_cast(input, [1, 2, 3, 4, 5])
|
527
|
+
|
528
|
+
assert_equal input, input_was
|
529
|
+
end
|
530
|
+
|
531
|
+
def test_filter_with_argument_error
|
532
|
+
schema :array, filter: :nonzero? do
|
533
|
+
list :integer
|
534
|
+
end
|
535
|
+
|
536
|
+
assert_validation([0, 1, 2, :a]) do
|
537
|
+
error '/[2]', 'Invalid type, got type "Symbol", expected "integer".'
|
538
|
+
end
|
539
|
+
end
|
540
|
+
|
541
|
+
def test_doc_example_reject_blank
|
542
|
+
# FYI: This example requires active_support for the blank? method
|
543
|
+
schema = Schemacop::Schema3.new :array, reject: :blank? do
|
544
|
+
list :string
|
545
|
+
end
|
546
|
+
|
547
|
+
assert_equal ['foo'], schema.validate!(['', 'foo'])
|
548
|
+
end
|
549
|
+
|
550
|
+
def test_doc_example_filter_proc
|
551
|
+
schema = Schemacop::Schema3.new :array, filter: ->(value) { value.is_a?(String) } do
|
552
|
+
list :string
|
553
|
+
end
|
554
|
+
|
555
|
+
assert_equal ['foo'], schema.validate!(['foo', 42])
|
556
|
+
end
|
557
|
+
|
558
|
+
def test_doc_example_reject_zero
|
559
|
+
schema = Schemacop::Schema3.new :array, reject: :zero? do
|
560
|
+
list :integer
|
561
|
+
end
|
562
|
+
|
563
|
+
assert_raises_with_message(
|
564
|
+
Schemacop::Exceptions::ValidationError,
|
565
|
+
'/[0]: Invalid type, got type "String", expected "integer".'
|
566
|
+
) do
|
567
|
+
schema.validate!(['foo', 42, 0])
|
568
|
+
end
|
569
|
+
end
|
570
|
+
|
465
571
|
def test_contains
|
466
572
|
schema :array do
|
467
573
|
cont :string
|
@@ -5,7 +5,7 @@ module Schemacop
|
|
5
5
|
module V3
|
6
6
|
class BooleanNodeTest < V3Test
|
7
7
|
def self.invalid_type_error(type)
|
8
|
-
type = type.class unless type.
|
8
|
+
type = type.class unless type.instance_of?(Class)
|
9
9
|
"Invalid type, got type \"#{type}\", expected \"boolean\"."
|
10
10
|
end
|
11
11
|
|
@@ -53,9 +53,9 @@ module Schemacop
|
|
53
53
|
def test_file_reload
|
54
54
|
dir = Dir.mktmpdir
|
55
55
|
Schemacop.load_paths << dir
|
56
|
-
|
56
|
+
File.write(File.join(dir, 'foo.rb'), %(schema :string))
|
57
57
|
assert_is_a StringNode, GlobalContext.instance.schema_for('foo')
|
58
|
-
|
58
|
+
File.write(File.join(dir, 'foo.rb'), %(schema :integer))
|
59
59
|
assert_is_a IntegerNode, GlobalContext.instance.schema_for('foo')
|
60
60
|
end
|
61
61
|
|
@@ -63,12 +63,12 @@ module Schemacop
|
|
63
63
|
dir = Dir.mktmpdir
|
64
64
|
Schemacop.load_paths << dir
|
65
65
|
|
66
|
-
|
66
|
+
File.write(File.join(dir, 'foo.rb'), %(schema :string))
|
67
67
|
|
68
68
|
GlobalContext.instance.eager_load!
|
69
69
|
|
70
70
|
assert_is_a StringNode, GlobalContext.instance.schema_for('foo')
|
71
|
-
|
71
|
+
File.write(File.join(dir, 'foo.rb'), %(schema :integer))
|
72
72
|
assert_is_a StringNode, GlobalContext.instance.schema_for('foo')
|
73
73
|
end
|
74
74
|
|
@@ -117,7 +117,7 @@ module Schemacop
|
|
117
117
|
def test_empty_schema
|
118
118
|
dir = Dir.mktmpdir
|
119
119
|
Schemacop.load_paths << dir
|
120
|
-
|
120
|
+
File.write(File.join(dir, 'foo.rb'), %())
|
121
121
|
assert_raises_with_message RuntimeError, /does not define any schema/ do
|
122
122
|
GlobalContext.instance.schema_for('foo')
|
123
123
|
end
|
@@ -126,7 +126,7 @@ module Schemacop
|
|
126
126
|
def test_multiple_schemas
|
127
127
|
dir = Dir.mktmpdir
|
128
128
|
Schemacop.load_paths << dir
|
129
|
-
|
129
|
+
File.write(File.join(dir, 'foo.rb'), %(schema :string\nschema :integer))
|
130
130
|
assert_raises_with_message RuntimeError, /Schema "#{File.join(dir, 'foo.rb')}" defines multiple schemas/ do
|
131
131
|
GlobalContext.instance.schema_for('foo')
|
132
132
|
end
|
@@ -135,7 +135,7 @@ module Schemacop
|
|
135
135
|
def test_invalid_schema
|
136
136
|
dir = Dir.mktmpdir
|
137
137
|
Schemacop.load_paths << dir
|
138
|
-
|
138
|
+
File.write(File.join(dir, 'foo.rb'), %(foobarbaz))
|
139
139
|
|
140
140
|
assert_raises_with_message RuntimeError, /Could not load schema/ do
|
141
141
|
GlobalContext.schema_for('foo')
|
@@ -145,7 +145,7 @@ module Schemacop
|
|
145
145
|
def test_overrides_with_eager_load
|
146
146
|
dir = Dir.mktmpdir
|
147
147
|
Schemacop.load_paths << dir
|
148
|
-
|
148
|
+
File.write(File.join(dir, 'user.rb'), %(schema :string))
|
149
149
|
|
150
150
|
assert_raises_with_message RuntimeError, %r{in both load paths "test/schemas" and "#{dir}"} do
|
151
151
|
GlobalContext.eager_load!
|
@@ -155,7 +155,7 @@ module Schemacop
|
|
155
155
|
def test_overrides_with_lazy_load
|
156
156
|
dir = Dir.mktmpdir
|
157
157
|
Schemacop.load_paths << dir
|
158
|
-
|
158
|
+
File.write(File.join(dir, 'user.rb'), %(schema :string))
|
159
159
|
|
160
160
|
assert_raises_with_message RuntimeError, %r{in both load paths "test/schemas" and "#{dir}"} do
|
161
161
|
GlobalContext.instance.schema_for('user')
|
@@ -1005,6 +1005,133 @@ module Schemacop
|
|
1005
1005
|
assert_validation({ active: '', id: '' })
|
1006
1006
|
assert_cast({ active: '', id: '' }, { active: nil, id: nil }.with_indifferent_access)
|
1007
1007
|
end
|
1008
|
+
|
1009
|
+
def test_ignore_obsolete_properties_true
|
1010
|
+
schema :hash, ignore_obsolete_properties: true do
|
1011
|
+
int? :foo
|
1012
|
+
str? :bar
|
1013
|
+
end
|
1014
|
+
|
1015
|
+
# Some standard validations first
|
1016
|
+
assert_validation({})
|
1017
|
+
assert_validation({ foo: 1 })
|
1018
|
+
assert_validation({ bar: 'baz' })
|
1019
|
+
assert_validation({ foo: 1, bar: 'baz' })
|
1020
|
+
|
1021
|
+
assert_cast({}, {}.with_indifferent_access)
|
1022
|
+
assert_cast({ foo: 1 }, { foo: 1 }.with_indifferent_access)
|
1023
|
+
assert_cast({ bar: 'baz' }, { bar: 'baz' }.with_indifferent_access)
|
1024
|
+
assert_cast({ foo: 1, bar: 'baz' }, { foo: 1, bar: 'baz' }.with_indifferent_access)
|
1025
|
+
|
1026
|
+
# Should allow obsolete properties and remove them from the result
|
1027
|
+
assert_validation({ obsolete_key: 42 })
|
1028
|
+
assert_validation({ foo: 1, obsolete_key: 42 })
|
1029
|
+
assert_validation({ bar: 'baz', obsolete_key: 42 })
|
1030
|
+
assert_validation({ foo: 1, bar: 'baz', obsolete_key: 42 })
|
1031
|
+
|
1032
|
+
assert_cast({ obsolete_key: 42 }, {}.with_indifferent_access)
|
1033
|
+
assert_cast({ foo: 1, obsolete_key: 42 }, { foo: 1 }.with_indifferent_access)
|
1034
|
+
assert_cast({ bar: 'baz', obsolete_key: 42 }, { bar: 'baz' }.with_indifferent_access)
|
1035
|
+
assert_cast({ foo: 1, bar: 'baz', obsolete_key: 42 }, { foo: 1, bar: 'baz' }.with_indifferent_access)
|
1036
|
+
end
|
1037
|
+
|
1038
|
+
def test_ignore_obsolete_properties_false
|
1039
|
+
schema :hash, ignore_obsolete_properties: false do
|
1040
|
+
int? :foo
|
1041
|
+
str? :bar
|
1042
|
+
end
|
1043
|
+
|
1044
|
+
# Some standard validations first
|
1045
|
+
assert_validation({})
|
1046
|
+
assert_validation({ foo: 1 })
|
1047
|
+
assert_validation({ bar: 'baz' })
|
1048
|
+
assert_validation({ foo: 1, bar: 'baz' })
|
1049
|
+
|
1050
|
+
assert_cast({}, {}.with_indifferent_access)
|
1051
|
+
assert_cast({ foo: 1 }, { foo: 1 }.with_indifferent_access)
|
1052
|
+
assert_cast({ bar: 'baz' }, { bar: 'baz' }.with_indifferent_access)
|
1053
|
+
assert_cast({ foo: 1, bar: 'baz' }, { foo: 1, bar: 'baz' }.with_indifferent_access)
|
1054
|
+
|
1055
|
+
# Should not allow obsolete properties as the option is set to false
|
1056
|
+
assert_validation({ obsolete_key: 42 }) do
|
1057
|
+
error '/', 'Obsolete property "obsolete_key".'
|
1058
|
+
end
|
1059
|
+
assert_validation({ foo: 1, obsolete_key: 42 }) do
|
1060
|
+
error '/', 'Obsolete property "obsolete_key".'
|
1061
|
+
end
|
1062
|
+
assert_validation({ bar: 'baz', obsolete_key: 42 }) do
|
1063
|
+
error '/', 'Obsolete property "obsolete_key".'
|
1064
|
+
end
|
1065
|
+
assert_validation({ foo: 1, bar: 'baz', obsolete_key: 42 }) do
|
1066
|
+
error '/', 'Obsolete property "obsolete_key".'
|
1067
|
+
end
|
1068
|
+
end
|
1069
|
+
|
1070
|
+
def test_ignore_obsolete_properties_true_and_additional_properties_true
|
1071
|
+
# Cannot set both options to true at the same time
|
1072
|
+
assert_raises_with_message Exceptions::InvalidSchemaError,
|
1073
|
+
'Cannot set "additional_properties" and "ignore_obsolete_properties" to true at the same time' do
|
1074
|
+
schema :hash, ignore_obsolete_properties: true, additional_properties: true
|
1075
|
+
end
|
1076
|
+
end
|
1077
|
+
|
1078
|
+
def test_ignore_obsolete_properties_false_and_additional_properties_true
|
1079
|
+
# This should allow any additional properties and keep them in the hash
|
1080
|
+
schema :hash, ignore_obsolete_properties: false, additional_properties: true do
|
1081
|
+
int? :foo
|
1082
|
+
str? :bar
|
1083
|
+
end
|
1084
|
+
|
1085
|
+
assert_validation({ obsolete_key: 42 })
|
1086
|
+
assert_validation({ foo: 1, obsolete_key: 42 })
|
1087
|
+
assert_validation({ bar: 'baz', obsolete_key: 42 })
|
1088
|
+
assert_validation({ foo: 1, bar: 'baz', obsolete_key: 42 })
|
1089
|
+
|
1090
|
+
assert_cast({ obsolete_key: 42 }, { obsolete_key: 42 }.with_indifferent_access)
|
1091
|
+
assert_cast({ foo: 1, obsolete_key: 42 }, { foo: 1, obsolete_key: 42 }.with_indifferent_access)
|
1092
|
+
assert_cast({ bar: 'baz', obsolete_key: 42 }, { bar: 'baz', obsolete_key: 42 }.with_indifferent_access)
|
1093
|
+
assert_cast({ foo: 1, bar: 'baz', obsolete_key: 42 }, { foo: 1, bar: 'baz', obsolete_key: 42 }.with_indifferent_access)
|
1094
|
+
end
|
1095
|
+
|
1096
|
+
def test_ignore_obsolete_properties_true_and_additional_properties_false
|
1097
|
+
# This should allow any additional properties and keep them in the hash
|
1098
|
+
schema :hash, ignore_obsolete_properties: true, additional_properties: false do
|
1099
|
+
int? :foo
|
1100
|
+
str? :bar
|
1101
|
+
end
|
1102
|
+
|
1103
|
+
# Should allow obsolete properties and remove them from the result
|
1104
|
+
assert_validation({ obsolete_key: 42 })
|
1105
|
+
assert_validation({ foo: 1, obsolete_key: 42 })
|
1106
|
+
assert_validation({ bar: 'baz', obsolete_key: 42 })
|
1107
|
+
assert_validation({ foo: 1, bar: 'baz', obsolete_key: 42 })
|
1108
|
+
|
1109
|
+
assert_cast({ obsolete_key: 42 }, {}.with_indifferent_access)
|
1110
|
+
assert_cast({ foo: 1, obsolete_key: 42 }, { foo: 1 }.with_indifferent_access)
|
1111
|
+
assert_cast({ bar: 'baz', obsolete_key: 42 }, { bar: 'baz' }.with_indifferent_access)
|
1112
|
+
assert_cast({ foo: 1, bar: 'baz', obsolete_key: 42 }, { foo: 1, bar: 'baz' }.with_indifferent_access)
|
1113
|
+
end
|
1114
|
+
|
1115
|
+
def test_ignore_obsolete_properties_false_and_additional_properties_false
|
1116
|
+
# This should not allow any additional properties
|
1117
|
+
schema :hash, ignore_obsolete_properties: false, additional_properties: false do
|
1118
|
+
int? :foo
|
1119
|
+
str? :bar
|
1120
|
+
end
|
1121
|
+
|
1122
|
+
assert_validation({ obsolete_key: 42 }) do
|
1123
|
+
error '/', 'Obsolete property "obsolete_key".'
|
1124
|
+
end
|
1125
|
+
assert_validation({ foo: 1, obsolete_key: 42 }) do
|
1126
|
+
error '/', 'Obsolete property "obsolete_key".'
|
1127
|
+
end
|
1128
|
+
assert_validation({ bar: 'baz', obsolete_key: 42 }) do
|
1129
|
+
error '/', 'Obsolete property "obsolete_key".'
|
1130
|
+
end
|
1131
|
+
assert_validation({ foo: 1, bar: 'baz', obsolete_key: 42 }) do
|
1132
|
+
error '/', 'Obsolete property "obsolete_key".'
|
1133
|
+
end
|
1134
|
+
end
|
1008
1135
|
end
|
1009
1136
|
end
|
1010
1137
|
end
|
@@ -181,6 +181,14 @@ module Schemacop
|
|
181
181
|
|
182
182
|
assert_equal(@schema.root.children, [])
|
183
183
|
end
|
184
|
+
|
185
|
+
def test_default_options
|
186
|
+
Schemacop.v3_default_options = { cast_str: true }.freeze
|
187
|
+
schema :number
|
188
|
+
assert_cast('1', 1)
|
189
|
+
ensure
|
190
|
+
Schemacop.v3_default_options = {}
|
191
|
+
end
|
184
192
|
end
|
185
193
|
end
|
186
194
|
end
|
@@ -263,6 +263,10 @@ module Schemacop
|
|
263
263
|
assert_cast '1,-2,3', [1, -2, 3]
|
264
264
|
assert_cast '1', [1]
|
265
265
|
assert_cast '-1', [-1]
|
266
|
+
assert_cast '08', [8]
|
267
|
+
assert_cast '09', [9]
|
268
|
+
assert_cast '050', [50]
|
269
|
+
assert_cast '01,032', [1, 32]
|
266
270
|
end
|
267
271
|
|
268
272
|
def test_format_custom
|
@@ -4,7 +4,7 @@ module Schemacop
|
|
4
4
|
module V3
|
5
5
|
class SymbolNodeTest < V3Test
|
6
6
|
def self.invalid_type_error(type)
|
7
|
-
type = type.class unless type.
|
7
|
+
type = type.class unless type.instance_of?(Class)
|
8
8
|
"Invalid type, got type \"#{type}\", expected \"Symbol\"."
|
9
9
|
end
|
10
10
|
|
@@ -25,7 +25,7 @@ module Schemacop
|
|
25
25
|
def test_required
|
26
26
|
schema :symbol, required: true
|
27
27
|
assert_validation :foo
|
28
|
-
assert_validation
|
28
|
+
assert_validation :""
|
29
29
|
assert_validation nil do
|
30
30
|
error '/', 'Value must be given.'
|
31
31
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: schemacop
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.0.
|
4
|
+
version: 3.0.18
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sitrox
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-07-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -114,14 +114,14 @@ dependencies:
|
|
114
114
|
requirements:
|
115
115
|
- - '='
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version:
|
117
|
+
version: 1.24.1
|
118
118
|
type: :development
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
122
|
- - '='
|
123
123
|
- !ruby/object:Gem::Version
|
124
|
-
version:
|
124
|
+
version: 1.24.1
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
126
|
name: pry
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -292,7 +292,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
292
292
|
- !ruby/object:Gem::Version
|
293
293
|
version: '0'
|
294
294
|
requirements: []
|
295
|
-
rubygems_version: 3.
|
295
|
+
rubygems_version: 3.2.15
|
296
296
|
signing_key:
|
297
297
|
specification_version: 4
|
298
298
|
summary: Schemacop validates ruby structures consisting of nested hashes and arrays
|