schemacop 3.0.3 → 3.0.8

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: 8beb01b4d3fc6d20f2179d2e44086b534d50b673248635d19782fba609737ce3
4
- data.tar.gz: e905b06d0f7bed58cf5a1247a4ec4a201fe053241516aa6269275b87ef41ba31
3
+ metadata.gz: f11e7ce866105fc0749471f503ec88accb8307fdbef31ed417b675e29fa1141e
4
+ data.tar.gz: 400dfe76003e347560eaab180a6df3df073bc8ec1930edad3395331c494ce6e8
5
5
  SHA512:
6
- metadata.gz: 2418e8eacb3854f85b8fa4689d3a4819d4b6ff76aedb0910c5e7b2f41566d15339347e5890e46588f4d8859f79594bd049988d669e9c3486d4bef4db06733fa7
7
- data.tar.gz: 26e0d958b4509fa5376703d17bc00ca05d28fc39fc631a26e2444356065e3c2f80982aa8411b89d197bccafa4a18023aaf3933221be347e1030973e8f64af5e4
6
+ metadata.gz: 5bd90d0c7de2ca4c48626b6410eb8f7711a8ad6e179e1a4f96ac92890da8f2cac113ec495ff1af7335365a0e32ea7f528ce7f141a7973f5c7779615ab84929b7
7
+ data.tar.gz: f6dee225eecc7ae469ac1162f08b2a6108bc5625629077b317e0b378bd6dd953417d6d5b463fdb62ad1ee8a61275a8cca7eabad4862abfff27503b5d998328f5
data/.releaser_config CHANGED
@@ -1,3 +1,4 @@
1
1
  version_file: VERSION
2
2
  always_from_master: true
3
3
  gem_style: github
4
+ ruby_command: ruby -S
data/CHANGELOG.md CHANGED
@@ -1,14 +1,40 @@
1
1
  # Change log
2
2
 
3
- <!--
4
- ## master (unreleased)
3
+ ## 3.0.8 (2021-02-23)
5
4
 
6
- ### New features
5
+ * Fix `object` nodes in hashes with no classes
7
6
 
8
- ### Bug fixes
7
+ * Document `cast_str` option
9
8
 
