From b6a07783d5145920d742d7096dc3934ebdd70a25 Mon Sep 17 00:00:00 2001 From: Michael Edgar Date: Tue, 25 Apr 2023 00:39:53 +0800 Subject: [PATCH] TCK: fix several incorrectly used annotations and associated tests (#562) * 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 Co-authored-by: Andrew Rouse --- .../openapi/apps/airlines/JAXRSApp.java | 5 +-- .../openapi/apps/airlines/model/User.java | 2 +- .../airlines/resources/AirlinesResource.java | 1 - .../airlines/resources/ReviewResource.java | 9 ++-- .../apps/airlines/resources/UserResource.java | 9 ++-- .../apps/petstore/resource/PetResource.java | 43 +++++-------------- .../petstore/resource/PetStoreResource.java | 6 +-- .../apps/petstore/resource/UserResource.java | 13 +++--- .../openapi/tck/AirlinesAppTest.java | 10 +---- .../openapi/tck/PetStoreAppTest.java | 2 +- 10 files changed, 31 insertions(+), 69 deletions(-) diff --git a/tck/src/main/java/org/eclipse/microprofile/openapi/apps/airlines/JAXRSApp.java b/tck/src/main/java/org/eclipse/microprofile/openapi/apps/airlines/JAXRSApp.java index 7851534d9..a9995962a 100644 --- a/tck/src/main/java/org/eclipse/microprofile/openapi/apps/airlines/JAXRSApp.java +++ b/tck/src/main/java/org/eclipse/microprofile/openapi/apps/airlines/JAXRSApp.java @@ -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", @@ -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 getSingletons() { diff --git a/tck/src/main/java/org/eclipse/microprofile/openapi/apps/airlines/model/User.java b/tck/src/main/java/org/eclipse/microprofile/openapi/apps/airlines/model/User.java index 7599e41ba..c955d599e 100644 --- a/tck/src/main/java/org/eclipse/microprofile/openapi/apps/airlines/model/User.java +++ b/tck/src/main/java/org/eclipse/microprofile/openapi/apps/airlines/model/User.java @@ -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") diff --git a/tck/src/main/java/org/eclipse/microprofile/openapi/apps/airlines/resources/AirlinesResource.java b/tck/src/main/java/org/eclipse/microprofile/openapi/apps/airlines/resources/AirlinesResource.java index ce24f9086..6e81186bb 100644 --- a/tck/src/main/java/org/eclipse/microprofile/openapi/apps/airlines/resources/AirlinesResource.java +++ b/tck/src/main/java/org/eclipse/microprofile/openapi/apps/airlines/resources/AirlinesResource.java @@ -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 = { diff --git a/tck/src/main/java/org/eclipse/microprofile/openapi/apps/airlines/resources/ReviewResource.java b/tck/src/main/java/org/eclipse/microprofile/openapi/apps/airlines/resources/ReviewResource.java index 5674daf8e..2e895c4ba 100644 --- a/tck/src/main/java/org/eclipse/microprofile/openapi/apps/airlines/resources/ReviewResource.java +++ b/tck/src/main/java/org/eclipse/microprofile/openapi/apps/airlines/resources/ReviewResource.java @@ -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) { @@ -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") diff --git a/tck/src/main/java/org/eclipse/microprofile/openapi/apps/airlines/resources/UserResource.java b/tck/src/main/java/org/eclipse/microprofile/openapi/apps/airlines/resources/UserResource.java index d888ddedb..db3a2c0a6 100644 --- a/tck/src/main/java/org/eclipse/microprofile/openapi/apps/airlines/resources/UserResource.java +++ b/tck/src/main/java/org/eclipse/microprofile/openapi/apps/airlines/resources/UserResource.java @@ -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); } @@ -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")) }) diff --git a/tck/src/main/java/org/eclipse/microprofile/openapi/apps/petstore/resource/PetResource.java b/tck/src/main/java/org/eclipse/microprofile/openapi/apps/petstore/resource/PetResource.java index d923199db..322b755ab 100644 --- a/tck/src/main/java/org/eclipse/microprofile/openapi/apps/petstore/resource/PetResource.java +++ b/tck/src/main/java/org/eclipse/microprofile/openapi/apps/petstore/resource/PetResource.java @@ -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; @@ -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") @@ -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 = { @@ -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) { @@ -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") @@ -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))) diff --git a/tck/src/main/java/org/eclipse/microprofile/openapi/apps/petstore/resource/PetStoreResource.java b/tck/src/main/java/org/eclipse/microprofile/openapi/apps/petstore/resource/PetStoreResource.java index f6dd63678..d34971fc5 100644 --- a/tck/src/main/java/org/eclipse/microprofile/openapi/apps/petstore/resource/PetStoreResource.java +++ b/tck/src/main/java/org/eclipse/microprofile/openapi/apps/petstore/resource/PetStoreResource.java @@ -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; @@ -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, @@ -94,7 +94,7 @@ public java.util.Map 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", @@ -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); } diff --git a/tck/src/main/java/org/eclipse/microprofile/openapi/apps/petstore/resource/UserResource.java b/tck/src/main/java/org/eclipse/microprofile/openapi/apps/petstore/resource/UserResource.java index b09b49038..9018e3c81 100644 --- a/tck/src/main/java/org/eclipse/microprofile/openapi/apps/petstore/resource/UserResource.java +++ b/tck/src/main/java/org/eclipse/microprofile/openapi/apps/petstore/resource/UserResource.java @@ -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; @@ -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, @@ -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(); } @@ -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); } @@ -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 users) { + @RequestBody(description = "List of user object", required = true) java.util.List users) { for (User user : users) { userData.addUser(user); } @@ -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(); } diff --git a/tck/src/main/java/org/eclipse/microprofile/openapi/tck/AirlinesAppTest.java b/tck/src/main/java/org/eclipse/microprofile/openapi/tck/AirlinesAppTest.java index cc415d9ba..c938d71ce 100644 --- a/tck/src/main/java/org/eclipse/microprofile/openapi/tck/AirlinesAppTest.java +++ b/tck/src/main/java/org/eclipse/microprofile/openapi/tck/AirlinesAppTest.java @@ -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."; @@ -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")); @@ -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") diff --git a/tck/src/main/java/org/eclipse/microprofile/openapi/tck/PetStoreAppTest.java b/tck/src/main/java/org/eclipse/microprofile/openapi/tck/PetStoreAppTest.java index 8d166e27f..9b56df70f 100644 --- a/tck/src/main/java/org/eclipse/microprofile/openapi/tck/PetStoreAppTest.java +++ b/tck/src/main/java/org/eclipse/microprofile/openapi/tck/PetStoreAppTest.java @@ -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",