|
19 | 19 | from openapi_schema_validator import OAS30Validator |
20 | 20 | from openapi_schema_validator import OAS30WriteValidator |
21 | 21 | from openapi_schema_validator import OAS31Validator |
| 22 | +from openapi_schema_validator import OAS32Validator |
22 | 23 | from openapi_schema_validator import oas30_format_checker |
23 | 24 | from openapi_schema_validator import oas30_strict_format_checker |
24 | 25 | from openapi_schema_validator import oas31_format_checker |
| 26 | +from openapi_schema_validator import oas32_format_checker |
25 | 27 |
|
26 | 28 |
|
27 | 29 | class TestOAS30ValidatorFormatChecker: |
@@ -1003,6 +1005,206 @@ def test_array_prefixitems_invalid(self, validator_class, value): |
1003 | 1005 | assert any(error in str(excinfo.value) for error in errors) |
1004 | 1006 |
|
1005 | 1007 |
|
| 1008 | +class TestOAS32ValidatorFormatChecker: |
| 1009 | + @pytest.fixture |
| 1010 | + def format_checker(self): |
| 1011 | + return OAS32Validator.FORMAT_CHECKER |
| 1012 | + |
| 1013 | + def test_required_checkers(self, format_checker): |
| 1014 | + required_formats_set = { |
| 1015 | + # standard formats |
| 1016 | + "int32", |
| 1017 | + "int64", |
| 1018 | + "float", |
| 1019 | + "double", |
| 1020 | + "password", |
| 1021 | + } |
| 1022 | + assert required_formats_set.issubset( |
| 1023 | + set(format_checker.checkers.keys()) |
| 1024 | + ) |
| 1025 | + |
| 1026 | + |
| 1027 | +class TestOAS32ValidatorValidate(BaseTestOASValidatorValidate): |
| 1028 | + @pytest.fixture |
| 1029 | + def validator_class(self): |
| 1030 | + return OAS32Validator |
| 1031 | + |
| 1032 | + @pytest.fixture |
| 1033 | + def format_checker(self): |
| 1034 | + return oas32_format_checker |
| 1035 | + |
| 1036 | + @pytest.mark.parametrize("value", [b"test"]) |
| 1037 | + def test_string_disallow_binary(self, validator_class, value): |
| 1038 | + schema = {"type": "string"} |
| 1039 | + validator = validator_class(schema) |
| 1040 | + |
| 1041 | + with pytest.raises(ValidationError): |
| 1042 | + validator.validate(value) |
| 1043 | + |
| 1044 | + @pytest.mark.parametrize( |
| 1045 | + "schema_type", |
| 1046 | + [ |
| 1047 | + "boolean", |
| 1048 | + "array", |
| 1049 | + "integer", |
| 1050 | + "number", |
| 1051 | + "string", |
| 1052 | + ], |
| 1053 | + ) |
| 1054 | + def test_null(self, validator_class, schema_type): |
| 1055 | + schema = {"type": schema_type} |
| 1056 | + validator = validator_class(schema) |
| 1057 | + value = None |
| 1058 | + |
| 1059 | + with pytest.raises(ValidationError): |
| 1060 | + validator.validate(value) |
| 1061 | + |
| 1062 | + @pytest.mark.parametrize( |
| 1063 | + "schema_type", |
| 1064 | + [ |
| 1065 | + "boolean", |
| 1066 | + "array", |
| 1067 | + "integer", |
| 1068 | + "number", |
| 1069 | + "string", |
| 1070 | + ], |
| 1071 | + ) |
| 1072 | + def test_nullable(self, validator_class, schema_type): |
| 1073 | + schema = {"type": [schema_type, "null"]} |
| 1074 | + validator = validator_class(schema) |
| 1075 | + value = None |
| 1076 | + |
| 1077 | + result = validator.validate(value) |
| 1078 | + |
| 1079 | + assert result is None |
| 1080 | + |
| 1081 | + def test_schema_validation(self, validator_class, format_checker): |
| 1082 | + schema = { |
| 1083 | + "type": "object", |
| 1084 | + "required": ["name"], |
| 1085 | + "properties": { |
| 1086 | + "name": {"type": "string"}, |
| 1087 | + "age": { |
| 1088 | + "type": "integer", |
| 1089 | + "format": "int32", |
| 1090 | + "minimum": 0, |
| 1091 | + }, |
| 1092 | + "birth-date": { |
| 1093 | + "type": "string", |
| 1094 | + "format": "date", |
| 1095 | + }, |
| 1096 | + }, |
| 1097 | + "additionalProperties": False, |
| 1098 | + } |
| 1099 | + validator = validator_class( |
| 1100 | + schema, |
| 1101 | + format_checker=format_checker, |
| 1102 | + ) |
| 1103 | + |
| 1104 | + result = validator.validate({"name": "John", "age": 23}) |
| 1105 | + assert result is None |
| 1106 | + |
| 1107 | + with pytest.raises(ValidationError) as excinfo: |
| 1108 | + validator.validate({"name": "John", "city": "London"}) |
| 1109 | + |
| 1110 | + error = "Additional properties are not allowed ('city' was unexpected)" |
| 1111 | + assert error in str(excinfo.value) |
| 1112 | + |
| 1113 | + with pytest.raises(ValidationError) as excinfo: |
| 1114 | + validator.validate({"name": "John", "birth-date": "-12"}) |
| 1115 | + |
| 1116 | + error = "'-12' is not a 'date'" |
| 1117 | + assert error in str(excinfo.value) |
| 1118 | + |
| 1119 | + def test_schema_ref(self, validator_class, format_checker): |
| 1120 | + schema = { |
| 1121 | + "$ref": "#/$defs/Pet", |
| 1122 | + "$defs": { |
| 1123 | + "Pet": { |
| 1124 | + "required": ["id", "name"], |
| 1125 | + "properties": { |
| 1126 | + "id": {"type": "integer", "format": "int64"}, |
| 1127 | + "name": {"type": "string"}, |
| 1128 | + "tag": {"type": "string"}, |
| 1129 | + }, |
| 1130 | + } |
| 1131 | + }, |
| 1132 | + } |
| 1133 | + validator = validator_class( |
| 1134 | + schema, |
| 1135 | + format_checker=format_checker, |
| 1136 | + ) |
| 1137 | + |
| 1138 | + result = validator.validate({"id": 1, "name": "John"}) |
| 1139 | + assert result is None |
| 1140 | + |
| 1141 | + with pytest.raises(ValidationError) as excinfo: |
| 1142 | + validator.validate({"name": "John"}) |
| 1143 | + |
| 1144 | + error = "'id' is a required property" |
| 1145 | + assert error in str(excinfo.value) |
| 1146 | + |
| 1147 | + @pytest.mark.parametrize( |
| 1148 | + "value", |
| 1149 | + [ |
| 1150 | + [1600, "Pennsylvania", "Avenue", "NW"], |
| 1151 | + [1600, "Pennsylvania", "Avenue"], |
| 1152 | + ], |
| 1153 | + ) |
| 1154 | + def test_array_prefixitems(self, validator_class, format_checker, value): |
| 1155 | + schema = { |
| 1156 | + "type": "array", |
| 1157 | + "prefixItems": [ |
| 1158 | + {"type": "number"}, |
| 1159 | + {"type": "string"}, |
| 1160 | + {"enum": ["Street", "Avenue", "Boulevard"]}, |
| 1161 | + {"enum": ["NW", "NE", "SW", "SE"]}, |
| 1162 | + ], |
| 1163 | + "items": False, |
| 1164 | + } |
| 1165 | + validator = validator_class( |
| 1166 | + schema, |
| 1167 | + format_checker=format_checker, |
| 1168 | + ) |
| 1169 | + |
| 1170 | + result = validator.validate(value) |
| 1171 | + |
| 1172 | + assert result is None |
| 1173 | + |
| 1174 | + @pytest.mark.parametrize( |
| 1175 | + "value", |
| 1176 | + [ |
| 1177 | + [1600, "Pennsylvania", "Avenue", "NW", "Washington"], |
| 1178 | + ], |
| 1179 | + ) |
| 1180 | + def test_array_prefixitems_invalid(self, validator_class, value): |
| 1181 | + schema = { |
| 1182 | + "type": "array", |
| 1183 | + "prefixItems": [ |
| 1184 | + {"type": "number"}, |
| 1185 | + {"type": "string"}, |
| 1186 | + {"enum": ["Street", "Avenue", "Boulevard"]}, |
| 1187 | + {"enum": ["NW", "NE", "SW", "SE"]}, |
| 1188 | + ], |
| 1189 | + "items": False, |
| 1190 | + } |
| 1191 | + validator = validator_class( |
| 1192 | + schema, |
| 1193 | + format_checker=oas32_format_checker, |
| 1194 | + ) |
| 1195 | + |
| 1196 | + with pytest.raises(ValidationError) as excinfo: |
| 1197 | + validator.validate(value) |
| 1198 | + |
| 1199 | + errors = [ |
| 1200 | + # jsonschema < 4.20.0 |
| 1201 | + "Expected at most 4 items, but found 5", |
| 1202 | + # jsonschema >= 4.20.0 |
| 1203 | + "Expected at most 4 items but found 1 extra", |
| 1204 | + ] |
| 1205 | + assert any(error in str(excinfo.value) for error in errors) |
| 1206 | + |
| 1207 | + |
1006 | 1208 | class TestOAS30StrictValidator: |
1007 | 1209 | """ |
1008 | 1210 | Tests for OAS30StrictValidator which follows OAS spec strictly: |
|
0 commit comments