10
- ### Changes
11
- -->
9
+ ## 3.0.7 (2021-02-22)
10
+
11
+ * Adapt schema definitions handling when using Swagger-standard JSON
12
+
13
+ ## 3.0.6 (2021-02-14)
14
+
15
+ * Remove option `json_format` from {Schemacop::Schema3.as_json as_json} again.
16
+ If you need to use the swagger format, use
17
+ {Schemacop::V3::Context.with_json_format} instead.
18
+
19
+ * Rename `Schemacop::V3::Context.spawn_with` to
20
+ {Schemacop::V3::Context.with_json_format} and make keyword argument
21
+ `json_format` a positional argument.
22
+
23
+ ## 3.0.5 (2021-02-14)
24
+
25
+ * Allow option `pattern` to be a `Regexp` for `string` (`str`) nodes
26
+
27
+ * Remove `examples_keyword` from context again
28
+
29
+ * Add option `json_format` to {Schemacop::Schema3.as_json as_json}. This allows
30
+ generating a JSON schema that is [specific to
31
+ swagger](https://swagger.io/docs/specification/data-models/keywords/) by
32
+ passing `:swagger` to it.
33
+
34
+ ## 3.0.4 (2021-02-15)
35
+
36
+ * Add `examples_keyword` to context which allows to customize the name of the
37
+ `examples` attribute in JSON output
12
38
 
13
39
  ## 3.0.3 (2021-02-15)
14
40
 
data/README_V3.md CHANGED
@@ -199,9 +199,10 @@ transformed into various types.
199
199
  * `max_length`
200
200
  Defines the (inclusive) maximum required string length
201
201
  * `pattern`
202
- Defines a (ruby) regex pattern the value will be matched against. Must be a
203
- string and should generally start with `^` and end with `$` so as to evaluate
204
- the entire string. It should not be enclosed in `/` characters.
202
+ Defines a (ruby) regex pattern the value will be matched against. Must be either
203
+ a string which should not be enclosed in `/` characters, or a Ruby Regexp.
204
+ The pattern should generally start with `^` and end with `$` so as to evaluate
205
+ the entire string.
205
206
  * `format`
206
207
  The `format` option allows for basic semantic validation on certain kinds of
207
208
  string values that are commonly used. See section *formats* for more
@@ -277,6 +278,10 @@ integer can be done.
277
278
  * `multiple_of`
278
279
  The received number has to be a multiple of the given number for the validation to
279
280
  pass.
281
+ * `cast_str`
282
+ When set to `true`, this node also accepts strings that can be casted to an integer, e.g.
283
+ the values `'-5'` or `'42'`. Please note that you can only validate numbers which
284
+ are in the `Integer` format.
280
285
 
281
286
  #### Examples
282
287
 
@@ -293,6 +298,20 @@ schema.validate!((4 + 0i)) # => Schemacop::Exceptions::ValidationError: /:
293
298
  schema.validate!(BigDecimal(5)) # => Schemacop::Exceptions::ValidationError: /: Invalid type, expected "integer".
294
299
  ```
295
300
 
301
+ With `cast_str` enabled:
302
+
303
+ ```ruby
304
+ # Validates that the input is an even number between 0 and 100 (inclusive)
305
+ schema = Schemacop::Schema3.new(:integer, minimum: 0, maximum: 100, multiple_of: 2, cast_str: true)
306
+ schema.validate!('42') # => 42
307
+ schema.validate!('43') # => Schemacop::Exceptions::ValidationError: /: Matches 0 definitions but should match exactly 1.
308
+ schema.validate!('-2') # => Schemacop::Exceptions::ValidationError: /: Matches 0 definitions but should match exactly 1.
309
+ schema.validate!('102') # => Schemacop::Exceptions::ValidationError: /: Matches 0 definitions but should match exactly 1.
310
+ schema.validate!('42.1') # => Schemacop::Exceptions::ValidationError: /: Matches 0 definitions but should match exactly 1.
311
+ schema.validate!('4r') # => Schemacop::Exceptions::ValidationError: /: Matches 0 definitions but should match exactly 1.
312
+ schema.validate!('(4 + 0i)') # => Schemacop::Exceptions::ValidationError: /: Matches 0 definitions but should match exactly 1.
313
+ ```
314
+
296
315
  ### Number
297
316
 
298
317
  Type: `:number`\
@@ -327,6 +346,11 @@ With the various available options, validations on the value of the number can b
327
346
  * `multiple_of`
328
347
  The received number has to be a multiple of the given number for the validation to
329
348
  pass.
349
+ * `cast_str`
350
+ When set to `true`, this node also accepts strings that can be casted to a number, e.g.
351
+ the values `'0.1'` or `'3.1415'`. Please note that you can only validate numbers which
352
+ are in the `Integer` or `Float` format, i.e. values like `'1.5r'` or `'(4 + 0i)'` will
353
+ not work.
330
354
 
331
355
  #### Examples
332
356
 
@@ -343,6 +367,19 @@ schema.validate!(BigDecimal(5)) # => 0.5e1
343
367
  schema.validate!((4 + 0i)) # => Schemacop::Exceptions::ValidationError: /: Invalid type, expected "big_decimal" or "float" or "integer" or "rational".
344
368
  ```
345
369
 
370
+ With `cast_str` enabled:
371
+
372
+ ```ruby
373
+ schema = Schemacop::Schema3.new(:number, cast_str: true, minimum: 0.0, maximum: (50r), multiple_of: BigDecimal('0.5'))
374
+ schema.validate!('42') # => 42
375
+ schema.validate!('42.2') # => Schemacop::Exceptions::ValidationError: /: Matches 0 definitions but should match exactly 1.
376
+ schema.validate!('-2') # => Schemacop::Exceptions::ValidationError: /: Matches 0 definitions but should match exactly 1.
377
+ schema.validate!('51') # => Schemacop::Exceptions::ValidationError: /: Matches 0 definitions but should match exactly 1.
378
+ schema.validate!('42.5') # => 42.5
379
+ schema.validate!('1.5r') # => Schemacop::Exceptions::ValidationError: /: Matches 0 definitions but should match exactly 1.
380
+ schema.validate!('(4 + 0i)') # => Schemacop::Exceptions::ValidationError: /: Matches 0 definitions but should match exactly 1.
381
+ ```
382
+
346
383
  ### Symbol
347
384
 
348
385
  Type: `:symbol`\
@@ -350,15 +387,33 @@ DSL: `sym`
350
387
 
351
388
  The symbol type is used to validate elements for the Ruby `Symbol` class.
352
389
 
390
+ #### Options
391
+
392
+ * `cast_str`
393
+ When set to `true`, this node also accepts strings that can be casted to a symbol.
394
+
353
395
  #### Examples
354
396
 
355
397
  ```ruby
356
398
  # Validates that the input is a symbol
357
399
  schema = Schemacop::Schema3.new(:symbol)
358
- schema.validate!(:foo) # => :foo
359
- schema.validate!('foo') # => Schemacop::Exceptions::ValidationError: /: Invalid type, expected "Symbol".
360
- schema.validate!(123) # => Schemacop::Exceptions::ValidationError: /: Invalid type, expected "Symbol".
361
- schema.validate!(false) # => Schemacop::Exceptions::ValidationError: /: Invalid type, expected "Symbol".
400
+ schema.validate!(:foo) # => :foo
401
+ schema.validate!('foo') # => Schemacop::Exceptions::ValidationError: /: Invalid type, expected "Symbol".
402
+ schema.validate!(123) # => Schemacop::Exceptions::ValidationError: /: Invalid type, expected "Symbol".
403
+ schema.validate!(false) # => Schemacop::Exceptions::ValidationError: /: Invalid type, expected "Symbol".
404
+ schema.validate!(:false) # => :false
405
+ ```
406
+
407
+ With `cast_str` enabled:
408
+
409
+ ```ruby
410
+ # Validates that the input is a symbol
411
+ schema = Schemacop::Schema3.new(:symbol, cast_str: true)
412
+ schema.validate!(':foo') # => :":foo"
413
+ schema.validate!('foo') # => :foo
414
+ schema.validate!('123') # => :"123"
415
+ schema.validate!('false') # => :false
416
+ schema.validate!(':false') # => :":false"
362
417
  ```
363
418
 
364
419
  ### Boolean
@@ -368,6 +423,12 @@ DSL: `boo`
368
423
 
369
424
  The boolean type is used to validate Ruby booleans, i.e. the `TrueClass` and `FalseClass`
370
425
 
426
+ #### Options
427
+
428
+ * `cast_str`
429
+ When set to `true`, this node also accepts strings that can be casted to a boolean, i.e.
430
+ the values `'true'` and `'false'`
431
+
371
432
  #### Examples
372
433
 
373
434
  ```ruby
@@ -380,6 +441,17 @@ schema.validate!('false') # => Schemacop::Exceptions::ValidationError: /: Invali
380
441
  schema.validate!(1234) # => Schemacop::Exceptions::ValidationError: /: Invalid type, expected "boolean".
381
442
  ```
382
443
 
444
+ With `cast_str` enabled:
445
+
446
+ ```ruby
447
+ schema = Schemacop::Schema3.new(:boolean, cast_str: true)
448
+ schema.validate!(true) # => true
449
+ schema.validate!(false) # => false
450
+ schema.validate!(:false) # => Schemacop::Exceptions::ValidationError: /: Matches 0 definitions but should match exactly 1.
451
+ schema.validate!('false') # => false
452
+ schema.validate!(1234) # => Schemacop::Exceptions::ValidationError: /: Matches 0 definitions but should match exactly 1.
453
+ ```
454
+
383
455
  ### Array
384
456
 
385
457
  Type: `:array`\
data/VERSION CHANGED
@@ -1 +1 @@
1
- 3.0.3
1
+ 3.0.8
data/lib/schemacop/v3.rb CHANGED
@@ -3,6 +3,24 @@ module Schemacop
3
3
  def self.register(*args)
4
4
  NodeRegistry.register(*args)
5
5
  end
6
+
7
+ # @private
8
+ def self.sanitize_exp(exp)
9
+ return exp if exp.is_a?(String)
10
+
11
+ _start_slash, caret, exp, dollar, _end_slash, flags = exp.inspect.match(%r{^(/?)(\^)?(.*?)(\$)?(/?)([ixm]*)?$}).captures
12
+ flags = flags.split('')
13
+
14
+ if flags.delete('i')
15
+ exp = "(?i)(#{exp})"
16
+ end
17
+
18
+ if flags.any?
19
+ fail "Flags #{flags.inspect} are not supported by Schemacop."
20
+ end
21
+
22
+ return "#{caret}#{exp}#{dollar}"
23
+ end
6
24
  end
7
25
  end
8
26
 
@@ -19,6 +19,10 @@ module Schemacop
19
19
  default
20
20
  end
21
21
  end
22
+
23
+ def self.allowed_options
24
+ super + %i[cast_str]
25
+ end
22
26
  end
23
27
  end
24
28
  end
@@ -2,9 +2,13 @@ module Schemacop
2
2
  module V3
3
3
  class Context
4
4
  attr_accessor :schemas
5
+ attr_accessor :json_format
5
6
 
6
- def initialize
7
+ DEFAULT_JSON_FORMAT = :default
8
+
9
+ def initialize(json_format: DEFAULT_JSON_FORMAT)
7
10
  @schemas = {}.with_indifferent_access.freeze
11
+ @json_format = json_format
8
12
  end
9
13
 
10
14
  def schema(name, type = :hash, **options, &block)
@@ -12,6 +16,18 @@ module Schemacop
12
16
  name => Node.create(type, **options, &block)
13
17
  ).freeze
