1 package com.networknt.schema; 2 3 import com.fasterxml.jackson.databind.JsonNode; 4 import org.junit.jupiter.api.BeforeAll; 5 import org.junit.jupiter.api.Test; 6 7 import java.io.IOException; 8 import java.util.List; 9 import java.util.Set; 10 11 import static java.util.stream.Collectors.toList; 12 import static org.junit.jupiter.api.Assertions.assertTrue; 13 14 public class Issue662Test extends BaseJsonSchemaValidatorTest { 15 16 private static final String RESOURCE_PREFIX = "issues/662/"; 17 private static JsonSchema schema; 18 19 @BeforeAll setup()20 static void setup() { 21 schema = getJsonSchemaFromClasspath(resource("schema.json"), SpecVersion.VersionFlag.V7); 22 } 23 24 @Test testNoErrorsForEmptyObject()25 void testNoErrorsForEmptyObject() throws IOException { 26 JsonNode node = getJsonNodeFromClasspath(resource("emptyObject.json")); 27 Set<ValidationMessage> errors = schema.validate(node); 28 assertTrue(errors.isEmpty(), "No validation errors for empty optional object"); 29 } 30 31 @Test testNoErrorsForValidObject()32 void testNoErrorsForValidObject() throws IOException { 33 JsonNode node = getJsonNodeFromClasspath(resource("validObject.json")); 34 Set<ValidationMessage> errors = schema.validate(node); 35 assertTrue(errors.isEmpty(), "No validation errors for a valid optional object"); 36 } 37 38 @Test testCorrectErrorForInvalidValue()39 void testCorrectErrorForInvalidValue() throws IOException { 40 JsonNode node = getJsonNodeFromClasspath(resource("objectInvalidValue.json")); 41 Set<ValidationMessage> errors = schema.validate(node); 42 List<String> errorMessages = errors.stream() 43 .map(v -> v.getEvaluationPath() + " = " + v.getMessage()) 44 .collect(toList()); 45 46 // As this is from an anyOf evaluation both error messages should be present as they didn't match any 47 // The evaluation cannot be expected to know the semantic meaning that this is an optional object 48 // The evaluation path can be used to provide clarity on the reason 49 // Omitting the 'object found, null expected' message also provides the misleading impression that the 50 // object is required when leaving it empty is a possible option 51 assertTrue(errorMessages 52 .contains("$.properties.optionalObject.anyOf[0].type = $.optionalObject: object found, null expected")); 53 assertTrue(errorMessages.contains( 54 "$.properties.optionalObject.anyOf[1].properties.value.enum = $.optionalObject.value: does not have a value in the enumeration [one, two]")); 55 } 56 resource(String name)57 private static String resource(String name) { 58 return RESOURCE_PREFIX + name; 59 } 60 } 61