Issue5055Test.java
package io.swagger.v3.core.converting;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.swagger.v3.core.converter.ModelConverters;
import io.swagger.v3.core.converter.ResolvedSchema;
import io.swagger.v3.core.util.Json31;
import io.swagger.v3.oas.annotations.media.ArraySchema;
import org.testng.annotations.Test;
import java.util.List;
import static org.testng.Assert.*;
/**
* test documenting the behavior of sibling @Schema and @ArraySchema annotations.
*/
public class Issue5055Test {
@Test
public void testArrayMetadataDoesNotLeakToItemsRef() throws Exception {
ResolvedSchema schema = ModelConverters.getInstance(true).readAllAsResolvedSchema(
TestModels.ArrayWithFullMetadata.class
);
assertNotNull(schema, "Schema should resolve");
String json = Json31.pretty(schema);
assertNotNull(json);
ObjectMapper mapper = new ObjectMapper();
JsonNode root = mapper.readTree(json);
JsonNode itemsProp = root.at("/schema/properties/pets");
assertFalse(itemsProp.isMissingNode(), "pets property should exist");
assertEquals(itemsProp.get("type").asText(), "array", "Should be array type");
assertEquals(itemsProp.get("description").asText(), "Collection of pets", "Array should have description");
assertEquals(itemsProp.get("minItems").asInt(), 1, "Array should have minItems");
assertEquals(itemsProp.get("maxItems").asInt(), 100, "Array should have maxItems");
assertTrue(itemsProp.get("uniqueItems").asBoolean(), "Array should have uniqueItems");
JsonNode items = itemsProp.get("items");
assertNotNull(items, "Items should exist");
assertTrue(items.has("$ref"), "Items should be a reference");
assertFalse(items.has("minItems"), "BUG: minItems leaked to items $ref");
assertFalse(items.has("maxItems"), "BUG: maxItems leaked to items $ref");
assertFalse(items.has("uniqueItems"), "BUG: uniqueItems leaked to items $ref");
assertFalse(items.has("description") && items.get("description") != null,
"BUG: array description leaked to items $ref");
if (items.has("type")) {
assertTrue(items.get("type").isNull() || items.get("type").asText().isEmpty(),
"BUG: type value leaked to items $ref");
}
}
@Test
public void testComponentSchemaIsCleanWithoutLeakedProperties() throws Exception {
ResolvedSchema schema = ModelConverters.getInstance(true).readAllAsResolvedSchema(
TestModels.ArrayWithFullMetadata.class
);
assertNotNull(schema);
assertNotNull(schema.referencedSchemas);
io.swagger.v3.oas.models.media.Schema petSchema = schema.referencedSchemas.get("Pet");
assertNotNull(petSchema, "Pet component schema should exist");
assertNull(petSchema.getMinItems(), "Component schema should not have minItems");
assertNull(petSchema.getMaxItems(), "Component schema should not have maxItems");
assertNull(petSchema.getUniqueItems(), "Component schema should not have uniqueItems");
if (petSchema.getDescription() != null) {
assertNotEquals(petSchema.getDescription(), "Collection of pets",
"Component should not have array's description");
}
}
@Test
public void testArraySchemaAttributesSeparation() throws Exception {
ResolvedSchema schema = ModelConverters.getInstance(true).readAllAsResolvedSchema(
TestModels.BothArraySchemaAttributes.class
);
assertNotNull(schema);
String json = Json31.pretty(schema);
ObjectMapper mapper = new ObjectMapper();
JsonNode root = mapper.readTree(json);
JsonNode dataField = root.at("/schema/properties/data");
if (!dataField.isMissingNode()) {
assertTrue(dataField.has("description"));
assertEquals(dataField.get("type").asText(), "array");
JsonNode items = dataField.get("items");
assertNotNull(items);
assertTrue(items.has("description") || items.has("$ref"));
}
}
@Test
public void testTypeInferenceWithNoImplementation() throws Exception {
ResolvedSchema schema = ModelConverters.getInstance(true).readAllAsResolvedSchema(
TestModels.NoImplementationSpecified.class
);
assertNotNull(schema);
String json = Json31.pretty(schema);
ObjectMapper mapper = new ObjectMapper();
JsonNode root = mapper.readTree(json);
JsonNode dataField = root.at("/schema/properties/data");
assertEquals(dataField.get("type").asText(), "array");
JsonNode items = dataField.get("items");
assertNotNull(items);
if (items.has("type")) {
assertEquals(items.get("type").asText(), "string");
}
}
@Test
public void testSchemaEqualsSemanticsForPrecedence() {
io.swagger.v3.oas.models.media.Schema unchanged = new io.swagger.v3.oas.models.media.Schema();
unchanged.setType("array");
io.swagger.v3.oas.models.media.Schema alsoUnchanged = new io.swagger.v3.oas.models.media.Schema();
alsoUnchanged.setType("array");
assertEquals(unchanged, alsoUnchanged, "Equal content should be detected");
io.swagger.v3.oas.models.media.Schema changed = new io.swagger.v3.oas.models.media.Schema();
changed.setType("array");
changed.setDescription("added");
assertNotEquals(unchanged, changed, "Changes should be detected by equals");
}
@Test
public void testSchemaEqualsIncludesExtensions() {
io.swagger.v3.oas.models.media.Schema s1 = new io.swagger.v3.oas.models.media.Schema();
s1.addExtension("x-prop", "value");
io.swagger.v3.oas.models.media.Schema s2 = new io.swagger.v3.oas.models.media.Schema();
s2.addExtension("x-prop", "value");
assertEquals(s1, s2, "Same extensions should be equal");
io.swagger.v3.oas.models.media.Schema s3 = new io.swagger.v3.oas.models.media.Schema();
s3.addExtension("x-prop", "different");
assertNotEquals(s1, s3, "Different extensions should not be equal");
}
@Test
public void testNoImplementationCase() throws Exception {
ResolvedSchema schema = ModelConverters.getInstance(true).readAllAsResolvedSchema(
TestModels.NoImplementationSpecified.class
);
assertNotNull(schema);
String json = Json31.pretty(schema);
ObjectMapper mapper = new ObjectMapper();
JsonNode root = mapper.readTree(json);
JsonNode dataField = root.at("/schema/properties/data");
assertFalse(dataField.isMissingNode(), "data property should exist");
assertEquals(dataField.get("type").asText(), "array");
assertEquals(dataField.get("description").asText(), "Inferred from type");
JsonNode items = dataField.get("items");
assertNotNull(items);
assertEquals(items.get("type").asText(), "string", "Items should infer string type");
}
@Test
public void testNoSchemaAtAllCase() throws Exception {
ResolvedSchema schema = ModelConverters.getInstance(true).readAllAsResolvedSchema(
TestModels.NoSchemaAnnotations.class
);
assertNotNull(schema);
String json = Json31.pretty(schema);
ObjectMapper mapper = new ObjectMapper();
JsonNode root = mapper.readTree(json);
JsonNode dataField = root.at("/schema/properties/data");
assertFalse(dataField.isMissingNode(), "data property should exist");
assertEquals(dataField.get("type").asText(), "array");
JsonNode items = dataField.get("items");
assertNotNull(items);
assertEquals(items.get("type").asText(), "string", "Items should infer string type from List<String>");
}
public static class TestModels {
@io.swagger.v3.oas.annotations.media.Schema(description = "Model with full array metadata")
public static class ArrayWithFullMetadata {
private List<Pet> pets;
@ArraySchema(
schema = @io.swagger.v3.oas.annotations.media.Schema(implementation = Pet.class),
arraySchema = @io.swagger.v3.oas.annotations.media.Schema(
type = "array",
description = "Collection of pets"
),
minItems = 1,
maxItems = 100,
uniqueItems = true
)
public List<Pet> getPets() {
return pets;
}
}
@io.swagger.v3.oas.annotations.media.Schema(description = "Pet model")
public static class Pet {
private String name;
private String species;
public String getName() {
return name;
}
public String getSpecies() {
return species;
}
}
@io.swagger.v3.oas.annotations.media.Schema(description = "Test precedence")
public static class SchemaTakesPrecedence {
private List<String> data;
@io.swagger.v3.oas.annotations.media.Schema(type = "array", description = "Schema description")
@ArraySchema(minItems = 10)
public List<String> getData() {
return data;
}
}
@io.swagger.v3.oas.annotations.media.Schema(description = "Test both attributes")
public static class BothArraySchemaAttributes {
private List<String> data;
@ArraySchema(
schema = @io.swagger.v3.oas.annotations.media.Schema(type = "string", description = "Item description"),
arraySchema = @io.swagger.v3.oas.annotations.media.Schema(type = "array", description = "Array description")
)
public List<String> getData() {
return data;
}
}
@io.swagger.v3.oas.annotations.media.Schema(description = "Test no implementation")
public static class NoImplementationSpecified {
private List<String> data;
@io.swagger.v3.oas.annotations.media.Schema(description = "Inferred from type")
public List<String> getData() {
return data;
}
}
@io.swagger.v3.oas.annotations.media.Schema(description = "Test no schema annotations")
public static class NoSchemaAnnotations {
private List<String> data;
public List<String> getData() {
return data;
}
}
}
}