14
18
  end
19
+
20
+ def with_json_format(json_format)
21
+ prev_json_format = @json_format
22
+ @json_format = json_format
23
+ return yield
24
+ ensure
25
+ @json_format = prev_json_format
26
+ end
27
+
28
+ def swagger_json?
29
+ @json_format == :swagger
30
+ end
15
31
  end
16
32
  end
17
33
  end
@@ -21,14 +21,6 @@ module Schemacop
21
21
  super + NodeRegistry.dsl_methods(true) + %i[dsl_dep dsl_add]
22
22
  end
23
23
 
24
- def self.sanitize_exp(exp)
25
- exp = exp.to_s
26
- if exp.start_with?('(?-mix:')
27
- exp = exp.to_s.gsub(/^\(\?-mix:/, '').gsub(/\)$/, '')
28
- end
29
- return exp
30
- end
31
-
32
24
  def add_child(node)
33
25
  unless node.name
34
26
  fail Exceptions::InvalidSchemaError, 'Child nodes must have a name.'
@@ -64,7 +56,7 @@ module Schemacop
64
56
 
65
57
  json = {}
66
58
  json[:properties] = Hash[properties.values.map { |p| [p.name, p.as_json] }] if properties.any?
67
- json[:patternProperties] = Hash[pattern_properties.values.map { |p| [self.class.sanitize_exp(p.name), p.as_json] }] if pattern_properties.any?
59
+ json[:patternProperties] = Hash[pattern_properties.values.map { |p| [V3.sanitize_exp(p.name), p.as_json] }] if pattern_properties.any?
68
60
 
