schemacop 3.0.0.rc0 → 3.0.0.rc5

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.
data/schemacop.gemspec CHANGED
@@ -1,15 +1,15 @@
1
1
  # -*- encoding: utf-8 -*-
2
- # stub: schemacop 3.0.0.rc0 ruby lib
2
+ # stub: schemacop 3.0.0.rc5 ruby lib
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = "schemacop".freeze
6
- s.version = "3.0.0.rc0"
6
+ s.version = "3.0.0.rc5"
7
7
 
8
8
  s.required_rubygems_version = Gem::Requirement.new("> 1.3.1".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-01-14"
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/root_node.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 = "2021-02-05"
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
15
  s.rubygems_version = "3.0.3".freeze
@@ -21,6 +21,7 @@ Gem::Specification.new do |s|
21
21
 
22
22
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
23
23
  s.add_runtime_dependency(%q<activesupport>.freeze, [">= 4.0"])
24
+ s.add_runtime_dependency(%q<ruby2_keywords>.freeze, ["= 0.0.4"])
24
25
  s.add_development_dependency(%q<bundler>.freeze, [">= 0"])
25
26
  s.add_development_dependency(%q<rake>.freeze, [">= 0"])
26
27
  s.add_development_dependency(%q<minitest>.freeze, [">= 0"])
@@ -32,6 +33,7 @@ Gem::Specification.new do |s|
32
33
  s.add_development_dependency(%q<simplecov>.freeze, ["= 0.21.2"])
33
34
  else
34
35
  s.add_dependency(%q<activesupport>.freeze, [">= 4.0"])
36
+ s.add_dependency(%q<ruby2_keywords>.freeze, ["= 0.0.4"])
35
37
  s.add_dependency(%q<bundler>.freeze, [">= 0"])
36
38
  s.add_dependency(%q<rake>.freeze, [">= 0"])
37
39
  s.add_dependency(%q<minitest>.freeze, [">= 0"])
@@ -44,6 +46,7 @@ Gem::Specification.new do |s|
44
46
  end
45
47
  else
46
48
  s.add_dependency(%q<activesupport>.freeze, [">= 4.0"])
49
+ s.add_dependency(%q<ruby2_keywords>.freeze, ["= 0.0.4"])
47
50
  s.add_dependency(%q<bundler>.freeze, [">= 0"])
48
51
  s.add_dependency(%q<rake>.freeze, [">= 0"])
49
52
  s.add_dependency(%q<minitest>.freeze, [">= 0"])
@@ -1,5 +1,15 @@
1
1
  require 'simplecov'
2
- SimpleCov.start
2
+ SimpleCov.start do
3
+ add_group 'v3', 'lib/schemacop/v3'
4
+ add_group 'v2', 'lib/schemacop/v2'
5
+
6
+ # We don't care about the test coverage for the
7
+ # tests themselves
8
+ add_filter 'test'
9
+
10
+ # Also enable branch coverage reporting
11
+ enable_coverage :branch
12
+ end
3
13
 
4
14
  # TODO: Move to more sensible location
5
15
  def assert_verr(&block)
@@ -141,7 +151,12 @@ class V3Test < SchemacopTest
141
151
  input_data_was = Marshal.load(Marshal.dump(input_data))
142
152
  result = @schema.validate(input_data)
143
153
  assert_empty result.errors
144
- assert_equal expected_data, result.data, 'Unexpected result data.'
154
+
155
+ if expected_data.nil?
156
+ assert_nil result.data, 'Unexpected result data.'
157
+ else
158
+ assert_equal expected_data, result.data, 'Unexpected result data.'
159
+ end
145
160
 
146
161
  if input_data.nil?
147
162
  assert_nil input_data_was, 'Expected input_data to stay the same.'
@@ -115,6 +115,43 @@ module Schemacop
115
115
  assert_equal expected_float, s.validate!(float_field: '')
116
116
  assert_equal expected_float, s.validate!(float_field: ' ')
117
117
  end
118
+
119
+ def test_float_to_integer
120
+ s = Schema.new do
121
+ req :foo, :integer, cast: [Float]
122
+ end
123
+
124
+ assert_equal({ foo: 42 }, s.validate!(foo: 42.0))
125
+ assert_equal({ foo: 42 }, s.validate!(foo: Float(42)))
126
+ end
127
+
128
+ def test_integer_to_float
129
+ s = Schema.new do
130
+ req :foo, :float, cast: [Integer]
131
+ end
132
+
133
+ assert_equal({ foo: 42.0 }, s.validate!(foo: 42))
134
+ assert_equal({ foo: 42.0 }, s.validate!(foo: Integer(42)))
135
+ end
136
+
137
+ def test_invalid_cast_option
138
+ s = Schema.new do
139
+ req :foo, :integer, cast: true
140
+ end
141
+
142
+ assert_raises Schemacop::Exceptions::InvalidSchemaError do
143
+ s.validate!({ foo: '42' })
144
+ end
145
+ end
146
+
147
+ def test_impossible_cast
148
+ s = Schema.new do
149
+ req :foo, :integer, cast: [String]
150
+ end
151
+
152
+ assert_equal({ foo: 42 }, s.validate!(foo: '42'))
153
+ assert_verr { s.validate!(foo: 'foo') }
154
+ end
118
155
  end
119
156
  end
120
157
  end
@@ -90,6 +90,17 @@ module Schemacop
90
90
  assert_verr { s.validate!(o: true) }
91
91
  assert_verr { s.validate!(r: nil, r_nil: false, o: true) }
92
92
  end
93
+
94
+ def test_invalid_hash
95
+ s = Schema.new do
96
+ type :hash do
97
+ req :foo
98
+ end
99
+ end
100
+
101
+ assert_verr { s.validate!({ foo: 42, 'foo' => 42 }) }
102
+ assert_nothing_raised { s.validate!({ foo: 42 }.with_indifferent_access) }
103
+ end
93
104
  end
94
105
  end
95
106
  end
@@ -142,8 +142,7 @@ module Schemacop
142
142
 
143
143
  assert_cast(
144
144
  { foo: '42', bar: '2020-01-15' },
145
- foo: 42,
146
- bar: Date.new(2020, 1, 15)
145
+ { foo: 42, bar: Date.new(2020, 1, 15) }.with_indifferent_access
147
146
  )
148
147
  end
149
148
 
@@ -133,11 +133,11 @@ module Schemacop
133
133
 
134
134
  assert_cast(
135
135
  { created_at: '2020-01-01' },
136
- created_at: Date.new(2020, 1, 1)
136
+ { created_at: Date.new(2020, 1, 1) }.with_indifferent_access
137
137
  )
138
138
  assert_cast(
139
139
  { created_at: '2020-01-01T17:38:20' },
140
- created_at: DateTime.new(2020, 1, 1, 17, 38, 20)
140
+ { created_at: DateTime.new(2020, 1, 1, 17, 38, 20) }.with_indifferent_access
141
141
  )
142
142
  end
143
143
 
@@ -158,12 +158,12 @@ module Schemacop
158
158
 
159
159
  assert_cast(
160
160
  { foo: { bar: nil } },
161
- foo: { bar: nil }
161
+ { foo: { bar: nil } }.with_indifferent_access
162
162
  )
163
163
 
164
164
  assert_cast(
165
165
  { foo: { baz: nil } },
166
- foo: { baz: 'Baz' }
166
+ { foo: { baz: 'Baz' } }.with_indifferent_access
167
167
  )
168
168
 
169
169
  schema do
@@ -175,12 +175,12 @@ module Schemacop
175
175
 
176
176
  assert_cast(
177
177
  { foo: { bar: '1990-01-13' } },
178
- foo: { bar: Date.new(1990, 1, 13) }
178
+ { foo: { bar: Date.new(1990, 1, 13) } }.with_indifferent_access
179
179
  )
180
180
 
181
181
  assert_cast(
182
182
  { foo: { bar: '1990-01-13T10:00:00Z' } },
183
- foo: { bar: DateTime.new(1990, 1, 13, 10, 0, 0) }
183
+ { foo: { bar: DateTime.new(1990, 1, 13, 10, 0, 0) } }.with_indifferent_access
184
184
  )
185
185
  end
186
186
 
@@ -446,8 +446,8 @@ module Schemacop
446
446
  end
447
447
 
448
448
  assert_cast(['foo', 42], ['foo', 42])
449
- assert_cast(['foo', 42, { foo: '1990-01-01' }], ['foo', 42, { foo: Date.new(1990, 1, 1) }])
450
- assert_cast(['foo', 42, { foo: '1990-01-01', bar: :baz }], ['foo', 42, { foo: Date.new(1990, 1, 1), bar: :baz }])
449
+ assert_cast(['foo', 42, { foo: '1990-01-01' }], ['foo', 42, { foo: Date.new(1990, 1, 1) }.with_indifferent_access])
450
+ assert_cast(['foo', 42, { foo: '1990-01-01', bar: :baz }], ['foo', 42, { foo: Date.new(1990, 1, 1), bar: :baz }.with_indifferent_access])
451
451
  end
452
452
 
453
453
  def test_multiple_add_in_schema
@@ -537,7 +537,7 @@ module Schemacop
537
537
  additionalItems: false
538
538
  )
