schemacop 3.0.15 → 3.0.18

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2e43238e69ebe95beaac85536a9dadbf3233bd4fa5751c7e019ca6d07aa05860
4
- data.tar.gz: 8bafd412f0572e0c12a7c163cba48b6f6f69900ec903684dc3c9495b4913cf52
3
+ metadata.gz: d7be04fe24124ae7715ad4bf2ac992d97e0e7fbc924df352ddb09094e02ace5d
4
+ data.tar.gz: c9a21f9cd191d54ad1f56a9434fd47a63a420e4dbe9a890baacfb6a1354b2c1c
5
5
  SHA512:
6
- metadata.gz: 9da291f938673bf76f55f4f4fddbf5a3355fe9c72ae30f8be8c9e224b9bea2f1a89dbcb2da8312ddbaca09dcd25da5511e904963400633d9ef193014da9ee0ec
7
- data.tar.gz: 21793a6a7f3fc730a123f7ed8ceacde1e930620b77fef63c7e30c919a9e9ebf3372a8a5208dbdf177880e011322f529d04558bd68d363cbfd85b023a1f2ed265
6
+ metadata.gz: 661976d31dc6cfa271cd3347b786e47c7c213f128d36e7431116c5244ae89eff7ad72f25eceead000eb26afd0096bafd39c270f087aea7caac95e23277dc1169
7
+ data.tar.gz: 18f397c6759b4c801a949e310b0cc8c1938972abc08f9e0a59800dab121c7f028143769157969786e61b931973a5f467379290df7103d480dd0d253bbd0987c6
@@ -12,7 +12,7 @@ jobs:
12
12
  strategy:
13
13
  fail-fast: false
14
14
  matrix:
15
- ruby-version: ['2.6.2', '2.7.1', '3.0.1']
15
+ ruby-version: ['2.6.2', '2.7.1', '3.0.1', '3.1.0']
16
16
 
17
17
  steps:
18
18
  - uses: actions/checkout@v2
data/.rubocop.yml CHANGED
@@ -105,4 +105,7 @@ Style/ConditionalAssignment:
105
105
  Enabled: false
106
106
 
107
107
  Style/CaseLikeIf:
108
+ Enabled: false
109
+
110
+ Lint/EmptyClass:
108
111
  Enabled: false
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
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright © 2016 - 2021 Sitrox
3
+ Copyright © 2016 - 2022 Sitrox
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
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.0
17
+ * 3.0.1
18
+ * 3.1.0
18
19
 
19
- Other ruby versions might work but are not covered by our Travis tests.
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 - 2021 Sitrox. See `LICENSE` for further details.
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 = IO.read('VERSION').chomp
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', '0.92.0'
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.open('schemacop.gemspec', 'w') { |f| f.write(gemspec.to_ruby.strip) }
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.15
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('')}: #{e[:message]}"
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
- # Validate length #
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 IO.read(path)
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] = Hash[properties.values.map { |p| [p.name, p.as_json] }] if properties.any?
59
- json[:patternProperties] = Hash[pattern_properties.values.map { |p| [V3.sanitize_exp(p.name), p.as_json] }] if pattern_properties.any?
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
- else
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
@@ -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 !default.nil?
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
 
@@ -12,7 +12,7 @@ module Schemacop
12
12
  protected
13
13
 
14
14
  def allowed_types
15
- Hash[@classes.map { |c| [c, c.name] }]
15
+ @classes.map { |c| [c, c.name] }.to_h
16
16
  end
17
17
 
18
18
  def init
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.split('')
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(&:to_i) }
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.15 ruby lib
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.15"
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 = "2021-10-11"
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.0.3".freeze
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
- if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
23
- s.add_runtime_dependency(%q<activesupport>.freeze, [">= 4.0"])
24
- s.add_runtime_dependency(%q<ruby2_keywords>.freeze, ["= 0.0.4"])
25
- s.add_development_dependency(%q<bundler>.freeze, [">= 0"])
26
- s.add_development_dependency(%q<rake>.freeze, [">= 0"])
27
- s.add_development_dependency(%q<minitest>.freeze, [">= 0"])
28
- s.add_development_dependency(%q<minitest-reporters>.freeze, [">= 0"])
29
- s.add_development_dependency(%q<colorize>.freeze, [">= 0"])
30
- s.add_development_dependency(%q<rubocop>.freeze, ["= 0.92.0"])
31
- s.add_development_dependency(%q<pry>.freeze, [">= 0"])
32
- s.add_development_dependency(%q<byebug>.freeze, [">= 0"])
33
- s.add_development_dependency(%q<simplecov>.freeze, ["= 0.21.2"])
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, ["= 0.92.0"])
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"])
@@ -1,6 +1,6 @@
1
1
  require 'test_helper'
2
2
 
3
- # Note: A test for req and opt is part of validator_hash_test.rb
3
+ # NOTE: A test for req and opt is part of validator_hash_test.rb
4
4
 
5
5
  module Schemacop
6
6
  module V2
@@ -9,7 +9,7 @@ module Schemacop
9
9
  end
10
10
 
11
11
  assert_nothing_raised { s.validate!(:good) }
12
- assert_nothing_raised { s.validate!('-+/'.to_sym) }
12
+ assert_nothing_raised { s.validate!(:'-+/') }
13
13
  assert_verr { s.validate!('bad') }
14
14
  assert_verr { s.validate!(456) }
15
15
  end
@@ -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.class == Class
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
- IO.write(File.join(dir, 'foo.rb'), %(schema :string))
56
+ File.write(File.join(dir, 'foo.rb'), %(schema :string))
57
57
  assert_is_a StringNode, GlobalContext.instance.schema_for('foo')
58
- IO.write(File.join(dir, 'foo.rb'), %(schema :integer))
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
- IO.write(File.join(dir, 'foo.rb'), %(schema :string))
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
- IO.write(File.join(dir, 'foo.rb'), %(schema :integer))
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
- IO.write(File.join(dir, 'foo.rb'), %())
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
- IO.write(File.join(dir, 'foo.rb'), %(schema :string\nschema :integer))
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
- IO.write(File.join(dir, 'foo.rb'), %(foobarbaz))
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
- IO.write(File.join(dir, 'user.rb'), %(schema :string))
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
- IO.write(File.join(dir, 'user.rb'), %(schema :string))
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
@@ -339,6 +339,11 @@ module Schemacop
339
339
  assert_cast('1', 1)
340
340
  assert_cast(1, 1)
341
341
 
342
+ assert_cast('08', 8)
343
+ assert_cast('09', 9)
344
+ assert_cast('050', 50)
345
+ assert_cast('01', 1)
346
+
342
347
  assert_cast(nil, nil)
343
348
  assert_cast('', nil)
344
349
 
@@ -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
@@ -308,6 +308,11 @@ module Schemacop
308
308
  assert_cast('1', 1)
309
309
  assert_cast(1, 1)
310
310
 
311
+ assert_cast('08', 8)
312
+ assert_cast('09', 9)
313
+ assert_cast('050', 50)
314
+ assert_cast('01', 1)
315
+
311
316
  assert_validation(nil)
312
317
  assert_validation('')
313
318
 
@@ -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.class == Class
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 ''.to_sym
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.15
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: 2021-10-11 00:00:00.000000000 Z
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: 0.92.0
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: 0.92.0
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.0.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