AnnotatedOperationMethodTest.java
package io.swagger.v3.jaxrs2.annotations.operations;
import io.swagger.v3.jaxrs2.annotations.AbstractAnnotationTest;
import io.swagger.v3.jaxrs2.resources.GenericResponsesResource;
import io.swagger.v3.jaxrs2.resources.HiddenAnnotatedUserResource;
import io.swagger.v3.jaxrs2.resources.HiddenUserResource;
import io.swagger.v3.jaxrs2.resources.PetResource;
import io.swagger.v3.jaxrs2.resources.PetResourceSlashesinPath;
import io.swagger.v3.jaxrs2.resources.SimpleUserResource;
import io.swagger.v3.jaxrs2.resources.UserResource;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.enums.Explode;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.headers.Header;
import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.ExampleObject;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import org.testng.annotations.Test;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import java.io.IOException;
import static org.testng.Assert.assertEquals;
public class AnnotatedOperationMethodTest extends AbstractAnnotationTest {
@Test
public void testSimpleGetOperation() {
String openApiYAML = readIntoYaml(SimpleGetOperationTest.class);
int start = openApiYAML.indexOf("get:");
int end = openApiYAML.length() - 1;
String expectedYAML = "get:\n" +
" summary: Simple get operation\n" +
" description: Defines a simple get operation with no inputs and a complex\n" +
" operationId: getWithNoParameters\n" +
" responses:\n" +
" \"200\":\n" +
" description: voila!\n" +
" deprecated: true";
String extractedYAML = openApiYAML.substring(start, end);
assertEquals(extractedYAML, expectedYAML);
}
static class SimpleGetOperationTest {
@Operation(
summary = "Simple get operation",
description = "Defines a simple get operation with no inputs and a complex",
operationId = "getWithNoParameters",
deprecated = true,
responses = {
@ApiResponse(
responseCode = "200",
description = "voila!")
}
)
@GET
@Path("/path")
public void simpleGet() {
}
}
@Test
public void testSimpleGetOperationWithoutResponses() {
String openApiYAML = readIntoYaml(SimpleGetWithoutResponses.class);
int start = openApiYAML.indexOf("get:");
int end = openApiYAML.length() - 1;
String expectedYAML = "get:\n" +
" summary: Simple get operation\n" +
" description: Defines a simple get operation with no inputs or responses\n" +
" operationId: getWithNoParametersAndNoResponses\n" +
" responses:\n" +
" default:\n" +
" description: default response\n" +
" content:\n" +
" '*/*': {}\n" +
" deprecated: true";
String extractedYAML = openApiYAML.substring(start, end);
assertEquals(extractedYAML, expectedYAML);
}
static class SimpleGetWithoutResponses {
@Operation(
summary = "Simple get operation",
description = "Defines a simple get operation with no inputs or responses",
operationId = "getWithNoParametersAndNoResponses",
deprecated = true
)
@GET
@Path("/path")
public void simpleGet() {
}
}
@Test
public void testGetOperationWithResponsePayloadAndAlternateCodes() {
String openApiYAML = readIntoYaml(GetOperationWithResponsePayloadAndAlternateCodes.class);
int start = openApiYAML.indexOf("get:");
int end = openApiYAML.indexOf("components:");
String extractedYAML = openApiYAML.substring(start, end);
String expectedYAML = "get:\n" +
" summary: Simple get operation\n" +
" description: Defines a simple get operation with no inputs and a complex\n" +
" operationId: getWithPayloadResponse\n" +
" responses:\n" +
" \"200\":\n" +
" description: voila!\n" +
" content:\n" +
" application/json:\n" +
" schema:\n" +
" $ref: \"#/components/schemas/SampleResponseSchema\"\n" +
" default:\n" +
" description: boo\n" +
" content:\n" +
" '*/*':\n" +
" schema:\n" +
" $ref: \"#/components/schemas/GenericError\"\n" +
" examples:\n" +
" boo:\n" +
" summary: example of boo\n" +
" description: boo\n" +
" value: example\n" +
" externalValue: example of external value\n" +
" deprecated: true\n";
assertEquals(extractedYAML, expectedYAML);
}
static class GetOperationWithResponsePayloadAndAlternateCodes {
@Operation(
summary = "Simple get operation",
description = "Defines a simple get operation with no inputs and a complex",
operationId = "getWithPayloadResponse",
deprecated = true,
responses = {
@ApiResponse(
responseCode = "200",
description = "voila!",
content = @Content(
mediaType = "application/json",
schema = @Schema(implementation = SampleResponseSchema.class)
)
),
@ApiResponse(
description = "boo",
content = @Content(
mediaType = "*/*",
schema = @Schema(implementation = GenericError.class),
examples = {
@ExampleObject(name = "boo", value = "example",
summary = "example of boo", externalValue = "example of external value")
}
)
)
}
)
@Path("/path")
@GET
public void simpleGet() {
}
}
static class SampleResponseSchema {
@Schema(description = "the user id")
public String id;
}
static class SampleHeaderSchema {
public String id;
}
static class GenericError {
public int code;
public String message;
}
@Test(description = "reads an operation with response examples defined")
public void testOperationWithResponseExamples() {
String openApiYAML = readIntoYaml(GetOperationWithResponseExamples.class);
int start = openApiYAML.indexOf("get:");
int end = openApiYAML.indexOf("components:");
String extractedYAML = openApiYAML.substring(start, end);
String expectedYAML = "get:\n" +
" summary: Simple get operation\n" +
" description: Defines a simple get operation with no inputs and a complex output\n" +
" operationId: getWithPayloadResponse\n" +
" responses:\n" +
" \"200\":\n" +
" description: voila!\n" +
" content:\n" +
" application/json:\n" +
" schema:\n" +
" $ref: \"#/components/schemas/SampleResponseSchema\"\n" +
" examples:\n" +
" basic:\n" +
" summary: shows a basic example\n" +
" description: basic\n" +
" value: \"{id: 19877734}\"\n" +
" deprecated: true\n";
assertEquals(extractedYAML, expectedYAML);
}
@Test(description = "reads an operation with response examples defined")
public void testOperationWithParameterExample() {
String openApiYAML = readIntoYaml(GetOperationWithParameterExample.class);
int start = openApiYAML.indexOf("get:");
int end = openApiYAML.indexOf("components:");
String extractedYAML = openApiYAML.substring(start, end);
String expectedYAML = "get:\n" +
" summary: Simple get operation\n" +
" description: Defines a simple get operation with a parameter example\n" +
" operationId: getWithPayloadResponse\n" +
" parameters:\n" +
" - in: query\n" +
" schema:\n" +
" type: string\n" +
" example:\n" +
" id: 19877734\n" +
" responses:\n" +
" \"200\":\n" +
" description: voila!\n" +
" content:\n" +
" application/json:\n" +
" schema:\n" +
" $ref: \"#/components/schemas/SampleResponseSchema\"\n" +
" examples:\n" +
" basic:\n" +
" summary: shows a basic example\n" +
" description: basic\n" +
" value: \"{id: 19877734}\"\n" +
" deprecated: true\n";
assertEquals(extractedYAML, expectedYAML);
}
static class GetOperationWithResponseExamples {
@Operation(
summary = "Simple get operation",
description = "Defines a simple get operation with no inputs and a complex output",
operationId = "getWithPayloadResponse",
deprecated = true,
responses = {
@ApiResponse(
responseCode = "200",
description = "voila!",
content = @Content(
mediaType = "application/json",
schema = @Schema(implementation = SampleResponseSchema.class),
examples = {
@ExampleObject(
name = "basic",
summary = "shows a basic example",
value = "{id: 19877734}")
}
)
)
}
)
@GET
@Path("/path")
public void simpleGet() {
}
}
static class GetOperationWithParameterExample {
@Operation(
summary = "Simple get operation",
description = "Defines a simple get operation with a parameter example",
operationId = "getWithPayloadResponse",
deprecated = true,
responses = {
@ApiResponse(
responseCode = "200",
description = "voila!",
content = @Content(
mediaType = "application/json",
schema = @Schema(implementation = SampleResponseSchema.class),
examples = {
@ExampleObject(
name = "basic",
summary = "shows a basic example",
value = "{id: 19877734}")
}
)
)
}
)
@GET
@Path("/path")
public void simpleGet(@Parameter(in = ParameterIn.QUERY, example = "{\"id\": 19877734}") String exParam) {
}
}
static class GetOperationWithResponseSingleHeader {
@Operation(
summary = "Simple get operation",
description = "Defines a simple get operation with no inputs and a complex output",
operationId = "getWithPayloadResponse",
deprecated = true,
responses = {
@ApiResponse(
responseCode = "200",
description = "voila!",
headers = {@Header(
name = "Rate-Limit-Limit",
description = "The number of allowed requests in the current period",
schema = @Schema(type = "integer"))})
})
@GET
@Path("/path")
public void simpleGet() {
}
}
@Test
public void testOperationWithResponseSingleHeader() {
String openApiYAML = readIntoYaml(GetOperationWithResponseSingleHeader.class);
int start = openApiYAML.indexOf("get:");
String extractedYAML = openApiYAML.substring(start);
String expectedYAML = "get:\n" +
" summary: Simple get operation\n" +
" description: Defines a simple get operation with no inputs and a complex output\n" +
" operationId: getWithPayloadResponse\n" +
" responses:\n" +
" \"200\":\n" +
" description: voila!\n" +
" headers:\n" +
" Rate-Limit-Limit:\n" +
" description: The number of allowed requests in the current period\n" +
" style: simple\n" +
" schema:\n" +
" type: integer\n" +
" deprecated: true\n";
assertEquals(expectedYAML, extractedYAML);
}
static class GetOperationWithResponseMultipleHeaders {
@Operation(
summary = "Simple get operation",
description = "Defines a simple get operation with no inputs and a complex output",
operationId = "getWithPayloadResponse",
deprecated = true,
responses = {
@ApiResponse(
responseCode = "200",
description = "voila!",
headers = {@Header(
explode = Explode.TRUE,
name = "Rate-Limit-Limit",
description = "The number of allowed requests in the current period",
schema = @Schema(type = "integer")),
@Header(
name = "X-Rate-Limit-Desc",
description = "The description of rate limit",
schema = @Schema(type = "string"))})
})
@GET
@Path("/path")
public void simpleGet() {
}
}
@Test
public void testOperationWithResponseArraySchema() {
String openApiYAML = readIntoYaml(GetOperationResponseHeaderWithArraySchema.class);
int start = openApiYAML.indexOf("get:");
String extractedYAML = openApiYAML.substring(start);
String expectedYAML = "get:\n" +
" summary: Simple get operation\n" +
" description: Defines a simple get operation with no inputs and a complex output\n" +
" operationId: getWithPayloadResponse\n" +
" responses:\n" +
" \"200\":\n" +
" description: voila!\n" +
" headers:\n" +
" Rate-Limit-Limit:\n" +
" description: The number of allowed requests in the current period\n" +
" style: simple\n" +
" schema:\n" +
" maxItems: 10\n" +
" minItems: 1\n" +
" type: array\n" +
" items:\n" +
" type: integer\n" +
" deprecated: true\n";
assertEquals(expectedYAML, extractedYAML);
}
static class GetOperationResponseHeaderWithArraySchema {
@Operation(
summary = "Simple get operation",
description = "Defines a simple get operation with no inputs and a complex output",
operationId = "getWithPayloadResponse",
deprecated = true,
responses = {
@ApiResponse(
responseCode = "200",
description = "voila!",
headers = {@Header(
name = "Rate-Limit-Limit",
description = "The number of allowed requests in the current period",
array = @ArraySchema(maxItems = 10, minItems = 1,schema = @Schema(type = "integer")))})})
@GET
@Path("/path")
public void simpleGet() {
}
}
static class GetOperationResponseWithoutHiddenHeader {
@Operation(
summary = "Simple get operation",
description = "Defines a simple get operation with no inputs and a complex output",
operationId = "getWithPayloadResponse",
deprecated = true,
responses = {
@ApiResponse(
responseCode = "200",
description = "voila!",
headers = {@Header(
hidden = true,
name = "Rate-Limit-Limit",
description = "The number of allowed requests in the current period",
schema = @Schema(type = "integer")),
@Header(
name = "X-Rate-Limit-Desc",
description = "The description of rate limit",
schema = @Schema(type = "string"))})
})
@GET
@Path("/path")
public void simpleGet() {
}
}
static class GetOperationWithResponseMultipleHeadersAndExamples {
@Operation(
summary = "Simple get operation",
description = "Defines a simple get operation with no inputs and a complex output",
operationId = "getWithPayloadResponse",
deprecated = true,
responses = {
@ApiResponse(
responseCode = "200",
description = "voila!",
headers = {@Header(
examples = {
@ExampleObject(
name = "ex 1",
description = "example description",
value = "example value"
),
@ExampleObject(
name = "ex 2",
description = "example description 2",
value = "example value 2"
)
},
name = "Rate-Limit-Limit",
description = "The number of allowed requests in the current period",
schema = @Schema(type = "object")),
@Header(
name = "X-Rate-Limit-Desc",
description = "The description of rate limit",
array = @ArraySchema(schema = @Schema()),
example = "example1")})
})
@GET
@Path("/path")
public void simpleGet() {
}
}
static class GetOperationResponseWithHeaderExplodeAttribute {
@Operation(
summary = "Simple get operation",
description = "Defines a simple get operation with no inputs and a complex output",
operationId = "getWithPayloadResponse",
deprecated = true,
responses = {
@ApiResponse(
responseCode = "200",
description = "voila!",
headers = {@Header(
name = "Rate-Limit-Limit",
description = "The number of allowed requests in the current period",
explode = Explode.TRUE,
schema = @Schema(type = "object")),
@Header(
name = "X-Rate-Limit-Desc",
description = "The description of rate limit",
explode = Explode.FALSE,
schema = @Schema(type = "array"))})
})
@GET
@Path("/path")
public void simpleGet() {
}
}
@Test
public void testOperationWithResponseMultipleHeaders() {
String openApiYAML = readIntoYaml(GetOperationWithResponseMultipleHeaders.class);
int start = openApiYAML.indexOf("get:");
String extractedYAML = openApiYAML.substring(start);
String expectedYAML = "get:\n" +
" summary: Simple get operation\n" +
" description: Defines a simple get operation with no inputs and a complex output\n" +
" operationId: getWithPayloadResponse\n" +
" responses:\n" +
" \"200\":\n" +
" description: voila!\n" +
" headers:\n" +
" X-Rate-Limit-Desc:\n" +
" description: The description of rate limit\n" +
" style: simple\n" +
" schema:\n" +
" type: string\n" +
" Rate-Limit-Limit:\n" +
" description: The number of allowed requests in the current period\n" +
" style: simple\n" +
" schema:\n" +
" type: integer\n" +
" deprecated: true\n";
assertEquals(expectedYAML, extractedYAML);
}
static class GetOperationWithResponseMultipleHeadersWithImplementationSchema {
@Operation(
summary = "Simple get operation",
description = "Defines a simple get operation with no inputs and a complex output",
operationId = "getWithPayloadResponse",
deprecated = true,
responses = {
@ApiResponse(
responseCode = "200",
description = "voila!",
headers = {@Header(
explode = Explode.TRUE,
name = "Rate-Limit-Limit",
description = "The number of allowed requests in the current period",
array = @ArraySchema(maxItems = 10, minItems = 1,schema = @Schema(implementation = SampleHeaderSchema.class))),
@Header(
explode = Explode.TRUE,
name = "X-Rate-Limit-Desc",
description = "The description of rate limit",
schema = @Schema(implementation = SampleHeaderSchema.class))})})
@GET
@Path("/path")
public void simpleGet() {
}
}
@Test
public void testOperationWithResponseMultipleHeadersImplementationSchema() {
String openApiYAML = readIntoYaml(GetOperationWithResponseMultipleHeadersWithImplementationSchema.class);
int start = openApiYAML.indexOf("get:");
String extractedYAML = openApiYAML.substring(start);
String expectedYAML = "get:\n" +
" summary: Simple get operation\n" +
" description: Defines a simple get operation with no inputs and a complex output\n" +
" operationId: getWithPayloadResponse\n" +
" responses:\n" +
" \"200\":\n" +
" description: voila!\n" +
" headers:\n" +
" X-Rate-Limit-Desc:\n" +
" description: The description of rate limit\n" +
" style: simple\n" +
" explode: true\n" +
" schema:\n" +
" $ref: \"#/components/schemas/SampleHeaderSchema\"\n" +
" Rate-Limit-Limit:\n" +
" description: The number of allowed requests in the current period\n" +
" style: simple\n" +
" explode: true\n" +
" schema:\n" +
" maxItems: 10\n" +
" minItems: 1\n" +
" type: array\n" +
" items:\n" +
" $ref: \"#/components/schemas/SampleHeaderSchema\"\n" +
" deprecated: true\n" +
"components:\n" +
" schemas:\n" +
" SampleHeaderSchema:\n" +
" type: object\n" +
" properties:\n" +
" id:\n" +
" type: string\n";
assertEquals(expectedYAML, extractedYAML);
}
@Test
public void testOperationWithResponseMultipleHeadersAndExplodeAttribute() {
String openApiYAML = readIntoYaml(GetOperationResponseWithHeaderExplodeAttribute.class);
int start = openApiYAML.indexOf("get:");
String extractedYAML = openApiYAML.substring(start);
String expectedYAML = "get:\n" +
" summary: Simple get operation\n" +
" description: Defines a simple get operation with no inputs and a complex output\n" +
" operationId: getWithPayloadResponse\n" +
" responses:\n" +
" \"200\":\n" +
" description: voila!\n" +
" headers:\n" +
" X-Rate-Limit-Desc:\n" +
" description: The description of rate limit\n" +
" style: simple\n" +
" explode: false\n" +
" schema:\n" +
" type: array\n" +
" Rate-Limit-Limit:\n" +
" description: The number of allowed requests in the current period\n" +
" style: simple\n" +
" explode: true\n" +
" schema:\n" +
" type: object\n" +
" deprecated: true\n";
assertEquals(expectedYAML, extractedYAML);
}
@Test
public void testOperationResponseWithoutHiddenHeader() {
String openApiYAML = readIntoYaml(GetOperationResponseWithoutHiddenHeader.class);
int start = openApiYAML.indexOf("get:");
String extractedYAML = openApiYAML.substring(start);
String expectedYAML = "get:\n" +
" summary: Simple get operation\n" +
" description: Defines a simple get operation with no inputs and a complex output\n" +
" operationId: getWithPayloadResponse\n" +
" responses:\n" +
" \"200\":\n" +
" description: voila!\n" +
" headers:\n" +
" X-Rate-Limit-Desc:\n" +
" description: The description of rate limit\n" +
" style: simple\n" +
" schema:\n" +
" type: string\n" +
" deprecated: true\n";
assertEquals(expectedYAML, extractedYAML);
}
@Test
public void testOperationWithResponseMultipleHeadersAndExamples() {
String openApiYAML = readIntoYaml(GetOperationWithResponseMultipleHeadersAndExamples.class);
int start = openApiYAML.indexOf("get:");
String extractedYAML = openApiYAML.substring(start);
String expectedYAML = "get:\n" +
" summary: Simple get operation\n" +
" description: Defines a simple get operation with no inputs and a complex output\n" +
" operationId: getWithPayloadResponse\n" +
" responses:\n" +
" \"200\":\n" +
" description: voila!\n" +
" headers:\n" +
" X-Rate-Limit-Desc:\n" +
" description: The description of rate limit\n" +
" style: simple\n" +
" example: example1\n" +
" Rate-Limit-Limit:\n" +
" description: The number of allowed requests in the current period\n" +
" style: simple\n" +
" schema:\n" +
" type: object\n" +
" examples:\n" +
" ex 1:\n" +
" description: example description\n" +
" value: example value\n" +
" ex 2:\n" +
" description: example description 2\n" +
" value: example value 2\n" +
" deprecated: true\n";
assertEquals(expectedYAML, extractedYAML);
}
@Test(description = "reads the pet resource from sample")
public void testCompletePetResource() throws IOException {
String expectedYAML = "openapi: 3.0.1\n" +
"paths:\n" +
" /pet/findByTags:\n" +
" get:\n" +
" summary: Finds Pets by tags\n" +
" description: Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.\n" +
" operationId: findPetsByTags\n" +
" parameters:\n" +
" - name: tags\n" +
" in: query\n" +
" description: Tags to filter by\n" +
" required: true\n" +
" schema:\n" +
" type: string\n" +
" responses:\n" +
" default:\n" +
" description: Pets matching criteria\n" +
" content:\n" +
" application/json:\n" +
" schema:\n" +
" $ref: \"#/components/schemas/Pet\"\n" +
" \"400\":\n" +
" description: Invalid tag value\n" +
" deprecated: true\n" +
" /pet/findByCategory/{category}:\n" +
" get:\n" +
" summary: Finds Pets by category\n" +
" operationId: findPetsByCategory\n" +
" parameters:\n" +
" - name: category\n" +
" in: path\n" +
" description: Category value that need to be considered for filter\n" +
" required: true\n" +
" style: matrix\n" +
" schema:\n" +
" $ref: \"#/components/schemas/Category\"\n" +
" - name: skip\n" +
" in: query\n" +
" schema:\n" +
" type: integer\n" +
" format: int32\n" +
" - name: limit\n" +
" in: query\n" +
" schema:\n" +
" type: integer\n" +
" format: int32\n" +
" responses:\n" +
" default:\n" +
" content:\n" +
" application/json:\n" +
" schema:\n" +
" $ref: \"#/components/schemas/Pet\"\n" +
" \"400\":\n" +
" description: Invalid category value\n" +
" /pet/{petId}:\n" +
" get:\n" +
" summary: Find pet by ID\n" +
" description: Returns a pet when 0 < ID <= 10. ID > 10 or nonintegers will simulate API error conditions\n" +
" operationId: getPetById\n" +
" parameters:\n" +
" - name: petId\n" +
" in: path\n" +
" description: ID of pet that needs to be fetched\n" +
" required: true\n" +
" schema:\n" +
" type: integer\n" +
" format: int64\n" +
" responses:\n" +
" default:\n" +
" description: The pet\n" +
" content:\n" +
" application/json:\n" +
" schema:\n" +
" $ref: \"#/components/schemas/Pet\"\n" +
" application/xml:\n" +
" schema:\n" +
" $ref: \"#/components/schemas/Pet\"\n" +
" \"400\":\n" +
" description: Invalid ID supplied\n" +
" \"404\":\n" +
" description: Pet not found\n" +
" /pet/bodynoannotation:\n" +
" post:\n" +
" summary: Add a new pet to the store no annotation\n" +
" operationId: addPetNoAnnotation\n" +
" requestBody:\n" +
" content:\n" +
" application/json:\n" +
" schema:\n" +
" $ref: \"#/components/schemas/Pet\"\n" +
" application/xml:\n" +
" schema:\n" +
" $ref: \"#/components/schemas/Pet\"\n" +
" responses:\n" +
" \"405\":\n" +
" description: Invalid input\n" +
" /pet/bodyid:\n" +
" post:\n" +
" summary: Add a new pet to the store passing an integer with generic parameter annotation\n" +
" operationId: addPetByInteger\n" +
" requestBody:\n" +
" description: Pet object that needs to be added to the store\n" +
" content:\n" +
" application/json:\n" +
" schema:\n" +
" type: integer\n" +
" format: int32\n" +
" application/xml:\n" +
" schema:\n" +
" type: integer\n" +
" format: int32\n" +
" required: true\n" +
" responses:\n" +
" \"405\":\n" +
" description: Invalid input\n" +
" /pet/bodyidnoannotation:\n" +
" post:\n" +
" summary: Add a new pet to the store passing an integer without parameter annotation\n" +
" operationId: addPetByIntegerNoAnnotation\n" +
" requestBody:\n" +
" content:\n" +
" application/json:\n" +
" schema:\n" +
" type: integer\n" +
" format: int32\n" +
" application/xml:\n" +
" schema:\n" +
" type: integer\n" +
" format: int32\n" +
" responses:\n" +
" \"405\":\n" +
" description: Invalid input\n" +
" /pet:\n" +
" put:\n" +
" summary: Update an existing pet\n" +
" operationId: updatePet\n" +
" requestBody:\n" +
" description: Pet object that needs to be added to the store\n" +
" content:\n" +
" application/json:\n" +
" schema:\n" +
" $ref: \"#/components/schemas/Pet\"\n" +
" required: true\n" +
" responses:\n" +
" \"400\":\n" +
" description: Invalid ID supplied\n" +
" \"404\":\n" +
" description: Pet not found\n" +
" \"405\":\n" +
" description: Validation exception\n" +
" post:\n" +
" summary: Add a new pet to the store\n" +
" operationId: addPet\n" +
" requestBody:\n" +
" description: Pet object that needs to be added to the store\n" +
" content:\n" +
" application/json:\n" +
" schema:\n" +
" $ref: \"#/components/schemas/Pet\"\n" +
" application/xml:\n" +
" schema:\n" +
" $ref: \"#/components/schemas/Pet\"\n" +
" required: true\n" +
" responses:\n" +
" \"405\":\n" +
" description: Invalid input\n" +
" /pet/findByStatus:\n" +
" get:\n" +
" summary: Finds Pets by status\n" +
" description: Multiple status values can be provided with comma separated strings\n" +
" operationId: findPetsByStatus\n" +
" parameters:\n" +
" - name: status\n" +
" in: query\n" +
" description: Status values that need to be considered for filter\n" +
" required: true\n" +
" schema:\n" +
" type: string\n" +
" - name: skip\n" +
" in: query\n" +
" schema:\n" +
" type: integer\n" +
" format: int32\n" +
" - name: limit\n" +
" in: query\n" +
" schema:\n" +
" type: integer\n" +
" format: int32\n" +
" responses:\n" +
" default:\n" +
" content:\n" +
" application/json:\n" +
" schema:\n" +
" $ref: \"#/components/schemas/Pet\"\n" +
" \"400\":\n" +
" description: Invalid status value\n" +
"components:\n" +
" schemas:\n" +
" Category:\n" +
" type: object\n" +
" properties:\n" +
" id:\n" +
" type: integer\n" +
" format: int64\n" +
" name:\n" +
" type: string\n" +
" xml:\n" +
" name: Category\n" +
" Tag:\n" +
" type: object\n" +
" properties:\n" +
" id:\n" +
" type: integer\n" +
" format: int64\n" +
" name:\n" +
" type: string\n" +
" xml:\n" +
" name: Tag\n" +
" Pet:\n" +
" type: object\n" +
" properties:\n" +
" id:\n" +
" type: integer\n" +
" format: int64\n" +
" category:\n" +
" $ref: \"#/components/schemas/Category\"\n" +
" name:\n" +
" type: string\n" +
" photoUrls:\n" +
" type: array\n" +
" xml:\n" +
" wrapped: true\n" +
" items:\n" +
" type: string\n" +
" xml:\n" +
" name: photoUrl\n" +
" tags:\n" +
" type: array\n" +
" xml:\n" +
" wrapped: true\n" +
" items:\n" +
" $ref: \"#/components/schemas/Tag\"\n" +
" status:\n" +
" type: string\n" +
" description: pet status in the store\n" +
" enum:\n" +
" - available,pending,sold\n" +
" xml:\n" +
" name: Pet";
compareAsYaml(PetResource.class, expectedYAML);
compareAsYaml(PetResourceSlashesinPath.class, expectedYAML);
}
@Test(description = "reads the resource with generic response from sample")
public void testGenericResponseResource() throws IOException {
String yaml = "openapi: 3.0.1\n" +
"paths:\n" +
" /:\n" +
" get:\n" +
" summary: Returns a list of somethings\n" +
" operationId: getSomethings\n" +
" responses:\n" +
" default:\n" +
" content:\n" +
" '*/*':\n" +
" schema:\n" +
" $ref: \"#/components/schemas/SomethingResponse\"\n" +
" /overridden:\n" +
" get:\n" +
" summary: Returns a list of somethings\n" +
" operationId: getSomethingsOverridden\n" +
" responses:\n" +
" default:\n" +
" content:\n" +
" '*/*':\n" +
" schema:\n" +
" $ref: \"#/components/schemas/Something\"\n" +
"components:\n" +
" schemas:\n" +
" SomethingResponse:\n" +
" type: object\n" +
" properties:\n" +
" data:\n" +
" $ref: \"#/components/schemas/DataSomething\"\n" +
" DataSomething:\n" +
" type: object\n" +
" properties:\n" +
" items:\n" +
" type: array\n" +
" items:\n" +
" $ref: \"#/components/schemas/Something\"\n" +
" Something:\n" +
" type: object\n" +
" properties:\n" +
" id:\n" +
" type: string\n";
compareAsYaml(GenericResponsesResource.class, yaml);
}
@Test(description = "reads the user resource from sample")
public void testCompleteUserResource() throws IOException {
String expectedYAML = "openapi: 3.0.1\n" +
"paths:\n" +
" /user:\n" +
" post:\n" +
" summary: Create user\n" +
" description: This can only be done by the logged in user.\n" +
" operationId: createUser\n" +
" requestBody:\n" +
" description: Created user object\n" +
" content:\n" +
" '*/*':\n" +
" schema:\n" +
" $ref: \"#/components/schemas/User\"\n" +
" required: true\n" +
" responses:\n" +
" default:\n" +
" description: default response\n" +
" content:\n" +
" 'application/json': {}\n" +
" 'application/xml': {}\n" +
" /user/createWithArray:\n" +
" post:\n" +
" summary: Creates list of users with given input array\n" +
" operationId: createUsersWithArrayInput\n" +
" requestBody:\n" +
" description: List of user object\n" +
" content:\n" +
" '*/*':\n" +
" schema:\n" +
" type: array\n" +
" items:\n" +
" $ref: \"#/components/schemas/User\"\n" +
" required: true\n" +
" responses:\n" +
" default:\n" +
" description: default response\n" +
" content:\n" +
" 'application/json': {}\n" +
" 'application/xml': {}\n" +
" /user/createWithList:\n" +
" post:\n" +
" summary: Creates list of users with given input array\n" +
" operationId: createUsersWithListInput\n" +
" requestBody:\n" +
" description: List of user object\n" +
" content:\n" +
" '*/*':\n" +
" schema:\n" +
" type: array\n" +
" items:\n" +
" $ref: \"#/components/schemas/User\"\n" +
" required: true\n" +
" responses:\n" +
" default:\n" +
" description: default response\n" +
" content:\n" +
" 'application/json': {}\n" +
" 'application/xml': {}\n" +
" /user/{username}:\n" +
" get:\n" +
" summary: Get user by user name\n" +
" operationId: getUserByName\n" +
" parameters:\n" +
" - name: username\n" +
" in: path\n" +
" description: 'The name that needs to be fetched. Use user1 for testing. '\n" +
" required: true\n" +
" schema:\n" +
" type: string\n" +
" responses:\n" +
" default:\n" +
" description: The user\n" +
" content:\n" +
" application/json:\n" +
" schema:\n" +
" $ref: \"#/components/schemas/User\"\n" +
" \"400\":\n" +
" description: User not found\n" +
" put:\n" +
" summary: Updated user\n" +
" description: This can only be done by the logged in user.\n" +
" operationId: updateUser\n" +
" parameters:\n" +
" - name: username\n" +
" in: path\n" +
" description: name that need to be deleted\n" +
" required: true\n" +
" schema:\n" +
" type: string\n" +
" examples:\n" +
" example2:\n" +
" summary: Summary example 2\n" +
" description: example2\n" +
" value: example2\n" +
" externalValue: external value 2\n" +
" example1:\n" +
" summary: Summary example 1\n" +
" description: example1\n" +
" value: example1\n" +
" externalValue: external value 1\n" +
" requestBody:\n" +
" description: Updated user object\n" +
" content:\n" +
" '*/*':\n" +
" schema:\n" +
" $ref: \"#/components/schemas/User\"\n" +
" required: true\n" +
" responses:\n" +
" \"200\":\n" +
" description: user updated\n" +
" \"400\":\n" +
" description: Invalid user supplied\n" +
" \"404\":\n" +
" description: User not found\n" +
" delete:\n" +
" summary: Delete user\n" +
" description: This can only be done by the logged in user.\n" +
" operationId: deleteUser\n" +
" parameters:\n" +
" - name: username\n" +
" in: path\n" +
" description: The name that needs to be deleted\n" +
" required: true\n" +
" schema:\n" +
" type: string\n" +
" responses:\n" +
" \"200\":\n" +
" description: user deteled\n" +
" \"400\":\n" +
" description: Invalid username supplied\n" +
" \"404\":\n" +
" description: User not found\n" +
" /user/login:\n" +
" get:\n" +
" summary: Logs user into the system\n" +
" operationId: loginUser\n" +
" parameters:\n" +
" - name: username\n" +
" in: query\n" +
" description: The user name for login\n" +
" required: true\n" +
" schema:\n" +
" type: string\n" +
" - name: password\n" +
" in: query\n" +
" description: The password for login in clear text\n" +
" required: true\n" +
" schema:\n" +
" type: string\n" +
" responses:\n" +
" default:\n" +
" description: Successfully logged in\n" +
" content:\n" +
" application/json:\n" +
" schema:\n" +
" type: string\n" +
" application/xml:\n" +
" schema:\n" +
" type: string\n" +
" \"400\":\n" +
" description: Invalid username/password supplied\n" +
" /user/logout:\n" +
" get:\n" +
" summary: Logs out current logged in user session\n" +
" operationId: logoutUser\n" +
" responses:\n" +
" default:\n" +
" description: default response\n" +
" content:\n" +
" 'application/json': {}\n" +
" 'application/xml': {}\n" +
"components:\n" +
" schemas:\n" +
" User:\n" +
" type: object\n" +
" properties:\n" +
" id:\n" +
" type: integer\n" +
" format: int64\n" +
" username:\n" +
" type: string\n" +
" firstName:\n" +
" type: string\n" +
" lastName:\n" +
" type: string\n" +
" email:\n" +
" type: string\n" +
" password:\n" +
" type: string\n" +
" phone:\n" +
" type: string\n" +
" userStatus:\n" +
" type: integer\n" +
" description: User Status\n" +
" format: int32\n" +
" xml:\n" +
" name: User";
compareAsYaml(UserResource.class, expectedYAML);
}
@Test(description = "reads the simple user resource from sample")
public void testSimpleUserResource() throws IOException {
String expectedYAML = "openapi: 3.0.1\n" +
"paths:\n" +
" /user:\n" +
" post:\n" +
" summary: Create user\n" +
" description: This can only be done by the logged in user.\n" +
" operationId: createUser\n" +
" requestBody:\n" +
" description: Created user object\n" +
" content:\n" +
" application/json:\n" +
" schema:\n" +
" $ref: \"#/components/schemas/User\"\n" +
" application/xml:\n" +
" schema:\n" +
" $ref: \"#/components/schemas/User\"\n" +
" required: true\n" +
" responses:\n" +
" default:\n" +
" description: default response\n" +
" content:\n" +
" 'application/json': {}\n" +
" 'application/xml': {}\n" +
" /user/createUserWithReturnType:\n" +
" post:\n" +
" summary: Create user with return type\n" +
" description: This can only be done by the logged in user.\n" +
" operationId: createUserWithReturnType\n" +
" requestBody:\n" +
" description: Created user object\n" +
" content:\n" +
" application/json:\n" +
" schema:\n" +
" $ref: \"#/components/schemas/User\"\n" +
" application/xml:\n" +
" schema:\n" +
" $ref: \"#/components/schemas/User\"\n" +
" required: true\n" +
" responses:\n" +
" default:\n" +
" description: default response\n" +
" content:\n" +
" application/json:\n" +
" schema:\n" +
" $ref: \"#/components/schemas/User\"\n" +
" application/xml:\n" +
" schema:\n" +
" $ref: \"#/components/schemas/User\"\n" +
" /user/createUserWithResponseAnnotation:\n" +
" post:\n" +
" summary: Create user with response annotation\n" +
" description: This can only be done by the logged in user.\n" +
" operationId: createUserWithResponseAnnotation\n" +
" requestBody:\n" +
" description: Created user object\n" +
" content:\n" +
" application/json:\n" +
" schema:\n" +
" $ref: \"#/components/schemas/User\"\n" +
" application/xml:\n" +
" schema:\n" +
" $ref: \"#/components/schemas/User\"\n" +
" required: true\n" +
" responses:\n" +
" \"200\":\n" +
" description: aaa\n" +
" content:\n" +
" application/json:\n" +
" schema:\n" +
" $ref: \"#/components/schemas/User\"\n" +
" application/xml:\n" +
" schema:\n" +
" $ref: \"#/components/schemas/User\"\n" +
" /user/createUserWithReturnTypeAndResponseAnnotation:\n" +
" post:\n" +
" summary: Create user with return type and response annotation\n" +
" description: This can only be done by the logged in user.\n" +
" operationId: createUserWithReturnTypeAndResponseAnnotation\n" +
" requestBody:\n" +
" description: Created user object\n" +
" content:\n" +
" application/json:\n" +
" schema:\n" +
" $ref: \"#/components/schemas/User\"\n" +
" application/xml:\n" +
" schema:\n" +
" $ref: \"#/components/schemas/User\"\n" +
" required: true\n" +
" responses:\n" +
" \"200\":\n" +
" description: aaa\n" +
"components:\n" +
" schemas:\n" +
" User:\n" +
" type: object\n" +
" properties:\n" +
" id:\n" +
" type: integer\n" +
" format: int64\n" +
" username:\n" +
" type: string\n" +
" firstName:\n" +
" type: string\n" +
" lastName:\n" +
" type: string\n" +
" email:\n" +
" type: string\n" +
" password:\n" +
" type: string\n" +
" phone:\n" +
" type: string\n" +
" userStatus:\n" +
" type: integer\n" +
" description: User Status\n" +
" format: int32\n" +
" xml:\n" +
" name: User";
compareAsYaml(SimpleUserResource.class, expectedYAML);
}
@Test(description = "reads and skips the hidden user resource")
public void testHiddenUserResource() {
String openApiYAML = readIntoYaml(HiddenUserResource.class);
assertEquals(openApiYAML, "openapi: 3.0.1\n");
}
@Test(description = "reads and skips the hidden user resource")
public void testHiddenAnnotatedUserResource() throws IOException {
String openApiYAML = readIntoYaml(HiddenAnnotatedUserResource.class);
assertEquals(openApiYAML, "openapi: 3.0.1\n");
compareAsYaml(HiddenAnnotatedUserResource.HiddenAnnotatedUserResourceMethodAndData.class, "openapi: 3.0.1\n" +
"paths:\n" +
" /user/2:\n" +
" post:\n" +
" summary: Create user\n" +
" description: This can only be done by the logged in user.\n" +
" operationId: createUserWithHiddenBeanProperty\n" +
" requestBody:\n" +
" description: Created user object\n" +
" content:\n" +
" '*/*':\n" +
" schema:\n" +
" $ref: \"#/components/schemas/UserResourceBean\"\n" +
" required: true\n" +
" responses:\n" +
" default:\n" +
" description: default response\n" +
" content:\n" +
" 'application/json': {}\n" +
" 'application/xml': {}\n" +
"components:\n" +
" schemas:\n" +
" UserResourceBean:\n" +
" type: object\n" +
" properties:\n" +
" foo:\n" +
" type: string");
}
@Test
public void testSimpleGetOperationWithSecurity() {
String openApiYAML = readIntoYaml(SimpleGetOperationWithSecurity.class);
int start = openApiYAML.indexOf("get:");
int end = openApiYAML.length() - 1;
String expectedYAML = "get:\n" +
" summary: Simple get operation\n" +
" description: Defines a simple get operation with no inputs and a complex\n" +
" operationId: getWithNoParameters\n" +
" responses:\n" +
" \"200\":\n" +
" description: voila!\n" +
" security:\n" +
" - petstore-auth:\n" +
" - write:pets";
String extractedYAML = openApiYAML.substring(start, end);
assertEquals(expectedYAML, extractedYAML);
}
static class SimpleGetOperationWithSecurity {
@Operation(
summary = "Simple get operation",
description = "Defines a simple get operation with no inputs and a complex",
operationId = "getWithNoParameters",
responses = {
@ApiResponse(
responseCode = "200",
description = "voila!")
},
security = @SecurityRequirement(
name = "petstore-auth",
scopes = "write:pets"))
@GET
@Path("/path")
public void simpleGet() {
}
}
@Test
public void testSimpleGetOperationWithMultipleSecurity() {
String openApiYAML = readIntoYaml(SimpleGetOperationWithMultipleSecurityScopes.class);
int start = openApiYAML.indexOf("get:");
int end = openApiYAML.length() - 1;
String expectedYAML = "get:\n" +
" summary: Simple get operation\n" +
" description: Defines a simple get operation with no inputs and a complex\n" +
" operationId: getWithNoParameters\n" +
" responses:\n" +
" \"200\":\n" +
" description: voila!\n" +
" security:\n" +
" - petstore-auth:\n" +
" - write:pets\n" +
" - read:pets";
String extractedYAML = openApiYAML.substring(start, end);
assertEquals(extractedYAML, expectedYAML);
}
static class SimpleGetOperationWithMultipleSecurityScopes {
@Operation(
summary = "Simple get operation",
description = "Defines a simple get operation with no inputs and a complex",
operationId = "getWithNoParameters",
responses = {
@ApiResponse(
responseCode = "200",
description = "voila!")
},
security = @SecurityRequirement(
name = "petstore-auth",
scopes = {"write:pets", "read:pets"}))
@GET
@Path("/path")
public void simpleGet() {
}
}
@Test
public void testSimpleGetOperationWithMultipleSecurityAnnotations() {
String openApiYAML = readIntoYaml(SimpleGetOperationWithMultipleSecurityAnnotations.class);
int start = openApiYAML.indexOf("get:");
int end = openApiYAML.length() - 1;
String expectedYAML = "get:\n" +
" summary: Simple get operation\n" +
" description: Defines a simple get operation with no inputs and a complex\n" +
" operationId: getWithNoParameters\n" +
" responses:\n" +
" \"200\":\n" +
" description: voila!\n" +
" security:\n" +
" - review-auth:\n" +
" - write:review\n" +
" - petstore-auth:\n" +
" - write:pets\n" +
" - read:pets\n" +
" - api_key: []";
String extractedYAML = openApiYAML.substring(start, end);
assertEquals(extractedYAML, expectedYAML);
}
static class SimpleGetOperationWithMultipleSecurityAnnotations {
@SecurityRequirement(name = "review-auth", scopes = {"write:review"})
@Operation(
summary = "Simple get operation",
description = "Defines a simple get operation with no inputs and a complex",
operationId = "getWithNoParameters",
responses = {
@ApiResponse(
responseCode = "200",
description = "voila!")
},
security = {@SecurityRequirement(
name = "petstore-auth",
scopes = {"write:pets", "read:pets"}),
@SecurityRequirement(
name = "api_key",
scopes = {}),})
@GET
@Path("/path")
public void simpleGet() {
}
}
@Test
public void testSimpleDeprecatedGetOperation() {
String openApiYAML = readIntoYaml(SimpleDeprecatedGetOperationTest.class);
int start = openApiYAML.indexOf("get:");
int end = openApiYAML.length() - 1;
String expectedYAML = "get:\n" +
" summary: Deprecated get operation\n" +
" description: Defines a deprecated get operation with no inputs and a complex\n" +
" operationId: getWithNoParameters\n" +
" responses:\n" +
" \"200\":\n" +
" description: voila!\n" +
" deprecated: true";
String extractedYAML = openApiYAML.substring(start, end);
assertEquals(extractedYAML, expectedYAML);
}
static class SimpleDeprecatedGetOperationTest {
@Operation(
summary = "Deprecated get operation",
description = "Defines a deprecated get operation with no inputs and a complex",
operationId = "getWithNoParameters",
responses = {
@ApiResponse(
responseCode = "200",
description = "voila!")
}
)
@GET
@Path("/path")
@Deprecated
public void deprecatedGet() {
}
}
@Test
public void testSimpleGetOperationInDeprecatedClass() {
String openApiYAML = readIntoYaml(DeprecatedSimpleGetOperationTest.class);
int start = openApiYAML.indexOf("get:");
int end = openApiYAML.length() - 1;
String expectedYAML = "get:\n" +
" summary: Simple get operation in deprecated class\n" +
" description: Defines a simple get operation in a deprecated class with no inputs\n" +
" operationId: getWithNoParameters\n" +
" responses:\n" +
" \"200\":\n" +
" description: voila!\n" +
" deprecated: true";
String extractedYAML = openApiYAML.substring(start, end);
assertEquals(extractedYAML, expectedYAML);
}
@Deprecated
static class DeprecatedSimpleGetOperationTest {
@Operation(
summary = "Simple get operation in deprecated class",
description = "Defines a simple get operation in a deprecated class with no inputs",
operationId = "getWithNoParameters",
responses = {
@ApiResponse(
responseCode = "200",
description = "voila!")
}
)
@GET
@Path("/path")
public void simpleGet() {
}
}
}