Skip to content

Commit

Permalink
Add tests for ref processing changes
Browse files Browse the repository at this point in the history
Code refactoring
  • Loading branch information
andurairaj committed May 1, 2024
1 parent e32eace commit 18400a0
Show file tree
Hide file tree
Showing 29 changed files with 1,430 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -195,13 +195,11 @@ public String processRefToExternalSchema(String $ref, RefFormat refFormat) {
.filter(Objects::nonNull)
.flatMap(Collection::stream)
.forEach(s -> {
if (s.get$ref() != null){
if (s.get$ref() != null){
if (s.get$ref() != null) {
processRefSchema(s, file);
}else{
} else {
processSchema(s, file);
}
}
});
} else {
if (arraySchema.getItems() instanceof ComposedSchema) {
Expand Down Expand Up @@ -266,7 +264,6 @@ private void processSchema(Schema property, String file) {
}
if (property instanceof ComposedSchema) {
ComposedSchema composed = (ComposedSchema) property;
// Map to cache old - new refs in composed schemas
final Map<String, String> refMap = Optional.ofNullable(property.getDiscriminator())
.map(Discriminator::getMapping).orElse(Collections.emptyMap()).entrySet()
.stream().collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey));
Expand Down Expand Up @@ -948,18 +945,19 @@ public String processRefToExternalCallback(String $ref, RefFormat refFormat) {
} else {
for (String path : callback.keySet()) {
PathItem pathItem = callback.get(path);
if(pathItem.get$ref() != null) {
RefFormat pathRefFormat = computeRefFormat(pathItem.get$ref());
String path$ref = pathItem.get$ref();
if (isAnExternalRefFormat(refFormat)) {
pathItem = this.processRefToExternalPathItem(path$ref, pathRefFormat);
if(pathItem != null) {
if (pathItem.get$ref() != null) {
RefFormat pathRefFormat = computeRefFormat(pathItem.get$ref());
String path$ref = pathItem.get$ref();
if (isAnExternalRefFormat(refFormat)) {
pathItem = this.processRefToExternalPathItem(path$ref, pathRefFormat);
} else {
pathItem = cache.loadRef(pathItem.get$ref(), refFormat, PathItem.class);
}
callback.put(path, pathItem);
} else {
pathItem = cache.loadRef(pathItem.get$ref(), refFormat, PathItem.class);
this.processPathItem(pathItem, $ref);
}

callback.put(path, pathItem);
} else {
this.processPathItem(pathItem, $ref);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package io.swagger.v3.parser.test;


import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import org.junit.Before;
import org.junit.Test;
import org.testng.Assert;

import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.examples.Example;
import io.swagger.v3.oas.models.media.MediaType;
import io.swagger.v3.oas.models.media.Schema;
import io.swagger.v3.parser.OpenAPIV3Parser;
import io.swagger.v3.parser.core.models.ParseOptions;

import static io.swagger.v3.oas.models.Components.COMPONENTS_SCHEMAS_REF;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;


public class OpenAPIV3RefTest {
private OpenAPI oas;
@Before
public void parseOASSpec() {
ParseOptions options = new ParseOptions();
options.setResolve(true);
oas = new OpenAPIV3Parser().read("oas3-refs-test/openapi.json", null, options);
}
@Test
public void testParameterExampleRefProcessed() {
String paramName = "correlation_id";
Map<String, Example> paramExamples = oas.getComponents().getParameters().get(paramName).getExamples();
Assert.assertEquals(paramExamples.size(), 1, "Parameter has an example");
Assert.assertTrue(paramExamples.values()
.stream().allMatch(e -> e.get$ref().equalsIgnoreCase("#/components/examples/" + paramName)),
"Examples are referenced");
Assert.assertEquals(oas.getComponents().getExamples().get(paramName).getValue(), "7758b780aaaca",
"Examples are processed");
}

@Test
public void testDiscriminatorMappingRefsUpdated() {
Schema reqSchema = oas.getPaths().values().stream()
.findFirst()
.map(path -> path.getPost().getRequestBody().getContent().getOrDefault("application/json", null))
.map(MediaType::getSchema)
.orElseThrow(() -> new IllegalStateException("Path not processed!"));
Collection<String> discriminator = reqSchema.getDiscriminator().getMapping().values();
Set<String> allOfs = ((List<Schema>)reqSchema.getAnyOf())
.stream().map(Schema::get$ref).collect(Collectors.toSet());
assertTrue(allOfs.stream().allMatch(s -> s.contains(COMPONENTS_SCHEMAS_REF)),"Schema mappings are processed");
assertTrue(allOfs.containsAll(discriminator),"Discriminator mappings are updated");

}

@Test
public void testCallbackRef() {
assertEquals(oas.getComponents().getCallbacks().size(), 1, "Callbacks processed");
Operation cbOperation = oas.getComponents().getCallbacks()
.get("vaccination_complete")
.get("{$request.body#/callback_url}/pets/{$request.path.id}/vaccinations").getPut();
assertNotNull(cbOperation);
assertEquals(cbOperation.getRequestBody().getContent().get("application/json").getSchema().get$ref(),
COMPONENTS_SCHEMAS_REF + "vaccination_record", "Callback Request body processed");
assertEquals(cbOperation.getResponses().get("400").getContent().get("application/json").getSchema().get$ref(),
COMPONENTS_SCHEMAS_REF + "error" , "Callback responses Processed");
}

@Test
public void testComposedArrayItemsRef() {
Schema adoptionRequest = oas.getComponents()
.getSchemas().get("adoption_request");
assertEquals(adoptionRequest.getTitle(), "Adoption Request", "Processed ref Schemas");
assertEquals(((Schema) adoptionRequest.getProperties().get("adopter_alias")).get$ref(),
COMPONENTS_SCHEMAS_REF + "alias_array", "Processed ref added to Schemas");
Schema adopterAlias = ((Schema) oas.getComponents().getSchemas().get("alias_array"));
assertEquals(adopterAlias.getTitle(),"AdopterAlias", "Processed Schemas");
assertEquals(adopterAlias.getItems().getAllOf().size(), 2, "Processed schemas items");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
{
"{$request.body#/callback_url}/pets/{$request.path.id}/vaccinations": {
"put": {
"summary": "Vaccination record sent on completion",
"description": "New vaccination record for a pet sent after vaccination order is complete.",
"x-slo": {
"response_time_95th_percentile": 100,
"error_rate": 0.001
},
"x-visibility": {
"extent": "INTERNAL"
},
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "../../../schemas/vaccination_record.json"
},
"examples": {
"vaccination": {
"summary": "Vaccination with ID",
"description": "Vaccination record for pet with vaccination id.",
"value": {
"id": "8ce1edf4-3014-4b5c-b50d-9ed697768ead",
"vaccine_name": "Feline Viral Rhinotracheitis",
"administration_date": "2023-12-20"
}
}
}
}
}
},
"responses": {
"204": {
"description": "Your server implementation should return this HTTP status code if the data was received successfully."
},
"400": {
"description": "Your server should return this HTTP status code if the request is malformed.",
"content": {
"application/json": {
"schema": {
"$ref": "../../../schemas/error.json"
},
"examples": {
"bad_vaccine_name": {
"summary": "Vaccine name is invalid.",
"value": {
"name": "INVALID_REQUEST",
"debug_id": "b1d1f06c7246c",
"message": "Request is not well-formed, syntactically incorrect, or violates schema.",
"details": [
{
"field": "/vaccine_name",
"location": "body",
"value": "#bad-value#",
"issue": "INVALID_PARAMETER_SYNTAX",
"description": "The value of a field does not conform to the expected format."
}
]
}
}
}
}
}
},
"404": {
"description": "Your server should return this HTTP status code if the pet id is not found.",
"content": {
"application/json": {
"schema": {
"$ref": "../../../schemas/error.json"
},
"examples": {
"generic": {
"summary": "Pet 'Not Found' error.",
"value": {
"name": "RESOURCE_NOT_FOUND",
"debug_id": "b1d1f06c7246c",
"message": "The specified resource does not exist."
}
}
}
}
}
},
"500": {
"description": "Your server should return this HTTP status code if there is an internal error processing the request.",
"content": {
"application/json": {
"schema": {
"$ref": "../../../schemas/error.json"
},
"examples": {
"generic": {
"summary": "Generic internal server error.",
"value": {
"name": "INTERNAL_SERVER_ERROR",
"debug_id": "b1d1f06c7246c",
"message": "An internal server error has occurred."
}
}
}
}
}
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"summary": "A correlation id.",
"description": "A correlation-id header with a randomized id value.",
"value": "7758b780aaaca"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"name": "Correlation-Id",
"in": "header",
"description": "Correlation ID for distributed tracing.",
"required": false,
"schema": {
"$ref": "../../../schemas/correlation_id.json"
},
"examples": {
"correlation_id": {
"$ref": "../../../examples/parameter/header/correlation_id.json"
}
},
"x-redacted": true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
{
"title": "Adoption Request",
"description": "A pet adoption request.",
"type": "object",
"required": [
"animal_type",
"pet_id",
"adopter_name",
"adopter_address"
],
"properties": {
"animal_type": {
"$ref": "./animal_type.json"
},
"pet_id": {
"allOf": [
{
"$ref": "correlation_id.json"
},
{
"title": "Pet Id",
"description": "Unique ID of a pet.",
"x-redacted": true,
"readOnly": true
}
]
},
"adopter_name": {
"allOf": [
{
"$ref": "vaccine_name.json"
},
{
"description": "The adopter's name.",
"x-redacted": true
}
]
},
"adopter_alias" : {
"$ref": "./alias_array.json"
},
"adopter_address": {
"allOf": [
{
"$ref": "full_name.json"
},
{
"description": "The adopter's address.",
"x-redacted": true
}
]
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"allOf": [
{
"$ref": "./adoption_request.json"
},
{
"title": "Adoption Request for Bird",
"description": "A bird adoption request.",
"type": "object",
"properties": {
"have_birdcage": {
"description": "Indicates if the adopter has a birdcage.",
"type": "boolean",
"x-redacted": true
}
}
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"allOf": [
{
"$ref": "./adoption_request.json"
},
{
"title": "Adoption Request for Cat",
"description": "A cat adoption request.",
"type": "object",
"properties": {
"have_litter_box": {
"description": "Indicates if the adopter has a litter box.",
"type": "boolean",
"x-redacted": true
},
"have_scratching_post": {
"description": "Indicates if the adopter has a scratching post.",
"type": "boolean",
"x-redacted": true
}
}
}
]
}
Loading

0 comments on commit 18400a0

Please sign in to comment.