fixed conditional errors with false schemas and unevaluatedProperties

This commit is contained in:
2025-06-12 22:27:49 -04:00
parent 1085964c17
commit cbda45e610
2 changed files with 197 additions and 11 deletions

View File

@ -335,7 +335,7 @@ fn test_validate_json_schema_oneof_validation_errors() {
let result_empty_obj = validate_json_schema(schema_id, jsonb(invalid_empty_obj));
// Now we expect 2 errors because required fields are split into individual errors
assert_failure_with_json!(result_empty_obj, 2);
let errors_empty = result_empty_obj.0["errors"].as_array().expect("Expected error array for empty object");
let errors_empty = result_empty_obj.0["errors"].as_array().unwrap();
assert_eq!(errors_empty.len(), 2, "Expected two errors for missing required fields");
// Check that we have errors for both missing fields
@ -628,6 +628,121 @@ fn test_auto_strict_validation() {
let result_permissive = validate_json_schema(schema_id_permissive, jsonb(instance_with_extra));
assert_success_with_json!(result_permissive, "Instance with extra property should pass when additionalProperties is explicitly true, even with strict=true");
// Test 7: Schema with conditionals (if/then/else) should NOT add unevaluatedProperties to conditional branches
let schema_id_conditional = "conditional_strict_test";
let conditional_schema = json!({
"type": "object",
"properties": {
"kind": { "type": "string", "enum": ["checking", "savings"] },
"creating": { "type": "boolean" }
},
"if": {
"properties": {
"creating": { "const": true }
}
},
"then": {
"properties": {
"account_number": {
"type": "string",
"pattern": "^[0-9]{4,17}$"
},
"routing_number": {
"type": "string",
"pattern": "^[0-9]{9}$"
}
},
"required": ["account_number", "routing_number"]
}
});
let _ = cache_json_schema(schema_id_conditional, jsonb(conditional_schema), true); // strict=true
// Valid data with properties from both main schema and then clause
let valid_conditional = json!({
"kind": "checking",
"creating": true,
"account_number": "1234567890",
"routing_number": "123456789"
});
let result_conditional = validate_json_schema(schema_id_conditional, jsonb(valid_conditional));
assert_success_with_json!(result_conditional, "Conditional properties should be recognized as evaluated");
// Invalid: extra property not defined anywhere
let invalid_conditional = json!({
"kind": "checking",
"creating": true,
"account_number": "1234567890",
"routing_number": "123456789",
"extra": "not allowed"
});
let result_invalid_conditional = validate_json_schema(schema_id_conditional, jsonb(invalid_conditional));
assert_failure_with_json!(result_invalid_conditional, 1, "Schema validation always fails");
let errors_conditional = result_invalid_conditional.0["errors"].as_array().unwrap();
assert_eq!(errors_conditional[0]["code"], "FALSE_SCHEMA");
assert_eq!(errors_conditional[0]["details"]["path"], "/extra");
// Test the specific edge case: pattern validation failure in a conditional branch
// We filter out FALSE_SCHEMA errors when there are other validation errors
let pattern_failure = json!({
"kind": "checking",
"creating": true,
"account_number": "22", // Too short - will fail pattern validation
"routing_number": "123456789" // Valid, but would be unevaluated - filtered out
});
let result_pattern = validate_json_schema(schema_id_conditional, jsonb(pattern_failure));
let pattern_errors = result_pattern.0["errors"].as_array().unwrap();
// We expect only 1 error: PATTERN_VIOLATED for account_number
// FALSE_SCHEMA for routing_number is filtered out because there's a real validation error
assert_failure_with_json!(result_pattern, 1);
assert_eq!(pattern_errors[0]["code"], "PATTERN_VIOLATED");
assert_eq!(pattern_errors[0]["details"]["path"], "/account_number");
// Test case where both fields have pattern violations
let both_pattern_failures = json!({
"kind": "checking",
"creating": true,
"account_number": "22", // Too short - will fail pattern validation
"routing_number": "123" // Too short - will fail pattern validation
});
let result_both = validate_json_schema(schema_id_conditional, jsonb(both_pattern_failures));
let both_errors = result_both.0["errors"].as_array().unwrap();
// We expect 2 errors: both PATTERN_VIOLATED
assert_failure_with_json!(result_both, 2);
assert!(both_errors.iter().any(|e|
e["code"] == "PATTERN_VIOLATED" &&
e["details"]["path"] == "/account_number"
), "Should have pattern violation for account_number");
assert!(both_errors.iter().any(|e|
e["code"] == "PATTERN_VIOLATED" &&
e["details"]["path"] == "/routing_number"
), "Should have pattern violation for routing_number");
// Test case where there are only FALSE_SCHEMA errors (no other validation errors)
let only_false_schema = json!({
"kind": "checking",
"creating": true,
"account_number": "1234567890", // Valid
"routing_number": "123456789", // Valid
"extra": "not allowed" // Will cause FALSE_SCHEMA
});
let result_only_false = validate_json_schema(schema_id_conditional, jsonb(only_false_schema));
let only_false_errors = result_only_false.0["errors"].as_array().unwrap();
// We expect 1 FALSE_SCHEMA error since there are no other validation errors
assert_failure_with_json!(result_only_false, 1);
assert_eq!(only_false_errors[0]["code"], "FALSE_SCHEMA");
assert_eq!(only_false_errors[0]["details"]["path"], "/extra");
}
#[pg_test]