539
539
 
540
- assert_cast [{}], [{ name: 'John' }]
540
+ assert_cast [{}], [{ name: 'John' }.with_indifferent_access]
541
541
  end
542
542
 
543
543
  def test_enum_schema
@@ -800,6 +800,16 @@ module Schemacop
800
800
 
801
801
  assert_cast(%w[foo 1990-01-01], ['foo', Date.new(1990, 1, 1)])
802
802
  end
803
+
804
+ def test_contains_multiple_should_fail
805
+ assert_raises_with_message Exceptions::InvalidSchemaError, 'You can only use "cont" once.' do
806
+ schema :array do
807
+ list :string
808
+ cont :string
809
+ cont :integer
810
+ end
811
+ end
812
+ end
803
813
  end
804
814
  end
805
815
  end
@@ -25,8 +25,10 @@ module Schemacop
25
25
 
26
26
  def test_schemas
27
27
  assert_equal({}, GlobalContext.instance.schemas)
28
+ assert_equal({}, GlobalContext.schemas)
28
29
  GlobalContext.instance.eager_load!
29
30
  assert_equal(%i[nested/group user], GlobalContext.instance.schemas.keys)
31
+ assert_equal(%i[nested/group user], GlobalContext.schemas.keys)
30
32
  assert_is_a Node, GlobalContext.instance.schemas.values.first