69
61
  # In schemacop, by default, additional properties are not allowed,
70
62
  # the users explicitly need to enable additional properties
@@ -48,7 +48,7 @@ module Schemacop
48
48
  end
49
49
 
50
50
  def self.allowed_options
51
- %i[name required default description examples enum parent options cast_str title as]
51
+ %i[name required default description examples enum parent options title as]
52
52
  end
53
53
 
54
54
  def self.dsl_methods
@@ -150,6 +150,10 @@ module Schemacop
150
150
 
151
151
  protected
152
152
 
153
+ def context
154
+ Schemacop.context
155
+ end
156
+
153
157
  def item_matches?(item, data)
154
158
  item_result = Result.new(self)
155
159
  item._validate(data, result: item_result)
@@ -157,12 +161,13 @@ module Schemacop
157
161
  end
158
162
 
159
163
  def process_json(attrs, json)
160
- if @schemas.any?
164
+ if !context.swagger_json? && @schemas.any?
161
165
  json[:definitions] = {}
162
166
  @schemas.each do |name, subschema|
163
167
  json[:definitions][name] = subschema.as_json
164
168
  end
165
169
  end
170
+
166
171
  attrs.each do |attr|
167
172
  if options.include?(attr)
168
173
  json[attr.to_s.camelize(:lower).to_sym] = options[attr]
