schemacop 3.0.38 → 3.0.39

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4a3a54c489ac60b4a01424d7a4949724c15fdec793de16a4375e3097f691128b
4
- data.tar.gz: 48390b41d456f5362ecabf0e97ed37fdc035247ec3d8335d105e97ab0d858378
3
+ metadata.gz: 5265f8c948ca9f0d23aa7e13ff78a5a980ce12ccd16c6fd1dae4e8ec6a30b833
4
+ data.tar.gz: 77177403eccb133730a9359172c6d37362d2d76184a2758131bcd35fe5869f0a
5
5
  SHA512:
6
- metadata.gz: 911a618277694321833a85cc051ff139b14e9a1117dab7380bcc4c9ebc08e87a258f131224e1f3cef40d5b6495de6142f1b6f23009ce62917c8a07bf75960678
7
- data.tar.gz: 1add721c851198435cf89b0b9d95d94c607bc443df180072fda1b35d4b956a4a2bdab429252f630fca8e4ddf09baf13153278d60f401318e0ad591bbc7c481b8
6
+ metadata.gz: 306a17bfebac65db3f0c7fbd37f2b5d0fa3c44b26c6217732241fa8cd43455a552a07f21327c805d421c0a2649f8b1b936b8063d9cf5b97673e416aea3dff8b6
7
+ data.tar.gz: 64f2e2a148374b811fb4ac251606b25c48be802a1255e3dd72389aa2f4250f59695dba9b20b8cc62f48a9e646ea45d6cc9c9aeacc216b4704300b3864fa1701c
data/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Change log
2
2
 
3
+ ## 3.0.39 (2026-03-26)
4
+
5
+ * Add `BinaryNode` for validating binary data fields such as file uploads.
6
+ Represented as `{ type: 'string', format: 'binary' }` in JSON Schema / OpenAPI
7
+ output. By default accepts `ActionDispatch::Http::UploadedFile`,
8
+ `Rack::Multipart::UploadedFile`, `Tempfile`, and `String`. Custom classes can
9
+ be specified via the `classes` option. DSL: `bin` / `bin!` / `bin?`.
10
+
3
11
  ## 3.0.38 (2026-02-25)
4
12
 
5
13
  * Fix namespaced schema `$ref` paths in generated JSON. For OpenAPI (swagger)
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. [AllOf](#allOf)
18
- 10. [AnyOf](#anyOf)
19
- 11. [OneOf](#oneOf)
20
- 12. [IsNot](#isNot)
21
- 13. [Reference](#reference)
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)
@@ -1290,6 +1291,45 @@ schema.validate!('foo'.html_safe) # => "foo"
1290
1291
  If you set the `strict` option to `false`, the check is done using `is_a?` instead of
1291
1292
  `instance_of?`, which also allows subclasses
1292
1293
 
1294
+ ### Binary
1295
+
1296
+ Type: `:binary`\
1297
+ DSL: `bin`
1298
+
1299
+ The binary type represents binary data fields such as file uploads. It is
1300
+ represented as `{ type: 'string', format: 'binary' }` in JSON Schema / OpenAPI
1301
+ output. At runtime, it validates that the value is an instance of one of the
1302
+ configured classes (using `is_a?`, so subclasses are accepted).
1303
+
1304
+ By default, the node accepts instances of `ActionDispatch::Http::UploadedFile`,
1305
+ `Rack::Multipart::UploadedFile`, `Tempfile`, and `String`. Missing classes (e.g.
1306
+ when not running within Rails) are silently skipped.
1307
+
1308
+ ```ruby
1309
+ schema = Schemacop::Schema3.new :binary, classes: [Tempfile, String]
1310
+
1311
+ schema.validate!(nil) # => nil
1312
+ schema.validate!(Tempfile.new('f')) # => #<Tempfile:...>
1313
+ schema.validate!('binary data') # => "binary data"
1314
+ schema.validate!(42) # => Schemacop::Exceptions::ValidationError: /: Invalid type, got type "Integer", expected "String" or "Tempfile".
1315
+ ```
1316
+
1317
+ If you want to limit the accepted classes, use the `classes` option:
1318
+
1319
+ ```ruby
1320
+ schema = Schemacop::Schema3.new :binary, classes: [Tempfile]
1321
+
1322
+ schema.validate!(nil) # => nil
1323
+ schema.validate!(Tempfile.new('f')) # => #<Tempfile:...>
1324
+ schema.validate!('foo') # => Schemacop::Exceptions::ValidationError: /: Invalid type, got type "String", expected "Tempfile".
1325
+ ```
1326
+
1327
+ #### Options
1328
+
1329
+ * `classes`
1330
+ An array of `Class` objects that should be accepted. Must not be empty. If not
1331
+ given, the default classes listed above are used.
1332
+
1293
1333
  ### AllOf
1294
1334
 
1295
1335
  Type: `:all_of`\
data/VERSION CHANGED
@@ -1 +1 @@
1
- 3.0.38
1
+ 3.0.39
@@ -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
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/schemacop.gemspec CHANGED
@@ -1,20 +1,20 @@
1
1
  # -*- encoding: utf-8 -*-
2
- # stub: schemacop 3.0.38 ruby lib
2
+ # stub: schemacop 3.0.39 ruby lib
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = "schemacop".freeze
6
- s.version = "3.0.38".freeze
6
+ s.version = "3.0.39".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-02-25"
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-03-26"
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
 
@@ -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
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.38
4
+ version: 3.0.39
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sitrox
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2026-02-25 00:00:00.000000000 Z
10
+ date: 2026-03-26 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