schemacop 3.0.0.rc1 → 3.0.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.
@@ -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
@@ -72,8 +91,8 @@ module Schemacop
72
91
  propertyNames: '^[a-zA-Z0-9]+$'
73
92
  )
74
93
 
75
- assert_cast({ foo: 123 }, { foo: 123 })
76
- assert_cast({ Foo: 123 }, { Foo: 123 })
94
+ assert_cast({ foo: 123 }, { foo: 123 }.with_indifferent_access)
95
+ assert_cast({ Foo: 123 }, { Foo: 123 }.with_indifferent_access)
77
96
 
78
97
  # New schema
79
98
  schema :hash, additional_properties: true, property_names: '^[a-z]+$'
@@ -82,13 +101,13 @@ module Schemacop
82
101
  assert_validation(foo: :bar)
83
102
  assert_validation('foo' => 'bar')
84
103
  assert_validation(Foo: :bar) do
85
- error '/', 'Property name :Foo does not match "^[a-z]+$".'
104
+ error '/', 'Property name "Foo" does not match "^[a-z]+$".'
86
105
  end
87
106
  assert_validation('_foo39sjfdoi 345893(%' => 'bar', 'foo' => 'bar') do
88
107
  error '/', 'Property name "_foo39sjfdoi 345893(%" does not match "^[a-z]+$".'
89
108
  end
90
109
 
91
- assert_cast({ foo: 123 }, { foo: 123 })
110
+ assert_cast({ foo: 123 }, { foo: 123 }.with_indifferent_access)
92
111
  end
93
112
 
94
113
  def test_required
@@ -293,9 +312,9 @@ module Schemacop
293
312
  assert_validation({ id_foo: 1, id_bar: 2 })
294
313
  assert_validation({ id_foo: 1, id_bar: 2, value: 4 })
295
314
 
296
- assert_cast({ id_foo: 1 }, { id_foo: 1 })
297
- assert_cast({ id_foo: 1, id_bar: 2 }, { id_foo: 1, id_bar: 2 })
298
- assert_cast({ id_foo: 1, id_bar: 2, value: 4 }, { id_foo: 1, id_bar: 2, value: 4 })
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)
299
318
  end
300
319
 
301
320
  def test_defaults
@@ -311,7 +330,9 @@ module Schemacop
311
330
  data = { last_name: 'Doeringer', active: 'true' }
312
331
  data_was = data.dup
313
332
 
314
- 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)
315
336
  assert_equal data_was, data
316
337
 
317
338
  schema do
@@ -526,7 +547,7 @@ module Schemacop
526
547
 
527
548
  assert_validation(nil)
528
549
  assert_validation(foo: '1')
529
- assert_cast({ foo: '1' }, { foo: 1 })
550
+ assert_cast({ foo: '1' }, { foo: 1 }.with_indifferent_access)
530
551
 
531
552
  assert_validation(foo: '1', bar: '2') do
532
553
  error '/', 'Obsolete property "bar".'
@@ -552,11 +573,11 @@ module Schemacop
552
573
 
553
574
  assert_validation(nil)
554
575
  assert_validation(foo: '1')
555
- assert_cast({ foo: '1' }, { foo: 1 })
576
+ assert_cast({ foo: '1' }, { foo: 1 }.with_indifferent_access)
556
577
 
557
578
  assert_validation(foo: '1', bar: nil)
558
579
  assert_validation(foo: '1', bar: '2')
559
- assert_cast({ foo: '1', bar: '2' }, { foo: 1, bar: '2' })
580
+ assert_cast({ foo: '1', bar: '2' }, { foo: 1, bar: '2' }.with_indifferent_access)
560
581
 
561
582
  assert_json(
562
583
  type: 'object',
@@ -589,11 +610,11 @@ module Schemacop
589
610
 
590
611
  assert_validation(nil)
591
612
  assert_validation(foo: '1')
592
- assert_cast({ foo: '1' }, { foo: 1 })
613
+ assert_cast({ foo: '1' }, { foo: 1 }.with_indifferent_access)
593
614
 
594
615
  assert_validation(foo: '1', bar: nil)
595
616
  assert_validation(foo: '1', bar: '2')
596
- assert_cast({ foo: '1', bar: '2' }, { foo: 1, bar: '2' })
617
+ assert_cast({ foo: '1', bar: '2' }, { foo: 1, bar: '2' }.with_indifferent_access)
597
618
 
598
619
  assert_json(
599
620
  type: 'object',
@@ -616,11 +637,11 @@ module Schemacop
616
637
 
617
638
  assert_validation(nil)
618
639
  assert_validation(foo: '1')
619
- assert_cast({ foo: '1' }, { foo: 1 })
640
+ assert_cast({ foo: '1' }, { foo: 1 }.with_indifferent_access)
620
641
 
621
642
  assert_validation(foo: '1', bar: nil)
622
643
  assert_validation(foo: '1', bar: '2')
623
- assert_cast({ foo: '1', bar: '2' }, { foo: 1, bar: 2 })
644
+ assert_cast({ foo: '1', bar: '2' }, { foo: 1, bar: 2 }.with_indifferent_access)
624
645
  end
625
646
 
626
647
  def test_cast_with_additional_any_of
@@ -634,7 +655,7 @@ module Schemacop
634
655
 
635
656
  assert_validation(nil)
636
657
  assert_validation(foo: '1')
637
- assert_cast({ foo: '1' }, { foo: 1 })
658
+ assert_cast({ foo: '1' }, { foo: 1 }.with_indifferent_access)
638
659
 
639
660
  assert_validation(foo: '1', bar: nil)
640
661
  assert_validation(foo: '1', bar: '2')
@@ -643,7 +664,7 @@ module Schemacop
643
664
  error '/qux', 'Does not match any anyOf condition.'
644
665
  end
645
666
 
646
- assert_cast({ foo: '1', bar: '2' }, { foo: 1, bar: '2' })
667
+ assert_cast({ foo: '1', bar: '2' }, { foo: 1, bar: '2' }.with_indifferent_access)
647
668
 
648
669
  assert_json(
649
670
  type: 'object',
@@ -675,7 +696,7 @@ module Schemacop
675
696
 
676
697
  assert_validation(nil)
677
698
  assert_validation(foo: '1')
678
- assert_cast({ foo: '1' }, { foo: 1 })
699
+ assert_cast({ foo: '1' }, { foo: 1 }.with_indifferent_access)
679
700
 
680
701
  assert_validation(foo: '1', bar: nil)
681
702
  assert_validation(foo: '1', bar: '2')
@@ -684,8 +705,8 @@ module Schemacop
684
705
  error '/qux', 'Does not match any anyOf condition.'
685
706
  end
686
707
 
687
- assert_cast({ foo: '1', bar: '2' }, { foo: 1, bar: 2 })
688
- 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)
689
710
 
690
711
  assert_json(
691
712
  type: 'object',
@@ -821,6 +842,131 @@ module Schemacop
821
842
  end
822
843
  end
823
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
824
970
  end
825
971
  end
826
972
  end