@@ -170,7 +175,7 @@ module Schemacop
170
175
  end
171
176
 
172
177
  json[:title] = @title if @title
173
- json[:examples] = @examples if @examples
178
+ json[context.swagger_json? ? :example : :examples] = @examples if @examples
174
179
  json[:description] = @description if @description
175
180
  json[:default] = @default if @default
176
181
  json[:enum] = @enum.to_a if @enum
@@ -4,14 +4,32 @@ module Schemacop
4
4
  class NumericNode < Node
5
5
  ATTRIBUTES = %i[
6
6
  minimum
7
- exclusive_minimum
8
7
  maximum
9
- exclusive_maximum
10
8
  multiple_of
9
+ exclusive_minimum
10
+ exclusive_maximum
11
11
  ].freeze
12
12
 
13
13
  def self.allowed_options
14
- super + ATTRIBUTES
14
+ super + ATTRIBUTES + %i[cast_str]
15
+ end
16
+
17
+ def process_json(attrs, json)
18
+ if context.swagger_json?
19
+ if options[:exclusive_minimum]
20
+ json[:minimum] = options[:exclusive_minimum]
21
+ json[:exclusiveMinimum] = true
22
+ end
23
+
24
+ if options[:exclusive_maximum]
25
+ json[:maximum] = options[:exclusive_maximum]
26
+ json[:exclusiveMaximum] = true
27
+ end
28
+
29
+ attrs -= %i[exclusive_minimum exclusive_maximum]
30
+ end
31
+
32
+ super attrs, json
15
33
  end
16
34
 
17
35
  def _validate(data, result:)
@@ -5,11 +5,6 @@ module Schemacop
5
5
  super + %i[classes strict]
6
6
  end
7
7
 
8
- def self.create(classes, **options, &block)
9
- options[:classes] = classes
10
- super(**options, &block)
11
- end
12
-
13
8
  def as_json
14
9
  {} # Not supported by Json Schema
15
10
  end
@@ -11,7 +11,11 @@ module Schemacop
11
11
  end
12
12
 
13
13
  def as_json
14
- process_json([], '$ref': "#/definitions/#{@path}")
14
+ if context.swagger_json?
15
+ process_json([], '$ref': "#/components/schemas/#{@path}")
16
+ else
17
+ process_json([], '$ref': "#/definitions/#{@path}")
18
+ end
15
19
  end
16
20
 
17
21
  def _validate(data, result:)
@@ -4,7 +4,6 @@ module Schemacop
4
4
  ATTRIBUTES = %i[
5
5
  min_length
6
6
  max_length
7
- pattern
8
7
  format
9
8
  ].freeze
10
9
 
@@ -23,7 +22,7 @@ module Schemacop
23
22
  # rubocop:enable Layout/LineLength