31
33
  end
32
34
 
@@ -16,7 +16,7 @@ module Schemacop
16
16
  assert_json(type: :object, additionalProperties: false)
17
17
  end
18
18
 
19
- def test_additional_properties_false
19
+ def test_additional_properties_false_by_default
20
20
  schema
21
21
  assert_validation({})
22
22
  assert_validation(foo: :bar, bar: :baz) do
@@ -26,6 +26,17 @@ module Schemacop
26
26
  assert_json(type: :object, additionalProperties: false)
27
27
  end
28
28
 
29
+ def test_additional_properties_false
30
+ schema :hash, additional_properties: false
31
+
32
+ assert_validation({})
33
+ assert_validation(foo: :bar, bar: :baz) do
34
+ error '/', 'Obsolete property "foo".'
35
+ error '/', 'Obsolete property "bar".'
36
+ end
37
+ assert_json(type: :object, additionalProperties: false)
38
+ end
39
+
29
40
  def test_additional_properties_true
30
41
  schema :hash, additional_properties: true
31
42
  assert_validation({})
@@ -54,6 +65,14 @@ module Schemacop
54
65
  type: :object,
55
66
  additionalProperties: { type: :string }
56
67
  )
68
+
69
+ assert_nothing_raised do
70
+ @schema.validate!({ foo: 'foo' })
71
+ end
72
+
73
+ assert_raises_with_message Exceptions::ValidationError, '/bar: Invalid type, expected "string".' do
74
+ @schema.validate!({ foo: 'foo', bar: :baz })
75
+ end
57
76
  end
58
77
 
59
78
  def test_property_names
@@ -61,6 +80,7 @@ module Schemacop
61
80
  assert_validation({})
62
81
  assert_validation(foo: :bar)
63
82
  assert_validation('foo' => 'bar')
83
+ assert_validation(Foo: :bar)
64
84
  assert_validation('_foo39sjfdoi 345893(%' => 'bar', 'foo' => 'bar') do
65
85
  error '/', 'Property name "_foo39sjfdoi 345893(%" does not match "^[a-zA-Z0-9]+$".'
66
86
  end
@@ -70,6 +90,24 @@ module Schemacop
70
90
  additionalProperties: true,
71
91
  propertyNames: '^[a-zA-Z0-9]+$'
72
92
  )
