@@ -31,6 +31,16 @@ def test_null(self, schema_type):
31
31
with pytest .raises (ValidationError ):
32
32
validator .validate (value )
33
33
34
+ @pytest .mark .parametrize ("is_nullable" , [True , False ])
35
+ def test_nullable_untyped (self , is_nullable ):
36
+ schema = {"nullable" : is_nullable }
37
+ validator = OAS30Validator (schema )
38
+ value = None
39
+
40
+ result = validator .validate (value )
41
+
42
+ assert result is None
43
+
34
44
@pytest .mark .parametrize (
35
45
"schema_type" ,
36
46
[
@@ -50,6 +60,23 @@ def test_nullable(self, schema_type):
50
60
51
61
assert result is None
52
62
63
+ def test_nullable_enum_without_none (self ):
64
+ schema = {"type" : "integer" , "nullable" : True , "enum" : [1 , 2 , 3 ]}
65
+ validator = OAS30Validator (schema )
66
+ value = None
67
+
68
+ with pytest .raises (ValidationError ):
69
+ validator .validate (value )
70
+
71
+ def test_nullable_enum_with_none (self ):
72
+ schema = {"type" : "integer" , "nullable" : True , "enum" : [1 , 2 , 3 , None ]}
73
+ validator = OAS30Validator (schema )
74
+ value = None
75
+
76
+ result = validator .validate (value )
77
+
78
+ assert result is None
79
+
53
80
@pytest .mark .parametrize (
54
81
"value" ,
55
82
[
@@ -442,6 +469,103 @@ def test_oneof_discriminator(self, schema_type):
442
469
result = validator .validate ({"discipline" : "other" })
443
470
assert False
444
471
472
+ @pytest .mark .parametrize ("is_nullable" , [True , False ])
473
+ def test_nullable_ref (self , is_nullable ):
474
+ """
475
+ Tests that a field that points to a schema reference is null checked based on the $ref schema rather than
476
+ on this schema
477
+ :param is_nullable: if the schema is marked as nullable. If not, validate an exception is raised on None
478
+ """
479
+ schema = {
480
+ "$ref" : "#/$defs/Pet" ,
481
+ "$defs" : {
482
+ "NullableText" : {
483
+ "type" : "string" ,
484
+ "nullable" : is_nullable
485
+ },
486
+ "Pet" : {
487
+ "properties" : {
488
+ "testfield" : {"$ref" : "#/$defs/NullableText" },
489
+ },
490
+ }
491
+ },
492
+ }
493
+ validator = OAS30Validator (
494
+ schema ,
495
+ format_checker = oas30_format_checker ,
496
+ )
497
+
498
+ result = validator .validate ({"testfield" : "John" })
499
+ assert result is None
500
+
501
+ if is_nullable :
502
+ result = validator .validate ({"testfield" : None })
503
+ assert result is None
504
+ else :
505
+ with pytest .raises (
506
+ ValidationError ,
507
+ match = "None for not nullable" ,
508
+ ):
509
+ validator .validate ({"testfield" : None })
510
+ assert False
511
+
512
+
513
+ @pytest .mark .parametrize (
514
+ "schema_type, not_nullable_regex" ,
515
+ [
516
+ ("oneOf" , "None is not valid under any of the given schemas" ),
517
+ ("anyOf" , "None is not valid under any of the given schemas" ),
518
+ ("allOf" , "None for not nullable" )
519
+ ],
520
+ )
521
+ @pytest .mark .parametrize ("is_nullable" , [True , False ])
522
+ def test_nullable_schema_combos (self , is_nullable , schema_type , not_nullable_regex ):
523
+ """
524
+ This test ensures that nullablilty semantics are correct for oneOf, anyOf and allOf
525
+ Specifically, nullable should checked on the children schemas
526
+ :param is_nullable: if the schema is marked as nullable. If not, validate an exception is raised on None
527
+ :param schema_type: the schema type to validate
528
+ :param not_nullable_regex: the expected raised exception if fields are marked as not nullable
529
+ """
530
+ schema = {
531
+ "$ref" : "#/$defs/Pet" ,
532
+ "$defs" : {
533
+ "NullableText" : {
534
+ "type" : "string" ,
535
+ "nullable" : False if schema_type == "oneOf" else is_nullable
536
+ },
537
+ "NullableEnum" : {
538
+ "type" : "string" ,
539
+ "nullable" : is_nullable ,
540
+ "enum" : ["John" , "Alice" , None ]
541
+ },
542
+ "Pet" : {
543
+ "properties" : {
544
+ "testfield" : {
545
+ schema_type : [
546
+ {"$ref" : "#/$defs/NullableText" },
547
+ {"$ref" : "#/$defs/NullableEnum" },
548
+ ]
549
+ }
550
+ },
551
+ }
552
+ },
553
+ }
554
+ validator = OAS30Validator (
555
+ schema ,
556
+ format_checker = oas30_format_checker ,
557
+ )
558
+
559
+ if is_nullable :
560
+ result = validator .validate ({"testfield" : None })
561
+ assert result is None
562
+ else :
563
+ with pytest .raises (
564
+ ValidationError ,
565
+ match = not_nullable_regex
566
+ ):
567
+ validator .validate ({"testfield" : None })
568
+ assert False
445
569
446
570
class TestOAS31ValidatorValidate :
447
571
@pytest .mark .parametrize (
0 commit comments