24
23
 
25
24
  def self.allowed_options
26
- super + ATTRIBUTES - %i[cast_str] + %i[format_options]
25
+ super + ATTRIBUTES + %i[format_options pattern]
27
26
  end
28
27
 
29
28
  def allowed_types
@@ -31,7 +30,11 @@ module Schemacop
31
30
  end
32
31
 
33
32
  def as_json
34
- process_json(ATTRIBUTES, type: :string)
33
+ json = { type: :string }
34
+ if options[:pattern]
35
+ json[:pattern] = V3.sanitize_exp(Regexp.compile(options[:pattern]))
36
+ end
37
+ process_json(ATTRIBUTES, json)
35
38
  end
36
39
 
37
40
  def _validate(data, result:)
@@ -50,8 +53,14 @@ module Schemacop
50
53
  end
51
54
 
52
55
  # Validate pattern #
53
- if options[:pattern] && !super_data.match?(Regexp.compile(options[:pattern]))
54
- result.error "String does not match pattern #{options[:pattern].inspect}."
56
+ if (pattern = options[:pattern])
57
+ unless options[:pattern].is_a?(Regexp)
58
+ pattern = Regexp.compile(pattern)
59
+ end
60
+
61
+ unless super_data.match?(pattern)
62
+ result.error "String does not match pattern #{V3.sanitize_exp(pattern).inspect}."
63
+ end
55
64
  end
56
65
 
57
66
  # Validate format #
@@ -121,7 +130,9 @@ module Schemacop
121
130
  end
122
131
 
123
132
  if options[:pattern]
124
- fail 'Option "pattern" must be a string.' unless options[:pattern].is_a?(String)
133
+ unless options[:pattern].is_a?(String) || options[:pattern].is_a?(Regexp)
134
+ fail 'Option "pattern" must be a string or Regexp.'
135
+ end
125
136
 
126
137
  begin
127
138
  Regexp.compile(options[:pattern])
@@ -8,6 +8,10 @@ module Schemacop
8
8
  def allowed_types
9
9
  { Symbol => 'Symbol' }
10
10
  end
11
+
12
+ def self.allowed_options
13
+ super + %i[cast_str]
14
+ end
11
15
  end
12
16
  end
13
17
  end
data/schemacop.gemspec CHANGED
@@ -1,49 +1,37 @@
1
1
  # -*- encoding: utf-8 -*-
2
- # stub: schemacop 3.0.3 ruby lib
2
+ # stub: schemacop 3.0.8 ruby lib
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = "schemacop".freeze
6
- s.version = "3.0.3"
6
+ s.version = "3.0.8"
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-02-15"
11
+ s.date = "2021-02-23"
12
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, "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.1.2".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, ["= 0.92.0"])
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"])
@@ -142,6 +142,13 @@ class V3Test < SchemacopTest
142
142
  assert_equal expected_json.as_json, @schema.as_json.as_json
143
143
  end
144
144
 
145
+ def assert_swagger_json(expected_json)
146
+ # TODO: Double "as_json" should not be necessary
147
+ Schemacop.context.with_json_format(:swagger) do
148
+ assert_equal expected_json.as_json, @schema.as_json.as_json
149
+ end
150
+ end
151
+
145
152
  def assert_match_any(array, exp)
146
153
  assert array.any? { |element| element.match?(exp) },
147
154
  "Expected any of #{array.inspect} to match #{exp}."
@@ -73,8 +73,8 @@ module Schemacop
73
73
  hsh { str! :foo }
74
74
  end
75
75
  any_of do
76
- obj(Date)
77
- obj(Time)
76
+ obj classes: Date
77
+ obj classes: Time
78
78
  end
79
79
  ary
80
80
  boo
@@ -136,6 +136,20 @@ module Schemacop
136
136
  assert_cast(false, false)
137
137
  assert_cast(nil, true)
138
138
  end