93
+
94
+ assert_cast({ foo: 123 }, { foo: 123 }.with_indifferent_access)
95
+ assert_cast({ Foo: 123 }, { Foo: 123 }.with_indifferent_access)
96
+
97
+ # New schema
98
+ schema :hash, additional_properties: true, property_names: '^[a-z]+$'
99
+
100
+ assert_validation({})
101
+ assert_validation(foo: :bar)
102
+ assert_validation('foo' => 'bar')
103
+ assert_validation(Foo: :bar) do
104
+ error '/', 'Property name "Foo" does not match "^[a-z]+$".'
105
+ end
106
+ assert_validation('_foo39sjfdoi 345893(%' => 'bar', 'foo' => 'bar') do
107
+ error '/', 'Property name "_foo39sjfdoi 345893(%" does not match "^[a-z]+$".'
108
+ end
109
+
110
+ assert_cast({ foo: 123 }, { foo: 123 }.with_indifferent_access)
73
111
  end
74
112
 
75
113
  def test_required
@@ -254,6 +292,31 @@ module Schemacop
254
292
  )
255
293
  end
256
294
 
295
+ def test_pattern_properties_casting
296
+ schema do
297
+ int?(/^id_.*$/)
298
+ int?(/^val.*$/)
299
+ end
300
+
301
+ assert_json({
302
+ type: :object,
303
+ patternProperties: {
304
+ '^id_.*$': { type: :integer },
305
+ '^val.*$': { type: :integer }
306
+ },
307
+ additionalProperties: false
308
+ })
309
+
310
+ assert_validation({})
311
+ assert_validation({ id_foo: 1 })
312
+ assert_validation({ id_foo: 1, id_bar: 2 })
313
+ assert_validation({ id_foo: 1, id_bar: 2, value: 4 })
314
+
315
+ assert_cast({ id_foo: 1 }, { id_foo: 1 }.with_indifferent_access)
316
+ assert_cast({ id_foo: 1, id_bar: 2 }, { id_foo: 1, id_bar: 2 }.with_indifferent_access)
317
+ assert_cast({ id_foo: 1, id_bar: 2, value: 4 }, { id_foo: 1, id_bar: 2, value: 4 }.with_indifferent_access)
318
+ end
319
+
257
320
  def test_defaults
258
321
  schema do
259
322
  str? :first_name, default: 'John'
@@ -267,7 +330,9 @@ module Schemacop
267
330
  data = { last_name: 'Doeringer', active: 'true' }
268
331
  data_was = data.dup
269
332
 
270
- assert_equal({ first_name: 'John', last_name: 'Doeringer', active: true, address: { street: 'Example 42' } }, @schema.validate(data).data)
333
+ expected_data = { first_name: 'John', last_name: 'Doeringer', active: true, address: { street: 'Example 42' } }.with_indifferent_access
334
+
335
+ assert_equal(expected_data, @schema.validate(data).data)
271
336
  assert_equal data_was, data
272
337
 
273
338
  schema do
@@ -425,6 +490,13 @@ module Schemacop
425
490
  validate_self_should_error((4 + 6i))
426
491
  validate_self_should_error('13')
427
492
  validate_self_should_error('Lorem ipsum')
493
+
494
+ # rubocop:disable Lint/BooleanSymbol
495
+ assert_raises_with_message Exceptions::InvalidSchemaError,
496
+ 'Option "additional_properties" must be a boolean value' do
497
+ schema :hash, additional_properties: :true
498
+ end
499
+ # rubocop:enable Lint/BooleanSymbol
428
500
  end
429
501
 
430
502
  def test_doc_example
@@ -475,7 +547,7 @@ module Schemacop
475
547
 
476
548
  assert_validation(nil)
477
549
  assert_validation(foo: '1')
478
- assert_cast({ foo: '1' }, { foo: 1 })
550
+ assert_cast({ foo: '1' }, { foo: 1 }.with_indifferent_access)
479
551
 
480
552
  assert_validation(foo: '1', bar: '2') do
481
553
  error '/', 'Obsolete property "bar".'
@@ -501,11 +573,11 @@ module Schemacop
501
573
 
502
574
  assert_validation(nil)
503
575
  assert_validation(foo: '1')
504
- assert_cast({ foo: '1' }, { foo: 1 })
576
+ assert_cast({ foo: '1' }, { foo: 1 }.with_indifferent_access)
505
577
 
506
578
  assert_validation(foo: '1', bar: nil)
507
579
  assert_validation(foo: '1', bar: '2')
