Skip to content

Commit

Permalink
TCK: fix several incorrectly used annotations and associated tests (#562
Browse files Browse the repository at this point in the history
)

* TCK: fix several incorrectly used annotations and associated tests
* Align link parameter name with operation's path parameter name
* Remove `/findByStatus` endpoint

Signed-off-by: Michael Edgar <michael@xlate.io>
Co-authored-by: Andrew Rouse <anrouse@uk.ibm.com>
  • Loading branch information
MikeEdgar and Azquelt committed Apr 24, 2023
1 parent cb879f5 commit b6a0778
Show file tree
Hide file tree
Showing 10 changed files with 31 additions and 69 deletions.
Expand Up @@ -71,6 +71,7 @@
extensions = @Extension(name = "x-external-docs",
value = "test-external-docs")),
info = @Info(title = "AirlinesRatingApp API", version = "1.0",
description = "APIs for booking and managing air flights",
termsOfService = "http://airlinesratingapp.com/terms",
contact = @Contact(name = "AirlinesRatingApp API Support",
url = "http://exampleurl.com/contact",
Expand Down Expand Up @@ -208,10 +209,6 @@
@SecurityScheme(securitySchemeName = "testScheme2",
type = SecuritySchemeType.HTTP,
scheme = "Basic")
@Schema(name = "AirlinesRatingApp API",
description = "APIs for booking and managing air flights",
externalDocs = @ExternalDocumentation(description = "For more information, see the link.",
url = "http://exampleurl.com/schema"))
public class JAXRSApp extends Application {
@Override
public Set<Object> getSingletons() {
Expand Down
Expand Up @@ -33,7 +33,7 @@ public class User {
@Schema(required = true, example = "Smith")
private String lastName;

@Schema(required = true, example = "M")
@Schema(required = true, example = "Male")
private Gender gender;

@Schema(required = true, example = "37")
Expand Down
Expand Up @@ -37,7 +37,6 @@
import jakarta.ws.rs.core.Response;

@Path("")
@Schema(name = "Airline Booking API")
@Tags(value = @Tag(name = "Airlines", description = "All the airlines methods"))
@Callback(name = "availabilityCallback", callbackUrlExpression = "http://localhost:9080/oas3-airlines/availability",
operations = @CallbackOperation(method = "get", summary = "Retrieve available flights.", responses = {
Expand Down
Expand Up @@ -161,10 +161,8 @@ public Response getReviewById(
@Produces("application/json")
public Response getReviewByUser(
@Parameter(name = "user", description = "username of the user for the reviews", in = ParameterIn.PATH,
content = @Content(examples = @ExampleObject(name = "example", value = "bsmith")), examples = {
@ExampleObject(name = "example1", value = "bsmith"),
@ExampleObject(name = "example2",
value = "pat@example.com")}) @PathParam("user") String user,
content = @Content(examples = {
@ExampleObject(name = "example", value = "bsmith")})) @PathParam("user") String user,
@QueryParam("minRating") Integer minRating,
@HeaderParam("If-Match") String ifMatch,
@CookieParam("trackme") String trackme) {
Expand Down Expand Up @@ -201,8 +199,7 @@ public Response getReviewByUser(
@Operation(operationId = "getReviewByAirline", summary = "Get all reviews by airlines")
@Parameter(name = "airline", description = "name of the airlines for the reviews", required = true,
in = ParameterIn.PATH,
content = @Content(examples = @ExampleObject(name = "example", value = "Acme Air")),
example = "Acme Air")
content = @Content(examples = @ExampleObject(name = "example", value = "Acme Air")))
@APIResponse(responseCode = "200", description = "Review(s) retrieved",
content = @Content(schema = @Schema(implementation = Review.class)))
@APIResponse(responseCode = "404", description = "Review(s) not found")
Expand Down
Expand Up @@ -152,10 +152,7 @@ public Response createUsersWithArrayInput(
content = @Content(mediaType = "application/json",
schema = @Schema(type = SchemaType.ARRAY, implementation = User.class,
nullable = true, writeOnly = true, minItems = 2,
maxItems = 20, uniqueItems = true),
encoding = @Encoding(name = "firstName", contentType = "text/plain",
style = "form", allowReserved = true,
explode = true))) User[] users) {
maxItems = 20, uniqueItems = true))) User[] users) {
for (User user : users) {
userData.addUser(user);
}
Expand Down Expand Up @@ -279,8 +276,8 @@ public Response getUserByName(
parameters = @LinkParameter(name = "userId", expression = "$request.path.id"),
extensions = @Extension(name = "x-link", value = "test-link")),
@Link(name = "Review", description = "The reviews provided by user",
operationRef = "/db/reviews/{userName}",
parameters = @LinkParameter(name = "path.userName",
operationRef = "#/paths/~1reviews~1users~1{user}/get",
parameters = @LinkParameter(name = "path.user",
expression = "$response.body#userName"),
requestBody = "$request.path.id", server = @Server(url = "http://example.com"))
})
Expand Down
Expand Up @@ -22,8 +22,6 @@
import org.eclipse.microprofile.openapi.annotations.enums.SchemaType;
import org.eclipse.microprofile.openapi.annotations.enums.SecuritySchemeIn;
import org.eclipse.microprofile.openapi.annotations.enums.SecuritySchemeType;
import org.eclipse.microprofile.openapi.annotations.extensions.Extension;
import org.eclipse.microprofile.openapi.annotations.extensions.Extensions;
import org.eclipse.microprofile.openapi.annotations.media.Content;
import org.eclipse.microprofile.openapi.annotations.media.ExampleObject;
import org.eclipse.microprofile.openapi.annotations.media.Schema;
Expand Down Expand Up @@ -62,16 +60,17 @@
import jakarta.ws.rs.core.StreamingOutput;

@Path("/pet")
@Schema(name = "pet", description = "Operations on pets resource")
@SecuritySchemes(value = {
@SecurityScheme(securitySchemeName = "petsApiKey", type = SecuritySchemeType.APIKEY,
description = "authentication needed to create a new pet profile for the store",
apiKeyName = "createPetProfile", in = SecuritySchemeIn.HEADER),
@SecurityScheme(securitySchemeName = "petsOAuth2", type = SecuritySchemeType.OAUTH2,
description = "authentication needed to delete a pet profile",
flows = @OAuthFlows(implicit = @OAuthFlow(authorizationUrl = "https://example.com/api/oauth/dialog"),
flows = @OAuthFlows(implicit = @OAuthFlow(authorizationUrl = "https://example.com/api/oauth/dialog",
scopes = {}),
authorizationCode = @OAuthFlow(authorizationUrl = "https://example.com/api/oauth/dialog",
tokenUrl = "https://example.com/api/oauth/token"))),
tokenUrl = "https://example.com/api/oauth/token",
scopes = {}))),
@SecurityScheme(securitySchemeName = "petsHttp", type = SecuritySchemeType.HTTP,
description = "authentication needed to update an exsiting record of a pet in the store",
scheme = "bearer", bearerFormat = "jwt")
Expand All @@ -87,6 +86,7 @@ public class PetResource {
content = @Content(mediaType = "none")),
@APIResponse(responseCode = "404", description = "Pet not found", content = @Content(mediaType = "none")),
@APIResponse(responseCode = "200",
description = "Pet found",
content = @Content(mediaType = "application/json",
schema = @Schema(type = SchemaType.OBJECT, implementation = Pet.class,
oneOf = {
Expand Down Expand Up @@ -150,7 +150,7 @@ public void write(OutputStream output) throws IOException {
public Response deletePet(
@Parameter(name = "apiKey", description = "authentication key to access this method",
schema = @Schema(type = SchemaType.STRING, implementation = String.class, maxLength = 256,
minLength = 32)) @HeaderParam("api_key") String apiKey,
minLength = 32)) @HeaderParam("apiKey") String apiKey,
@Parameter(name = "petId", description = "ID of pet that needs to be fetched", required = true,
schema = @Schema(implementation = Long.class, maximum = "10",
minimum = "1")) @PathParam("petId") Long petId) {
Expand Down Expand Up @@ -191,37 +191,13 @@ public Response addPet(Pet pet) {
})
@Operation(summary = "Update an existing pet", description = "Update an existing pet with the given new attributes")
public Response updatePet(
@Parameter(name = "petAttribute", description = "Attribute to update existing pet record", required = true,
schema = @Schema(implementation = Pet.class)) Pet pet) {
@RequestBody(description = "Attribute to update existing pet record",
required = true,
content = @Content(schema = @Schema(implementation = Pet.class))) Pet pet) {
Pet updatedPet = petData.addPet(pet);
return Response.ok().entity(updatedPet).build();
}

@GET
@Path("/findByStatus")
@APIResponse(responseCode = "400", description = "Invalid status value", content = @Content(mediaType = "none"))
@APIResponse(responseCode = "200",
content = @Content(mediaType = "application/json",
schema = @Schema(type = SchemaType.ARRAY, implementation = Pet.class)))
@Operation(summary = "Finds Pets by status",
description = "Find all the Pets with the given status; Multiple status values can be provided with comma seperated strings")
@Extension(name = "x-mp-method1", value = "true")
@Extensions({@Extension(name = "x-mp-method2", value = "true"), @Extension(value = "false", name = "x-mp-method3")})
public Response findPetsByStatus(
@Parameter(name = "status", description = "Status values that need to be considered for filter",
required = true, schema = @Schema(implementation = String.class), content = {
@Content(examples = {
@ExampleObject(name = "Available", value = "available",
summary = "Retrieves all the pets that are available"),
@ExampleObject(name = "Pending", value = "pending",
summary = "Retrieves all the pets that are pending to be sold"),
@ExampleObject(name = "Sold", value = "sold",
summary = "Retrieves all the pets that are sold")
})
}, allowEmptyValue = true) @Extension(name = "x-mp-parm1", value = "true") String status) {
return Response.ok(petData.findPetByStatus(status)).build();
}

@GET
@Path("/findByTags")
@Produces("application/json")
Expand All @@ -233,6 +209,7 @@ public Response findPetsByStatus(
description = "Invalid tag value",
content = @Content(mediaType = "none")),
@APIResponse(responseCode = "200",
description = "Pet callback successfully processed",
content = @Content(mediaType = "application/json",
schema = @Schema(type = SchemaType.ARRAY,
implementation = Pet.class)))
Expand Down
Expand Up @@ -21,6 +21,7 @@
import org.eclipse.microprofile.openapi.annotations.media.DiscriminatorMapping;
import org.eclipse.microprofile.openapi.annotations.media.Schema;
import org.eclipse.microprofile.openapi.annotations.parameters.Parameter;
import org.eclipse.microprofile.openapi.annotations.parameters.RequestBody;
import org.eclipse.microprofile.openapi.annotations.responses.APIResponse;
import org.eclipse.microprofile.openapi.annotations.responses.APIResponses;
import org.eclipse.microprofile.openapi.annotations.security.SecurityRequirement;
Expand All @@ -43,7 +44,6 @@
import jakarta.ws.rs.core.Response;

@Path("/store")
@Schema(name = "/store")
@Produces({"application/json", "application/xml"})
@SecuritySchemes(value = {
@SecurityScheme(securitySchemeName = "storeOpenIdConnect", type = SecuritySchemeType.OPENIDCONNECT,
Expand Down Expand Up @@ -94,7 +94,7 @@ public java.util.Map<String, Integer> getInventory() {
BadOrder.class}, discriminatorProperty = "id",
discriminatorMapping = @DiscriminatorMapping(value = "0",
schema = BadOrder.class))))
@APIResponse(responseCode = "900", description = "Invalid",
@APIResponse(responseCode = "599", description = "Invalid",
content = @Content(schema = @Schema(implementation = Order.class, hidden = true)))
public Response getOrderById(
@Parameter(name = "orderId", description = "ID of pet that needs to be fetched",
Expand All @@ -115,7 +115,7 @@ public Response getOrderById(
@APIResponse(responseCode = "200", description = "successful operation")
@APIResponse(responseCode = "400", description = "Invalid Order")
public Order placeOrder(
@Parameter(description = "order placed for purchasing the pet", required = true) Order order) {
@RequestBody(description = "order placed for purchasing the pet", required = true) Order order) {
storeData.placeOrder(order);
return storeData.placeOrder(order);
}
Expand Down
Expand Up @@ -20,6 +20,7 @@
import org.eclipse.microprofile.openapi.annotations.media.Content;
import org.eclipse.microprofile.openapi.annotations.media.Schema;
import org.eclipse.microprofile.openapi.annotations.parameters.Parameter;
import org.eclipse.microprofile.openapi.annotations.parameters.RequestBody;
import org.eclipse.microprofile.openapi.annotations.responses.APIResponse;
import org.eclipse.microprofile.openapi.annotations.responses.APIResponses;
import org.eclipse.microprofile.openapi.annotations.security.SecurityRequirement;
Expand All @@ -43,7 +44,6 @@
import jakarta.ws.rs.core.Response;

@Path("/user")
@Schema(name = "/user")
@Produces({"application/json", "application/xml"})
@SecuritySchemes(value = {
@SecurityScheme(securitySchemeName = "userApiKey", type = SecuritySchemeType.APIKEY,
Expand All @@ -68,8 +68,9 @@ public class UserResource {
@SecurityRequirement(name = "userBearerHttp")
})
public Response createUser(
@Parameter(description = "Created user object", schema = @Schema(ref = "#/components/schemas/User"),
required = true) User user) {
@RequestBody(description = "Created user object",
content = @Content(schema = @Schema(ref = "#/components/schemas/User")),
required = true) User user) {
userData.addUser(user);
return Response.ok().entity("").build();
}
Expand All @@ -79,7 +80,7 @@ public Response createUser(
@APIResponse(description = "successful operation")
@Operation(summary = "Creates list of users with given input array")
public Response createUsersWithArrayInput(
@Parameter(description = "List of user object", required = true) User[] users) {
@RequestBody(description = "List of user object", required = true) User[] users) {
for (User user : users) {
userData.addUser(user);
}
Expand All @@ -91,7 +92,7 @@ public Response createUsersWithArrayInput(
@APIResponse(description = "successful operation")
@Operation(summary = "Creates list of users with given input array")
public Response createUsersWithListInput(
@Parameter(description = "List of user object", required = true) java.util.List<User> users) {
@RequestBody(description = "List of user object", required = true) java.util.List<User> users) {
for (User user : users) {
userData.addUser(user);
}
Expand All @@ -111,7 +112,7 @@ public Response updateUser(
@Parameter(name = "username", description = "name that need to be deleted",
schema = @Schema(type = SchemaType.STRING),
required = true) @PathParam("username") String username,
@Parameter(description = "Updated user object", required = true) User user) {
@RequestBody(description = "Updated user object", required = true) User user) {
userData.addUser(user);
return Response.ok().entity("").build();
}
Expand Down
Expand Up @@ -671,7 +671,7 @@ public void testLink(String type) {
vr.body(s + "x-link", equalTo("test-link"));

String t = "paths.'/user/id/{id}'.get.responses.'200'.links.Review.";
vr.body(t + "operationRef", equalTo("/db/reviews/{userName}"));
vr.body(t + "operationRef", equalTo("#/paths/~1reviews~1users~1{user}/get"));
vr.body(t + "description", equalTo("The reviews provided by user"));

String k = "paths.'/reviews'.post.responses.'201'.links.Review.";
Expand All @@ -686,7 +686,7 @@ public void testLinkParameter(String type) {
vr.body(s + "parameters.userId", equalTo("$request.path.id"));

String t = "paths.'/user/id/{id}'.get.responses.'200'.links.Review.";
vr.body(t + "parameters.'path.userName'", equalTo("$response.body#userName"));
vr.body(t + "parameters.'path.user'", equalTo("$response.body#userName"));

String k = "paths.'/reviews'.post.responses.'201'.links.Review.";
vr.body(k + "parameters.reviewId", equalTo("$request.path.id"));
Expand Down Expand Up @@ -752,12 +752,6 @@ public void testExampleObject(String type) {
// Example in Parameter Content
vr.body("paths.'/reviews/users/{user}'.get.parameters.find{ it.name=='user'}.content.'*/*'.examples.example.value",
equalTo("bsmith"));

// Example in Parameter
vr.body("paths.'/reviews/users/{user}'.get.parameters.find{ it.name=='user'}.examples.example1.value",
equalTo("bsmith"));
vr.body("paths.'/reviews/users/{user}'.get.parameters.find{ it.name=='user'}.examples.example2.value",
equalTo("pat@example.com"));
}

@Test(dataProvider = "formatProvider")
Expand Down
Expand Up @@ -57,7 +57,7 @@ public void testSchema(String type) {
vr.body("paths.'/pet/findByTags'.get.parameters.find{ it.name == 'tags' }.schema.externalDocs.description",
equalTo("Pet Types"));
vr.body("paths.'/pet/findByTags'.get.parameters.find{ it.name == 'tags' }.schema.deprecated", equalTo(true));
vr.body("paths.'/store/order/{orderId}'.get.responses.'900'.schema", nullValue());
vr.body("paths.'/store/order/{orderId}'.get.responses.'599'.schema", nullValue());

// Numerical properties
vr.body("paths.'/pet/{petId}'.get.parameters.find{ it.name == 'petId' }.schema.maximum",
Expand Down

0 comments on commit b6a0778

Please sign in to comment.