139
+
140
+ def test_cast_str
141
+ schema :boolean, cast_str: true
142
+
143
+ assert_cast('true', true)
144
+ assert_cast('false', false)
145
+
146
+ assert_cast(true, true)
147
+ assert_cast(false, false)
148
+
149
+ assert_validation('1') do
150
+ error '/', 'Matches 0 definitions but should match exactly 1.'
151
+ end
152
+ end
139
153
  end
140
154
  end
141
155
  end
@@ -125,6 +125,12 @@ module Schemacop
125
125
  exclusiveMinimum: 0
126
126
  )
127
127
 
128
+ assert_swagger_json(
129
+ type: :integer,
130
+ minimum: 0,
131
+ exclusiveMinimum: true
132
+ )
133
+
128
134
  assert_validation 5
129
135
  assert_validation 1
130
136
  assert_validation(0) do
@@ -158,6 +164,12 @@ module Schemacop
158
164
  exclusiveMaximum: 5
159
165
  )
160
166
 
167
+ assert_swagger_json(
168
+ type: :integer,
169
+ maximum: 5,
170
+ exclusiveMaximum: true
171
+ )
172
+
161
173
  assert_validation 4
162
174
  assert_validation 1
163
175
  assert_validation(5) do
@@ -318,6 +330,17 @@ module Schemacop
318
330
  ]
319
331
  })
320
332
  end
333
+
334
+ def test_cast_str
335
+ schema :integer, cast_str: true
336
+
337
+ assert_cast('1', 1)
338
+ assert_cast(1, 1)
339
+
340
+ assert_validation('true') do
341
+ error '/', 'Matches 0 definitions but should match exactly 1.'
342
+ end
343
+ end
321
344
  end
322
345
  end
323
346
  end
@@ -63,6 +63,20 @@ module Schemacop
63
63
  })
64
64
  end
65
65
 
66
+ def test_swagger_example
67
+ schema :string, examples: ['Foo', 'Foo bar']
68
+
69
+ assert_json(
70
+ type: :string,
71
+ examples: ['Foo', 'Foo bar']
72
+ )
73
+
74
+ assert_swagger_json(
75
+ type: :string,
76
+ example: ['Foo', 'Foo bar']
77
+ )
78
+ end
79
+
66
80
  def test_cast_in_root
67
81
  schema :integer, cast_str: true, required: true
68
82
 
@@ -101,6 +101,12 @@ module Schemacop
101
101
  exclusiveMinimum: 0
102
102
  )
103
103
 
104
+ assert_swagger_json(
105
+ type: :number,
106
+ minimum: 0,
107
+ exclusiveMinimum: true
108
+ )
109
+
104
110
  assert_validation 5
105
111
  assert_validation 1
106
112
  assert_validation(0) do
@@ -134,6 +140,12 @@ module Schemacop
134
140
  exclusiveMaximum: 5
135
141
  )
136
142
 
143
+ assert_swagger_json(
144
+ type: :number,
145
+ maximum: 5,
146
+ exclusiveMaximum: true
147
+ )
148
+
137
149
  assert_validation 4
138
150
  assert_validation 1
139
151
  assert_validation(5) do
@@ -287,6 +299,35 @@ module Schemacop
287
299
  ]
288
300
  })
289
301
  end
302
+
303
+ def test_cast_str
304
+ schema :number, cast_str: true, minimum: 0.0, maximum: 50r, multiple_of: BigDecimal('0.5')
305
+
306
+ assert_cast('1', 1)
307
+ assert_cast(1, 1)
308
+
309
+ assert_cast('1.0', 1.0)
310
+ assert_cast(1.0, 1.0)
311
+
312
+ assert_validation('42')
313
+ assert_validation('0.5')
314
+
315
+ assert_validation('true') do
316
+ error '/', 'Matches 0 definitions but should match exactly 1.'
317
+ end
318
+
319
+ assert_validation('51') do
320
+ error '/', 'Matches 0 definitions but should match exactly 1.'
321
+ end
322
+
323
+ assert_validation('-2') do
324
+ error '/', 'Matches 0 definitions but should match exactly 1.'
325
+ end
326
+
327
+ assert_validation('3.1415') do
328
+ error '/', 'Matches 0 definitions but should match exactly 1.'
329
+ end
330
+ end
290
331
  end