508
- assert_cast({ foo: '1', bar: '2' }, { foo: 1, bar: '2' })
580
+ assert_cast({ foo: '1', bar: '2' }, { foo: 1, bar: '2' }.with_indifferent_access)
509
581
 
510
582
  assert_json(
511
583
  type: 'object',
@@ -538,11 +610,11 @@ module Schemacop
538
610
 
539
611
  assert_validation(nil)
540
612
  assert_validation(foo: '1')
541
- assert_cast({ foo: '1' }, { foo: 1 })
613
+ assert_cast({ foo: '1' }, { foo: 1 }.with_indifferent_access)
542
614
 
543
615
  assert_validation(foo: '1', bar: nil)
544
616
  assert_validation(foo: '1', bar: '2')
545
- assert_cast({ foo: '1', bar: '2' }, { foo: 1, bar: '2' })
617
+ assert_cast({ foo: '1', bar: '2' }, { foo: 1, bar: '2' }.with_indifferent_access)
546
618
 
547
619
  assert_json(
548
620
  type: 'object',
@@ -565,11 +637,11 @@ module Schemacop
565
637
 
566
638
  assert_validation(nil)
567
639
  assert_validation(foo: '1')
568
- assert_cast({ foo: '1' }, { foo: 1 })
640
+ assert_cast({ foo: '1' }, { foo: 1 }.with_indifferent_access)
569
641
 
570
642
  assert_validation(foo: '1', bar: nil)
571
643
  assert_validation(foo: '1', bar: '2')
572
- assert_cast({ foo: '1', bar: '2' }, { foo: 1, bar: 2 })
644
+ assert_cast({ foo: '1', bar: '2' }, { foo: 1, bar: 2 }.with_indifferent_access)
573
645
  end
574
646
 
575
647
  def test_cast_with_additional_any_of
@@ -583,7 +655,7 @@ module Schemacop
583
655
 
584
656
  assert_validation(nil)
585
657
  assert_validation(foo: '1')
586
- assert_cast({ foo: '1' }, { foo: 1 })
658
+ assert_cast({ foo: '1' }, { foo: 1 }.with_indifferent_access)
587
659
 
588
660
  assert_validation(foo: '1', bar: nil)
589
661
  assert_validation(foo: '1', bar: '2')
@@ -592,7 +664,7 @@ module Schemacop
592
664
  error '/qux', 'Does not match any anyOf condition.'
593
665
  end
594
666
 
595
- assert_cast({ foo: '1', bar: '2' }, { foo: 1, bar: '2' })
667
+ assert_cast({ foo: '1', bar: '2' }, { foo: 1, bar: '2' }.with_indifferent_access)
596
668
 
597
669
  assert_json(
598
670
  type: 'object',
@@ -624,7 +696,7 @@ module Schemacop
624
696
 
625
697
  assert_validation(nil)
626
698
  assert_validation(foo: '1')
627
- assert_cast({ foo: '1' }, { foo: 1 })
699
+ assert_cast({ foo: '1' }, { foo: 1 }.with_indifferent_access)
628
700
 
629
701
  assert_validation(foo: '1', bar: nil)
630
702
  assert_validation(foo: '1', bar: '2')
@@ -633,8 +705,8 @@ module Schemacop
633
705
  error '/qux', 'Does not match any anyOf condition.'
634
706
  end
635
707
 
636
- assert_cast({ foo: '1', bar: '2' }, { foo: 1, bar: 2 })
637
- assert_cast({ foo: '1', bar: '2', qux: '2020-01-13', asd: 1 }, { foo: 1, bar: 2, qux: Date.new(2020, 1, 13), asd: 1 })
708
+ assert_cast({ foo: '1', bar: '2' }, { foo: 1, bar: 2 }.with_indifferent_access)
709
+ assert_cast({ foo: '1', bar: '2', qux: '2020-01-13', asd: 1 }, { foo: 1, bar: 2, qux: Date.new(2020, 1, 13), asd: 1 }.with_indifferent_access)
638
710
 
639
711
  assert_json(
640
712
  type: 'object',
@@ -770,6 +842,131 @@ module Schemacop
770
842
  end
771
843
  end
772
844
  end
845
+
846
+ def test_schema_with_string_keys
847
+ schema :hash do
848
+ int! 'foo'
849
+ end
850
+
851
+ assert_validation(nil)
852
+ assert_validation({ 'foo' => 42 })
853
+ assert_validation({ foo: 42 })
854
+
855
+ assert_cast({ 'foo' => 42 }, { 'foo' => 42 })
856
+ assert_cast({ foo: 42 }, { foo: 42 }.with_indifferent_access)
857
+
858
+ assert_validation({}) do
859
+ error '/foo', 'Value must be given.'
860
+ end
861
+
862
+ assert_validation({ :foo => 42, 'foo' => 43 }) do
863
+ error '/', 'Has 1 ambiguous properties: [:foo].'
864
+ end
865
+ end
866
+
867
+ def test_schema_with_string_keys_in_data
868
+ schema :hash do
869
+ int! :foo
870
+ end
871
+
872
+ assert_validation(nil)
873
+ assert_validation({ 'foo' => 42 })
874
+ assert_validation({ foo: 42 })
875
+
876
+ assert_cast({ 'foo' => 42 }, { 'foo' => 42 })
877
+ assert_cast({ foo: 42 }, { foo: 42 }.with_indifferent_access)
878
+
879
+ assert_validation({}) do
880
+ error '/foo', 'Value must be given.'
881
+ end
882
+
883
+ assert_validation({ :foo => 42, 'foo' => 43 }) do
884
+ error '/', 'Has 1 ambiguous properties: [:foo].'
885
+ end
886
+ end
887
+
888
+ def test_invalid_options
889
+ assert_raises_with_message Schemacop::Exceptions::InvalidSchemaError, 'Options [:foo] are not allowed for this node.' do
890
+ schema :hash, foo: 'bar' do
891
+ int! :id
892
+ end
893
+ end
894
+ end
895
+
896
+ def test_casting_optional
897
+ schema :hash do
898
+ str? :foo, format: :integer
899
+ end
900
+
901
+ assert_validation(nil)
902
+ assert_validation({})
903
+
904
+ assert_cast(nil, nil)
905
+ assert_cast({}, {}.with_indifferent_access)
906
+ end
907
+
908
+ def test_as_option
909
+ schema :hash do
910
+ int! :foo, as: :bar
911
+ end
912
+
913
+ assert_validation(nil)
914
+ assert_validation({ foo: 42 })
915
+ assert_validation({ bar: 13 }) do
916
+ error '/', 'Obsolete property "bar".'
917
+ error '/foo', 'Value must be given.'
918
+ end
919
+
920
+ assert_validation({ foo: '13' }) do
921
+ error '/foo', 'Invalid type, expected "integer".'
922
+ end
923
+
924
+ assert_cast(nil, nil)
925
+ assert_cast({ foo: 42 }, { bar: 42 }.with_indifferent_access)
926
+ end
927
+
928
+ def test_as_option_overriding
929
+ schema :hash do
930
+ int? :foo, as: :bar
931
+ int? :bar
932
+ end
933
+
934
+ assert_validation(nil)
935
+ assert_validation({})
936
+ assert_validation({ foo: 42 })
937
+ assert_validation({ foo: 42, bar: 13 })
938
+
939
+ assert_validation({ foo: '13' }) do
940
+ error '/foo', 'Invalid type, expected "integer".'
941
+ end
942
+
943
+ # assert_cast(nil, nil)
944
+ assert_cast({ foo: 42 }, { bar: 42 }.with_indifferent_access)
945
+ assert_cast({ foo: 42, bar: 13 }, { bar: 13 }.with_indifferent_access)
946
+ assert_cast({ bar: 13, foo: 42 }, { bar: 13 }.with_indifferent_access)
947
+
948
+ # Swap order
949
+ schema :hash do
950
+ int? :bar
951
+ int! :foo, as: :bar
952
+ end
953
+
954
+ assert_validation(nil)
955
+ assert_validation({ foo: 42 })
956
+ assert_validation({ foo: 42, bar: 13 })
957
+ assert_validation({ bar: 13 }) do
958
+ error '/foo', 'Value must be given.'
959
+ end
960
+
961
+ assert_validation({ foo: '13' }) do
962
+ error '/foo', 'Invalid type, expected "integer".'
963
+ end
964
+
965
+ assert_cast(nil, nil)
966
+ assert_cast({ foo: 42 }, { bar: 42 }.with_indifferent_access)
967
+ assert_cast({ foo: 42, bar: 13 }, { bar: 42 }.with_indifferent_access)
968
+ assert_cast({ bar: 13, foo: 42 }, { bar: 42 }.with_indifferent_access)
969
+ end
773
970
  end
774
971
  end
775
972
  end