bringing back type constants for validation via new overrides vocabulary
This commit is contained in:
109
src/tests.rs
109
src/tests.rs
@ -824,8 +824,8 @@ fn test_validate_type_matching() {
|
||||
"job_id": "job123"
|
||||
});
|
||||
let result_invalid_job = validate_json_schema("job", jsonb(invalid_job));
|
||||
assert_error_count(&result_invalid_job, 1);
|
||||
assert_has_error(&result_invalid_job, "TYPE_MISMATCH", "/type");
|
||||
assert_failure(&result_invalid_job);
|
||||
assert_has_error(&result_invalid_job, "CONST_VIOLATED", "/type");
|
||||
|
||||
// 2. Test 'super_job' which extends 'job'
|
||||
let valid_super_job = json!({
|
||||
@ -854,9 +854,8 @@ fn test_validate_type_matching() {
|
||||
"manager_id": "mgr1"
|
||||
});
|
||||
let result_invalid_short = validate_json_schema("super_job.short", jsonb(invalid_short_super_job));
|
||||
assert_error_count(&result_invalid_short, 1);
|
||||
let error = find_error_with_code_and_path(&result_invalid_short, "TYPE_MISMATCH", "/type");
|
||||
assert_error_message_contains(error, "Instance type 'job' does not match expected type 'super_job'");
|
||||
assert_failure(&result_invalid_short);
|
||||
assert_has_error(&result_invalid_short, "CONST_VIOLATED", "/type");
|
||||
|
||||
// 4. Test punc with root, nested, and oneOf type refs
|
||||
let valid_punc_instance = json!({
|
||||
@ -890,8 +889,8 @@ fn test_validate_type_matching() {
|
||||
}
|
||||
});
|
||||
let result_invalid_punc_root = validate_json_schema("type_test_punc.request", jsonb(invalid_punc_root));
|
||||
assert_error_count(&result_invalid_punc_root, 1);
|
||||
assert_has_error(&result_invalid_punc_root, "TYPE_MISMATCH", "/root_job/type");
|
||||
assert_failure(&result_invalid_punc_root);
|
||||
assert_has_error(&result_invalid_punc_root, "CONST_VIOLATED", "/root_job/type");
|
||||
|
||||
// 6. Test invalid type at punc nested ref
|
||||
let invalid_punc_nested = json!({
|
||||
@ -909,8 +908,8 @@ fn test_validate_type_matching() {
|
||||
}
|
||||
});
|
||||
let result_invalid_punc_nested = validate_json_schema("type_test_punc.request", jsonb(invalid_punc_nested));
|
||||
assert_error_count(&result_invalid_punc_nested, 1);
|
||||
assert_has_error(&result_invalid_punc_nested, "TYPE_MISMATCH", "/nested_or_super_job/my_job/type");
|
||||
assert_failure(&result_invalid_punc_nested);
|
||||
assert_has_error(&result_invalid_punc_nested, "CONST_VIOLATED", "/nested_or_super_job/my_job/type");
|
||||
|
||||
// 7. Test invalid type at punc oneOf ref
|
||||
let invalid_punc_oneof = json!({
|
||||
@ -927,8 +926,8 @@ fn test_validate_type_matching() {
|
||||
}
|
||||
});
|
||||
let result_invalid_punc_oneof = validate_json_schema("type_test_punc.request", jsonb(invalid_punc_oneof));
|
||||
// This will have multiple errors because the invalid oneOf branch will also fail the other branch's validation
|
||||
assert_has_error(&result_invalid_punc_oneof, "TYPE_MISMATCH", "/nested_or_super_job/type");
|
||||
assert_failure(&result_invalid_punc_oneof);
|
||||
assert_has_error(&result_invalid_punc_oneof, "CONST_VIOLATED", "/nested_or_super_job/type");
|
||||
}
|
||||
|
||||
#[pg_test]
|
||||
@ -939,6 +938,7 @@ fn test_validate_union_type_matching() {
|
||||
// 1. Test valid instance with type 'union_a'
|
||||
let valid_instance_a = json!({
|
||||
"union_prop": {
|
||||
"id": "123",
|
||||
"type": "union_a",
|
||||
"prop_a": "hello"
|
||||
}
|
||||
@ -949,6 +949,7 @@ fn test_validate_union_type_matching() {
|
||||
// 2. Test valid instance with type 'union_b'
|
||||
let valid_instance_b = json!({
|
||||
"union_prop": {
|
||||
"id": "456",
|
||||
"type": "union_b",
|
||||
"prop_b": 123
|
||||
}
|
||||
@ -956,50 +957,30 @@ fn test_validate_union_type_matching() {
|
||||
let result_b = validate_json_schema("union_test.request", jsonb(valid_instance_b));
|
||||
assert_success(&result_b);
|
||||
|
||||
// 3. Test invalid instance - correct type, but fails sub-schema validation
|
||||
// 3. Test invalid instance - wrong type const in a valid oneOf branch
|
||||
let invalid_sub_schema = json!({
|
||||
"union_prop": {
|
||||
"type": "union_a",
|
||||
"prop_a": 123 // prop_a should be a string
|
||||
"id": "789",
|
||||
"type": "union_b", // Should be union_a
|
||||
"prop_a": "hello"
|
||||
}
|
||||
});
|
||||
let result_invalid_sub = validate_json_schema("union_test.request", jsonb(invalid_sub_schema));
|
||||
// Expect 4 errors because the instance fails validation against all 3 sub-schemas for different reasons,
|
||||
// and the error collector flattens all unique-path errors.
|
||||
assert_error_count(&result_invalid_sub, 4);
|
||||
// The "correct" error from the matched branch 'union_a'
|
||||
assert_has_error(&result_invalid_sub, "TYPE_MISMATCH", "/union_prop/prop_a");
|
||||
// Noise from failing the 'union_b' schema
|
||||
assert_failure(&result_invalid_sub);
|
||||
// This should fail because the `type` override in `union_a` is `const: "union_a"`
|
||||
assert_has_error(&result_invalid_sub, "CONST_VIOLATED", "/union_prop/type");
|
||||
assert_has_error(&result_invalid_sub, "REQUIRED_FIELD_MISSING", "/union_prop/prop_b");
|
||||
// Noise from failing the 'union_c' schema
|
||||
assert_has_error(&result_invalid_sub, "REQUIRED_FIELD_MISSING", "/union_prop/prop_c");
|
||||
|
||||
// 4. Test invalid instance - type does not match any union member
|
||||
let invalid_type = json!({
|
||||
// 4. Test invalid instance - base type, should fail due to override
|
||||
let invalid_base_type = json!({
|
||||
"union_prop": {
|
||||
"type": "union_d", // not a valid type in the oneOf
|
||||
"prop_d": "whatever"
|
||||
"id": "101",
|
||||
"type": "union_base", // This is the base type, but the override should be enforced
|
||||
"prop_a": "world"
|
||||
}
|
||||
});
|
||||
let result_invalid_type = validate_json_schema("union_test.request", jsonb(invalid_type));
|
||||
assert_error_count(&result_invalid_type, 4);
|
||||
assert_has_error(&result_invalid_type, "CONST_VIOLATED", "/union_prop/type");
|
||||
assert_has_error(&result_invalid_type, "REQUIRED_FIELD_MISSING", "/union_prop/prop_a");
|
||||
assert_has_error(&result_invalid_type, "REQUIRED_FIELD_MISSING", "/union_prop/prop_b");
|
||||
assert_has_error(&result_invalid_type, "REQUIRED_FIELD_MISSING", "/union_prop/prop_c");
|
||||
|
||||
// 5. Test invalid instance - missing 'type' property for union
|
||||
let missing_type = json!({
|
||||
"union_prop": {
|
||||
"prop_a": "hello" // no 'type' field
|
||||
}
|
||||
});
|
||||
let result_missing_type = validate_json_schema("union_test.request", jsonb(missing_type));
|
||||
assert_error_count(&result_missing_type, 3);
|
||||
assert_has_error(&result_missing_type, "REQUIRED_FIELD_MISSING", "/union_prop/type");
|
||||
assert_has_error(&result_missing_type, "REQUIRED_FIELD_MISSING", "/union_prop/prop_b");
|
||||
assert_has_error(&result_missing_type, "REQUIRED_FIELD_MISSING", "/union_prop/prop_c");
|
||||
let result_invalid_base = validate_json_schema("union_test.request", jsonb(invalid_base_type));
|
||||
assert_failure(&result_invalid_base);
|
||||
assert_has_error(&result_invalid_base, "CONST_VIOLATED", "/union_prop/type");
|
||||
}
|
||||
|
||||
#[pg_test]
|
||||
@ -1007,30 +988,52 @@ fn test_validate_nullable_union() {
|
||||
let cache_result = nullable_union_schemas();
|
||||
assert_success(&cache_result);
|
||||
|
||||
// 1. Test valid instance with the object type
|
||||
let valid_object = json!({
|
||||
// 1. Test valid instance with object type 'thing_a'
|
||||
let valid_object_a = json!({
|
||||
"nullable_prop": {
|
||||
"id": "123",
|
||||
"type": "thing_a",
|
||||
"prop_a": "hello"
|
||||
}
|
||||
});
|
||||
let result_obj = validate_json_schema("nullable_union_test.request", jsonb(valid_object));
|
||||
assert_success(&result_obj);
|
||||
let result_obj_a = validate_json_schema("nullable_union_test.request", jsonb(valid_object_a));
|
||||
assert_success(&result_obj_a);
|
||||
|
||||
// 2. Test valid instance with null
|
||||
// 2. Test valid instance with object type 'thing_b'
|
||||
let valid_object_b = json!({
|
||||
"nullable_prop": {
|
||||
"id": "456",
|
||||
"type": "thing_b",
|
||||
"prop_b": "goodbye"
|
||||
}
|
||||
});
|
||||
let result_obj_b = validate_json_schema("nullable_union_test.request", jsonb(valid_object_b));
|
||||
assert_success(&result_obj_b);
|
||||
|
||||
// 3. Test valid instance with null
|
||||
let valid_null = json!({
|
||||
"nullable_prop": null
|
||||
});
|
||||
let result_null = validate_json_schema("nullable_union_test.request", jsonb(valid_null));
|
||||
assert_success(&result_null);
|
||||
|
||||
// 3. Test invalid instance (e.g., a string)
|
||||
// 4. Test invalid instance - base type, should fail due to override
|
||||
let invalid_base_type = json!({
|
||||
"nullable_prop": {
|
||||
"id": "789",
|
||||
"type": "thing_base",
|
||||
"prop_a": "should fail"
|
||||
}
|
||||
});
|
||||
let result_invalid_base = validate_json_schema("nullable_union_test.request", jsonb(invalid_base_type));
|
||||
assert_failure(&result_invalid_base);
|
||||
assert_has_error(&result_invalid_base, "CONST_VIOLATED", "/nullable_prop/type");
|
||||
|
||||
// 5. Test invalid instance (e.g., a string)
|
||||
let invalid_string = json!({
|
||||
"nullable_prop": "not_an_object_or_null"
|
||||
});
|
||||
let result_invalid = validate_json_schema("nullable_union_test.request", jsonb(invalid_string));
|
||||
assert_failure(&result_invalid);
|
||||
// The boon validator will report that the string doesn't match either schema in the oneOf.
|
||||
// We expect at least one TYPE_MISMATCH error at the path of the property.
|
||||
assert_has_error(&result_invalid, "TYPE_MISMATCH", "/nullable_prop");
|
||||
}
|
||||
Reference in New Issue
Block a user