schemacop 3.0.38 → 3.1.0
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 +4 -1
- data/CHANGELOG.md +35 -0
- data/Gemfile +1 -1
- data/README.md +8 -7
- data/README_V3.md +54 -5
- data/VERSION +1 -1
- data/lib/schemacop/schema3.rb +2 -2
- data/lib/schemacop/v2/node.rb +1 -1
- data/lib/schemacop/v2/validator/string_validator.rb +1 -1
- data/lib/schemacop/v3/any_of_node.rb +13 -0
- data/lib/schemacop/v3/array_node.rb +2 -3
- data/lib/schemacop/v3/binary_node.rb +75 -0
- data/lib/schemacop/v3/global_context.rb +1 -1
- data/lib/schemacop/v3/hash_node.rb +5 -9
- data/lib/schemacop/v3/node.rb +5 -0
- data/lib/schemacop/v3/numeric_node.rb +2 -2
- data/lib/schemacop/v3/object_node.rb +1 -1
- data/lib/schemacop/v3/one_of_node.rb +14 -1
- data/lib/schemacop/v3/string_node.rb +26 -1
- data/lib/schemacop/v3.rb +2 -0
- data/lib/schemacop.rb +1 -1
- data/schemacop.gemspec +5 -5
- data/test/unit/schemacop/v2/casting_test.rb +1 -1
- data/test/unit/schemacop/v2/custom_check_test.rb +2 -2
- data/test/unit/schemacop/v2/custom_if_test.rb +2 -2
- data/test/unit/schemacop/v3/any_of_node_test.rb +24 -0
- data/test/unit/schemacop/v3/array_node_test.rb +40 -1
- data/test/unit/schemacop/v3/binary_node_test.rb +266 -0
- data/test/unit/schemacop/v3/hash_node_test.rb +1 -1
- data/test/unit/schemacop/v3/integer_node_test.rb +1 -1
- data/test/unit/schemacop/v3/number_node_test.rb +1 -1
- data/test/unit/schemacop/v3/one_of_node_test.rb +23 -0
- data/test/unit/schemacop/v3/string_node_test.rb +69 -1
- metadata +5 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9ef422cfe57686302457be2282f2b8e5f45ccdc79d6cd62597e8308bbb94026e
|
|
4
|
+
data.tar.gz: d45307834a863e1fdfdf616acbb9727fd78db428ce88436c27a67db88a3e802f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1253508e8f7270b6fa5f8f54563e79fa034a97fa8f89334f416d0e4549a5b374a2cdc0b3b4777e15202a7759a275d389a8390d67efd7acbb9114de38e21aceb1
|
|
7
|
+
data.tar.gz: 5aa472bf5a7d1aa37f946cf298b76349ad4faee611491c0ecf1bd377baa1127cfaae668f4a71ad00381a0afa88b5c23d073a3b84018ee5387808ad645766b37a
|
data/.github/workflows/ruby.yml
CHANGED
data/.rubocop.yml
CHANGED
|
@@ -10,7 +10,7 @@ AllCops:
|
|
|
10
10
|
- 'locale/translations.rb'
|
|
11
11
|
- 'lib/scratch.rb'
|
|
12
12
|
- 'schemacop.gemspec'
|
|
13
|
-
|
|
13
|
+
SuggestExtensions: false
|
|
14
14
|
DisplayCopNames: true
|
|
15
15
|
|
|
16
16
|
Style/SignalException:
|
|
@@ -108,4 +108,7 @@ Style/CaseLikeIf:
|
|
|
108
108
|
Enabled: false
|
|
109
109
|
|
|
110
110
|
Lint/EmptyClass:
|
|
111
|
+
Enabled: false
|
|
112
|
+
|
|
113
|
+
Lint/RedundantRequireStatement:
|
|
111
114
|
Enabled: false
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,40 @@
|
|
|
1
1
|
# Change log
|
|
2
2
|
|
|
3
|
+
## 3.1.0 (2026-05-09)
|
|
4
|
+
|
|
5
|
+
* Add option `encoding` to `str` node for Schemacop V3 schemas to validate that
|
|
6
|
+
a string has one of the specified encodings. Accepts a single encoding name or
|
|
7
|
+
an array of encoding names (e.g. `encoding: 'UTF-8'` or
|
|
8
|
+
`encoding: %w[UTF-8 US-ASCII]`).
|
|
9
|
+
|
|
10
|
+
Internal reference: `#143271`.
|
|
11
|
+
|
|
12
|
+
* All strings are now validated for valid encoding (via `valid_encoding?`),
|
|
13
|
+
regardless of whether the `encoding` option is set. Strings with invalid byte
|
|
14
|
+
sequences for their declared encoding will now produce a validation error.
|
|
15
|
+
|
|
16
|
+
Internal reference: `#143271`.
|
|
17
|
+
|
|
18
|
+
* Update RuboCop from 1.24.1 to 1.69.2.
|
|
19
|
+
|
|
20
|
+
* Drop support for all EOL Rubies (2.6.2, 2.7.1, 3.0.1, 3.1.0)
|
|
21
|
+
|
|
22
|
+
* Fix `cast_str` default option causing incorrect casting and validation errors
|
|
23
|
+
when used with combination nodes and array tuples. Numeric-looking strings
|
|
24
|
+
(e.g. `"1"`) were incorrectly cast to integers in schemas where a string type
|
|
25
|
+
was also valid. With this fix, `cast_str` only activates when the value cannot
|
|
26
|
+
be matched natively by another sibling schema.
|
|
27
|
+
|
|
28
|
+
Internal reference: `#149255`.
|
|
29
|
+
|
|
30
|
+
## 3.0.39 (2026-03-26)
|
|
31
|
+
|
|
32
|
+
* Add `BinaryNode` for validating binary data fields such as file uploads.
|
|
33
|
+
Represented as `{ type: 'string', format: 'binary' }` in JSON Schema / OpenAPI
|
|
34
|
+
output. By default accepts `ActionDispatch::Http::UploadedFile`,
|
|
35
|
+
`Rack::Multipart::UploadedFile`, `Tempfile`, and `String`. Custom classes can
|
|
36
|
+
be specified via the `classes` option. DSL: `bin` / `bin!` / `bin?`.
|
|
37
|
+
|
|
3
38
|
## 3.0.38 (2026-02-25)
|
|
4
39
|
|
|
5
40
|
* Fix namespaced schema `$ref` paths in generated JSON. For OpenAPI (swagger)
|
data/Gemfile
CHANGED
data/README.md
CHANGED
|
@@ -12,13 +12,14 @@ use in conjunction with [OpenAPI](https://swagger.io/specification/).
|
|
|
12
12
|
|
|
13
13
|
Schemacop is tested with the following ruby versions:
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
15
|
+
| Schemacop | Ruby |
|
|
16
|
+
|:----------|:------------------------------------------------|
|
|
17
|
+
| >= 3.1.0 | 3.2.0, 3.3.0, 3.4.0, 4.0.0 |
|
|
18
|
+
| >= 3.0.31 | 2.6.2, 2.7.1, 3.0.1, 3.1.0, 3.2.0, 3.3.0, 3.4.0 |
|
|
19
|
+
| >= 3.0.29 | 2.6.2, 2.7.1, 3.0.1, 3.1.0, 3.2.0, 3.3.0 |
|
|
20
|
+
| >= 3.0.23 | 2.6.2, 2.7.1, 3.0.1, 3.1.0, 3.2.0 |
|
|
21
|
+
| >= 3.0.17 | 2.6.2, 2.7.1, 3.0.1, 3.1.0 |
|
|
22
|
+
| <= 3.0.16 | 2.6.2, 2.7.1, 3.0.1 |
|
|
22
23
|
|
|
23
24
|
Other ruby versions might work but are not covered by our automated tests.
|
|
24
25
|
|
data/README_V3.md
CHANGED
|
@@ -14,11 +14,12 @@
|
|
|
14
14
|
6. [Array](#array)
|
|
15
15
|
7. [Hash](#hash)
|
|
16
16
|
8. [Object](#object)
|
|
17
|
-
9. [
|
|
18
|
-
10. [
|
|
19
|
-
11. [
|
|
20
|
-
12. [
|
|
21
|
-
13. [
|
|
17
|
+
9. [Binary](#binary)
|
|
18
|
+
10. [AllOf](#allOf)
|
|
19
|
+
11. [AnyOf](#anyOf)
|
|
20
|
+
12. [OneOf](#oneOf)
|
|
21
|
+
13. [IsNot](#isNot)
|
|
22
|
+
14. [Reference](#reference)
|
|
22
23
|
5. [Context](#context)
|
|
23
24
|
6. [External schemas](#external-schemas)
|
|
24
25
|
7. [Default options](#default-options)
|
|
@@ -223,6 +224,15 @@ transformed into various types.
|
|
|
223
224
|
By default, blank strings are allowed and left as they are when casted (e.g.
|
|
224
225
|
the string `''` is valid). If you want to disallow blank strings, set this
|
|
225
226
|
option to `false`.
|
|
227
|
+
* `encoding`
|
|
228
|
+
Validates the encoding of the string. Accepts a single encoding name or an
|
|
229
|
+
array of encoding names (e.g. `encoding: 'UTF-8'` or
|
|
230
|
+
`encoding: %w[UTF-8 US-ASCII]`). See `Encoding.name_list` for all available
|
|
231
|
+
encoding names.
|
|
232
|
+
|
|
233
|
+
Note that regardless of the `encoding` option, all strings are validated for
|
|
234
|
+
valid encoding using `valid_encoding?`. Strings with invalid byte sequences for
|
|
235
|
+
their declared encoding will always produce a validation error.
|
|
226
236
|
|
|
227
237
|
#### Formats
|
|
228
238
|
|
|
@@ -1290,6 +1300,45 @@ schema.validate!('foo'.html_safe) # => "foo"
|
|
|
1290
1300
|
If you set the `strict` option to `false`, the check is done using `is_a?` instead of
|
|
1291
1301
|
`instance_of?`, which also allows subclasses
|
|
1292
1302
|
|
|
1303
|
+
### Binary
|
|
1304
|
+
|
|
1305
|
+
Type: `:binary`\
|
|
1306
|
+
DSL: `bin`
|
|
1307
|
+
|
|
1308
|
+
The binary type represents binary data fields such as file uploads. It is
|
|
1309
|
+
represented as `{ type: 'string', format: 'binary' }` in JSON Schema / OpenAPI
|
|
1310
|
+
output. At runtime, it validates that the value is an instance of one of the
|
|
1311
|
+
configured classes (using `is_a?`, so subclasses are accepted).
|
|
1312
|
+
|
|
1313
|
+
By default, the node accepts instances of `ActionDispatch::Http::UploadedFile`,
|
|
1314
|
+
`Rack::Multipart::UploadedFile`, `Tempfile`, and `String`. Missing classes (e.g.
|
|
1315
|
+
when not running within Rails) are silently skipped.
|
|
1316
|
+
|
|
1317
|
+
```ruby
|
|
1318
|
+
schema = Schemacop::Schema3.new :binary, classes: [Tempfile, String]
|
|
1319
|
+
|
|
1320
|
+
schema.validate!(nil) # => nil
|
|
1321
|
+
schema.validate!(Tempfile.new('f')) # => #<Tempfile:...>
|
|
1322
|
+
schema.validate!('binary data') # => "binary data"
|
|
1323
|
+
schema.validate!(42) # => Schemacop::Exceptions::ValidationError: /: Invalid type, got type "Integer", expected "String" or "Tempfile".
|
|
1324
|
+
```
|
|
1325
|
+
|
|
1326
|
+
If you want to limit the accepted classes, use the `classes` option:
|
|
1327
|
+
|
|
1328
|
+
```ruby
|
|
1329
|
+
schema = Schemacop::Schema3.new :binary, classes: [Tempfile]
|
|
1330
|
+
|
|
1331
|
+
schema.validate!(nil) # => nil
|
|
1332
|
+
schema.validate!(Tempfile.new('f')) # => #<Tempfile:...>
|
|
1333
|
+
schema.validate!('foo') # => Schemacop::Exceptions::ValidationError: /: Invalid type, got type "String", expected "Tempfile".
|
|
1334
|
+
```
|
|
1335
|
+
|
|
1336
|
+
#### Options
|
|
1337
|
+
|
|
1338
|
+
* `classes`
|
|
1339
|
+
An array of `Class` objects that should be accepted. Must not be empty. If not
|
|
1340
|
+
given, the default classes listed above are used.
|
|
1341
|
+
|
|
1293
1342
|
### AllOf
|
|
1294
1343
|
|
|
1295
1344
|
Type: `:all_of`\
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
3.0
|
|
1
|
+
3.1.0
|
data/lib/schemacop/schema3.rb
CHANGED
data/lib/schemacop/v2/node.rb
CHANGED
|
@@ -88,7 +88,7 @@ module Schemacop
|
|
|
88
88
|
|
|
89
89
|
if option?(:cast) && self.class.klasses.size > 1
|
|
90
90
|
fail Exceptions::InvalidSchemaError,
|
|
91
|
-
"Casting is only allowed for single-value datatypes, but type #{self.class.inspect} has classes "\
|
|
91
|
+
"Casting is only allowed for single-value datatypes, but type #{self.class.inspect} has classes " \
|
|
92
92
|
"#{self.class.klasses.map(&:inspect)}."
|
|
93
93
|
end
|
|
94
94
|
end
|
|
@@ -5,6 +5,19 @@ module Schemacop
|
|
|
5
5
|
:anyOf
|
|
6
6
|
end
|
|
7
7
|
|
|
8
|
+
protected
|
|
9
|
+
|
|
10
|
+
def matches(data)
|
|
11
|
+
all_matches = super
|
|
12
|
+
if all_matches.size > 1
|
|
13
|
+
non_wrappers = all_matches.reject(&:cast_str_wrapper?)
|
|
14
|
+
return non_wrappers if non_wrappers.any?
|
|
15
|
+
end
|
|
16
|
+
all_matches
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
public
|
|
20
|
+
|
|
8
21
|
def _validate(data, result:)
|
|
9
22
|
super_data = super
|
|
10
23
|
return if super_data.nil?
|
|
@@ -156,7 +156,7 @@ module Schemacop
|
|
|
156
156
|
result = []
|
|
157
157
|
|
|
158
158
|
value.each_with_index do |value_item, index|
|
|
159
|
-
if cont_item.present? && item_matches?(cont_item, value_item)
|
|
159
|
+
if cont_item.present? && !cont_item.cast_str_wrapper? && item_matches?(cont_item, value_item)
|
|
160
160
|
result << cont_item.cast(value_item)
|
|
161
161
|
elsif list?
|
|
162
162
|
result << list_item.cast(value_item)
|
|
@@ -168,8 +168,7 @@ module Schemacop
|
|
|
168
168
|
result << value_item
|
|
169
169
|
end
|
|
170
170
|
else
|
|
171
|
-
|
|
172
|
-
result << item.cast(value_item)
|
|
171
|
+
result << items[index].cast(value_item)
|
|
173
172
|
end
|
|
174
173
|
else
|
|
175
174
|
result << value_item
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
module Schemacop
|
|
2
|
+
module V3
|
|
3
|
+
# Node type for binary data fields such as file uploads. Represented as
|
|
4
|
+
# `{ type: 'string', format: 'binary' }` in JSON Schema / OpenAPI output.
|
|
5
|
+
#
|
|
6
|
+
# At runtime, validates that the value is an instance of one of the
|
|
7
|
+
# configured classes (using `is_a?`).
|
|
8
|
+
#
|
|
9
|
+
# Default accepted classes (resolved lazily, missing classes are silently
|
|
10
|
+
# skipped):
|
|
11
|
+
# - `ActionDispatch::Http::UploadedFile`
|
|
12
|
+
# - `Rack::Multipart::UploadedFile`
|
|
13
|
+
# - `Tempfile`
|
|
14
|
+
# - `String`
|
|
15
|
+
#
|
|
16
|
+
# @example Default usage (accepts common upload and binary types)
|
|
17
|
+
# bin! :file
|
|
18
|
+
#
|
|
19
|
+
# @example Restrict to specific classes
|
|
20
|
+
# bin! :file, classes: [ActionDispatch::Http::UploadedFile]
|
|
21
|
+
class BinaryNode < Node
|
|
22
|
+
# Classes that are always available (stdlib).
|
|
23
|
+
DEFAULT_CLASSES = [Tempfile, String].freeze
|
|
24
|
+
|
|
25
|
+
# Optional classes resolved lazily via `safe_constantize` (may not be
|
|
26
|
+
# available outside of Rails/Rack).
|
|
27
|
+
OPTIONAL_CLASS_NAMES = %w[
|
|
28
|
+
ActionDispatch::Http::UploadedFile
|
|
29
|
+
Rack::Multipart::UploadedFile
|
|
30
|
+
].freeze
|
|
31
|
+
|
|
32
|
+
def self.allowed_options
|
|
33
|
+
super + %i[classes]
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def as_json
|
|
37
|
+
process_json([], type: :string, format: :binary)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
protected
|
|
41
|
+
|
|
42
|
+
def init
|
|
43
|
+
@classes = options.delete(:classes)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def allowed_types
|
|
47
|
+
resolved_classes.to_h { |c| [c, c.name] }
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def validate_self
|
|
51
|
+
return unless @classes
|
|
52
|
+
|
|
53
|
+
unless @classes.is_a?(Array)
|
|
54
|
+
fail 'Option "classes" must be an array of classes.'
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
if @classes.empty?
|
|
58
|
+
fail 'Option "classes" must not be empty.'
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
@classes.each do |c|
|
|
62
|
+
unless c.is_a?(Class)
|
|
63
|
+
fail "Option \"classes\" must contain classes, got #{c.inspect}."
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
private
|
|
69
|
+
|
|
70
|
+
def resolved_classes
|
|
71
|
+
@resolved_classes ||= @classes || (OPTIONAL_CLASS_NAMES.map(&:safe_constantize).compact + DEFAULT_CLASSES)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
@@ -97,7 +97,7 @@ module Schemacop
|
|
|
97
97
|
fail "Schema #{path.inspect} does not define any schema."
|
|
98
98
|
when 1
|
|
99
99
|
if @schemas.include?(virtual_path)
|
|
100
|
-
fail "Schema #{virtual_path.to_s.inspect} is defined in both load paths "\
|
|
100
|
+
fail "Schema #{virtual_path.to_s.inspect} is defined in both load paths " \
|
|
101
101
|
"#{@load_paths_by_schemas[virtual_path].inspect} and #{load_path.inspect}."
|
|
102
102
|
end
|
|
103
103
|
|
|
@@ -65,8 +65,8 @@ module Schemacop
|
|
|
65
65
|
end
|
|
66
66
|
|
|
67
67
|
json = {}
|
|
68
|
-
json[:properties] = properties.values.
|
|
69
|
-
json[:patternProperties] = pattern_properties.values.
|
|
68
|
+
json[:properties] = properties.values.to_h { |p| [p.name, p.as_json] } if properties.any?
|
|
69
|
+
json[:patternProperties] = pattern_properties.values.to_h { |p| [V3.sanitize_exp(p.name), p.as_json] } if pattern_properties.any?
|
|
70
70
|
|
|
71
71
|
# In schemacop, by default, additional properties are not allowed,
|
|
72
72
|
# the users explicitly need to enable additional properties
|
|
@@ -300,19 +300,15 @@ module Schemacop
|
|
|
300
300
|
protected
|
|
301
301
|
|
|
302
302
|
def as_json_with_inline_refs(properties, pattern_properties)
|
|
303
|
-
all_of = []
|
|
304
|
-
|
|
305
303
|
# Add each inline ref
|
|
306
|
-
@inline_refs.
|
|
307
|
-
all_of << inline_ref.as_json
|
|
308
|
-
end
|
|
304
|
+
all_of = @inline_refs.map(&:as_json)
|
|
309
305
|
|
|
310
306
|
# Add own properties schema if any direct properties exist
|
|
311
307
|
if properties.any? || pattern_properties.any?
|
|
312
308
|
own_schema = {}
|
|
313
309
|
own_schema[:type] = :object
|
|
314
|
-
own_schema[:properties] = properties.values.
|
|
315
|
-
own_schema[:patternProperties] = pattern_properties.values.
|
|
310
|
+
own_schema[:properties] = properties.values.to_h { |p| [p.name, p.as_json] } if properties.any?
|
|
311
|
+
own_schema[:patternProperties] = pattern_properties.values.to_h { |p| [V3.sanitize_exp(p.name), p.as_json] } if pattern_properties.any?
|
|
316
312
|
|
|
317
313
|
if options[:additional_properties].is_a?(TrueClass)
|
|
318
314
|
own_schema[:additionalProperties] = true
|
data/lib/schemacop/v3/node.rb
CHANGED
|
@@ -45,6 +45,7 @@ module Schemacop
|
|
|
45
45
|
self.node node
|
|
46
46
|
str format: format, format_options: options
|
|
47
47
|
end
|
|
48
|
+
node.instance_variable_set(:@cast_str_wrapper, true)
|
|
48
49
|
end
|
|
49
50
|
|
|
50
51
|
return node
|
|
@@ -136,6 +137,10 @@ module Schemacop
|
|
|
136
137
|
(parent&.schemas || {}).merge(@schemas)
|
|
137
138
|
end
|
|
138
139
|
|
|
140
|
+
def cast_str_wrapper?
|
|
141
|
+
!!@cast_str_wrapper
|
|
142
|
+
end
|
|
143
|
+
|
|
139
144
|
def required?
|
|
140
145
|
@required
|
|
141
146
|
end
|
|
@@ -30,7 +30,7 @@ module Schemacop
|
|
|
30
30
|
attrs -= %i[exclusive_minimum exclusive_maximum]
|
|
31
31
|
end
|
|
32
32
|
|
|
33
|
-
super
|
|
33
|
+
super
|
|
34
34
|
end
|
|
35
35
|
|
|
36
36
|
def _validate(data, result:)
|
|
@@ -102,7 +102,7 @@ module Schemacop
|
|
|
102
102
|
fail 'Option "minimum" can\'t be greater than "maximum".'
|
|
103
103
|
end
|
|
104
104
|
|
|
105
|
-
if options[:exclusive_minimum] && options[:exclusive_maximum]\
|
|
105
|
+
if options[:exclusive_minimum] && options[:exclusive_maximum] \
|
|
106
106
|
&& options[:exclusive_minimum] > options[:exclusive_maximum]
|
|
107
107
|
fail 'Option "exclusive_minimum" can\'t be greater than "exclusive_maximum".'
|
|
108
108
|
end
|
|
@@ -23,12 +23,25 @@ module Schemacop
|
|
|
23
23
|
return item.cast(value)
|
|
24
24
|
end
|
|
25
25
|
|
|
26
|
+
protected
|
|
27
|
+
|
|
28
|
+
def matches(data)
|
|
29
|
+
all_matches = super
|
|
30
|
+
if all_matches.size > 1
|
|
31
|
+
non_wrappers = all_matches.reject(&:cast_str_wrapper?)
|
|
32
|
+
return non_wrappers if non_wrappers.any?
|
|
33
|
+
end
|
|
34
|
+
all_matches
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
public
|
|
38
|
+
|
|
26
39
|
def _validate(data, result:)
|
|
27
40
|
if options[:treat_blank_as_nil] && data.blank? && !data.is_a?(FalseClass)
|
|
28
41
|
data = nil
|
|
29
42
|
end
|
|
30
43
|
|
|
31
|
-
super_data = super
|
|
44
|
+
super_data = super
|
|
32
45
|
return if super_data.nil?
|
|
33
46
|
|
|
34
47
|
matches = matches(super_data)
|
|
@@ -8,7 +8,7 @@ module Schemacop
|
|
|
8
8
|
].freeze
|
|
9
9
|
|
|
10
10
|
def self.allowed_options
|
|
11
|
-
super + ATTRIBUTES + %i[format_options pattern allow_blank]
|
|
11
|
+
super + ATTRIBUTES + %i[format_options pattern allow_blank encoding]
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
def allowed_types
|
|
@@ -55,6 +55,19 @@ module Schemacop
|
|
|
55
55
|
end
|
|
56
56
|
end
|
|
57
57
|
|
|
58
|
+
# Validate encoding matches #
|
|
59
|
+
if options[:encoding]
|
|
60
|
+
allowed_encodings = Array(options[:encoding])
|
|
61
|
+
unless allowed_encodings.include?(super_data.encoding.name)
|
|
62
|
+
result.error "String has encoding #{super_data.encoding.name.inspect} but must be #{allowed_encodings.map(&:inspect).join(' or ')}."
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Validate encoding #
|
|
67
|
+
unless super_data.valid_encoding?
|
|
68
|
+
result.error "String has invalid #{super_data.encoding.name.inspect} encoding."
|
|
69
|
+
end
|
|
70
|
+
|
|
58
71
|
# Validate format #
|
|
59
72
|
if options[:format] && Schemacop.string_formatters.include?(options[:format])
|
|
60
73
|
pattern = Schemacop.string_formatters[options[:format]][:pattern]
|
|
@@ -109,6 +122,18 @@ module Schemacop
|
|
|
109
122
|
fail 'Option "min_length" can\'t be greater than "max_length".'
|
|
110
123
|
end
|
|
111
124
|
|
|
125
|
+
if options[:encoding]
|
|
126
|
+
unless options[:encoding].is_a?(String) || (options[:encoding].is_a?(Array) && options[:encoding].all? { |e| e.is_a?(String) })
|
|
127
|
+
fail 'Option "encoding" must be a string or an array of strings.'
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
Array(options[:encoding]).each do |encoding|
|
|
131
|
+
Encoding.find(encoding)
|
|
132
|
+
rescue ArgumentError
|
|
133
|
+
fail "Option \"encoding\" contains unknown encoding #{encoding.inspect}."
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
112
137
|
if options[:pattern]
|
|
113
138
|
unless options[:pattern].is_a?(String) || options[:pattern].is_a?(Regexp)
|
|
114
139
|
fail 'Option "pattern" must be a string or Regexp.'
|
data/lib/schemacop/v3.rb
CHANGED
|
@@ -39,6 +39,7 @@ require 'schemacop/v3/numeric_node'
|
|
|
39
39
|
require 'schemacop/v3/all_of_node'
|
|
40
40
|
require 'schemacop/v3/any_of_node'
|
|
41
41
|
require 'schemacop/v3/array_node'
|
|
42
|
+
require 'schemacop/v3/binary_node'
|
|
42
43
|
require 'schemacop/v3/boolean_node'
|
|
43
44
|
require 'schemacop/v3/hash_node'
|
|
44
45
|
require 'schemacop/v3/integer_node'
|
|
@@ -54,6 +55,7 @@ require 'schemacop/v3/symbol_node'
|
|
|
54
55
|
Schemacop::V3.register :all_of, :all_of, Schemacop::V3::AllOfNode
|
|
55
56
|
Schemacop::V3.register :any_of, :any_of, Schemacop::V3::AnyOfNode
|
|
56
57
|
Schemacop::V3.register :array, :ary, Schemacop::V3::ArrayNode
|
|
58
|
+
Schemacop::V3.register :binary, :bin, Schemacop::V3::BinaryNode
|
|
57
59
|
Schemacop::V3.register :boolean, :boo, Schemacop::V3::BooleanNode
|
|
58
60
|
Schemacop::V3.register :integer, :int, Schemacop::V3::IntegerNode
|
|
59
61
|
Schemacop::V3.register :is_not, :is_not, Schemacop::V3::IsNotNode
|
data/lib/schemacop.rb
CHANGED
data/schemacop.gemspec
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
|
2
|
-
# stub: schemacop 3.0
|
|
2
|
+
# stub: schemacop 3.1.0 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.1.0".freeze
|
|
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 = "2026-
|
|
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]
|
|
11
|
+
s.date = "2026-05-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/binary_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/binary_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
15
|
s.rubygems_version = "3.5.18".freeze
|
|
16
16
|
s.summary = "Schemacop validates ruby structures consisting of nested hashes and arrays against simple schema definitions.".freeze
|
|
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]
|
|
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/binary_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
|
s.specification_version = 4
|
|
20
20
|
|
|
@@ -75,7 +75,7 @@ module Schemacop
|
|
|
75
75
|
end
|
|
76
76
|
end
|
|
77
77
|
|
|
78
|
-
assert_equal 'Casting is only allowed for single-value datatypes, '\
|
|
78
|
+
assert_equal 'Casting is only allowed for single-value datatypes, ' \
|
|
79
79
|
'but type Schemacop::V2::NumberValidator has classes ["Integer", "Float"].',
|
|
80
80
|
e.message
|
|
81
81
|
end
|
|
@@ -4,7 +4,7 @@ module Schemacop
|
|
|
4
4
|
module V2
|
|
5
5
|
class CustomCheckTest < V2Test
|
|
6
6
|
def test_integer_check_short_form
|
|
7
|
-
s = Schema.new :integer, check: proc
|
|
7
|
+
s = Schema.new :integer, check: proc(&:even?)
|
|
8
8
|
assert_nothing_raised { s.validate!(2) }
|
|
9
9
|
assert_nothing_raised { s.validate!(-8) }
|
|
10
10
|
assert_nothing_raised { s.validate!(0) }
|
|
@@ -22,7 +22,7 @@ module Schemacop
|
|
|
22
22
|
|
|
23
23
|
def test_integer_check_with_lambda
|
|
24
24
|
s = Schema.new do
|
|
25
|
-
type :integer, check:
|
|
25
|
+
type :integer, check: lambda(&:even?)
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
assert_nothing_raised { s.validate!(2) }
|
|
@@ -5,7 +5,7 @@ module Schemacop
|
|
|
5
5
|
class CustomIfTest < V2Test
|
|
6
6
|
def test_allowed_subset_only
|
|
7
7
|
s = Schema.new do
|
|
8
|
-
type :integer, if: proc
|
|
8
|
+
type :integer, if: proc(&:odd?)
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
assert_nothing_raised { s.validate! 5 }
|
|
@@ -15,7 +15,7 @@ module Schemacop
|
|
|
15
15
|
|
|
16
16
|
def test_if_with_multiple_types
|
|
17
17
|
s = Schema.new do
|
|
18
|
-
type :integer, if: proc
|
|
18
|
+
type :integer, if: proc(&:odd?)
|
|
19
19
|
type :string
|
|
20
20
|
end
|
|
21
21
|
|
|
@@ -362,6 +362,30 @@ module Schemacop
|
|
|
362
362
|
schema :any_of
|
|
363
363
|
end
|
|
364
364
|
end
|
|
365
|
+
|
|
366
|
+
# With cast_str as default option, int gets wrapped in a OneOfNode containing
|
|
367
|
+
# [IntegerNode, StringNode(format: :integer)]. In any_of, the first matching
|
|
368
|
+
# schema is used for casting. Since the wrapped int node matches numeric-looking
|
|
369
|
+
# strings (via StringNode(format: :integer)), a string like "1" gets cast to
|
|
370
|
+
# integer 1, even though the plain str branch also matches and the value is
|
|
371
|
+
# already a valid string.
|
|
372
|
+
def test_default_cast_str_with_int_and_str
|
|
373
|
+
Schemacop.v3_default_options = { cast_str: true }.freeze
|
|
374
|
+
|
|
375
|
+
schema :any_of do
|
|
376
|
+
int
|
|
377
|
+
str
|
|
378
|
+
end
|
|
379
|
+
|
|
380
|
+
assert_validation(42)
|
|
381
|
+
assert_validation('hello')
|
|
382
|
+
assert_validation('1')
|
|
383
|
+
assert_cast(42, 42)
|
|
384
|
+
assert_cast('hello', 'hello')
|
|
385
|
+
assert_cast('1', '1')
|
|
386
|
+
ensure
|
|
387
|
+
Schemacop.v3_default_options = {}
|
|
388
|
+
end
|
|
365
389
|
end
|
|
366
390
|
end
|
|
367
391
|
end
|
|
@@ -988,13 +988,52 @@ module Schemacop
|
|
|
988
988
|
end
|
|
989
989
|
|
|
990
990
|
assert_validation('{42]') do
|
|
991
|
-
error '/', /JSON parse error: "((\d+: )?unexpected token at '{42]'|expected object key, got '42]' at line \d+ column \d+)"\./
|
|
991
|
+
error '/', /JSON parse error: "((\d+: )?unexpected token at '{42\]'|expected object key, got '42\]' at line \d+ column \d+)"\./
|
|
992
992
|
end
|
|
993
993
|
|
|
994
994
|
assert_validation('"foo"') do
|
|
995
995
|
error '/', 'Invalid type, got type "String", expected "array".'
|
|
996
996
|
end
|
|
997
997
|
end
|
|
998
|
+
|
|
999
|
+
def test_tuple_cast_with_default_cast_str
|
|
1000
|
+
Schemacop.v3_default_options = { cast_str: true }.freeze
|
|
1001
|
+
|
|
1002
|
+
schema :array do
|
|
1003
|
+
list :array do
|
|
1004
|
+
int
|
|
1005
|
+
str
|
|
1006
|
+
end
|
|
1007
|
+
end
|
|
1008
|
+
|
|
1009
|
+
# String "1" at position 1 (str) must not be cast to integer
|
|
1010
|
+
assert_validation([[1, '1']])
|
|
1011
|
+
assert_cast([[1, '1']], [[1, '1']])
|
|
1012
|
+
|
|
1013
|
+
# String "1" at position 0 (int with cast_str) should be cast to integer
|
|
1014
|
+
assert_validation([%w[1 foo]])
|
|
1015
|
+
assert_cast([%w[1 foo]], [[1, 'foo']])
|
|
1016
|
+
ensure
|
|
1017
|
+
Schemacop.v3_default_options = {}
|
|
1018
|
+
end
|
|
1019
|
+
|
|
1020
|
+
# With cast_str as default option, cont :integer creates a OneOfNode containing
|
|
1021
|
+
# [IntegerNode, StringNode(format: :integer)]. The cont_item takes priority in
|
|
1022
|
+
# casting over the list_item, so numeric-looking strings that match the cont
|
|
1023
|
+
# schema get cast to integers even though the list schema says they are strings.
|
|
1024
|
+
def test_cont_cast_with_default_cast_str
|
|
1025
|
+
Schemacop.v3_default_options = { cast_str: true }.freeze
|
|
1026
|
+
|
|
1027
|
+
schema :array do
|
|
1028
|
+
list :string
|
|
1029
|
+
cont :integer
|
|
1030
|
+
end
|
|
1031
|
+
|
|
1032
|
+
assert_validation(%w[hello 42 world])
|
|
1033
|
+
assert_cast(%w[hello 42 world], %w[hello 42 world])
|
|
1034
|
+
ensure
|
|
1035
|
+
Schemacop.v3_default_options = {}
|
|
1036
|
+
end
|
|
998
1037
|
end
|
|
999
1038
|
end
|
|
1000
1039
|
end
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
|
|
3
|
+
module Schemacop
|
|
4
|
+
module V3
|
|
5
|
+
class BinaryNodeTest < V3Test
|
|
6
|
+
def test_basic
|
|
7
|
+
schema :binary
|
|
8
|
+
|
|
9
|
+
assert_validation nil
|
|
10
|
+
assert_validation Tempfile.new('test')
|
|
11
|
+
assert_validation 'binary string data'
|
|
12
|
+
|
|
13
|
+
assert_json(type: :string, format: :binary)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def test_required
|
|
17
|
+
schema :binary, required: true
|
|
18
|
+
|
|
19
|
+
assert_validation Tempfile.new('test')
|
|
20
|
+
|
|
21
|
+
assert_validation nil do
|
|
22
|
+
error '/', 'Value must be given.'
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
assert_json(type: :string, format: :binary)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def test_type
|
|
29
|
+
schema :binary
|
|
30
|
+
|
|
31
|
+
assert_validation 'foo'
|
|
32
|
+
assert_validation Tempfile.new('test')
|
|
33
|
+
|
|
34
|
+
assert_validation 42 do
|
|
35
|
+
error '/', 'Invalid type, got type "Integer", expected "String" or "Tempfile".'
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
assert_validation true do
|
|
39
|
+
error '/', 'Invalid type, got type "TrueClass", expected "String" or "Tempfile".'
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
assert_validation :foo do
|
|
43
|
+
error '/', 'Invalid type, got type "Symbol", expected "String" or "Tempfile".'
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def test_hash
|
|
48
|
+
schema do
|
|
49
|
+
bin! :attachment
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
assert_json(
|
|
53
|
+
type: :object,
|
|
54
|
+
properties: {
|
|
55
|
+
attachment: { type: :string, format: :binary }
|
|
56
|
+
},
|
|
57
|
+
required: %i[attachment],
|
|
58
|
+
additionalProperties: false
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
assert_validation attachment: Tempfile.new('test')
|
|
62
|
+
assert_validation attachment: 'binary data'
|
|
63
|
+
|
|
64
|
+
assert_validation({}) do
|
|
65
|
+
error '/attachment', 'Value must be given.'
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
assert_validation(attachment: 42) do
|
|
69
|
+
error '/attachment', 'Invalid type, got type "Integer", expected "String" or "Tempfile".'
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def test_hash_optional
|
|
74
|
+
schema do
|
|
75
|
+
bin? :attachment
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
assert_json(
|
|
79
|
+
type: :object,
|
|
80
|
+
properties: {
|
|
81
|
+
attachment: { type: :string, format: :binary }
|
|
82
|
+
},
|
|
83
|
+
additionalProperties: false
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
assert_validation attachment: Tempfile.new('test')
|
|
87
|
+
assert_validation({})
|
|
88
|
+
assert_validation attachment: nil
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def test_array
|
|
92
|
+
schema(:array) do
|
|
93
|
+
list :binary
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
assert_validation [Tempfile.new('a'), Tempfile.new('b')]
|
|
97
|
+
assert_json(type: :array, items: { type: :string, format: :binary })
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def test_with_custom_classes
|
|
101
|
+
schema :binary, classes: [String, Integer]
|
|
102
|
+
|
|
103
|
+
assert_validation 'hello'
|
|
104
|
+
assert_validation 42
|
|
105
|
+
assert_validation nil
|
|
106
|
+
|
|
107
|
+
assert_validation :foo do
|
|
108
|
+
error '/', 'Invalid type, got type "Symbol", expected "Integer" or "String".'
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def test_with_single_custom_class
|
|
113
|
+
schema :binary, classes: [Tempfile]
|
|
114
|
+
|
|
115
|
+
assert_validation Tempfile.new('test')
|
|
116
|
+
|
|
117
|
+
assert_validation 'hello' do
|
|
118
|
+
error '/', 'Invalid type, got type "String", expected "Tempfile".'
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def test_custom_classes_uses_is_a
|
|
123
|
+
schema :binary, classes: [Numeric]
|
|
124
|
+
|
|
125
|
+
assert_validation 42
|
|
126
|
+
assert_validation 3.14
|
|
127
|
+
assert_validation BigDecimal('1.5')
|
|
128
|
+
|
|
129
|
+
assert_validation 'hello' do
|
|
130
|
+
error '/', 'Invalid type, got type "String", expected "Numeric".'
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def test_default
|
|
135
|
+
schema :binary, default: Tempfile.new('default')
|
|
136
|
+
|
|
137
|
+
assert_validation nil
|
|
138
|
+
assert_validation Tempfile.new('other')
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def test_enum
|
|
142
|
+
tempfile_a = Tempfile.new('a')
|
|
143
|
+
tempfile_b = Tempfile.new('b')
|
|
144
|
+
tempfile_c = Tempfile.new('c')
|
|
145
|
+
|
|
146
|
+
schema :binary, enum: [tempfile_a, tempfile_b]
|
|
147
|
+
|
|
148
|
+
assert_validation nil
|
|
149
|
+
assert_validation tempfile_a
|
|
150
|
+
assert_validation tempfile_b
|
|
151
|
+
|
|
152
|
+
assert_validation tempfile_c do
|
|
153
|
+
error '/', /Value not included in enum/
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def test_with_generic_keywords
|
|
158
|
+
schema :binary, title: 'Binary schema',
|
|
159
|
+
description: 'Binary schema holding generic keywords',
|
|
160
|
+
examples: [
|
|
161
|
+
'binary data'
|
|
162
|
+
]
|
|
163
|
+
|
|
164
|
+
assert_json(
|
|
165
|
+
type: :string,
|
|
166
|
+
format: :binary,
|
|
167
|
+
title: 'Binary schema',
|
|
168
|
+
description: 'Binary schema holding generic keywords',
|
|
169
|
+
examples: [
|
|
170
|
+
'binary data'
|
|
171
|
+
]
|
|
172
|
+
)
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def test_validate_self_classes_not_array
|
|
176
|
+
assert_raises_with_message Exceptions::InvalidSchemaError,
|
|
177
|
+
'Option "classes" must be an array of classes.' do
|
|
178
|
+
schema :binary, classes: 'String'
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
def test_validate_self_classes_empty
|
|
183
|
+
assert_raises_with_message Exceptions::InvalidSchemaError,
|
|
184
|
+
'Option "classes" must not be empty.' do
|
|
185
|
+
schema :binary, classes: []
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
def test_validate_self_classes_not_classes
|
|
190
|
+
assert_raises_with_message Exceptions::InvalidSchemaError,
|
|
191
|
+
'Option "classes" must contain classes, got "String".' do
|
|
192
|
+
schema :binary, classes: ['String']
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
def test_validate_self_classes_mixed
|
|
197
|
+
assert_raises_with_message Exceptions::InvalidSchemaError,
|
|
198
|
+
'Option "classes" must contain classes, got :symbol.' do
|
|
199
|
+
schema :binary, classes: [String, :symbol]
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
def test_validate_self_classes_with_module
|
|
204
|
+
assert_raises_with_message Exceptions::InvalidSchemaError,
|
|
205
|
+
'Option "classes" must contain classes, got Comparable.' do
|
|
206
|
+
schema :binary, classes: [Comparable]
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
def test_cast
|
|
211
|
+
tempfile = Tempfile.new('test')
|
|
212
|
+
schema :binary
|
|
213
|
+
|
|
214
|
+
result = @schema.validate(tempfile)
|
|
215
|
+
assert_empty result.errors
|
|
216
|
+
assert_equal tempfile, result.data
|
|
217
|
+
|
|
218
|
+
result = @schema.validate(nil)
|
|
219
|
+
assert_empty result.errors
|
|
220
|
+
assert_nil result.data
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
def test_cast_default
|
|
224
|
+
default_file = Tempfile.new('default')
|
|
225
|
+
schema :binary, default: default_file
|
|
226
|
+
|
|
227
|
+
result = @schema.validate(nil)
|
|
228
|
+
assert_empty result.errors
|
|
229
|
+
assert_equal default_file, result.data
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
def test_cast_in_hash
|
|
233
|
+
schema do
|
|
234
|
+
bin? :attachment
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
tempfile = Tempfile.new('test')
|
|
238
|
+
result = @schema.validate(attachment: tempfile)
|
|
239
|
+
assert_empty result.errors
|
|
240
|
+
assert_equal({ 'attachment' => tempfile }, result.data)
|
|
241
|
+
|
|
242
|
+
result = @schema.validate({})
|
|
243
|
+
assert_empty result.errors
|
|
244
|
+
assert_equal({}, result.data)
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
def test_default_classes_include_string
|
|
248
|
+
schema :binary
|
|
249
|
+
|
|
250
|
+
assert_validation 'a plain string'
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
def test_as_json
|
|
254
|
+
schema :binary
|
|
255
|
+
|
|
256
|
+
assert_json(type: :string, format: :binary)
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
def test_swagger_json
|
|
260
|
+
schema :binary
|
|
261
|
+
|
|
262
|
+
assert_swagger_json(type: :string, format: :binary)
|
|
263
|
+
end
|
|
264
|
+
end
|
|
265
|
+
end
|
|
266
|
+
end
|
|
@@ -32,7 +32,7 @@ module Schemacop
|
|
|
32
32
|
end
|
|
33
33
|
|
|
34
34
|
assert_validation('{42]') do
|
|
35
|
-
error '/', /JSON parse error: "((\d+: )?unexpected token at '{42]'|expected object key, got '42]' at line \d+ column \d+)"\./
|
|
35
|
+
error '/', /JSON parse error: "((\d+: )?unexpected token at '{42\]'|expected object key, got '42\]' at line \d+ column \d+)"\./
|
|
36
36
|
end
|
|
37
37
|
|
|
38
38
|
assert_validation('"foo"') do
|
|
@@ -256,7 +256,7 @@ module Schemacop
|
|
|
256
256
|
end
|
|
257
257
|
|
|
258
258
|
assert_raises_with_message Exceptions::InvalidSchemaError,
|
|
259
|
-
'Option "exclusive_minimum" can\'t be '\
|
|
259
|
+
'Option "exclusive_minimum" can\'t be ' \
|
|
260
260
|
'greater than "exclusive_maximum".' do
|
|
261
261
|
schema :integer, exclusive_minimum: 5, exclusive_maximum: 4
|
|
262
262
|
end
|
|
@@ -298,7 +298,7 @@ module Schemacop
|
|
|
298
298
|
end
|
|
299
299
|
|
|
300
300
|
assert_raises_with_message Exceptions::InvalidSchemaError,
|
|
301
|
-
'Option "exclusive_minimum" can\'t be '\
|
|
301
|
+
'Option "exclusive_minimum" can\'t be ' \
|
|
302
302
|
'greater than "exclusive_maximum".' do
|
|
303
303
|
schema :number, exclusive_minimum: 5, exclusive_maximum: 4
|
|
304
304
|
end
|
|
@@ -259,6 +259,29 @@ module Schemacop
|
|
|
259
259
|
assert_validation('true')
|
|
260
260
|
assert_validation(true)
|
|
261
261
|
end
|
|
262
|
+
|
|
263
|
+
# With cast_str as default option, int gets wrapped in a OneOfNode containing
|
|
264
|
+
# [IntegerNode, StringNode(format: :integer)]. When combined with a sibling str
|
|
265
|
+
# node in one_of, numeric-looking strings like "1" match both the wrapped int
|
|
266
|
+
# (via StringNode(format: :integer)) and the plain str, causing a "matches 2"
|
|
267
|
+
# validation error.
|
|
268
|
+
def test_default_cast_str_with_int_and_str
|
|
269
|
+
Schemacop.v3_default_options = { cast_str: true }.freeze
|
|
270
|
+
|
|
271
|
+
schema :one_of do
|
|
272
|
+
int
|
|
273
|
+
str
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
assert_validation(42)
|
|
277
|
+
assert_validation('hello')
|
|
278
|
+
assert_validation('1')
|
|
279
|
+
assert_cast(42, 42)
|
|
280
|
+
assert_cast('hello', 'hello')
|
|
281
|
+
assert_cast('1', '1')
|
|
282
|
+
ensure
|
|
283
|
+
Schemacop.v3_default_options = {}
|
|
284
|
+
end
|
|
262
285
|
end
|
|
263
286
|
end
|
|
264
287
|
end
|
|
@@ -653,7 +653,7 @@ module Schemacop
|
|
|
653
653
|
end
|
|
654
654
|
|
|
655
655
|
assert_raises_with_message Exceptions::InvalidSchemaError,
|
|
656
|
-
'Option "pattern" can\'t be parsed: end pattern '\
|
|
656
|
+
'Option "pattern" can\'t be parsed: end pattern ' \
|
|
657
657
|
'with unmatched parenthesis: /(abcde/.' do
|
|
658
658
|
schema :string, pattern: '(abcde'
|
|
659
659
|
end
|
|
@@ -750,6 +750,74 @@ module Schemacop
|
|
|
750
750
|
assert_cast("\t", "\t")
|
|
751
751
|
end
|
|
752
752
|
|
|
753
|
+
def test_encoding_single
|
|
754
|
+
schema :string, encoding: 'UTF-8'
|
|
755
|
+
|
|
756
|
+
assert_validation 'Hello World'
|
|
757
|
+
assert_validation ''
|
|
758
|
+
|
|
759
|
+
assert_validation 'Hello World'.encode('ASCII') do
|
|
760
|
+
error '/', 'String has encoding "US-ASCII" but must be "UTF-8".'
|
|
761
|
+
end
|
|
762
|
+
end
|
|
763
|
+
|
|
764
|
+
def test_encoding_multiple
|
|
765
|
+
schema :string, encoding: %w[UTF-8 US-ASCII]
|
|
766
|
+
|
|
767
|
+
assert_validation 'Hello World'
|
|
768
|
+
assert_validation 'Hello World'.encode('ASCII')
|
|
769
|
+
|
|
770
|
+
assert_validation 'Hello World'.encode('ISO-8859-1') do
|
|
771
|
+
error '/', 'String has encoding "ISO-8859-1" but must be "UTF-8" or "US-ASCII".'
|
|
772
|
+
end
|
|
773
|
+
end
|
|
774
|
+
|
|
775
|
+
def test_encoding_with_nil
|
|
776
|
+
schema :string, encoding: 'UTF-8'
|
|
777
|
+
|
|
778
|
+
assert_validation nil
|
|
779
|
+
end
|
|
780
|
+
|
|
781
|
+
def test_encoding_invalid_bytes
|
|
782
|
+
schema :string, encoding: 'UTF-8'
|
|
783
|
+
|
|
784
|
+
invalid_string = "abc\x80def".force_encoding('UTF-8')
|
|
785
|
+
assert_validation invalid_string do
|
|
786
|
+
error '/', 'String has invalid "UTF-8" encoding.'
|
|
787
|
+
end
|
|
788
|
+
end
|
|
789
|
+
|
|
790
|
+
def test_encoding_invalid_bytes_without_specific_encoding
|
|
791
|
+
schema :string
|
|
792
|
+
|
|
793
|
+
invalid_string = "abc\x80def".force_encoding('UTF-8')
|
|
794
|
+
assert_validation invalid_string do
|
|
795
|
+
error '/', 'String has invalid "UTF-8" encoding.'
|
|
796
|
+
end
|
|
797
|
+
end
|
|
798
|
+
|
|
799
|
+
def test_encoding_validate_self
|
|
800
|
+
assert_raises_with_message Exceptions::InvalidSchemaError,
|
|
801
|
+
'Option "encoding" must be a string or an array of strings.' do
|
|
802
|
+
schema :string, encoding: 123
|
|
803
|
+
end
|
|
804
|
+
|
|
805
|
+
assert_raises_with_message Exceptions::InvalidSchemaError,
|
|
806
|
+
'Option "encoding" must be a string or an array of strings.' do
|
|
807
|
+
schema :string, encoding: [123]
|
|
808
|
+
end
|
|
809
|
+
|
|
810
|
+
assert_raises_with_message Exceptions::InvalidSchemaError,
|
|
811
|
+
'Option "encoding" contains unknown encoding "UNKNOWN-FOO".' do
|
|
812
|
+
schema :string, encoding: 'UNKNOWN-FOO'
|
|
813
|
+
end
|
|
814
|
+
|
|
815
|
+
assert_raises_with_message Exceptions::InvalidSchemaError,
|
|
816
|
+
'Option "encoding" contains unknown encoding "UNKNOWN-FOO".' do
|
|
817
|
+
schema :string, encoding: %w[UTF-8 UNKNOWN-FOO]
|
|
818
|
+
end
|
|
819
|
+
end
|
|
820
|
+
|
|
753
821
|
def test_empty_or_whitespace_string_blank_not_allowed
|
|
754
822
|
schema :string, allow_blank: false
|
|
755
823
|
|
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: schemacop
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.0
|
|
4
|
+
version: 3.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Sitrox
|
|
8
8
|
bindir: bin
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date: 2026-
|
|
10
|
+
date: 2026-05-12 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: activesupport
|
|
@@ -87,6 +87,7 @@ files:
|
|
|
87
87
|
- lib/schemacop/v3/all_of_node.rb
|
|
88
88
|
- lib/schemacop/v3/any_of_node.rb
|
|
89
89
|
- lib/schemacop/v3/array_node.rb
|
|
90
|
+
- lib/schemacop/v3/binary_node.rb
|
|
90
91
|
- lib/schemacop/v3/boolean_node.rb
|
|
91
92
|
- lib/schemacop/v3/combination_node.rb
|
|
92
93
|
- lib/schemacop/v3/context.rb
|
|
@@ -132,6 +133,7 @@ files:
|
|
|
132
133
|
- test/unit/schemacop/v3/all_of_node_test.rb
|
|
133
134
|
- test/unit/schemacop/v3/any_of_node_test.rb
|
|
134
135
|
- test/unit/schemacop/v3/array_node_test.rb
|
|
136
|
+
- test/unit/schemacop/v3/binary_node_test.rb
|
|
135
137
|
- test/unit/schemacop/v3/boolean_node_test.rb
|
|
136
138
|
- test/unit/schemacop/v3/global_context_test.rb
|
|
137
139
|
- test/unit/schemacop/v3/hash_node_test.rb
|
|
@@ -193,6 +195,7 @@ test_files:
|
|
|
193
195
|
- test/unit/schemacop/v3/all_of_node_test.rb
|
|
194
196
|
- test/unit/schemacop/v3/any_of_node_test.rb
|
|
195
197
|
- test/unit/schemacop/v3/array_node_test.rb
|
|
198
|
+
- test/unit/schemacop/v3/binary_node_test.rb
|
|
196
199
|
- test/unit/schemacop/v3/boolean_node_test.rb
|
|
197
200
|
- test/unit/schemacop/v3/global_context_test.rb
|
|
198
201
|
- test/unit/schemacop/v3/hash_node_test.rb
|