291
332
  end
292
333
  end
@@ -59,7 +59,10 @@ module Schemacop
59
59
  end
60
60
 
61
61
  def test_hash
62
- schema { obj! :myobj, String }
62
+ schema do
63
+ obj! :myobj, classes: String
64
+ end
65
+
63
66
  assert_json(
64
67
  type: :object,
65
68
  properties: {
@@ -78,6 +81,16 @@ module Schemacop
78
81
  end
79
82
  end
80
83
 
84
+ def test_hash_no_class
85
+ schema do
86
+ obj! :myobj
87
+ end
88
+
89
+ assert_validation(myobj: 'str')
90
+ assert_validation(myobj: 123)
91
+ assert_validation(myobj: Object.new)
92
+ end
93
+
81
94
  def test_enum_schema
82
95
  schema :object, enum: [true, 'foo', :baz, [], { qux: '123' }]
83
96
 
@@ -80,7 +80,7 @@ module Schemacop
80
80
  end
81
81
  end
82
82
 
83
- def test_pattern
83
+ def test_pattern_as_string
84
84
  schema :string, pattern: '^a_.*_z$'
85
85
 
86
86
  assert_json(type: :string, pattern: '^a_.*_z$')
@@ -95,6 +95,22 @@ module Schemacop
95
95
  end
96
96
  end
97
97
 
98
+ def test_pattern_as_regexp
99
+ schema :string, pattern: /^a_.*_z$/i
100
+
101
+ assert_json(type: :string, pattern: '^(?i)(a_.*_z)$')
102
+
103
+ assert_validation 'a__z'
104
+ assert_validation 'a__Z'
105
+ assert_validation 'a_ foo bar _Z'
106
+ assert_validation '' do
107
+ error '/', 'String does not match pattern "^(?i)(a_.*_z)$".'
108
+ end
109
+ assert_validation 'a_ _zfoo' do
110
+ error '/', 'String does not match pattern "^(?i)(a_.*_z)$".'
111
+ end
112
+ end
113
+
98
114
  def test_format_date
99
115
  schema :string, format: :date
100
116
 
@@ -314,8 +330,8 @@ module Schemacop
314
330
  end
315
331
 
316
332
  assert_raises_with_message Exceptions::InvalidSchemaError,
317
- 'Option "pattern" must be a string.' do
318
- schema :string, pattern: //
333
+ 'Option "pattern" must be a string or Regexp.' do
334
+ schema :string, pattern: 42
319
335
  end
320
336
 
321
337
  assert_raises_with_message Exceptions::InvalidSchemaError,
@@ -70,6 +70,20 @@ module Schemacop
70
70
  error '/', 'Value not included in enum [1, 2, "foo", :bar, {:qux=>42}].'
71
71
  end
72
72
  end
73
+
74
+ # rubocop:disable Lint/BooleanSymbol
75
+ def test_cast_str
76
+ schema :symbol, cast_str: true
77
+
78
+ assert_cast('true', :true)
79
+ assert_cast('foo', :foo)
80
+ assert_cast('1', :'1')
81
+
82
+ assert_cast(:true, :true)
83
+ assert_cast(:foo, :foo)
84
+ assert_cast(:'1', :'1')
85
+ end
86
+ # rubocop:enable Lint/BooleanSymbol
73
87
  end
74
88
  end
75
89
  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.3
4
+ version: 3.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sitrox
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-02-15 00:00:00.000000000 Z
11
+ date: 2021-02-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -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.1.2
296
296
  signing_key:
297
297
  specification_version: 4
298
298
  summary: Schemacop validates ruby structures consisting of nested hashes and arrays